Commit 2167f96c authored by Matthew Dharm's avatar Matthew Dharm Committed by Linus Torvalds

[PATCH] usb-storage: generalize transfer functions

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

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