From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([140.186.70.92]:55545) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1REJ63-0007Fg-EV for qemu-devel@nongnu.org; Thu, 13 Oct 2011 07:05:11 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1REJ5t-0004Hw-BN for qemu-devel@nongnu.org; Thu, 13 Oct 2011 07:05:07 -0400 Received: from mail-wy0-f173.google.com ([74.125.82.173]:61406) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1REJ5t-00048s-6f for qemu-devel@nongnu.org; Thu, 13 Oct 2011 07:04:57 -0400 Received: by mail-wy0-f173.google.com with SMTP id 22so1888325wyh.4 for ; Thu, 13 Oct 2011 04:04:56 -0700 (PDT) Sender: Paolo Bonzini From: Paolo Bonzini Date: Thu, 13 Oct 2011 13:03:57 +0200 Message-Id: <1318503845-11473-28-git-send-email-pbonzini@redhat.com> In-Reply-To: <1318503845-11473-1-git-send-email-pbonzini@redhat.com> References: <1318503845-11473-1-git-send-email-pbonzini@redhat.com> Subject: [Qemu-devel] [PATCH 27/35] scsi-generic: snoop READ CAPACITY commands to get block size List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: qemu-devel@nongnu.org Instead of "guessing" the block size when there is no medium in the drive, wait for the guest to send a READ CAPACITY command and retrieve it from there. Signed-off-by: Paolo Bonzini --- hw/scsi-generic.c | 50 +++++++++++--------------------------------------- 1 files changed, 11 insertions(+), 39 deletions(-) diff --git a/hw/scsi-generic.c b/hw/scsi-generic.c index 787c581..cb02a7e 100644 --- a/hw/scsi-generic.c +++ b/hw/scsi-generic.c @@ -155,6 +155,7 @@ static int execute_command(BlockDriverState *bdrv, static void scsi_read_complete(void * opaque, int ret) { SCSIGenericReq *r = (SCSIGenericReq *)opaque; + SCSIDevice *s = r->req.dev; int len; r->req.aiocb = NULL; @@ -170,6 +171,15 @@ static void scsi_read_complete(void * opaque, int ret) if (len == 0) { scsi_command_complete(r, 0); } else { + /* Snoop READ CAPACITY output to set the blocksize. */ + if (r->req.cmd.buf[0] == READ_CAPACITY_10) { + s->blocksize = ldl_be_p(&r->buf[4]); + } else if (r->req.cmd.buf[0] == SERVICE_ACTION_IN_16 && + (r->req.cmd.buf[1] & 31) == SAI_READ_CAPACITY_16) { + s->blocksize = ldl_be_p(&r->buf[8]); + } + bdrv_set_buffer_alignment(s->conf.bs, s->blocksize); + scsi_req_data(&r->req, len); } } @@ -299,36 +309,6 @@ static int32_t scsi_send_command(SCSIRequest *req, uint8_t *cmd) } } -static int get_blocksize(BlockDriverState *bdrv) -{ - uint8_t cmd[10]; - uint8_t buf[8]; - uint8_t sensebuf[8]; - sg_io_hdr_t io_header; - int ret; - - memset(cmd, 0, sizeof(cmd)); - memset(buf, 0, sizeof(buf)); - cmd[0] = READ_CAPACITY_10; - - memset(&io_header, 0, sizeof(io_header)); - io_header.interface_id = 'S'; - io_header.dxfer_direction = SG_DXFER_FROM_DEV; - io_header.dxfer_len = sizeof(buf); - io_header.dxferp = buf; - io_header.cmdp = cmd; - io_header.cmd_len = sizeof(cmd); - io_header.mx_sb_len = sizeof(sensebuf); - io_header.sbp = sensebuf; - io_header.timeout = 6000; /* XXX */ - - ret = bdrv_ioctl(bdrv, SG_IO, &io_header); - if (ret < 0 || io_header.driver_status || io_header.host_status) - return -1; - - return (buf[4] << 24) | (buf[5] << 16) | (buf[6] << 8) | buf[7]; -} - static int get_stream_blocksize(BlockDriverState *bdrv) { uint8_t cmd[6]; @@ -413,20 +393,12 @@ static int scsi_generic_initfn(SCSIDevice *s) /* define device state */ s->type = scsiid.scsi_type; + s->blocksize = 0; DPRINTF("device type %d\n", s->type); if (s->type == TYPE_TAPE) { s->blocksize = get_stream_blocksize(s->conf.bs); if (s->blocksize == -1) s->blocksize = 0; - } else { - s->blocksize = get_blocksize(s->conf.bs); - /* removable media returns 0 if not present */ - if (s->blocksize <= 0) { - if (s->type == TYPE_ROM || s->type == TYPE_WORM) - s->blocksize = 2048; - else - s->blocksize = 512; - } } DPRINTF("block size %d\n", s->blocksize); -- 1.7.6