patch-2.4.22 linux-2.4.22/drivers/usb/storage/protocol.c
Next file: linux-2.4.22/drivers/usb/storage/protocol.h
Previous file: linux-2.4.22/drivers/usb/storage/initializers.h
Back to the patch index
Back to the overall index
- Lines: 91
- Date:
2003-08-25 04:44:42.000000000 -0700
- Orig file:
linux-2.4.21/drivers/usb/storage/protocol.c
- Orig date:
2002-08-02 17:39:45.000000000 -0700
diff -urN linux-2.4.21/drivers/usb/storage/protocol.c linux-2.4.22/drivers/usb/storage/protocol.c
@@ -53,6 +53,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
@@ -65,21 +81,48 @@
if (srb->cmnd[0] != INQUIRY)
return;
- US_DEBUGP("Fixing INQUIRY data to show SCSI rev 2\n");
+ /* oddly short buffer -- bail out */
+ if (srb->request_bufflen < 3)
+ return;
- /* find the location of the data */
- if (srb->use_sg) {
- struct scatterlist *sg;
+ data_ptr = find_data_location(srb);
- sg = (struct scatterlist *) srb->request_buffer;
- data_ptr = (unsigned char *) sg[0].address;
- } else
- data_ptr = (unsigned char *)srb->request_buffer;
+ /* if it's already 2, bail */
+ if ((data_ptr[2] & 7) == 2)
+ return;
+
+ US_DEBUGP("Fixing INQUIRY data to show SCSI rev 2 - was %d\n",
+ data_ptr[2] & 7);
/* Change the SCSI revision number */
data_ptr[2] = (data_ptr[2] & ~7) | 2;
}
+/*
+ * Fix-up the return data from a READ CAPACITY command. A 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 +388,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);
}
}
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)