patch-2.3.12 linux/drivers/usb/usb_scsi.c
Next file: linux/fs/Makefile
Previous file: linux/drivers/usb/usb.h
Back to the patch index
Back to the overall index
- Lines: 202
- Date:
Sun Jul 25 20:30:47 1999
- Orig file:
v2.3.11/linux/drivers/usb/usb_scsi.c
- Orig date:
Wed Jun 30 13:38:20 1999
diff -u --recursive --new-file v2.3.11/linux/drivers/usb/usb_scsi.c linux/drivers/usb/usb_scsi.c
@@ -139,10 +139,20 @@
this_xfer = length > max_size ? max_size : length;
length -= this_xfer;
do {
- US_DEBUGP("Bulk xfer %x(%d)\n", (unsigned int)buf, this_xfer);
+ /*US_DEBUGP("Bulk xfer %x(%d)\n", (unsigned int)buf, this_xfer);*/
result = us->pusb_dev->bus->op->bulk_msg(us->pusb_dev, pipe, buf,
this_xfer, &partial);
+ if (result != 0 || partial != this_xfer)
+ US_DEBUGP("bulk_msg returned %d xferred %lu/%d\n",
+ result, partial, this_xfer);
+
+ if (result == USB_ST_STALL) {
+ US_DEBUGP("clearing endpoing halt for pipe %x\n", pipe);
+ usb_clear_halt(us->pusb_dev,
+ usb_pipeendpoint(pipe) | (pipe & 0x80));
+ }
+
/* we want to retry if the device reported NAK */
if (result == USB_ST_TIMEOUT) {
if (partial != this_xfer) {
@@ -171,28 +181,31 @@
return 0;
}
+
static int us_transfer(Scsi_Cmnd *srb, int dir_in)
{
struct us_data *us = (struct us_data *)srb->host_scribble;
int i;
int result = -1;
+ unsigned int pipe = dir_in ? usb_rcvbulkpipe(us->pusb_dev, us->ep_in) :
+ usb_sndbulkpipe(us->pusb_dev, us->ep_out);
if (srb->use_sg) {
struct scatterlist *sg = (struct scatterlist *) srb->request_buffer;
for (i = 0; i < srb->use_sg; i++) {
- result = us_one_transfer(us, dir_in ? usb_rcvbulkpipe(us->pusb_dev, us->ep_in) :
- usb_sndbulkpipe(us->pusb_dev, us->ep_out),
- sg[i].address, sg[i].length);
+ result = us_one_transfer(us, pipe, sg[i].address, sg[i].length);
if (result)
break;
}
- return result;
}
else
- return us_one_transfer(us, dir_in ? usb_rcvbulkpipe(us->pusb_dev, us->ep_in) :
- usb_sndbulkpipe(us->pusb_dev, us->ep_out),
- srb->request_buffer, srb->request_bufflen);
+ result = us_one_transfer(us, pipe,
+ srb->request_buffer, srb->request_bufflen);
+
+ if (result)
+ US_DEBUGP("us_transfer returning error %d\n", result);
+ return result;
}
static unsigned int us_transfer_length(Scsi_Cmnd *srb)
@@ -232,12 +245,13 @@
struct us_data *us = (struct us_data *)dev_id;
if (state != USB_ST_REMOVED) {
- us->ip_data = *(__u16 *)buffer;
- US_DEBUGP("Interrupt Status %x\n", us->ip_data);
+ us->ip_data = le16_to_cpup((__u16 *)buffer);
+ /* US_DEBUGP("Interrupt Status %x\n", us->ip_data); */
}
- if (us->ip_wanted)
+ if (us->ip_wanted) {
+ us->ip_wanted = 0;
wake_up(&us->ip_waitq);
- us->ip_wanted = 0;
+ }
/* we dont want another interrupt */
@@ -250,6 +264,7 @@
devrequest dr;
int result;
+ US_DEBUGP("pop_CB_reset\n");
dr.requesttype = USB_TYPE_CLASS | USB_RT_INTERFACE;
dr.request = US_CBI_ADSC;
dr.value = 0;
@@ -262,12 +277,15 @@
usb_sndctrlpipe(us->pusb_dev,0),
&dr, cmd, 12);
- usb_clear_halt(us->pusb_dev, us->ep_in | 0x80);
- usb_clear_halt(us->pusb_dev, us->ep_out);
-
/* long wait for reset */
schedule_timeout(HZ*5);
+
+ US_DEBUGP("pop_CB_reset: clearing endpoint halt\n");
+ usb_clear_halt(us->pusb_dev, us->ep_in | 0x80);
+ usb_clear_halt(us->pusb_dev, us->ep_out);
+
+ US_DEBUGP("pop_CB_reset done\n");
return 0;
}
@@ -325,6 +343,7 @@
/* as per spec try a start command, wait and retry */
done_start++;
+ memset(cmd, 0, sizeof(cmd));
cmd[0] = START_STOP;
cmd[4] = 1; /* start */
result = us->pusb_dev->bus->op->control_msg(us->pusb_dev,
@@ -338,7 +357,7 @@
result = us->pusb_dev->bus->op->control_msg(us->pusb_dev,
usb_sndctrlpipe(us->pusb_dev,0),
&dr, srb->cmnd, srb->cmd_len);
- if (result != USB_ST_STALL && result != USB_ST_TIMEOUT)
+ if (/*result != USB_ST_STALL &&*/ result != USB_ST_TIMEOUT)
return result;
}
return result;
@@ -356,6 +375,7 @@
devrequest dr;
int retry = 5;
+ US_DEBUGP("pop_CB_status, proto=%x\n", us->protocol);
switch (us->protocol) {
case US_PR_CB:
/* get from control */
@@ -439,23 +459,26 @@
if (result == USB_ST_STALL || result == USB_ST_TIMEOUT) {
return (DID_OK << 16) | 2;
}
- return DID_ABORT << 16;
+ return DID_ERROR << 16;
}
/* transfer the data */
if (us_transfer_length(srb)) {
result = us_transfer(srb, US_DIRECTION(srb->cmnd[0]));
- if (result && result != USB_ST_DATAUNDERRUN) {
+ if (result && result != USB_ST_DATAUNDERRUN && result != USB_ST_STALL) {
US_DEBUGP("CBI transfer %x\n", result);
- return DID_ABORT << 16;
- } else if (result == USB_ST_DATAUNDERRUN) {
+ return DID_ERROR << 16;
+ }
+#if 0
+ else if (result == USB_ST_DATAUNDERRUN) {
return DID_OK << 16;
}
} else {
if (!result) {
return DID_OK << 16;
}
+#endif
}
/* get status */
@@ -947,6 +970,7 @@
US_DEBUGP("Old/New length = %d/%d\n", savelen, length);
if (us->srb->request_bufflen != length) {
+ US_DEBUGP("redoing cmd with len=%d\n", length);
us->srb->request_bufflen = length;
us->srb->result = us->pop(us->srb);
}
@@ -957,6 +981,15 @@
case REQUEST_SENSE:
case INQUIRY:
case MODE_SENSE:
+ if (us->srb->use_sg == 0 && length > 0) {
+ int i;
+ printk(KERN_DEBUG "Data is");
+ for (i = 0; i < 32 && i < length; ++i)
+ printk(" %.2x", ((unsigned char *)us->srb->request_buffer)[i]);
+ if (i < length)
+ printk(" ...");
+ printk("\n");
+ }
us->srb->cmnd[4] = saveallocation;
break;
@@ -969,6 +1002,7 @@
}
/* force attention on first command */
if (!us->attention_done) {
+ US_DEBUGP("forcing unit attention\n");
if (us->srb->cmnd[0] == REQUEST_SENSE) {
if (us->srb->result == (DID_OK << 16)) {
unsigned char *p = (unsigned char *)us->srb->request_buffer;
@@ -987,6 +1021,7 @@
}
}
}
+ US_DEBUGP("scsi cmd done, result=%x\n", us->srb->result);
us->srb->scsi_done(us->srb);
us->srb = NULL;
break;
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)