From c5caa015c1e745f3e529be1054523fb9cbfa33c8 Mon Sep 17 00:00:00 2001
From: Paolo Bonzini <pbonzini@redhat.com>
Date: Wed, 22 Feb 2012 14:12:05 +0100
Subject: [PATCH 049/109] scsi-disk: support DVD profile in GET CONFIGURATION

RH-Author: Paolo Bonzini <pbonzini@redhat.com>
Message-id: <1329919979-20948-49-git-send-email-pbonzini@redhat.com>
Patchwork-id: 37529
O-Subject: [RHEL 6.3 qemu-kvm PATCH v2 048/102] scsi-disk: support DVD profile in GET CONFIGURATION
Bugzilla: 782029
RH-Acked-by: Laszlo Ersek <lersek@redhat.com>
RH-Acked-by: Orit Wasserman <owasserm@redhat.com>
RH-Acked-by: Gerd Hoffmann <kraxel@redhat.com>

Upstream used st*_be_p functions, which are not available to
common code in RHEL6 qemu.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
(cherry picked from 430ee2f26f01f146f3757467b3f0b802ad309ff8)
---
 hw/scsi-disk.c |   51 +++++++++++++++++++++++++++++++++++++++++++--------
 1 files changed, 43 insertions(+), 8 deletions(-)

Signed-off-by: Michal Novotny <minovotn@redhat.com>
---
 hw/scsi-disk.c |   51 +++++++++++++++++++++++++++++++++++++++++++--------
 1 files changed, 43 insertions(+), 8 deletions(-)

diff --git a/hw/scsi-disk.c b/hw/scsi-disk.c
index 7e6b0df..771721d 100644
--- a/hw/scsi-disk.c
+++ b/hw/scsi-disk.c
@@ -601,6 +601,19 @@ static int scsi_disk_emulate_inquiry(SCSIRequest *req, uint8_t *outbuf)
     return buflen;
 }
 
+static inline bool media_is_dvd(SCSIDiskState *s)
+{
+    uint64_t nb_sectors;
+    if (s->qdev.type != TYPE_ROM) {
+        return false;
+    }
+    if (!bdrv_is_inserted(s->bs)) {
+        return false;
+    }
+    bdrv_get_geometry(s->bs, &nb_sectors);
+    return nb_sectors > CD_MAX_SECTORS;
+}
+
 static int scsi_read_dvd_structure(SCSIDiskState *s, SCSIDiskReq *r,
                                    uint8_t *outbuf)
 {
@@ -615,17 +628,39 @@ static int scsi_get_event_status_notification(SCSIDiskState *s,
     return -1;
 }
 
-static int scsi_get_configuration(SCSIDiskState *s, SCSIDiskReq *r,
-                                  uint8_t *outbuf)
+static int scsi_get_configuration(SCSIDiskState *s, uint8_t *outbuf)
 {
+    int current;
+
     if (s->qdev.type != TYPE_ROM) {
         return -1;
     }
-    memset(outbuf, 0, 8);
-    /* ??? This should probably return much more information.  For now
-       just return the basic header indicating the CD-ROM profile.  */
-    outbuf[7] = 8; /* CD-ROM */
-    return 8;
+    current = media_is_dvd(s) ? MMC_PROFILE_DVD_ROM : MMC_PROFILE_CD_ROM;
+    memset(outbuf, 0, 40);
+    outbuf[3] = 36; /* Bytes after the data length field */
+    outbuf[6] = current >> 8;
+    outbuf[7] = current;
+    /* outbuf[8] - outbuf[19]: Feature 0 - Profile list */
+    outbuf[10] = 0x03; /* persistent, current */
+    outbuf[11] = 8; /* two profiles */
+    outbuf[13] = MMC_PROFILE_DVD_ROM;
+    outbuf[14] = (current == MMC_PROFILE_DVD_ROM);
+    outbuf[17] = MMC_PROFILE_CD_ROM;
+    outbuf[18] = (current == MMC_PROFILE_CD_ROM);
+    /* outbuf[20] - outbuf[31]: Feature 1 - Core feature */
+    outbuf[21] = 1;
+    outbuf[22] = 0x08 | 0x03; /* version 2, persistent, current */
+    outbuf[23] = 8;
+    outbuf[27] = 1; /* SCSI */
+    outbuf[28] = 1; /* DBE = 1, mandatory */
+    /* outbuf[32] - outbuf[39]: Feature 3 - Removable media feature */
+    outbuf[33] = 3;
+    outbuf[34] = 0x08 | 0x03; /* version 2, persistent, current */
+    outbuf[35] = 4;
+    outbuf[36] = 0x39; /* tray, load=1, eject=1, unlocked at powerup, lock=1 */
+    /* TODO: Random readable, CD read, DVD read, drive serial number,
+       power management */
+    return 40;
 }
 
 static int scsi_emulate_mechanism_status(SCSIDiskState *s, uint8_t *outbuf)
@@ -1058,7 +1093,7 @@ static int scsi_disk_emulate_command(SCSIDiskReq *r)
         }
         break;
     case GET_CONFIGURATION:
-        buflen = scsi_get_configuration(s, r, outbuf);
+        buflen = scsi_get_configuration(s, outbuf);
         if (buflen < 0) {
             goto illegal_request;
         }
-- 
1.7.7.6

