Commit eae28375 authored by Andries E. Brouwer's avatar Andries E. Brouwer Committed by Greg Kroah-Hartman

[PATCH] usb-storage

Created the first of a series of usb-storage patches
this afternoon. Please find it below or on ftp.XX.kernel.org
under people/aeb/2.5.16-us-patch .
It removes 5% of the usb-storage code, but should, if I made
no mistake, not affect the behaviour of the code.

(This is the introduction of raw_bulk.c to hold USB-bulk
and scatter-gather code that was repeated three-five times
in various drivers. The next patch is smartmedia.c.)
parent 9d74f116
......@@ -11,14 +11,14 @@ EXTRA_CFLAGS := -I../../scsi/
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)
......
This diff is collapsed.
This diff is collapsed.
/*
* 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<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);
}
#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
......@@ -255,7 +255,7 @@ static int bus_reset( Scsi_Cmnd *srb )
/* 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 @@ int usb_stor_scsiSense10to6( Scsi_Cmnd* the10 )
/* 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 @@ int usb_stor_scsiSense6to10( Scsi_Cmnd* the6 )
/* 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 @@ int usb_stor_scsiSense6to10( Scsi_Cmnd* the6 )
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 @@ void usb_stor_scsiSenseParseBuffer( Scsi_Cmnd* srb, Usb_Stor_Scsi_Sense_Hdr_u* t
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 */
......
This diff is collapsed.
This diff is collapsed.
......@@ -40,6 +40,7 @@
*/
#include "transport.h"
#include "raw_bulk.h"
#include "protocol.h"
#include "usb.h"
#include "debug.h"
......@@ -61,174 +62,6 @@ extern int usb_stor_bulk_msg(struct us_data *us, void *data, int pipe,
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<use_sg && transferred<len; i++) {
result = usbat_raw_bulk(us, direction,
page_address(sg[i].page) + sg[i].offset,
len-transferred > 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 usbat_read(struct us_data *us,
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 usbat_write(struct us_data *us,
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 @@ int usbat_set_shuttle_features(struct us_data *us,
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 @@ int usbat_read_block(struct us_data *us,
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 @@ int usbat_read_block(struct us_data *us,
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 @@ int usbat_write_block(struct us_data *us,
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 @@ int usbat_write_block(struct us_data *us,
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 @@ int usbat_rw_block_test(struct us_data *us,
* 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 @@ int usbat_rw_block_test(struct us_data *us,
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 @@ int usbat_rw_block_test(struct us_data *us,
// 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 @@ int usbat_multiple_write(struct us_data *us,
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 @@ int usbat_multiple_write(struct us_data *us,
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 usbat_read_user_io(struct us_data *us,
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 usbat_write_user_io(struct us_data *us,
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 @@ int usbat_handle_read10(struct us_data *us,
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 @@ int usbat_handle_read10(struct us_data *us,
// 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<len) {
if (len - 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
......
......@@ -151,10 +151,13 @@ extern unsigned int usb_stor_transfer_length(Scsi_Cmnd*);
extern void usb_stor_invoke_transport(Scsi_Cmnd*, struct us_data*);
extern void usb_stor_abort_transport(struct us_data*);
extern int usb_stor_transfer_partial(struct us_data*, char*, int);
extern int usb_stor_bulk_msg(struct us_data*, 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
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment