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
msg06653/pgp00000.pgp
Description: PGP signature
