ChangeSet 1.1079.1.3, 2003/07/14 09:48:18-07:00, stern@rowland.harvard.edu [PATCH] USB: Implement US_FL_FIX_CAPACITY for 2.4 On Wed, 9 Jul 2003, Greg KH wrote: > After applying all three patches here (as49, as50, as51) I get the > following build error: > > In file included from usb.c:190: > unusual_devs.h:562: `US_FL_FIX_CAPACITY' undeclared here (not in a function) > unusual_devs.h:562: initializer element is not constant > unusual_devs.h:562: (near initialization for `us_unusual_dev_list[72].flags') > > Care to send me a patch to fix this up? This should fix everything. It defines the new flag and adds the corresponding implementation. drivers/usb/storage/protocol.c | 54 ++++++++++++++++++++++++++++++++++------- drivers/usb/storage/usb.h | 1 2 files changed, 47 insertions(+), 8 deletions(-) diff -Nru a/drivers/usb/storage/protocol.c b/drivers/usb/storage/protocol.c --- a/drivers/usb/storage/protocol.c Mon Jul 14 10:04:02 2003 +++ b/drivers/usb/storage/protocol.c Mon Jul 14 10:04:02 2003 @@ -54,6 +54,22 @@ * Helper routines ***********************************************************************/ +static void * +find_data_location(Scsi_Cmnd *srb) { + if (srb->use_sg) { + /* + * This piece of code only works if the first page is + * big enough to hold more than 3 bytes -- which is + * _very_ likely. + */ + struct scatterlist *sg; + + sg = (struct scatterlist *) srb->request_buffer; + return (void *) sg[0].address; + } else + return (void *) srb->request_buffer; +} + /* Fix-up the return data from an INQUIRY command to show * ANSI SCSI rev 2 so we don't confuse the SCSI layers above us */ @@ -67,19 +83,37 @@ US_DEBUGP("Fixing INQUIRY data to show SCSI rev 2\n"); - /* find the location of the data */ - if (srb->use_sg) { - struct scatterlist *sg; - - sg = (struct scatterlist *) srb->request_buffer; - data_ptr = (unsigned char *) sg[0].address; - } else - data_ptr = (unsigned char *)srb->request_buffer; + data_ptr = find_data_location(srb); /* Change the SCSI revision number */ data_ptr[2] = (data_ptr[2] & ~7) | 2; } +/* + * Fix-up the return data from a READ CAPACITY command. My Feiya reader + * returns a value that is 1 too large. + */ +static void fix_read_capacity(Scsi_Cmnd *srb) +{ + unsigned char *dp; + unsigned long capacity; + + /* verify that it's a READ CAPACITY command */ + if (srb->cmnd[0] != READ_CAPACITY) + return; + + dp = find_data_location(srb); + + capacity = (dp[0]<<24) + (dp[1]<<16) + (dp[2]<<8) + (dp[3]); + US_DEBUGP("US: Fixing capacity: from %ld to %ld\n", + capacity+1, capacity); + capacity--; + dp[0] = (capacity >> 24); + dp[1] = (capacity >> 16); + dp[2] = (capacity >> 8); + dp[3] = (capacity); +} + /*********************************************************************** * Protocol routines ***********************************************************************/ @@ -345,6 +379,10 @@ /* fix the INQUIRY data if necessary */ fix_inquiry_data(srb); + + /* Fix the READ CAPACITY result if necessary */ + if (us->flags & US_FL_FIX_CAPACITY) + fix_read_capacity(srb); } } diff -Nru a/drivers/usb/storage/usb.h b/drivers/usb/storage/usb.h --- a/drivers/usb/storage/usb.h Mon Jul 14 10:04:02 2003 +++ b/drivers/usb/storage/usb.h Mon Jul 14 10:04:02 2003 @@ -102,6 +102,7 @@ #define US_FL_IGNORE_SER 0x00000010 /* Ignore the serial number given */ #define US_FL_SCM_MULT_TARG 0x00000020 /* supports multiple targets */ #define US_FL_FIX_INQUIRY 0x00000040 /* INQUIRY response needs fixing */ +#define US_FL_FIX_CAPACITY 0x00000080 /* READ CAPACITY response too big */ #define USB_STOR_STRING_LEN 32