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 # # 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 # Signed-off-by: James Bottomley # # 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 # # important error handling improvements that I've made as the result of # problem reports. # # signed-off-by: Willem Riede # Signed-off-by: James Bottomley # # 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 # Signed-off-by: James Bottomley # # 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 # Signed-off-by: James Bottomley # # 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 # Signed-off-by: James Bottomley # # 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 # Signed-off-by: James Bottomley # # 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 # Signed-off-by: James Bottomley # # 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 # # 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 # Signed-off-by: James Bottomley # # 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 # # 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 # Signed-off-by: James Bottomley # # 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 # Signed-off-by: James Bottomley # # 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 #include -#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 #include #include +#include #include #include #include @@ -46,6 +47,7 @@ #include #include #include +#include #include #include #include @@ -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 @@ -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 #include #include +#include #include #include @@ -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 #include -#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 -#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<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<tmo_ccbq[j])) { - sym_walk_ccb_tmo_list(np, &np->tmo_ccbq[j]); - } - np->tmo_actq ^= (1<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);