bk://linux-scsi.bkbits.net/scsi-misc-2.6
jejb@mulgrave.(none)|ChangeSet|20050102030752|05705 jejb

# This is a BitKeeper generated diff -Nru style patch.
#
# ChangeSet
#   2005/01/01 21:07:52-06:00 jejb@mulgrave.(none) 
#   osst: add sysfs support
#   
#   From: 	Willem Riede <osst@riede.org>
#   
#   adds sysfs support to osst. This enables hotplug and udev to manage
#   the osst /dev nodes, which is a real necessity on installations that
#   use a dynamic /dev, such as Fedora Core 3.
#   
#   signed-off-by: Willem Riede <osst@riede.org>
#   Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
# 
# drivers/scsi/osst.c
#   2005/01/01 21:04:08-06:00 jejb@mulgrave.(none) +167 -7
#   osst: add sysfs support
# 
# ChangeSet
#   2005/01/01 20:51:14-06:00 jejb@mulgrave.(none) 
#   osst: error handling updates
#   
#   From: 	Willem Riede <osst@riede.org>
#   
#   important error handling improvements that I've made as the result of
#   problem reports.
#   
#   signed-off-by: Willem Riede <osst@riede.org>
#   Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
# 
# drivers/scsi/osst.h
#   2005/01/01 20:49:34-06:00 jejb@mulgrave.(none) +2 -1
#   osst: error handling updates
# 
# drivers/scsi/osst.c
#   2005/01/01 20:49:34-06:00 jejb@mulgrave.(none) +131 -53
#   osst: error handling updates
# 
# ChangeSet
#   2005/01/01 20:40:31-06:00 osst@riede.org 
#   [PATCH] osst: remove typedefs
#   
#   Make style changes that are the equivalent of recent changes to st,
#   such as using 'struct osst_tape' where we used to have 'OS_Scsi_Tape'
#   as a typedef. Osst behavior is not affected by this patch.
#   
#   signed-off-by: Willem Riede <osst@riede.org>
#   Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
# 
# drivers/scsi/osst.h
#   2005/01/01 18:05:27-06:00 osst@riede.org +6 -6
#   osst: remove typedefs
# 
# drivers/scsi/osst.c
#   2005/01/01 18:11:25-06:00 osst@riede.org +247 -246
#   osst: remove typedefs
# 
# ChangeSet
#   2004/12/31 14:54:38-06:00 sleddog@us.ibm.com 
#   [PATCH] ibmvscsi: fix abort and reset error path
#   
#   Description: Fix error paths to handle SCSI targets
#   that reject SCSI aborts and resets and subsequently
#   complete SCSI commands.  There are targets in the field
#   that currently exhibit this behaviour, particularly in
#   the case of bad media (a CD drive got stuck for a LOOONG
#   time on a read op.)  We previously ignore the status
#   on aborts and resets under the mistaken belief that
#   whether they worked or not, the command response was
#   never going to show up.
#   
#   Signed-off-by: Dave Boutcher <boutcher@us.ibm.com>
#   Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
# 
# drivers/scsi/ibmvscsi/ibmvscsi.h
#   2004/12/21 14:47:44-06:00 sleddog@us.ibm.com +1 -0
#   ibmvscsi: fix abort and reset error path
# 
# drivers/scsi/ibmvscsi/ibmvscsi.c
#   2004/12/21 14:47:43-06:00 sleddog@us.ibm.com +79 -4
#   ibmvscsi: fix abort and reset error path
# 
# ChangeSet
#   2004/12/31 13:33:47-06:00 sleddog@us.ibm.com 
#   [PATCH] ibmvscsi: fix dangling pointer reference
#   
#   This code has been problematic for a while and still contained a leg
#   where free_event_struct was called....followed by a reference to the
#   event_struct.  Restructure to make the code cleaner and fix the
#   dangling pointer reference.
#   
#   Signed-off-by: Dave Boutcher <boutcher@us.ibm.com>
#   Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
# 
# drivers/scsi/ibmvscsi/ibmvscsi.c
#   2004/12/31 09:59:46-06:00 sleddog@us.ibm.com +24 -25
#   ibmvscsi: fix dangling pointer reference
# 
# ChangeSet
#   2004/12/31 13:29:49-06:00 sleddog@us.ibm.com 
#   [PATCH] ibmvscsi: fix loop exit condition
#   
#   Fix a bug where we could fall out of our delay loop and then forget to
#   scan for drives.
#   
#   Signed-off-by: Dave Boutcher <boutcher@us.ibm.com>
#   Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
# 
# drivers/scsi/ibmvscsi/ibmvscsi.c
#   2004/12/31 09:59:39-06:00 sleddog@us.ibm.com +2 -2
#   ibmvscsi: fix loop exit condition
# 
# ChangeSet
#   2004/12/31 12:19:50-06:00 sleddog@us.ibm.com 
#   [PATCH] ibmvscsi: limit size of I/O requests, updated
#   
#   Description: Limit the size of I/O requests sent by the
#   ibmvscsi adapter.  With better I/O scheduling (and thus larger
#   requests) we were breaking some servers.
#   
#   Updated based on comments from Jens Axboe and James
#   Bottomley to not specify max I/O sectors as a module
#   parameter, and subsequently not needlessly store
#   the value as a static variable.
#   
#   Signed-off-by: Dave Boutcher <boutcher@us.ibm.com>
#   Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
# 
# drivers/scsi/ibmvscsi/ibmvscsi.c
#   2004/12/31 10:42:38-06:00 sleddog@us.ibm.com +9 -3
#   ibmvscsi: limit size of I/O requests, updated
# 
# ChangeSet
#   2004/12/31 11:35:21-06:00 James.Bottomley@steeleye.com 
#   [PATCH] fix SPI transport class to do DV for broken Western Digital drives
#   
#   There's been a problem reported where a WD Ultra3 drive reports that it
#   has an echo buffer of length 255 and then returns ILLEGAL REQUEST when
#   anyone tries to use it.  This causes DV to treat this as a retraining
#   error and eventually drop back to async.
#   
#   The attached fix makes the DV code identify the ILLEGAL REQUEST
#   condition and configure the drive using the read only DV tests instead.
#   
#   Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
# 
# drivers/scsi/scsi_transport_spi.c
#   2004/12/30 14:55:59-06:00 James.Bottomley@steeleye.com +63 -28
#   fix SPI transport class to do DV for broken Western Digital drives
# 
# ChangeSet
#   2004/12/31 11:30:15-06:00 matthew@wil.cx 
#   [PATCH] Misc zalon fixes
#   
#   Some miscellaneous cleanups for the Zalon driver:
#   
#    - Remove unused definitions of sync_scsi_data_for_cpu and
#      sync_scsi_data_for_device
#    - Fill in dev->irq in the zalon driver
#    - Request the interrupt in the name of the driver, not the bus address
#    - Change the driver name to look better in sysfs
#    - Call ncr53c8xx_exit() in zalon7xx_exit()
#   
#   Signed-off-by: Matthew Wilcox <matthew@wil.cx>
#   Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
# 
# drivers/scsi/zalon.c
#   2004/12/24 17:40:00-06:00 matthew@wil.cx +10 -11
#   Misc zalon fixes
# 
# drivers/scsi/sym53c8xx_comm.h
#   2004/12/24 17:40:00-06:00 matthew@wil.cx +0 -2
#   Misc zalon fixes
# 
# ChangeSet
#   2004/12/31 11:26:43-06:00 matthew@wil.cx 
#   [PATCH] Remove lasi700.h
#   
#   Inline lasi700.h into lasi700.c to cut down on the size of the
#   drivers/scsi directory.
#   
#   Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
# 
# drivers/scsi/lasi700.c
#   2004/12/24 17:39:59-06:00 matthew@wil.cx +21 -1
#   Remove lasi700.h
# 
# BitKeeper/deleted/.del-lasi700.h~7b65d6523b8b75b
#   2004/12/31 11:25:37-06:00 matthew@wil.cx +0 -0
#   Delete: drivers/scsi/lasi700.h
# 
# ChangeSet
#   2004/12/31 11:21:01-06:00 matthew@wil.cx 
#   [PATCH] sym2 version 2.1.18n
#   
#   sym2 version 2.1.18n:
#    - Prevent querying for DT clocking on a single ended bus
#    - Check the U3EN bit instead of the ULTRA3 bit
#    - Only use PPR if SDTR is incapable of negotiating the desired options or
#      speed
#    - minsync bugfix (James Bottomley)
#    - Always calculate what negotiation to perform inside sym_prepare_nego()
#    - Delete unused SYM_OPT_HANDLE_IO_TIMEOUT and SYM_CONF_TIMEOUT_ORDER_MAX
#      code (Christoph Hellwig)
#    - Use SCSI-3 message names instead of SCSI-2 names
#    - Remove private definitions of PCI IDs
#    - Reorganise DMA mask setup
#    - Fix comment tpyo
#    - Make some needlessly global code static (Adrian Bunk)
#    - Reorder some functions to eliminate predeclaration
#    - Use memset instead of bzero
#    - Consolidate and abstract SPARC's special IRQ printing
#    - Convert hcb_p to struct sym_hcb *
#    - Remove cam_ccb_p and cam_scsiio_p typedefs
#    - Treat PA-RISC firmware as if it were a type of NVRAM
#   
#   Signed-off-by: Matthew Wilcox <matthew@wil.cx>
#   Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
# 
# drivers/scsi/sym53c8xx_2/sym_nvram.h
#   2004/12/24 17:40:03-06:00 matthew@wil.cx +6 -0
#   sym2 version 2.1.18n
# 
# drivers/scsi/sym53c8xx_2/sym_nvram.c
#   2004/12/24 17:40:03-06:00 matthew@wil.cx +38 -1
#   sym2 version 2.1.18n
# 
# drivers/scsi/sym53c8xx_2/sym_misc.c
#   2004/12/24 17:40:03-06:00 matthew@wil.cx +1 -97
#   sym2 version 2.1.18n
# 
# drivers/scsi/sym53c8xx_2/sym_malloc.c
#   2004/12/24 17:40:03-06:00 matthew@wil.cx +1 -1
#   sym2 version 2.1.18n
# 
# drivers/scsi/sym53c8xx_2/sym_hipd.h
#   2004/12/24 17:40:03-06:00 matthew@wil.cx +22 -50
#   sym2 version 2.1.18n
# 
# drivers/scsi/sym53c8xx_2/sym_hipd.c
#   2004/12/29 13:40:39-06:00 matthew@wil.cx +193 -276
#   sym2 version 2.1.18n
# 
# drivers/scsi/sym53c8xx_2/sym_glue.h
#   2004/12/24 17:40:02-06:00 matthew@wil.cx +9 -25
#   sym2 version 2.1.18n
# 
# drivers/scsi/sym53c8xx_2/sym_glue.c
#   2004/12/24 17:40:02-06:00 matthew@wil.cx +30 -53
#   sym2 version 2.1.18n
# 
# drivers/scsi/sym53c8xx_2/sym_fw.c
#   2004/12/24 17:40:02-06:00 matthew@wil.cx +2 -2
#   sym2 version 2.1.18n
# 
# drivers/scsi/sym53c8xx_2/sym_defs.h
#   2004/12/29 13:42:34-06:00 matthew@wil.cx +7 -27
#   sym2 version 2.1.18n
# 
# drivers/scsi/sym53c8xx_2/sym_conf.h
#   2004/12/24 17:40:02-06:00 matthew@wil.cx +0 -8
#   sym2 version 2.1.18n
# 
# ChangeSet
#   2004/12/31 11:17:57-06:00 jejb@mulgrave.(none) 
#   SCSI: update ipr to use the change_queue_depth API
#   
#   Instead of doing an attribute override.
#   
#   Ack'd by: Brian King <brking@us.ibm.com>
#   Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
# 
# drivers/scsi/ipr.c
#   2004/12/31 11:16:52-06:00 jejb@mulgrave.(none) +7 -21
#   SCSI: update ipr to use the change_queue_depth API
# 
# ChangeSet
#   2004/12/30 23:18:03-08:00 akpm@bix.(none) 
#   Merge bix.(none):/usr/src/bk25 into bix.(none):/usr/src/bk-scsi
# 
# include/linux/pci_ids.h
#   2004/12/30 23:17:59-08:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# ChangeSet
#   2004/12/29 18:17:11-08:00 akpm@bix.(none) 
#   Merge bix.(none):/usr/src/bk25 into bix.(none):/usr/src/bk-scsi
# 
# include/linux/pci_ids.h
#   2004/12/29 18:17:07-08:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# drivers/scsi/scsi_lib.c
#   2004/12/29 18:17:06-08:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# drivers/scsi/qla2xxx/qla_rscn.c
#   2004/12/29 18:17:06-08:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# drivers/scsi/aacraid/linit.c
#   2004/12/29 18:17:06-08:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# drivers/scsi/aacraid/aacraid.h
#   2004/12/29 18:17:06-08:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# drivers/scsi/Kconfig
#   2004/12/29 18:17:06-08:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# ChangeSet
#   2004/12/27 00:31:27-08:00 akpm@bix.(none) 
#   Merge bix.(none):/usr/src/bk25 into bix.(none):/usr/src/bk-scsi
# 
# include/linux/pci_ids.h
#   2004/12/27 00:31:23-08:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# ChangeSet
#   2004/12/25 08:39:48-08:00 akpm@bix.(none) 
#   Merge bix.(none):/usr/src/bk25 into bix.(none):/usr/src/bk-scsi
# 
# include/linux/pci_ids.h
#   2004/12/25 08:39:44-08:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# ChangeSet
#   2004/12/20 13:42:17-08:00 akpm@bix.(none) 
#   Merge bk://linux-scsi.bkbits.net/scsi-misc-2.6
#   into bix.(none):/usr/src/bk-scsi
# 
# drivers/scsi/scsi_lib.c
#   2004/12/20 13:42:11-08:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# drivers/scsi/qla2xxx/qla_rscn.c
#   2004/12/20 13:42:11-08:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# drivers/scsi/aacraid/linit.c
#   2004/12/20 13:42:11-08:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# drivers/scsi/aacraid/aacraid.h
#   2004/12/20 13:42:11-08:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# ChangeSet
#   2004/12/16 12:40:19-08:00 akpm@bix.(none) 
#   Merge bk://linux-scsi.bkbits.net/scsi-misc-2.6
#   into bix.(none):/usr/src/bk-scsi
# 
# include/linux/pci_ids.h
#   2004/12/16 12:40:15-08:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# drivers/scsi/scsi_lib.c
#   2004/12/16 12:40:15-08:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# drivers/scsi/Kconfig
#   2004/12/16 12:40:15-08:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
diff -Nru a/drivers/scsi/ibmvscsi/ibmvscsi.c b/drivers/scsi/ibmvscsi/ibmvscsi.c
--- a/drivers/scsi/ibmvscsi/ibmvscsi.c	2005-01-02 23:10:07 -08:00
+++ b/drivers/scsi/ibmvscsi/ibmvscsi.c	2005-01-02 23:10:07 -08:00
@@ -87,7 +87,7 @@
 static int init_timeout = 5;
 static int max_requests = 50;
 
-#define IBMVSCSI_VERSION "1.5.1"
+#define IBMVSCSI_VERSION "1.5.5"
 
 MODULE_DESCRIPTION("IBM Virtual SCSI");
 MODULE_AUTHOR("Dave Boutcher");
@@ -256,6 +256,7 @@
 {
 	evt_struct->cmnd = NULL;
 	evt_struct->cmnd_done = NULL;
+	evt_struct->sync_srp = NULL;
 	evt_struct->crq.format = format;
 	evt_struct->crq.timeout = timeout;
 	evt_struct->done = done;
@@ -467,7 +468,7 @@
 static int ibmvscsi_send_srp_event(struct srp_event_struct *evt_struct,
 				   struct ibmvscsi_host_data *hostdata)
 {
-	struct scsi_cmnd *cmnd = evt_struct->cmnd;
+	struct scsi_cmnd *cmnd;
 	u64 *crq_as_u64 = (u64 *) &evt_struct->crq;
 	int rc;
 
@@ -479,22 +480,15 @@
 	if ((evt_struct->crq.format == VIOSRP_SRP_FORMAT) &&
 	    (atomic_dec_if_positive(&hostdata->request_limit) < 0)) {
 		/* See if the adapter is disabled */
-		if (atomic_read(&hostdata->request_limit) < 0) {
-			if (cmnd)
-				cmnd->result = DID_ERROR << 16;
-			if (evt_struct->cmnd_done)
-				evt_struct->cmnd_done(cmnd);
-			unmap_cmd_data(&evt_struct->iu.srp.cmd,
-				       hostdata->dev);
-			free_event_struct(&hostdata->pool, evt_struct);
-			return 0;
-		} else {
-			printk("ibmvscsi: Warning, request_limit exceeded\n");
-			unmap_cmd_data(&evt_struct->iu.srp.cmd,
-				       hostdata->dev);
-			free_event_struct(&hostdata->pool, evt_struct);
-			return SCSI_MLQUEUE_HOST_BUSY;
-		}
+		if (atomic_read(&hostdata->request_limit) < 0)
+			goto send_error;
+	
+		printk(KERN_WARNING 
+		       "ibmvscsi: Warning, request_limit exceeded\n");
+		unmap_cmd_data(&evt_struct->iu.srp.cmd,
+			       hostdata->dev);
+		free_event_struct(&hostdata->pool, evt_struct);
+		return SCSI_MLQUEUE_HOST_BUSY;
 	}
 
 	/* Copy the IU into the transfer area */
@@ -511,18 +505,24 @@
 	     ibmvscsi_send_crq(hostdata, crq_as_u64[0], crq_as_u64[1])) != 0) {
 		list_del(&evt_struct->list);
 
-		cmnd = evt_struct->cmnd;
 		printk(KERN_ERR "ibmvscsi: failed to send event struct rc %d\n",
 		       rc);
-		unmap_cmd_data(&evt_struct->iu.srp.cmd, hostdata->dev);
-		free_event_struct(&hostdata->pool, evt_struct);
-		if (cmnd)
-			cmnd->result = DID_ERROR << 16;
-		if (evt_struct->cmnd_done)
-			evt_struct->cmnd_done(cmnd);
+		goto send_error;
 	}
 
 	return 0;
+
+ send_error:
+	unmap_cmd_data(&evt_struct->iu.srp.cmd, hostdata->dev);
+
+	if ((cmnd = evt_struct->cmnd) != NULL) {
+		cmnd->result = DID_ERROR << 16;
+		evt_struct->cmnd_done(cmnd);
+	} else if (evt_struct->done)
+		evt_struct->done(evt_struct);
+	
+	free_event_struct(&hostdata->pool, evt_struct);
+	return 0;
 }
 
 /**
@@ -537,6 +537,13 @@
 	struct srp_rsp *rsp = &evt_struct->xfer_iu->srp.rsp;
 	struct scsi_cmnd *cmnd = evt_struct->cmnd;
 
+	if (unlikely(rsp->type != SRP_RSP_TYPE)) {
+		if (printk_ratelimit())
+			printk(KERN_WARNING 
+			       "ibmvscsi: bad SRP RSP type %d\n",
+			       rsp->type);
+	}
+	
 	if (cmnd) {
 		cmnd->result = rsp->status;
 		if (((cmnd->result >> 1) & 0x1f) == CHECK_CONDITION)
@@ -641,11 +648,16 @@
 		       evt_struct->xfer_iu->mad.adapter_info.common.status);
 	} else {
 		printk("ibmvscsi: host srp version: %s, "
-		       "host partition %s (%d), OS %d\n",
+		       "host partition %s (%d), OS %d, max io %u\n",
 		       hostdata->madapter_info.srp_version,
 		       hostdata->madapter_info.partition_name,
 		       hostdata->madapter_info.partition_number,
-		       hostdata->madapter_info.os_type);
+		       hostdata->madapter_info.os_type,
+		       hostdata->madapter_info.port_max_txu[0]);
+		
+		if (hostdata->madapter_info.port_max_txu[0]) 
+			hostdata->host->max_sectors = 
+				hostdata->madapter_info.port_max_txu[0] >> 9;
 	}
 }
 
@@ -796,6 +808,10 @@
  */
 static void sync_completion(struct srp_event_struct *evt_struct)
 {
+	/* copy the response back */
+	if (evt_struct->sync_srp)
+		*evt_struct->sync_srp = *evt_struct->xfer_iu;
+	
 	complete(&evt_struct->comp);
 }
 
@@ -810,6 +826,8 @@
 	struct srp_tsk_mgmt *tsk_mgmt;
 	struct srp_event_struct *evt;
 	struct srp_event_struct *tmp_evt, *found_evt;
+	union viosrp_iu srp_rsp;
+	int rsp_rc;
 	u16 lun = lun_from_dev(cmd->device);
 
 	/* First, find this command in our sent list so we can figure
@@ -849,6 +867,7 @@
 	printk(KERN_INFO "ibmvscsi: aborting command. lun 0x%lx, tag 0x%lx\n",
 	       tsk_mgmt->lun, tsk_mgmt->managed_task_tag);
 
+	evt->sync_srp = &srp_rsp;
 	init_completion(&evt->comp);
 	if (ibmvscsi_send_srp_event(evt, hostdata) != 0) {
 		printk(KERN_ERR "ibmvscsi: failed to send abort() event\n");
@@ -859,6 +878,29 @@
 	wait_for_completion(&evt->comp);
 	spin_lock_irq(hostdata->host->host_lock);
 
+	/* make sure we got a good response */
+	if (unlikely(srp_rsp.srp.generic.type != SRP_RSP_TYPE)) {
+		if (printk_ratelimit())
+			printk(KERN_WARNING 
+			       "ibmvscsi: abort bad SRP RSP type %d\n",
+			       srp_rsp.srp.generic.type);
+		return FAILED;
+	}
+
+	if (srp_rsp.srp.rsp.rspvalid)
+		rsp_rc = *((int *)srp_rsp.srp.rsp.sense_and_response_data);
+	else
+		rsp_rc = srp_rsp.srp.rsp.status;
+
+	if (rsp_rc) {
+		if (printk_ratelimit())
+			printk(KERN_WARNING 
+		       "ibmvscsi: abort code %d for task tag 0x%lx\n",
+			       rsp_rc,
+			       tsk_mgmt->managed_task_tag);
+		return FAILED;
+	}
+
 	/* Because we dropped the spinlock above, it's possible
 	 * The event is no longer in our list.  Make sure it didn't
 	 * complete while we were aborting
@@ -871,13 +913,17 @@
 		}
 	}
 
+	if (found_evt == NULL) {
+		printk(KERN_INFO
+		       "ibmvscsi: aborted task tag 0x%lx completed\n",
+		       tsk_mgmt->managed_task_tag);
+		return SUCCESS;
+	}
+
 	printk(KERN_INFO
 	       "ibmvscsi: successfully aborted task tag 0x%lx\n",
 	       tsk_mgmt->managed_task_tag);
 
-	if (found_evt == NULL)
-		return SUCCESS;
-
 	cmd->result = (DID_ABORT << 16);
 	list_del(&found_evt->list);
 	unmap_cmd_data(&found_evt->iu.srp.cmd, found_evt->hostdata->dev);
@@ -899,6 +945,8 @@
 	struct srp_tsk_mgmt *tsk_mgmt;
 	struct srp_event_struct *evt;
 	struct srp_event_struct *tmp_evt, *pos;
+	union viosrp_iu srp_rsp;
+	int rsp_rc;
 	u16 lun = lun_from_dev(cmd->device);
 
 	evt = get_event_struct(&hostdata->pool);
@@ -923,6 +971,7 @@
 	printk(KERN_INFO "ibmvscsi: resetting device. lun 0x%lx\n",
 	       tsk_mgmt->lun);
 
+	evt->sync_srp = &srp_rsp;
 	init_completion(&evt->comp);
 	if (ibmvscsi_send_srp_event(evt, hostdata) != 0) {
 		printk(KERN_ERR "ibmvscsi: failed to send reset event\n");
@@ -933,6 +982,29 @@
 	wait_for_completion(&evt->comp);
 	spin_lock_irq(hostdata->host->host_lock);
 
+	/* make sure we got a good response */
+	if (unlikely(srp_rsp.srp.generic.type != SRP_RSP_TYPE)) {
+		if (printk_ratelimit())
+			printk(KERN_WARNING 
+			       "ibmvscsi: reset bad SRP RSP type %d\n",
+			       srp_rsp.srp.generic.type);
+		return FAILED;
+	}
+
+	if (srp_rsp.srp.rsp.rspvalid)
+		rsp_rc = *((int *)srp_rsp.srp.rsp.sense_and_response_data);
+	else
+		rsp_rc = srp_rsp.srp.rsp.status;
+
+	if (rsp_rc) {
+		if (printk_ratelimit())
+			printk(KERN_WARNING 
+			       "ibmvscsi: reset code %d for task tag 0x%lx\n",
+		       rsp_rc,
+			       tsk_mgmt->managed_task_tag);
+		return FAILED;
+	}
+
 	/* We need to find all commands for this LUN that have not yet been
 	 * responded to, and fail them with DID_RESET
 	 */
@@ -1048,6 +1120,13 @@
 		return;
 	}
 
+	if (atomic_read(&evt_struct->free)) {
+		printk(KERN_ERR
+		       "ibmvscsi: received duplicate  correlation_token 0x%p!\n",
+		       (void *)crq->IU_data_ptr);
+		return;
+	}
+
 	if (crq->format == VIOSRP_SRP_FORMAT)
 		atomic_add(evt_struct->xfer_iu->srp.rsp.request_limit_delta,
 			   &hostdata->request_limit);
@@ -1295,6 +1374,7 @@
 	hostdata->host = host;
 	hostdata->dev = dev;
 	atomic_set(&hostdata->request_limit, -1);
+	hostdata->host->max_sectors = 32 * 8; /* default max I/O 32 pages */
 
 	if (ibmvscsi_init_crq_queue(&hostdata->queue, hostdata,
 				    max_requests) != 0) {
@@ -1326,7 +1406,7 @@
 		 */
 		for (wait_switch = jiffies + (init_timeout * HZ);
 		     time_before(jiffies, wait_switch) &&
-		     atomic_read(&hostdata->request_limit) < 0;) {
+		     atomic_read(&hostdata->request_limit) < 2;) {
 
 			msleep(10);
 		}
diff -Nru a/drivers/scsi/ibmvscsi/ibmvscsi.h b/drivers/scsi/ibmvscsi/ibmvscsi.h
--- a/drivers/scsi/ibmvscsi/ibmvscsi.h	2005-01-02 23:10:07 -08:00
+++ b/drivers/scsi/ibmvscsi/ibmvscsi.h	2005-01-02 23:10:07 -08:00
@@ -67,6 +67,7 @@
 	union viosrp_iu iu;
 	void (*cmnd_done) (struct scsi_cmnd *);
 	struct completion comp;
+	union viosrp_iu *sync_srp;
 };
 
 /* a pool of event structs for use */
diff -Nru a/drivers/scsi/ipr.c b/drivers/scsi/ipr.c
--- a/drivers/scsi/ipr.c	2005-01-02 23:10:07 -08:00
+++ b/drivers/scsi/ipr.c	2005-01-02 23:10:07 -08:00
@@ -2610,23 +2610,19 @@
 #endif
 
 /**
- * ipr_store_queue_depth - Change the device's queue depth
- * @dev:	device struct
- * @buf:	buffer
+ * ipr_change_queue_depth - Change the device's queue depth
+ * @sdev:	scsi device struct
+ * @qdepth:	depth to set
  *
  * Return value:
- * 	number of bytes printed to buffer
+ * 	actual depth set
  **/
-static ssize_t ipr_store_queue_depth(struct device *dev,
-				    const char *buf, size_t count)
+static int ipr_change_queue_depth(struct scsi_device *sdev, int qdepth)
 {
-	struct scsi_device *sdev = to_scsi_device(dev);
 	struct ipr_ioa_cfg *ioa_cfg = (struct ipr_ioa_cfg *)sdev->host->hostdata;
 	struct ipr_resource_entry *res;
-	int qdepth = simple_strtoul(buf, NULL, 10);
 	int tagged = 0;
 	unsigned long lock_flags = 0;
-	ssize_t len = -ENXIO;
 
 	spin_lock_irqsave(ioa_cfg->host->host_lock, lock_flags);
 	res = (struct ipr_resource_entry *)sdev->hostdata;
@@ -2635,23 +2631,13 @@
 
 		if (ipr_is_gscsi(res) && res->tcq_active)
 			tagged = MSG_ORDERED_TAG;
-
-		len = strlen(buf);
 	}
 
 	spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags);
 	scsi_adjust_queue_depth(sdev, tagged, qdepth);
-	return len;
+	return qdepth;
 }
 
-static struct device_attribute ipr_queue_depth_attr = {
-	.attr = {
-		.name = 	"queue_depth",
-		.mode =		S_IRUSR | S_IWUSR,
-	},
-	.store = ipr_store_queue_depth
-};
-
 /**
  * ipr_show_tcq_enable - Show if the device is enabled for tcqing
  * @dev:	device struct
@@ -2760,7 +2746,6 @@
 };
 
 static struct device_attribute *ipr_dev_attrs[] = {
-	&ipr_queue_depth_attr,
 	&ipr_tcqing_attr,
 	&ipr_adapter_handle_attr,
 	NULL,
@@ -3961,6 +3946,7 @@
 	.slave_alloc = ipr_slave_alloc,
 	.slave_configure = ipr_slave_configure,
 	.slave_destroy = ipr_slave_destroy,
+	.change_queue_depth = ipr_change_queue_depth,
 	.bios_param = ipr_biosparam,
 	.can_queue = IPR_MAX_COMMANDS,
 	.this_id = -1,
diff -Nru a/drivers/scsi/lasi700.c b/drivers/scsi/lasi700.c
--- a/drivers/scsi/lasi700.c	2005-01-02 23:10:07 -08:00
+++ b/drivers/scsi/lasi700.c	2005-01-02 23:10:07 -08:00
@@ -54,12 +54,32 @@
 #include <scsi/scsi_transport.h>
 #include <scsi/scsi_transport_spi.h>
 
-#include "lasi700.h"
 #include "53c700.h"
 
 MODULE_AUTHOR("James Bottomley");
 MODULE_DESCRIPTION("lasi700 SCSI Driver");
 MODULE_LICENSE("GPL");
+
+#define LASI_700_SVERSION 0x00071
+#define LASI_710_SVERSION 0x00082
+
+#define LASI700_ID_TABLE {			\
+	.hw_type	= HPHW_FIO,		\
+	.sversion	= LASI_700_SVERSION,	\
+	.hversion	= HVERSION_ANY_ID,	\
+	.hversion_rev	= HVERSION_REV_ANY_ID,	\
+}
+
+#define LASI710_ID_TABLE {			\
+	.hw_type	= HPHW_FIO,		\
+	.sversion	= LASI_710_SVERSION,	\
+	.hversion	= HVERSION_ANY_ID,	\
+	.hversion_rev	= HVERSION_REV_ANY_ID,	\
+}
+
+#define LASI700_CLOCK	25
+#define LASI710_CLOCK	40
+#define LASI_SCSI_CORE_OFFSET 0x100
 
 static struct parisc_device_id lasi700_ids[] = {
 	LASI700_ID_TABLE,
diff -Nru a/drivers/scsi/lasi700.h b/drivers/scsi/lasi700.h
--- a/drivers/scsi/lasi700.h	2005-01-02 23:10:07 -08:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,49 +0,0 @@
-/* -*- mode: c; c-basic-offset: 8 -*- */
-
-/* PARISC LASI driver for the 53c700 chip
- *
- * Copyright (C) 2001 by James.Bottomley@HansenPartnership.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 of the License, or
-**  (at your option) any later version.
-**
-**  This program is distributed in the hope that it will be useful,
-**  but WITHOUT ANY WARRANTY; without even the implied warranty of
-**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-**  GNU General Public License for more details.
-**
-**  You should have received a copy of the GNU General Public License
-**  along with this program; if not, write to the Free Software
-**  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-**
-**-----------------------------------------------------------------------------
- */
-
-#ifndef _LASI700_H
-#define _LASI700_H
-
-#define LASI_710_SVERSION	0x082
-#define LASI_700_SVERSION	0x071
-
-#define LASI700_ID_TABLE {			\
-	.hw_type	= HPHW_FIO,		\
-	.sversion	= LASI_700_SVERSION,	\
-	.hversion	= HVERSION_ANY_ID,	\
-	.hversion_rev	= HVERSION_REV_ANY_ID,	\
-}
-
-#define LASI710_ID_TABLE {			\
-	.hw_type	= HPHW_FIO,		\
-	.sversion	= LASI_710_SVERSION,	\
-	.hversion	= HVERSION_ANY_ID,	\
-	.hversion_rev	= HVERSION_REV_ANY_ID,	\
-}
-
-#define LASI700_CLOCK	25
-#define LASI710_CLOCK	40
-#define LASI_SCSI_CORE_OFFSET 0x100
-
-#endif
diff -Nru a/drivers/scsi/osst.c b/drivers/scsi/osst.c
--- a/drivers/scsi/osst.c	2005-01-02 23:10:07 -08:00
+++ b/drivers/scsi/osst.c	2005-01-02 23:10:07 -08:00
@@ -13,18 +13,18 @@
   order) Klaus Ehrenfried, Wolfgang Denk, Steve Hirsch, Andreas Koppenh"ofer,
   Michael Leodolter, Eyal Lebedinsky, J"org Weule, and Eric Youngdale.
 
-  Copyright 1992 - 2002 Kai Makisara / Willem Riede
-	 email Kai.Makisara@metla.fi / osst@riede.org
+  Copyright 1992 - 2002 Kai Makisara / 2000 - 2004 Willem Riede
+	 email osst@riede.org
 
-  $Header: /cvsroot/osst/Driver/osst.c,v 1.70 2003/12/23 14:22:12 wriede Exp $
+  $Header: /cvsroot/osst/Driver/osst.c,v 1.73 2005/01/01 21:13:34 wriede Exp $
 
   Microscopic alterations - Rik Ling, 2000/12/21
   Last st.c sync: Tue Oct 15 22:01:04 2002 by makisara
   Some small formal changes - aeb, 950809
 */
 
-static const char * cvsid = "$Id: osst.c,v 1.70 2003/12/23 14:22:12 wriede Exp $";
-const char * osst_version = "0.99.1";
+static const char * cvsid = "$Id: osst.c,v 1.73 2005/01/01 21:13:34 wriede Exp $";
+const char * osst_version = "0.99.3";
 
 /* The "failure to reconnect" firmware bug */
 #define OSST_FW_NEED_POLL_MIN 10601 /*(107A)*/
@@ -36,6 +36,7 @@
 #include <linux/fs.h>
 #include <linux/kernel.h>
 #include <linux/sched.h>
+#include <linux/proc_fs.h>
 #include <linux/mm.h>
 #include <linux/init.h>
 #include <linux/string.h>
@@ -46,6 +47,7 @@
 #include <linux/spinlock.h>
 #include <linux/vmalloc.h>
 #include <linux/blkdev.h>
+#include <linux/moduleparam.h>
 #include <linux/devfs_fs_kernel.h>
 #include <linux/delay.h>
 #include <asm/uaccess.h>
@@ -82,13 +84,13 @@
 MODULE_DESCRIPTION("OnStream {DI-|FW-|SC-|USB}{30|50} Tape Driver");
 MODULE_LICENSE("GPL");
 
-module_param(max_dev, int, 0);
+module_param(max_dev, int, 0444);
 MODULE_PARM_DESC(max_dev, "Maximum number of OnStream Tape Drives to attach (4)");
 
-module_param(write_threshold_kbs, int, 0);
+module_param(write_threshold_kbs, int, 0644);
 MODULE_PARM_DESC(write_threshold_kbs, "Asynchronous write threshold (KB; 32)");
 
-module_param(max_sg_segs, int, 0);
+module_param(max_sg_segs, int, 0644);
 MODULE_PARM_DESC(max_sg_segs, "Maximum number of scatter/gather segments to use (9)");
 #else
 static struct osst_dev_parm {
@@ -119,10 +121,10 @@
 // #define OSST_INJECT_ERRORS 1 
 #endif
 
-#define MAX_RETRIES 2
-#define MAX_READ_RETRIES 0
-#define MAX_WRITE_RETRIES 0
-#define MAX_READY_RETRIES 0
+/* Do not retry! The drive firmware already retries when appropriate,
+   and when it tries to tell us something, we had better listen... */
+#define MAX_RETRIES 0
+
 #define NO_TAPE  NOT_READY
 
 #define OSST_WAIT_POSITION_COMPLETE   (HZ > 200 ? HZ / 200 : 1)
@@ -147,19 +149,19 @@
 static int osst_max_dev           = OSST_MAX_TAPES;
 static int osst_nr_dev;
 
-static OS_Scsi_Tape **os_scsi_tapes = NULL;
-static rwlock_t  os_scsi_tapes_lock = RW_LOCK_UNLOCKED;
+static struct osst_tape **os_scsi_tapes = NULL;
+static rwlock_t os_scsi_tapes_lock = RW_LOCK_UNLOCKED;
 
 static int modes_defined = FALSE;
 
-static OSST_buffer *new_tape_buffer(int, int, int);
-static int enlarge_buffer(OSST_buffer *, int);
-static void normalize_buffer(OSST_buffer *);
-static int append_to_buffer(const char __user *, OSST_buffer *, int);
-static int from_buffer(OSST_buffer *, char __user *, int);
-static int osst_zero_buffer_tail(OSST_buffer *);
-static int osst_copy_to_buffer(OSST_buffer *, unsigned char *);
-static int osst_copy_from_buffer(OSST_buffer *, unsigned char *);
+static struct osst_buffer *new_tape_buffer(int, int, int);
+static int enlarge_buffer(struct osst_buffer *, int);
+static void normalize_buffer(struct osst_buffer *);
+static int append_to_buffer(const char __user *, struct osst_buffer *, int);
+static int from_buffer(struct osst_buffer *, char __user *, int);
+static int osst_zero_buffer_tail(struct osst_buffer *);
+static int osst_copy_to_buffer(struct osst_buffer *, unsigned char *);
+static int osst_copy_from_buffer(struct osst_buffer *, unsigned char *);
 
 static int osst_probe(struct device *);
 static int osst_remove(struct device *);
@@ -173,17 +175,18 @@
 	}
 };
 
-static int osst_int_ioctl(OS_Scsi_Tape *STp, Scsi_Request ** aSRpnt, unsigned int cmd_in,unsigned long arg);
+static int osst_int_ioctl(struct osst_tape *STp, struct scsi_request ** aSRpnt,
+			    unsigned int cmd_in, unsigned long arg);
 
-static int osst_set_frame_position(OS_Scsi_Tape *STp, Scsi_Request ** aSRpnt, int frame, int skip);
+static int osst_set_frame_position(struct osst_tape *STp, struct scsi_request ** aSRpnt, int frame, int skip);
 
-static int osst_get_frame_position(OS_Scsi_Tape *STp, Scsi_Request ** aSRpnt);
+static int osst_get_frame_position(struct osst_tape *STp, struct scsi_request ** aSRpnt);
 
-static int osst_flush_write_buffer(OS_Scsi_Tape *STp, Scsi_Request ** aSRpnt);
+static int osst_flush_write_buffer(struct osst_tape *STp, struct scsi_request ** aSRpnt);
 
-static int osst_write_error_recovery(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt, int pending);
+static int osst_write_error_recovery(struct osst_tape * STp, struct scsi_request ** aSRpnt, int pending);
 
-static inline char *tape_name(OS_Scsi_Tape *tape)
+static inline char *tape_name(struct osst_tape *tape)
 {
 	return tape->drive->disk_name;
 }
@@ -191,7 +194,7 @@
 /* Routines that handle the interaction with mid-layer SCSI routines */
 
 /* Convert the result to success code */
-static int osst_chk_result(OS_Scsi_Tape * STp, Scsi_Request * SRpnt)
+static int osst_chk_result(struct osst_tape * STp, struct scsi_request * SRpnt)
 {
 	char *name = tape_name(STp);
 	int result = SRpnt->sr_result;
@@ -222,7 +225,7 @@
 		if (driver_byte(result) & DRIVER_SENSE)
 			print_req_sense("osst ", SRpnt);
 	}
-//	else
+	else
 #endif
 	if (!(driver_byte(result) & DRIVER_SENSE) ||
 		((sense[0] & 0x70) == 0x70 &&
@@ -234,7 +237,7 @@
 		 SRpnt->sr_cmnd[0] != MODE_SENSE &&
 		 SRpnt->sr_cmnd[0] != TEST_UNIT_READY)) { /* Abnormal conditions for tape */
 		if (driver_byte(result) & DRIVER_SENSE) {
-			printk(KERN_WARNING "%s:W: Command with sense data: ", name);
+			printk(KERN_WARNING "%s:W: Command with sense data:\n", name);
 			print_req_sense("osst:", SRpnt);
 		}
 		else {
@@ -281,7 +284,7 @@
 /* Wakeup from interrupt */
 static void osst_sleep_done (Scsi_Cmnd * SCpnt)
 {
-	OS_Scsi_Tape * STp = container_of(SCpnt->request->rq_disk->private_data, OS_Scsi_Tape, driver);
+	struct osst_tape * STp = container_of(SCpnt->request->rq_disk->private_data, struct osst_tape, driver);
 
 	if ((STp->buffer)->writing &&
 	    (SCpnt->sense_buffer[0] & 0x70) == 0x70 &&
@@ -307,7 +310,7 @@
 /* Do the scsi command. Waits until command performed if do_wait is true.
    Otherwise osst_write_behind_check() is used to check that the command
    has finished. */
-static	Scsi_Request * osst_do_scsi(Scsi_Request *SRpnt, OS_Scsi_Tape *STp, 
+static	struct scsi_request * osst_do_scsi(struct scsi_request *SRpnt, struct osst_tape *STp, 
 	unsigned char *cmd, int bytes, int direction, int timeout, int retries, int do_wait)
 {
 	unsigned char *bp;
@@ -366,9 +369,9 @@
 
 
 /* Handle the write-behind checking (downs the semaphore) */
-static void osst_write_behind_check(OS_Scsi_Tape *STp)
+static void osst_write_behind_check(struct osst_tape *STp)
 {
-	OSST_buffer * STbuffer;
+	struct osst_buffer * STbuffer;
 
 	STbuffer = STp->buffer;
 
@@ -406,7 +409,7 @@
 /*
  * Initialize the OnStream AUX
  */
-static void osst_init_aux(OS_Scsi_Tape * STp, int frame_type, int frame_seq_number,
+static void osst_init_aux(struct osst_tape * STp, int frame_type, int frame_seq_number,
 					 int logical_blk_num, int blk_sz, int blk_cnt)
 {
 	os_aux_t       *aux = STp->buffer->aux;
@@ -468,13 +471,13 @@
 /*
  * Verify that we have the correct tape frame
  */
-static int osst_verify_frame(OS_Scsi_Tape * STp, int frame_seq_number, int quiet)
+static int osst_verify_frame(struct osst_tape * STp, int frame_seq_number, int quiet)
 {
-	char           * name = tape_name(STp);
-	os_aux_t       * aux  = STp->buffer->aux;
-	os_partition_t * par  = &(aux->partition);
-	struct st_partstat    * STps = &(STp->ps[STp->partition]);
-	int		 blk_cnt, blk_sz, i;
+	char               * name = tape_name(STp);
+	os_aux_t           * aux  = STp->buffer->aux;
+	os_partition_t     * par  = &(aux->partition);
+	struct st_partstat * STps = &(STp->ps[STp->partition]);
+	int		     blk_cnt, blk_sz, i;
 
 	if (STp->raw) {
 		if (STp->buffer->syscall_result) {
@@ -602,14 +605,15 @@
 /*
  * Wait for the unit to become Ready
  */
-static int osst_wait_ready(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt, unsigned timeout, int initial_delay)
+static int osst_wait_ready(struct osst_tape * STp, struct scsi_request ** aSRpnt,
+				 unsigned timeout, int initial_delay)
 {
-	unsigned char	cmd[MAX_COMMAND_SIZE];
-	Scsi_Request  * SRpnt;
-	unsigned long	startwait = jiffies;
+	unsigned char		cmd[MAX_COMMAND_SIZE];
+	struct scsi_request   * SRpnt;
+	unsigned long		startwait = jiffies;
 #if DEBUG
-	int		dbg  = debugging;
-	char          * name = tape_name(STp);
+	int			dbg  = debugging;
+	char    	      * name = tape_name(STp);
 
 	printk(OSST_DEB_MSG "%s:D: Reached onstream wait ready\n", name);
 #endif
@@ -620,7 +624,7 @@
 	memset(cmd, 0, MAX_COMMAND_SIZE);
 	cmd[0] = TEST_UNIT_READY;
 
-	SRpnt = osst_do_scsi(*aSRpnt, STp, cmd, 0, SCSI_DATA_NONE, STp->timeout, MAX_READY_RETRIES, TRUE);
+	SRpnt = osst_do_scsi(*aSRpnt, STp, cmd, 0, SCSI_DATA_NONE, STp->timeout, MAX_RETRIES, TRUE);
 	*aSRpnt = SRpnt;
 	if (!SRpnt) return (-EBUSY);
 
@@ -641,7 +645,7 @@
 	    memset(cmd, 0, MAX_COMMAND_SIZE);
 	    cmd[0] = TEST_UNIT_READY;
 
-	    SRpnt = osst_do_scsi(SRpnt, STp, cmd, 0, SCSI_DATA_NONE, STp->timeout, MAX_READY_RETRIES, TRUE);
+	    SRpnt = osst_do_scsi(SRpnt, STp, cmd, 0, SCSI_DATA_NONE, STp->timeout, MAX_RETRIES, TRUE);
 	}
 	*aSRpnt = SRpnt;
 #if DEBUG
@@ -666,14 +670,14 @@
 /*
  * Wait for a tape to be inserted in the unit
  */
-static int osst_wait_for_medium(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt, unsigned timeout)
+static int osst_wait_for_medium(struct osst_tape * STp, struct scsi_request ** aSRpnt, unsigned timeout)
 {
-	unsigned char	cmd[MAX_COMMAND_SIZE];
-	Scsi_Request  * SRpnt;
-	unsigned long	startwait = jiffies;
+	unsigned char		cmd[MAX_COMMAND_SIZE];
+	struct scsi_request   * SRpnt;
+	unsigned long		startwait = jiffies;
 #if DEBUG
-	int		dbg = debugging;
-	char          * name = tape_name(STp);
+	int			dbg = debugging;
+	char    	      * name = tape_name(STp);
 
 	printk(OSST_DEB_MSG "%s:D: Reached onstream wait for medium\n", name);
 #endif
@@ -681,7 +685,7 @@
 	memset(cmd, 0, MAX_COMMAND_SIZE);
 	cmd[0] = TEST_UNIT_READY;
 
-	SRpnt = osst_do_scsi(*aSRpnt, STp, cmd, 0, SCSI_DATA_NONE, STp->timeout, MAX_READY_RETRIES, TRUE);
+	SRpnt = osst_do_scsi(*aSRpnt, STp, cmd, 0, SCSI_DATA_NONE, STp->timeout, MAX_RETRIES, TRUE);
 	*aSRpnt = SRpnt;
 	if (!SRpnt) return (-EBUSY);
 
@@ -700,7 +704,7 @@
 	    memset(cmd, 0, MAX_COMMAND_SIZE);
 	    cmd[0] = TEST_UNIT_READY;
 
-	    SRpnt = osst_do_scsi(SRpnt, STp, cmd, 0, SCSI_DATA_NONE, STp->timeout, MAX_READY_RETRIES, TRUE);
+	    SRpnt = osst_do_scsi(SRpnt, STp, cmd, 0, SCSI_DATA_NONE, STp->timeout, MAX_RETRIES, TRUE);
 	}
 	*aSRpnt = SRpnt;
 #if DEBUG
@@ -722,7 +726,7 @@
 	return 1;
 }
 
-static int osst_position_tape_and_confirm(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt, int frame)
+static int osst_position_tape_and_confirm(struct osst_tape * STp, struct scsi_request ** aSRpnt, int frame)
 {
 	int	retval;
 
@@ -736,15 +740,14 @@
 /*
  * Wait for write(s) to complete
  */
-static int osst_flush_drive_buffer(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt)
+static int osst_flush_drive_buffer(struct osst_tape * STp, struct scsi_request ** aSRpnt)
 {
-	unsigned char	cmd[MAX_COMMAND_SIZE];
-	Scsi_Request  * SRpnt;
-
-	int             result = 0;
-	int		delay  = OSST_WAIT_WRITE_COMPLETE;
+	unsigned char		cmd[MAX_COMMAND_SIZE];
+	struct scsi_request   * SRpnt;
+	int			result = 0;
+	int			delay  = OSST_WAIT_WRITE_COMPLETE;
 #if DEBUG
-	char          * name = tape_name(STp);
+	char		      * name = tape_name(STp);
 
 	printk(OSST_DEB_MSG "%s:D: Reached onstream flush drive buffer (write filemark)\n", name);
 #endif
@@ -753,7 +756,7 @@
 	cmd[0] = WRITE_FILEMARKS;
 	cmd[1] = 1;
 
-	SRpnt = osst_do_scsi(*aSRpnt, STp, cmd, 0, SCSI_DATA_NONE, STp->timeout, MAX_WRITE_RETRIES, TRUE);
+	SRpnt = osst_do_scsi(*aSRpnt, STp, cmd, 0, SCSI_DATA_NONE, STp->timeout, MAX_RETRIES, TRUE);
 	*aSRpnt = SRpnt;
 	if (!SRpnt) return (-EBUSY);
 	if (STp->buffer->syscall_result) {
@@ -771,12 +774,12 @@
 }
 
 #define OSST_POLL_PER_SEC 10
-static int osst_wait_frame(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt, int curr, int minlast, int to)
+static int osst_wait_frame(struct osst_tape * STp, struct scsi_request ** aSRpnt, int curr, int minlast, int to)
 {
-	unsigned long	startwait     = jiffies;
-	char	      * name          = tape_name(STp);
+	unsigned long	startwait = jiffies;
+	char	      * name      = tape_name(STp);
 #if DEBUG
-	char	notyetprinted = 1;
+	char	   notyetprinted  = 1;
 #endif
 	if (minlast >= 0 && STp->ps[STp->partition].rw != ST_READING)
 		printk(KERN_ERR "%s:A: Waiting for frame without having initialized read!\n", name);
@@ -784,7 +787,7 @@
 	while (time_before (jiffies, startwait + to*HZ))
 	{ 
 		int result;
-		result = osst_get_frame_position (STp, aSRpnt);
+		result = osst_get_frame_position(STp, aSRpnt);
 		if (result == -EIO)
 			if ((result = osst_write_error_recovery(STp, aSRpnt, 0)) == 0)
 				return 0;	/* successful recovery leaves drive ready for frame */
@@ -826,23 +829,79 @@
 	return -EBUSY;
 }
 
+static int osst_recover_wait_frame(struct osst_tape * STp, struct scsi_request ** aSRpnt, int writing)
+{
+	struct scsi_request   * SRpnt;
+	unsigned char		cmd[MAX_COMMAND_SIZE];
+	unsigned long   	startwait = jiffies;
+	int			retval    = 1;
+        char		      * name      = tape_name(STp);
+                                                                                                                                
+	if (writing) {
+		char	mybuf[24];
+		char  * olddata = STp->buffer->b_data;
+		int	oldsize = STp->buffer->buffer_size;
+
+		/* write zero fm then read pos - if shows write error, try to recover - if no progress, wait */
+
+		memset(cmd, 0, MAX_COMMAND_SIZE);
+		cmd[0] = WRITE_FILEMARKS;
+		cmd[1] = 1;
+		SRpnt = osst_do_scsi(*aSRpnt, STp, cmd, 0, SCSI_DATA_NONE, STp->timeout,
+								MAX_RETRIES, TRUE);
+
+		while (retval && time_before (jiffies, startwait + 5*60*HZ)) {
+
+			if (STp->buffer->syscall_result && (SRpnt->sr_sense_buffer[2] & 0x0f) != 2) {
+
+				/* some failure - not just not-ready */
+				retval = osst_write_error_recovery(STp, aSRpnt, 0);
+				break;
+			}
+			set_current_state(TASK_INTERRUPTIBLE);
+			schedule_timeout (HZ / OSST_POLL_PER_SEC);
+
+			STp->buffer->b_data = mybuf; STp->buffer->buffer_size = 24;
+			memset(cmd, 0, MAX_COMMAND_SIZE);
+			cmd[0] = READ_POSITION;
+
+			SRpnt = osst_do_scsi(SRpnt, STp, cmd, 20, SCSI_DATA_READ, STp->timeout,
+										MAX_RETRIES, TRUE);
+
+			retval = ( STp->buffer->syscall_result || (STp->buffer)->b_data[15] > 25 );
+			STp->buffer->b_data = olddata; STp->buffer->buffer_size = oldsize;
+		}
+		if (retval)
+			printk(KERN_ERR "%s:E: Device did not succeed to write buffered data\n", name);
+	} else
+		/* TODO - figure out which error conditions can be handled */
+		if (STp->buffer->syscall_result)
+			printk(KERN_WARNING
+				"%s:W: Recover_wait_frame(read) cannot handle %02x:%02x:%02x\n", name,
+					(*aSRpnt)->sr_sense_buffer[ 2] & 0x0f,
+					(*aSRpnt)->sr_sense_buffer[12],
+					(*aSRpnt)->sr_sense_buffer[13]);
+
+	return retval;
+}
+
 /*
  * Read the next OnStream tape frame at the current location
  */
-static int osst_read_frame(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt, int timeout)
+static int osst_read_frame(struct osst_tape * STp, struct scsi_request ** aSRpnt, int timeout)
 {
-	unsigned char	cmd[MAX_COMMAND_SIZE];
-	Scsi_Request  * SRpnt;
-	int		retval = 0;
+	unsigned char		cmd[MAX_COMMAND_SIZE];
+	struct scsi_request   * SRpnt;
+	int			retval = 0;
 #if DEBUG
-	os_aux_t      * aux    = STp->buffer->aux;
-	char          * name = tape_name(STp);
+	os_aux_t	      * aux    = STp->buffer->aux;
+	char		      * name   = tape_name(STp);
 #endif
 
-	/* TODO: Error handling */
 	if (STp->poll)
-		retval = osst_wait_frame (STp, aSRpnt, STp->first_frame_position, 0, timeout);
-	
+		if (osst_wait_frame (STp, aSRpnt, STp->first_frame_position, 0, timeout))
+			retval = osst_recover_wait_frame(STp, aSRpnt, 0);
+
 	memset(cmd, 0, MAX_COMMAND_SIZE);
 	cmd[0] = READ_6;
 	cmd[1] = 1;
@@ -850,13 +909,13 @@
 
 #if DEBUG
 	if (debugging)
-	    printk(OSST_DEB_MSG "%s:D: Reading frame from OnStream tape\n", name);
+		printk(OSST_DEB_MSG "%s:D: Reading frame from OnStream tape\n", name);
 #endif
 	SRpnt = osst_do_scsi(*aSRpnt, STp, cmd, OS_FRAME_SIZE, SCSI_DATA_READ,
-				      STp->timeout, MAX_READ_RETRIES, TRUE);
+				      STp->timeout, MAX_RETRIES, TRUE);
 	*aSRpnt = SRpnt;
 	if (!SRpnt)
-	    return (-EBUSY);
+		return (-EBUSY);
 
 	if ((STp->buffer)->syscall_result) {
 	    retval = 1;
@@ -900,15 +959,13 @@
 	return (retval);
 }
 
-static int osst_initiate_read(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt)
+static int osst_initiate_read(struct osst_tape * STp, struct scsi_request ** aSRpnt)
 {
-	struct st_partstat   * STps   = &(STp->ps[STp->partition]);
-	Scsi_Request  * SRpnt  ;
-	unsigned char	cmd[MAX_COMMAND_SIZE];
-	int		retval = 0;
-#if DEBUG
-	char          * name = tape_name(STp);
-#endif
+	struct st_partstat    * STps   = &(STp->ps[STp->partition]);
+	struct scsi_request   * SRpnt  ;
+	unsigned char		cmd[MAX_COMMAND_SIZE];
+	int			retval = 0;
+	char		      * name   = tape_name(STp);
 
 	if (STps->rw != ST_READING) {         /* Initialize read operation */
 		if (STps->rw == ST_WRITING || STp->dirty) {
@@ -930,23 +987,25 @@
 #if DEBUG
 		printk(OSST_DEB_MSG "%s:D: Start Read Ahead on OnStream tape\n", name);
 #endif
-		SRpnt   = osst_do_scsi(*aSRpnt, STp, cmd, 0, SCSI_DATA_NONE, STp->timeout, MAX_READ_RETRIES, TRUE);
+		SRpnt   = osst_do_scsi(*aSRpnt, STp, cmd, 0, SCSI_DATA_NONE, STp->timeout, MAX_RETRIES, TRUE);
 		*aSRpnt = SRpnt;
-		retval  = STp->buffer->syscall_result;
+		if ((retval = STp->buffer->syscall_result))
+			printk(KERN_WARNING "%s:W: Error starting read ahead\n", name);
 	}
 
 	return retval;
 }
 
-static int osst_get_logical_frame(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt, int frame_seq_number, int quiet)
+static int osst_get_logical_frame(struct osst_tape * STp, struct scsi_request ** aSRpnt,
+						int frame_seq_number, int quiet)
 {
 	struct st_partstat * STps  = &(STp->ps[STp->partition]);
-	char        * name  = tape_name(STp);
-	int           cnt   = 0,
-		      bad   = 0,
-		      past  = 0,
-		      x,
-		      position;
+	char		   * name  = tape_name(STp);
+	int		     cnt   = 0,
+			     bad   = 0,
+			     past  = 0,
+			     x,
+			     position;
 
 	/*
 	 * If we want just any frame (-1) and there is a frame in the buffer, return it
@@ -971,6 +1030,7 @@
 						    name, STp->read_error_frame);
 #endif
 				STp->read_error_frame = 0;
+				STp->abort_count++;
 			}
 			return (-EIO);
 		}
@@ -988,10 +1048,11 @@
 				position = 0xbb8;
 			else if (position > STp->eod_frame_ppos || ++bad == 10) {
 				position = STp->read_error_frame - 1;
+				bad = 0;
 			}
 			else {
-				position += 39;
-				cnt += 20;
+				position += 29;
+				cnt      += 19;
 			}
 #if DEBUG
 			printk(OSST_DEB_MSG "%s:D: Bad frame detected, positioning tape to block %d\n",
@@ -1064,10 +1125,10 @@
 	return (STps->eof);
 }
 
-static int osst_seek_logical_blk(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt, int logical_blk_num)
+static int osst_seek_logical_blk(struct osst_tape * STp, struct scsi_request ** aSRpnt, int logical_blk_num)
 {
         struct st_partstat * STps = &(STp->ps[STp->partition]);
-	char        * name = tape_name(STp);
+	char		   * name = tape_name(STp);
 	int	retries    = 0;
 	int	frame_seq_estimate, ppos_estimate, move;
 	
@@ -1173,7 +1234,7 @@
 #define OSST_SECTOR_SHIFT 9
 #define OSST_SECTOR_MASK  0x03F
 
-static int osst_get_sector(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt)
+static int osst_get_sector(struct osst_tape * STp, struct scsi_request ** aSRpnt)
 {
 	int	sector;
 #if DEBUG
@@ -1203,12 +1264,12 @@
 	return sector;
 }
 
-static int osst_seek_sector(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt, int sector)
+static int osst_seek_sector(struct osst_tape * STp, struct scsi_request ** aSRpnt, int sector)
 {
-        struct st_partstat   * STps   = &(STp->ps[STp->partition]);
-	int		frame  = sector >> OSST_FRAME_SHIFT,
-			offset = (sector & OSST_SECTOR_MASK) << OSST_SECTOR_SHIFT, 
-			r;
+        struct st_partstat * STps   = &(STp->ps[STp->partition]);
+	int		     frame  = sector >> OSST_FRAME_SHIFT,
+			     offset = (sector & OSST_SECTOR_MASK) << OSST_SECTOR_SHIFT, 
+			     r;
 #if DEBUG
 	char          * name = tape_name(STp);
 
@@ -1266,23 +1327,23 @@
  * Precondition for this function to work: all frames in the
  * drive's buffer must be of one type (DATA, MARK or EOD)!
  */
-static int osst_read_back_buffer_and_rewrite(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt,
-					unsigned int frame, unsigned int skip, int pending)
+static int osst_read_back_buffer_and_rewrite(struct osst_tape * STp, struct scsi_request ** aSRpnt,
+						unsigned int frame, unsigned int skip, int pending)
 {
-	Scsi_Request  * SRpnt = * aSRpnt;
-	unsigned char * buffer, * p;
-	unsigned char	cmd[MAX_COMMAND_SIZE];
-	int		flag, new_frame, i;
-	int		nframes          = STp->cur_frames;
-	int		blks_per_frame   = ntohs(STp->buffer->aux->dat.dat_list[0].blk_cnt);
-	int		frame_seq_number = ntohl(STp->buffer->aux->frame_seq_num)
+	struct scsi_request   * SRpnt = * aSRpnt;
+	unsigned char	      * buffer, * p;
+	unsigned char		cmd[MAX_COMMAND_SIZE];
+	int			flag, new_frame, i;
+	int			nframes          = STp->cur_frames;
+	int			blks_per_frame   = ntohs(STp->buffer->aux->dat.dat_list[0].blk_cnt);
+	int			frame_seq_number = ntohl(STp->buffer->aux->frame_seq_num)
 						- (nframes + pending - 1);
-	int		logical_blk_num  = ntohl(STp->buffer->aux->logical_blk_num) 
+	int			logical_blk_num  = ntohl(STp->buffer->aux->logical_blk_num) 
 						- (nframes + pending - 1) * blks_per_frame;
-	char	      * name             = tape_name(STp);
-	unsigned long	startwait        = jiffies;
+	char		      * name             = tape_name(STp);
+	unsigned long		startwait        = jiffies;
 #if DEBUG
-	int		dbg              = debugging;
+	int			dbg              = debugging;
 #endif
 
 	if ((buffer = (unsigned char *)vmalloc((nframes + 1) * OS_DATA_SIZE)) == NULL)
@@ -1308,7 +1369,7 @@
 		cmd[8] = 32768 & 0xff;
 
 		SRpnt = osst_do_scsi(SRpnt, STp, cmd, OS_FRAME_SIZE, SCSI_DATA_READ,
-					    STp->timeout, MAX_READ_RETRIES, TRUE);
+					    STp->timeout, MAX_RETRIES, TRUE);
 	
 		if ((STp->buffer)->syscall_result || !SRpnt) {
 			printk(KERN_ERR "%s:E: Failed to read frame back from OnStream buffer\n", name);
@@ -1357,8 +1418,8 @@
 				vfree((void *)buffer);
 				return (-EIO);
 			}
-			flag = 0;
 			if ( i >= nframes + pending ) break;
+			flag = 0;
 		}
 		osst_copy_to_buffer(STp->buffer, p);
 		/*
@@ -1380,7 +1441,7 @@
 				p[0], p[1], p[2], p[3]);
 #endif
 		SRpnt = osst_do_scsi(SRpnt, STp, cmd, OS_FRAME_SIZE, SCSI_DATA_WRITE,
-					    STp->timeout, MAX_WRITE_RETRIES, TRUE);
+					    STp->timeout, MAX_RETRIES, TRUE);
 
 		if (STp->buffer->syscall_result)
 			flag = 1;
@@ -1396,7 +1457,7 @@
 				cmd[0] = WRITE_FILEMARKS;
 				cmd[1] = 1;
 				SRpnt = osst_do_scsi(SRpnt, STp, cmd, 0, SCSI_DATA_NONE,
-							    STp->timeout, MAX_WRITE_RETRIES, TRUE);
+							    STp->timeout, MAX_RETRIES, TRUE);
 #if DEBUG
 				if (debugging) {
 					printk(OSST_DEB_MSG "%s:D: Sleeping in re-write wait ready\n", name);
@@ -1411,7 +1472,7 @@
 					cmd[0] = TEST_UNIT_READY;
 
 					SRpnt = osst_do_scsi(SRpnt, STp, cmd, 0, SCSI_DATA_NONE, STp->timeout,
-									 MAX_READY_RETRIES, TRUE);
+												MAX_RETRIES, TRUE);
 
 					if (SRpnt->sr_sense_buffer[2] == 2 && SRpnt->sr_sense_buffer[12] == 4 &&
 					    (SRpnt->sr_sense_buffer[13] == 1 || SRpnt->sr_sense_buffer[13] == 8)) {
@@ -1448,29 +1509,34 @@
 #endif
 			osst_get_frame_position(STp, aSRpnt);
 #if DEBUG
-			printk(OSST_DEB_MSG "%s:D: reported frame positions: host = %d, tape = %d\n",
-					  name, STp->first_frame_position, STp->last_frame_position);
+			printk(OSST_DEB_MSG "%s:D: reported frame positions: host = %d, tape = %d, buffer = %d\n",
+					  name, STp->first_frame_position, STp->last_frame_position, STp->cur_frames);
 #endif
 		}
-	}    
+	}
+	if (flag) {
+		/* error recovery did not successfully complete */
+		printk(KERN_ERR "%s:D: Write error recovery failed in %s\n", name,
+				STp->write_type == OS_WRITE_HEADER?"header":"body");
+	}
 	if (!pending)
 		osst_copy_to_buffer(STp->buffer, p);	/* so buffer content == at entry in all cases */
 	vfree((void *)buffer);
 	return 0;
 }
 
-static int osst_reposition_and_retry(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt,
+static int osst_reposition_and_retry(struct osst_tape * STp, struct scsi_request ** aSRpnt,
 					unsigned int frame, unsigned int skip, int pending)
 {
-	unsigned char	cmd[MAX_COMMAND_SIZE];
-	Scsi_Request  * SRpnt;
-	char	      * name      = tape_name(STp);
-	int		expected  = 0;
-	int		attempts  = 1000 / skip;
-	int		flag      = 1;
-	unsigned long	startwait = jiffies;
+	unsigned char		cmd[MAX_COMMAND_SIZE];
+	struct scsi_request   * SRpnt;
+	char		      * name      = tape_name(STp);
+	int			expected  = 0;
+	int			attempts  = 1000 / skip;
+	int			flag      = 1;
+	unsigned long		startwait = jiffies;
 #if DEBUG
-	int		dbg       = debugging;
+	int			dbg       = debugging;
 #endif
 
 	while (attempts && time_before(jiffies, startwait + 60*HZ)) {
@@ -1512,7 +1578,7 @@
 					  name, STp->frame_seq_number-1, STp->first_frame_position);
 #endif
 			SRpnt = osst_do_scsi(*aSRpnt, STp, cmd, OS_FRAME_SIZE, SCSI_DATA_WRITE,
-						      STp->timeout, MAX_WRITE_RETRIES, TRUE);
+						      STp->timeout, MAX_RETRIES, TRUE);
 			*aSRpnt = SRpnt;
 
 			if (STp->buffer->syscall_result) {		/* additional write error */
@@ -1550,6 +1616,7 @@
 			debugging = 0;
 		}
 #endif
+		set_current_state(TASK_INTERRUPTIBLE);
 		schedule_timeout(HZ / 10);
 	}
 	printk(KERN_ERR "%s:E: Failed to find valid tape media\n", name);
@@ -1563,14 +1630,14 @@
  * Error recovery algorithm for the OnStream tape.
  */
 
-static int osst_write_error_recovery(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt, int pending)
+static int osst_write_error_recovery(struct osst_tape * STp, struct scsi_request ** aSRpnt, int pending)
 {
-	Scsi_Request * SRpnt  = * aSRpnt;
+	struct scsi_request * SRpnt  = * aSRpnt;
 	struct st_partstat  * STps   = & STp->ps[STp->partition];
-	char         * name   = tape_name(STp);
-	int            retval = 0;
-	int            rw_state;
-	unsigned int  frame, skip;
+	char		    * name   = tape_name(STp);
+	int		      retval = 0;
+	int		      rw_state;
+	unsigned int	      frame, skip;
 
 	rw_state = STps->rw;
 
@@ -1635,12 +1702,14 @@
 	if (retval == 0) {
 		STp->recover_count++;
 		STp->recover_erreg++;
-	}
+	} else
+		STp->abort_count++;
+
 	STps->rw = rw_state;
 	return retval;
 }
 
-static int osst_space_over_filemarks_backward(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt,
+static int osst_space_over_filemarks_backward(struct osst_tape * STp, struct scsi_request ** aSRpnt,
 								 int mt_op, int mt_count)
 {
 	char  * name = tape_name(STp);
@@ -1739,7 +1808,7 @@
  *
  * Just scans for the filemark sequentially.
  */
-static int osst_space_over_filemarks_forward_slow(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt,
+static int osst_space_over_filemarks_forward_slow(struct osst_tape * STp, struct scsi_request ** aSRpnt,
 								     int mt_op, int mt_count)
 {
 	int	cnt = 0;
@@ -1793,7 +1862,7 @@
 /*
  * Fast linux specific version of OnStream FSF
  */
-static int osst_space_over_filemarks_forward_fast(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt,
+static int osst_space_over_filemarks_forward_fast(struct osst_tape * STp, struct scsi_request ** aSRpnt,
 								     int mt_op, int mt_count)
 {
 	char  * name = tape_name(STp);
@@ -1944,11 +2013,11 @@
  * to test the error recovery mechanism.
  */
 #if DEBUG
-static void osst_set_retries(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt, int retries)
+static void osst_set_retries(struct osst_tape * STp, struct scsi_request ** aSRpnt, int retries)
 {
-	unsigned char	cmd[MAX_COMMAND_SIZE];
-	Scsi_Request  * SRpnt  = * aSRpnt;
-	char          * name   = tape_name(STp);
+	unsigned char		cmd[MAX_COMMAND_SIZE];
+	struct scsi_request   * SRpnt  = * aSRpnt;
+	char		      * name   = tape_name(STp);
 
 	memset(cmd, 0, MAX_COMMAND_SIZE);
 	cmd[0] = MODE_SELECT;
@@ -1976,7 +2045,7 @@
 #endif
 
 
-static int osst_write_filemark(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt)
+static int osst_write_filemark(struct osst_tape * STp, struct scsi_request ** aSRpnt)
 {
 	int	result;
 	int	this_mark_ppos = STp->first_frame_position;
@@ -2004,7 +2073,7 @@
 	return result;
 }
 
-static int osst_write_eod(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt)
+static int osst_write_eod(struct osst_tape * STp, struct scsi_request ** aSRpnt)
 {
 	int	result;
 #if DEBUG
@@ -2027,7 +2096,7 @@
 	return result;
 }
 
-static int osst_write_filler(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt, int where, int count)
+static int osst_write_filler(struct osst_tape * STp, struct scsi_request ** aSRpnt, int where, int count)
 {
 	char * name = tape_name(STp);
 
@@ -2052,7 +2121,7 @@
 	return osst_flush_drive_buffer(STp, aSRpnt);
 }
 
-static int __osst_write_header(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt, int where, int count)
+static int __osst_write_header(struct osst_tape * STp, struct scsi_request ** aSRpnt, int where, int count)
 {
 	char * name = tape_name(STp);
 	int     result;
@@ -2079,7 +2148,7 @@
 	return result;
 }
 
-static int osst_write_header(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt, int locate_eod)
+static int osst_write_header(struct osst_tape * STp, struct scsi_request ** aSRpnt, int locate_eod)
 {
 	os_header_t * header;
 	int	      result;
@@ -2153,7 +2222,7 @@
 	return result;
 }
 
-static int osst_reset_header(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt)
+static int osst_reset_header(struct osst_tape * STp, struct scsi_request ** aSRpnt)
 {
 	if (STp->header_cache != NULL)
 		memset(STp->header_cache, 0, sizeof(os_header_t));
@@ -2166,7 +2235,7 @@
 	return osst_write_header(STp, aSRpnt, 1);
 }
 
-static int __osst_analyze_headers(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt, int ppos)
+static int __osst_analyze_headers(struct osst_tape * STp, struct scsi_request ** aSRpnt, int ppos)
 {
 	char        * name = tape_name(STp);
 	os_header_t * header;
@@ -2343,7 +2412,7 @@
 	return 1;
 }
 
-static int osst_analyze_headers(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt)
+static int osst_analyze_headers(struct osst_tape * STp, struct scsi_request ** aSRpnt)
 {
 	int	position, ppos;
 	int	first, last;
@@ -2398,7 +2467,7 @@
 	return 1;
 }
 
-static int osst_verify_position(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt)
+static int osst_verify_position(struct osst_tape * STp, struct scsi_request ** aSRpnt)
 {
 	int	frame_position  = STp->first_frame_position;
 	int	frame_seq_numbr = STp->frame_seq_number;
@@ -2474,11 +2543,11 @@
 /*
  * Configure the OnStream SCII tape drive for default operation
  */
-static int osst_configure_onstream(OS_Scsi_Tape *STp, Scsi_Request ** aSRpnt)
+static int osst_configure_onstream(struct osst_tape *STp, struct scsi_request ** aSRpnt)
 {
 	unsigned char                  cmd[MAX_COMMAND_SIZE];
 	char                         * name = tape_name(STp);
-	Scsi_Request                 * SRpnt = * aSRpnt;
+	struct scsi_request                 * SRpnt = * aSRpnt;
 	osst_mode_parameter_header_t * header;
 	osst_block_size_page_t       * bs;
 	osst_capabilities_page_t     * cp;
@@ -2645,7 +2714,7 @@
 
 /* Step over EOF if it has been inadvertently crossed (ioctl not used because
    it messes up the block number). */
-static int cross_eof(OS_Scsi_Tape *STp, Scsi_Request ** aSRpnt, int forward)
+static int cross_eof(struct osst_tape *STp, struct scsi_request ** aSRpnt, int forward)
 {
 	int	result;
 	char  * name = tape_name(STp);
@@ -2674,18 +2743,18 @@
 
 /* Get the tape position. */
 
-static int osst_get_frame_position(OS_Scsi_Tape *STp, Scsi_Request ** aSRpnt)
+static int osst_get_frame_position(struct osst_tape *STp, struct scsi_request ** aSRpnt)
 {
-	unsigned char	scmd[MAX_COMMAND_SIZE];
-	Scsi_Request  * SRpnt;
-	int		result = 0;
+	unsigned char		scmd[MAX_COMMAND_SIZE];
+	struct scsi_request   * SRpnt;
+	int			result = 0;
+	char    	      * name   = tape_name(STp);
 
 	/* KG: We want to be able to use it for checking Write Buffer availability
 	 *  and thus don't want to risk to overwrite anything. Exchange buffers ... */
 	char		mybuf[24];
 	char	      * olddata = STp->buffer->b_data;
 	int		oldsize = STp->buffer->buffer_size;
-	char          * name    = tape_name(STp);
 
 	if (STp->ready != ST_READY) return (-EIO);
 
@@ -2702,13 +2771,12 @@
 	*aSRpnt = SRpnt;
 
 	if (STp->buffer->syscall_result)
-		result = ((SRpnt->sr_sense_buffer[2] & 0x0f) == 3) ? -EIO : -EINVAL;
+		result = ((SRpnt->sr_sense_buffer[2] & 0x0f) == 3) ? -EIO : -EINVAL;	/* 3: Write Error */
 
 	if (result == -EINVAL)
 		printk(KERN_ERR "%s:E: Can't read tape position.\n", name);
 	else {
-
-		if (result == -EIO) {	/* re-read position */
+		if (result == -EIO) {	/* re-read position - this needs to preserve media errors */
 			unsigned char mysense[16];
 			memcpy (mysense, SRpnt->sr_sense_buffer, 16);
 			memset (scmd, 0, MAX_COMMAND_SIZE);
@@ -2716,8 +2784,15 @@
 			STp->buffer->b_data = mybuf; STp->buffer->buffer_size = 24;
 			SRpnt = osst_do_scsi(SRpnt, STp, scmd, 20, SCSI_DATA_READ,
 						    STp->timeout, MAX_RETRIES, TRUE);
+#if DEBUG
+			printk(OSST_DEB_MSG "%s:D: Reread position, reason=[%02x:%02x:%02x], result=[%s%02x:%02x:%02x]\n",
+					name, mysense[2], mysense[12], mysense[13], STp->buffer->syscall_result?"":"ok:",
+					SRpnt->sr_sense_buffer[2],SRpnt->sr_sense_buffer[12],SRpnt->sr_sense_buffer[13]);
+#endif
 			if (!STp->buffer->syscall_result)
 				memcpy (SRpnt->sr_sense_buffer, mysense, 16);
+			else
+				printk(KERN_WARNING "%s:W: Double error in get position\n", name);
 		}
 		STp->first_frame_position = ((STp->buffer)->b_data[4] << 24)
 					  + ((STp->buffer)->b_data[5] << 16)
@@ -2739,7 +2814,7 @@
 #endif
 		if (STp->cur_frames == 0 && STp->first_frame_position != STp->last_frame_position) {
 #if DEBUG
-			printk(KERN_WARNING "%s:D: Correcting read position %d, %d, %d\n", name,
+			printk(OSST_DEB_MSG "%s:D: Correcting read position %d, %d, %d\n", name,
 					STp->first_frame_position, STp->last_frame_position, STp->cur_frames);
 #endif
 			STp->first_frame_position = STp->last_frame_position;
@@ -2752,14 +2827,14 @@
 
 
 /* Set the tape block */
-static int osst_set_frame_position(OS_Scsi_Tape *STp, Scsi_Request ** aSRpnt, int ppos, int skip)
+static int osst_set_frame_position(struct osst_tape *STp, struct scsi_request ** aSRpnt, int ppos, int skip)
 {
-	unsigned char	scmd[MAX_COMMAND_SIZE];
-	Scsi_Request  * SRpnt;
-	struct st_partstat   * STps;
-	int		result = 0;
-	int		pp     = (ppos == 3000 && !skip)? 0 : ppos;
-	char          * name   = tape_name(STp);
+	unsigned char		scmd[MAX_COMMAND_SIZE];
+	struct scsi_request   * SRpnt;
+	struct st_partstat    * STps;
+	int			result = 0;
+	int			pp     = (ppos == 3000 && !skip)? 0 : ppos;
+	char		      * name   = tape_name(STp);
 
 	if (STp->ready != ST_READY) return (-EIO);
 
@@ -2810,7 +2885,7 @@
 	return result;
 }
 
-static int osst_write_trailer(OS_Scsi_Tape *STp, Scsi_Request ** aSRpnt, int leave_at_EOT)
+static int osst_write_trailer(struct osst_tape *STp, struct scsi_request ** aSRpnt, int leave_at_EOT)
 {
 	struct st_partstat * STps = &(STp->ps[STp->partition]);
 	int result = 0;
@@ -2837,26 +2912,26 @@
 /* osst versions of st functions - augmented and stripped to suit OnStream only */
 
 /* Flush the write buffer (never need to write if variable blocksize). */
-static int osst_flush_write_buffer(OS_Scsi_Tape *STp, Scsi_Request ** aSRpnt)
+static int osst_flush_write_buffer(struct osst_tape *STp, struct scsi_request ** aSRpnt)
 {
-	int            offset, transfer, blks = 0;
-	int            result = 0;
-	unsigned char  cmd[MAX_COMMAND_SIZE];
-	Scsi_Request * SRpnt = *aSRpnt;
-	struct st_partstat  * STps;
-	char         * name = tape_name(STp);
+	int			offset, transfer, blks = 0;
+	int			result = 0;
+	unsigned char		cmd[MAX_COMMAND_SIZE];
+	struct scsi_request   * SRpnt = *aSRpnt;
+	struct st_partstat    * STps;
+	char		      * name = tape_name(STp);
 
 	if ((STp->buffer)->writing) {
 		if (SRpnt == (STp->buffer)->last_SRpnt)
 #if DEBUG
 			{ printk(OSST_DEB_MSG
-	 "%s:D: aSRpnt points to Scsi_Request that write_behind_check will release -- cleared\n", name);
+	 "%s:D: aSRpnt points to scsi_request that write_behind_check will release -- cleared\n", name);
 #endif
 			*aSRpnt = SRpnt = NULL;
 #if DEBUG
 			} else if (SRpnt)
 				printk(OSST_DEB_MSG
-	 "%s:D: aSRpnt does not point to Scsi_Request that write_behind_check will release -- strange\n", name);
+	 "%s:D: aSRpnt does not point to scsi_request that write_behind_check will release -- strange\n", name);
 #endif	
 		osst_write_behind_check(STp);
 		if ((STp->buffer)->syscall_result) {
@@ -2884,9 +2959,9 @@
 		if (offset < OS_DATA_SIZE)
 			osst_zero_buffer_tail(STp->buffer);
 
-		/* TODO: Error handling! */
 		if (STp->poll)
-			result = osst_wait_frame (STp, aSRpnt, STp->first_frame_position, -50, 120);
+			if (osst_wait_frame (STp, aSRpnt, STp->first_frame_position, -50, 120))
+				result = osst_recover_wait_frame(STp, aSRpnt, 1);
 
 		memset(cmd, 0, MAX_COMMAND_SIZE);
 		cmd[0] = WRITE_6;
@@ -2925,7 +3000,7 @@
 #endif
 
 		SRpnt = osst_do_scsi(*aSRpnt, STp, cmd, transfer, SCSI_DATA_WRITE,
-					  STp->timeout, MAX_WRITE_RETRIES, TRUE);
+					      STp->timeout, MAX_RETRIES, TRUE);
 		*aSRpnt = SRpnt;
 		if (!SRpnt)
 			return (-EBUSY);
@@ -2967,12 +3042,12 @@
 
 /* Flush the tape buffer. The tape will be positioned correctly unless
    seek_next is true. */
-static int osst_flush_buffer(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt, int seek_next)
+static int osst_flush_buffer(struct osst_tape * STp, struct scsi_request ** aSRpnt, int seek_next)
 {
 	struct st_partstat * STps;
-	int           backspace = 0, result = 0;
+	int    backspace = 0, result = 0;
 #if DEBUG
-	char        * name = tape_name(STp);
+	char * name = tape_name(STp);
 #endif
 
 	/*
@@ -3029,13 +3104,13 @@
 	return result;
 }
 
-static int osst_write_frame(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt, int synchronous)
+static int osst_write_frame(struct osst_tape * STp, struct scsi_request ** aSRpnt, int synchronous)
 {
-	unsigned char	cmd[MAX_COMMAND_SIZE];
-	Scsi_Request  * SRpnt;
-	int		blks;
+	unsigned char		cmd[MAX_COMMAND_SIZE];
+	struct scsi_request   * SRpnt;
+	int			blks;
 #if DEBUG
-	char          * name = tape_name(STp);
+	char		      * name = tape_name(STp);
 #endif
 
 	if ((!STp-> raw) && (STp->first_frame_position == 0xbae)) { /* _must_ preserve buffer! */
@@ -3055,8 +3130,9 @@
 	}
 
 	if (STp->poll)
-		osst_wait_frame (STp, aSRpnt, STp->first_frame_position, -50, 60);
-	/* TODO: Check for an error ! */
+		if (osst_wait_frame (STp, aSRpnt, STp->first_frame_position, -48, 120))
+			if (osst_recover_wait_frame(STp, aSRpnt, 1))
+				return (-EIO);
 
 //	osst_build_stats(STp, &SRpnt);
 
@@ -3081,7 +3157,7 @@
 		STp->write_pending = 1;
 #endif
 	SRpnt = osst_do_scsi(*aSRpnt, STp, cmd, OS_FRAME_SIZE, SCSI_DATA_WRITE, STp->timeout,
-							MAX_WRITE_RETRIES, synchronous);
+									MAX_RETRIES, synchronous);
 	if (!SRpnt)
 		return (-EBUSY);
 	*aSRpnt = SRpnt;
@@ -3111,8 +3187,8 @@
 	return 0;
 }
 
-/* Lock or unlock the drive door. Don't use when Scsi_Request allocated. */
-static int do_door_lock(OS_Scsi_Tape * STp, int do_lock)
+/* Lock or unlock the drive door. Don't use when struct scsi_request allocated. */
+static int do_door_lock(struct osst_tape * STp, int do_lock)
 {
 	int retval, cmd;
 
@@ -3131,7 +3207,7 @@
 }
 
 /* Set the internal state after reset */
-static void reset_state(OS_Scsi_Tape *STp)
+static void reset_state(struct osst_tape *STp)
 {
 	int i;
 	struct st_partstat *STps;
@@ -3154,16 +3230,16 @@
 /* Write command */
 static ssize_t osst_write(struct file * filp, const char __user * buf, size_t count, loff_t *ppos)
 {
-	ssize_t        total, retval = 0;
-	ssize_t        i, do_count, blks, transfer;
-	int            write_threshold;
-	int            doing_write = 0;
+	ssize_t		      total, retval = 0;
+	ssize_t		      i, do_count, blks, transfer;
+	int		      write_threshold;
+	int		      doing_write = 0;
 	const char   __user * b_point;
-	Scsi_Request * SRpnt = NULL;
+	struct scsi_request * SRpnt = NULL;
 	struct st_modedef   * STm;
 	struct st_partstat  * STps;
-	OS_Scsi_Tape * STp  = filp->private_data;
-	char         * name = tape_name(STp);
+	struct osst_tape    * STp  = filp->private_data;
+	char		    * name = tape_name(STp);
 
 
 	if (down_interruptible(&STp->lock))
@@ -3477,14 +3553,14 @@
 /* Read command */
 static ssize_t osst_read(struct file * filp, char __user * buf, size_t count, loff_t *ppos)
 {
-	ssize_t        total, retval = 0;
-	ssize_t        i, transfer;
-	int            special;
-	struct st_modedef      * STm;
+	ssize_t		      total, retval = 0;
+	ssize_t		      i, transfer;
+	int		      special;
+	struct st_modedef   * STm;
 	struct st_partstat  * STps;
-	Scsi_Request * SRpnt = NULL;
-	OS_Scsi_Tape * STp   = filp->private_data;
-	char         * name  = tape_name(STp);
+	struct scsi_request * SRpnt = NULL;
+	struct osst_tape    * STp   = filp->private_data;
+	char		    * name  = tape_name(STp);
 
 
 	if (down_interruptible(&STp->lock))
@@ -3660,8 +3736,7 @@
 
 
 /* Set the driver options */
-static void osst_log_options(OS_Scsi_Tape *STp, struct st_modedef *STm,
-			     char *name)
+static void osst_log_options(struct osst_tape *STp, struct st_modedef *STm, char *name)
 {
   printk(KERN_INFO
 "%s:I: Mode %d options: buffer writes: %d, async writes: %d, read ahead: %d\n",
@@ -3684,12 +3759,12 @@
 }
 
 
-static int osst_set_options(OS_Scsi_Tape *STp, long options)
+static int osst_set_options(struct osst_tape *STp, long options)
 {
-	int       value;
-	long      code;
+	int		    value;
+	long		    code;
 	struct st_modedef * STm;
-	char    * name = tape_name(STp);
+	char		  * name = tape_name(STp);
 
 	STm = &(STp->modes[STp->current_mode]);
 	if (!STm->defined) {
@@ -3840,18 +3915,19 @@
 
 
 /* Internal ioctl function */
-static int osst_int_ioctl(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt, unsigned int cmd_in, unsigned long arg)
+static int osst_int_ioctl(struct osst_tape * STp, struct scsi_request ** aSRpnt,
+			     unsigned int cmd_in, unsigned long arg)
 {
-	int            timeout;
-	long           ltmp;
-	int            i, ioctl_result;
-	int            chg_eof = TRUE;
-	unsigned char  cmd[MAX_COMMAND_SIZE];
-	Scsi_Request * SRpnt = * aSRpnt;
-	struct st_partstat  * STps;
-	int            fileno, blkno, at_sm, frame_seq_numbr, logical_blk_num;
-	int            datalen = 0, direction = SCSI_DATA_NONE;
-	char         * name = tape_name(STp);
+	int			timeout;
+	long			ltmp;
+	int			i, ioctl_result;
+	int			chg_eof = TRUE;
+	unsigned char		cmd[MAX_COMMAND_SIZE];
+	struct scsi_request   * SRpnt = * aSRpnt;
+	struct st_partstat    * STps;
+	int			fileno, blkno, at_sm, frame_seq_numbr, logical_blk_num;
+	int			datalen = 0, direction = SCSI_DATA_NONE;
+	char		      * name = tape_name(STp);
 
 	if (STp->ready != ST_READY && cmd_in != MTLOAD) {
 		if (STp->ready == ST_NO_TAPE)
@@ -4227,16 +4303,16 @@
 /* Open the device */
 static int os_scsi_tape_open(struct inode * inode, struct file * filp)
 {
-	unsigned short flags;
-	int            i, b_size, new_session = FALSE, retval = 0;
-	unsigned char  cmd[MAX_COMMAND_SIZE];
-	Scsi_Request * SRpnt = NULL;
-	OS_Scsi_Tape * STp;
-	struct st_modedef      * STm;
+	unsigned short	      flags;
+	int		      i, b_size, new_session = FALSE, retval = 0;
+	unsigned char	      cmd[MAX_COMMAND_SIZE];
+	struct scsi_request * SRpnt = NULL;
+	struct osst_tape    * STp;
+	struct st_modedef   * STm;
 	struct st_partstat  * STps;
-	char         * name;
-	int            dev  = TAPE_NR(inode);
-	int            mode = TAPE_MODE(inode);
+	char		    * name;
+	int		      dev  = TAPE_NR(inode);
+	int		      mode = TAPE_MODE(inode);
 
 	nonseekable_open(inode, filp);
 	write_lock(&os_scsi_tapes_lock);
@@ -4327,9 +4403,9 @@
 	memset (cmd, 0, MAX_COMMAND_SIZE);
 	cmd[0] = TEST_UNIT_READY;
 
-	SRpnt = osst_do_scsi(NULL, STp, cmd, 0, SCSI_DATA_NONE, STp->timeout, MAX_READY_RETRIES, TRUE);
+	SRpnt = osst_do_scsi(NULL, STp, cmd, 0, SCSI_DATA_NONE, STp->timeout, MAX_RETRIES, TRUE);
 	if (!SRpnt) {
-		retval = (STp->buffer)->syscall_result;
+		retval = (STp->buffer)->syscall_result;		/* FIXME - valid? */
 		goto err_out;
 	}
 	if ((SRpnt->sr_sense_buffer[0] & 0x70) == 0x70      &&
@@ -4348,7 +4424,7 @@
 			cmd[1] = 1;
 			cmd[4] = 1;
 			SRpnt = osst_do_scsi(SRpnt, STp, cmd, 0, SCSI_DATA_NONE,
-					     STp->timeout, MAX_READY_RETRIES, TRUE);
+					     STp->timeout, MAX_RETRIES, TRUE);
 		}
 		osst_wait_ready(STp, &SRpnt, (SRpnt->sr_sense_buffer[13]==1?15:3) * 60, 0);
 	}
@@ -4365,7 +4441,7 @@
 			cmd[0] = TEST_UNIT_READY;
 
 			SRpnt = osst_do_scsi(SRpnt, STp, cmd, 0, SCSI_DATA_NONE,
-					     STp->timeout, MAX_READY_RETRIES, TRUE);
+					     STp->timeout, MAX_RETRIES, TRUE);
 			if ((SRpnt->sr_sense_buffer[0] & 0x70) != 0x70 ||
 			    (SRpnt->sr_sense_buffer[2] & 0x0f) != UNIT_ATTENTION)
 				break;
@@ -4386,6 +4462,7 @@
 		}
 		new_session = TRUE;
 		STp->recover_count = 0;
+		STp->abort_count = 0;
 	}
 	/*
 	 * if we have valid headers from before, and the drive/tape seem untouched,
@@ -4473,7 +4550,7 @@
 			cmd[0] = TEST_UNIT_READY;
 
 			SRpnt = osst_do_scsi(SRpnt, STp, cmd, 0, SCSI_DATA_NONE,
-					     STp->timeout, MAX_READY_RETRIES, TRUE);
+						    STp->timeout, MAX_RETRIES, TRUE);
 			if ((SRpnt->sr_sense_buffer[0] & 0x70) != 0x70 ||
 			    (SRpnt->sr_sense_buffer[2] & 0x0f) == NOT_READY)
 			break;
@@ -4588,12 +4665,12 @@
 /* Flush the tape buffer before close */
 static int os_scsi_tape_flush(struct file * filp)
 {
-	int            result = 0, result2;
-	OS_Scsi_Tape * STp  = filp->private_data;
-	struct st_modedef      * STm  = &(STp->modes[STp->current_mode]);
-	struct st_partstat  * STps = &(STp->ps[STp->partition]);
-	Scsi_Request * SRpnt = NULL;
-	char         * name = tape_name(STp);
+	int		      result = 0, result2;
+	struct osst_tape    * STp    = filp->private_data;
+	struct st_modedef   * STm    = &(STp->modes[STp->current_mode]);
+	struct st_partstat  * STps   = &(STp->ps[STp->partition]);
+	struct scsi_request * SRpnt  = NULL;
+	char		    * name   = tape_name(STp);
 
 	if (file_count(filp) > 1)
 		return 0;
@@ -4657,14 +4734,19 @@
 	}
 	if (SRpnt) scsi_release_request(SRpnt);
 
-	if (STp->recover_count) {
-		printk(KERN_INFO "%s:I: %d recovered errors in", name, STp->recover_count);
+	if (STp->abort_count || STp->recover_count) {
+		printk(KERN_INFO "%s:I:", name);
+		if (STp->abort_count)
+			printk(" %d unrecovered errors", STp->abort_count);
+		if (STp->recover_count)
+			printk(" %d recovered errors", STp->recover_count);
 		if (STp->write_count)
-			printk(" %d frames written", STp->write_count);
+			printk(" in %d frames written", STp->write_count);
 		if (STp->read_count)
-			printk(" %d frames read", STp->read_count);
+			printk(" in %d frames read", STp->read_count);
 		printk("\n");
 		STp->recover_count = 0;
+		STp->abort_count   = 0;
 	}
 	STp->write_count = 0;
 	STp->read_count  = 0;
@@ -4676,9 +4758,9 @@
 /* Close the device and release it */
 static int os_scsi_tape_close(struct inode * inode, struct file * filp)
 {
-	int result = 0;
-	OS_Scsi_Tape * STp = filp->private_data;
-	Scsi_Request * SRpnt = NULL;
+	int		      result = 0;
+	struct osst_tape    * STp    = filp->private_data;
+	struct scsi_request * SRpnt  = NULL;
 
 	if (SRpnt) scsi_release_request(SRpnt);
 
@@ -4703,14 +4785,14 @@
 static int osst_ioctl(struct inode * inode,struct file * file,
 	 unsigned int cmd_in, unsigned long arg)
 {
-	int            i, cmd_nr, cmd_type, retval = 0;
-	unsigned int   blk;
-	struct st_modedef      * STm;
+	int		      i, cmd_nr, cmd_type, retval = 0;
+	unsigned int	      blk;
+	struct st_modedef   * STm;
 	struct st_partstat  * STps;
-	Scsi_Request * SRpnt = NULL;
-	OS_Scsi_Tape * STp   = file->private_data;
-	char         * name  = tape_name(STp);
-	void __user *p = (void __user *)arg;
+	struct scsi_request * SRpnt = NULL;
+	struct osst_tape    * STp   = file->private_data;
+	char		    * name  = tape_name(STp);
+	void	    __user  * p     = (void __user *)arg;
 
 	if (down_interruptible(&STp->lock))
 		return -ERESTARTSYS;
@@ -5039,18 +5121,18 @@
 /* Memory handling routines */
 
 /* Try to allocate a new tape buffer skeleton. Caller must not hold os_scsi_tapes_lock */
-static OSST_buffer * new_tape_buffer( int from_initialization, int need_dma, int max_sg )
+static struct osst_buffer * new_tape_buffer( int from_initialization, int need_dma, int max_sg )
 {
 	int i, priority;
-	OSST_buffer *tb;
+	struct osst_buffer *tb;
 
 	if (from_initialization)
 		priority = GFP_ATOMIC;
 	else
 		priority = GFP_KERNEL;
 
-	i = sizeof(OSST_buffer) + (osst_max_sg_segs - 1) * sizeof(struct scatterlist);
-	tb = (OSST_buffer *)kmalloc(i, priority);
+	i = sizeof(struct osst_buffer) + (osst_max_sg_segs - 1) * sizeof(struct scatterlist);
+	tb = (struct osst_buffer *)kmalloc(i, priority);
 	if (!tb) {
 		printk(KERN_NOTICE "osst :I: Can't allocate new tape buffer.\n");
 		return NULL;
@@ -5071,7 +5153,7 @@
 }
 
 /* Try to allocate a temporary (while a user has the device open) enlarged tape buffer */
-static int enlarge_buffer(OSST_buffer *STbuffer, int need_dma)
+static int enlarge_buffer(struct osst_buffer *STbuffer, int need_dma)
 {
 	int segs, nbr, max_segs, b_size, priority, order, got;
 
@@ -5087,12 +5169,10 @@
 	if (nbr <= 2)
 		return FALSE;
 
-	priority = GFP_KERNEL;
+	priority = GFP_KERNEL /* | __GFP_NOWARN */;
 	if (need_dma)
 		priority |= GFP_DMA;
 
-	priority |= __GFP_NOWARN;
-
 	/* Try to allocate the first segment up to OS_DATA_SIZE and the others
 	   big enough to reach the goal (code assumes no segments in place) */
 	for (b_size = OS_DATA_SIZE, order = OSST_FIRST_ORDER; b_size >= PAGE_SIZE; order--, b_size /= 2) {
@@ -5150,7 +5230,7 @@
 
 
 /* Release the segments */
-static void normalize_buffer(OSST_buffer *STbuffer)
+static void normalize_buffer(struct osst_buffer *STbuffer)
 {
   int i, order, b_size;
 
@@ -5174,7 +5254,7 @@
 
 /* Move data from the user buffer to the tape buffer. Returns zero (success) or
    negative error code. */
-static int append_to_buffer(const char __user *ubp, OSST_buffer *st_bp, int do_count)
+static int append_to_buffer(const char __user *ubp, struct osst_buffer *st_bp, int do_count)
 {
 	int i, cnt, res, offset;
 
@@ -5207,7 +5287,7 @@
 
 /* Move data from the tape buffer to the user buffer. Returns zero (success) or
    negative error code. */
-static int from_buffer(OSST_buffer *st_bp, char __user *ubp, int do_count)
+static int from_buffer(struct osst_buffer *st_bp, char __user *ubp, int do_count)
 {
 	int i, cnt, res, offset;
 
@@ -5239,7 +5319,7 @@
 
 /* Sets the tail of the buffer after fill point to zero.
    Returns zero (success) or negative error code.        */
-static int osst_zero_buffer_tail(OSST_buffer *st_bp)
+static int osst_zero_buffer_tail(struct osst_buffer *st_bp)
 {
 	int	i, offset, do_count, cnt;
 
@@ -5267,7 +5347,7 @@
 
 /* Copy a osst 32K chunk of memory into the buffer.
    Returns zero (success) or negative error code.  */
-static int osst_copy_to_buffer(OSST_buffer *st_bp, unsigned char *ptr)
+static int osst_copy_to_buffer(struct osst_buffer *st_bp, unsigned char *ptr)
 {
 	int	i, cnt, do_count = OS_DATA_SIZE;
 
@@ -5288,7 +5368,7 @@
 
 /* Copy a osst 32K chunk of memory from the buffer.
    Returns zero (success) or negative error code.  */
-static int osst_copy_from_buffer(OSST_buffer *st_bp, unsigned char *ptr)
+static int osst_copy_from_buffer(struct osst_buffer *st_bp, unsigned char *ptr)
 {
 	int	i, cnt, do_count = OS_DATA_SIZE;
 
@@ -5406,18 +5486,163 @@
 }
 
 /*
+ * sysfs support for osst driver parameter information
+ */
+
+static ssize_t osst_version_show(struct device_driver *ddd, char *buf)
+{
+	return snprintf(buf, PAGE_SIZE, "%s\n", osst_version);
+}
+
+static DRIVER_ATTR(version, S_IRUGO, osst_version_show, NULL);
+
+static void osst_create_driverfs_files(struct device_driver *driverfs)
+{
+	driver_create_file(driverfs, &driver_attr_version);
+}
+
+static void osst_remove_driverfs_files(struct device_driver *driverfs)
+{
+	driver_remove_file(driverfs, &driver_attr_version);
+}
+
+/*
+ * sysfs support for accessing ADR header information
+ */
+
+static ssize_t osst_adr_rev_show(struct class_device *class_dev, char *buf)
+{
+	struct osst_tape * STp = (struct osst_tape *) class_get_devdata (class_dev);
+	ssize_t l = 0;
+
+	if (STp && STp->header_ok && STp->linux_media)
+		l = snprintf(buf, PAGE_SIZE, "%d.%d\n", STp->header_cache->major_rev, STp->header_cache->minor_rev);
+	return l;
+}
+
+CLASS_DEVICE_ATTR(ADR_rev, S_IRUGO, osst_adr_rev_show, NULL);
+
+static ssize_t osst_linux_media_version_show(struct class_device *class_dev, char *buf)
+{
+	struct osst_tape * STp = (struct osst_tape *) class_get_devdata (class_dev);
+	ssize_t l = 0;
+
+	if (STp && STp->header_ok && STp->linux_media)
+		l = snprintf(buf, PAGE_SIZE, "LIN%d\n", STp->linux_media_version);
+	return l;
+}
+
+CLASS_DEVICE_ATTR(media_version, S_IRUGO, osst_linux_media_version_show, NULL);
+
+static ssize_t osst_capacity_show(struct class_device *class_dev, char *buf)
+{
+	struct osst_tape * STp = (struct osst_tape *) class_get_devdata (class_dev);
+	ssize_t l = 0;
+
+	if (STp && STp->header_ok && STp->linux_media)
+		l = snprintf(buf, PAGE_SIZE, "%d\n", STp->capacity);
+	return l;
+}
+
+CLASS_DEVICE_ATTR(capacity, S_IRUGO, osst_capacity_show, NULL);
+
+static ssize_t osst_first_data_ppos_show(struct class_device *class_dev, char *buf)
+{
+	struct osst_tape * STp = (struct osst_tape *) class_get_devdata (class_dev);
+	ssize_t l = 0;
+
+	if (STp && STp->header_ok && STp->linux_media)
+		l = snprintf(buf, PAGE_SIZE, "%d\n", STp->first_data_ppos);
+	return l;
+}
+
+CLASS_DEVICE_ATTR(BOT_frame, S_IRUGO, osst_first_data_ppos_show, NULL);
+
+static ssize_t osst_eod_frame_ppos_show(struct class_device *class_dev, char *buf)
+{
+	struct osst_tape * STp = (struct osst_tape *) class_get_devdata (class_dev);
+	ssize_t l = 0;
+
+	if (STp && STp->header_ok && STp->linux_media)
+		l = snprintf(buf, PAGE_SIZE, "%d\n", STp->eod_frame_ppos);
+	return l;
+}
+
+CLASS_DEVICE_ATTR(EOD_frame, S_IRUGO, osst_eod_frame_ppos_show, NULL);
+
+static ssize_t osst_filemark_cnt_show(struct class_device *class_dev, char *buf)
+{
+	struct osst_tape * STp = (struct osst_tape *) class_get_devdata (class_dev);
+	ssize_t l = 0;
+
+	if (STp && STp->header_ok && STp->linux_media)
+		l = snprintf(buf, PAGE_SIZE, "%d\n", STp->filemark_cnt);
+	return l;
+}
+
+CLASS_DEVICE_ATTR(file_count, S_IRUGO, osst_filemark_cnt_show, NULL);
+
+static struct class_simple * osst_sysfs_class;
+
+static int osst_sysfs_valid = 0;
+
+static void osst_sysfs_init(void)
+{
+	osst_sysfs_class = class_simple_create(THIS_MODULE, "onstream_tape");
+	if ( IS_ERR(osst_sysfs_class) )
+		printk(KERN_WARNING "osst :W: Unable to register sysfs class\n");
+	else
+		osst_sysfs_valid = TRUE;
+}
+
+static void osst_sysfs_add(dev_t dev, struct device *device, struct osst_tape * STp, char * name)
+{
+	struct class_device *osst_class_member;
+
+	if (!osst_sysfs_valid) return;
+
+	osst_class_member = class_simple_device_add(osst_sysfs_class, dev, device, "%s", name);
+	if (IS_ERR(osst_class_member)) {
+		printk(KERN_WARNING "osst :W: Unable to add sysfs class member %s\n", name);
+		return;
+	}
+	class_set_devdata(osst_class_member, STp);
+	class_device_create_file(osst_class_member, &class_device_attr_ADR_rev);
+	class_device_create_file(osst_class_member, &class_device_attr_media_version);
+	class_device_create_file(osst_class_member, &class_device_attr_capacity);
+	class_device_create_file(osst_class_member, &class_device_attr_BOT_frame);
+	class_device_create_file(osst_class_member, &class_device_attr_EOD_frame);
+	class_device_create_file(osst_class_member, &class_device_attr_file_count);
+}
+
+static void osst_sysfs_destroy(dev_t dev)
+{
+	if (!osst_sysfs_valid) return; 
+
+	class_simple_device_remove(dev);
+}
+
+static void osst_sysfs_cleanup(void)
+{
+	if (osst_sysfs_valid) {
+		class_simple_destroy(osst_sysfs_class);
+		osst_sysfs_valid = 0;
+	}
+}
+
+/*
  * osst startup / cleanup code
  */
 
 static int osst_probe(struct device *dev)
 {
-	Scsi_Device    * SDp = to_scsi_device(dev);
-	OS_Scsi_Tape   * tpnt;
-	struct st_modedef        * STm;
-	struct st_partstat    * STps;
-	OSST_buffer    * buffer;
-	struct gendisk * drive;
-	int              i, mode, dev_num;
+	Scsi_Device	   * SDp = to_scsi_device(dev);
+	struct osst_tape   * tpnt;
+	struct st_modedef  * STm;
+	struct st_partstat * STps;
+	struct osst_buffer * buffer;
+	struct gendisk	   * drive;
+	int		     i, mode, dev_num;
 
 	if (SDp->type != TYPE_TAPE || !osst_supports(SDp))
 		return -ENODEV;
@@ -5432,7 +5657,7 @@
 	write_lock(&os_scsi_tapes_lock);
 	if (os_scsi_tapes == NULL) {
 		os_scsi_tapes =
-			(OS_Scsi_Tape **)kmalloc(osst_max_dev * sizeof(OS_Scsi_Tape *),
+			(struct osst_tape **)kmalloc(osst_max_dev * sizeof(struct osst_tape *),
 				   GFP_ATOMIC);
 		if (os_scsi_tapes == NULL) {
 			write_unlock(&os_scsi_tapes_lock);
@@ -5453,14 +5678,14 @@
 	if(i >= osst_max_dev) panic ("Scsi_devices corrupt (osst)");
 	dev_num = i;
 
-	/* allocate a OS_Scsi_Tape for this device */
-	tpnt = (OS_Scsi_Tape *)kmalloc(sizeof(OS_Scsi_Tape), GFP_ATOMIC);
+	/* allocate a struct osst_tape for this device */
+	tpnt = (struct osst_tape *)kmalloc(sizeof(struct osst_tape), GFP_ATOMIC);
 	if (tpnt == NULL) {
 		write_unlock(&os_scsi_tapes_lock);
 		printk(KERN_ERR "osst :E: Can't allocate device descriptor, device not attached.\n");
 		goto out_put_disk;
 	}
-	memset(tpnt, 0, sizeof(OS_Scsi_Tape));
+	memset(tpnt, 0, sizeof(struct osst_tape));
 
 	/* allocate a buffer for this device */
 	i = SDp->host->sg_tablesize;
@@ -5545,7 +5770,14 @@
 	init_MUTEX(&tpnt->lock);
 	osst_nr_dev++;
 	write_unlock(&os_scsi_tapes_lock);
-
+	{
+		char name[8];
+		/*  Rewind entry  */
+		osst_sysfs_add(MKDEV(OSST_MAJOR, dev_num), dev, tpnt, tape_name(tpnt));
+		/*  No-rewind entry  */
+		snprintf(name, 8, "%s%s", "n", tape_name(tpnt));
+		osst_sysfs_add(MKDEV(OSST_MAJOR, dev_num + 128), dev, tpnt, name);
+	}
 	for (mode = 0; mode < ST_NBR_MODES; ++mode) {
 		/*  Rewind entry  */
 		devfs_mk_cdev(MKDEV(OSST_MAJOR, dev_num + (mode << 5)),
@@ -5572,8 +5804,8 @@
 
 static int osst_remove(struct device *dev)
 {
-	Scsi_Device  * SDp = to_scsi_device(dev);
-	OS_Scsi_Tape * tpnt;
+	Scsi_Device	 * SDp = to_scsi_device(dev);
+	struct osst_tape * tpnt;
 	int i, mode;
 
 	if ((SDp->type != TYPE_TAPE) || (osst_nr_dev <= 0))
@@ -5582,6 +5814,8 @@
 	write_lock(&os_scsi_tapes_lock);
 	for(i=0; i < osst_max_dev; i++) {
 		if((tpnt = os_scsi_tapes[i]) && (tpnt->device == SDp)) {
+			osst_sysfs_destroy(MKDEV(OSST_MAJOR, i));
+			osst_sysfs_destroy(MKDEV(OSST_MAJOR, i+128));
 			tpnt->device = NULL;
 			for (mode = 0; mode < ST_NBR_MODES; ++mode) {
 				devfs_remove("%s/ot%s", SDp->devfs_name, osst_formats[mode]);
@@ -5610,11 +5844,14 @@
 	printk(KERN_INFO "osst :I: Tape driver with OnStream support version %s\nosst :I: %s\n", osst_version, cvsid);
 
 	validate_options();
-	
+	osst_sysfs_init();
+
 	if ((register_chrdev(OSST_MAJOR,"osst", &osst_fops) < 0) || scsi_register_driver(&osst_template.gendrv)) {
 		printk(KERN_ERR "osst :E: Unable to register major %d for OnStream tapes\n", OSST_MAJOR);
+		osst_sysfs_cleanup();
 		return 1;
 	}
+	osst_create_driverfs_files(&osst_template.gendrv);
 
 	return 0;
 }
@@ -5622,10 +5859,12 @@
 static void __exit exit_osst (void)
 {
 	int i;
-	OS_Scsi_Tape * STp;
+	struct osst_tape * STp;
 
+	osst_remove_driverfs_files(&osst_template.gendrv);
 	scsi_unregister_driver(&osst_template.gendrv);
 	unregister_chrdev(OSST_MAJOR, "osst");
+	osst_sysfs_cleanup();
 
 	if (os_scsi_tapes) {
 		for (i=0; i < osst_max_dev; ++i) {
diff -Nru a/drivers/scsi/osst.h b/drivers/scsi/osst.h
--- a/drivers/scsi/osst.h	2005-01-02 23:10:07 -08:00
+++ b/drivers/scsi/osst.h	2005-01-02 23:10:07 -08:00
@@ -1,5 +1,5 @@
 /*
- *	$Header: /cvsroot/osst/Driver/osst.h,v 1.14 2003/12/14 14:34:38 wriede Exp $
+ *	$Header: /cvsroot/osst/Driver/osst.h,v 1.16 2005/01/01 21:13:35 wriede Exp $
  */
 
 #include <asm/byteorder.h>
@@ -70,7 +70,7 @@
 #define BLOCK_SIZE_PAGE_LENGTH     4
 
 #define BUFFER_FILLING_PAGE        0x33
-#define BUFFER_FILLING_PAGE_LENGTH 
+#define BUFFER_FILLING_PAGE_LENGTH 4
 
 #define VENDOR_IDENT_PAGE          0x36
 #define VENDOR_IDENT_PAGE_LENGTH   8
@@ -508,7 +508,7 @@
 //#define OSST_MAX_SG      2
 
 /* The OnStream tape buffer descriptor. */
-typedef struct {
+struct osst_buffer {
   unsigned char in_use;
   unsigned char dma;	/* DMA-able buffer */
   int buffer_size;
@@ -525,16 +525,16 @@
   unsigned short sg_segs;      /* number of segments in s/g list                  */
   unsigned short orig_sg_segs; /* number of segments allocated at first try       */
   struct scatterlist sg[1];    /* MUST BE last item                               */
-} OSST_buffer;
+} ;
 
 /* The OnStream tape drive descriptor */
-typedef struct {
+struct osst_tape {
   struct scsi_driver *driver;
   unsigned capacity;
   Scsi_Device* device;
   struct semaphore lock;       /* for serialization */
   struct completion wait;      /* for SCSI commands */
-  OSST_buffer * buffer;
+  struct osst_buffer * buffer;
 
   /* Drive characteristics */
   unsigned char omit_blklims;
@@ -577,6 +577,7 @@
   int min_block;
   int max_block;
   int recover_count;            /* from tape opening */
+  int abort_count;
   int write_count;
   int read_count;
   int recover_erreg;            /* from last status call */
@@ -623,7 +624,7 @@
   unsigned char last_sense[16];
 #endif
   struct gendisk *drive;
-} OS_Scsi_Tape;
+} ;
 
 /* Values of write_type */
 #define OS_WRITE_DATA      0
diff -Nru a/drivers/scsi/scsi_transport_spi.c b/drivers/scsi/scsi_transport_spi.c
--- a/drivers/scsi/scsi_transport_spi.c	2005-01-02 23:10:07 -08:00
+++ b/drivers/scsi/scsi_transport_spi.c	2005-01-02 23:10:07 -08:00
@@ -31,6 +31,7 @@
 #include <scsi/scsi_device.h>
 #include <scsi/scsi_host.h>
 #include <scsi/scsi_request.h>
+#include <scsi/scsi_eh.h>
 #include <scsi/scsi_transport.h>
 #include <scsi/scsi_transport_spi.h>
 
@@ -378,10 +379,16 @@
 #define DV_RETRIES	3	/* should only need at most 
 				 * two cc/ua clears */
 
+enum spi_compare_returns {
+	SPI_COMPARE_SUCCESS,
+	SPI_COMPARE_FAILURE,
+	SPI_COMPARE_SKIP_TEST,
+};
+
 
 /* This is for read/write Domain Validation:  If the device supports
  * an echo buffer, we do read/write tests to it */
-static int
+static enum spi_compare_returns
 spi_dv_device_echo_buffer(struct scsi_request *sreq, u8 *buffer,
 			  u8 *ptr, const int retries)
 {
@@ -438,9 +445,23 @@
 		scsi_wait_req(sreq, spi_write_buffer, buffer, len,
 			      DV_TIMEOUT, DV_RETRIES);
 		if(sreq->sr_result || !scsi_device_online(sdev)) {
+			struct scsi_sense_hdr sshdr;
+
 			scsi_device_set_state(sdev, SDEV_QUIESCE);
+			if (scsi_request_normalize_sense(sreq, &sshdr)
+			    && sshdr.sense_key == ILLEGAL_REQUEST
+			    /* INVALID FIELD IN CDB */
+			    && sshdr.asc == 0x24 && sshdr.ascq == 0x00)
+				/* This would mean that the drive lied
+				 * to us about supporting an echo
+				 * buffer (unfortunately some Western
+				 * Digital drives do precisely this)
+				 */
+				return SPI_COMPARE_SKIP_TEST;
+
+
 			SPI_PRINTK(sdev->sdev_target, KERN_ERR, "Write Buffer failure %x\n", sreq->sr_result);
-			return 0;
+			return SPI_COMPARE_FAILURE;
 		}
 
 		memset(ptr, 0, len);
@@ -451,14 +472,14 @@
 		scsi_device_set_state(sdev, SDEV_QUIESCE);
 
 		if (memcmp(buffer, ptr, len) != 0)
-			return 0;
+			return SPI_COMPARE_FAILURE;
 	}
-	return 1;
+	return SPI_COMPARE_SUCCESS;
 }
 
 /* This is for the simplest form of Domain Validation: a read test
  * on the inquiry data from the device */
-static int
+static enum spi_compare_returns
 spi_dv_device_compare_inquiry(struct scsi_request *sreq, u8 *buffer,
 			      u8 *ptr, const int retries)
 {
@@ -480,7 +501,7 @@
 		
 		if(sreq->sr_result || !scsi_device_online(sdev)) {
 			scsi_device_set_state(sdev, SDEV_QUIESCE);
-			return 0;
+			return SPI_COMPARE_FAILURE;
 		}
 
 		/* If we don't have the inquiry data already, the
@@ -493,24 +514,28 @@
 
 		if (memcmp(buffer, ptr, len) != 0)
 			/* failure */
-			return 0;
+			return SPI_COMPARE_FAILURE;
 	}
-	return 1;
+	return SPI_COMPARE_SUCCESS;
 }
 
-static int
+static enum spi_compare_returns
 spi_dv_retrain(struct scsi_request *sreq, u8 *buffer, u8 *ptr,
-	       int (*compare_fn)(struct scsi_request *, u8 *, u8 *, int))
+	       enum spi_compare_returns 
+	       (*compare_fn)(struct scsi_request *, u8 *, u8 *, int))
 {
 	struct spi_internal *i = to_spi_internal(sreq->sr_host->transportt);
 	struct scsi_device *sdev = sreq->sr_device;
 	int period = 0, prevperiod = 0; 
+	enum spi_compare_returns retval;
 
 
 	for (;;) {
 		int newperiod;
-		if (compare_fn(sreq, buffer, ptr, DV_LOOPS))
-			/* Successful DV */
+		retval = compare_fn(sreq, buffer, ptr, DV_LOOPS);
+
+		if (retval == SPI_COMPARE_SUCCESS
+		    || retval == SPI_COMPARE_SKIP_TEST)
 			break;
 
 		/* OK, retrain, fallback */
@@ -527,13 +552,13 @@
 			/* Total failure; set to async and return */
 			SPI_PRINTK(sdev->sdev_target, KERN_ERR, "Domain Validation Failure, dropping back to Asynchronous\n");
 			DV_SET(offset, 0);
-			return 0;
+			return SPI_COMPARE_FAILURE;
 		}
 		SPI_PRINTK(sdev->sdev_target, KERN_ERR, "Domain Validation detected failure, dropping back\n");
 		DV_SET(period, period);
 		prevperiod = period;
 	}
-	return 1;
+	return retval;
 }
 
 static int
@@ -599,7 +624,8 @@
 	DV_SET(offset, 0);
 	DV_SET(width, 0);
 	
-	if (!spi_dv_device_compare_inquiry(sreq, buffer, buffer, DV_LOOPS)) {
+	if (spi_dv_device_compare_inquiry(sreq, buffer, buffer, DV_LOOPS)
+	    != SPI_COMPARE_SUCCESS) {
 		SPI_PRINTK(sdev->sdev_target, KERN_ERR, "Domain Validation Initial Inquiry Failed\n");
 		/* FIXME: should probably offline the device here? */
 		return;
@@ -609,9 +635,10 @@
 	if (i->f->set_width && sdev->wdtr) {
 		i->f->set_width(sdev->sdev_target, 1);
 
-		if (!spi_dv_device_compare_inquiry(sreq, buffer,
+		if (spi_dv_device_compare_inquiry(sreq, buffer,
 						   buffer + len,
-						   DV_LOOPS)) {
+						   DV_LOOPS)
+		    != SPI_COMPARE_SUCCESS) {
 			SPI_PRINTK(sdev->sdev_target, KERN_ERR, "Wide Transfers Fail\n");
 			i->f->set_width(sdev->sdev_target, 0);
 		}
@@ -624,31 +651,39 @@
 	if(!sdev->ppr && !sdev->sdtr)
 		return;
 
-	/* now set up to the maximum */
-	DV_SET(offset, 255);
-	DV_SET(period, 1);
-	if (!spi_dv_retrain(sreq, buffer, buffer + len,
-			    spi_dv_device_compare_inquiry))
-		return;
-
-	/* OK, now we have our initial speed set by the read only inquiry
-	 * test, now try an echo buffer test (if the device allows it) */
+	/* see if the device has an echo buffer.  If it does we can
+	 * do the SPI pattern write tests */
 
 	len = 0;
 	if (sdev->ppr)
 		len = spi_dv_device_get_echo_buffer(sreq, buffer);
 
+ retry:
+
+	/* now set up to the maximum */
+	DV_SET(offset, 255);
+	DV_SET(period, 1);
+
 	if (len == 0) {
 		SPI_PRINTK(sdev->sdev_target, KERN_INFO, "Domain Validation skipping write tests\n");
+		spi_dv_retrain(sreq, buffer, buffer + len,
+			       spi_dv_device_compare_inquiry);
 		return;
 	}
+
 	if (len > SPI_MAX_ECHO_BUFFER_SIZE) {
 		SPI_PRINTK(sdev->sdev_target, KERN_WARNING, "Echo buffer size %d is too big, trimming to %d\n", len, SPI_MAX_ECHO_BUFFER_SIZE);
 		len = SPI_MAX_ECHO_BUFFER_SIZE;
 	}
 
-	spi_dv_retrain(sreq, buffer, buffer + len,
-		       spi_dv_device_echo_buffer);
+	if (spi_dv_retrain(sreq, buffer, buffer + len,
+			   spi_dv_device_echo_buffer)
+	    == SPI_COMPARE_SKIP_TEST) {
+		/* OK, the stupid drive can't do a write echo buffer
+		 * test after all, fall back to the read tests */
+		len = 0;
+		goto retry;
+	}
 }
 
 
diff -Nru a/drivers/scsi/sym53c8xx_2/sym_conf.h b/drivers/scsi/sym53c8xx_2/sym_conf.h
--- a/drivers/scsi/sym53c8xx_2/sym_conf.h	2005-01-02 23:10:07 -08:00
+++ b/drivers/scsi/sym53c8xx_2/sym_conf.h	2005-01-02 23:10:07 -08:00
@@ -79,14 +79,6 @@
 /* #define SYM_CONF_IARB_SUPPORT */
 
 /*
- *  Number of lists for the optimization of the IO timeout handling.
- *  Not used under FreeBSD and Linux.
- */
-#ifndef SYM_CONF_TIMEOUT_ORDER_MAX
-#define SYM_CONF_TIMEOUT_ORDER_MAX	(8)
-#endif
-
-/*
  *  Only relevant if IARB support configured.
  *  - Max number of successive settings of IARB hints.
  *  - Set IARB on arbitration lost.
diff -Nru a/drivers/scsi/sym53c8xx_2/sym_defs.h b/drivers/scsi/sym53c8xx_2/sym_defs.h
--- a/drivers/scsi/sym53c8xx_2/sym_defs.h	2005-01-02 23:10:07 -08:00
+++ b/drivers/scsi/sym53c8xx_2/sym_defs.h	2005-01-02 23:10:07 -08:00
@@ -40,30 +40,10 @@
 #ifndef SYM_DEFS_H
 #define SYM_DEFS_H
 
-#define SYM_VERSION "2.1.18m"
+#define SYM_VERSION "2.1.18n"
 #define SYM_DRIVER_NAME	"sym-" SYM_VERSION
 
 /*
- *  PCI device identifier of SYMBIOS chips.
- */
-#define PCI_ID_SYM53C810	PCI_DEVICE_ID_NCR_53C810
-#define PCI_ID_SYM53C810AP	PCI_DEVICE_ID_LSI_53C810AP
-#define PCI_ID_SYM53C815	PCI_DEVICE_ID_NCR_53C815
-#define PCI_ID_SYM53C820	PCI_DEVICE_ID_NCR_53C820
-#define PCI_ID_SYM53C825	PCI_DEVICE_ID_NCR_53C825
-#define PCI_ID_SYM53C860	PCI_DEVICE_ID_NCR_53C860
-#define PCI_ID_SYM53C875	PCI_DEVICE_ID_NCR_53C875
-#define PCI_ID_SYM53C875_2	PCI_DEVICE_ID_NCR_53C875J
-#define PCI_ID_SYM53C885	PCI_DEVICE_ID_NCR_53C885
-#define PCI_ID_SYM53C895	PCI_DEVICE_ID_NCR_53C895
-#define PCI_ID_SYM53C896	PCI_DEVICE_ID_NCR_53C896
-#define PCI_ID_SYM53C895A	PCI_DEVICE_ID_LSI_53C895A
-#define PCI_ID_SYM53C875A	PCI_DEVICE_ID_LSI_53C875A
-#define PCI_ID_LSI53C1010_33	PCI_DEVICE_ID_LSI_53C1010_33
-#define PCI_ID_LSI53C1010_66	PCI_DEVICE_ID_LSI_53C1010_66
-#define PCI_ID_LSI53C1510D	PCI_DEVICE_ID_LSI_53C1510
-
-/*
  *	SYM53C8XX device features descriptor.
  */
 struct sym_pci_chip {
@@ -764,27 +744,27 @@
 #define	M_RESTORE_DP	RESTORE_POINTERS
 #define	M_DISCONNECT	DISCONNECT
 #define	M_ID_ERROR	INITIATOR_ERROR
-#define	M_ABORT		ABORT
+#define	M_ABORT		ABORT_TASK_SET
 #define	M_REJECT	MESSAGE_REJECT
 #define	M_NOOP		NOP
 #define	M_PARITY	MSG_PARITY_ERROR
 #define	M_LCOMPLETE	LINKED_CMD_COMPLETE
 #define	M_FCOMPLETE	LINKED_FLG_CMD_COMPLETE
-#define	M_RESET		BUS_DEVICE_RESET
-#define	M_ABORT_TAG	(0x0d)
-#define	M_CLEAR_QUEUE	(0x0e)
+#define	M_RESET		TARGET_RESET
+#define	M_ABORT_TAG	ABORT_TASK
+#define	M_CLEAR_QUEUE	CLEAR_TASK_SET
 #define	M_INIT_REC	INITIATE_RECOVERY
 #define	M_REL_REC	RELEASE_RECOVERY
 #define	M_TERMINATE	(0x11)
 #define	M_SIMPLE_TAG	SIMPLE_QUEUE_TAG
 #define	M_HEAD_TAG	HEAD_OF_QUEUE_TAG
 #define	M_ORDERED_TAG	ORDERED_QUEUE_TAG
-#define	M_IGN_RESIDUE	(0x23)
+#define	M_IGN_RESIDUE	IGNORE_WIDE_RESIDUE
 
 #define	M_X_MODIFY_DP	EXTENDED_MODIFY_DATA_POINTER
 #define	M_X_SYNC_REQ	EXTENDED_SDTR
 #define	M_X_WIDE_REQ	EXTENDED_WDTR
-#define	M_X_PPR_REQ	(0x04)
+#define	M_X_PPR_REQ	EXTENDED_PPR
 
 /*
  *	PPR protocol options
diff -Nru a/drivers/scsi/sym53c8xx_2/sym_fw.c b/drivers/scsi/sym53c8xx_2/sym_fw.c
--- a/drivers/scsi/sym53c8xx_2/sym_fw.c	2005-01-02 23:10:07 -08:00
+++ b/drivers/scsi/sym53c8xx_2/sym_fw.c	2005-01-02 23:10:07 -08:00
@@ -223,13 +223,13 @@
 	 *  Remove a couple of work-arounds specific to C1010 if 
 	 *  they are not desirable. See `sym_fw2.h' for more details.
 	 */
-	if (!(np->device_id == PCI_ID_LSI53C1010_66 &&
+	if (!(np->device_id == PCI_DEVICE_ID_LSI_53C1010_66 &&
 	      np->revision_id < 0x1 &&
 	      np->pciclk_khz < 60000)) {
 		scripta0->datao_phase[0] = cpu_to_scr(SCR_NO_OP);
 		scripta0->datao_phase[1] = cpu_to_scr(0);
 	}
-	if (!(np->device_id == PCI_ID_LSI53C1010_33 &&
+	if (!(np->device_id == PCI_DEVICE_ID_LSI_53C1010_33 &&
 	      /* np->revision_id < 0xff */ 1)) {
 		scripta0->sel_done[0] = cpu_to_scr(SCR_NO_OP);
 		scripta0->sel_done[1] = cpu_to_scr(0);
diff -Nru a/drivers/scsi/sym53c8xx_2/sym_glue.c b/drivers/scsi/sym53c8xx_2/sym_glue.c
--- a/drivers/scsi/sym53c8xx_2/sym_glue.c	2005-01-02 23:10:07 -08:00
+++ b/drivers/scsi/sym53c8xx_2/sym_glue.c	2005-01-02 23:10:07 -08:00
@@ -55,6 +55,15 @@
 #define NAME53C		"sym53c"
 #define NAME53C8XX	"sym53c8xx"
 
+/* SPARC just has to be different ... */
+#ifdef __sparc__
+#define IRQ_FMT "%s"
+#define IRQ_PRM(x) __irq_itoa(x)
+#else
+#define IRQ_FMT "%d"
+#define IRQ_PRM(x) (x)
+#endif
+
 struct sym_driver_setup sym_driver_setup = SYM_LINUX_DRIVER_SETUP;
 unsigned int sym_debug_flags = 0;
 
@@ -147,7 +156,7 @@
 }
 
 /* This lock protects only the memory allocation/free.  */
-spinlock_t sym53c8xx_lock = SPIN_LOCK_UNLOCKED;
+static spinlock_t sym53c8xx_lock = SPIN_LOCK_UNLOCKED;
 
 static struct scsi_transport_template *sym2_transport_template = NULL;
 
@@ -285,7 +294,7 @@
 	ccb->scsi_done(ccb);
 }
 
-void sym_xpt_done2(struct sym_hcb *np, struct scsi_cmnd *ccb, int cam_status)
+static void sym_xpt_done2(struct sym_hcb *np, struct scsi_cmnd *ccb, int cam_status)
 {
 	sym_set_cam_status(ccb, cam_status);
 	sym_xpt_done(np, ccb);
@@ -379,7 +388,7 @@
 			/*
 			 *  Bounce back the sense data to user.
 			 */
-			bzero(&csio->sense_buffer, sizeof(csio->sense_buffer));
+			memset(&csio->sense_buffer, 0, sizeof(csio->sense_buffer));
 			memcpy(csio->sense_buffer, cp->sns_bbuf,
 			      min(sizeof(csio->sense_buffer),
 				  (size_t)SYM_SNS_BBUF_LEN));
@@ -513,7 +522,7 @@
 	}
 
 	/*
-	 *  Retreive the target descriptor.
+	 *  Retrieve the target descriptor.
 	 */
 	tp = &np->target[ccb->device->id];
 
@@ -1277,7 +1286,7 @@
 	int		arg_len;
 	u_long 		target;
 
-	bzero(uc, sizeof(*uc));
+	memset(uc, 0, sizeof(*uc));
 
 	if (len > 0 && ptr[len-1] == '\n')
 		--len;
@@ -1467,18 +1476,8 @@
 	copy_info(&info, "Chip " NAME53C "%s, device id 0x%x, "
 			 "revision id 0x%x\n",
 			 np->s.chip_name, np->device_id, np->revision_id);
-	copy_info(&info, "At PCI address %s, "
-#ifdef __sparc__
-		"IRQ %s\n",
-#else
-		"IRQ %d\n",
-#endif
-		pci_name(np->s.device),
-#ifdef __sparc__
-		__irq_itoa(np->s.irq));
-#else
-		(int) np->s.irq);
-#endif
+	copy_info(&info, "At PCI address %s, IRQ " IRQ_FMT "\n",
+		pci_name(np->s.device), IRQ_PRM(np->s.irq));
 	copy_info(&info, "Min. period factor %d, %s SCSI BUS%s\n",
 			 (int) (np->minsync_dt ? np->minsync_dt : np->minsync),
 			 np->maxwide ? "Wide" : "Narrow",
@@ -1558,32 +1557,23 @@
  */
 static int sym_setup_bus_dma_mask(struct sym_hcb *np)
 {
-#if   SYM_CONF_DMA_ADDRESSING_MODE == 0
-	if (pci_set_dma_mask(np->s.device, 0xffffffffUL))
-		goto out_err32;
-#else
+#if SYM_CONF_DMA_ADDRESSING_MODE > 0
 #if   SYM_CONF_DMA_ADDRESSING_MODE == 1
-#define	PciDmaMask	0xffffffffffULL
+#define	DMA_DAC_MASK	0x000000ffffffffffULL /* 40-bit */
 #elif SYM_CONF_DMA_ADDRESSING_MODE == 2
-#define	PciDmaMask	0xffffffffffffffffULL
+#define	DMA_DAC_MASK	DMA_64BIT_MASK
 #endif
-	if (np->features & FE_DAC) {
-		if (!pci_set_dma_mask(np->s.device, PciDmaMask)) {
-			np->use_dac = 1;
-			printf_info("%s: using 64 bit DMA addressing\n",
-					sym_name(np));
-		} else {
-			if (pci_set_dma_mask(np->s.device, 0xffffffffUL))
-				goto out_err32;
-		}
+	if ((np->features & FE_DAC) &&
+			!pci_set_dma_mask(np->s.device, DMA_DAC_MASK)) {
+		np->use_dac = 1;
+		return 0;
 	}
-#undef	PciDmaMask
 #endif
-	return 0;
 
-out_err32:
-	printf_warning("%s: 32 BIT DMA ADDRESSING NOT SUPPORTED\n",
-			sym_name(np));
+	if (!pci_set_dma_mask(np->s.device, DMA_32BIT_MASK))
+		return 0;
+
+	printf_warning("%s: No suitable DMA available\n", sym_name(np));
 	return -1;
 }
 
@@ -1606,19 +1596,9 @@
 	struct sym_fw *fw;
 
 	printk(KERN_INFO
-		"sym%d: <%s> rev 0x%x at pci %s "
-#ifdef __sparc__
-		"irq %s\n",
-#else
-		"irq %d\n",
-#endif
+		"sym%d: <%s> rev 0x%x at pci %s irq " IRQ_FMT "\n",
 		unit, dev->chip.name, dev->chip.revision_id,
-		pci_name(dev->pdev),
-#ifdef __sparc__
-		__irq_itoa(dev->s.irq));
-#else
-		dev->s.irq);
-#endif
+		pci_name(dev->pdev), IRQ_PRM(dev->s.irq));
 
 	/*
 	 *  Get the firmware for this chip.
@@ -1672,9 +1652,6 @@
 	strlcpy(np->s.chip_name, dev->chip.name, sizeof(np->s.chip_name));
 	sprintf(np->s.inst_name, "sym%d", np->s.unit);
 
-	/*
-	 *  Ask/tell the system about DMA addressing.
-	 */
 	if (sym_setup_bus_dma_mask(np))
 		goto attach_failed;
 
@@ -2010,7 +1987,7 @@
  * the preset SCSI ID (which may be zero) must be read in from
  * a special configuration space register of the 875.
  */
-void sym_config_pqs(struct pci_dev *pdev, struct sym_device *sym_dev)
+static void sym_config_pqs(struct pci_dev *pdev, struct sym_device *sym_dev)
 {
 	int slot;
 	u8 tmp;
diff -Nru a/drivers/scsi/sym53c8xx_2/sym_glue.h b/drivers/scsi/sym53c8xx_2/sym_glue.h
--- a/drivers/scsi/sym53c8xx_2/sym_glue.h	2005-01-02 23:10:07 -08:00
+++ b/drivers/scsi/sym53c8xx_2/sym_glue.h	2005-01-02 23:10:07 -08:00
@@ -58,13 +58,6 @@
 #include <scsi/scsi_device.h>
 #include <scsi/scsi_host.h>
 
-#ifndef bzero
-#define bzero(d, n)	memset((d), 0, (n))
-#endif
-
-/*
- *  General driver includes.
- */
 #include "sym_conf.h"
 #include "sym_defs.h"
 #include "sym_misc.h"
@@ -123,14 +116,6 @@
 typedef struct sym_tcb *tcb_p;
 typedef struct sym_lcb *lcb_p;
 typedef struct sym_ccb *ccb_p;
-typedef struct sym_hcb *hcb_p;
-
-/*
- *  Define a reference to the O/S dependent IO request.
- */
-typedef struct scsi_cmnd *cam_ccb_p;	/* Generic */
-typedef struct scsi_cmnd *cam_scsiio_p;/* SCSI I/O */
-
 
 /*
  *  IO functions definition for big/little endian CPU support.
@@ -525,7 +510,7 @@
 /*
  *  Async handler for negotiations.
  */
-void sym_xpt_async_nego_wide(hcb_p np, int target);
+void sym_xpt_async_nego_wide(struct sym_hcb *np, int target);
 #define sym_xpt_async_nego_sync(np, target)	\
 	sym_announce_transfer_rate(np, target)
 #define sym_xpt_async_nego_ppr(np, target)	\
@@ -534,14 +519,14 @@
 /*
  *  Build CAM result for a successful IO and for a failed IO.
  */
-static __inline void sym_set_cam_result_ok(hcb_p np, ccb_p cp, int resid)
+static __inline void sym_set_cam_result_ok(struct sym_hcb *np, ccb_p cp, int resid)
 {
 	struct scsi_cmnd *cmd = cp->cam_ccb;
 
 	cmd->resid = resid;
 	cmd->result = (((DID_OK) << 16) + ((cp->ssss_status) & 0x7f));
 }
-void sym_set_cam_result_error(hcb_p np, ccb_p cp, int resid);
+void sym_set_cam_result_error(struct sym_hcb *np, ccb_p cp, int resid);
 
 /*
  *  Other O/S specific methods.
@@ -549,13 +534,12 @@
 #define sym_cam_target_id(ccb)	(ccb)->target
 #define sym_cam_target_lun(ccb)	(ccb)->lun
 #define	sym_freeze_cam_ccb(ccb)	do { ; } while (0)
-void sym_xpt_done(hcb_p np, cam_ccb_p ccb);
-void sym_xpt_done2(hcb_p np, cam_ccb_p ccb, int cam_status);
+void sym_xpt_done(struct sym_hcb *np, struct scsi_cmnd *ccb);
 void sym_print_addr (ccb_p cp);
-void sym_xpt_async_bus_reset(hcb_p np);
-void sym_xpt_async_sent_bdr(hcb_p np, int target);
-int  sym_setup_data_and_start (hcb_p np, cam_scsiio_p csio, ccb_p cp);
-void sym_log_bus_error(hcb_p np);
-void sym_sniff_inquiry(hcb_p np, struct scsi_cmnd *cmd, int resid);
+void sym_xpt_async_bus_reset(struct sym_hcb *np);
+void sym_xpt_async_sent_bdr(struct sym_hcb *np, int target);
+int  sym_setup_data_and_start (struct sym_hcb *np, struct scsi_cmnd *csio, ccb_p cp);
+void sym_log_bus_error(struct sym_hcb *np);
+void sym_sniff_inquiry(struct sym_hcb *np, struct scsi_cmnd *cmd, int resid);
 
 #endif /* SYM_GLUE_H */
diff -Nru a/drivers/scsi/sym53c8xx_2/sym_hipd.c b/drivers/scsi/sym53c8xx_2/sym_hipd.c
--- a/drivers/scsi/sym53c8xx_2/sym_hipd.c	2005-01-02 23:10:07 -08:00
+++ b/drivers/scsi/sym53c8xx_2/sym_hipd.c	2005-01-02 23:10:07 -08:00
@@ -47,14 +47,14 @@
 /*
  *  Needed function prototypes.
  */
-static void sym_int_ma (hcb_p np);
-static void sym_int_sir (hcb_p np);
-static ccb_p sym_alloc_ccb(hcb_p np);
-static ccb_p sym_ccb_from_dsa(hcb_p np, u32 dsa);
-static void sym_alloc_lcb_tags (hcb_p np, u_char tn, u_char ln);
-static void sym_complete_error (hcb_p np, ccb_p cp);
-static void sym_complete_ok (hcb_p np, ccb_p cp);
-static int sym_compute_residual(hcb_p np, ccb_p cp);
+static void sym_int_ma (struct sym_hcb *np);
+static void sym_int_sir (struct sym_hcb *np);
+static ccb_p sym_alloc_ccb(struct sym_hcb *np);
+static ccb_p sym_ccb_from_dsa(struct sym_hcb *np, u32 dsa);
+static void sym_alloc_lcb_tags (struct sym_hcb *np, u_char tn, u_char ln);
+static void sym_complete_error (struct sym_hcb *np, ccb_p cp);
+static void sym_complete_ok (struct sym_hcb *np, ccb_p cp);
+static int sym_compute_residual(struct sym_hcb *np, ccb_p cp);
 
 /*
  *  Returns the name of this driver.
@@ -86,12 +86,12 @@
  *  Print something which allows to retrieve the controler type, 
  *  unit, target, lun concerned by a kernel message.
  */
-static void sym_print_target (hcb_p np, int target)
+static void sym_print_target (struct sym_hcb *np, int target)
 {
 	printf ("%s:%d:", sym_name(np), target);
 }
 
-static void sym_print_lun(hcb_p np, int target, int lun)
+static void sym_print_lun(struct sym_hcb *np, int target, int lun)
 {
 	printf ("%s:%d:%d:", sym_name(np), target, lun);
 }
@@ -126,7 +126,7 @@
 	printf (".\n");
 }
 
-static void sym_print_nego_msg (hcb_p np, int target, char *label, u_char *msg)
+static void sym_print_nego_msg (struct sym_hcb *np, int target, char *label, u_char *msg)
 {
 	PRINT_TARGET(np, target);
 	if (label)
@@ -184,7 +184,7 @@
  *  On the other hand, LVD devices need some delay 
  *  to settle and report actual BUS mode in STEST4.
  */
-static void sym_chip_reset (hcb_p np)
+static void sym_chip_reset (struct sym_hcb *np)
 {
 	OUTB (nc_istat, SRST);
 	UDELAY (10);
@@ -201,7 +201,7 @@
  *  So, we need to abort the current operation prior to 
  *  soft resetting the chip.
  */
-static void sym_soft_reset (hcb_p np)
+static void sym_soft_reset (struct sym_hcb *np)
 {
 	u_char istat = 0;
 	int i;
@@ -234,12 +234,12 @@
  *
  *  The interrupt handler will reinitialize the chip.
  */
-static void sym_start_reset(hcb_p np)
+static void sym_start_reset(struct sym_hcb *np)
 {
 	(void) sym_reset_scsi_bus(np, 1);
 }
  
-int sym_reset_scsi_bus(hcb_p np, int enab_int)
+int sym_reset_scsi_bus(struct sym_hcb *np, int enab_int)
 {
 	u32 term;
 	int retv = 0;
@@ -293,7 +293,7 @@
 /*
  *  Select SCSI clock frequency
  */
-static void sym_selectclock(hcb_p np, u_char scntl3)
+static void sym_selectclock(struct sym_hcb *np, u_char scntl3)
 {
 	/*
 	 *  If multiplier not present or not selected, leave here.
@@ -348,7 +348,7 @@
 /*
  *  calculate SCSI clock frequency (in KHz)
  */
-static unsigned getfreq (hcb_p np, int gen)
+static unsigned getfreq (struct sym_hcb *np, int gen)
 {
 	unsigned int ms = 0;
 	unsigned int f;
@@ -420,7 +420,7 @@
 	return f;
 }
 
-static unsigned sym_getfreq (hcb_p np)
+static unsigned sym_getfreq (struct sym_hcb *np)
 {
 	u_int f1, f2;
 	int gen = 8;
@@ -435,7 +435,7 @@
 /*
  *  Get/probe chip SCSI clock frequency
  */
-static void sym_getclock (hcb_p np, int mult)
+static void sym_getclock (struct sym_hcb *np, int mult)
 {
 	unsigned char scntl3 = np->sv_scntl3;
 	unsigned char stest1 = np->sv_stest1;
@@ -492,7 +492,7 @@
 /*
  *  Get/probe PCI clock frequency
  */
-static int sym_getpciclock (hcb_p np)
+static int sym_getpciclock (struct sym_hcb *np)
 {
 	int f = 0;
 
@@ -528,7 +528,7 @@
  *  synchronous factor period.
  */
 static int 
-sym_getsync(hcb_p np, u_char dt, u_char sfac, u_char *divp, u_char *fakp)
+sym_getsync(struct sym_hcb *np, u_char dt, u_char sfac, u_char *divp, u_char *fakp)
 {
 	u32	clk = np->clock_khz;	/* SCSI clock frequency in kHz	*/
 	int	div = np->clock_divn;	/* Number of divisors supported	*/
@@ -648,7 +648,7 @@
 /*
  *  Set initial io register bits from burst code.
  */
-static __inline void sym_init_burst(hcb_p np, u_char bc)
+static __inline void sym_init_burst(struct sym_hcb *np, u_char bc)
 {
 	np->rv_ctest4	&= ~0x80;
 	np->rv_dmode	&= ~(0x3 << 6);
@@ -668,7 +668,7 @@
 /*
  * Print out the list of targets that have some flag disabled by user.
  */
-static void sym_print_targets_flag(hcb_p np, int mask, char *msg)
+static void sym_print_targets_flag(struct sym_hcb *np, int mask, char *msg)
 {
 	int cnt;
 	int i;
@@ -696,7 +696,7 @@
  *  is not safe on paper, but it seems to work quite 
  *  well. :)
  */
-static void sym_save_initial_setting (hcb_p np)
+static void sym_save_initial_setting (struct sym_hcb *np)
 {
 	np->sv_scntl0	= INB(nc_scntl0) & 0x0a;
 	np->sv_scntl3	= INB(nc_scntl3) & 0x07;
@@ -716,44 +716,11 @@
 		np->sv_ctest5	= INB(nc_ctest5) & 0x24;
 }
 
-#ifdef CONFIG_PARISC
-static u32 parisc_setup_hcb(hcb_p np, u32 period)
-{
-	unsigned long pdc_period;
-	char scsi_mode;
-	struct hardware_path hwpath;
-
-	/* Host firmware (PDC) keeps a table for crippling SCSI capabilities.
-	 * Many newer machines export one channel of 53c896 chip
-	 * as SE, 50-pin HD.  Also used for Multi-initiator SCSI clusters
-	 * to set the SCSI Initiator ID.
-	 */
-	get_pci_node_path(np->s.device, &hwpath);
-	if (!pdc_get_initiator(&hwpath, &np->myaddr, &pdc_period,
-				&np->maxwide, &scsi_mode))
-		return period;
-
-	if (scsi_mode >= 0) {
-		/* C3000 PDC reports period/mode */
-		SYM_SETUP_SCSI_DIFF = 0;
-		switch(scsi_mode) {
-		case 0:	np->scsi_mode = SMODE_SE; break;
-		case 1:	np->scsi_mode = SMODE_HVD; break;
-		case 2:	np->scsi_mode = SMODE_LVD; break;
-		default:	break;
-		}
-	}
-
-	return (u32) pdc_period;
-}
-#else
-static inline int parisc_setup_hcb(hcb_p np, u32 period) { return period; }
-#endif
 /*
  *  Prepare io register values used by sym_start_up() 
  *  according to selected and supported features.
  */
-static int sym_prepare_setting(hcb_p np, struct sym_nvram *nvram)
+static int sym_prepare_setting(struct sym_hcb *np, struct sym_nvram *nvram)
 {
 	u_char	burst_max;
 	u32	period;
@@ -816,8 +783,6 @@
 	 */
 	period = (4 * div_10M[0] + np->clock_khz - 1) / np->clock_khz;
 
-	period = parisc_setup_hcb(np, period);
-
 	if	(period <= 250)		np->minsync = 10;
 	else if	(period <= 303)		np->minsync = 11;
 	else if	(period <= 500)		np->minsync = 12;
@@ -880,7 +845,7 @@
 	 *  In dual channel mode, contention occurs if internal cycles
 	 *  are used. Disable internal cycles.
 	 */
-	if (np->device_id == PCI_ID_LSI53C1010_33 &&
+	if (np->device_id == PCI_DEVICE_ID_LSI_53C1010_33 &&
 	    np->revision_id < 0x1)
 		np->rv_ccntl0	|=  DILS;
 
@@ -904,9 +869,9 @@
 	 *  this driver. The generic ncr driver that does not use 
 	 *  LOAD/STORE instructions does not need this work-around.
 	 */
-	if ((np->device_id == PCI_ID_SYM53C810 &&
+	if ((np->device_id == PCI_DEVICE_ID_NCR_53C810 &&
 	     np->revision_id >= 0x10 && np->revision_id <= 0x11) ||
-	    (np->device_id == PCI_ID_SYM53C860 &&
+	    (np->device_id == PCI_DEVICE_ID_NCR_53C860 &&
 	     np->revision_id <= 0x1))
 		np->features &= ~(FE_WRIE|FE_ERL|FE_ERMP);
 
@@ -1000,7 +965,7 @@
 	if ((SYM_SETUP_SCSI_LED || 
 	     (nvram->type == SYM_SYMBIOS_NVRAM ||
 	      (nvram->type == SYM_TEKRAM_NVRAM &&
-	       np->device_id == PCI_ID_SYM53C895))) &&
+	       np->device_id == PCI_DEVICE_ID_NCR_53C895))) &&
 	    !(np->features & FE_LEDC) && !(np->sv_gpcntl & 0x01))
 		np->features |= FE_LED0;
 
@@ -1091,7 +1056,7 @@
  *  Has to be called with interrupts disabled.
  */
 #ifndef SYM_CONF_IOMAPPED
-static int sym_regtest (hcb_p np)
+static int sym_regtest (struct sym_hcb *np)
 {
 	register volatile u32 data;
 	/*
@@ -1115,7 +1080,7 @@
 }
 #endif
 
-static int sym_snooptest (hcb_p np)
+static int sym_snooptest (struct sym_hcb *np)
 {
 	u32	sym_rd, sym_wr, sym_bk, host_rd, host_wr, pc, dstat;
 	int	i, err=0;
@@ -1241,7 +1206,7 @@
  *  First 24 register of the chip:
  *  	r0..rf
  */
-static void sym_log_hard_error(hcb_p np, u_short sist, u_char dstat)
+static void sym_log_hard_error(struct sym_hcb *np, u_short sist, u_char dstat)
 {
 	u32	dsp;
 	int	script_ofs;
@@ -1299,85 +1264,85 @@
 }
 
 static struct sym_pci_chip sym_pci_dev_table[] = {
- {PCI_ID_SYM53C810, 0x0f, "810", 4, 8, 4, 64,
+ {PCI_DEVICE_ID_NCR_53C810, 0x0f, "810", 4, 8, 4, 64,
  FE_ERL}
  ,
 #ifdef SYM_DEBUG_GENERIC_SUPPORT
- {PCI_ID_SYM53C810, 0xff, "810a", 4,  8, 4, 1,
+ {PCI_DEVICE_ID_NCR_53C810, 0xff, "810a", 4,  8, 4, 1,
  FE_BOF}
  ,
 #else
- {PCI_ID_SYM53C810, 0xff, "810a", 4,  8, 4, 1,
+ {PCI_DEVICE_ID_NCR_53C810, 0xff, "810a", 4,  8, 4, 1,
  FE_CACHE_SET|FE_LDSTR|FE_PFEN|FE_BOF}
  ,
 #endif
- {PCI_ID_SYM53C815, 0xff, "815", 4,  8, 4, 64,
+ {PCI_DEVICE_ID_NCR_53C815, 0xff, "815", 4,  8, 4, 64,
  FE_BOF|FE_ERL}
  ,
- {PCI_ID_SYM53C825, 0x0f, "825", 6,  8, 4, 64,
+ {PCI_DEVICE_ID_NCR_53C825, 0x0f, "825", 6,  8, 4, 64,
  FE_WIDE|FE_BOF|FE_ERL|FE_DIFF}
  ,
- {PCI_ID_SYM53C825, 0xff, "825a", 6,  8, 4, 2,
+ {PCI_DEVICE_ID_NCR_53C825, 0xff, "825a", 6,  8, 4, 2,
  FE_WIDE|FE_CACHE0_SET|FE_BOF|FE_DFS|FE_LDSTR|FE_PFEN|FE_RAM|FE_DIFF}
  ,
- {PCI_ID_SYM53C860, 0xff, "860", 4,  8, 5, 1,
+ {PCI_DEVICE_ID_NCR_53C860, 0xff, "860", 4,  8, 5, 1,
  FE_ULTRA|FE_CACHE_SET|FE_BOF|FE_LDSTR|FE_PFEN}
  ,
- {PCI_ID_SYM53C875, 0x01, "875", 6, 16, 5, 2,
+ {PCI_DEVICE_ID_NCR_53C875, 0x01, "875", 6, 16, 5, 2,
  FE_WIDE|FE_ULTRA|FE_CACHE0_SET|FE_BOF|FE_DFS|FE_LDSTR|FE_PFEN|
  FE_RAM|FE_DIFF|FE_VARCLK}
  ,
- {PCI_ID_SYM53C875, 0xff, "875", 6, 16, 5, 2,
+ {PCI_DEVICE_ID_NCR_53C875, 0xff, "875", 6, 16, 5, 2,
  FE_WIDE|FE_ULTRA|FE_DBLR|FE_CACHE0_SET|FE_BOF|FE_DFS|FE_LDSTR|FE_PFEN|
  FE_RAM|FE_DIFF|FE_VARCLK}
  ,
- {PCI_ID_SYM53C875_2, 0xff, "875", 6, 16, 5, 2,
+ {PCI_DEVICE_ID_NCR_53C875J, 0xff, "875J", 6, 16, 5, 2,
  FE_WIDE|FE_ULTRA|FE_DBLR|FE_CACHE0_SET|FE_BOF|FE_DFS|FE_LDSTR|FE_PFEN|
  FE_RAM|FE_DIFF|FE_VARCLK}
  ,
- {PCI_ID_SYM53C885, 0xff, "885", 6, 16, 5, 2,
+ {PCI_DEVICE_ID_NCR_53C885, 0xff, "885", 6, 16, 5, 2,
  FE_WIDE|FE_ULTRA|FE_DBLR|FE_CACHE0_SET|FE_BOF|FE_DFS|FE_LDSTR|FE_PFEN|
  FE_RAM|FE_DIFF|FE_VARCLK}
  ,
 #ifdef SYM_DEBUG_GENERIC_SUPPORT
- {PCI_ID_SYM53C895, 0xff, "895", 6, 31, 7, 2,
+ {PCI_DEVICE_ID_NCR_53C895, 0xff, "895", 6, 31, 7, 2,
  FE_WIDE|FE_ULTRA2|FE_QUAD|FE_CACHE_SET|FE_BOF|FE_DFS|
  FE_RAM|FE_LCKFRQ}
  ,
 #else
- {PCI_ID_SYM53C895, 0xff, "895", 6, 31, 7, 2,
+ {PCI_DEVICE_ID_NCR_53C895, 0xff, "895", 6, 31, 7, 2,
  FE_WIDE|FE_ULTRA2|FE_QUAD|FE_CACHE_SET|FE_BOF|FE_DFS|FE_LDSTR|FE_PFEN|
  FE_RAM|FE_LCKFRQ}
  ,
 #endif
- {PCI_ID_SYM53C896, 0xff, "896", 6, 31, 7, 4,
+ {PCI_DEVICE_ID_NCR_53C896, 0xff, "896", 6, 31, 7, 4,
  FE_WIDE|FE_ULTRA2|FE_QUAD|FE_CACHE_SET|FE_BOF|FE_DFS|FE_LDSTR|FE_PFEN|
  FE_RAM|FE_RAM8K|FE_64BIT|FE_DAC|FE_IO256|FE_NOPM|FE_LEDC|FE_LCKFRQ}
  ,
- {PCI_ID_SYM53C895A, 0xff, "895a", 6, 31, 7, 4,
+ {PCI_DEVICE_ID_LSI_53C895A, 0xff, "895a", 6, 31, 7, 4,
  FE_WIDE|FE_ULTRA2|FE_QUAD|FE_CACHE_SET|FE_BOF|FE_DFS|FE_LDSTR|FE_PFEN|
  FE_RAM|FE_RAM8K|FE_DAC|FE_IO256|FE_NOPM|FE_LEDC|FE_LCKFRQ}
  ,
- {PCI_ID_SYM53C875A, 0xff, "875a", 6, 31, 7, 4,
+ {PCI_DEVICE_ID_LSI_53C875A, 0xff, "875a", 6, 31, 7, 4,
  FE_WIDE|FE_ULTRA|FE_QUAD|FE_CACHE_SET|FE_BOF|FE_DFS|FE_LDSTR|FE_PFEN|
  FE_RAM|FE_DAC|FE_IO256|FE_NOPM|FE_LEDC|FE_LCKFRQ}
  ,
- {PCI_ID_LSI53C1010_33, 0x00, "1010-33", 6, 31, 7, 8,
+ {PCI_DEVICE_ID_LSI_53C1010_33, 0x00, "1010-33", 6, 31, 7, 8,
  FE_WIDE|FE_ULTRA3|FE_QUAD|FE_CACHE_SET|FE_BOF|FE_DFBC|FE_LDSTR|FE_PFEN|
  FE_RAM|FE_RAM8K|FE_64BIT|FE_DAC|FE_IO256|FE_NOPM|FE_LEDC|FE_CRC|
  FE_C10}
  ,
- {PCI_ID_LSI53C1010_33, 0xff, "1010-33", 6, 31, 7, 8,
+ {PCI_DEVICE_ID_LSI_53C1010_33, 0xff, "1010-33", 6, 31, 7, 8,
  FE_WIDE|FE_ULTRA3|FE_QUAD|FE_CACHE_SET|FE_BOF|FE_DFBC|FE_LDSTR|FE_PFEN|
  FE_RAM|FE_RAM8K|FE_64BIT|FE_DAC|FE_IO256|FE_NOPM|FE_LEDC|FE_CRC|
  FE_C10|FE_U3EN}
  ,
- {PCI_ID_LSI53C1010_66, 0xff, "1010-66", 6, 31, 7, 8,
+ {PCI_DEVICE_ID_LSI_53C1010_66, 0xff, "1010-66", 6, 31, 7, 8,
  FE_WIDE|FE_ULTRA3|FE_QUAD|FE_CACHE_SET|FE_BOF|FE_DFBC|FE_LDSTR|FE_PFEN|
  FE_RAM|FE_RAM8K|FE_64BIT|FE_DAC|FE_IO256|FE_NOPM|FE_LEDC|FE_66MHZ|FE_CRC|
  FE_C10|FE_U3EN}
  ,
- {PCI_ID_LSI53C1510D, 0xff, "1510d", 6, 31, 7, 4,
+ {PCI_DEVICE_ID_LSI_53C1510, 0xff, "1510d", 6, 31, 7, 4,
  FE_WIDE|FE_ULTRA2|FE_QUAD|FE_CACHE_SET|FE_BOF|FE_DFS|FE_LDSTR|FE_PFEN|
  FE_RAM|FE_IO256|FE_LEDC}
 };
@@ -1415,7 +1380,7 @@
  *  This is only used if the direct mapping 
  *  has been unsuccessful.
  */
-int sym_lookup_dmap(hcb_p np, u32 h, int s)
+int sym_lookup_dmap(struct sym_hcb *np, u32 h, int s)
 {
 	int i;
 
@@ -1448,7 +1413,7 @@
  *  Update IO registers scratch C..R so they will be 
  *  in sync. with queued CCB expectations.
  */
-static void sym_update_dmap_regs(hcb_p np)
+static void sym_update_dmap_regs(struct sym_hcb *np)
 {
 	int o, i;
 
@@ -1463,13 +1428,12 @@
 }
 #endif
 
+/* Enforce all the fiddly SPI rules and the chip limitations */
 static void sym_check_goals(struct scsi_device *sdev)
 {
 	struct sym_hcb *np = ((struct host_data *)sdev->host->hostdata)->ncb;
 	struct sym_trans *st = &np->target[sdev->id].tinfo.goal;
 
-	/* here we enforce all the fiddly SPI rules */
-
 	if (!scsi_device_wide(sdev))
 		st->width = 0;
 
@@ -1479,7 +1443,7 @@
 		st->offset = 0;
 		return;
 	}
-		
+
 	if (scsi_device_dt(sdev)) {
 		if (scsi_device_dt_only(sdev))
 			st->options |= PPR_OPT_DT;
@@ -1490,7 +1454,8 @@
 		st->options &= ~PPR_OPT_DT;
 	}
 
-	if (!(np->features & FE_ULTRA3))
+	/* Some targets fail to properly negotiate DT in SE mode */
+	if ((np->scsi_mode != SMODE_LVD) || !(np->features & FE_U3EN))
 		st->options &= ~PPR_OPT_DT;
 
 	if (st->options & PPR_OPT_DT) {
@@ -1520,38 +1485,31 @@
  *  negotiation and the nego_status field of the CCB.
  *  Returns the size of the message in bytes.
  */
-static int sym_prepare_nego(hcb_p np, ccb_p cp, int nego, u_char *msgptr)
+static int sym_prepare_nego(struct sym_hcb *np, ccb_p cp, u_char *msgptr)
 {
 	tcb_p tp = &np->target[cp->target];
-	int msglen = 0;
 	struct scsi_device *sdev = tp->sdev;
+	struct sym_trans *goal = &tp->tinfo.goal;
+	struct sym_trans *curr = &tp->tinfo.curr;
+	int msglen = 0;
+	int nego;
 
 	if (likely(sdev))
 		sym_check_goals(sdev);
 
 	/*
-	 *  Early C1010 chips need a work-around for DT 
-	 *  data transfer to work.
+	 * Many devices implement PPR in a buggy way, so only use it if we
+	 * really want to.
 	 */
-	if (!(np->features & FE_U3EN))
-		tp->tinfo.goal.options = 0;
-	/*
-	 *  negotiate using PPR ?
-	 */
-	if (scsi_device_dt(sdev)) {
+	if ((goal->options & PPR_OPT_MASK) || (goal->period < 0xa)) {
 		nego = NS_PPR;
+	} else if (curr->width != goal->width) {
+		nego = NS_WIDE;
+	} else if (curr->period != goal->period ||
+		   curr->offset != goal->offset) {
+		nego = NS_SYNC;
 	} else {
-		/*
-		 *  negotiate wide transfers ?
-		 */
-		if (tp->tinfo.curr.width != tp->tinfo.goal.width)
-			nego = NS_WIDE;
-		/*
-		 *  negotiate synchronous transfers?
-		 */
-		else if (tp->tinfo.curr.period != tp->tinfo.goal.period ||
-			 tp->tinfo.curr.offset != tp->tinfo.goal.offset)
-			nego = NS_SYNC;
+		nego = 0;
 	}
 
 	switch (nego) {
@@ -1559,24 +1517,24 @@
 		msgptr[msglen++] = M_EXTENDED;
 		msgptr[msglen++] = 3;
 		msgptr[msglen++] = M_X_SYNC_REQ;
-		msgptr[msglen++] = tp->tinfo.goal.period;
-		msgptr[msglen++] = tp->tinfo.goal.offset;
+		msgptr[msglen++] = goal->period;
+		msgptr[msglen++] = goal->offset;
 		break;
 	case NS_WIDE:
 		msgptr[msglen++] = M_EXTENDED;
 		msgptr[msglen++] = 2;
 		msgptr[msglen++] = M_X_WIDE_REQ;
-		msgptr[msglen++] = tp->tinfo.goal.width;
+		msgptr[msglen++] = goal->width;
 		break;
 	case NS_PPR:
 		msgptr[msglen++] = M_EXTENDED;
 		msgptr[msglen++] = 6;
 		msgptr[msglen++] = M_X_PPR_REQ;
-		msgptr[msglen++] = tp->tinfo.goal.period;
+		msgptr[msglen++] = goal->period;
 		msgptr[msglen++] = 0;
-		msgptr[msglen++] = tp->tinfo.goal.offset;
-		msgptr[msglen++] = tp->tinfo.goal.width;
-		msgptr[msglen++] = tp->tinfo.goal.options & PPR_OPT_MASK;
+		msgptr[msglen++] = goal->offset;
+		msgptr[msglen++] = goal->width;
+		msgptr[msglen++] = goal->options & PPR_OPT_MASK;
 		break;
 	};
 
@@ -1598,7 +1556,7 @@
 /*
  *  Insert a job into the start queue.
  */
-void sym_put_start_queue(hcb_p np, ccb_p cp)
+void sym_put_start_queue(struct sym_hcb *np, ccb_p cp)
 {
 	u_short	qidx;
 
@@ -1630,13 +1588,6 @@
 #endif
 
 	/*
-	 *  Optionnaly, set the IO timeout condition.
-	 */
-#ifdef	SYM_OPT_HANDLE_IO_TIMEOUT
-	sym_timeout_ccb(np, cp, sym_cam_timeout(cp->cam_ccb));
-#endif
-
-	/*
 	 *  Insert first the idle task and then our job.
 	 *  The MBs should ensure proper ordering.
 	 */
@@ -1664,7 +1615,7 @@
 /*
  *  Start next ready-to-start CCBs.
  */
-void sym_start_next_ccbs(hcb_p np, lcb_p lp, int maxn)
+void sym_start_next_ccbs(struct sym_hcb *np, lcb_p lp, int maxn)
 {
 	SYM_QUEHEAD *qp;
 	ccb_p cp;
@@ -1718,7 +1669,7 @@
  *  prevent out of order LOADs by the CPU from having 
  *  prefetched stale data prior to DMA having occurred.
  */
-static int sym_wakeup_done (hcb_p np)
+static int sym_wakeup_done (struct sym_hcb *np)
 {
 	ccb_p cp;
 	int i, n;
@@ -1752,10 +1703,64 @@
 }
 
 /*
+ *  Complete all CCBs queued to the COMP queue.
+ *
+ *  These CCBs are assumed:
+ *  - Not to be referenced either by devices or 
+ *    SCRIPTS-related queues and datas.
+ *  - To have to be completed with an error condition 
+ *    or requeued.
+ *
+ *  The device queue freeze count is incremented 
+ *  for each CCB that does not prevent this.
+ *  This function is called when all CCBs involved 
+ *  in error handling/recovery have been reaped.
+ */
+static void sym_flush_comp_queue(struct sym_hcb *np, int cam_status)
+{
+	SYM_QUEHEAD *qp;
+	ccb_p cp;
+
+	while ((qp = sym_remque_head(&np->comp_ccbq)) != 0) {
+		struct scsi_cmnd *ccb;
+		cp = sym_que_entry(qp, struct sym_ccb, link_ccbq);
+		sym_insque_tail(&cp->link_ccbq, &np->busy_ccbq);
+		/* Leave quiet CCBs waiting for resources */
+		if (cp->host_status == HS_WAIT)
+			continue;
+		ccb = cp->cam_ccb;
+		if (cam_status)
+			sym_set_cam_status(ccb, cam_status);
+#ifdef SYM_OPT_HANDLE_DEVICE_QUEUEING
+		if (sym_get_cam_status(ccb) == CAM_REQUEUE_REQ) {
+			tcb_p tp = &np->target[cp->target];
+			lcb_p lp = sym_lp(np, tp, cp->lun);
+			if (lp) {
+				sym_remque(&cp->link2_ccbq);
+				sym_insque_tail(&cp->link2_ccbq,
+				                &lp->waiting_ccbq);
+				if (cp->started) {
+					if (cp->tag != NO_TAG)
+						--lp->started_tags;
+					else
+						--lp->started_no_tag;
+				}
+			}
+			cp->started = 0;
+			continue;
+		}
+#endif
+		sym_free_ccb(np, cp);
+		sym_freeze_cam_ccb(ccb);
+		sym_xpt_done(np, ccb);
+	}
+}
+
+/*
  *  Complete all active CCBs with error.
  *  Used on CHIP/SCSI RESET.
  */
-static void sym_flush_busy_queue (hcb_p np, int cam_status)
+static void sym_flush_busy_queue (struct sym_hcb *np, int cam_status)
 {
 	/*
 	 *  Move all active CCBs to the COMP queue 
@@ -1774,7 +1779,7 @@
  *     1: SCSI BUS RESET delivered or received.
  *     2: SCSI BUS MODE changed.
  */
-void sym_start_up (hcb_p np, int reason)
+void sym_start_up (struct sym_hcb *np, int reason)
 {
  	int	i;
 	u32	phys;
@@ -1865,7 +1870,7 @@
 	/*
 	 *  For now, disable AIP generation on C1010-66.
 	 */
-	if (np->device_id == PCI_ID_LSI53C1010_66)
+	if (np->device_id == PCI_DEVICE_ID_LSI_53C1010_66)
 		OUTB (nc_aipcntl1, DISAIP);
 
 	/*
@@ -1875,7 +1880,7 @@
 	 *  that from SCRIPTS for each selection/reselection, but 
 	 *  I just don't want. :)
 	 */
-	if (np->device_id == PCI_ID_LSI53C1010_33 &&
+	if (np->device_id == PCI_DEVICE_ID_LSI_53C1010_33 &&
 	    np->revision_id < 1)
 		OUTB (nc_stest1, INB(nc_stest1) | 0x30);
 
@@ -1884,9 +1889,9 @@
 	 *  Disable overlapped arbitration for some dual function devices, 
 	 *  regardless revision id (kind of post-chip-design feature. ;-))
 	 */
-	if (np->device_id == PCI_ID_SYM53C875)
+	if (np->device_id == PCI_DEVICE_ID_NCR_53C875)
 		OUTB (nc_ctest0, (1<<5));
-	else if (np->device_id == PCI_ID_SYM53C896)
+	else if (np->device_id == PCI_DEVICE_ID_NCR_53C896)
 		np->rv_ccntl0 |= DPR;
 
 	/*
@@ -2010,7 +2015,7 @@
 /*
  *  Switch trans mode for current job and it's target.
  */
-static void sym_settrans(hcb_p np, int target, u_char opts, u_char ofs,
+static void sym_settrans(struct sym_hcb *np, int target, u_char opts, u_char ofs,
 			 u_char per, u_char wide, u_char div, u_char fak)
 {
 	SYM_QUEHEAD *qp;
@@ -2119,7 +2124,7 @@
  *  We received a WDTR.
  *  Let everything be aware of the changes.
  */
-static void sym_setwide(hcb_p np, int target, u_char wide)
+static void sym_setwide(struct sym_hcb *np, int target, u_char wide)
 {
 	tcb_p tp = &np->target[target];
 
@@ -2138,7 +2143,7 @@
  *  Let everything be aware of the changes.
  */
 static void
-sym_setsync(hcb_p np, int target,
+sym_setsync(struct sym_hcb *np, int target,
             u_char ofs, u_char per, u_char div, u_char fak)
 {
 	tcb_p tp = &np->target[target];
@@ -2164,7 +2169,7 @@
  *  Let everything be aware of the changes.
  */
 static void 
-sym_setpprot(hcb_p np, int target, u_char opts, u_char ofs,
+sym_setpprot(struct sym_hcb *np, int target, u_char opts, u_char ofs,
              u_char per, u_char wide, u_char div, u_char fak)
 {
 	tcb_p tp = &np->target[target];
@@ -2205,7 +2210,7 @@
  *  pushes a DSA into a queue, we can trust it when it 
  *  points to a CCB.
  */
-static void sym_recover_scsi_int (hcb_p np, u_char hsts)
+static void sym_recover_scsi_int (struct sym_hcb *np, u_char hsts)
 {
 	u32	dsp	= INL (nc_dsp);
 	u32	dsa	= INL (nc_dsa);
@@ -2256,7 +2261,7 @@
 /*
  *  chip exception handler for selection timeout
  */
-static void sym_int_sto (hcb_p np)
+static void sym_int_sto (struct sym_hcb *np)
 {
 	u32 dsp	= INL (nc_dsp);
 
@@ -2271,7 +2276,7 @@
 /*
  *  chip exception handler for unexpected disconnect
  */
-static void sym_int_udc (hcb_p np)
+static void sym_int_udc (struct sym_hcb *np)
 {
 	printf ("%s: unexpected disconnect\n", sym_name(np));
 	sym_recover_scsi_int(np, HS_UNEXPECTED);
@@ -2287,7 +2292,7 @@
  *  mode to eight bit asynchronous, etc...
  *  So, just reinitializing all except chip should be enough.
  */
-static void sym_int_sbmc (hcb_p np)
+static void sym_int_sbmc (struct sym_hcb *np)
 {
 	u_char scsi_mode = INB (nc_stest4) & SMODE;
 
@@ -2328,7 +2333,7 @@
  *    The chip will load the DSP with the phase mismatch 
  *    JUMP address and interrupt the host processor.
  */
-static void sym_int_par (hcb_p np, u_short sist)
+static void sym_int_par (struct sym_hcb *np, u_short sist)
 {
 	u_char	hsts	= INB (HS_PRT);
 	u32	dsp	= INL (nc_dsp);
@@ -2416,7 +2421,7 @@
  *  We have to construct a new transfer descriptor,
  *  to transfer the rest of the current block.
  */
-static void sym_int_ma (hcb_p np)
+static void sym_int_ma (struct sym_hcb *np)
 {
 	u32	dbc;
 	u32	rest;
@@ -2826,7 +2831,7 @@
  *  Use at your own decision and risk.
  */
 
-void sym_interrupt (hcb_p np)
+void sym_interrupt (struct sym_hcb *np)
 {
 	u_char	istat, istatc;
 	u_char	dstat;
@@ -2981,7 +2986,7 @@
  *  It is called with SCRIPTS not running.
  */
 static int 
-sym_dequeue_from_squeue(hcb_p np, int i, int target, int lun, int task)
+sym_dequeue_from_squeue(struct sym_hcb *np, int i, int target, int lun, int task)
 {
 	int j;
 	ccb_p cp;
@@ -3025,60 +3030,6 @@
 }
 
 /*
- *  Complete all CCBs queued to the COMP queue.
- *
- *  These CCBs are assumed:
- *  - Not to be referenced either by devices or 
- *    SCRIPTS-related queues and datas.
- *  - To have to be completed with an error condition 
- *    or requeued.
- *
- *  The device queue freeze count is incremented 
- *  for each CCB that does not prevent this.
- *  This function is called when all CCBs involved 
- *  in error handling/recovery have been reaped.
- */
-void sym_flush_comp_queue(hcb_p np, int cam_status)
-{
-	SYM_QUEHEAD *qp;
-	ccb_p cp;
-
-	while ((qp = sym_remque_head(&np->comp_ccbq)) != 0) {
-		cam_ccb_p ccb;
-		cp = sym_que_entry(qp, struct sym_ccb, link_ccbq);
-		sym_insque_tail(&cp->link_ccbq, &np->busy_ccbq);
-		/* Leave quiet CCBs waiting for resources */
-		if (cp->host_status == HS_WAIT)
-			continue;
-		ccb = cp->cam_ccb;
-		if (cam_status)
-			sym_set_cam_status(ccb, cam_status);
-#ifdef SYM_OPT_HANDLE_DEVICE_QUEUEING
-		if (sym_get_cam_status(ccb) == CAM_REQUEUE_REQ) {
-			tcb_p tp = &np->target[cp->target];
-			lcb_p lp = sym_lp(np, tp, cp->lun);
-			if (lp) {
-				sym_remque(&cp->link2_ccbq);
-				sym_insque_tail(&cp->link2_ccbq,
-				                &lp->waiting_ccbq);
-				if (cp->started) {
-					if (cp->tag != NO_TAG)
-						--lp->started_tags;
-					else
-						--lp->started_no_tag;
-				}
-			}
-			cp->started = 0;
-			continue;
-		}
-#endif
-		sym_free_ccb(np, cp);
-		sym_freeze_cam_ccb(ccb);
-		sym_xpt_done(np, ccb);
-	}
-}
-
-/*
  *  chip handler for bad SCSI status condition
  *
  *  In case of bad SCSI status, we unqueue all the tasks 
@@ -3096,14 +3047,13 @@
  *  SCRATCHA is assumed to have been loaded with STARTPOS 
  *  before the SCRIPTS called the C code.
  */
-static void sym_sir_bad_scsi_status(hcb_p np, int num, ccb_p cp)
+static void sym_sir_bad_scsi_status(struct sym_hcb *np, int num, ccb_p cp)
 {
 	tcb_p tp	= &np->target[cp->target];
 	u32		startp;
 	u_char		s_status = cp->ssss_status;
 	u_char		h_flags  = cp->host_flags;
 	int		msglen;
-	int		nego;
 	int		i;
 
 	/*
@@ -3178,16 +3128,7 @@
 		 *  cp->nego_status is filled by sym_prepare_nego().
 		 */
 		cp->nego_status = 0;
-		nego = 0;
-		if	(tp->tinfo.curr.options & PPR_OPT_MASK)
-			nego = NS_PPR;
-		else if	(tp->tinfo.curr.width != BUS_8_BIT)
-			nego = NS_WIDE;
-		else if (tp->tinfo.curr.offset != 0)
-			nego = NS_SYNC;
-		if (nego)
-			msglen +=
-			sym_prepare_nego (np,cp, nego, &cp->scsi_smsg2[msglen]);
+		msglen += sym_prepare_nego(np, cp, &cp->scsi_smsg2[msglen]);
 		/*
 		 *  Message table indirect structure.
 		 */
@@ -3213,7 +3154,7 @@
 		/*
 		 *  sense data
 		 */
-		bzero(cp->sns_bbuf, SYM_SNS_BBUF_LEN);
+		memset(cp->sns_bbuf, 0, SYM_SNS_BBUF_LEN);
 		cp->phys.sense.addr	= cpu_to_scr(vtobus(cp->sns_bbuf));
 		cp->phys.sense.size	= cpu_to_scr(SYM_SNS_BBUF_LEN);
 
@@ -3263,7 +3204,7 @@
  *  - lun=-1  means any logical UNIT otherwise a given one.
  *  - task=-1 means any task, otherwise a given one.
  */
-int sym_clear_tasks(hcb_p np, int cam_status, int target, int lun, int task)
+int sym_clear_tasks(struct sym_hcb *np, int cam_status, int target, int lun, int task)
 {
 	SYM_QUEHEAD qtmp, *qp;
 	int i = 0;
@@ -3282,7 +3223,7 @@
 	 *  the BUSY queue.
 	 */
 	while ((qp = sym_remque_head(&qtmp)) != 0) {
-		cam_ccb_p ccb;
+		struct scsi_cmnd *ccb;
 		cp = sym_que_entry(qp, struct sym_ccb, link_ccbq);
 		ccb = cp->cam_ccb;
 		if (cp->host_status != HS_DISCONNECT ||
@@ -3346,7 +3287,7 @@
  *  all the CCBs that should have been aborted by the 
  *  target according to our message.
  */
-static void sym_sir_task_recovery(hcb_p np, int num)
+static void sym_sir_task_recovery(struct sym_hcb *np, int num)
 {
 	SYM_QUEHEAD *qp;
 	ccb_p cp;
@@ -3698,7 +3639,7 @@
  *  the corresponding values of dp_sg and dp_ofs.
  */
 
-static int sym_evaluate_dp(hcb_p np, ccb_p cp, u32 scr, int *ofs)
+static int sym_evaluate_dp(struct sym_hcb *np, ccb_p cp, u32 scr, int *ofs)
 {
 	u32	dp_scr;
 	int	dp_ofs, dp_sg, dp_sgmin;
@@ -3816,7 +3757,7 @@
  *  is equivalent to a MODIFY DATA POINTER (offset=-1).
  */
 
-static void sym_modify_dp(hcb_p np, tcb_p tp, ccb_p cp, int ofs)
+static void sym_modify_dp(struct sym_hcb *np, tcb_p tp, ccb_p cp, int ofs)
 {
 	int dp_ofs	= ofs;
 	u32	dp_scr	= sym_get_script_dp (np, cp);
@@ -3915,7 +3856,7 @@
  *  a relevant information. :)
  */
 
-int sym_compute_residual(hcb_p np, ccb_p cp)
+int sym_compute_residual(struct sym_hcb *np, ccb_p cp)
 {
 	int dp_sg, dp_sgmin, resid = 0;
 	int dp_ofs = 0;
@@ -4015,7 +3956,7 @@
  *  chip handler for SYNCHRONOUS DATA TRANSFER REQUEST (SDTR) message.
  */
 static int  
-sym_sync_nego_check(hcb_p np, int req, int target)
+sym_sync_nego_check(struct sym_hcb *np, int req, int target)
 {
 	u_char	chg, ofs, per, fak, div;
 
@@ -4096,7 +4037,7 @@
 	return -1;
 }
 
-static void sym_sync_nego(hcb_p np, tcb_p tp, ccb_p cp)
+static void sym_sync_nego(struct sym_hcb *np, tcb_p tp, ccb_p cp)
 {
 	int req = 1;
 	int result;
@@ -4133,7 +4074,7 @@
  *  chip handler for PARALLEL PROTOCOL REQUEST (PPR) message.
  */
 static int 
-sym_ppr_nego_check(hcb_p np, int req, int target)
+sym_ppr_nego_check(struct sym_hcb *np, int req, int target)
 {
 	tcb_p tp = &np->target[target];
 	unsigned char fak, div;
@@ -4176,7 +4117,7 @@
 
 	if (ofs) {
 		unsigned char minsync = dt ? np->minsync_dt : np->minsync;
-		if (per < np->minsync_dt) {
+		if (per < minsync) {
 			chg = 1;
 			per = minsync;
 		}
@@ -4242,7 +4183,7 @@
 	return -1;
 }
 
-static void sym_ppr_nego(hcb_p np, tcb_p tp, ccb_p cp)
+static void sym_ppr_nego(struct sym_hcb *np, tcb_p tp, ccb_p cp)
 {
 	int req = 1;
 	int result;
@@ -4279,7 +4220,7 @@
  *  chip handler for WIDE DATA TRANSFER REQUEST (WDTR) message.
  */
 static int  
-sym_wide_nego_check(hcb_p np, int req, int target)
+sym_wide_nego_check(struct sym_hcb *np, int req, int target)
 {
 	u_char	chg, wide;
 
@@ -4344,7 +4285,7 @@
 	return -1;
 }
 
-static void sym_wide_nego(hcb_p np, tcb_p tp, ccb_p cp)
+static void sym_wide_nego(struct sym_hcb *np, tcb_p tp, ccb_p cp)
 {
 	int req = 1;
 	int result;
@@ -4413,7 +4354,7 @@
  *  So, if a PPR makes problems, we may just want to 
  *  try a legacy negotiation later.
  */
-static void sym_nego_default(hcb_p np, tcb_p tp, ccb_p cp)
+static void sym_nego_default(struct sym_hcb *np, tcb_p tp, ccb_p cp)
 {
 	switch (cp->nego_status) {
 	case NS_PPR:
@@ -4443,7 +4384,7 @@
  *  chip handler for MESSAGE REJECT received in response to 
  *  PPR, WIDE or SYNCHRONOUS negotiation.
  */
-static void sym_nego_rejected(hcb_p np, tcb_p tp, ccb_p cp)
+static void sym_nego_rejected(struct sym_hcb *np, tcb_p tp, ccb_p cp)
 {
 	sym_nego_default(np, tp, cp);
 	OUTB (HS_PRT, HS_BUSY);
@@ -4452,7 +4393,7 @@
 /*
  *  chip exception handler for programmed interrupts.
  */
-static void sym_int_sir (hcb_p np)
+static void sym_int_sir (struct sym_hcb *np)
 {
 	u_char	num	= INB (nc_dsps);
 	u32	dsa	= INL (nc_dsa);
@@ -4726,7 +4667,7 @@
 /*
  *  Acquire a control block
  */
-ccb_p sym_get_ccb (hcb_p np, u_char tn, u_char ln, u_char tag_order)
+ccb_p sym_get_ccb (struct sym_hcb *np, u_char tn, u_char ln, u_char tag_order)
 {
 	tcb_p tp = &np->target[tn];
 	lcb_p lp = sym_lp(np, tp, ln);
@@ -4875,7 +4816,7 @@
 /*
  *  Release one control block
  */
-void sym_free_ccb (hcb_p np, ccb_p cp)
+void sym_free_ccb (struct sym_hcb *np, ccb_p cp)
 {
 	tcb_p tp = &np->target[cp->target];
 	lcb_p lp = sym_lp(np, tp, cp->lun);
@@ -4960,13 +4901,6 @@
 	sym_remque(&cp->link_ccbq);
 	sym_insque_head(&cp->link_ccbq, &np->free_ccbq);
 
-#ifdef	SYM_OPT_HANDLE_IO_TIMEOUT
-	/*
-	 *  Cancel any pending timeout condition.
-	 */
-	sym_untimeout_ccb(np, cp);
-#endif
-
 #ifdef SYM_OPT_HANDLE_DEVICE_QUEUEING
 	if (lp) {
 		sym_remque(&cp->link2_ccbq);
@@ -4985,7 +4919,7 @@
 /*
  *  Allocate a CCB from memory and initialize its fixed part.
  */
-static ccb_p sym_alloc_ccb(hcb_p np)
+static ccb_p sym_alloc_ccb(struct sym_hcb *np)
 {
 	ccb_p cp = NULL;
 	int hcode;
@@ -5053,9 +4987,6 @@
 	/*
 	 *  Chain into optionnal lists.
 	 */
-#ifdef	SYM_OPT_HANDLE_IO_TIMEOUT
-	sym_insque_head(&cp->tmo_linkq, &np->tmo0_ccbq);
-#endif
 #ifdef SYM_OPT_HANDLE_DEVICE_QUEUEING
 	sym_insque_head(&cp->link2_ccbq, &np->dummy_ccbq);
 #endif
@@ -5072,7 +5003,7 @@
 /*
  *  Look up a CCB from a DSA value.
  */
-static ccb_p sym_ccb_from_dsa(hcb_p np, u32 dsa)
+static ccb_p sym_ccb_from_dsa(struct sym_hcb *np, u32 dsa)
 {
 	int hcode;
 	ccb_p cp;
@@ -5092,7 +5023,7 @@
  *  Target control block initialisation.
  *  Nothing important to do at the moment.
  */
-static void sym_init_tcb (hcb_p np, u_char tn)
+static void sym_init_tcb (struct sym_hcb *np, u_char tn)
 {
 #if 0	/*  Hmmm... this checking looks paranoid. */
 	/*
@@ -5108,7 +5039,7 @@
 /*
  *  Lun control block allocation and initialization.
  */
-lcb_p sym_alloc_lcb (hcb_p np, u_char tn, u_char ln)
+lcb_p sym_alloc_lcb (struct sym_hcb *np, u_char tn, u_char ln)
 {
 	tcb_p tp = &np->target[tn];
 	lcb_p lp = sym_lp(np, tp, ln);
@@ -5210,7 +5141,7 @@
 /*
  *  Allocate LCB resources for tagged command queuing.
  */
-static void sym_alloc_lcb_tags (hcb_p np, u_char tn, u_char ln)
+static void sym_alloc_lcb_tags (struct sym_hcb *np, u_char tn, u_char ln)
 {
 	tcb_p tp = &np->target[tn];
 	lcb_p lp = sym_lp(np, tp, ln);
@@ -5262,7 +5193,7 @@
 /*
  *  Queue a SCSI IO to the controller.
  */
-int sym_queue_scsiio(hcb_p np, cam_scsiio_p csio, ccb_p cp)
+int sym_queue_scsiio(struct sym_hcb *np, struct scsi_cmnd *csio, ccb_p cp)
 {
 	tcb_p	tp;
 	lcb_p	lp;
@@ -5273,7 +5204,7 @@
 	/*
 	 *  Keep track of the IO in our CCB.
 	 */
-	cp->cam_ccb = (cam_ccb_p) csio;
+	cp->cam_ccb = csio;
 
 	/*
 	 *  Retrieve the target descriptor.
@@ -5351,7 +5282,7 @@
 	    tp->tinfo.curr.offset  != tp->tinfo.goal.offset ||
 	    tp->tinfo.curr.options != tp->tinfo.goal.options) {
 		if (!tp->nego_cp && lp)
-			msglen += sym_prepare_nego(np, cp, 0, msgptr + msglen);
+			msglen += sym_prepare_nego(np, cp, msgptr + msglen);
 	}
 
 	/*
@@ -5401,7 +5332,7 @@
 /*
  *  Reset a SCSI target (all LUNs of this target).
  */
-int sym_reset_scsi_target(hcb_p np, int target)
+int sym_reset_scsi_target(struct sym_hcb *np, int target)
 {
 	tcb_p tp;
 
@@ -5420,7 +5351,7 @@
 /*
  *  Abort a SCSI IO.
  */
-int sym_abort_ccb(hcb_p np, ccb_p cp, int timed_out)
+int sym_abort_ccb(struct sym_hcb *np, ccb_p cp, int timed_out)
 {
 	/*
 	 *  Check that the IO is active.
@@ -5450,7 +5381,7 @@
 	return 0;
 }
 
-int sym_abort_scsiio(hcb_p np, cam_ccb_p ccb, int timed_out)
+int sym_abort_scsiio(struct sym_hcb *np, struct scsi_cmnd *ccb, int timed_out)
 {
 	ccb_p cp;
 	SYM_QUEHEAD *qp;
@@ -5480,7 +5411,7 @@
  *  SCRATCHA is assumed to have been loaded with STARTPOS 
  *  before the SCRIPTS called the C code.
  */
-void sym_complete_error (hcb_p np, ccb_p cp)
+void sym_complete_error (struct sym_hcb *np, ccb_p cp)
 {
 	tcb_p tp;
 	lcb_p lp;
@@ -5614,11 +5545,11 @@
  *  The SCRIPTS processor is running while we are 
  *  completing successful commands.
  */
-void sym_complete_ok (hcb_p np, ccb_p cp)
+void sym_complete_ok (struct sym_hcb *np, ccb_p cp)
 {
 	tcb_p tp;
 	lcb_p lp;
-	cam_ccb_p ccb;
+	struct scsi_cmnd *ccb;
 	int resid;
 
 	/*
@@ -5724,7 +5655,7 @@
 /*
  *  Soft-attach the controller.
  */
-int sym_hcb_attach(hcb_p np, struct sym_fw *fw, struct sym_nvram *nvram)
+int sym_hcb_attach(struct sym_hcb *np, struct sym_fw *fw, struct sym_nvram *nvram)
 {
 	int i;
 
@@ -5815,17 +5746,9 @@
 	sym_que_init(&np->comp_ccbq);
 
 	/*
-	 *  Initializations for optional handling 
-	 *  of IO timeouts and device queueing.
+	 *  Initialization for optional handling 
+	 *  of device queueing.
 	 */
-#ifdef	SYM_OPT_HANDLE_IO_TIMEOUT
-	sym_que_init(&np->tmo0_ccbq);
-	np->tmo_ccbq =
-		sym_calloc(2*SYM_CONF_TIMEOUT_ORDER_MAX*sizeof(SYM_QUEHEAD),
-			   "TMO_CCBQ");
-	for (i = 0 ; i < 2*SYM_CONF_TIMEOUT_ORDER_MAX ; i++)
-		sym_que_init(&np->tmo_ccbq[i]);
-#endif
 #ifdef SYM_OPT_HANDLE_DEVICE_QUEUEING
 	sym_que_init(&np->dummy_ccbq);
 #endif
@@ -5957,7 +5880,7 @@
 /*
  *  Free everything that has been allocated for this device.
  */
-void sym_hcb_free(hcb_p np)
+void sym_hcb_free(struct sym_hcb *np)
 {
 	SYM_QUEHEAD *qp;
 	ccb_p cp;
@@ -5971,12 +5894,6 @@
 		sym_mfree_dma(np->scriptb0, np->scriptb_sz, "SCRIPTB0");
 	if (np->scripta0)
 		sym_mfree_dma(np->scripta0, np->scripta_sz, "SCRIPTA0");
-#ifdef	SYM_OPT_HANDLE_IO_TIMEOUT
-	if (np->tmo_ccbq)
-		sym_mfree(np->tmo_ccbq,
-			  2*SYM_CONF_TIMEOUT_ORDER_MAX*sizeof(SYM_QUEHEAD),
-			  "TMO_CCBQ");
-#endif
 	if (np->squeue)
 		sym_mfree_dma(np->squeue, sizeof(u32)*(MAX_QUEUE*2), "SQUEUE");
 	if (np->dqueue)
diff -Nru a/drivers/scsi/sym53c8xx_2/sym_hipd.h b/drivers/scsi/sym53c8xx_2/sym_hipd.h
--- a/drivers/scsi/sym53c8xx_2/sym_hipd.h	2005-01-02 23:10:07 -08:00
+++ b/drivers/scsi/sym53c8xx_2/sym_hipd.h	2005-01-02 23:10:07 -08:00
@@ -749,7 +749,7 @@
 	/*
 	 *  Pointer to CAM ccb and related stuff.
 	 */
-	cam_ccb_p cam_ccb;	/* CAM scsiio ccb		*/
+	struct scsi_cmnd *cam_ccb;	/* CAM scsiio ccb		*/
 	u8	cdb_buf[16];	/* Copy of CDB			*/
 	u8	*sns_bbuf;	/* Bounce buffer for sense data	*/
 #ifndef	SYM_SNS_BBUF_LEN
@@ -796,10 +796,6 @@
 	/*
 	 *  Other fields.
 	 */
-#ifdef	SYM_OPT_HANDLE_IO_TIMEOUT
-	SYM_QUEHEAD tmo_linkq;	/* Optional timeout handling	*/
-	u_int	tmo_clock;	/* (link and dealine value)	*/
-#endif
 	u32	ccb_ba;		/* BUS address of this CCB	*/
 	u_short	tag;		/* Tag for this transfer	*/
 				/*  NO_TAG means no tag		*/
@@ -946,8 +942,8 @@
 	struct sym_fwa_ba fwa_bas;	/* Useful SCRIPTA bus addresses	*/
 	struct sym_fwb_ba fwb_bas;	/* Useful SCRIPTB bus addresses	*/
 	struct sym_fwz_ba fwz_bas;	/* Useful SCRIPTZ bus addresses	*/
-	void		(*fw_setup)(hcb_p np, struct sym_fw *fw);
-	void		(*fw_patch)(hcb_p np);
+	void		(*fw_setup)(struct sym_hcb *np, struct sym_fw *fw);
+	void		(*fw_patch)(struct sym_hcb *np);
 	char		*fw_name;
 
 	/*
@@ -1025,15 +1021,6 @@
 #ifdef SYM_OPT_HANDLE_DEVICE_QUEUEING
 	SYM_QUEHEAD	dummy_ccbq;
 #endif
-	/*
-	 *  Optional handling of IO timeouts.
-	 */
-#ifdef	SYM_OPT_HANDLE_IO_TIMEOUT
-	SYM_QUEHEAD tmo0_ccbq;
-	SYM_QUEHEAD *tmo_ccbq;	/* [2*SYM_TIMEOUT_ORDER_MAX] */
-	u_int	tmo_clock;
-	u_int	tmo_actq;
-#endif
 
 	/*
 	 *  IMMEDIATE ARBITRATION (IARB) control.
@@ -1082,54 +1069,39 @@
  *  FIRMWARES (sym_fw.c)
  */
 struct sym_fw * sym_find_firmware(struct sym_pci_chip *chip);
-void sym_fw_bind_script (hcb_p np, u32 *start, int len);
+void sym_fw_bind_script (struct sym_hcb *np, u32 *start, int len);
 
 /*
  *  Driver methods called from O/S specific code.
  */
 char *sym_driver_name(void);
 void sym_print_xerr(ccb_p cp, int x_status);
-int sym_reset_scsi_bus(hcb_p np, int enab_int);
+int sym_reset_scsi_bus(struct sym_hcb *np, int enab_int);
 struct sym_pci_chip *
 sym_lookup_pci_chip_table (u_short device_id, u_char revision);
-void sym_put_start_queue(hcb_p np, ccb_p cp);
+void sym_put_start_queue(struct sym_hcb *np, ccb_p cp);
 #ifdef SYM_OPT_HANDLE_DEVICE_QUEUEING
-void sym_start_next_ccbs(hcb_p np, lcb_p lp, int maxn);
+void sym_start_next_ccbs(struct sym_hcb *np, lcb_p lp, int maxn);
 #endif
-void sym_start_up (hcb_p np, int reason);
-void sym_interrupt (hcb_p np);
-void sym_flush_comp_queue(hcb_p np, int cam_status);
-int sym_clear_tasks(hcb_p np, int cam_status, int target, int lun, int task);
-ccb_p sym_get_ccb (hcb_p np, u_char tn, u_char ln, u_char tag_order);
-void sym_free_ccb (hcb_p np, ccb_p cp);
-lcb_p sym_alloc_lcb (hcb_p np, u_char tn, u_char ln);
-int sym_queue_scsiio(hcb_p np, cam_scsiio_p csio, ccb_p cp);
-int sym_abort_scsiio(hcb_p np, cam_ccb_p ccb, int timed_out);
-int sym_abort_ccb(hcb_p np, ccb_p cp, int timed_out);
-int sym_reset_scsi_target(hcb_p np, int target);
-void sym_hcb_free(hcb_p np);
-int sym_hcb_attach(hcb_p np, struct sym_fw *fw, struct sym_nvram *nvram);
-
-/*
- *  Optionnaly, the driver may handle IO timeouts.
- */
-#ifdef	SYM_OPT_HANDLE_IO_TIMEOUT
-int sym_abort_ccb(hcb_p np, ccb_p cp, int timed_out);
-void sym_timeout_ccb(hcb_p np, ccb_p cp, u_int ticks);
-static void __inline sym_untimeout_ccb(hcb_p np, ccb_p cp)
-{
-	sym_remque(&cp->tmo_linkq);
-	sym_insque_head(&cp->tmo_linkq, &np->tmo0_ccbq);
-}
-void sym_clock(hcb_p np);
-#endif	/* SYM_OPT_HANDLE_IO_TIMEOUT */
+void sym_start_up (struct sym_hcb *np, int reason);
+void sym_interrupt (struct sym_hcb *np);
+int sym_clear_tasks(struct sym_hcb *np, int cam_status, int target, int lun, int task);
+ccb_p sym_get_ccb (struct sym_hcb *np, u_char tn, u_char ln, u_char tag_order);
+void sym_free_ccb (struct sym_hcb *np, ccb_p cp);
+lcb_p sym_alloc_lcb (struct sym_hcb *np, u_char tn, u_char ln);
+int sym_queue_scsiio(struct sym_hcb *np, struct scsi_cmnd *csio, ccb_p cp);
+int sym_abort_scsiio(struct sym_hcb *np, struct scsi_cmnd *ccb, int timed_out);
+int sym_abort_ccb(struct sym_hcb *np, ccb_p cp, int timed_out);
+int sym_reset_scsi_target(struct sym_hcb *np, int target);
+void sym_hcb_free(struct sym_hcb *np);
+int sym_hcb_attach(struct sym_hcb *np, struct sym_fw *fw, struct sym_nvram *nvram);
 
 /*
  *  Optionnaly, the driver may provide a function
  *  to announce transfer rate changes.
  */
 #ifdef	SYM_OPT_ANNOUNCE_TRANSFER_RATE
-void sym_announce_transfer_rate(hcb_p np, int target);
+void sym_announce_transfer_rate(struct sym_hcb *np, int target);
 #endif
 
 /*
@@ -1153,9 +1125,9 @@
 	(data)->size = cpu_to_scr((((badd) >> 8) & 0xff000000) + len);	\
 } while (0)
 #elif SYM_CONF_DMA_ADDRESSING_MODE == 2
-int sym_lookup_dmap(hcb_p np, u32 h, int s);
+int sym_lookup_dmap(struct sym_hcb *np, u32 h, int s);
 static __inline void 
-sym_build_sge(hcb_p np, struct sym_tblmove *data, u64 badd, int len)
+sym_build_sge(struct sym_hcb *np, struct sym_tblmove *data, u64 badd, int len)
 {
 	u32 h = (badd>>32);
 	int s = (h&SYM_DMAP_MASK);
diff -Nru a/drivers/scsi/sym53c8xx_2/sym_malloc.c b/drivers/scsi/sym53c8xx_2/sym_malloc.c
--- a/drivers/scsi/sym53c8xx_2/sym_malloc.c	2005-01-02 23:10:07 -08:00
+++ b/drivers/scsi/sym53c8xx_2/sym_malloc.c	2005-01-02 23:10:07 -08:00
@@ -170,7 +170,7 @@
 	}
 
 	if (p)
-		bzero(p, size);
+		memset(p, 0, size);
 	else if (uflags & SYM_MEM_WARN)
 		printf ("__sym_calloc2: failed to allocate %s[%d]\n", name, size);
 	return p;
diff -Nru a/drivers/scsi/sym53c8xx_2/sym_misc.c b/drivers/scsi/sym53c8xx_2/sym_misc.c
--- a/drivers/scsi/sym53c8xx_2/sym_misc.c	2005-01-02 23:10:07 -08:00
+++ b/drivers/scsi/sym53c8xx_2/sym_misc.c	2005-01-02 23:10:07 -08:00
@@ -37,109 +37,13 @@
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
 
-#ifdef __FreeBSD__
-#include <dev/sym/sym_glue.h>
-#else
 #include "sym_glue.h"
-#endif
-
-#ifdef	SYM_OPT_HANDLE_IO_TIMEOUT
-/*
- *  Optional CCB timeout handling.
- *
- *  This code is useful for O/Ses that allow or expect 
- *  SIMs (low-level drivers) to handle SCSI IO timeouts.
- *  It uses a power-of-two based algorithm of my own:) 
- *  that avoids scanning of lists, provided that:
- *
- *  - The IO does complete in less than half the associated
- *    timeout value.
- *  - The greatest delay between the queuing of the IO and 
- *    its completion is less than 
- *          (1<<(SYM_CONF_TIMEOUT_ORDER_MAX-1))/2 ticks.
- *
- *  For example, if tick is 1 second and the max order is 8,
- *  any IO that is completed within less than 64 seconds will 
- *  just be put into some list at queuing and be removed 
- *  at completion without any additionnal overhead.
- */
-
-/*
- *  Set a timeout condition on a CCB.
- */ 
-void sym_timeout_ccb(hcb_p np, ccb_p cp, u_int ticks)
-{
-	sym_remque(&cp->tmo_linkq);
-	cp->tmo_clock = np->tmo_clock + ticks;
-	if (!ticks) {
-		sym_insque_head(&cp->tmo_linkq, &np->tmo0_ccbq);
-	}
-	else {
-		int i = SYM_CONF_TIMEOUT_ORDER_MAX - 1;
-		while (i > 0) {
-			if (ticks >= (1<<(i+1)))
-				break;
-			--i;
-		}
-		if (!(np->tmo_actq & (1<<i)))
-			i += SYM_CONF_TIMEOUT_ORDER_MAX;
-		sym_insque_head(&cp->tmo_linkq, &np->tmo_ccbq[i]);
-	}
-}
-
-/*
- *  Walk a list of CCB and handle timeout conditions.
- *  Should never be called in normal situations.
- */
-static void sym_walk_ccb_tmo_list(hcb_p np, SYM_QUEHEAD *tmoq)
-{
-	SYM_QUEHEAD qtmp, *qp;
-	ccb_p cp;
-
-	sym_que_move(tmoq, &qtmp);
-	while ((qp = sym_remque_head(&qtmp)) != 0) {
-		sym_insque_head(qp, &np->tmo0_ccbq);
-		cp = sym_que_entry(qp, struct sym_ccb, tmo_linkq);
-		if (cp->tmo_clock     != np->tmo_clock &&
-		    cp->tmo_clock + 1 != np->tmo_clock)
-			sym_timeout_ccb(np, cp, cp->tmo_clock - np->tmo_clock);
-		else
-			sym_abort_ccb(np, cp, 1);
-	}
-}
-
-/*
- * Our clock handler called from the O/S specific side.
- */
-void sym_clock(hcb_p np)
-{
-	int i, j;
-	u_int tmp;
-
-	tmp = np->tmo_clock;
-	tmp ^= (++np->tmo_clock);
-
-	for (i = 0; i < SYM_CONF_TIMEOUT_ORDER_MAX; i++, tmp >>= 1) {
-		if (!(tmp & 1))
-			continue;
-		j = i;
-		if (np->tmo_actq & (1<<i))
-			j += SYM_CONF_TIMEOUT_ORDER_MAX;
-
-		if (!sym_que_empty(&np->tmo_ccbq[j])) {
-			sym_walk_ccb_tmo_list(np, &np->tmo_ccbq[j]);
-		}
-		np->tmo_actq ^= (1<<i);
-	}
-}
-#endif	/* SYM_OPT_HANDLE_IO_TIMEOUT */
-
 
 #ifdef	SYM_OPT_ANNOUNCE_TRANSFER_RATE
 /*
  *  Announce transfer rate if anything changed since last announcement.
  */
-void sym_announce_transfer_rate(hcb_p np, int target)
+void sym_announce_transfer_rate(struct sym_hcb *np, int target)
 {
 	tcb_p tp = &np->target[target];
 
diff -Nru a/drivers/scsi/sym53c8xx_2/sym_nvram.c b/drivers/scsi/sym53c8xx_2/sym_nvram.c
--- a/drivers/scsi/sym53c8xx_2/sym_nvram.c	2005-01-02 23:10:07 -08:00
+++ b/drivers/scsi/sym53c8xx_2/sym_nvram.c	2005-01-02 23:10:07 -08:00
@@ -68,6 +68,21 @@
 	case SYM_TEKRAM_NVRAM:
 		np->myaddr = nvram->data.Tekram.host_id & 0x0f;
 		break;
+#ifdef CONFIG_PARISC
+	case SYM_PARISC_PDC:
+		if (nvram->data.parisc.host_id != -1)
+			np->myaddr = nvram->data.parisc.host_id;
+		if (nvram->data.parisc.factor != -1)
+			np->minsync = nvram->data.parisc.factor;
+		if (nvram->data.parisc.width != -1)
+			np->maxwide = nvram->data.parisc.width;
+		switch (nvram->data.parisc.mode) {
+			case 0: np->scsi_mode = SMODE_SE; break;
+			case 1: np->scsi_mode = SMODE_HVD; break;
+			case 2: np->scsi_mode = SMODE_LVD; break;
+			default: break;
+		}
+#endif
 	default:
 		break;
 	}
@@ -702,6 +717,28 @@
 	return 0;
 }
 
+#ifdef CONFIG_PARISC
+/*
+ * Host firmware (PDC) keeps a table for altering SCSI capabilities.
+ * Many newer machines export one channel of 53c896 chip as SE, 50-pin HD.
+ * Also used for Multi-initiator SCSI clusters to set the SCSI Initiator ID.
+ */
+static int sym_read_parisc_pdc(struct sym_device *np, struct pdc_initiator *pdc)
+{
+	struct hardware_path hwpath;
+	get_pci_node_path(np->pdev, &hwpath);
+	if (!pdc_get_initiator(&hwpath, pdc))
+		return 0;
+
+	return SYM_PARISC_PDC;
+}
+#else
+static int sym_read_parisc_pdc(struct sym_device *np, struct pdc_initiator *x)
+{
+	return 0;
+}
+#endif
+
 /*
  *  Try reading Symbios or Tekram NVRAM
  */
@@ -714,7 +751,7 @@
 		nvp->type = SYM_TEKRAM_NVRAM;
 		sym_display_Tekram_nvram(np, &nvp->data.Tekram);
 	} else {
-		nvp->type = 0;
+		nvp->type = sym_read_parisc_pdc(np, &nvp->data.parisc);
 	}
 	return nvp->type;
 }
diff -Nru a/drivers/scsi/sym53c8xx_2/sym_nvram.h b/drivers/scsi/sym53c8xx_2/sym_nvram.h
--- a/drivers/scsi/sym53c8xx_2/sym_nvram.h	2005-01-02 23:10:07 -08:00
+++ b/drivers/scsi/sym53c8xx_2/sym_nvram.h	2005-01-02 23:10:07 -08:00
@@ -171,6 +171,10 @@
 typedef struct Tekram_nvram	Tekram_nvram;
 typedef struct Tekram_target	Tekram_target;
 
+#ifndef CONFIG_PARISC
+struct pdc_initiator { int dummy; };
+#endif
+
 /*
  *  Union of supported NVRAM formats.
  */
@@ -178,10 +182,12 @@
 	int type;
 #define	SYM_SYMBIOS_NVRAM	(1)
 #define	SYM_TEKRAM_NVRAM	(2)
+#define SYM_PARISC_PDC		(3)
 #if SYM_CONF_NVRAM_SUPPORT
 	union {
 		Symbios_nvram Symbios;
 		Tekram_nvram Tekram;
+		struct pdc_initiator parisc;
 	} data;
 #endif
 };
diff -Nru a/drivers/scsi/sym53c8xx_comm.h b/drivers/scsi/sym53c8xx_comm.h
--- a/drivers/scsi/sym53c8xx_comm.h	2005-01-02 23:10:07 -08:00
+++ b/drivers/scsi/sym53c8xx_comm.h	2005-01-02 23:10:07 -08:00
@@ -505,8 +505,6 @@
 #define unmap_scsi_data(np, cmd)	__unmap_scsi_data(np->dev, cmd)
 #define map_scsi_single_data(np, cmd)	__map_scsi_single_data(np->dev, cmd)
 #define map_scsi_sg_data(np, cmd)	__map_scsi_sg_data(np->dev, cmd)
-#define sync_scsi_data_for_cpu(np, cmd)	__sync_scsi_data_for_cpu(np->dev, cmd)
-#define sync_scsi_data_for_device(np, cmd) __sync_scsi_data_for_device(np->dev, cmd)
 
 /*==========================================================
 **
diff -Nru a/drivers/scsi/zalon.c b/drivers/scsi/zalon.c
--- a/drivers/scsi/zalon.c	2005-01-02 23:10:07 -08:00
+++ b/drivers/scsi/zalon.c	2005-01-02 23:10:07 -08:00
@@ -87,7 +87,7 @@
 {
 	struct gsc_irq gsc_irq;
 	u32 zalon_vers;
-	int irq, error = -ENODEV;
+	int error = -ENODEV;
 	unsigned long zalon = dev->hpa;
 	unsigned long io_port = zalon + GSC_SCSI_ZALON_OFFSET;
 	static int unit = 0;
@@ -107,10 +107,10 @@
 	/* Setup the interrupts first.
 	** Later on request_irq() will register the handler.
 	*/
-	irq = gsc_alloc_irq(&gsc_irq);
+	dev->irq = gsc_alloc_irq(&gsc_irq);
 
 	printk("%s: Zalon vers field is 0x%x, IRQ %d\n", __FUNCTION__,
-		zalon_vers, irq);
+		zalon_vers, dev->irq);
 
 	__raw_writel(gsc_irq.txn_addr | gsc_irq.txn_data, dev->hpa + IO_MODULE_EIM);
 
@@ -130,16 +130,16 @@
 	device.dev		= &dev->dev;
 	device.slot.base	= (u_long)io_port;
 	device.slot.base_c	= (u_long)io_port;
-	device.slot.irq		= irq;
+	device.slot.irq		= dev->irq;
 	device.differential	= 2;
 
 	host = ncr_attach(&zalon7xx_template, unit, &device);
 	if (!host)
 		goto fail;
 
-	if (request_irq(irq, ncr53c8xx_intr, SA_SHIRQ, dev->dev.bus_id, host)) {
+	if (request_irq(dev->irq, ncr53c8xx_intr, SA_SHIRQ, "zalon", host)) {
 		printk(KERN_ERR "%s: irq problem with %d, detaching\n ",
-			dev->dev.bus_id, irq);
+			dev->dev.bus_id, dev->irq);
 		goto fail;
 	}
 
@@ -155,7 +155,7 @@
 	return 0;
 
  fail_free_irq:
-	free_irq(irq, host);
+	free_irq(dev->irq, host);
  fail:
 	ncr53c8xx_release(host);
 	return error;
@@ -171,18 +171,16 @@
 static int __exit zalon_remove(struct parisc_device *dev)
 {
 	struct Scsi_Host *host = dev_get_drvdata(&dev->dev);
-	int irq = host->irq;
 
 	scsi_remove_host(host);
 	ncr53c8xx_release(host);
-	free_irq(irq, host);
+	free_irq(dev->irq, host);
 
 	return 0;
 }
-	
 
 static struct parisc_driver zalon_driver = {
-	.name =		"GSC SCSI (Zalon)",
+	.name =		"zalon",
 	.id_table =	zalon_tbl,
 	.probe =	zalon_probe,
 	.remove =	__devexit_p(zalon_remove),
@@ -201,6 +199,7 @@
 static void __exit zalon7xx_exit(void)
 {
 	unregister_parisc_driver(&zalon_driver);
+	ncr53c8xx_exit();
 }
 
 module_init(zalon7xx_init);