Okay, now I'm seeing where you are headed...

So why are you creating all these new functions and not just using the
control/bulk messaging functions in transport.c, which do all the
scatter-gather management for you?

Matt

On Tue, May 21, 2002 at 12:21:51PM +0200, [EMAIL PROTECTED] wrote:
> Ach, too quick.
> 
> > diff -urb
> 
> that should have been "diff -urbN". Sorry about that.
> Am not going to send the diff once more. Below the new files.
> 
> ---- raw_bulk.h ----
> #ifndef _USB_STORAGE_RAW_BULK_H_
> #define _USB_STORAGE_RAW_BULK_H_
> 
> /* usb bulk */
> extern int usb_storage_send_control(
>       struct us_data *us, int pipe,
>       unsigned char request, unsigned char requesttype,
>       unsigned int value, unsigned int index,
>       unsigned char *xfer_data, unsigned int xfer_len);
> 
> extern int usb_storage_raw_bulk(
>       struct us_data *us, int direction,
>       unsigned char *data, unsigned int len, unsigned int *act_len);
> 
> extern int usb_storage_bulk_transport(
>       struct us_data *us, int direction,
>       unsigned char *data, unsigned int len, int use_sg);
> 
> /* scatter-gather */
> extern unsigned char *us_copy_from_sgbuf(
>       unsigned char *content, int buflen,
>       int *index, int *offset, int use_sg);
> 
> extern unsigned char *us_copy_from_sgbuf_all(
>       unsigned char *content, int len, int use_sg);
> 
> extern void us_copy_to_sgbuf(
>       unsigned char *buffer, int buflen,
>       void *content, int *index, int *offset, int use_sg);
> 
> extern void us_copy_to_sgbuf_all(
>       unsigned char *buffer, int buflen,
>       void *content, int use_sg);
> 
> #endif
> 
> ---- raw_bulk.c ----
> /*
>  * Common routines for a handful of drivers.
>  * Unrelated to CF/SM - just USB stuff.
>  *
>  * This is mostly a thin layer on top of transport.c.
>  * It converts routines that return values like -ENOENT and -EPIPE
>  * into routines that return USB_STOR_TRANSPORT_ABORTED etc.
>  *
>  * There is also some debug printing here.
>  */
> 
> #include "debug.h"
> #include "transport.h"
> #include "raw_bulk.h"
> 
> #ifdef CONFIG_USB_STORAGE_DEBUG
> #define DEBUG_PRCT 12
> #else
> #define DEBUG_PRCT 0
> #endif
> 
> /*
>  * Send a control message and wait for the response.
>  *
>  * us - the pointer to the us_data structure for the device to use
>  *
>  * request - the URB Setup Packet's first 6 bytes. The first byte always
>  *  corresponds to the request type, and the second byte always corresponds
>  *  to the request.  The other 4 bytes do not correspond to value and index,
>  *  since they are used in a custom way by the SCM protocol.
>  *
>  * xfer_data - a buffer from which to get, or to which to store, any data
>  *  that gets send or received, respectively, with the URB. Even though
>  *  it looks like we allocate a buffer in this code for the data, xfer_data
>  *  must contain enough allocated space.
>  *
>  * xfer_len - the number of bytes to send or receive with the URB.
>  *
>  */
> 
> int
> usb_storage_send_control(struct us_data *us,
>                        int pipe,
>                        unsigned char request,
>                        unsigned char requesttype,
>                        unsigned int value,
>                        unsigned int index,
>                        unsigned char *xfer_data,
>                        unsigned int xfer_len) {
> 
>       int result;
> 
>       // Send the URB to the device and wait for a response.
> 
>       printk("usb_storage_send_control\n");
> 
>       /* Why are request and request type reversed in this call? */
> 
>       result = usb_stor_control_msg(us, pipe,
>                       request, requesttype, value, index,
>                       xfer_data, xfer_len);
> 
>       printk("usb_stor_control_msg returns %d\n", result);
> 
> 
>       // Check the return code for the command.
> 
>       if (result < 0) {
>               /* if the command was aborted, indicate that */
>               if (result == -ENOENT)
>                       return USB_STOR_TRANSPORT_ABORTED;
> 
>               /* a stall is a fatal condition from the device */
>               if (result == -EPIPE) {
>                       US_DEBUGP("-- Stall on control pipe. Clearing\n");
>                       result = usb_clear_halt(us->pusb_dev, pipe);
>                       US_DEBUGP("-- usb_clear_halt() returns %d\n",
>                                 result);
>                       return USB_STOR_TRANSPORT_FAILED;
>               }
> 
>               /* Uh oh... serious problem here */
>               return USB_STOR_TRANSPORT_ERROR;
>       }
> 
>       return USB_STOR_TRANSPORT_GOOD;
> }
> 
> int
> usb_storage_raw_bulk(struct us_data *us, int direction, unsigned char *data,
>                    unsigned int len, unsigned int *act_len) {
> 
>       int result;
>       int pipe;
> 
>       if (direction == SCSI_DATA_READ)
>               pipe = usb_rcvbulkpipe(us->pusb_dev, us->ep_in);
>       else
>               pipe = usb_sndbulkpipe(us->pusb_dev, us->ep_out);
> 
>       result = usb_stor_bulk_msg(us, data, pipe, len, act_len);
> 
>       /* if we stall, we need to clear it before we go on */
>       if (result == -EPIPE) {
>               US_DEBUGP("EPIPE: clearing endpoint halt for"
>                         " pipe 0x%x, stalled at %d bytes\n",
>                         pipe, *act_len);
>               usb_clear_halt(us->pusb_dev, pipe);
>               /* return US_BULK_TRANSFER_SHORT; */
>       }
> 
>       if (result) {
>               /* -ENOENT -- we canceled this transfer */
>               if (result == -ENOENT) {
>                       US_DEBUGP("raw_bulk(): transfer aborted\n");
>                       return US_BULK_TRANSFER_ABORTED;
>               }
> 
>               /* NAK - that means we've retried a few times already */
>                       if (result == -ETIMEDOUT)
>                       US_DEBUGP("raw_bulk(): device NAKed\n");
>               else if (result == -EOVERFLOW)
>                       US_DEBUGP("raw_bulk(): babble/overflow\n");
>               else if (result == -ECONNRESET)
>                       US_DEBUGP("raw_bulk(): asynchronous reset\n");
>               else if (result != -EPIPE)
>                       US_DEBUGP("raw_bulk(): unknown error %d\n",
>                                 result);
> 
>               return US_BULK_TRANSFER_FAILED;
>       }
> 
>       if (*act_len != len) {
>               US_DEBUGP("Warning: Transferred only %d of %d bytes\n",
>                         *act_len, len);
>               return US_BULK_TRANSFER_SHORT;
>       }
> 
> #if 0
>       US_DEBUGP("raw_bulk(): Transferred %s %d of %d bytes\n",
>                 (direction == SCSI_DATA_READ) ? "in" : "out",
>                 *act_len, len);
> #endif
> 
>       return US_BULK_TRANSFER_GOOD;
> }
> 
> int
> usb_storage_bulk_transport(struct us_data *us, int direction,
>                          unsigned char *data, unsigned int len,
>                          int use_sg) {
> 
>       int result = USB_STOR_TRANSPORT_GOOD;
>       int transferred = 0;
>       int i;
>       struct scatterlist *sg;
>       unsigned int act_len;
> 
>       if (len == 0)
>               return USB_STOR_TRANSPORT_GOOD;
> 
> #if DEBUG_PRCT
> 
>       if (direction == SCSI_DATA_WRITE && !use_sg) {
>               char string[64];
> 
>               /* Debug-print the first N bytes of the write transfer */
> 
>               strcpy(string, "wr: ");
>               for (i=0; i<len && i<DEBUG_PRCT; i++) {
>                       sprintf(string+strlen(string), "%02X ", data[i]);
>                       if ((i%16) == 15) {
>                               US_DEBUGP("%s\n", string);
>                               strcpy(string, "wr: ");
>                       }
>               }
>               if ((i%16)!=0)
>                       US_DEBUGP("%s\n", string);
>       }
> 
>       US_DEBUGP("SCM data %s transfer %d sg buffers %d\n",
>                 (direction == SCSI_DATA_READ) ? "in" : "out",
>                 len, use_sg);
> 
> #endif /* DEBUG_PRCT */
> 
>       if (!use_sg)
>               result = usb_storage_raw_bulk(us, direction,
>                                             data, len, &act_len);
>       else {
>               sg = (struct scatterlist *)data;
> 
>               for (i=0; i<use_sg && transferred<len; i++) {
>                       unsigned char *buf;
>                       unsigned int length;
> 
>                       buf = page_address(sg[i].page) + sg[i].offset;
>                       length = len-transferred;
>                       if (length > sg[i].length)
>                               length = sg[i].length;
> 
>                       result = usb_storage_raw_bulk(us, direction,
>                                                     buf, length, &act_len);
>                       if (result != US_BULK_TRANSFER_GOOD)
>                               break;
>                       transferred += length;
>               }
>       }
> 
> #if DEBUG_PRCT
> 
>       if (direction == SCSI_DATA_READ && !use_sg) {
>               char string[64];
> 
>               /* Debug-print the first N bytes of the read transfer */
> 
>               strcpy(string, "rd: ");
>               for (i=0; i<len && i<act_len && i<DEBUG_PRCT; i++) {
>                       sprintf(string+strlen(string), "%02X ", data[i]);
>                       if ((i%16) == 15) {
>                               US_DEBUGP("%s\n", string);
>                               strcpy(string, "rd: ");
>                       }
>               }
>               if ((i%16)!=0)
>                       US_DEBUGP("%s\n", string);
>       }
> 
> #endif /* DEBUG_PRCT */
> 
>       return result;
> }
> 
> /*
>  * The routines below convert scatter-gather to single buffer.
>  * Some drivers claim this is necessary.
>  * Nothing is done when use_sg is zero.
>  */
> 
> /*
>  * Copy from scatter-gather buffer into a newly allocated single buffer,
>  * starting at a given index and offset.
>  * When done, update index and offset.
>  * Return a pointer to the single buffer.
>  */
> unsigned char *
> us_copy_from_sgbuf(unsigned char *content, int len,
>                  int *index, int *offset, int use_sg) {
>       struct scatterlist *sg;
>       unsigned char *buffer;
>       int transferred, i;
> 
>       if (!use_sg)
>               return content;
> 
>       sg = (struct scatterlist *)content;
>       buffer = kmalloc(len, GFP_NOIO);
>       if (buffer == NULL)
>               return NULL;
> 
>       transferred = 0;
>       i = *index;
>       while (i < use_sg && transferred < len) {
>               unsigned char *ptr;
>               unsigned int length, room;
> 
>               ptr = page_address(sg[i].page) + sg[i].offset + *offset;
> 
>               room = sg[i].length - *offset;
>               length = len - transferred;
>               if (length > room)
>                       length = room;
> 
>               memcpy(buffer+transferred, ptr, length);
>               transferred += length;
>               *offset += length;
>               if (length == room) {
>                       i++;
>                       *offset = 0;
>               }
>       }
>       *index = i;
> 
>       return buffer;
> }
> 
> unsigned char *
> us_copy_from_sgbuf_all(unsigned char *content, int len, int use_sg) {
>       int index, offset;
> 
>       index = offset = 0;
>       return us_copy_from_sgbuf(content, len, &index, &offset, use_sg);
> }
> 
> /*
>  * Copy from a single buffer into a scatter-gather buffer,
>  * starting at a given index and offset.
>  * When done, update index and offset.
>  */
> void
> us_copy_to_sgbuf(unsigned char *buffer, int buflen,
>                void *content, int *index, int *offset, int use_sg) {
>       struct scatterlist *sg;
>       int i, transferred;
> 
>       if (!use_sg)
>               return;
> 
>       transferred = 0;
>       sg = content;
>       i = *index;
>       while (i < use_sg && transferred < buflen) {
>               unsigned char *ptr;
>               unsigned int length, room;
> 
>               ptr = page_address(sg[i].page) + sg[i].offset + *offset;
> 
>               room = sg[i].length - *offset;
>               length = buflen - transferred;
>               if (length > room)
>                       length = room;
>               
>               memcpy(ptr, buffer+transferred, length);
>               transferred += sg[i].length;
>               *offset += length;
>               if (length == room) {
>                       i++;
>                       *offset = 0;
>               }
>       }
>       *index = i;
> }
> 
> void
> us_copy_to_sgbuf_all(unsigned char *buffer, int buflen,
>                    void *content, int use_sg) {
>       int index, offset;
> 
>       index = offset = 0;
>       us_copy_to_sgbuf(buffer, buflen, content, &index, &offset, use_sg);
> }

-- 
Matthew Dharm                              Home: [EMAIL PROTECTED] 
Maintainer, Linux USB Mass Storage Driver

It's monday.  It must be monday.
                                        -- Greg
User Friendly, 5/4/1998

Attachment: msg06653/pgp00000.pgp
Description: PGP signature

Reply via email to