diff -u --recursive --new-file ../linux-2.5.16/linux/drivers/usb/storage/Makefile ./linux/drivers/usb/storage/Makefile --- ../linux-2.5.16/linux/drivers/usb/storage/Makefile Sat May 18 16:25:57 2002 +++ ./linux/drivers/usb/storage/Makefile Sat May 18 21:57:33 2002 @@ -11,14 +11,14 @@ obj-$(CONFIG_USB_STORAGE) += usb-storage.o usb-storage-obj-$(CONFIG_USB_STORAGE_DEBUG) += debug.o -usb-storage-obj-$(CONFIG_USB_STORAGE_HP8200e) += shuttle_usbat.o -usb-storage-obj-$(CONFIG_USB_STORAGE_SDDR09) += sddr09.o -usb-storage-obj-$(CONFIG_USB_STORAGE_SDDR55) += sddr55.o +usb-storage-obj-$(CONFIG_USB_STORAGE_HP8200e) += shuttle_usbat.o raw_bulk.o +usb-storage-obj-$(CONFIG_USB_STORAGE_SDDR09) += sddr09.o raw_bulk.o +usb-storage-obj-$(CONFIG_USB_STORAGE_SDDR55) += sddr55.o raw_bulk.o usb-storage-obj-$(CONFIG_USB_STORAGE_FREECOM) += freecom.o usb-storage-obj-$(CONFIG_USB_STORAGE_DPCM) += dpcm.o usb-storage-obj-$(CONFIG_USB_STORAGE_ISD200) += isd200.o -usb-storage-obj-$(CONFIG_USB_STORAGE_DATAFAB) += datafab.o -usb-storage-obj-$(CONFIG_USB_STORAGE_JUMPSHOT) += jumpshot.o +usb-storage-obj-$(CONFIG_USB_STORAGE_DATAFAB) += datafab.o raw_bulk.o +usb-storage-obj-$(CONFIG_USB_STORAGE_JUMPSHOT) += jumpshot.o raw_bulk.o usb-storage-objs := scsiglue.o protocol.o transport.o usb.o \ initializers.o $(usb-storage-obj-y) diff -u --recursive --new-file ../linux-2.5.16/linux/drivers/usb/storage/datafab.c ./linux/drivers/usb/storage/datafab.c --- ../linux-2.5.16/linux/drivers/usb/storage/datafab.c Sat May 18 16:25:57 2002 +++ ./linux/drivers/usb/storage/datafab.c Sun May 19 17:28:28 2002 @@ -51,6 +51,7 @@ */ #include "transport.h" +#include "raw_bulk.h" #include "protocol.h" #include "usb.h" #include "debug.h" @@ -60,131 +61,48 @@ #include #include -extern int usb_stor_bulk_msg(struct us_data *us, void *data, int pipe, - unsigned int len, unsigned int *act_len); - -static int datafab_determine_lun(struct us_data *us, struct datafab_info *info); - - -static void datafab_dump_data(unsigned char *data, int len) -{ - unsigned char buf[80]; - int sofar = 0; - - if (!data) - return; - - memset(buf, 0, sizeof(buf)); - - for (sofar = 0; sofar < len; sofar++) { - sprintf(buf + strlen(buf), "%02x ", - ((unsigned int) data[sofar]) & 0xFF); - - if (sofar % 16 == 15) { - US_DEBUGP("datafab: %s\n", buf); - memset(buf, 0, sizeof(buf)); - } - } - - if (strlen(buf) != 0) - US_DEBUGP("datafab: %s\n", buf); -} - - -static int datafab_raw_bulk(int direction, - struct us_data *us, - unsigned char *data, - unsigned int len) -{ - int result; - int act_len; - 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("datafab_raw_bulk: EPIPE. clearing endpoint halt for" - " pipe 0x%x, stalled at %d bytes\n", pipe, act_len); - usb_stor_clear_halt(us, pipe); - } - - if (result) { - // NAK - that means we've retried a few times already - if (result == -ETIMEDOUT) { - US_DEBUGP("datafab_raw_bulk: device NAKed\n"); - return US_BULK_TRANSFER_FAILED; - } - - // -ENOENT -- we canceled this transfer - if (result == -ENOENT) { - US_DEBUGP("datafab_raw_bulk: transfer aborted\n"); - return US_BULK_TRANSFER_ABORTED; - } - - if (result == -EPIPE) { - US_DEBUGP("datafab_raw_bulk: output pipe stalled\n"); - return USB_STOR_TRANSPORT_FAILED; - } - - // the catch-all case - US_DEBUGP("datafab_raw_bulk: unknown error\n"); - return US_BULK_TRANSFER_FAILED; - } +static int datafab_determine_lun(struct us_data *us, + struct datafab_info *info); - if (act_len != len) { - US_DEBUGP("datafab_raw_bulk: Warning. Transferred only %d bytes\n", act_len); - return US_BULK_TRANSFER_SHORT; - } - US_DEBUGP("datafab_raw_bulk: Transfered %d of %d bytes\n", act_len, len); - return US_BULK_TRANSFER_GOOD; -} +static inline int +datafab_bulk_read(struct us_data *us, unsigned char *data, unsigned int len) { + unsigned int act_len; /* ignored */ -static inline int datafab_bulk_read(struct us_data *us, - unsigned char *data, - unsigned int len) -{ if (len == 0) return USB_STOR_TRANSPORT_GOOD; US_DEBUGP("datafab_bulk_read: len = %d\n", len); - return datafab_raw_bulk(SCSI_DATA_READ, us, data, len); + return usb_storage_raw_bulk(us, SCSI_DATA_READ, data, len, &act_len); } -static inline int datafab_bulk_write(struct us_data *us, - unsigned char *data, - unsigned int len) -{ +static inline int +datafab_bulk_write(struct us_data *us, unsigned char *data, unsigned int len) { + unsigned int act_len; /* ignored */ + if (len == 0) return USB_STOR_TRANSPORT_GOOD; US_DEBUGP("datafab_bulk_write: len = %d\n", len); - return datafab_raw_bulk(SCSI_DATA_WRITE, us, data, len); + return usb_storage_raw_bulk(us, SCSI_DATA_WRITE, data, len, &act_len); } static int datafab_read_data(struct us_data *us, - struct datafab_info *info, - u32 sector, - u32 sectors, - unsigned char *dest, - int use_sg) + struct datafab_info *info, + u32 sector, + u32 sectors, + unsigned char *dest, + int use_sg) { unsigned char command[8] = { 0, 0, 0, 0, 0, 0xE0, 0x20, 0x01 }; unsigned char *buffer = NULL; unsigned char *ptr; unsigned char thistime; - struct scatterlist *sg = NULL; int totallen, len, result; - int sg_idx = 0, current_sg_offset = 0; - int transferred, rc; + int sg_idx = 0, sg_offset = 0; + int rc; // we're working in LBA mode. according to the ATA spec, // we can support up to 28-bit addressing. I don't know if Datafab @@ -202,28 +120,17 @@ command[5] += (info->lun << 4); - // If we're using scatter-gather, we have to create a new - // buffer to read all of the data in first, since a - // scatter-gather buffer could in theory start in the middle - // of a page, which would be bad. A developer who wants a - // challenge might want to write a limited-buffer - // version of this code. - totallen = sectors * info->ssize; do { - // loop, never allocate or transfer more than 64k at once (min(128k, 255*info->ssize) is the real limit) + // loop, never allocate or transfer more than 64k at once + // (min(128k, 255*info->ssize) is the real limit) + len = min_t(int, totallen, 65536); - if (use_sg) { - sg = (struct scatterlist *) dest; - buffer = kmalloc(len, GFP_NOIO); - if (buffer == NULL) - return USB_STOR_TRANSPORT_ERROR; - ptr = buffer; - } else { - ptr = dest; - } + ptr = buffer = (use_sg ? kmalloc(len, GFP_NOIO) : dest); + if (buffer == NULL) + return USB_STOR_TRANSPORT_ERROR; thistime = (len / info->ssize) & 0xff; @@ -235,53 +142,22 @@ command[5] |= (sector >> 24) & 0x0F; - // send the command - US_DEBUGP("datafab_read_data: sending following command\n"); - datafab_dump_data(command, sizeof(command)); - + // send the read command result = datafab_bulk_write(us, command, sizeof(command)); - if (result != USB_STOR_TRANSPORT_GOOD) { - if (use_sg) - kfree(buffer); - return result; - } + if (result != USB_STOR_TRANSPORT_GOOD) + goto leave; // read the result result = datafab_bulk_read(us, ptr, len); - if (result != USB_STOR_TRANSPORT_GOOD) { - if (use_sg) - kfree(buffer); - return result; - } - - US_DEBUGP("datafab_read_data results: %d bytes\n", len); - // datafab_dump_data(ptr, len); + if (result != USB_STOR_TRANSPORT_GOOD) + goto leave; sectors -= thistime; sector += thistime; if (use_sg) { - transferred = 0; - while (sg_idx < use_sg && transferred < len) { - if (len - transferred >= sg[sg_idx].length - current_sg_offset) { - US_DEBUGP("datafab_read_data: adding %d bytes to %d byte sg buffer\n", sg[sg_idx].length - current_sg_offset, sg[sg_idx].length); - memcpy(page_address(sg[sg_idx].page) + sg[sg_idx].offset + current_sg_offset, - buffer + transferred, - sg[sg_idx].length - current_sg_offset); - transferred += sg[sg_idx].length - current_sg_offset; - current_sg_offset = 0; - // on to the next sg buffer - ++sg_idx; - } else { - US_DEBUGP("datafab_read_data: adding %d bytes to %d byte sg buffer\n", len - transferred, sg[sg_idx].length); - memcpy(page_address(sg[sg_idx].page) + sg[sg_idx].offset + current_sg_offset, - buffer + transferred, - len - transferred); - current_sg_offset += len - transferred; - // this sg buffer is only partially full and we're out of data to copy in - break; - } - } + us_copy_to_sgbuf(buffer, len, dest, + &sg_idx, &sg_offset, use_sg); kfree(buffer); } else { dest += len; @@ -291,25 +167,28 @@ } while (totallen > 0); return USB_STOR_TRANSPORT_GOOD; + + leave: + if (use_sg) + kfree(buffer); + return result; } static int datafab_write_data(struct us_data *us, - struct datafab_info *info, - u32 sector, - u32 sectors, - unsigned char *src, - int use_sg) + struct datafab_info *info, + u32 sector, + u32 sectors, + unsigned char *src, + int use_sg) { unsigned char command[8] = { 0, 0, 0, 0, 0, 0xE0, 0x30, 0x02 }; unsigned char reply[2] = { 0, 0 }; unsigned char *buffer = NULL; unsigned char *ptr; unsigned char thistime; - struct scatterlist *sg = NULL; - int totallen, len, result; - int sg_idx = 0, current_sg_offset = 0; - int transferred, rc; + int totallen, len, result, rc; + int sg_idx = 0, sg_offset = 0; // we're working in LBA mode. according to the ATA spec, // we can support up to 28-bit addressing. I don't know if Datafab @@ -337,44 +216,20 @@ totallen = sectors * info->ssize; do { - // loop, never allocate or transfer more than 64k at once (min(128k, 255*info->ssize) is the real limit) + // loop, never allocate or transfer more than 64k at once + // (min(128k, 255*info->ssize) is the real limit) + len = min_t(int, totallen, 65536); - if (use_sg) { - sg = (struct scatterlist *) src; - buffer = kmalloc(len, GFP_NOIO); - if (buffer == NULL) - return USB_STOR_TRANSPORT_ERROR; - ptr = buffer; - - memset(buffer, 0, len); - - // copy the data from the sg bufs into the big contiguous buf - // - transferred = 0; - while (transferred < len) { - if (len - transferred >= sg[sg_idx].length - current_sg_offset) { - US_DEBUGP("datafab_write_data: getting %d bytes from %d byte sg buffer\n", sg[sg_idx].length - current_sg_offset, sg[sg_idx].length); - memcpy(ptr + transferred, - page_address(sg[sg_idx].page) + sg[sg_idx].offset + current_sg_offset, - sg[sg_idx].length - current_sg_offset); - transferred += sg[sg_idx].length - current_sg_offset; - current_sg_offset = 0; - // on to the next sg buffer - ++sg_idx; - } else { - US_DEBUGP("datafab_write_data: getting %d bytes from %d byte sg buffer\n", len - transferred, sg[sg_idx].length); - memcpy(ptr + transferred, - page_address(sg[sg_idx].page) + sg[sg_idx].offset + current_sg_offset, - len - transferred); - current_sg_offset += len - transferred; - // we only copied part of this sg buffer - break; - } - } - } else { - ptr = src; - } + // if we are using scatter-gather, + // first copy all to one big buffer + + buffer = us_copy_from_sgbuf(src, len, &sg_idx, + &sg_offset, use_sg); + if (buffer == NULL) + return USB_STOR_TRANSPORT_ERROR; + + ptr = buffer; thistime = (len / info->ssize) & 0xff; @@ -387,64 +242,57 @@ command[5] |= (sector >> 24) & 0x0F; // send the command - US_DEBUGP("datafab_write_data: sending following command\n"); - datafab_dump_data(command, sizeof(command)); - result = datafab_bulk_write(us, command, sizeof(command)); - if (result != USB_STOR_TRANSPORT_GOOD) { - if (use_sg) - kfree(buffer); - return result; - } + if (result != USB_STOR_TRANSPORT_GOOD) + goto leave; // send the data result = datafab_bulk_write(us, ptr, len); - if (result != USB_STOR_TRANSPORT_GOOD) { - if (use_sg) - kfree(buffer); - return result; - } + if (result != USB_STOR_TRANSPORT_GOOD) + goto leave; // read the result result = datafab_bulk_read(us, reply, sizeof(reply)); - if (result != USB_STOR_TRANSPORT_GOOD) { - if (use_sg) - kfree(buffer); - return result; - } + if (result != USB_STOR_TRANSPORT_GOOD) + goto leave; if (reply[0] != 0x50 && reply[1] != 0) { - US_DEBUGP("datafab_write_data: Gah! write return code: %02x %02x\n", reply[0], reply[1]); - if (use_sg) - kfree(buffer); - return USB_STOR_TRANSPORT_ERROR; + US_DEBUGP("datafab_write_data: Gah! " + "write return code: %02x %02x\n", + reply[0], reply[1]); + result = USB_STOR_TRANSPORT_ERROR; + goto leave; } sectors -= thistime; sector += thistime; - if (use_sg) { + if (use_sg) kfree(buffer); - } else { + else src += len; - } totallen -= len; } while (totallen > 0); return USB_STOR_TRANSPORT_GOOD; + + leave: + if (use_sg) + kfree(buffer); + return result; } static int datafab_determine_lun(struct us_data *us, struct datafab_info *info) { - // dual-slot readers can be thought of as dual-LUN devices. we need to - // determine which card slot is being used. we'll send an IDENTIFY DEVICE - // command and see which LUN responds... - // - // there might be a better way of doing this? + // Dual-slot readers can be thought of as dual-LUN devices. + // We need to determine which card slot is being used. + // We'll send an IDENTIFY DEVICE command and see which LUN responds... // + // There might be a better way of doing this? + unsigned char command[8] = { 0, 1, 0, 0, 0, 0xa0, 0xec, 1 }; unsigned char buf[512]; int count = 0, rc; @@ -454,9 +302,9 @@ US_DEBUGP("datafab_determine_lun: locating...\n"); - // we'll try 10 times before giving up... + // we'll try 3 times before giving up... // - while (count++ < 10) { + while (count++ < 3) { command[5] = 0xa0; rc = datafab_bulk_write(us, command, 8); @@ -481,7 +329,7 @@ return USB_STOR_TRANSPORT_GOOD; } - wait_ms(20); + wait_ms(20); } return USB_STOR_TRANSPORT_FAILED; @@ -531,7 +379,7 @@ static int datafab_handle_mode_sense(struct us_data *us, Scsi_Cmnd * srb, - unsigned char *ptr, + unsigned char *ptr, int sense_6) { unsigned char mode_param_header[8] = { @@ -557,7 +405,7 @@ // datafab reader doesn't present a SCSI interface so we // fudge the SCSI commands... // - + if (sense_6) param_len = srb->cmnd[4]; else @@ -676,7 +524,8 @@ if (!us->extra) { us->extra = kmalloc(sizeof(struct datafab_info), GFP_NOIO); if (!us->extra) { - US_DEBUGP("datafab_transport: Gah! Can't allocate storage for Datafab info struct!\n"); + US_DEBUGP("datafab_transport: Gah! " + "Can't allocate storage for Datafab info struct!\n"); return USB_STOR_TRANSPORT_ERROR; } memset(us->extra, 0, sizeof(struct datafab_info)); @@ -728,7 +577,7 @@ // if (srb->cmnd[0] == READ_10) { block = ((u32)(srb->cmnd[2]) << 24) | ((u32)(srb->cmnd[3]) << 16) | - ((u32)(srb->cmnd[4]) << 8) | ((u32)(srb->cmnd[5])); + ((u32)(srb->cmnd[4]) << 8) | ((u32)(srb->cmnd[5])); blocks = ((u32)(srb->cmnd[7]) << 8) | ((u32)(srb->cmnd[8])); @@ -740,10 +589,10 @@ // we'll probably never see a READ_12 but we'll do it anyway... // block = ((u32)(srb->cmnd[2]) << 24) | ((u32)(srb->cmnd[3]) << 16) | - ((u32)(srb->cmnd[4]) << 8) | ((u32)(srb->cmnd[5])); + ((u32)(srb->cmnd[4]) << 8) | ((u32)(srb->cmnd[5])); blocks = ((u32)(srb->cmnd[6]) << 24) | ((u32)(srb->cmnd[7]) << 16) | - ((u32)(srb->cmnd[8]) << 8) | ((u32)(srb->cmnd[9])); + ((u32)(srb->cmnd[8]) << 8) | ((u32)(srb->cmnd[9])); US_DEBUGP("datafab_transport: READ_12: read block 0x%04lx count %ld\n", block, blocks); return datafab_read_data(us, info, block, blocks, ptr, srb->use_sg); @@ -751,7 +600,7 @@ if (srb->cmnd[0] == WRITE_10) { block = ((u32)(srb->cmnd[2]) << 24) | ((u32)(srb->cmnd[3]) << 16) | - ((u32)(srb->cmnd[4]) << 8) | ((u32)(srb->cmnd[5])); + ((u32)(srb->cmnd[4]) << 8) | ((u32)(srb->cmnd[5])); blocks = ((u32)(srb->cmnd[7]) << 8) | ((u32)(srb->cmnd[8])); @@ -763,10 +612,10 @@ // we'll probably never see a WRITE_12 but we'll do it anyway... // block = ((u32)(srb->cmnd[2]) << 24) | ((u32)(srb->cmnd[3]) << 16) | - ((u32)(srb->cmnd[4]) << 8) | ((u32)(srb->cmnd[5])); + ((u32)(srb->cmnd[4]) << 8) | ((u32)(srb->cmnd[5])); blocks = ((u32)(srb->cmnd[6]) << 24) | ((u32)(srb->cmnd[7]) << 16) | - ((u32)(srb->cmnd[8]) << 8) | ((u32)(srb->cmnd[9])); + ((u32)(srb->cmnd[8]) << 8) | ((u32)(srb->cmnd[9])); US_DEBUGP("datafab_transport: WRITE_12: write block 0x%04lx count %ld\n", block, blocks); return datafab_write_data(us, info, block, blocks, ptr, srb->use_sg); @@ -825,8 +674,9 @@ srb->result = CHECK_CONDITION << 1; } return rc; - } + } - US_DEBUGP("datafab_transport: Gah! Unknown command: %d (0x%x)\n", srb->cmnd[0], srb->cmnd[0]); + US_DEBUGP("datafab_transport: Gah! Unknown command: %d (0x%x)\n", + srb->cmnd[0], srb->cmnd[0]); return USB_STOR_TRANSPORT_ERROR; } diff -u --recursive --new-file ../linux-2.5.16/linux/drivers/usb/storage/jumpshot.c ./linux/drivers/usb/storage/jumpshot.c --- ../linux-2.5.16/linux/drivers/usb/storage/jumpshot.c Sat May 18 16:25:57 2002 +++ ./linux/drivers/usb/storage/jumpshot.c Sun May 19 17:26:26 2002 @@ -48,6 +48,7 @@ */ #include "transport.h" +#include "raw_bulk.h" #include "protocol.h" #include "usb.h" #include "debug.h" @@ -57,176 +58,31 @@ #include #include -extern int usb_stor_control_msg(struct us_data *us, unsigned int pipe, - u8 request, u8 requesttype, u16 value, - u16 index, void *data, u16 size); -extern int usb_stor_bulk_msg(struct us_data *us, void *data, int pipe, - unsigned int len, unsigned int *act_len); - -#if 0 -static void jumpshot_dump_data(unsigned char *data, int len) -{ - unsigned char buf[80]; - int sofar = 0; - - if (!data) - return; - - memset(buf, 0, sizeof(buf)); - - for (sofar = 0; sofar < len; sofar++) { - sprintf(buf + strlen(buf), "%02x ", - ((unsigned int) data[sofar]) & 0xFF); - - if (sofar % 16 == 15) { - US_DEBUGP("jumpshot: %s\n", buf); - memset(buf, 0, sizeof(buf)); - } - } - - if (strlen(buf) != 0) - US_DEBUGP("jumpshot: %s\n", buf); -} -#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. - * - * This routine snarfed from the SanDisk SDDR-09 driver - * - */ -static int jumpshot_send_control(struct us_data *us, - int pipe, - unsigned char request, - unsigned char requesttype, - unsigned short value, - unsigned short index, - unsigned char *xfer_data, - unsigned int xfer_len) -{ - int result; - - // Send the URB to the device and wait for a response. - - /* 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); - - // 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("jumpshot_send_control: -- Stall on control pipe. Clearing\n"); - result = usb_stor_clear_halt(us, pipe); - US_DEBUGP("jumpshot_send_control: -- usb_stor_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; -} - - -static int jumpshot_raw_bulk(int direction, - struct us_data *us, - unsigned char *data, - unsigned int len) -{ - int result; - int act_len; - 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("jumpshot_raw_bulk: EPIPE. clearing endpoint halt for" - " pipe 0x%x, stalled at %d bytes\n", pipe, act_len); - usb_stor_clear_halt(us, pipe); - } - - if (result) { - // NAK - that means we've retried a few times already - if (result == -ETIMEDOUT) { - US_DEBUGP("jumpshot_raw_bulk: device NAKed\n"); - return US_BULK_TRANSFER_FAILED; - } - - // -ENOENT -- we canceled this transfer - if (result == -ENOENT) { - US_DEBUGP("jumpshot_raw_bulk: transfer aborted\n"); - return US_BULK_TRANSFER_ABORTED; - } - - if (result == -EPIPE) { - US_DEBUGP("jumpshot_raw_bulk: output pipe stalled\n"); - return USB_STOR_TRANSPORT_FAILED; - } - - // the catch-all case - US_DEBUGP("jumpshot_raw_bulk: unknown error\n"); - return US_BULK_TRANSFER_FAILED; - } - - if (act_len != len) { - US_DEBUGP("jumpshot_raw_bulk: Warning. Transferred only %d bytes\n", act_len); - return US_BULK_TRANSFER_SHORT; - } - - US_DEBUGP("jumpshot_raw_bulk: Transferred %d of %d bytes\n", act_len, len); - return US_BULK_TRANSFER_GOOD; -} - static inline int jumpshot_bulk_read(struct us_data *us, - unsigned char *data, - unsigned int len) + unsigned char *data, + unsigned int len) { + unsigned int act_len; /* ignored */ + if (len == 0) return USB_STOR_TRANSPORT_GOOD; US_DEBUGP("jumpshot_bulk_read: len = %d\n", len); - return jumpshot_raw_bulk(SCSI_DATA_READ, us, data, len); + return usb_storage_raw_bulk(us, SCSI_DATA_READ, data, len, &act_len); } static inline int jumpshot_bulk_write(struct us_data *us, - unsigned char *data, - unsigned int len) + unsigned char *data, + unsigned int len) { + unsigned int act_len; /* ignored */ + if (len == 0) return USB_STOR_TRANSPORT_GOOD; US_DEBUGP("jumpshot_bulk_write: len = %d\n", len); - return jumpshot_raw_bulk(SCSI_DATA_WRITE, us, data, len); + return usb_storage_raw_bulk(us, SCSI_DATA_WRITE, data, len, &act_len); } @@ -239,7 +95,7 @@ return USB_STOR_TRANSPORT_ERROR; // send the setup - rc = jumpshot_send_control(us, + rc = usb_storage_send_control(us, usb_rcvctrlpipe(us->pusb_dev, 0), 0, 0xA0, 0, 7, &reply, 1); @@ -256,53 +112,44 @@ } static int jumpshot_read_data(struct us_data *us, - struct jumpshot_info *info, - u32 sector, - u32 sectors, - unsigned char *dest, - int use_sg) + struct jumpshot_info *info, + u32 sector, + u32 sectors, + unsigned char *dest, + int use_sg) { unsigned char command[] = { 0, 0, 0, 0, 0, 0xe0, 0x20 }; unsigned char *buffer = NULL; unsigned char *ptr; unsigned char thistime; - struct scatterlist *sg = NULL; - int totallen, len, result; - int sg_idx = 0, current_sg_offset = 0; - int transferred; - - // we're working in LBA mode. according to the ATA spec, - // we can support up to 28-bit addressing. I don't know if Jumpshot - // supports beyond 24-bit addressing. It's kind of hard to test - // since it requires > 8GB CF card. - // + int totallen, len, result; + int sg_idx = 0, current_sg_offset = 0; + + // we're working in LBA mode. according to the ATA spec, + // we can support up to 28-bit addressing. I don't know if Jumpshot + // supports beyond 24-bit addressing. It's kind of hard to test + // since it requires > 8GB CF card. + if (sector > 0x0FFFFFFF) return USB_STOR_TRANSPORT_ERROR; - // If we're using scatter-gather, we have to create a new - // buffer to read all of the data in first, since a - // scatter-gather buffer could in theory start in the middle - // of a page, which would be bad. A developer who wants a - // challenge might want to write a limited-buffer - // version of this code. - totallen = sectors * info->ssize; do { - // loop, never allocate or transfer more than 64k at once (min(128k, 255*info->ssize) is the real limit) - len = min_t(int, totallen, 65536); - - if (use_sg) { - sg = (struct scatterlist *) dest; - buffer = kmalloc(len, GFP_NOIO); - if (buffer == NULL) - return USB_STOR_TRANSPORT_ERROR; - ptr = buffer; - } else { - ptr = dest; - } + // loop, never allocate or transfer more than 64k at once + // (min(128k, 255*info->ssize) is the real limit) + len = min_t(int, totallen, 65536); + + if (use_sg) { + buffer = kmalloc(len, GFP_NOIO); + if (buffer == NULL) + return USB_STOR_TRANSPORT_ERROR; + ptr = buffer; + } else { + ptr = dest; + } - thistime = (len / info->ssize) & 0xff; + thistime = (len / info->ssize) & 0xff; command[0] = 0; command[1] = thistime; @@ -313,137 +160,83 @@ command[5] |= (sector >> 24) & 0x0F; // send the setup + command - result = jumpshot_send_control(us, + result = usb_storage_send_control(us, usb_sndctrlpipe(us->pusb_dev, 0), 0, 0x20, 0, 1, command, 7); - if (result != USB_STOR_TRANSPORT_GOOD) { - if (use_sg) - kfree(buffer); - return result; - } + if (result != USB_STOR_TRANSPORT_GOOD) + goto leave; // read the result result = jumpshot_bulk_read(us, ptr, len); - if (result != USB_STOR_TRANSPORT_GOOD) { - if (use_sg) - kfree(buffer); - return result; - } + if (result != USB_STOR_TRANSPORT_GOOD) + goto leave; US_DEBUGP("jumpshot_read_data: %d bytes\n", len); - //jumpshot_dump_data(ptr, len); sectors -= thistime; sector += thistime; - if (use_sg) { - transferred = 0; - while (sg_idx < use_sg && transferred < len) { - if (len - transferred >= sg[sg_idx].length - current_sg_offset) { - US_DEBUGP("jumpshot_read_data: adding %d bytes to %d byte sg buffer\n", sg[sg_idx].length - current_sg_offset, sg[sg_idx].length); - memcpy(page_address(sg[sg_idx].page) + sg[sg_idx].offset + current_sg_offset, - buffer + transferred, - sg[sg_idx].length - current_sg_offset); - transferred += sg[sg_idx].length - current_sg_offset; - current_sg_offset = 0; - // on to the next sg buffer - ++sg_idx; - } else { - US_DEBUGP("jumpshot_read_data: adding %d bytes to %d byte sg buffer\n", len - transferred, sg[sg_idx].length); - memcpy(page_address(sg[sg_idx].page) + sg[sg_idx].offset + current_sg_offset, - buffer + transferred, - len - transferred); - current_sg_offset += len - transferred; - // this sg buffer is only partially full and we're out of data to copy in - break; - } - } - kfree(buffer); - } else { - dest += len; - } + if (use_sg) { + us_copy_to_sgbuf(buffer, len, dest, + &sg_idx, ¤t_sg_offset, use_sg); + kfree(buffer); + } else { + dest += len; + } - totallen -= len; - } while (totallen > 0); + totallen -= len; + } while (totallen > 0); return USB_STOR_TRANSPORT_GOOD; + + leave: + if (use_sg) + kfree(buffer); + return result; } static int jumpshot_write_data(struct us_data *us, - struct jumpshot_info *info, + struct jumpshot_info *info, u32 sector, u32 sectors, - unsigned char *src, - int use_sg) + unsigned char *src, + int use_sg) { unsigned char command[7] = { 0, 0, 0, 0, 0, 0xE0, 0x30 }; unsigned char *buffer = NULL; unsigned char *ptr; unsigned char thistime; - struct scatterlist *sg = NULL; - int totallen, len, result, waitcount; - int sg_idx = 0, current_sg_offset = 0; - int transferred; - - // we're working in LBA mode. according to the ATA spec, - // we can support up to 28-bit addressing. I don't know if Jumpshot - // supports beyond 24-bit addressing. It's kind of hard to test - // since it requires > 8GB CF card. - // + int totallen, len, result, waitcount; + int sg_idx = 0, sg_offset = 0; + + // we're working in LBA mode. according to the ATA spec, + // we can support up to 28-bit addressing. I don't know if Jumpshot + // supports beyond 24-bit addressing. It's kind of hard to test + // since it requires > 8GB CF card. + // if (sector > 0x0FFFFFFF) return USB_STOR_TRANSPORT_ERROR; - // If we're using scatter-gather, we have to create a new - // buffer to read all of the data in first, since a - // scatter-gather buffer could in theory start in the middle - // of a page, which would be bad. A developer who wants a - // challenge might want to write a limited-buffer - // version of this code. - totallen = sectors * info->ssize; do { - // loop, never allocate or transfer more than 64k at once (min(128k, 255*info->ssize) is the real limit) - len = min_t(int, totallen, 65536); + // loop, never allocate or transfer more than 64k at once + // (min(128k, 255*info->ssize) is the real limit) + + len = min_t(int, totallen, 65536); + + // if we are using scatter-gather, + // first copy all to one big buffer - if (use_sg) { - sg = (struct scatterlist *) src; - buffer = kmalloc(len, GFP_NOIO); - if (buffer == NULL) - return USB_STOR_TRANSPORT_ERROR; - ptr = buffer; - - memset(buffer, 0, len); - - // copy the data from the sg bufs into the big contiguous buf - // - transferred = 0; - while (transferred < len) { - if (len - transferred >= sg[sg_idx].length - current_sg_offset) { - US_DEBUGP("jumpshot_write_data: getting %d bytes from %d byte sg buffer\n", sg[sg_idx].length - current_sg_offset, sg[sg_idx].length); - memcpy(ptr + transferred, - page_address(sg[sg_idx].page) + sg[sg_idx].offset + current_sg_offset, - sg[sg_idx].length - current_sg_offset); - transferred += sg[sg_idx].length - current_sg_offset; - current_sg_offset = 0; - // on to the next sg buffer - ++sg_idx; - } else { - US_DEBUGP("jumpshot_write_data: getting %d bytes from %d byte sg buffer\n", len - transferred, sg[sg_idx].length); - memcpy(ptr + transferred, - page_address(sg[sg_idx].page) + sg[sg_idx].offset + current_sg_offset, - len - transferred); - current_sg_offset += len - transferred; - // we only copied part of this sg buffer - break; - } - } - } else { - ptr = src; - } + buffer = us_copy_from_sgbuf(src, len, &sg_idx, + &sg_offset, use_sg); + if (buffer == NULL) + return USB_STOR_TRANSPORT_ERROR; + + ptr = buffer; - thistime = (len / info->ssize) & 0xff; + thistime = (len / info->ssize) & 0xff; command[0] = 0; command[1] = thistime; @@ -454,21 +247,18 @@ command[5] |= (sector >> 24) & 0x0F; // send the setup + command - result = jumpshot_send_control(us, - usb_sndctrlpipe(us->pusb_dev, 0), - 0, 0x20, 0, 1, command, 7); + result = usb_storage_send_control( + us, usb_sndctrlpipe(us->pusb_dev, 0), + 0, 0x20, 0, 1, command, 7); // send the data result = jumpshot_bulk_write(us, ptr, len); - if (result != USB_STOR_TRANSPORT_GOOD) { - if (use_sg) - kfree(buffer); - return result; - } + if (result != USB_STOR_TRANSPORT_GOOD) + goto leave; - // read the result. apparently the bulk write can complete before the - // jumpshot drive is finished writing. so we loop here until we - // get a good return code + // read the result. apparently the bulk write can complete + // before the jumpshot drive is finished writing. so we loop + // here until we get a good return code waitcount = 0; do { result = jumpshot_get_status(us); @@ -485,20 +275,24 @@ sectors -= thistime; sector += thistime; - if (use_sg) { - kfree(buffer); - } else { - src += len; - } + if (use_sg) + kfree(buffer); + else + src += len; + + totallen -= len; + } while (totallen > 0); - totallen -= len; - } while (totallen > 0); + return result; + leave: + if (use_sg) + kfree(buffer); return result; } static int jumpshot_id_device(struct us_data *us, - struct jumpshot_info *info) + struct jumpshot_info *info) { unsigned char command[2] = { 0xe0, 0xec }; unsigned char reply[512]; @@ -508,12 +302,13 @@ return USB_STOR_TRANSPORT_ERROR; // send the setup - rc = jumpshot_send_control(us, + rc = usb_storage_send_control(us, usb_sndctrlpipe(us->pusb_dev, 0), 0, 0x20, 0, 6, command, 2); if (rc != USB_STOR_TRANSPORT_GOOD) { - US_DEBUGP("jumpshot_id_device: Gah! send_control for read_capacity failed\n"); + US_DEBUGP("jumpshot_id_device: Gah! " + "send_control for read_capacity failed\n"); return rc; } @@ -532,8 +327,8 @@ static int jumpshot_handle_mode_sense(struct us_data *us, Scsi_Cmnd * srb, - unsigned char *ptr, - int sense_6) + unsigned char *ptr, + int sense_6) { unsigned char mode_param_header[8] = { 0, 0, 0, 0, 0, 0, 0, 0 @@ -730,7 +525,7 @@ if (srb->cmnd[0] == READ_10) { block = ((u32)(srb->cmnd[2]) << 24) | ((u32)(srb->cmnd[3]) << 16) | - ((u32)(srb->cmnd[4]) << 8) | ((u32)(srb->cmnd[5])); + ((u32)(srb->cmnd[4]) << 8) | ((u32)(srb->cmnd[5])); blocks = ((u32)(srb->cmnd[7]) << 8) | ((u32)(srb->cmnd[8])); @@ -742,10 +537,10 @@ // I don't think we'll ever see a READ_12 but support it anyway... // block = ((u32)(srb->cmnd[2]) << 24) | ((u32)(srb->cmnd[3]) << 16) | - ((u32)(srb->cmnd[4]) << 8) | ((u32)(srb->cmnd[5])); + ((u32)(srb->cmnd[4]) << 8) | ((u32)(srb->cmnd[5])); blocks = ((u32)(srb->cmnd[6]) << 24) | ((u32)(srb->cmnd[7]) << 16) | - ((u32)(srb->cmnd[8]) << 8) | ((u32)(srb->cmnd[9])); + ((u32)(srb->cmnd[8]) << 8) | ((u32)(srb->cmnd[9])); US_DEBUGP("jumpshot_transport: READ_12: read block 0x%04lx count %ld\n", block, blocks); return jumpshot_read_data(us, info, block, blocks, ptr, srb->use_sg); @@ -753,7 +548,7 @@ if (srb->cmnd[0] == WRITE_10) { block = ((u32)(srb->cmnd[2]) << 24) | ((u32)(srb->cmnd[3]) << 16) | - ((u32)(srb->cmnd[4]) << 8) | ((u32)(srb->cmnd[5])); + ((u32)(srb->cmnd[4]) << 8) | ((u32)(srb->cmnd[5])); blocks = ((u32)(srb->cmnd[7]) << 8) | ((u32)(srb->cmnd[8])); @@ -765,10 +560,10 @@ // I don't think we'll ever see a WRITE_12 but support it anyway... // block = ((u32)(srb->cmnd[2]) << 24) | ((u32)(srb->cmnd[3]) << 16) | - ((u32)(srb->cmnd[4]) << 8) | ((u32)(srb->cmnd[5])); + ((u32)(srb->cmnd[4]) << 8) | ((u32)(srb->cmnd[5])); blocks = ((u32)(srb->cmnd[6]) << 24) | ((u32)(srb->cmnd[7]) << 16) | - ((u32)(srb->cmnd[8]) << 8) | ((u32)(srb->cmnd[9])); + ((u32)(srb->cmnd[8]) << 8) | ((u32)(srb->cmnd[9])); US_DEBUGP("jumpshot_transport: WRITE_12: write block 0x%04lx count %ld\n", block, blocks); return jumpshot_write_data(us, info, block, blocks, ptr, srb->use_sg); @@ -824,8 +619,9 @@ srb->result = CHECK_CONDITION << 1; } return rc; - } + } - US_DEBUGP("jumpshot_transport: Gah! Unknown command: %d (0x%x)\n", srb->cmnd[0], srb->cmnd[0]); + US_DEBUGP("jumpshot_transport: Gah! Unknown command: %d (0x%x)\n", + srb->cmnd[0], srb->cmnd[0]); return USB_STOR_TRANSPORT_ERROR; } diff -u --recursive --new-file ../linux-2.5.16/linux/drivers/usb/storage/raw_bulk.c ./linux/drivers/usb/storage/raw_bulk.c --- ../linux-2.5.16/linux/drivers/usb/storage/raw_bulk.c Thu Jan 1 01:00:00 1970 +++ ./linux/drivers/usb/storage/raw_bulk.c Sun May 19 16:06:01 2002 @@ -0,0 +1,337 @@ +/* + * 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. + + /* 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); + + + // 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_stor_clear_halt(us, pipe); + US_DEBUGP("-- usb_stor_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_stor_clear_halt(us, 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 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 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); +} diff -u --recursive --new-file ../linux-2.5.16/linux/drivers/usb/storage/raw_bulk.h ./linux/drivers/usb/storage/raw_bulk.h --- ../linux-2.5.16/linux/drivers/usb/storage/raw_bulk.h Thu Jan 1 01:00:00 1970 +++ ./linux/drivers/usb/storage/raw_bulk.h Sun May 19 16:06:30 2002 @@ -0,0 +1,35 @@ +#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 diff -u --recursive --new-file ../linux-2.5.16/linux/drivers/usb/storage/scsiglue.c ./linux/drivers/usb/storage/scsiglue.c --- ../linux-2.5.16/linux/drivers/usb/storage/scsiglue.c Sat May 18 16:25:57 2002 +++ ./linux/drivers/usb/storage/scsiglue.c Sun May 19 17:05:30 2002 @@ -255,7 +255,7 @@ /* FIXME: This needs to lock out driver probing while it's working * or we can have race conditions */ /* Is that still true? I don't see how... AS */ - for (i = 0; i < pusb_dev_save->actconfig->bNumInterfaces; i++) { + for (i = 0; i < pusb_dev_save->actconfig->bNumInterfaces; i++) { struct usb_interface *intf = &pusb_dev_save->actconfig->interface[i]; const struct usb_device_id *id; @@ -560,11 +560,11 @@ /* copy one byte */ { - char *src = page_address(sg[sb].page) + sg[sb].offset + si; - char *dst = page_address(sg[db].page) + sg[db].offset + di; + char *src = page_address(sg[sb].page) + sg[sb].offset + si; + char *dst = page_address(sg[db].page) + sg[db].offset + di; - *dst = *src; - } + *dst = *src; + } /* get next destination */ if ( sg[db].length-1 == di ) @@ -753,11 +753,11 @@ /* copy one byte */ { - char *src = page_address(sg[sb].page) + sg[sb].offset + si; - char *dst = page_address(sg[db].page) + sg[db].offset + di; + char *src = page_address(sg[sb].page) + sg[sb].offset + si; + char *dst = page_address(sg[db].page) + sg[db].offset + di; - *dst = *src; - } + *dst = *src; + } /* get next destination */ if ( di == 0 ) @@ -794,11 +794,11 @@ break; } - { - char *dst = page_address(sg[db].page) + sg[db].offset + di; + { + char *dst = page_address(sg[db].page) + sg[db].offset + di; - *dst = tempBuffer[element-USB_STOR_SCSI_SENSE_HDRSZ]; - } + *dst = tempBuffer[element-USB_STOR_SCSI_SENSE_HDRSZ]; + } /* get next destination */ @@ -852,14 +852,14 @@ the6->array[element] = page_address(sg[i].page) + sg[i].offset + j; the10->array[element] = page_address(sg[i].page) + - sg[i].offset + j; + sg[i].offset + j; } else if ( element < USB_STOR_SCSI_SENSE_10_HDRSZ ) { /* only the longer headers still cares now */ the10->array[element] = page_address(sg[i].page) + - sg[i].offset + j; + sg[i].offset + j; } /* increase element counter */ diff -u --recursive --new-file ../linux-2.5.16/linux/drivers/usb/storage/sddr09.c ./linux/drivers/usb/storage/sddr09.c --- ../linux-2.5.16/linux/drivers/usb/storage/sddr09.c Sat May 18 16:25:57 2002 +++ ./linux/drivers/usb/storage/sddr09.c Sun May 19 17:27:13 2002 @@ -28,6 +28,7 @@ */ #include "transport.h" +#include "raw_bulk.h" #include "protocol.h" #include "usb.h" #include "debug.h" @@ -215,67 +216,6 @@ static int erase_bad_lba_entries = 0; -/* - * 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. - * - */ - -static int -sddr09_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. - - /* 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); - - - // 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_stor_clear_halt(us, pipe); - US_DEBUGP("-- usb_stor_clear_halt() returns %d\n", result); - return USB_STOR_TRANSPORT_FAILED; - } - - return USB_STOR_TRANSPORT_ERROR; - } - - return USB_STOR_TRANSPORT_GOOD; -} - /* send vendor interface command (0x41) */ /* called for requests 0, 1, 8 */ static int @@ -294,7 +234,7 @@ else pipe = usb_sndctrlpipe(us->pusb_dev,0); - return sddr09_send_control(us, pipe, request, requesttype, + return usb_storage_send_control(us, pipe, request, requesttype, 0, 0, xfer_data, xfer_len); } @@ -305,135 +245,6 @@ return sddr09_send_command(us, 0, USB_DIR_OUT, command, command_len); } -static int -sddr09_raw_bulk(struct us_data *us, int direction, - unsigned char *data, unsigned int len) { - - int result; - int act_len; - 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_stor_clear_halt(us, pipe); - } - - if (result) { - /* -ENOENT -- we canceled this transfer */ - if (result == -ENOENT) { - US_DEBUGP("usbat_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("usbat_raw_bulk(): device NAKed\n"); - else if (result == -EOVERFLOW) - US_DEBUGP("us_transfer_partial(): babble/overflow\n"); - else if (result != -EPIPE) - US_DEBUGP("us_transfer_partial(): 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; - } - - return US_BULK_TRANSFER_GOOD; -} - -static int -sddr09_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; - char string[64]; - -#define DEBUG_PRCT 12 - - if (len == 0) - return USB_STOR_TRANSPORT_GOOD; - - if (direction == SCSI_DATA_WRITE && !use_sg) { - - /* Debug-print the first N bytes of the write transfer */ - - strcpy(string, "wr: "); - for (i=0; i sg[i].length) - length = sg[i].length; - - result = sddr09_raw_bulk(us, direction, buf, length); - if (result != US_BULK_TRANSFER_GOOD) - break; - transferred += sg[i].length; - } - } - - if (direction == SCSI_DATA_READ && !use_sg) { - - /* Debug-print the first N bytes of the read transfer */ - - strcpy(string, "rd: "); - for (i=0; ipagesize; - if (use_sg) { - sg = (struct scatterlist *)content; - buffer = kmalloc(len, GFP_NOIO); - if (buffer == NULL) - return USB_STOR_TRANSPORT_ERROR; - ptr = buffer; - } else - ptr = content; + buffer = (use_sg ? kmalloc(len, GFP_NOIO) : content); + if (buffer == NULL) + return USB_STOR_TRANSPORT_ERROR; + + ptr = buffer; // Figure out the initial LBA and page lba = address >> info->blockshift; @@ -913,23 +721,8 @@ ptr += (pages << info->pageshift); } - if (use_sg && result == USB_STOR_TRANSPORT_GOOD) { - int transferred = 0; - - for (i=0; i sg[i].length) - length = sg[i].length; - - memcpy(buf, buffer+transferred, length); - transferred += sg[i].length; - } - } + if (use_sg && result == USB_STOR_TRANSPORT_GOOD) + us_copy_to_sgbuf_all(buffer, len, content, use_sg); if (use_sg) kfree(buffer); @@ -1080,50 +873,20 @@ unsigned int lba, page, pages; unsigned char *buffer = NULL; unsigned char *ptr; - struct scatterlist *sg = NULL; - int result, i, len; - - // If we're using scatter-gather, we have to create a new - // buffer to write all of the data in first, since a - // scatter-gather buffer could in theory start in the middle - // of a page, which would be bad. A developer who wants a - // challenge might want to write a limited-buffer - // version of this code. + int result, len; len = sectors*info->pagesize; - if (use_sg) { - int transferred = 0; - - sg = (struct scatterlist *)content; - buffer = kmalloc(len, GFP_NOIO); - if (buffer == NULL) - return USB_STOR_TRANSPORT_ERROR; - - for (i=0; i sg[i].length) - length = sg[i].length; + buffer = us_copy_from_sgbuf_all(content, len, use_sg); + if (buffer == NULL) + return USB_STOR_TRANSPORT_ERROR; - memcpy(buffer+transferred, buf, length); - transferred += sg[i].length; - } - ptr = buffer; - } else - ptr = content; + ptr = buffer; // Figure out the initial LBA and page lba = address >> info->blockshift; page = (address & info->blockmask); - // This could be made much more efficient by checking for - // contiguous LBA's. Another exercise left to the student. - result = USB_STOR_TRANSPORT_GOOD; while (sectors > 0) { @@ -1185,7 +948,7 @@ if (result != USB_STOR_TRANSPORT_GOOD) return result; - result = sddr09_bulk_transport(us, SCSI_DATA_READ, content, 64, 0); + result = usb_storage_bulk_transport(us, SCSI_DATA_READ, content, 64, 0); for (i = 0; i < 4; i++) deviceID[i] = content[i]; @@ -1792,7 +1555,7 @@ "sending" : "receiving", srb->request_bufflen); - result = sddr09_bulk_transport(us, + result = usb_storage_bulk_transport(us, srb->sc_data_direction, srb->request_buffer, srb->request_bufflen, diff -u --recursive --new-file ../linux-2.5.16/linux/drivers/usb/storage/sddr55.c ./linux/drivers/usb/storage/sddr55.c --- ../linux-2.5.16/linux/drivers/usb/storage/sddr55.c Sat May 18 16:25:57 2002 +++ ./linux/drivers/usb/storage/sddr55.c Sun May 19 17:04:05 2002 @@ -25,6 +25,7 @@ */ #include "transport.h" +#include "raw_bulk.h" #include "protocol.h" #include "usb.h" #include "debug.h" @@ -70,142 +71,16 @@ #define CIS_BLOCK 0x400 #define UNUSED_BLOCK 0x3ff - - -static int sddr55_raw_bulk(struct us_data *us, - int direction, - unsigned char *data, - unsigned int len) { - - int result; - int act_len; - 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); - } - - if (result) { - - /* NAK - that means we've retried a few times already */ - if (result == -ETIMEDOUT) { - US_DEBUGP("usbat_raw_bulk():" - " device NAKed\n"); - - return US_BULK_TRANSFER_FAILED; - } - - /* -ENOENT -- we canceled this transfer */ - if (result == -ENOENT) { - US_DEBUGP("usbat_raw_bulk():" - " transfer aborted\n"); - return US_BULK_TRANSFER_ABORTED; - } - - if (result == -EPIPE) { - US_DEBUGP("usbat_raw_bulk():" - " output pipe stalled\n"); - return US_BULK_TRANSFER_FAILED; - } - - /* the catch-all case */ - US_DEBUGP("us_transfer_partial(): unknown error\n"); - return US_BULK_TRANSFER_FAILED; - } - - if (act_len != len) { - US_DEBUGP("Warning: Transferred only %d bytes\n", - act_len); - return US_BULK_TRANSFER_SHORT; - } - - US_DEBUGP("Transferred %d of %d bytes\n", act_len, len); - - return US_BULK_TRANSFER_GOOD; -} - -/* - * Note: direction must be set if command_len == 0. - */ - -static int sddr55_bulk_transport(struct us_data *us, - int direction, - unsigned char *data, - unsigned int len) { - - int result = USB_STOR_TRANSPORT_GOOD; +static int +sddr55_bulk_transport(struct us_data *us, int direction, + unsigned char *data, unsigned int len) { struct sddr55_card_info *info = (struct sddr55_card_info *)us->extra; - if (len==0) - return USB_STOR_TRANSPORT_GOOD; - - info->last_access = jiffies; - -#ifdef CONFIG_USB_STORAGE_DEBUG - if (direction == SCSI_DATA_WRITE) { - int i; - char string[64]; - - /* Debug-print the first 48 bytes of the write transfer */ - - strcpy(string, "wr: "); - for (i=0; ilast_access = jiffies; + return usb_storage_bulk_transport(us, direction, data, len, 0); } - /* check if card inserted, if there is, update read_only status * return non zero if no card */ @@ -278,7 +153,7 @@ unsigned char *content, int use_sg) { - int result; + int result = USB_STOR_TRANSPORT_GOOD; unsigned char command[8] = { 0, 0, 0, 0, 0, 0xb0, 0, 0x85 }; @@ -291,31 +166,15 @@ unsigned short pages; unsigned char *buffer = NULL; unsigned char *ptr; - struct scatterlist *sg = NULL; - int i; int len; - int transferred; - - // If we're using scatter-gather, we have to create a new - // buffer to read all of the data in first, since a - // scatter-gather buffer could in theory start in the middle - // of a page, which would be bad. A developer who wants a - // challenge might want to write a limited-buffer - // version of this code. len = sectors * PAGESIZE; - if (use_sg) { - sg = (struct scatterlist *)content; - buffer = kmalloc(len, GFP_NOIO); - if (buffer == NULL) - return USB_STOR_TRANSPORT_ERROR; - ptr = buffer; - } else - ptr = content; + buffer = (use_sg ? kmalloc(len, GFP_NOIO) : content); + if (buffer == NULL) + return USB_STOR_TRANSPORT_ERROR; /* out of memory */ - // This could be made much more efficient by checking for - // contiguous LBA's. Another exercise left to the student. + ptr = buffer; while (sectors>0) { @@ -355,42 +214,30 @@ US_DEBUGP("Result for send_command in read_data %d\n", result); - if (result != US_BULK_TRANSFER_GOOD) { - if (use_sg) - kfree(buffer); - return result; - } + if (result != US_BULK_TRANSFER_GOOD) + goto leave; /* read data */ result = sddr55_bulk_transport(us, SCSI_DATA_READ, ptr, pages<pageshift); - if (result != US_BULK_TRANSFER_GOOD) { - if (use_sg) - kfree(buffer); - return result; - } + if (result != US_BULK_TRANSFER_GOOD) + goto leave; /* now read status */ result = sddr55_bulk_transport(us, SCSI_DATA_READ, status, 2); - if (result != US_BULK_TRANSFER_GOOD) { - if (use_sg) - kfree(buffer); - return result; - } + if (result != US_BULK_TRANSFER_GOOD) + goto leave; /* check status for error */ if (status[0] == 0xff && status[1] == 0x4) { set_sense_info (3, 0x11, 0); - if (use_sg) - kfree(buffer); - - return USB_STOR_TRANSPORT_FAILED; + result = USB_STOR_TRANSPORT_FAILED; + goto leave; } - } page = 0; @@ -399,18 +246,13 @@ ptr += (pages << info->pageshift); } - if (use_sg) { - transferred = 0; - for (i=0; i sg[i].length ? - sg[i].length : len-transferred); - transferred += sg[i].length; - } + us_copy_to_sgbuf_all(buffer, len, content, use_sg); + +leave: + if (use_sg) kfree(buffer); - } - return USB_STOR_TRANSPORT_GOOD; + return result; } static int sddr55_write_data(struct us_data *us, @@ -420,7 +262,7 @@ unsigned char *content, int use_sg) { - int result; + int result = USB_STOR_TRANSPORT_GOOD; unsigned char command[8] = { 0, 0, 0, 0, 0, 0xb0, 0, 0x86 }; @@ -434,10 +276,7 @@ unsigned short pages; unsigned char *buffer = NULL; unsigned char *ptr; - struct scatterlist *sg = NULL; - int i; - int len; - int transferred; + int i, len; /* check if we are allowed to write */ if (info->read_only || info->force_read_only) { @@ -445,33 +284,13 @@ return USB_STOR_TRANSPORT_FAILED; } - // If we're using scatter-gather, we have to create a new - // buffer to write all of the data in first, since a - // scatter-gather buffer could in theory start in the middle - // of a page, which would be bad. A developer who wants a - // challenge might want to write a limited-buffer - // version of this code. - len = sectors * PAGESIZE; - if (use_sg) { - sg = (struct scatterlist *)content; - buffer = kmalloc(len, GFP_NOIO); - if (buffer == NULL) - return USB_STOR_TRANSPORT_ERROR; - - transferred = 0; - for (i=0; i sg[i].length ? - sg[i].length : len-transferred); - transferred += sg[i].length; - } + buffer = us_copy_from_sgbuf_all(content, len, use_sg); + if (buffer == NULL) + return USB_STOR_TRANSPORT_ERROR; - ptr = buffer; - } else - ptr = content; + ptr = buffer; while (sectors > 0) { @@ -508,10 +327,12 @@ if (max_pba > 1024) max_pba = 1024; - /* scan through the map lookiong for an unused block - * leave 16 unused blocks at start (or as many as possible) - * since the sddr55 seems to reuse a used block when it shouldn't - * if we don't leave space */ + /* + * Scan through the map looking for an unused block + * leave 16 unused blocks at start (or as many as + * possible) since the sddr55 seems to reuse a used + * block when it shouldn't if we don't leave space. + */ for (i = 0; i < max_pba; i++, pba++) { if (info->pba_to_lba[pba] == UNUSED_BLOCK) { found_pba = pba; @@ -523,15 +344,12 @@ pba = found_pba; if (pba == -1) { - /* oh dear, couldn't find an unallocated block */ + /* oh dear */ US_DEBUGP("Couldn't find unallocated block\n"); set_sense_info (3, 0x31, 0); /* medium error */ - - if (use_sg) - kfree(buffer); - - return USB_STOR_TRANSPORT_FAILED; + result = USB_STOR_TRANSPORT_FAILED; + goto leave; } US_DEBUGP("Allocating PBA %04X for LBA %04X\n", pba, lba); @@ -560,11 +378,9 @@ US_DEBUGP("Result for send_command in write_data %d\n", result); - set_sense_info (3, 0x3, 0); /* peripheral write error */ - - if (use_sg) - kfree(buffer); - return result; + /* set_sense_info is superfluous here? */ + set_sense_info (3, 0x3, 0);/* peripheral write error */ + goto leave; } /* send the data */ @@ -574,41 +390,35 @@ if (result != US_BULK_TRANSFER_GOOD) { US_DEBUGP("Result for send_data in write_data %d\n", - result); + result); - set_sense_info (3, 0x3, 0); /* peripheral write error */ - - if (use_sg) - kfree(buffer); - return result; + /* set_sense_info is superfluous here? */ + set_sense_info (3, 0x3, 0);/* peripheral write error */ + goto leave; } /* now read status */ - result = sddr55_bulk_transport(us, - SCSI_DATA_READ, status, 6); + result = sddr55_bulk_transport(us, SCSI_DATA_READ, status, 6); if (result != US_BULK_TRANSFER_GOOD) { US_DEBUGP("Result for get_status in write_data %d\n", - result); - - set_sense_info (3, 0x3, 0); /* peripheral write error */ + result); - if (use_sg) - kfree(buffer); - return result; + /* set_sense_info is superfluous here? */ + set_sense_info (3, 0x3, 0);/* peripheral write error */ + goto leave; } - new_pba = (status[3] + (status[4] << 8) + (status[5] << 16)) >> info->blockshift; + new_pba = (status[3] + (status[4] << 8) + (status[5] << 16)) + >> info->blockshift; /* check status for error */ if (status[0] == 0xff && status[1] == 0x4) { - set_sense_info (3, 0x0c, 0); - if (use_sg) - kfree(buffer); - info->pba_to_lba[new_pba] = BAD_BLOCK; - return USB_STOR_TRANSPORT_FAILED; + set_sense_info (3, 0x0c, 0); + result = USB_STOR_TRANSPORT_FAILED; + goto leave; } US_DEBUGP("Updating maps for LBA %04X: old PBA %04X, new PBA %04X\n", @@ -624,10 +434,8 @@ new_pba, info->pba_to_lba[new_pba]); info->fatal_error = 1; set_sense_info (3, 0x31, 0); - if (use_sg) - kfree(buffer); - - return USB_STOR_TRANSPORT_FAILED; + result = USB_STOR_TRANSPORT_FAILED; + goto leave; } /* update the pba<->lba maps for new_pba */ @@ -639,11 +447,10 @@ ptr += (pages << info->pageshift); } - if (use_sg) { + leave: + if (use_sg) kfree(buffer); - } - - return USB_STOR_TRANSPORT_GOOD; + return result; } static int sddr55_read_deviceID(struct us_data *us, @@ -982,7 +789,8 @@ } } - /* if we detected a problem with the map when writing, don't allow any more access */ + /* if we detected a problem with the map when writing, + don't allow any more access */ if (info->fatal_error) { set_sense_info (3, 0x31, 0); @@ -994,14 +802,14 @@ capacity = sddr55_get_capacity(us); if (!capacity) { - set_sense_info (3, 0x30, 0); /* incompatible medium */ + set_sense_info (3, 0x30, 0); /* incompatible medium */ return USB_STOR_TRANSPORT_FAILED; } info->capacity = capacity; - /* figure out the maximum logical block number, allowing for the fact - * that only 250 out of every 256 are used */ + /* figure out the maximum logical block number, allowing for + * the fact that only 250 out of every 256 are used */ info->max_log_blks = ((info->capacity >> (info->pageshift + info->blockshift)) / 256) * 250; /* Last page in the card, adjust as we only use 250 out of every 256 pages */ @@ -1106,14 +914,14 @@ if (srb->cmnd[0] == WRITE_10) { US_DEBUGP("WRITE_10: write block %04X (LBA %04X) page %01X" - " pages %d\n", - pba, lba, page, pages); + " pages %d\n", + pba, lba, page, pages); return sddr55_write_data(us, lba, page, pages, ptr, srb->use_sg); } else { US_DEBUGP("READ_10: read block %04X (LBA %04X) page %01X" - " pages %d\n", - pba, lba, page, pages); + " pages %d\n", + pba, lba, page, pages); return sddr55_read_data(us, lba, page, pages, ptr, srb->use_sg); } diff -u --recursive --new-file ../linux-2.5.16/linux/drivers/usb/storage/shuttle_usbat.c ./linux/drivers/usb/storage/shuttle_usbat.c --- ../linux-2.5.16/linux/drivers/usb/storage/shuttle_usbat.c Sat May 18 16:25:57 2002 +++ ./linux/drivers/usb/storage/shuttle_usbat.c Sun May 19 16:23:44 2002 @@ -40,6 +40,7 @@ */ #include "transport.h" +#include "raw_bulk.h" #include "protocol.h" #include "usb.h" #include "debug.h" @@ -61,174 +62,6 @@ int transferred = 0; -/* - * 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. - * - */ - -static int usbat_send_control(struct us_data *us, - int pipe, - unsigned char request, - unsigned char requesttype, - unsigned short value, - unsigned short index, - unsigned char *xfer_data, - unsigned int xfer_len) { - - int result; - - // Send the URB to the device and wait for a response. - - /* 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); - - - // 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_stor_clear_halt(us, pipe); - US_DEBUGP("-- usb_stor_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; -} - -static int usbat_raw_bulk(struct us_data *us, - int direction, - unsigned char *data, - unsigned short len) { - - int result; - int act_len; - 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_stor_clear_halt(us, pipe); - } - - if (result) { - - /* NAK - that means we've retried a few times already */ - if (result == -ETIMEDOUT) { - US_DEBUGP("usbat_raw_bulk():" - " device NAKed\n"); - return US_BULK_TRANSFER_FAILED; - } - - /* -ENOENT -- we canceled this transfer */ - if (result == -ENOENT) { - US_DEBUGP("usbat_raw_bulk():" - " transfer aborted\n"); - return US_BULK_TRANSFER_ABORTED; - } - - if (result == -EPIPE) { - US_DEBUGP("usbat_raw_bulk():" - " output pipe stalled\n"); - return US_BULK_TRANSFER_SHORT; - } - - /* the catch-all case */ - US_DEBUGP("us_transfer_partial(): unknown error\n"); - return US_BULK_TRANSFER_FAILED; - } - - if (act_len != len) { - US_DEBUGP("Warning: Transferred only %d bytes\n", - act_len); - return US_BULK_TRANSFER_SHORT; - } - - US_DEBUGP("Transferred %s %d of %d bytes\n", - direction==SCSI_DATA_READ ? "in" : "out", act_len, len); - - return US_BULK_TRANSFER_GOOD; -} - -/* - * Note: direction must be set if command_len == 0. - */ - -static int usbat_bulk_transport(struct us_data *us, - unsigned char *command, - unsigned short command_len, - int direction, - unsigned char *data, - unsigned short len, - int use_sg) { - - int result = USB_STOR_TRANSPORT_GOOD; - int transferred = 0; - int i; - struct scatterlist *sg; - - if (len==0) - return USB_STOR_TRANSPORT_GOOD; - - /* transfer the data payload for the command, if there is any */ - - if (command_len != 0) - direction = (command[0]&0x80) ? SCSI_DATA_READ : - SCSI_DATA_WRITE; - - if (!use_sg) - result = usbat_raw_bulk(us, direction, data, len); - else { - sg = (struct scatterlist *)data; - for (i=0; i sg[i].length ? - sg[i].length : len-transferred); - if (result!=US_BULK_TRANSFER_GOOD) - break; - transferred += sg[i].length; - } - } - - return result; -} - int usbat_read(struct us_data *us, unsigned char access, unsigned char reg, @@ -236,7 +69,7 @@ int result; - result = usbat_send_control(us, + result = usb_storage_send_control(us, usb_rcvctrlpipe(us->pusb_dev,0), access, 0xC0, @@ -255,7 +88,7 @@ int result; - result = usbat_send_control(us, + result = usb_storage_send_control(us, usb_sndctrlpipe(us->pusb_dev,0), access|0x01, 0x40, @@ -281,7 +114,7 @@ test_pattern, mask_byte, subcountL, subcountH }; - result = usbat_send_control(us, + result = usb_storage_send_control(us, usb_sndctrlpipe(us->pusb_dev,0), 0x80, 0x40, @@ -306,7 +139,7 @@ LSB_of(len), MSB_of(len) }; - result = usbat_send_control(us, + result = usb_storage_send_control(us, usb_sndctrlpipe(us->pusb_dev,0), 0x80, 0x40, @@ -318,8 +151,7 @@ if (result != USB_STOR_TRANSPORT_GOOD) return result; - result = usbat_bulk_transport(us, - NULL, 0, SCSI_DATA_READ, content, len, use_sg); + result = usb_storage_bulk_transport(us, SCSI_DATA_READ, content, len, use_sg); return result; } @@ -388,7 +220,7 @@ LSB_of(len), MSB_of(len) }; - result = usbat_send_control(us, + result = usb_storage_send_control(us, usb_sndctrlpipe(us->pusb_dev,0), 0x80, 0x40, @@ -400,8 +232,7 @@ if (result != USB_STOR_TRANSPORT_GOOD) return result; - result = usbat_bulk_transport(us, - NULL, 0, SCSI_DATA_WRITE, content, len, use_sg); + result = usb_storage_bulk_transport(us, SCSI_DATA_WRITE, content, len, use_sg); if (result != USB_STOR_TRANSPORT_GOOD) return result; @@ -460,7 +291,7 @@ * that, we just return a failure. */ - result = usbat_send_control(us, + result = usb_storage_send_control(us, usb_sndctrlpipe(us->pusb_dev,0), 0x80, 0x40, @@ -474,8 +305,8 @@ if (i==0) { - result = usbat_bulk_transport(us, - NULL, 0, SCSI_DATA_WRITE, + result = usb_storage_bulk_transport(us, + SCSI_DATA_WRITE, data, num_registers*2, 0); if (result!=USB_STOR_TRANSPORT_GOOD) @@ -488,8 +319,8 @@ // direction == SCSI_DATA_WRITE ? "out" : "in", // len, use_sg); - result = usbat_bulk_transport(us, - NULL, 0, direction, content, len, use_sg); + result = usb_storage_bulk_transport(us, + direction, content, len, use_sg); /* * If we get a stall on the bulk download, we'll retry @@ -576,7 +407,7 @@ data[1+(i<<1)] = data_out[i]; } - result = usbat_send_control(us, + result = usb_storage_send_control(us, usb_sndctrlpipe(us->pusb_dev,0), 0x80, 0x40, @@ -588,10 +419,10 @@ if (result != USB_STOR_TRANSPORT_GOOD) return result; - result = usbat_bulk_transport(us, - NULL, 0, SCSI_DATA_WRITE, data, num_registers*2, 0); + result = usb_storage_bulk_transport(us, + SCSI_DATA_WRITE, data, num_registers*2, 0); - if (result!=USB_STOR_TRANSPORT_GOOD) + if (result != USB_STOR_TRANSPORT_GOOD) return result; return usbat_wait_not_busy(us, 0); @@ -602,7 +433,7 @@ int result; - result = usbat_send_control(us, + result = usb_storage_send_control(us, usb_rcvctrlpipe(us->pusb_dev,0), 0x82, 0xC0, @@ -620,7 +451,7 @@ int result; - result = usbat_send_control(us, + result = usb_storage_send_control(us, usb_sndctrlpipe(us->pusb_dev,0), 0x82, 0x40, @@ -646,7 +477,6 @@ unsigned char *buffer; unsigned int len; unsigned int sector; - unsigned int amount; struct scatterlist *sg = NULL; int sg_segment = 0; int sg_offset = 0; @@ -735,31 +565,11 @@ // Transfer the received data into the srb buffer - if (!srb->use_sg) { + if (srb->use_sg) + us_copy_to_sgbuf(buffer, len, sg, + &sg_segment, &sg_offset, srb->use_sg); + else memcpy(srb->request_buffer+transferred, buffer, len); - } else { - amount = 0; - while (amount= - sg[sg_segment].length-sg_offset) { - memcpy(page_address(sg[sg_segment].page) + - sg[sg_segment].offset + sg_offset, - buffer + amount, - sg[sg_segment].length - sg_offset); - amount += - sg[sg_segment].length-sg_offset; - sg_segment++; - sg_offset=0; - } else { - memcpy(page_address(sg[sg_segment].page) + - sg[sg_segment].offset + sg_offset, - buffer + amount, - len - amount); - sg_offset += (len - amount); - amount = len; - } - } - } // Update the amount transferred and the sector number diff -u --recursive --new-file ../linux-2.5.16/linux/drivers/usb/storage/transport.h ./linux/drivers/usb/storage/transport.h --- ../linux-2.5.16/linux/drivers/usb/storage/transport.h Sat May 18 16:25:57 2002 +++ ./linux/drivers/usb/storage/transport.h Sun May 19 15:46:45 2002 @@ -151,10 +151,13 @@ 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*, void*, int, unsigned int, - unsigned int*); -extern int usb_stor_control_msg(struct us_data*, unsigned int, u8, u8, - u16, u16, void*, u16); + +extern int usb_stor_bulk_msg(struct us_data *us, void *data, int pipe, + unsigned int len, unsigned int *act_len); +extern int usb_stor_control_msg(struct us_data *us, unsigned int pipe, + u8 request, u8 requesttype, u16 value, u16 index, + void *data, u16 size); + extern int usb_stor_clear_halt(struct us_data*, int ); extern void usb_stor_transfer(Scsi_Cmnd*, struct us_data*); #endif