scsi-disk: support DVD profile in GET CONFIGURATION

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
This commit is contained in:
Paolo Bonzini 2011-09-13 15:22:31 +02:00 committed by Kevin Wolf
parent a07c7dcd6f
commit 430ee2f26f

View file

@ -567,6 +567,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)
{
@ -581,17 +594,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 */
stw_be_p(&outbuf[6], current);
/* outbuf[8] - outbuf[19]: Feature 0 - Profile list */
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)
@ -1024,7 +1058,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;
}