From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([140.186.70.92]:40934) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1RKruL-0004yJ-Jt for qemu-devel@nongnu.org; Mon, 31 Oct 2011 09:28:13 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1RKruK-0004Jt-6z for qemu-devel@nongnu.org; Mon, 31 Oct 2011 09:28:09 -0400 Received: from mx1.redhat.com ([209.132.183.28]:23893) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1RKruJ-0004Ja-VG for qemu-devel@nongnu.org; Mon, 31 Oct 2011 09:28:08 -0400 From: Kevin Wolf Date: Mon, 31 Oct 2011 14:30:04 +0100 Message-Id: <1320067830-12093-30-git-send-email-kwolf@redhat.com> In-Reply-To: <1320067830-12093-1-git-send-email-kwolf@redhat.com> References: <1320067830-12093-1-git-send-email-kwolf@redhat.com> Subject: [Qemu-devel] [PATCH 29/55] scsi-disk: support READ DVD STRUCTURE List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: anthony@codemonkey.ws Cc: kwolf@redhat.com, qemu-devel@nongnu.org From: Paolo Bonzini Signed-off-by: Paolo Bonzini Signed-off-by: Kevin Wolf --- hw/scsi-disk.c | 102 +++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 files changed, 101 insertions(+), 1 deletions(-) diff --git a/hw/scsi-disk.c b/hw/scsi-disk.c index 38b196b..8f8a94d 100644 --- a/hw/scsi-disk.c +++ b/hw/scsi-disk.c @@ -580,10 +580,110 @@ static inline bool media_is_dvd(SCSIDiskState *s) return nb_sectors > CD_MAX_SECTORS; } +static inline bool media_is_cd(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) { - scsi_check_condition(r, SENSE_CODE(INVALID_OPCODE)); + static const int rds_caps_size[5] = { + [0] = 2048 + 4, + [1] = 4 + 4, + [3] = 188 + 4, + [4] = 2048 + 4, + }; + + uint8_t media = r->req.cmd.buf[1]; + uint8_t layer = r->req.cmd.buf[6]; + uint8_t format = r->req.cmd.buf[7]; + int size = -1; + + if (s->qdev.type != TYPE_ROM) { + return -1; + } + if (media != 0) { + scsi_check_condition(r, SENSE_CODE(INVALID_FIELD)); + return -1; + } + + if (format != 0xff) { + if (s->tray_open || !bdrv_is_inserted(s->bs)) { + scsi_check_condition(r, SENSE_CODE(NO_MEDIUM)); + return -1; + } + if (media_is_cd(s)) { + scsi_check_condition(r, SENSE_CODE(INCOMPATIBLE_FORMAT)); + return -1; + } + if (format >= ARRAY_SIZE(rds_caps_size)) { + return -1; + } + size = rds_caps_size[format]; + memset(outbuf, 0, size); + } + + switch (format) { + case 0x00: { + /* Physical format information */ + uint64_t nb_sectors; + if (layer != 0) { + goto fail; + } + bdrv_get_geometry(s->bs, &nb_sectors); + + outbuf[4] = 1; /* DVD-ROM, part version 1 */ + outbuf[5] = 0xf; /* 120mm disc, minimum rate unspecified */ + outbuf[6] = 1; /* one layer, read-only (per MMC-2 spec) */ + outbuf[7] = 0; /* default densities */ + + stl_be_p(&outbuf[12], (nb_sectors >> 2) - 1); /* end sector */ + stl_be_p(&outbuf[16], (nb_sectors >> 2) - 1); /* l0 end sector */ + break; + } + + case 0x01: /* DVD copyright information, all zeros */ + break; + + case 0x03: /* BCA information - invalid field for no BCA info */ + return -1; + + case 0x04: /* DVD disc manufacturing information, all zeros */ + break; + + case 0xff: { /* List capabilities */ + int i; + size = 4; + for (i = 0; i < ARRAY_SIZE(rds_caps_size); i++) { + if (!rds_caps_size[i]) { + continue; + } + outbuf[size] = i; + outbuf[size + 1] = 0x40; /* Not writable, readable */ + stw_be_p(&outbuf[size + 2], rds_caps_size[i]); + size += 4; + } + break; + } + + default: + return -1; + } + + /* Size of buffer, not including 2 byte size field */ + stw_be_p(outbuf, size - 2); + return size; + +fail: return -1; } -- 1.7.6.4