diff --git a/drivers/usb_storage/scsi.c b/drivers/usb_storage/scsi.c index f4ff43e1a..8ed74d419 100755 --- a/drivers/usb_storage/scsi.c +++ b/drivers/usb_storage/scsi.c @@ -258,7 +258,7 @@ check_csw(mass_storage_csw * csw, unsigned int tag) } if (CSW_STATUS_GOOD != csw->bCSWStatus) { - MASS_MSG("CSW status error!"); + MASS_MSG("CSW status error (0x%02X)!", csw->bCSWStatus); return EXIT_FAILURE; } diff --git a/drivers/usb_storage/urb_helper.h b/drivers/usb_storage/urb_helper.h index 700323ae6..c9033c93b 100755 --- a/drivers/usb_storage/urb_helper.h +++ b/drivers/usb_storage/urb_helper.h @@ -24,7 +24,7 @@ /*---------------------------* * declared types * - *---------------------------* + *---------------------------*/ /* URB's endpoint configuration */ typedef struct urb_ep_config { diff --git a/drivers/usb_storage/usb_storage.c b/drivers/usb_storage/usb_storage.c index c455554e8..ecafdccba 100755 --- a/drivers/usb_storage/usb_storage.c +++ b/drivers/usb_storage/usb_storage.c @@ -45,10 +45,12 @@ static int mass_storage_send_scsi_data_in(void *, unsigned int); static int mass_storage_send_scsi_data_out(void *, unsigned int); static int mass_storage_send_scsi_csw_in(void); +#ifdef MASS_RESET_RECOVERY /* Bulk only URB related prototypes */ static int mass_storage_reset_recovery(void); static int mass_storage_send_bulk_reset(void); static int mass_storage_send_clear_feature(int, int); +#endif /* SEF related functions */ static int mass_storage_sef_hdlr(int, sef_init_info_t *); @@ -59,6 +61,7 @@ static void ddekit_usb_task(void *); /* Mass storage related prototypes */ static void mass_storage_task(void *); +static int mass_storage_test(void); static int mass_storage_try_first_open(void); static int mass_storage_transfer_restrictions(u64_t, unsigned long); static ssize_t mass_storage_write(unsigned long, endpoint_t, iovec_t *, @@ -143,6 +146,8 @@ static unsigned char buffer[BUFFER_SIZE]; /* Length of local buffer where descriptors are temporarily stored */ #define MAX_DESCRIPTORS_LEN 128 +/* Maximum 'Test Unit Ready' command retries */ +#define MAX_TEST_RETRIES 3 /*---------------------------* * defined functions * @@ -333,6 +338,7 @@ mass_storage_send_scsi_csw_in(void) } +#ifdef MASS_RESET_RECOVERY /*===========================================================================* * mass_storage_reset_recovery * *===========================================================================*/ @@ -472,6 +478,7 @@ mass_storage_send_clear_feature(int ep_num, int direction) return EXIT_SUCCESS; } +#endif /*===========================================================================* @@ -575,6 +582,33 @@ mass_storage_task(void * UNUSED(unused)) } +/*===========================================================================* + * mass_storage_test * + *===========================================================================*/ +static int +mass_storage_test(void) +{ + int repeat; + + MASS_DEBUG_DUMP; + + for (repeat = 0; repeat < MAX_TEST_RETRIES; repeat++) { + + /* SCSI TEST UNIT READY OUT stage */ + if (mass_storage_send_scsi_cbw_out(SCSI_TEST_UNIT_READY, NULL)) + return EXIT_FAILURE; + + /* TODO: Only CSW failure should normally contribute to retry */ + + /* SCSI TEST UNIT READY IN stage */ + if (EXIT_SUCCESS == mass_storage_send_scsi_csw_in()) + return EXIT_SUCCESS; + } + + return EXIT_FAILURE; +} + + /*===========================================================================* * mass_storage_try_first_open * *===========================================================================*/ @@ -593,6 +627,11 @@ mass_storage_try_first_open() llba = 0; /* Last logical block address */ blen = 0; /* Block length (usually 512B) */ + /* Run TEST UNIT READY before other SCSI command + * Some devices refuse to work without this */ + if (mass_storage_test()) + return EIO; + /* SCSI INQUIRY OUT stage */ if (mass_storage_send_scsi_cbw_out(SCSI_INQUIRY, NULL)) return EIO; @@ -609,6 +648,11 @@ mass_storage_try_first_open() if (check_inquiry_reply(inquiry)) return EIO; + /* Run TEST UNIT READY before other SCSI command + * Some devices refuse to work without this */ + if (mass_storage_test()) + return EIO; + /* SCSI READ CAPACITY OUT stage */ if (mass_storage_send_scsi_cbw_out(SCSI_READ_CAPACITY, NULL)) return EIO; @@ -1005,11 +1049,13 @@ mass_storage_open(devminor_t minor, int UNUSED(access)) /* Copy evaluated current drive for simplified dereference */ d = driver_state.cur_drive; +#ifdef MASS_RESET_RECOVERY /* In case of previous CBW mismatch */ if (mass_storage_reset_recovery()) { MASS_MSG("Resetting mass storage device failed"); return EIO; } +#endif /* In case of missing endpoint information, do simple * enumeration and hold it for future use */ @@ -1050,12 +1096,9 @@ mass_storage_open(devminor_t minor, int UNUSED(access)) return ENXIO; } - /* SCSI TEST UNIT READY OUT stage */ - if (mass_storage_send_scsi_cbw_out(SCSI_TEST_UNIT_READY, NULL)) - return EIO; - - /* SCSI TEST UNIT READY IN stage */ - if (mass_storage_send_scsi_csw_in()) + /* Run TEST UNIT READY before further commands + * Some devices refuse to work without this */ + if (mass_storage_test()) return EIO; /* Opening completed */ @@ -1346,6 +1389,8 @@ mass_storage_geometry(devminor_t minor, struct part_geom * part) static void mass_storage_geometry(devminor_t UNUSED(minor), struct part_geom * part) { + MASS_DEBUG_DUMP; + part->cylinders = part->size / SECTOR_SIZE; part->heads = 64; part->sectors = 32;