usb-msc: go through TEST UNIT READY for hard disks.
authorPaolo Bonzini <pbonzini@redhat.com>
Wed, 16 Nov 2011 12:02:51 +0000 (13:02 +0100)
committerKevin O'Connor <kevin@koconnor.net>
Fri, 18 Nov 2011 02:21:02 +0000 (21:21 -0500)
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
src/blockcmd.h
src/cdrom.c
src/usb-msc.c

index f5e2ce3f70518ba85bd504e2bb23486bd9056fdd..e86fe29c86d7dd6fb071a62fa5ee6a2a78be2346 100644 (file)
@@ -31,6 +31,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)
 {
index 6923e4c9f2620a765e0e039489049f607f9340d6..106a5294a576801f519ac455a0af1a1321c45357 100644 (file)
@@ -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
index b8179991da2f63211ab8cf259f1a64705f029437..170ffc482375f4829b35e0e718afb396db0f8d5b 100644 (file)
@@ -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];
index bed6495fd3b579efe5bd8789d0a265b1fc1a997f..2bdc957b30c0b2cbaa433cedd1fb10b7e9cdfa78 100644 (file)
@@ -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);