diff mbox

[10/35] scsi-disk: support DVD profile in GET CONFIGURATION

Message ID 1318503845-11473-11-git-send-email-pbonzini@redhat.com
State New
Headers show

Commit Message

Paolo Bonzini Oct. 13, 2011, 11:03 a.m. UTC
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 hw/scsi-disk.c |   50 ++++++++++++++++++++++++++++++++++++++++++--------
 1 files changed, 42 insertions(+), 8 deletions(-)

Comments

Kevin Wolf Oct. 17, 2011, 3:20 p.m. UTC | #1
Am 13.10.2011 13:03, schrieb Paolo Bonzini:
> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
> ---
>  hw/scsi-disk.c |   50 ++++++++++++++++++++++++++++++++++++++++++--------
>  1 files changed, 42 insertions(+), 8 deletions(-)
> 
> diff --git a/hw/scsi-disk.c b/hw/scsi-disk.c
> index 837747f..1786c37 100644
> --- a/hw/scsi-disk.c
> +++ b/hw/scsi-disk.c
> @@ -563,6 +563,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)
>  {
> @@ -577,17 +590,38 @@ 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);

Is the memset required at all? I seem to remember that the output buffer
was zeroed in generic code.

> +    stl_be_p(&outbuf[0], 36); /* Bytes after the data length field */
> +    /* outbuf[4] - outbuf[19]: Feature 0 - Profile list */

Isn't it outbuf[8] - outbuf[19]?

> +    stw_be_p(&outbuf[6], current);
> +    outbuf[10] = 0x03; /* persistent, current */
> +    outbuf[11] = 8; /* two profiles */
> +    stw_be_p(&outbuf[12], MMC_PROFILE_DVD_ROM);
> +    outbuf[14] = (current == MMC_PROFILE_DVD_ROM);
> +    stw_be_p(&outbuf[16], MMC_PROFILE_CD_ROM);
> +    outbuf[18] = (current == MMC_PROFILE_CD_ROM);
> +    /* outbuf[20] - outbuf[31]: Feature 1 - Core feature */
> +    stw_be_p(&outbuf[20], 1);
> +    outbuf[22] = 0x08 | 0x03; /* version 2, persistent, current */
> +    outbuf[23] = 8;
> +    stl_be_p(&outbuf[24], 1); /* SCSI */
> +    outbuf[28] = 1; /* DBE = 1, mandatory */
> +    /* outbuf[32] - outbuf[39]: Feature 3 - Removable media feature */
> +    stw_be_p(&outbuf[32], 3);
> +    outbuf[34] = 0x08 | 0x03; /* version 2, persistent, current */

MMC-5 doesn't know version 2, so I can't check this.

> +    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;
>  }

And some blank lines wouldn't hurt. :-)

>  
>  static int scsi_emulate_mechanism_status(SCSIDiskState *s, uint8_t *outbuf)
> @@ -1006,7 +1040,7 @@ static int scsi_disk_emulate_command(SCSIDiskReq *r)
>              goto illegal_request;
>          break;
>      case GET_CONFIGURATION:
> -        buflen = scsi_get_configuration(s, r, outbuf);
> +        buflen = scsi_get_configuration(s, outbuf);
>          if (buflen < 0)
>              goto illegal_request;
>          break;

Kevin
Paolo Bonzini Oct. 17, 2011, 3:28 p.m. UTC | #2
On 10/17/2011 05:20 PM, Kevin Wolf wrote:
>> >  +    current = media_is_dvd(s) ? MMC_PROFILE_DVD_ROM : MMC_PROFILE_CD_ROM;
>> >  +    memset(outbuf, 0, 40);
> Is the memset required at all? I seem to remember that the output buffer
> was zeroed in generic code.

No, it isn't.

>> >  +    stl_be_p(&outbuf[0], 36); /* Bytes after the data length field */
>> >  +    /* outbuf[4] - outbuf[19]: Feature 0 - Profile list */
>
> Isn't it outbuf[8] - outbuf[19]?

Right.

Paolo
diff mbox

Patch

diff --git a/hw/scsi-disk.c b/hw/scsi-disk.c
index 837747f..1786c37 100644
--- a/hw/scsi-disk.c
+++ b/hw/scsi-disk.c
@@ -563,6 +563,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)
 {
@@ -577,17 +590,38 @@  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);
+    stl_be_p(&outbuf[0], 36); /* Bytes after the data length field */
+    /* outbuf[4] - outbuf[19]: Feature 0 - Profile list */
+    stw_be_p(&outbuf[6], current);
+    outbuf[10] = 0x03; /* persistent, current */
+    outbuf[11] = 8; /* two profiles */
+    stw_be_p(&outbuf[12], MMC_PROFILE_DVD_ROM);
+    outbuf[14] = (current == MMC_PROFILE_DVD_ROM);
+    stw_be_p(&outbuf[16], MMC_PROFILE_CD_ROM);
+    outbuf[18] = (current == MMC_PROFILE_CD_ROM);
+    /* outbuf[20] - outbuf[31]: Feature 1 - Core feature */
+    stw_be_p(&outbuf[20], 1);
+    outbuf[22] = 0x08 | 0x03; /* version 2, persistent, current */
+    outbuf[23] = 8;
+    stl_be_p(&outbuf[24], 1); /* SCSI */
+    outbuf[28] = 1; /* DBE = 1, mandatory */
+    /* outbuf[32] - outbuf[39]: Feature 3 - Removable media feature */
+    stw_be_p(&outbuf[32], 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)
@@ -1006,7 +1040,7 @@  static int scsi_disk_emulate_command(SCSIDiskReq *r)
             goto illegal_request;
         break;
     case GET_CONFIGURATION:
-        buflen = scsi_get_configuration(s, r, outbuf);
+        buflen = scsi_get_configuration(s, outbuf);
         if (buflen < 0)
             goto illegal_request;
         break;