Commit c751e414 authored by Matthew Dharm's avatar Matthew Dharm Committed by Greg Kroah-Hartman

[PATCH] USB Storage: Fix scatter-gather for non READ/WRITE in sddr09

This patch (from Alan Stern as157) fixes the non-READ/WRITE paths of the
sddr09.c driver to be compliant to the requirements of scatter-gather.  It
also cleans up MODE_SENSE processing and reports errors a little better.

This patch also makes MODE_SENSE_10 commands report an error.  The old code
claimed to support both 6- and 10-byte versions, but really only supported
6-byte.   Bad data was returned for the 10-byte case, so it was removed.  A
patch to follow in a few minutes fixes this.
parent d3f45439
...@@ -1377,18 +1377,17 @@ int sddr09_transport(Scsi_Cmnd *srb, struct us_data *us) ...@@ -1377,18 +1377,17 @@ int sddr09_transport(Scsi_Cmnd *srb, struct us_data *us)
static unsigned char sensekey = 0, sensecode = 0; static unsigned char sensekey = 0, sensecode = 0;
static unsigned char havefakesense = 0; static unsigned char havefakesense = 0;
int result, i; int result, i;
unsigned char *ptr; unsigned char *ptr = us->iobuf;
unsigned long capacity; unsigned long capacity;
unsigned int page, pages; unsigned int page, pages;
char string[64];
struct sddr09_card_info *info; struct sddr09_card_info *info;
unsigned char inquiry_response[36] = { static unsigned char inquiry_response[8] = {
0x00, 0x80, 0x00, 0x02, 0x1F, 0x00, 0x00, 0x00 0x00, 0x80, 0x00, 0x02, 0x1F, 0x00, 0x00, 0x00
}; };
unsigned char mode_page_01[16] = { static unsigned char mode_page_01[16] = {
0x0F, 0x00, 0, 0x00, 0x0F, 0x00, 0, 0x00,
0x01, 0x0A, 0x01, 0x0A,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
...@@ -1403,18 +1402,14 @@ int sddr09_transport(Scsi_Cmnd *srb, struct us_data *us) ...@@ -1403,18 +1402,14 @@ int sddr09_transport(Scsi_Cmnd *srb, struct us_data *us)
return USB_STOR_TRANSPORT_ERROR; return USB_STOR_TRANSPORT_ERROR;
} }
ptr = (unsigned char *)srb->request_buffer;
if (srb->cmnd[0] == REQUEST_SENSE && havefakesense) { if (srb->cmnd[0] == REQUEST_SENSE && havefakesense) {
/* for a faked command, we have to follow with a faked sense */ /* for a faked command, we have to follow with a faked sense */
memset(ptr, 0, srb->request_bufflen); memset(ptr, 0, 18);
if (srb->request_bufflen > 7) { ptr[0] = 0x70;
ptr[0] = 0x70; ptr[2] = sensekey;
ptr[2] = sensekey; ptr[7] = 11;
ptr[7] = srb->request_bufflen - 7; ptr[12] = sensecode;
} usb_stor_set_xfer_buf(ptr, 18, srb);
if (srb->request_bufflen > 12)
ptr[12] = sensecode;
sensekey = sensecode = havefakesense = 0; sensekey = sensecode = havefakesense = 0;
return USB_STOR_TRANSPORT_GOOD; return USB_STOR_TRANSPORT_GOOD;
} }
...@@ -1425,8 +1420,8 @@ int sddr09_transport(Scsi_Cmnd *srb, struct us_data *us) ...@@ -1425,8 +1420,8 @@ int sddr09_transport(Scsi_Cmnd *srb, struct us_data *us)
respond to INQUIRY commands */ respond to INQUIRY commands */
if (srb->cmnd[0] == INQUIRY) { if (srb->cmnd[0] == INQUIRY) {
memset(inquiry_response+8, 0, 28); memcpy(ptr, inquiry_response, 8);
fill_inquiry_response(us, inquiry_response, 36); fill_inquiry_response(us, ptr, 36);
return USB_STOR_TRANSPORT_GOOD; return USB_STOR_TRANSPORT_GOOD;
} }
...@@ -1461,43 +1456,30 @@ int sddr09_transport(Scsi_Cmnd *srb, struct us_data *us) ...@@ -1461,43 +1456,30 @@ int sddr09_transport(Scsi_Cmnd *srb, struct us_data *us)
capacity = (info->lbact << info->blockshift) - 1; capacity = (info->lbact << info->blockshift) - 1;
ptr[0] = MSB_of(capacity>>16); ((u32 *) ptr)[0] = cpu_to_be32(capacity);
ptr[1] = LSB_of(capacity>>16);
ptr[2] = MSB_of(capacity&0xFFFF);
ptr[3] = LSB_of(capacity&0xFFFF);
// Report page size // Report page size
ptr[4] = MSB_of(info->pagesize>>16); ((u32 *) ptr)[1] = cpu_to_be32(info->pagesize);
ptr[5] = LSB_of(info->pagesize>>16); usb_stor_set_xfer_buf(ptr, 8, srb);
ptr[6] = MSB_of(info->pagesize&0xFFFF);
ptr[7] = LSB_of(info->pagesize&0xFFFF);
return USB_STOR_TRANSPORT_GOOD; return USB_STOR_TRANSPORT_GOOD;
} }
if (srb->cmnd[0] == MODE_SENSE || srb->cmnd[0] == MODE_SENSE_10) { if (srb->cmnd[0] == MODE_SENSE) {
int modepage = (srb->cmnd[2] & 0x3F); int modepage = (srb->cmnd[2] & 0x3F);
int len;
/* They ask for the Read/Write error recovery page, /* They ask for the Read/Write error recovery page,
or for all pages. Give as much as they have room for. */ or for all pages. */
/* %% We should check DBD %% */ /* %% We should check DBD %% */
if (modepage == 0x01 || modepage == 0x3F) { if (modepage == 0x01 || modepage == 0x3F) {
US_DEBUGP("SDDR09: Dummy up request for " US_DEBUGP("SDDR09: Dummy up request for "
"mode page 0x%x\n", modepage); "mode page 0x%x\n", modepage);
if (ptr == NULL) memcpy(ptr, mode_page_01, sizeof(mode_page_01));
return USB_STOR_TRANSPORT_ERROR; ptr[0] = sizeof(mode_page_01) - 1;
ptr[2] = (info->flags & SDDR09_WP) ? 0x80 : 0;
len = srb->request_bufflen; usb_stor_set_xfer_buf(ptr, sizeof(mode_page_01), srb);
if (len > sizeof(mode_page_01))
len = sizeof(mode_page_01);
mode_page_01[0] = sizeof(mode_page_01) - 1;
mode_page_01[2] = (info->flags & SDDR09_WP) ? 0x80 : 0;
memcpy(ptr, mode_page_01, len);
return USB_STOR_TRANSPORT_GOOD; return USB_STOR_TRANSPORT_GOOD;
} }
...@@ -1552,11 +1534,11 @@ int sddr09_transport(Scsi_Cmnd *srb, struct us_data *us) ...@@ -1552,11 +1534,11 @@ int sddr09_transport(Scsi_Cmnd *srb, struct us_data *us)
srb->cmnd[1] = LUNBITS; srb->cmnd[1] = LUNBITS;
string[0] = 0; ptr[0] = 0;
for (i=0; i<12; i++) for (i=0; i<12; i++)
sprintf(string+strlen(string), "%02X ", srb->cmnd[i]); sprintf(ptr+strlen(ptr), "%02X ", srb->cmnd[i]);
US_DEBUGP("SDDR09: Send control for command %s\n", string); US_DEBUGP("SDDR09: Send control for command %s\n", ptr);
result = sddr09_send_scsi_command(us, srb->cmnd, 12); result = sddr09_send_scsi_command(us, srb->cmnd, 12);
if (result != USB_STOR_TRANSPORT_GOOD) { if (result != USB_STOR_TRANSPORT_GOOD) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment