usb_block: support iomega zip drives

This patch enhances the initialization sequence by issueing a START_STOP
SCSI command when needed.

Fixes #3469
This commit is contained in:
Norman Feske 2019-08-09 10:54:31 +02:00 committed by Christian Helmuth
parent 67a3c2ea4b
commit 23c2606ce0
3 changed files with 51 additions and 5 deletions

View File

@ -105,6 +105,23 @@ struct Request_sense : Usb::Cbw, Scsi::Request_sense
}; };
struct Start_stop : Usb::Cbw, Scsi::Start_stop
{
Start_stop(addr_t addr, uint32_t tag, uint8_t lun)
:
Cbw(addr, tag, 0, Usb::ENDPOINT_IN, lun, Scsi::Start_stop::LENGTH),
Scsi::Start_stop(addr+15)
{ if (verbose_scsi) dump(); }
void dump()
{
Genode::log("--- Dump START_STOP command --");
Cbw::dump();
Scsi::Start_stop::dump();
}
};
struct Inquiry : Usb::Cbw, Scsi::Inquiry struct Inquiry : Usb::Cbw, Scsi::Inquiry
{ {
Inquiry(addr_t addr, uint32_t tag, uint8_t lun) Inquiry(addr_t addr, uint32_t tag, uint8_t lun)

View File

@ -169,6 +169,7 @@ struct Usb::Block_driver : Usb::Completion,
bool no_medium = false; bool no_medium = false;
bool try_again = false; bool try_again = false;
bool start_stop = false;
Usb::Device &device; Usb::Device &device;
uint8_t interface; uint8_t interface;
@ -249,22 +250,42 @@ struct Usb::Block_driver : Usb::Completion,
uint8_t const asc = r.read<Request_sense_response::Asc>(); uint8_t const asc = r.read<Request_sense_response::Asc>();
uint8_t const asq = r.read<Request_sense_response::Asq>(); uint8_t const asq = r.read<Request_sense_response::Asq>();
enum { MEDIUM_NOT_PRESENT = 0x3a, NOT_READY_TO_READY_CHANGE = 0x28 }; bool error = false;
enum { MEDIUM_NOT_PRESENT = 0x3a,
NOT_READY_TO_READY_CHANGE = 0x28,
POWER_ON_OR_RESET_OCCURRED = 0x29,
LOGICAL_UNIT_NOT_READY = 0x04 };
switch (asc) { switch (asc) {
case MEDIUM_NOT_PRESENT: case MEDIUM_NOT_PRESENT:
Genode::error("Not ready - medium not present"); Genode::error("Not ready - medium not present");
no_medium = true; no_medium = true;
break; break;
case NOT_READY_TO_READY_CHANGE: /* asq == 0x00 */
case NOT_READY_TO_READY_CHANGE: /* asq == 0x00 */
case POWER_ON_OR_RESET_OCCURRED: /* asq == 0x00 */
Genode::warning("Not ready - try again"); Genode::warning("Not ready - try again");
try_again = true; try_again = true;
break; break;
case LOGICAL_UNIT_NOT_READY:
if (asq == 2) start_stop = true; /* initializing command required */
else if (asq == 1) try_again = true; /* initializing in progress */
else error = true;
break;
default: default:
error = true;
break;
}
if (error)
Genode::error("Request_sense_response asc: ", Genode::error("Request_sense_response asc: ",
Hex(asc, Hex::PREFIX, Hex::PAD), Hex(asc, Hex::PREFIX, Hex::PAD),
" asq: ", Hex(asq, Hex::PREFIX, Hex::PAD)); " asq: ", Hex(asq, Hex::PREFIX, Hex::PAD));
break;
}
break; break;
} }
case Csw::LENGTH: case Csw::LENGTH:
@ -489,6 +510,14 @@ struct Usb::Block_driver : Usb::Completion,
/* do nothing for now */ /* do nothing for now */
} else if (init.try_again) { } else if (init.try_again) {
init.try_again = false; init.try_again = false;
} else if (init.start_stop) {
init.start_stop = false;
Start_stop start_stop((addr_t)cbw_buffer, SS_TAG, active_lun);
cbw(cbw_buffer, init, true);
csw(init, true);
} else break; } else break;
} else break; } else break;

View File

@ -47,6 +47,7 @@ namespace Scsi {
struct Request_sense_response; struct Request_sense_response;
struct Capacity_response_10; struct Capacity_response_10;
struct Capacity_response_16; struct Capacity_response_16;
struct Start_stop_response;
struct Cmd_6; struct Cmd_6;
struct Test_unit_ready; struct Test_unit_ready;
@ -274,7 +275,6 @@ struct Scsi::Inquiry : Cmd_6
}; };
/* not in use for now but might come in handy in the future */
struct Scsi::Start_stop : Genode::Mmio struct Scsi::Start_stop : Genode::Mmio
{ {
enum { LENGTH = 6 }; enum { LENGTH = 6 };