]> xenbits.xensource.com Git - seabios.git/commitdiff
scsi: do not send MODE SENSE except to QEMU disks
authorPaolo Bonzini <pbonzini@redhat.com>
Mon, 5 Mar 2012 11:29:12 +0000 (12:29 +0100)
committerKevin O'Connor <kevin@koconnor.net>
Tue, 6 Mar 2012 12:18:38 +0000 (07:18 -0500)
This is the simplest way to avoid breaking boot on USB sticks that
stall when asked for the MODE SENSE page 4.  Some old sticks do
not support the MODE SENSE command at all and just return a
"medium may have changed" unit attention condition when SeaBIOS
sends it!

Reported-by: Dave Frodin <dave@camp.se-eng.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
src/blockcmd.c

index 7ac7fc8f476ae4c0ffb7f88ae9dc6cf95364481b..d51e84e03d9ab88f30c73f1a9dbaa7af7b8bb3ac 100644 (file)
@@ -137,19 +137,29 @@ scsi_init_drive(struct drive_s *drive, const char *s, int prio)
     dprintf(1, "%s blksize=%d sectors=%d\n"
             , s, drive->blksize, (unsigned)drive->sectors);
 
-    struct cdbres_mode_sense_geom geomdata;
-    ret = cdb_mode_sense_geom(&dop, &geomdata);
-    if (ret == 0) {
-        u32 cylinders;
-        cylinders = geomdata.cyl[0] << 16;
-        cylinders |= geomdata.cyl[1] << 8;
-        cylinders |= geomdata.cyl[2];
-        if (cylinders && geomdata.heads &&
-            drive->sectors <= 0xFFFFFFFFULL &&
-            ((u32)drive->sectors % (geomdata.heads * cylinders) == 0)) {
-            drive->pchs.cylinders = cylinders;
-            drive->pchs.heads = geomdata.heads;
-            drive->pchs.spt = (u32)drive->sectors / (geomdata.heads * cylinders);
+    // We do not recover from USB stalls, so try to be safe and avoid
+    // sending the command if the (obsolete, but still provided by QEMU)
+    // fixed disk geometry page may not be supported.
+    //
+    // We could also send the command only to small disks (e.g. <504MiB)
+    // but some old USB keys only support a very small subset of SCSI which
+    // does not even include the MODE SENSE command!
+    //
+    if (! CONFIG_COREBOOT && memcmp(vendor, "QEMU    ", 8) == 0) {
+        struct cdbres_mode_sense_geom geomdata;
+        ret = cdb_mode_sense_geom(&dop, &geomdata);
+        if (ret == 0) {
+            u32 cylinders;
+            cylinders = geomdata.cyl[0] << 16;
+            cylinders |= geomdata.cyl[1] << 8;
+            cylinders |= geomdata.cyl[2];
+            if (cylinders && geomdata.heads &&
+                drive->sectors <= 0xFFFFFFFFULL &&
+                ((u32)drive->sectors % (geomdata.heads * cylinders) == 0)) {
+                drive->pchs.cylinders = cylinders;
+                drive->pchs.heads = geomdata.heads;
+                drive->pchs.spt = (u32)drive->sectors / (geomdata.heads * cylinders);
+            }
         }
     }