From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from [140.186.70.92] (port=56417 helo=eggs.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1OtL2Y-0004v4-MA for qemu-devel@nongnu.org; Wed, 08 Sep 2010 09:50:23 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.69) (envelope-from ) id 1OtKic-0005Zs-21 for qemu-devel@nongnu.org; Wed, 08 Sep 2010 09:29:45 -0400 Received: from mx1.redhat.com ([209.132.183.28]:56651) by eggs.gnu.org with esmtp (Exim 4.69) (envelope-from ) id 1OtKib-0005ZZ-S3 for qemu-devel@nongnu.org; Wed, 08 Sep 2010 09:29:42 -0400 From: Kevin Wolf Date: Wed, 8 Sep 2010 15:29:29 +0200 Message-Id: <1283952582-17498-13-git-send-email-kwolf@redhat.com> In-Reply-To: <1283952582-17498-1-git-send-email-kwolf@redhat.com> References: <1283952582-17498-1-git-send-email-kwolf@redhat.com> Subject: [Qemu-devel] [PATCH 12/25] scsi-disk: fix the mode data header returned by the MODE SENSE(10) command List-Id: qemu-devel.nongnu.org List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: anthony@codemonkey.ws Cc: kwolf@redhat.com, qemu-devel@nongnu.org From: Bernhard Kohl The header for the MODE SENSE(10) command is 8 bytes long. Signed-off-by: Bernhard Kohl Signed-off-by: Kevin Wolf --- hw/scsi-disk.c | 38 ++++++++++++++++++++++++++++++++------ 1 files changed, 32 insertions(+), 6 deletions(-) diff --git a/hw/scsi-disk.c b/hw/scsi-disk.c index b627ffe..3e727b9 100644 --- a/hw/scsi-disk.c +++ b/hw/scsi-disk.c @@ -607,6 +607,7 @@ static int scsi_disk_emulate_mode_sense(SCSIRequest *req, uint8_t *outbuf) uint64_t nb_sectors; int page, dbd, buflen; uint8_t *p; + uint8_t dev_specific_param; dbd = req->cmd.buf[1] & 0x8; page = req->cmd.buf[2] & 0x3f; @@ -614,16 +615,31 @@ static int scsi_disk_emulate_mode_sense(SCSIRequest *req, uint8_t *outbuf) memset(outbuf, 0, req->cmd.xfer); p = outbuf; - p[1] = 0; /* Default media type. */ - p[3] = 0; /* Block descriptor length. */ if (bdrv_is_read_only(s->bs)) { - p[2] = 0x80; /* Readonly. */ + dev_specific_param = 0x80; /* Readonly. */ + } else { + dev_specific_param = 0x00; + } + + if (req->cmd.buf[0] == MODE_SENSE) { + p[1] = 0; /* Default media type. */ + p[2] = dev_specific_param; + p[3] = 0; /* Block descriptor length. */ + p += 4; + } else { /* MODE_SENSE_10 */ + p[2] = 0; /* Default media type. */ + p[3] = dev_specific_param; + p[6] = p[7] = 0; /* Block descriptor length. */ + p += 8; } - p += 4; bdrv_get_geometry(s->bs, &nb_sectors); if ((~dbd) & nb_sectors) { - outbuf[3] = 8; /* Block descriptor length */ + if (req->cmd.buf[0] == MODE_SENSE) { + outbuf[3] = 8; /* Block descriptor length */ + } else { /* MODE_SENSE_10 */ + outbuf[7] = 8; /* Block descriptor length */ + } nb_sectors /= s->cluster_size; nb_sectors--; if (nb_sectors > 0xffffff) @@ -653,7 +669,17 @@ static int scsi_disk_emulate_mode_sense(SCSIRequest *req, uint8_t *outbuf) } buflen = p - outbuf; - outbuf[0] = buflen - 1; + /* + * The mode data length field specifies the length in bytes of the + * following data that is available to be transferred. The mode data + * length does not include itself. + */ + if (req->cmd.buf[0] == MODE_SENSE) { + outbuf[0] = buflen - 1; + } else { /* MODE_SENSE_10 */ + outbuf[0] = ((buflen - 2) >> 8) & 0xff; + outbuf[1] = (buflen - 2) & 0xff; + } if (buflen > req->cmd.xfer) buflen = req->cmd.xfer; return buflen; -- 1.7.2.2