From 613d15646d479701c95b1b33b8b005c675b08ee0 Mon Sep 17 00:00:00 2001 From: Matthew Dharm Date: Mon, 1 Sep 2003 03:37:10 -0700 Subject: [PATCH] [PATCH] sr.c should issue TEST_UNIT_READY The linux/drivers/scsi/sr.c code will issue a MODE_SENSE[_10] command to a device as the first command sent to the device. If the device has just come out of reset, it will likely respond with a UNIT_ATTENTION / NOT_READY status, which causes the MODE_SENSE to fail. In fact, the device may have several UNIT_ATTENTION conditions queued up (power-up reset, media change, etc.) This results in the mode page 0x2a data not being properly read and interpreted. As an end-effect, things like packet-writing don't work (because the writeable bit is not set). The solution to this is to issue one or more TEST_UNIT_READY commands to the device to clear any pending UNIT_ATTENTION conditions. This is the technique used by sd.c -- in fact, this code was lifted directly from sd.c At some point in the future, abstraction of this initial TEST_UNIT_READY code between all high-level SCSI drivers may be apropriate. For now, this patch makes sr.c issue TEST_UNIT_READY to clear the UNIT_ATTENTION, thus allowing the mode page 0x2a code to work properly. Given the approaching 2.6.0-final release, I urge that this patch be accepted. --- drivers/scsi/sr.c | 41 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/drivers/scsi/sr.c b/drivers/scsi/sr.c index f648b265fa268..bbef9a48030f8 100644 --- a/drivers/scsi/sr.c +++ b/drivers/scsi/sr.c @@ -695,6 +695,10 @@ static void get_capabilities(struct scsi_cd *cd) unsigned char *buffer; int rc, n; struct scsi_mode_data data; + struct scsi_request *SRpnt; + unsigned char cmd[MAX_COMMAND_SIZE]; + unsigned int the_result; + int retries; static char *loadmech[] = { @@ -708,11 +712,46 @@ static void get_capabilities(struct scsi_cd *cd) "" }; + /* allocate a request for the TEST_UNIT_READY */ + SRpnt = scsi_allocate_request(cd->device); + if (!SRpnt) { + printk(KERN_WARNING "(get_capabilities:) Request allocation " + "failure.\n"); + return; + } + + /* allocate transfer buffer */ buffer = kmalloc(512, GFP_KERNEL | GFP_DMA); if (!buffer) { printk(KERN_ERR "sr: out of memory.\n"); + scsi_release_request(SRpnt); return; } + + /* issue TEST_UNIT_READY until the initial startup UNIT_ATTENTION + * conditions are gone, or a timeout happens + */ + retries = 0; + do { + memset((void *)cmd, 0, MAX_COMMAND_SIZE); + cmd[0] = TEST_UNIT_READY; + + SRpnt->sr_cmd_len = 0; + SRpnt->sr_sense_buffer[0] = 0; + SRpnt->sr_sense_buffer[2] = 0; + SRpnt->sr_data_direction = DMA_NONE; + + scsi_wait_req (SRpnt, (void *) cmd, buffer, + 0, SR_TIMEOUT, MAX_RETRIES); + + the_result = SRpnt->sr_result; + retries++; + } while (retries < 5 && + (!scsi_status_is_good(the_result) || + ((driver_byte(the_result) & DRIVER_SENSE) && + SRpnt->sr_sense_buffer[2] == UNIT_ATTENTION))); + + /* ask for mode page 0x2a */ rc = scsi_mode_sense(cd->device, 0, 0x2a, buffer, 128, SR_TIMEOUT, 3, &data); @@ -722,6 +761,7 @@ static void get_capabilities(struct scsi_cd *cd) cd->cdi.mask |= (CDC_CD_R | CDC_CD_RW | CDC_DVD_R | CDC_DVD | CDC_DVD_RAM | CDC_SELECT_DISC | CDC_SELECT_SPEED); + scsi_release_request(SRpnt); kfree(buffer); printk("%s: scsi-1 drive\n", cd->cdi.name); return; @@ -775,6 +815,7 @@ static void get_capabilities(struct scsi_cd *cd) /*else I don't think it can close its tray cd->cdi.mask |= CDC_CLOSE_TRAY; */ + scsi_release_request(SRpnt); kfree(buffer); } -- 2.53.0