usb-msc: go through TEST UNIT READY for hard disks.
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>
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 @@
}
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_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 @@
* 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 @@
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 bed6495..2bdc957 100644
--- a/src/usb-msc.c
+++ b/src/usb-msc.c
@@ -243,11 +243,16 @@
, 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);