ChangeSet 1.738.5.25, 2002/10/13 13:48:19-07:00, [EMAIL PROTECTED]

[PATCH] usb-storage: generalize transfer functions

This patch generalizes the transfer functions.  This is in preparation for
consolidating all sub-drivers to use a common set of functions.

Oh, and this patch makes the residue field be initialized.  Making this the
correct value is still on the TODO list.


diff -Nru a/drivers/usb/storage/datafab.c b/drivers/usb/storage/datafab.c
--- a/drivers/usb/storage/datafab.c     Sun Oct 13 17:08:41 2002
+++ b/drivers/usb/storage/datafab.c     Sun Oct 13 17:08:41 2002
@@ -522,6 +522,7 @@
                0x00, 0x80, 0x00, 0x01, 0x1F, 0x00, 0x00, 0x00
        };
 
+       srb->resid = 0;
        if (!us->extra) {
                us->extra = kmalloc(sizeof(struct datafab_info), GFP_NOIO);
                if (!us->extra) {
diff -Nru a/drivers/usb/storage/freecom.c b/drivers/usb/storage/freecom.c
--- a/drivers/usb/storage/freecom.c     Sun Oct 13 17:08:42 2002
+++ b/drivers/usb/storage/freecom.c     Sun Oct 13 17:08:42 2002
@@ -108,69 +108,6 @@
 /* All packets (except for status) are 64 bytes long. */
 #define FCM_PACKET_LENGTH      64
 
-/*
- * Transfer an entire SCSI command's worth of data payload over the bulk
- * pipe.
- *
- * Note that this uses usb_stor_transfer_partial to achieve it's goals -- this
- * function simply determines if we're going to use scatter-gather or not,
- * and acts appropriately.  For now, it also re-interprets the error codes.
- */
-static void us_transfer_freecom(Scsi_Cmnd *srb, struct us_data* us, int 
transfer_amount)
-{
-       int i;
-       int result = -1;
-       struct scatterlist *sg;
-       unsigned int total_transferred = 0;
-
-       /* 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) {
-
-               /* loop over all the scatter gather structures and 
-                * make the appropriate requests for each, until done
-                */
-               sg = (struct scatterlist *) srb->request_buffer;
-               for (i = 0; i < srb->use_sg; i++) {
-
-                       US_DEBUGP("transfer_amount: %d and total_transferred: %d\n", 
transfer_amount, total_transferred);
-
-                       /* End this if we're done */
-                       if (transfer_amount == total_transferred)
-                               break;
-
-                       /* transfer the lesser of the next buffer or the
-                        * remaining data */
-                       if (transfer_amount - total_transferred >= 
-                                       sg[i].length) {
-                               result = usb_stor_transfer_partial(us,
-                                               sg_address(sg[i]), sg[i].length);
-                               total_transferred += sg[i].length;
-                       } else {
-                               result = usb_stor_transfer_partial(us,
-                                               sg_address(sg[i]),
-                                               transfer_amount - total_transferred);
-                               total_transferred += transfer_amount - 
total_transferred;
-                       }
-
-                       /* if we get an error, end the loop here */
-                       if (result)
-                               break;
-               }
-       }
-       else
-               /* no scatter-gather, just make the request */
-               result = usb_stor_transfer_partial(us, srb->request_buffer, 
-                                            transfer_amount);
-
-       /* return the result in the data structure itself */
-       srb->result = result;
-}
-
 static int
 freecom_readdata (Scsi_Cmnd *srb, struct us_data *us,
                 unsigned int ipipe, unsigned int opipe, int count)
@@ -206,10 +143,10 @@
 
         /* Now transfer all of our blocks. */
        US_DEBUGP("Start of read\n");
-       us_transfer_freecom(srb, us, count);
+       result = usb_stor_bulk_transfer_srb(us, ipipe, srb, count);
         US_DEBUGP("freecom_readdata done!\n");
 
-        return USB_STOR_TRANSPORT_GOOD;
+        return result;
 }
 
 static int
@@ -248,10 +185,10 @@
 
         /* Now transfer all of our blocks. */
        US_DEBUGP("Start of write\n");
-       us_transfer_freecom(srb, us, count);
+       result = usb_stor_bulk_transfer_srb(us, opipe, srb, count);
 
         US_DEBUGP("freecom_writedata done!\n");
-        return USB_STOR_TRANSPORT_GOOD;
+        return result;
 }
 
 /*
diff -Nru a/drivers/usb/storage/jumpshot.c b/drivers/usb/storage/jumpshot.c
--- a/drivers/usb/storage/jumpshot.c    Sun Oct 13 17:08:41 2002
+++ b/drivers/usb/storage/jumpshot.c    Sun Oct 13 17:08:41 2002
@@ -464,7 +464,7 @@
                0x00, 0x80, 0x00, 0x01, 0x1F, 0x00, 0x00, 0x00
        };
 
-
+       srb->resid = 0;
        if (!us->extra) {
                us->extra = kmalloc(sizeof(struct jumpshot_info), GFP_NOIO);
                if (!us->extra) {
diff -Nru a/drivers/usb/storage/sddr09.c b/drivers/usb/storage/sddr09.c
--- a/drivers/usb/storage/sddr09.c      Sun Oct 13 17:08:41 2002
+++ b/drivers/usb/storage/sddr09.c      Sun Oct 13 17:08:41 2002
@@ -1368,6 +1368,7 @@
                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
        };
 
+       srb->resid = 0;
        info = (struct sddr09_card_info *)us->extra;
        if (!info) {
                nand_init_ecc();
diff -Nru a/drivers/usb/storage/sddr55.c b/drivers/usb/storage/sddr55.c
--- a/drivers/usb/storage/sddr55.c      Sun Oct 13 17:08:41 2002
+++ b/drivers/usb/storage/sddr55.c      Sun Oct 13 17:08:41 2002
@@ -743,6 +743,7 @@
        unsigned short pages;
        struct sddr55_card_info *info;
 
+       srb->resid = 0;
        if (!us->extra) {
                us->extra = kmalloc(
                        sizeof(struct sddr55_card_info), GFP_NOIO);
diff -Nru a/drivers/usb/storage/shuttle_usbat.c b/drivers/usb/storage/shuttle_usbat.c
--- a/drivers/usb/storage/shuttle_usbat.c       Sun Oct 13 17:08:41 2002
+++ b/drivers/usb/storage/shuttle_usbat.c       Sun Oct 13 17:08:41 2002
@@ -766,6 +766,7 @@
        int i;
        char string[64];
 
+       srb->resid = 0;
        len = srb->request_bufflen;
 
        /* Send A0 (ATA PACKET COMMAND).
diff -Nru a/drivers/usb/storage/transport.c b/drivers/usb/storage/transport.c
--- a/drivers/usb/storage/transport.c   Sun Oct 13 17:08:41 2002
+++ b/drivers/usb/storage/transport.c   Sun Oct 13 17:08:41 2002
@@ -541,33 +541,76 @@
 }
 
 /*
- * Transfer one SCSI scatter-gather buffer via bulk transfer
+ * Transfer one control message
  *
- * Note that this function is necessary because we want the ability to
- * use scatter-gather memory.  Good performance is achieved by a combination
- * of scatter-gather and clustering (which makes each chunk bigger).
+ * This function does basically the same thing as usb_stor_control_msg()
+ * above, except that return codes are USB_STOR_XFER_xxx rather than the
+ * urb status or transfer length.
+ */
+int usb_stor_ctrl_transfer(struct us_data *us, unsigned int pipe,
+               u8 request, u8 requesttype, u16 value, u16 index,
+               void *data, u16 size) {
+       int result;
+
+       US_DEBUGP("usb_stor_ctrl_transfer(): rq=%02x rqtype=%02x "
+                       "value=%04x index=%02x len=%d\n",
+                       request, requesttype, value, index, size);
+       result = usb_stor_control_msg(us, pipe, request, requesttype,
+                       value, index, data, size);
+       US_DEBUGP("usb_stor_control_msg returned %d\n", result);
+
+       /* did we abort this command? */
+       if (atomic_read(&us->sm_state) == US_STATE_ABORTING) {
+               US_DEBUGP("-- transfer aborted\n");
+               return USB_STOR_XFER_ABORTED;
+       }
+
+       /* a stall indicates a protocol error */
+       if (result == -EPIPE) {
+               US_DEBUGP("-- stall on control pipe\n");
+               return USB_STOR_XFER_ERROR;
+       }
+
+       /* some other serious problem here */
+       if (result < 0) {
+               US_DEBUGP("-- unknown error\n");
+               return USB_STOR_XFER_ERROR;
+       }
+
+       /* was the entire command transferred? */
+       if (result < size) {
+               US_DEBUGP("-- transfer was short\n");
+               return USB_STOR_XFER_SHORT;
+       }
+
+       US_DEBUGP("-- transfer completed successfully\n");
+       return USB_STOR_XFER_GOOD;
+}
+
+/*
+ * Transfer one buffer via bulk transfer
+ *
+ * This function does basically the same thing as usb_stor_bulk_msg()
+ * above, except that:
  *
- * Note that the lower layer will always retry when a NAK occurs, up to the
- * timeout limit.  Thus we don't have to worry about it for individual
- * packets.
+ *     1.  If the bulk pipe stalls during the transfer, the halt is
+ *         automatically cleared;
+ *     2.  Return codes are USB_STOR_XFER_xxx rather than the
+ *         urb status or transfer length.
  */
-int usb_stor_transfer_partial(struct us_data *us, char *buf, int length)
+int usb_stor_bulk_transfer_buf(struct us_data *us, unsigned int pipe,
+       char *buf, unsigned int length, unsigned int *act_len)
 {
        int result;
        int partial;
-       unsigned int pipe;
-
-       /* get the appropriate pipe value */
-       if (us->srb->sc_data_direction == SCSI_DATA_READ)
-               pipe = us->recv_bulk_pipe;
-       else
-               pipe = us->send_bulk_pipe;
 
        /* transfer the data */
-       US_DEBUGP("usb_stor_transfer_partial(): xfer %d bytes\n", length);
+       US_DEBUGP("usb_stor_bulk_transfer_buf(): xfer %d bytes\n", length);
        result = usb_stor_bulk_msg(us, buf, pipe, length, &partial);
        US_DEBUGP("usb_stor_bulk_msg() returned %d xferred %d/%d\n",
                  result, partial, length);
+       if (act_len)
+               *act_len = partial;
 
        /* if we stall, we need to clear it before we go on */
        if (result == -EPIPE) {
@@ -579,25 +622,25 @@
 
        /* did we abort this command? */
        if (atomic_read(&us->sm_state) == US_STATE_ABORTING) {
-               US_DEBUGP("usb_stor_transfer_partial(): transfer aborted\n");
+               US_DEBUGP("-- transfer aborted\n");
                return USB_STOR_XFER_ABORTED;
        }
 
        /* NAK - that means we've retried a few times already */
        if (result == -ETIMEDOUT) {
-               US_DEBUGP("usb_stor_transfer_partial(): device NAKed\n");
+               US_DEBUGP("-- device NAKed\n");
                return USB_STOR_XFER_ERROR;
        }
 
        /* the catch-all error case */
        if (result) {
-               US_DEBUGP("usb_stor_transfer_partial(): unknown error\n");
+               US_DEBUGP("-- unknown error\n");
                return USB_STOR_XFER_ERROR;
        }
 
        /* did we send all the data? */
        if (partial == length) {
-               US_DEBUGP("usb_stor_transfer_partial(): transfer complete\n");
+               US_DEBUGP("-- transfer complete\n");
                return USB_STOR_XFER_GOOD;
        }
 
@@ -610,59 +653,51 @@
  * Transfer an entire SCSI command's worth of data payload over the bulk
  * pipe.
  *
- * Note that this uses usb_stor_transfer_partial to achieve its goals -- this
+ * Note that this uses usb_stor_transfer_buf to achieve its goals -- this
  * function simply determines if we're going to use scatter-gather or not,
  * and acts appropriately.  For now, it also re-interprets the error codes.
  */
-void usb_stor_transfer(Scsi_Cmnd *srb, struct us_data* us)
+int usb_stor_bulk_transfer_sg(struct us_data* us, unsigned int pipe,
+               char *buf, unsigned int length_left, int use_sg, int *residual)
 {
        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 = usb_stor_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;
+       unsigned int amount;
+       unsigned int partial;
 
        /* are we scatter-gathering? */
-       if (srb->use_sg) {
+       if (use_sg) {
 
                /* loop over all the scatter gather structures and 
                 * make the appropriate requests for each, until done
                 */
-               sg = (struct scatterlist *) srb->request_buffer;
-               for (i = 0; i < srb->use_sg; i++) {
+               sg = (struct scatterlist *) buf;
+               for (i = 0; (i < use_sg) && (length_left > 0); (i++, ++sg)) {
 
                        /* transfer the lesser of the next buffer or the
                         * remaining data */
-                       if (transfer_amount - total_transferred >= 
-                                       sg[i].length) {
-                               result = usb_stor_transfer_partial(us,
-                                               sg_address(sg[i]), sg[i].length);
-                               total_transferred += sg[i].length;
-                       } else
-                               result = usb_stor_transfer_partial(us,
-                                               sg_address(sg[i]),
-                                               transfer_amount - total_transferred);
+                       amount = sg->length < length_left ?
+                                       sg->length : length_left;
+                       result = usb_stor_bulk_transfer_buf(us, pipe,
+                                       sg_address(*sg), amount, &partial);
+                       length_left -= partial;
 
                        /* if we get an error, end the loop here */
-                       if (result)
+                       if (result != USB_STOR_XFER_GOOD)
                                break;
                }
-       }
-       else
+       } else {
                /* no scatter-gather, just make the request */
-               result = usb_stor_transfer_partial(us, srb->request_buffer, 
-                                            transfer_amount);
+               result = usb_stor_bulk_transfer_buf(us, pipe, buf, 
+                               length_left, &partial);
+               length_left -= partial;
+       }
 
-       /* return the result in the data structure itself */
-       srb->result = result;
+       /* store the residual and return the error code */
+       if (residual)
+               *residual = length_left;
+       return result;
 }
 
 /***********************************************************************
@@ -741,7 +776,7 @@
         * Also, if we have a short transfer on a command that can't have
         * a short transfer, we're going to do this.
         */
-       if ((srb->result == USB_STOR_XFER_SHORT) &&
+       if ((srb->resid > 0) &&
            !((srb->cmnd[0] == REQUEST_SENSE) ||
              (srb->cmnd[0] == INQUIRY) ||
              (srb->cmnd[0] == MODE_SENSE) ||
@@ -973,6 +1008,7 @@
 
 int usb_stor_CBI_transport(Scsi_Cmnd *srb, struct us_data *us)
 {
+       unsigned int transfer_length = usb_stor_transfer_length(srb);
        int result;
 
        /* re-initialize the mutex so that we avoid any races with
@@ -984,14 +1020,14 @@
 
        /* COMMAND STAGE */
        /* let's send the command via the control pipe */
-       result = usb_stor_control_msg(us, us->send_ctrl_pipe,
+       result = usb_stor_ctrl_transfer(us, us->send_ctrl_pipe,
                                      US_CBI_ADSC, 
                                      USB_TYPE_CLASS | USB_RECIP_INTERFACE, 0, 
                                      us->ifnum, srb->cmnd, srb->cmd_len);
 
        /* check the return code for the command */
-       US_DEBUGP("Call to usb_stor_control_msg() returned %d\n", result);
-       if (result < 0) {
+       US_DEBUGP("Call to usb_stor_ctrl_transfer() returned %d\n", result);
+       if (result != USB_STOR_XFER_GOOD) {
                /* Reset flag for status notification */
                clear_bit(US_FLIDX_IP_WANTED, &us->flags);
        }
@@ -1002,22 +1038,16 @@
                return USB_STOR_TRANSPORT_ABORTED;
        }
 
-       /* a stall indicates a protocol error */
-       if (result == -EPIPE) {
-               US_DEBUGP("-- Stall on control pipe\n");
-               return USB_STOR_TRANSPORT_ERROR;
-       }
-
-       if (result < 0) {
+       if (result != USB_STOR_XFER_GOOD) {
                /* Uh oh... serious problem here */
                return USB_STOR_TRANSPORT_ERROR;
        }
 
        /* DATA STAGE */
        /* transfer the data payload for this command, if one exists*/
-       if (usb_stor_transfer_length(srb)) {
-               usb_stor_transfer(srb, us);
-               result = srb->result;
+       if (transfer_length > 0) {
+               result = usb_stor_bulk_transfer_srb(us, us->send_bulk_pipe,
+                               srb, transfer_length);
                US_DEBUGP("CBI data stage result is 0x%x\n", result);
 
                /* report any errors */
@@ -1092,39 +1122,34 @@
  */
 int usb_stor_CB_transport(Scsi_Cmnd *srb, struct us_data *us)
 {
+       unsigned int transfer_length = usb_stor_transfer_length(srb);
        int result;
 
        /* COMMAND STAGE */
        /* let's send the command via the control pipe */
-       result = usb_stor_control_msg(us, us->send_ctrl_pipe,
+       result = usb_stor_ctrl_transfer(us, us->send_ctrl_pipe,
                                      US_CBI_ADSC, 
                                      USB_TYPE_CLASS | USB_RECIP_INTERFACE, 0, 
                                      us->ifnum, srb->cmnd, srb->cmd_len);
 
        /* check the return code for the command */
-       US_DEBUGP("Call to usb_stor_control_msg() returned %d\n", result);
-       if (result < 0) {
-               /* did we abort this command? */
-               if (atomic_read(&us->sm_state) == US_STATE_ABORTING) {
-                       US_DEBUGP("usb_stor_CB_transport(): transfer aborted\n");
-                       return USB_STOR_TRANSPORT_ABORTED;
-               }
+       US_DEBUGP("Call to usb_stor_ctrl_transfer() returned %d\n", result);
 
-               /* a stall indicates a protocol error */
-               if (result == -EPIPE) {
-                       US_DEBUGP("-- Stall on control pipe\n");
-                       return USB_STOR_TRANSPORT_ERROR;
-               }
+       /* did we abort this command? */
+       if (atomic_read(&us->sm_state) == US_STATE_ABORTING) {
+               US_DEBUGP("usb_stor_CB_transport(): transfer aborted\n");
+               return USB_STOR_TRANSPORT_ABORTED;
 
+       if (result != USB_STOR_XFER_GOOD) {
                /* Uh oh... serious problem here */
                return USB_STOR_TRANSPORT_ERROR;
        }
 
        /* DATA STAGE */
        /* transfer the data payload for this command, if one exists*/
-       if (usb_stor_transfer_length(srb)) {
-               usb_stor_transfer(srb, us);
-               result = srb->result;
+       if (transfer_length)
+               result = usb_stor_bulk_transfer_srb(us, us->send_bulk_pipe,
+                               srb, transfer_length);
                US_DEBUGP("CB data stage result is 0x%x\n", result);
 
                /* report any errors */
@@ -1178,12 +1203,13 @@
 {
        struct bulk_cb_wrap bcb;
        struct bulk_cs_wrap bcs;
+       unsigned int transfer_length = usb_stor_transfer_length(srb);
        int result;
        int partial;
 
        /* set up the command wrapper */
        bcb.Signature = cpu_to_le32(US_BULK_CB_SIGN);
-       bcb.DataTransferLength = cpu_to_le32(usb_stor_transfer_length(srb));
+       bcb.DataTransferLength = cpu_to_le32(transfer_length);
        bcb.Flags = srb->sc_data_direction == SCSI_DATA_READ ? 1 << 7 : 0;
        bcb.Tag = srb->serial_number;
        bcb.Lun = srb->cmnd[1] >> 5;
@@ -1221,26 +1247,24 @@
                        US_DEBUGP("usb_stor_Bulk_transport(): transfer aborted\n");
                        return USB_STOR_TRANSPORT_ABORTED;
                }
-               if (result < 0)
-                       return USB_STOR_TRANSPORT_ERROR;
-               result = -EPIPE;
+               return USB_STOR_TRANSPORT_ERROR;
        } else if (result) {
                /* unknown error -- we've got a problem */
                return USB_STOR_TRANSPORT_ERROR;
        }
 
-       /* if the command transfered well, then we go to the data stage */
-       if (result == 0) {
-               /* send/receive data payload, if there is any */
-               if (bcb.DataTransferLength) {
-                       usb_stor_transfer(srb, us);
-                       result = srb->result;
-                       US_DEBUGP("Bulk data transfer result 0x%x\n", result);
-
-                       /* if it was aborted, we need to indicate that */
-                       if (result == USB_STOR_XFER_ABORTED)
-                               return USB_STOR_TRANSPORT_ABORTED;
-               }
+       /* DATA STAGE */
+       /* send/receive data payload, if there is any */
+       if (transfer_length) {
+               result = usb_stor_bulk_transfer_srb(us, us->send_bulk_pipe,
+                               srb, transfer_length);
+               US_DEBUGP("Bulk data transfer result 0x%x\n", result);
+
+               /* if it was aborted, we need to indicate that */
+               if (result == USB_STOR_XFER_ABORTED)
+                       return USB_STOR_TRANSPORT_ABORTED;
+               if (result == USB_STOR_XFER_ERROR)
+                       return USB_STOR_TRANSPORT_ERROR;
        }
 
        /* See flow chart on pg 15 of the Bulk Only Transport spec for
diff -Nru a/drivers/usb/storage/transport.h b/drivers/usb/storage/transport.h
--- a/drivers/usb/storage/transport.h   Sun Oct 13 17:08:41 2002
+++ b/drivers/usb/storage/transport.h   Sun Oct 13 17:08:41 2002
@@ -115,7 +115,7 @@
 #define US_BULK_GET_MAX_LUN    0xfe
 
 /*
- * usb_stor_transfer() return codes, in order of severity
+ * usb_stor_bulk_transfer_xxx() return codes, in order of severity
  */
 #define USB_STOR_XFER_GOOD             0  /* good transfer                 */
 #define USB_STOR_XFER_SHORT            1  /* transfered less than expected */
@@ -151,7 +151,6 @@
 extern unsigned int usb_stor_transfer_length(Scsi_Cmnd*);
 extern void usb_stor_invoke_transport(Scsi_Cmnd*, struct us_data*);
 extern void usb_stor_abort_transport(struct us_data*);
-extern int usb_stor_transfer_partial(struct us_data*, char*, int);
 
 extern int usb_stor_bulk_msg(struct us_data *us, void *data,
                unsigned int pipe, unsigned int len, unsigned int *act_len);
@@ -160,5 +159,18 @@
                void *data, u16 size);
 
 extern int usb_stor_clear_halt(struct us_data*, unsigned int pipe);
-extern void usb_stor_transfer(Scsi_Cmnd*, struct us_data*);
+extern int usb_stor_ctrl_transfer(struct us_data *us, unsigned int pipe,
+               u8 request, u8 requesttype, u16 value, u16 index,
+               void *data, u16 size);
+extern int usb_stor_bulk_transfer_buf(struct us_data *us, unsigned int pipe,
+               char *buf, unsigned int length, unsigned int *act_len);
+extern int usb_stor_bulk_transfer_sg(struct us_data *us, unsigned int pipe,
+               char *buf, unsigned int length, int use_sg, int *residual);
+
+static __inline__ int usb_stor_bulk_transfer_srb(struct us_data *us,
+               unsigned int pipe, Scsi_Cmnd *srb, unsigned int length) {
+       return usb_stor_bulk_transfer_sg(us, pipe, srb->request_buffer,
+                       length, srb->use_sg, &srb->resid);
+}
+
 #endif


-------------------------------------------------------
This sf.net email is sponsored by:ThinkGeek
Welcome to geek heaven.
http://thinkgeek.com/sf
_______________________________________________
[EMAIL PROTECTED]
To unsubscribe, use the last form field at:
https://lists.sourceforge.net/lists/listinfo/linux-usb-devel

Reply via email to