qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Qemu-devel] [PATCH 5/5] scsi-block: special case CD burning commands


From: Paolo Bonzini
Subject: [Qemu-devel] [PATCH 5/5] scsi-block: special case CD burning commands
Date: Thu, 10 Nov 2011 17:01:12 +0100

CD burning commands do strange things including writing beyond the
maximum LBA and even to negative blocks for the lead-in.

WRITE(6), WRITE(16), WRITE AND VERIFY(16) are not in MMC.
WRITE AND VERIFY(12) is not in MMC but it seemed a good idea to
treat it like WRITE(12).

Also detect blanking of a disc and reset the maximum LBA.  It's possible
that more special casing is necessary, e.g. for track-at-once, since
those do not start with blanking.

Signed-off-by: Paolo Bonzini <address@hidden>
---
 hw/scsi-disk.c    |   18 +++++++++++++-----
 hw/scsi-generic.c |    5 +++++
 2 files changed, 18 insertions(+), 5 deletions(-)

diff --git a/hw/scsi-disk.c b/hw/scsi-disk.c
index 19e846c..f18a9e6 100644
--- a/hw/scsi-disk.c
+++ b/hw/scsi-disk.c
@@ -1755,17 +1755,25 @@ static SCSIRequest *scsi_block_new_request(SCSIDevice 
*d, uint32_t tag,
     SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, d);
 
     switch (buf[0]) {
-    case READ_6:
-    case READ_10:
-    case READ_12:
-    case READ_16:
-    case WRITE_6:
     case WRITE_10:
     case WRITE_12:
+    case WRITE_VERIFY_10:
+    case WRITE_VERIFY_12:
+        /* Detect if writing the lead-in of a CD, which is represented by
+         * negative LBA addresses.  If so, just pass through.  Also,
+         * when burning the maximum LBA is zero.  Play it safe and pass
+         * those writes through as well.  */
+        if (s->qdev.type == TYPE_ROM && (s->qdev.max_lba == 0 || buf[2] > 
0x7F)) {
+            break;
+        }
+
+    case WRITE_6:
     case WRITE_16:
-    case WRITE_VERIFY_10:
-    case WRITE_VERIFY_12:
     case WRITE_VERIFY_16:
+    case READ_6:
+    case READ_10:
+    case READ_12:
+    case READ_16:
         return scsi_req_alloc(&scsi_disk_reqops, &s->qdev, tag, lun,
                               hba_private);
     }
diff --git a/hw/scsi-generic.c b/hw/scsi-generic.c
index a86e5a8..fb34a33 100644
--- a/hw/scsi-generic.c
+++ b/hw/scsi-generic.c
@@ -236,6 +236,11 @@ static void scsi_read_complete(void * opaque, int ret)
         }
         bdrv_set_buffer_alignment(s->conf.bs, s->blocksize);
 
+        /* ... and BLANK to update the maximum LBA.  */
+        if (s->type == TYPE_ROM && r->req.cmd.buf[0] == BLANK) {
+            s->max_lba = 0;
+        }
+
         scsi_req_data(&r->req, len);
         if (!r->req.io_canceled) {
             scsi_req_unref(&r->req);
-- 
1.7.7.1




reply via email to

[Prev in Thread] Current Thread [Next in Thread]