diff options
-rw-r--r-- | 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 116e562bb8..38b196bd13 100644 --- a/hw/scsi-disk.c +++ b/hw/scsi-disk.c @@ -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; } |