Attached to this message is a patch for the usb-storage driver against
2.4.15-pre2. Please apply.
This patch fixes the following:
(o) No more crashing with cdrecord -scanbus with detached devices
(o) Freecom adaptor now works for commands which take longer than 20
seconds.
Note that this second item fixes the problem that several people reported
about not being able to burn CDs with Traveller CD-RWs, and intermittent
failures of the OnStream USB30 drive with the osst driver.
Matt
--
Matthew Dharm Home: [EMAIL PROTECTED]
Maintainer, Linux USB Mass Storage Driver
I'm just trying to think of a way to say "up yours" without getting fired.
-- Stef
User Friendly, 10/8/1998
Only in storage: CVS
diff -u storage.old/freecom.c storage/freecom.c
--- storage.old/freecom.c Sun Nov 11 00:14:54 2001
+++ storage/freecom.c Sat Nov 10 21:42:34 2001
@@ -1,6 +1,6 @@
/* Driver for Freecom USB/IDE adaptor
*
- * $Id: freecom.c,v 1.18 2001/11/04 13:01:17 mdharm Exp $
+ * $Id: freecom.c,v 1.19 2001/11/11 05:42:34 mdharm Exp $
*
* Freecom v0.1:
*
@@ -81,27 +81,28 @@
/* Freecom stuffs the interrupt status in the INDEX_STAT bit of the ide
* register. */
-#define FCM_INT_STATUS INDEX_STAT
+#define FCM_INT_STATUS 0x02 /* INDEX_STAT */
+#define FCM_STATUS_BUSY 0x80
/* These are the packet types. The low bit indicates that this command
* should wait for an interrupt. */
-#define FCM_PACKET_ATAPI 0x21
-#define FCM_PACKET_STATUS 0x20
+#define FCM_PACKET_ATAPI 0x21
+#define FCM_PACKET_STATUS 0x20
/* Receive data from the IDE interface. The ATAPI packet has already
* waited, so the data should be immediately available. */
-#define FCM_PACKET_INPUT 0x81
+#define FCM_PACKET_INPUT 0x81
/* Send data to the IDE interface. */
-#define FCM_PACKET_OUTPUT 0x01
+#define FCM_PACKET_OUTPUT 0x01
/* Write a value to an ide register. Or the ide register to write after
* munging the address a bit. */
-#define FCM_PACKET_IDE_WRITE 0x40
-#define FCM_PACKET_IDE_READ 0xC0
+#define FCM_PACKET_IDE_WRITE 0x40
+#define FCM_PACKET_IDE_READ 0xC0
/* 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
@@ -205,6 +206,7 @@
return USB_STOR_TRANSPORT_GOOD;
}
+#endif
/* Read a value from an ide register. */
static int
@@ -229,6 +231,8 @@
else
reg = 0x0e;
+ US_DEBUGP("IDE in request for register 0x%02x\n", reg);
+
idein->Type = FCM_PACKET_IDE_READ | reg;
memset (idein->Pad, 0, sizeof (idein->Pad));
@@ -253,17 +257,17 @@
else
return USB_STOR_TRANSPORT_ERROR;
}
+ US_DEBUGP("IDE in partial is %d\n", partial);
if (desired_length == 1)
*value = buffer[0];
else
*value = le16_to_cpu (*(__u16 *) buffer);
- US_DEBUGP("IDE in 0x%02x -> 0x%02x\n", reg, *value);
+ US_DEBUGP("IDE in 0x%02x -> 0x%02x\n", reg, *value);
return USB_STOR_TRANSPORT_GOOD;
}
-#endif
static int
freecom_readdata (Scsi_Cmnd *srb, struct us_data *us,
@@ -373,13 +377,6 @@
opipe = usb_sndbulkpipe (us->pusb_dev, us->ep_out);
ipipe = usb_rcvbulkpipe (us->pusb_dev, us->ep_in);
-#if 0
- /* Yuck, let's see if this helps us. Artificially increase the
- * length on this. */
- if (srb->cmnd[0] == 0x03 && srb->cmnd[4] == 0x12)
- srb->cmnd[4] = 0x0E;
-#endif
-
/* The ATAPI Command always goes out first. */
fcb->Type = FCM_PACKET_ATAPI | 0x00;
fcb->Timeout = 0;
@@ -421,17 +418,25 @@
US_DEBUG(pdump ((void *) fst, partial));
- /* while we haven't received the IRQ */
- while (!(fst->Status & 0x2)) {
- /* send a command to re-fetch the status */
- US_DEBUGP("Re-attempting to get status...\n");
+ /* The firmware will time-out commands after 20 seconds. Some commands
+ * can legitimately take longer than this, so we use a different
+ * command that only waits for the interrupt and then sends status,
+ * without having to send a new ATAPI command to the device.
+ *
+ * NOTE: There is some indication that a data transfer after a timeout
+ * may not work, but that is a condition that should never happen.
+ */
+ while (fst->Status & FCM_STATUS_BUSY) {
+ US_DEBUGP("20 second USB/ATAPI bridge TIMEOUT occured!\n");
+ US_DEBUGP("fst->Status is %x\n", fst->Status);
+ /* Get the status again */
fcb->Type = FCM_PACKET_STATUS;
fcb->Timeout = 0;
- memset (fcb->Atapi, 0, 12);
+ memset (fcb->Atapi, 0, sizeof(fcb->Filler));
memset (fcb->Filler, 0, sizeof (fcb->Filler));
- /* Send it out. */
+ /* Send it out. */
result = usb_stor_bulk_msg (us, fcb, opipe,
FCM_PACKET_LENGTH, &partial);
@@ -452,10 +457,12 @@
return USB_STOR_TRANSPORT_ERROR;
}
- /* actually get the status info */
- result = usb_stor_bulk_msg (us, fst, ipipe,
+ /* get the data */
+ result = usb_stor_bulk_msg (us, fst, ipipe,
FCM_PACKET_LENGTH, &partial);
+
US_DEBUGP("bar Status result %d %d\n", result, partial);
+
/* -ENOENT -- we canceled this transfer */
if (result == -ENOENT) {
US_DEBUGP("freecom_transport(): transfer aborted\n");
diff -u storage.old/scsiglue.c storage/scsiglue.c
--- storage.old/scsiglue.c Sun Nov 11 00:14:54 2001
+++ storage/scsiglue.c Sat Nov 10 19:33:58 2001
@@ -1,7 +1,7 @@
/* Driver for USB Mass Storage compliant devices
* SCSI layer glue code
*
- * $Id: scsiglue.c,v 1.23 2001/10/15 07:02:32 mdharm Exp $
+ * $Id: scsiglue.c,v 1.24 2001/11/11 03:33:58 mdharm Exp $
*
* Current development and maintenance by:
* (c) 1999, 2000 Matthew Dharm ([EMAIL PROTECTED])
@@ -346,7 +346,7 @@
/* show the GUID of the device */
SPRINTF(" GUID: " GUID_FORMAT "\n", GUID_ARGS(us->guid));
- SPRINTF(" Attached: %d\n", us->pusb_dev != NULL);
+ SPRINTF(" Attached: %s\n", us->pusb_dev ? "Yes" : "No");
/*
* Calculate start of next buffer, and return value.
diff -u storage.old/usb.c storage/usb.c
--- storage.old/usb.c Sun Nov 11 00:14:54 2001
+++ storage/usb.c Sat Nov 10 19:33:03 2001
@@ -1,6 +1,6 @@
/* Driver for USB Mass Storage compliant devices
*
- * $Id: usb.c,v 1.68 2001/10/15 07:02:33 mdharm Exp $
+ * $Id: usb.c,v 1.69 2001/11/11 03:33:03 mdharm Exp $
*
* Current development and maintenance by:
* (c) 1999, 2000 Matthew Dharm ([EMAIL PROTECTED])
@@ -262,16 +262,28 @@
if (data_len<36) // You lose.
return;
- memcpy(data+8, us->unusual_dev->vendorName,
- strlen(us->unusual_dev->vendorName) > 8 ? 8 :
- strlen(us->unusual_dev->vendorName));
- memcpy(data+16, us->unusual_dev->productName,
- strlen(us->unusual_dev->productName) > 16 ? 16 :
- strlen(us->unusual_dev->productName));
- data[32] = 0x30 + ((us->pusb_dev->descriptor.bcdDevice>>12) & 0x0F);
- data[33] = 0x30 + ((us->pusb_dev->descriptor.bcdDevice>>8) & 0x0F);
- data[34] = 0x30 + ((us->pusb_dev->descriptor.bcdDevice>>4) & 0x0F);
- data[35] = 0x30 + ((us->pusb_dev->descriptor.bcdDevice) & 0x0F);
+ if(data[0]&0x20) { /* USB device currently not connected. Return
+ peripheral qualifier 001b ("...however, the
+ physical device is not currently connected
+ to this logical unit") and leave vendor and
+ product identification empty. ("If the target
+ does store some of the INQUIRY data on the
+ device, it may return zeros or ASCII spaces
+ (20h) in those fields until the data is
+ available from the device."). */
+ memset(data+8,0,28);
+ } else {
+ memcpy(data+8, us->unusual_dev->vendorName,
+ strlen(us->unusual_dev->vendorName) > 8 ? 8 :
+ strlen(us->unusual_dev->vendorName));
+ memcpy(data+16, us->unusual_dev->productName,
+ strlen(us->unusual_dev->productName) > 16 ? 16 :
+ strlen(us->unusual_dev->productName));
+ data[32] = 0x30 + ((us->pusb_dev->descriptor.bcdDevice>>12) & 0x0F);
+ data[33] = 0x30 + ((us->pusb_dev->descriptor.bcdDevice>>8) & 0x0F);
+ data[34] = 0x30 + ((us->pusb_dev->descriptor.bcdDevice>>4) & 0x0F);
+ data[35] = 0x30 + ((us->pusb_dev->descriptor.bcdDevice) & 0x0F);
+ }
if (us->srb->use_sg) {
sg = (struct scatterlist *)us->srb->request_buffer;
@@ -389,24 +401,6 @@
break;
}
- /* Handle those devices which need us to fake their
- * inquiry data */
- if ((us->srb->cmnd[0] == INQUIRY) &&
- (us->flags & US_FL_FIX_INQUIRY)) {
- unsigned char data_ptr[36] = {
- 0x00, 0x80, 0x02, 0x02,
- 0x1F, 0x00, 0x00, 0x00};
-
- US_DEBUGP("Faking INQUIRY command\n");
- fill_inquiry_response(us, data_ptr, 36);
- us->srb->result = GOOD << 1;
-
- set_current_state(TASK_INTERRUPTIBLE);
- us->srb->scsi_done(us->srb);
- us->srb = NULL;
- break;
- }
-
/* lock the device pointers */
down(&(us->dev_semaphore));
@@ -422,6 +416,13 @@
usb_stor_sense_notready,
sizeof(usb_stor_sense_notready));
us->srb->result = GOOD << 1;
+ } else if(us->srb->cmnd[0] == INQUIRY) {
+ unsigned char data_ptr[36] = {
+ 0x20, 0x80, 0x02, 0x02,
+ 0x1F, 0x00, 0x00, 0x00};
+ US_DEBUGP("Faking INQUIRY command for
+disconnected device\n");
+ fill_inquiry_response(us, data_ptr, 36);
+ us->srb->result = GOOD << 1;
} else {
memcpy(us->srb->sense_buffer,
usb_stor_sense_notready,
@@ -429,9 +430,23 @@
us->srb->result = CHECK_CONDITION << 1;
}
} else { /* !us->pusb_dev */
- /* we've got a command, let's do it! */
- US_DEBUG(usb_stor_show_command(us->srb));
- us->proto_handler(us->srb, us);
+
+ /* Handle those devices which need us to fake
+ * their inquiry data */
+ if ((us->srb->cmnd[0] == INQUIRY) &&
+ (us->flags & US_FL_FIX_INQUIRY)) {
+ unsigned char data_ptr[36] = {
+ 0x00, 0x80, 0x02, 0x02,
+ 0x1F, 0x00, 0x00, 0x00};
+
+ US_DEBUGP("Faking INQUIRY command\n");
+ fill_inquiry_response(us, data_ptr, 36);
+ us->srb->result = GOOD << 1;
+ } else {
+ /* we've got a command, let's do it! */
+ US_DEBUG(usb_stor_show_command(us->srb));
+ us->proto_handler(us->srb, us);
+ }
}
/* unlock the device pointers */
PGP signature