|
|
@@ -87,6 +87,7 @@ static int do_read6_or_10(int target_id, uint32_t start_sector, uint32_t sectorc
|
|
|
|
|
|
static void scan_targets()
|
|
|
{
|
|
|
+ int found_count = 0;
|
|
|
int initiator_id = scsiInitiatorGetOwnID();
|
|
|
uint8_t inquiry_data[36] = {0};
|
|
|
g_msc_initiator_target_count = 0;
|
|
|
@@ -100,7 +101,8 @@ static void scan_targets()
|
|
|
|
|
|
bool inquiryok =
|
|
|
scsiStartStopUnit(target_id, true) &&
|
|
|
- scsiInquiry(target_id, inquiry_data) &&
|
|
|
+ scsiInquiry(target_id, inquiry_data);
|
|
|
+ bool readcapok =
|
|
|
scsiInitiatorReadCapacity(target_id, §orcount, §orsize);
|
|
|
|
|
|
char vendor_id[9] = {0};
|
|
|
@@ -110,11 +112,24 @@ static void scan_targets()
|
|
|
|
|
|
if (inquiryok)
|
|
|
{
|
|
|
- logmsg("Found SCSI drive with ID ", target_id, ": ", vendor_id, " ", product_id);
|
|
|
- g_msc_initiator_targets[g_msc_initiator_target_count].target_id = target_id;
|
|
|
- g_msc_initiator_targets[g_msc_initiator_target_count].sectorcount = sectorcount;
|
|
|
- g_msc_initiator_targets[g_msc_initiator_target_count].sectorsize = sectorsize;
|
|
|
- g_msc_initiator_target_count++;
|
|
|
+ if (readcapok)
|
|
|
+ {
|
|
|
+ logmsg("Found SCSI drive with ID ", target_id, ": ", vendor_id, " ", product_id,
|
|
|
+ " capacity ", (int)(((uint64_t)sectorcount * sectorsize) / 1024 / 1024), " MB");
|
|
|
+ g_msc_initiator_targets[found_count].target_id = target_id;
|
|
|
+ g_msc_initiator_targets[found_count].sectorcount = sectorcount;
|
|
|
+ g_msc_initiator_targets[found_count].sectorsize = sectorsize;
|
|
|
+ found_count++;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ logmsg("Found SCSI drive with ID ", target_id, ": ", vendor_id, " ", product_id,
|
|
|
+ " but failed to read capacity. Assuming SCSI-1 drive up to 1 GB.");
|
|
|
+ g_msc_initiator_targets[found_count].target_id = target_id;
|
|
|
+ g_msc_initiator_targets[found_count].sectorcount = 2097152;
|
|
|
+ g_msc_initiator_targets[found_count].sectorsize = 512;
|
|
|
+ found_count++;
|
|
|
+ }
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
@@ -122,6 +137,9 @@ static void scan_targets()
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
+
|
|
|
+ // USB MSC requests can start processing after we set this
|
|
|
+ g_msc_initiator_target_count = found_count;
|
|
|
}
|
|
|
|
|
|
bool setup_msc_initiator()
|
|
|
@@ -153,7 +171,8 @@ void poll_msc_initiator()
|
|
|
uint32_t time_since_scan = time_now - g_msc_initiator_state.last_scan_time;
|
|
|
if (g_msc_initiator_target_count == 0 && time_since_scan > 5000)
|
|
|
{
|
|
|
- // Scan for targets until we find one
|
|
|
+ // Scan for targets until we find one - drive might be slow to start up.
|
|
|
+ // MSC lock is not required here because commands will early exit when target_count is 0.
|
|
|
platform_reset_watchdog();
|
|
|
scan_targets();
|
|
|
g_msc_initiator_state.last_scan_time = time_now;
|
|
|
@@ -221,6 +240,16 @@ static int get_target(uint8_t lun)
|
|
|
|
|
|
void init_msc_inquiry_cb(uint8_t lun, uint8_t vendor_id[8], uint8_t product_id[16], uint8_t product_rev[4])
|
|
|
{
|
|
|
+ dbgmsg("-- MSC Inquiry");
|
|
|
+
|
|
|
+ if (g_msc_initiator_target_count == 0)
|
|
|
+ {
|
|
|
+ memset(vendor_id, 0, 8);
|
|
|
+ memset(product_id, 0, 8);
|
|
|
+ memset(product_rev, 0, 8);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
LED_ON();
|
|
|
g_msc_initiator_state.status_reqcount++;
|
|
|
|
|
|
@@ -246,6 +275,11 @@ uint8_t init_msc_get_maxlun_cb(void)
|
|
|
|
|
|
bool init_msc_is_writable_cb (uint8_t lun)
|
|
|
{
|
|
|
+ if (g_msc_initiator_target_count == 0)
|
|
|
+ {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
LED_ON();
|
|
|
g_msc_initiator_state.status_reqcount++;
|
|
|
|
|
|
@@ -260,6 +294,8 @@ bool init_msc_is_writable_cb (uint8_t lun)
|
|
|
|
|
|
bool init_msc_start_stop_cb(uint8_t lun, uint8_t power_condition, bool start, bool load_eject)
|
|
|
{
|
|
|
+ dbgmsg("-- MSC Start Stop, start: ", (int)start, ", load_eject: ", (int)load_eject);
|
|
|
+
|
|
|
if (g_msc_initiator_target_count == 0)
|
|
|
{
|
|
|
return false;
|
|
|
@@ -294,7 +330,7 @@ bool init_msc_start_stop_cb(uint8_t lun, uint8_t power_condition, bool start, bo
|
|
|
{
|
|
|
uint8_t sense_key;
|
|
|
scsiRequestSense(target, &sense_key);
|
|
|
- logmsg("START STOP UNIT on target ", target, " failed, sense key ", sense_key);
|
|
|
+ scsiLogInitiatorCommandFailure("START STOP UNIT", target, status, sense_key);
|
|
|
}
|
|
|
|
|
|
LED_OFF();
|
|
|
@@ -304,6 +340,8 @@ bool init_msc_start_stop_cb(uint8_t lun, uint8_t power_condition, bool start, bo
|
|
|
|
|
|
bool init_msc_test_unit_ready_cb(uint8_t lun)
|
|
|
{
|
|
|
+ dbgmsg("-- MSC Test Unit Ready");
|
|
|
+
|
|
|
if (g_msc_initiator_target_count == 0)
|
|
|
{
|
|
|
return false;
|
|
|
@@ -315,8 +353,16 @@ bool init_msc_test_unit_ready_cb(uint8_t lun)
|
|
|
|
|
|
void init_msc_capacity_cb(uint8_t lun, uint32_t *block_count, uint16_t *block_size)
|
|
|
{
|
|
|
+ dbgmsg("-- MSC Get Capacity");
|
|
|
g_msc_initiator_state.status_reqcount++;
|
|
|
|
|
|
+ if (g_msc_initiator_target_count == 0)
|
|
|
+ {
|
|
|
+ *block_count = 0;
|
|
|
+ *block_size = 0;
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
uint32_t sectorcount = 0;
|
|
|
uint32_t sectorsize = 0;
|
|
|
scsiInitiatorReadCapacity(get_target(lun), §orcount, §orsize);
|
|
|
@@ -326,6 +372,12 @@ void init_msc_capacity_cb(uint8_t lun, uint32_t *block_count, uint16_t *block_si
|
|
|
|
|
|
int32_t init_msc_scsi_cb(uint8_t lun, const uint8_t scsi_cmd[16], void *buffer, uint16_t bufsize)
|
|
|
{
|
|
|
+ if (g_msc_initiator_target_count == 0)
|
|
|
+ {
|
|
|
+ return -1;
|
|
|
+ }
|
|
|
+
|
|
|
+ dbgmsg("-- MSC Raw SCSI command ", bytearray(scsi_cmd, 16));
|
|
|
LED_ON();
|
|
|
g_msc_initiator_state.status_reqcount++;
|
|
|
|
|
|
@@ -386,6 +438,11 @@ static int do_read6_or_10(int target_id, uint32_t start_sector, uint32_t sectorc
|
|
|
|
|
|
int32_t init_msc_read10_cb(uint8_t lun, uint32_t lba, uint32_t offset, void* buffer, uint32_t bufsize)
|
|
|
{
|
|
|
+ if (g_msc_initiator_target_count == 0)
|
|
|
+ {
|
|
|
+ return -1;
|
|
|
+ }
|
|
|
+
|
|
|
LED_ON();
|
|
|
int status = 0;
|
|
|
|
|
|
@@ -437,8 +494,19 @@ int32_t init_msc_read10_cb(uint8_t lun, uint32_t lba, uint32_t offset, void* buf
|
|
|
uint8_t sense_key;
|
|
|
scsiRequestSense(target_id, &sense_key);
|
|
|
|
|
|
- logmsg("SCSI Initiator read failed: ", status, " sense key ", sense_key);
|
|
|
- return -1;
|
|
|
+ if (sense_key == RECOVERED_ERROR)
|
|
|
+ {
|
|
|
+ dbgmsg("SCSI Initiator read: RECOVERED_ERROR at ", (int)orig_lba);
|
|
|
+ }
|
|
|
+ else if (sense_key == UNIT_ATTENTION)
|
|
|
+ {
|
|
|
+ dbgmsg("SCSI Initiator read: UNIT_ATTENTION");
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ scsiLogInitiatorCommandFailure("SCSI Initiator read", target_id, status, sense_key);
|
|
|
+ return -1;
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
if (lba + total_sectorcount <= g_msc_initiator_targets[lun].sectorcount)
|
|
|
@@ -462,6 +530,11 @@ int32_t init_msc_read10_cb(uint8_t lun, uint32_t lba, uint32_t offset, void* buf
|
|
|
|
|
|
int32_t init_msc_write10_cb(uint8_t lun, uint32_t lba, uint32_t offset, uint8_t *buffer, uint32_t bufsize)
|
|
|
{
|
|
|
+ if (g_msc_initiator_target_count == 0)
|
|
|
+ {
|
|
|
+ return -1;
|
|
|
+ }
|
|
|
+
|
|
|
int status = -1;
|
|
|
|
|
|
int target_id = get_target(lun);
|
|
|
@@ -514,8 +587,19 @@ int32_t init_msc_write10_cb(uint8_t lun, uint32_t lba, uint32_t offset, uint8_t
|
|
|
uint8_t sense_key;
|
|
|
scsiRequestSense(target_id, &sense_key);
|
|
|
|
|
|
- logmsg("SCSI Initiator write failed: ", status, " sense key ", sense_key);
|
|
|
- return -1;
|
|
|
+ if (sense_key == RECOVERED_ERROR)
|
|
|
+ {
|
|
|
+ dbgmsg("SCSI Initiator write: RECOVERED_ERROR at ", (int)start_sector);
|
|
|
+ }
|
|
|
+ else if (sense_key == UNIT_ATTENTION)
|
|
|
+ {
|
|
|
+ dbgmsg("SCSI Initiator write: UNIT_ATTENTION");
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ scsiLogInitiatorCommandFailure("SCSI Initiator write", target_id, status, sense_key);
|
|
|
+ return -1;
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
return sectorcount * sectorsize;
|