--- linux-2.4.18-orig/drivers/scsi/scsi.h Wed Oct 2 15:00:40 2002 +++ linux-2.4.18/drivers/scsi/scsi.h Wed Oct 2 15:01:14 2002 @@ -857,6 +857,14 @@ remove_wait_queue(QUEUE, &wait);\ current->state = TASK_RUNNING; \ }; } +/* old style reset request from external source (private to sg.c and + * scsi_error.c, supplied by scsi_obsolete.c) + * */ +#define SCSI_TRY_RESET_DEVICE 1 +#define SCSI_TRY_RESET_BUS 2 +#define SCSI_TRY_RESET_HOST 3 + +extern int scsi_reset_provider(Scsi_Device *, int); #endif --- linux-2.4.18-orig/drivers/scsi/scsi_error.c Wed Oct 2 15:00:40 2002 +++ linux-2.4.18/drivers/scsi/scsi_error.c Wed Oct 2 15:01:14 2002 @@ -2001,6 +2001,45 @@ up(host->eh_notify); } + +/* + * Function: scsi_new_reset + * + * Purpose: Send requested reset to a bus or device at any phase. + * + * Arguments: SCpnt - command ptr to send reset with (usually a dummy) + * flag - reset type (see scsi.h) + * + * Returns: SUCCESS/FAILURE. + * + * Notes: This is used by the SCSI Generic driver to provide + * Bus/Device reset capability. + */ +int +scsi_new_reset(Scsi_Cmnd *SCpnt, int flag) +{ + int rtn; + + switch(flag) { + case SCSI_TRY_RESET_DEVICE: + rtn = scsi_try_bus_device_reset(SCpnt, 0); + if(rtn == SUCCESS) + break; + /* fall through */ + case SCSI_TRY_RESET_BUS: + rtn = scsi_try_bus_reset(SCpnt); + if(rtn == SUCCESS) + break; + /* fall through */ + case SCSI_TRY_RESET_HOST: + rtn = scsi_try_host_reset(SCpnt); + break; + default: + rtn = FAILED; + } + return rtn; +} + /* * Overrides for Emacs so that we follow Linus's tabbing style. * Emacs will notice this stuff at the end of the file and automatically --- linux-2.4.18-orig/drivers/scsi/scsi_obsolete.c Thu Jul 5 14:28:17 2001 +++ linux-2.4.18/drivers/scsi/scsi_obsolete.c Wed Oct 2 15:01:14 2002 @@ -1098,6 +1098,103 @@ return rtn; } +extern int scsi_new_reset(Scsi_Cmnd *SCpnt, int flag); /* see scsi_error.c */ + +/* Dummy done routine. We don't want the bogus command used for the + * bus/device reset to find its way into the mid-layer so we intercept + * it here */ +static void +scsi_reset_provider_done_command(Scsi_Cmnd *SCpnt) { + /* Empty function. Some low level drivers will call scsi_done + * (and end up here), others won't bother */ +} + + +/* + * Function: scsi_reset_provider + * + * Purpose: Send requested reset to a bus or device at any phase. + * + * Arguments: device - device to send reset to + * flag - reset type (see scsi.h) + * + * Returns: SUCCESS/FAILURE. + * + * Notes: This is used by the SCSI Generic driver to provide + * Bus/Device reset capability. + */ +int +scsi_reset_provider(Scsi_Device *dev, int flag) +{ + int rtn; + Scsi_Cmnd SC; + Scsi_Cmnd *SCpnt = ≻ + + memset(&SCpnt->eh_timeout, 0, sizeof(SCpnt->eh_timeout)); + SCpnt->host = dev->host; + SCpnt->device = dev; + SCpnt->target = dev->id; + SCpnt->lun = dev->lun; + SCpnt->channel = dev->channel; + SCpnt->request.rq_status = RQ_SCSI_BUSY; + // SCpnt->request.sem = NULL; + SCpnt->use_sg = 0; + SCpnt->old_use_sg = 0; + SCpnt->old_cmd_len = 0; + SCpnt->underflow = 0; + SCpnt->transfersize = 0; + SCpnt->resid = 0; + SCpnt->serial_number = 0; + SCpnt->serial_number_at_timeout = 0; + SCpnt->host_scribble = NULL; + SCpnt->next = NULL; + SCpnt->state = SCSI_STATE_INITIALIZING; + SCpnt->owner = SCSI_OWNER_MIDLEVEL; + + + memset(&SCpnt->cmnd, '\0', sizeof(SCpnt->cmnd)); + + SCpnt->scsi_done = scsi_reset_provider_done_command; + SCpnt->done = NULL; + SCpnt->reset_chain = NULL; + + SCpnt->buffer = NULL; + SCpnt->bufflen = 0; + SCpnt->request_buffer = NULL; + SCpnt->request_bufflen = 0; + + SCpnt->internal_timeout = NORMAL_TIMEOUT; + SCpnt->abort_reason = DID_ABORT; + + SCpnt->cmd_len = 0; + + SCpnt->sc_data_direction = SCSI_DATA_UNKNOWN; + SCpnt->sc_request = NULL; + SCpnt->sc_magic = SCSI_CMND_MAGIC; + + /* sometimes the command can get back into the timer chain, so + * use the pid as an identifier */ + SCpnt->pid = 0; + + +#ifdef OLD + if(dev->host->hostt->use_new_eh_code) { + rtn = scsi_new_reset(SCpnt, flag); + } else { + unsigned long flags; + spin_lock_irqsave(&io_request_lock, flags); + rtn = scsi_old_reset(SCpnt, flag); + spin_unlock_irqrestore(&io_request_lock, flags); + } +#else + rtn = scsi_new_reset(SCpnt, flag); +#endif + + scsi_delete_timer(SCpnt); + + return rtn; +} + /* * Overrides for Emacs so that we follow Linus's tabbing style. --- linux-2.4.18-orig/drivers/scsi/scsi_syms.c Mon Jul 2 18:27:56 2001 +++ linux-2.4.18/drivers/scsi/scsi_syms.c Wed Oct 2 15:01:14 2002 @@ -98,3 +98,4 @@ extern int scsi_delete_timer(Scsi_Cmnd *); EXPORT_SYMBOL(scsi_add_timer); EXPORT_SYMBOL(scsi_delete_timer); +EXPORT_SYMBOL(scsi_reset_provider);