From 23c2606ce095279d696b999c5e54d48dd9e0385a Mon Sep 17 00:00:00 2001 From: Norman Feske Date: Fri, 9 Aug 2019 10:54:31 +0200 Subject: [PATCH] usb_block: support iomega zip drives This patch enhances the initialization sequence by issueing a START_STOP SCSI command when needed. Fixes #3469 --- repos/os/src/drivers/usb_block/cbw_csw.h | 17 +++++++++++ repos/os/src/drivers/usb_block/main.cc | 37 +++++++++++++++++++++--- repos/os/src/drivers/usb_block/scsi.h | 2 +- 3 files changed, 51 insertions(+), 5 deletions(-) diff --git a/repos/os/src/drivers/usb_block/cbw_csw.h b/repos/os/src/drivers/usb_block/cbw_csw.h index 55f90ddd87..6c87f2a5e1 100644 --- a/repos/os/src/drivers/usb_block/cbw_csw.h +++ b/repos/os/src/drivers/usb_block/cbw_csw.h @@ -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 { Inquiry(addr_t addr, uint32_t tag, uint8_t lun) diff --git a/repos/os/src/drivers/usb_block/main.cc b/repos/os/src/drivers/usb_block/main.cc index c0966824a1..cbccece766 100644 --- a/repos/os/src/drivers/usb_block/main.cc +++ b/repos/os/src/drivers/usb_block/main.cc @@ -169,6 +169,7 @@ struct Usb::Block_driver : Usb::Completion, bool no_medium = false; bool try_again = false; + bool start_stop = false; Usb::Device &device; uint8_t interface; @@ -249,22 +250,42 @@ struct Usb::Block_driver : Usb::Completion, uint8_t const asc = r.read(); uint8_t const asq = r.read(); - 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) { + case MEDIUM_NOT_PRESENT: Genode::error("Not ready - medium not present"); no_medium = true; 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"); try_again = true; 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: + error = true; + break; + } + + if (error) Genode::error("Request_sense_response asc: ", Hex(asc, Hex::PREFIX, Hex::PAD), " asq: ", Hex(asq, Hex::PREFIX, Hex::PAD)); - break; - } break; } case Csw::LENGTH: @@ -489,6 +510,14 @@ struct Usb::Block_driver : Usb::Completion, /* do nothing for now */ } else if (init.try_again) { 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; diff --git a/repos/os/src/drivers/usb_block/scsi.h b/repos/os/src/drivers/usb_block/scsi.h index 161245ec3b..c4510fc0d3 100644 --- a/repos/os/src/drivers/usb_block/scsi.h +++ b/repos/os/src/drivers/usb_block/scsi.h @@ -47,6 +47,7 @@ namespace Scsi { struct Request_sense_response; struct Capacity_response_10; struct Capacity_response_16; + struct Start_stop_response; struct Cmd_6; 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 { enum { LENGTH = 6 };