patch-2.4.0-test8 linux/drivers/usb/storage/transport.c
Next file: linux/drivers/usb/storage/transport.h
Previous file: linux/drivers/usb/storage/shuttle_usbat.h
Back to the patch index
Back to the overall index
- Lines: 159
- Date:
Mon Aug 28 16:59:14 2000
- Orig file:
v2.4.0-test7/linux/drivers/usb/storage/transport.c
- Orig date:
Wed Aug 23 18:36:38 2000
diff -u --recursive --new-file v2.4.0-test7/linux/drivers/usb/storage/transport.c linux/drivers/usb/storage/transport.c
@@ -1,8 +1,8 @@
/* Driver for USB Mass Storage compliant devices
*
- * $Id: transport.c,v 1.12 2000/08/08 15:22:38 gowdy Exp $
+ * $Id: transport.c,v 1.18 2000/08/25 00:13:51 mdharm Exp $
*
- * Current development and maintainance by:
+ * Current development and maintenance by:
* (c) 1999, 2000 Matthew Dharm (mdharm-usb@one-eyed-alien.net)
*
* Developed with the assistance of:
@@ -59,43 +59,7 @@
/* Calculate the length of the data transfer (not the command) for any
* given SCSI command
*/
-static unsigned int us_transfer_length(Scsi_Cmnd *srb, struct us_data *us)
-{
- int i;
- unsigned int total = 0;
- struct scatterlist *sg;
-
- /* support those devices which need the length calculated
- * differently
- */
- if (srb->cmnd[0] == INQUIRY) {
- srb->cmnd[4] = 36;
- }
-
- if ((srb->cmnd[0] == INQUIRY) || (srb->cmnd[0] == MODE_SENSE))
- return srb->cmnd[4];
-
- if (srb->cmnd[0] == TEST_UNIT_READY)
- return 0;
-
- /* Are we going to scatter gather? */
- if (srb->use_sg) {
- /* Add up the sizes of all the scatter-gather segments */
- sg = (struct scatterlist *) srb->request_buffer;
- for (i = 0; i < srb->use_sg; i++)
- total += sg[i].length;
-
- return total;
- }
- else
- /* Just return the length of the buffer */
- return srb->request_bufflen;
-}
-
-/* Calculate the length of the data transfer (not the command) for any
- * given SCSI command
- */
-static unsigned int us_transfer_length_new(Scsi_Cmnd *srb, struct us_data *us)
+static unsigned int us_transfer_length(Scsi_Cmnd *srb)
{
int i;
int doDefault = 0;
@@ -245,10 +209,6 @@
WRITE_SAME 41
*/
- /* Not sure this is right as an INQUIRY can contain nonstandard info */
- if (srb->cmnd[0] == INQUIRY)
- srb->cmnd[4] = 36;
-
if (srb->sc_data_direction == SCSI_DATA_WRITE) {
doDefault = 1;
}
@@ -611,6 +571,16 @@
int i;
int result = -1;
struct scatterlist *sg;
+ unsigned int total_transferred = 0;
+ unsigned int transfer_amount;
+
+ /* calculate how much we want to transfer */
+ transfer_amount = us_transfer_length(srb);
+
+ /* was someone foolish enough to request more data than available
+ * buffer space? */
+ if (transfer_amount > srb->request_bufflen)
+ transfer_amount = srb->request_bufflen;
/* are we scatter-gathering? */
if (srb->use_sg) {
@@ -620,8 +590,19 @@
*/
sg = (struct scatterlist *) srb->request_buffer;
for (i = 0; i < srb->use_sg; i++) {
- result = us_transfer_partial(us, sg[i].address,
- sg[i].length);
+
+ /* transfer the lesser of the next buffer or the
+ * remaining data */
+ if (transfer_amount - total_transferred >=
+ sg[i].length) {
+ result = us_transfer_partial(us, sg[i].address,
+ sg[i].length);
+ total_transferred += sg[i].length;
+ } else
+ result = us_transfer_partial(us, sg[i].address,
+ transfer_amount - total_transferred);
+
+ /* if we get an error, end the loop here */
if (result)
break;
}
@@ -629,7 +610,7 @@
else
/* no scatter-gather, just make the request */
result = us_transfer_partial(us, srb->request_buffer,
- srb->request_bufflen);
+ transfer_amount);
/* return the result in the data structure itself */
srb->result = result;
@@ -874,7 +855,7 @@
/* DATA STAGE */
/* transfer the data payload for this command, if one exists*/
- if (us_transfer_length(srb, us)) {
+ if (us_transfer_length(srb)) {
us_transfer(srb, us);
US_DEBUGP("CBI data stage result is 0x%x\n", srb->result);
@@ -975,7 +956,7 @@
/* DATA STAGE */
/* transfer the data payload for this command, if one exists*/
- if (us_transfer_length(srb, us)) {
+ if (us_transfer_length(srb)) {
us_transfer(srb, us);
US_DEBUGP("CB data stage result is 0x%x\n", srb->result);
@@ -1039,10 +1020,12 @@
/* set up the command wrapper */
bcb.Signature = cpu_to_le32(US_BULK_CB_SIGN);
- bcb.DataTransferLength = cpu_to_le32(us_transfer_length(srb, us));
+ bcb.DataTransferLength = cpu_to_le32(us_transfer_length(srb));
bcb.Flags = srb->sc_data_direction == SCSI_DATA_READ ? 1 << 7 : 0;
bcb.Tag = srb->serial_number;
bcb.Lun = srb->cmnd[1] >> 5;
+ if (us->flags & US_FL_SCM_MULT_TARG)
+ bcb.Lun |= srb->target << 4;
bcb.Length = srb->cmd_len;
/* construct the pipe handle */
@@ -1053,8 +1036,9 @@
memcpy(bcb.CDB, srb->cmnd, bcb.Length);
/* send it to out endpoint */
- US_DEBUGP("Bulk command S 0x%x T 0x%x LUN %d L %d F %d CL %d\n",
- le32_to_cpu(bcb.Signature), bcb.Tag, bcb.Lun,
+ US_DEBUGP("Bulk command S 0x%x T 0x%x Trg %d LUN %d L %d F %d CL %d\n",
+ le32_to_cpu(bcb.Signature), bcb.Tag,
+ (bcb.Lun >> 4), (bcb.Lun & 0xFF),
bcb.DataTransferLength, bcb.Flags, bcb.Length);
result = usb_stor_bulk_msg(us, &bcb, pipe, US_BULK_CB_WRAP_LEN,
&partial);
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)