Commit 2c0ac5c5 authored by Matthew Dharm's avatar Matthew Dharm Committed by Greg Kroah-Hartman

[PATCH] PATCH: fix devices which don't support START_STOP

Based on my discussions with Pete Zaitcev <zaitcev@redhat.com>, I'm
convinced that globally re-writing the START_STOP command into a
TEST_UNIT_READY command is a good idea.  This is supported by the fact
that:

(1) Lots of devices don't support START_STOP
(2) Those that do support it often don't do a good job
(3) Win/Mac will never send these commands over a USB bus

So, here's a patch that re-writes them into Test Unit Ready commands.  It
seems to work on my system, but needs more testing.  There may be a problem
with this code still.... it seems that the SCSI layer can get convinced
that the unit is not ready permanently.  I'm honestly not certain what bit
of code is wrong where, so reports from others would be greatly
appreciated.
parent 3cc8f6c9
...@@ -385,13 +385,6 @@ static int usb_stor_control_thread(void * __us) ...@@ -385,13 +385,6 @@ static int usb_stor_control_thread(void * __us)
us->srb->result = DID_BAD_TARGET << 16; us->srb->result = DID_BAD_TARGET << 16;
} }
/* handle those devices which can't do a START_STOP */
else if ((us->srb->cmnd[0] == START_STOP) &&
(us->flags & US_FL_START_STOP)) {
US_DEBUGP("Skipping START_STOP command\n");
us->srb->result = GOOD << 1;
}
/* handle requests for EVPD, which most USB devices do /* handle requests for EVPD, which most USB devices do
* not support */ * not support */
else if((us->srb->cmnd[0] == INQUIRY) && else if((us->srb->cmnd[0] == INQUIRY) &&
...@@ -416,6 +409,7 @@ static int usb_stor_control_thread(void * __us) ...@@ -416,6 +409,7 @@ static int usb_stor_control_thread(void * __us)
sizeof(usb_stor_sense_notready)); sizeof(usb_stor_sense_notready));
us->srb->result = GOOD << 1; us->srb->result = GOOD << 1;
} else if(us->srb->cmnd[0] == INQUIRY) { } else if(us->srb->cmnd[0] == INQUIRY) {
/* INQUIRY should always work, per spec... */
unsigned char data_ptr[36] = { unsigned char data_ptr[36] = {
0x20, 0x80, 0x02, 0x02, 0x20, 0x80, 0x02, 0x02,
0x1F, 0x00, 0x00, 0x00}; 0x1F, 0x00, 0x00, 0x00};
...@@ -423,6 +417,7 @@ static int usb_stor_control_thread(void * __us) ...@@ -423,6 +417,7 @@ static int usb_stor_control_thread(void * __us)
fill_inquiry_response(us, data_ptr, 36); fill_inquiry_response(us, data_ptr, 36);
us->srb->result = GOOD << 1; us->srb->result = GOOD << 1;
} else { } else {
/* not ready */
memcpy(us->srb->sense_buffer, memcpy(us->srb->sense_buffer,
usb_stor_sense_notready, usb_stor_sense_notready,
sizeof(usb_stor_sense_notready)); sizeof(usb_stor_sense_notready));
...@@ -443,6 +438,35 @@ static int usb_stor_control_thread(void * __us) ...@@ -443,6 +438,35 @@ static int usb_stor_control_thread(void * __us)
us->srb->result = GOOD << 1; us->srb->result = GOOD << 1;
} }
/* Most USB devices can't handle START_STOP. But we
* need something for media-change, so we'll use TUR
* instead.
*/
else if (us->srb->cmnd[0] == START_STOP) {
unsigned char saved_cdb[16]; /* largest SCSI-III cmd */
__u8 old_cmd_len;
US_DEBUGP("Converting START_STOP to TUR\n");
/* save old command */
memcpy(saved_cdb, us->srb->cmnd, us->srb->cmd_len);
old_cmd_len = us->srb->cmd_len;
/* set up new command -- preserve LUN */
us->srb->cmd_len = 6;
memset(us->srb->cmnd, 0, us->srb->cmd_len);
us->srb->cmnd[0] = TEST_UNIT_READY;
us->srb->cmnd[1] = saved_cdb[1] & 0xE0;
/* do command */
US_DEBUG(usb_stor_show_command(us->srb));
us->proto_handler(us->srb, us);
/* restore original command */
us->srb->cmd_len = old_cmd_len;
memcpy(us->srb->cmnd, saved_cdb, us->srb->cmd_len);
}
/* we've got a command, let's do it! */ /* we've got a command, let's do it! */
else { else {
US_DEBUG(usb_stor_show_command(us->srb)); US_DEBUG(usb_stor_show_command(us->srb));
......
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