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.

This has been tested with multiple usb-storage peripherals.  Please apply.

Matthew Dharm

===== drivers/scsi/sr.c 1.53 vs edited =====
--- 1.53/drivers/scsi/sr.c      Tue Aug 19 10:38:06 2003
+++ edited/drivers/scsi/sr.c    Mon Sep  1 13:28:41 2003
@@ -695,6 +695,10 @@
        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 @@
                ""
        };
 
+       /* 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 @@
                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 @@
        /*else    I don't think it can close its tray
                cd->cdi.mask |= CDC_CLOSE_TRAY; */
 
+       scsi_release_request(SRpnt);
        kfree(buffer);
 }
 
-- 
Matthew Dharm                              Home: [EMAIL PROTECTED] 
Maintainer, Linux USB Mass Storage Driver

It's not that hard.  No matter what the problem is, tell the customer 
to reinstall Windows.
                                        -- Nurse
User Friendly, 3/22/1998

Attachment: pgp00000.pgp
Description: PGP signature

Reply via email to