Add the wait loop that CDs are already using to usb-msc in the HD case, to cope with a NOT READY or UNIT ATTENTION condition.
Signed-off-by: Paolo Bonzini pbonzini@redhat.com --- src/blockcmd.c | 44 ++++++++++++++++++++++++++++++++++++++++++++ src/blockcmd.h | 2 ++ src/cdrom.c | 48 ++---------------------------------------------- src/usb-msc.c | 7 ++++++- 4 files changed, 54 insertions(+), 47 deletions(-)
diff --git a/src/blockcmd.c b/src/blockcmd.c index f5e2ce3..e86fe29 100644 --- a/src/blockcmd.c +++ b/src/blockcmd.c @@ -32,6 +32,50 @@ cdb_cmd_data(struct disk_op_s *op, void *cdbcmd, u16 blocksize) }
int +scsi_is_ready(struct disk_op_s *op) +{ + dprintf(6, "scsi_is_ready (drive=%p)\n", op->drive_g); + + /* Retry TEST UNIT READY for 5 seconds unless MEDIUM NOT PRESENT is + * reported by the device. If the device reports "IN PROGRESS", + * 30 seconds is added. */ + int in_progress = 0; + u64 end = calc_future_tsc(5000); + for (;;) { + if (check_tsc(end)) { + dprintf(1, "test unit ready failed\n"); + return -1; + } + + int ret = cdb_test_unit_ready(op); + if (!ret) + // Success + break; + + struct cdbres_request_sense sense; + ret = cdb_get_sense(op, &sense); + if (ret) + // Error - retry. + continue; + + // Sense succeeded. + if (sense.asc == 0x3a) { /* MEDIUM NOT PRESENT */ + dprintf(1, "Device reports MEDIUM NOT PRESENT\n"); + return -1; + } + + if (sense.asc == 0x04 && sense.ascq == 0x01 && !in_progress) { + /* IN PROGRESS OF BECOMING READY */ + printf("Waiting for device to detect medium... "); + /* Allow 30 seconds more */ + end = calc_future_tsc(30000); + in_progress = 1; + } + } + return 0; +} + +int cdb_get_inquiry(struct disk_op_s *op, struct cdbres_inquiry *data) { struct cdb_request_sense cmd; diff --git a/src/blockcmd.h b/src/blockcmd.h index 6923e4c..106a529 100644 --- a/src/blockcmd.h +++ b/src/blockcmd.h @@ -80,4 +80,6 @@ int cdb_inquiry(struct disk_op_s *op, struct cdbres_inquiry *data); int cdb_read(struct disk_op_s *op); int cdb_write(struct disk_op_s *op);
+int scsi_is_ready(struct disk_op_s *op); + #endif // blockcmd.h diff --git a/src/cdrom.c b/src/cdrom.c index b817999..170ffc4 100644 --- a/src/cdrom.c +++ b/src/cdrom.c @@ -184,50 +184,6 @@ cdemu_134b(struct bregs *regs) * CD booting ****************************************************************/
-static int -atapi_is_ready(struct disk_op_s *op) -{ - dprintf(6, "atapi_is_ready (drive=%p)\n", op->drive_g); - - /* Retry TEST UNIT READY for 5 seconds unless MEDIUM NOT PRESENT is - * reported by the device. If the device reports "IN PROGRESS", - * 30 seconds is added. */ - int in_progress = 0; - u64 end = calc_future_tsc(5000); - for (;;) { - if (check_tsc(end)) { - dprintf(1, "test unit ready failed\n"); - return -1; - } - - int ret = cdb_test_unit_ready(op); - if (!ret) - // Success - break; - - struct cdbres_request_sense sense; - ret = cdb_get_sense(op, &sense); - if (ret) - // Error - retry. - continue; - - // Sense succeeded. - if (sense.asc == 0x3a) { /* MEDIUM NOT PRESENT */ - dprintf(1, "Device reports MEDIUM NOT PRESENT\n"); - return -1; - } - - if (sense.asc == 0x04 && sense.ascq == 0x01 && !in_progress) { - /* IN PROGRESS OF BECOMING READY */ - printf("Waiting for device to detect medium... "); - /* Allow 30 seconds more */ - end = calc_future_tsc(30000); - in_progress = 1; - } - } - return 0; -} - int cdrom_boot(struct drive_s *drive_g) { @@ -238,9 +194,9 @@ cdrom_boot(struct drive_s *drive_g) if (!dop.drive_g || cdid < 0) return 1;
- int ret = atapi_is_ready(&dop); + int ret = scsi_is_ready(&dop); if (ret) - dprintf(1, "atapi_is_ready returned %d\n", ret); + dprintf(1, "scsi_is_ready returned %d\n", ret);
// Read the Boot Record Volume Descriptor u8 buffer[2048]; diff --git a/src/usb-msc.c b/src/usb-msc.c index 115aaef..6617a9f 100644 --- a/src/usb-msc.c +++ b/src/usb-msc.c @@ -243,11 +243,16 @@ usb_msc_init(struct usb_pipe *pipe , vendor, product, rev); ret = setup_drive_cdrom(&udrive_g->drive, desc); } else { + ret = scsi_is_ready(&dop); + if (ret) { + dprintf(1, "scsi_is_ready returned %d\n", ret); + return ret; + } + struct cdbres_read_capacity capdata; ret = cdb_read_capacity(&dop, &capdata); if (ret) return ret; - // XXX - retry for some timeout?
// READ CAPACITY returns the address of the last block udrive_g->drive.blksize = ntohl(capdata.blksize);