> > I have a USB bridge that's implementing SAT passthru cdbs.  We ran into an
> > issue with the usb-storage driver in that when it does auto-sense (because
> > the CK_COND bit is set in the passthru cdb), the driver does a sense with
> > only 18 bytes for the sense buffer.  The problem is that SAT passthru wants
> > to return 22 bytes of sense data. The last 4 bytes that don't get returned
> > are fairly important ATA task files registers: lba high hob, lba high,
> > device, and status.
> > 
> > For testing purposes I use the patch below, but what's the correct way to
> > deal with this issue?  Is there something in the USB spec mandating 18 bytes
> > of sense data, or is the usb-storage simply making a hard-coded assumption?
> 
> I believe it's a hard-coded assumption, based on the observation that many 
> USB devices don't like it if you ask for more or less than 18 bytes.  Matt 
> Dharm can correct this if I'm wrong.
> 
> The sense buffer length is yet another quantity that ought to have an SG 
> passthru but doesn't.
> 
> Your patch looks to me like a reasonable approach, given the constraints
> we are under.  It would be nice to have a cleaner way of determining which
> commands need the extra sense data.  Could you make that test into a
> separate subroutine?  And perhaps use symbolic names for the command
> bytes.
> 
> Alan Stern
> 

Here is a patch that makes the test a separate routine and uses the
ATA_12/16 opcode defines found in scsi.h. Thoughts?

Thanks,
Tim Thelin


---

diff --git a/drivers/usb/storage/transport.c b/drivers/usb/storage/transport.c
index 7ca896a..cd0ab66 100644
--- a/drivers/usb/storage/transport.c
+++ b/drivers/usb/storage/transport.c
@@ -521,6 +521,14 @@ int usb_stor_bulk_transfer_sg(struct us_
  * Transport routines
  ***********************************************************************/
 
+static inline u8 usb_stor_sense_data_len(struct scsi_cmnd *srb, struct us_data 
*us)
+{
+       if ((us->subclass == US_SC_RBC || us->subclass == US_SC_SCSI) &&
+           (srb->cmnd[0] == ATA_12 || srb->cmnd[0] == ATA_16))
+               return 22;
+       return 18; 
+}
+
 /* Invoke the transport and basic error-handling/recovery methods
  *
  * This is used by the protocol layers to actually send the message to
@@ -611,9 +619,13 @@ void usb_stor_invoke_transport(struct sc
                unsigned char old_cmd_len;
                unsigned char old_cmnd[MAX_COMMAND_SIZE];
                int old_resid;
+               u8 sense_data_len;
 
                US_DEBUGP("Issuing auto-REQUEST_SENSE\n");
 
+               /* get the length before the srb is changed */
+               sense_data_len = usb_stor_sense_data_len(srb, us);
+               
                /* save the old command */
                memcpy(old_cmnd, srb->cmnd, MAX_COMMAND_SIZE);
                old_cmd_len = srb->cmd_len;
@@ -622,7 +634,7 @@ void usb_stor_invoke_transport(struct sc
                memset(srb->cmnd, 0, MAX_COMMAND_SIZE);
                srb->cmnd[0] = REQUEST_SENSE;
                srb->cmnd[1] = old_cmnd[1] & 0xE0;
-               srb->cmnd[4] = 18;
+               srb->cmnd[4] = sense_data_len;
 
                /* FIXME: we must do the protocol translation here */
                if (us->subclass == US_SC_RBC || us->subclass == US_SC_SCSI)
@@ -640,7 +652,7 @@ void usb_stor_invoke_transport(struct sc
 
                /* set the buffer length for transfer */
                old_request_bufflen = srb->request_bufflen;
-               srb->request_bufflen = US_SENSE_SIZE;
+               srb->request_bufflen = sense_data_len;
 
                /* set up for no scatter-gather use */
                old_sg = srb->use_sg;
diff --git a/drivers/usb/storage/usb.h b/drivers/usb/storage/usb.h
index 98b0971..80e3a22 100644
--- a/drivers/usb/storage/usb.h
+++ b/drivers/usb/storage/usb.h
@@ -117,7 +117,7 @@ enum { US_DO_ALL_FLAGS };
  */
 
 #define US_IOBUF_SIZE          64      /* Size of the DMA-mapped I/O buffer */
-#define US_SENSE_SIZE          18      /* Size of the autosense data buffer */
+#define US_SENSE_SIZE          22      /* Size of the autosense data buffer */
 
 typedef int (*trans_cmnd)(struct scsi_cmnd *, struct us_data*);
 typedef int (*trans_reset)(struct us_data*);



-------------------------------------------------------
This SF.net email is sponsored by: Splunk Inc. Do you grep through log files
for problems?  Stop!  Download the new AJAX search engine that makes
searching your log files as easy as surfing the  web.  DOWNLOAD SPLUNK!
http://ads.osdn.com/?ad_id=7637&alloc_id=16865&op=click
_______________________________________________
Linux-usb-users@lists.sourceforge.net
To unsubscribe, use the last form field at:
https://lists.sourceforge.net/lists/listinfo/linux-usb-users

Reply via email to