From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mailman by lists.gnu.org with tmda-scanned (Exim 4.43) id 1IxMry-0000pW-Ds for qemu-devel@nongnu.org; Wed, 28 Nov 2007 08:22:26 -0500 Received: from exim by lists.gnu.org with spam-scanned (Exim 4.43) id 1IxMrx-0000ox-B4 for qemu-devel@nongnu.org; Wed, 28 Nov 2007 08:22:25 -0500 Received: from [199.232.76.173] (helo=monty-python.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1IxMrx-0000ot-5K for qemu-devel@nongnu.org; Wed, 28 Nov 2007 08:22:25 -0500 Received: from ecfrec.frec.bull.fr ([129.183.4.8]) by monty-python.gnu.org with esmtp (Exim 4.60) (envelope-from ) id 1IxMrv-0001Q8-R1 for qemu-devel@nongnu.org; Wed, 28 Nov 2007 08:22:25 -0500 Received: from localhost (localhost [127.0.0.1]) by ecfrec.frec.bull.fr (Postfix) with ESMTP id 268F219D9F9 for ; Wed, 28 Nov 2007 14:21:48 +0100 (CET) Received: from ecfrec.frec.bull.fr ([127.0.0.1]) by localhost (ecfrec.frec.bull.fr [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id 13434-08 for ; Wed, 28 Nov 2007 14:21:44 +0100 (CET) Received: from ecn002.frec.bull.fr (ecn002.frec.bull.fr [129.183.4.6]) by ecfrec.frec.bull.fr (Postfix) with ESMTP id 9535519D9F7 for ; Wed, 28 Nov 2007 14:21:37 +0100 (CET) In-Reply-To: <11962562172906@bull.net> Date: Wed, 28 Nov 2007 14:23:40 +0100 Message-Id: <11962562201796@bull.net> Mime-Version: 1.0 From: Laurent Vivier Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="iso-8859-1" Subject: [Qemu-devel] [PATCH 2/3] SG support (Asynchronous Read/Write) Reply-To: Laurent Vivier , qemu-devel@nongnu.org List-Id: qemu-devel.nongnu.org List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: qemu-devel@nongnu.org This patch modifies scsi_read_data() and scsi_write_data() to use asynchronous I/O whith SCSI Generic. block-raw.s has been modified to define the number of bytes to transfer instead of the number of blocks: if nb_sectors is less than zero the nb_sectors is a number of bytes. --- block-raw.c | 5 + hw/lsi53c895a.c | 2=20 hw/scsi-generic.c | 198 ++++++++++++++++++++++++++++++++++---------------= ----- 3 files changed, 133 insertions(+), 72 deletions(-) Index: qemu/block-raw.c =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D --- qemu.orig/block-raw.c 2007-11-28 13:12:02.000000000 +0100 +++ qemu/block-raw.c 2007-11-28 13:12:22.000000000 +0100 @@ -385,7 +385,10 @@ static RawAIOCB *raw_aio_setup(BlockDriv acb->aiocb.aio_sigevent.sigev_signo =3D aio_sig_num; acb->aiocb.aio_sigevent.sigev_notify =3D SIGEV_SIGNAL; acb->aiocb.aio_buf =3D buf; - acb->aiocb.aio_nbytes =3D nb_sectors * 512; + if (nb_sectors < 0) + acb->aiocb.aio_nbytes =3D -nb_sectors; + else + acb->aiocb.aio_nbytes =3D nb_sectors * 512; acb->aiocb.aio_offset =3D sector_num * 512; acb->next =3D first_aio; first_aio =3D acb; Index: qemu/hw/scsi-generic.c =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D --- qemu.orig/hw/scsi-generic.c 2007-11-28 13:12:12.000000000 +0100 +++ qemu/hw/scsi-generic.c 2007-11-28 13:13:13.000000000 +0100 @@ -53,6 +53,7 @@ do { fprintf(stderr, "scsi-generic: " fm #define SG_ERR_DRIVER_SENSE 0x08 =20 typedef struct SCSIRequest { + BlockDriverAIOCB *aiocb; struct SCSIRequest *next; SCSIDeviceState *dev; uint32_t tag; @@ -61,8 +62,8 @@ typedef struct SCSIRequest { uint8_t *buf; int buflen; int len; - int driver_status; uint8_t sensebuf[SCSI_SENSE_BUF_SIZE]; + sg_io_hdr_t io_header; } SCSIRequest; =20 struct SCSIDeviceState @@ -94,13 +95,16 @@ static SCSIRequest *scsi_new_request(SCS r->tag =3D tag; memset(r->cmd, 0, sizeof(r->cmd)); memset(r->sensebuf, 0, sizeof(r->sensebuf)); + memset(&r->io_header, 0, sizeof(r->io_header)); r->cmdlen =3D 0; r->len =3D 0; + r->aiocb =3D NULL; =20 /* link */ =20 r->next =3D s->requests; s->requests =3D r; + DPRINTF("scsi_new_request tag=3D0x%x\n", tag); return r; } =20 @@ -109,6 +113,7 @@ static void scsi_remove_request(SCSIRequ SCSIRequest *last; SCSIDeviceState *s =3D r->dev; =20 + DPRINTF("scsi_remove_request tag=3D0x%x\n", r->tag); if (s->requests =3D=3D r) { s->requests =3D r->next; } else { @@ -138,16 +143,24 @@ static SCSIRequest *scsi_find_request(SC =20 static int scsi_get_sense(SCSIRequest *r) { - if ((r->driver_status & SG_ERR_DRIVER_SENSE) =3D=3D 0) + if ((r->io_header.driver_status & SG_ERR_DRIVER_SENSE) =3D=3D 0) return NO_SENSE; return r->sensebuf[2] & 0x0f; } =20 /* Helper function for command completion. */ -static void scsi_command_complete(SCSIRequest *r, int sense) +static void scsi_command_complete(void *opaque, int ret) { + SCSIRequest *r =3D (SCSIRequest *)opaque; SCSIDeviceState *s =3D r->dev; uint32_t tag; + int sense; + + if (ret !=3D 0) + sense =3D HARDWARE_ERROR; + else + sense =3D scsi_get_sense(r); + DPRINTF("Command complete 0x%p tag=3D0x%x sense=3D%d\n", r, r->tag, se= nse); tag =3D r->tag; scsi_remove_request(r); @@ -163,46 +176,70 @@ static void scsi_cancel_io(SCSIDevice *d DPRINTF("Cancel tag=3D0x%x\n", tag); r =3D scsi_find_request(s, tag); if (r) { + if (r->aiocb) + bdrv_aio_cancel(r->aiocb); + r->aiocb =3D NULL; scsi_remove_request(r); } } =20 -static int execute_command(BlockDriverState *bdrv, uint8_t *cmdbuf, int cm= dlen, - uint8_t *outbuf, uint32_t outlen, - uint8_t *sensebuf, int senselen, - int direction, int *len) -{ - sg_io_hdr_t io_header; - int ret; - - memset(&io_header, 0, sizeof(io_header)); - io_header.interface_id =3D 'S'; - io_header.dxfer_direction =3D direction; - io_header.dxfer_len =3D outlen; - io_header.dxferp =3D outbuf; - io_header.cmdp =3D cmdbuf; - io_header.cmd_len =3D cmdlen; - io_header.mx_sb_len =3D senselen; - io_header.sbp =3D sensebuf; - io_header.timeout =3D 6000; /* XXX */ +static int execute_command(BlockDriverState *bdrv, + SCSIRequest *r, int direction, + BlockDriverCompletionFunc *complete) +{ + r->io_header.interface_id =3D 'S'; + r->io_header.dxfer_direction =3D direction; + r->io_header.dxfer_len =3D r->buflen; + r->io_header.dxferp =3D r->buf; + r->io_header.cmdp =3D r->cmd; + r->io_header.cmd_len =3D r->cmdlen; + r->io_header.mx_sb_len =3D sizeof(r->sensebuf); + r->io_header.sbp =3D r->sensebuf; + r->io_header.timeout =3D 6000; /* XXX */ =20 - ret =3D bdrv_pwrite(bdrv, -1, &io_header, sizeof(io_header)); - if (ret =3D=3D -1) { + if (bdrv_pwrite(bdrv, -1, &r->io_header, sizeof(r->io_header)) =3D=3D = -1) { BADF("execute_command: write failed ! (%d)\n", errno); return -1; } - while ((ret =3D bdrv_pread(bdrv, -1, &io_header, sizeof(io_header))) = =3D=3D -1 && - errno =3D=3D EINTR); + if (complete =3D=3D NULL) { + int ret; + r->aiocb =3D NULL; + while ((ret =3D bdrv_pread(bdrv, -1, &r->io_header, + sizeof(r->io_header))) =3D=3D -= 1 && + errno =3D=3D EINTR); + if (ret =3D=3D -1) { + BADF("execute_command: read failed !\n"); + return -1; + } + return 0; + } =20 - if (ret =3D=3D -1) { + r->aiocb =3D bdrv_aio_read(bdrv, 0, (uint8_t*)&r->io_header, + -(int64_t)sizeof(r->io_header), complete, r); + if (r->aiocb =3D=3D NULL) { BADF("execute_command: read failed !\n"); return -1; } =20 - if (len !=3D NULL) - *len =3D io_header.dxfer_len - io_header.resid; + return 0; +} + +static void scsi_read_complete(void * opaque, int ret) +{ + SCSIRequest *r =3D (SCSIRequest *)opaque; + SCSIDeviceState *s =3D r->dev; + int len; =20 - return io_header.driver_status; + if (ret) { + DPRINTF("IO error\n"); + scsi_command_complete(r, ret); + return; + } + len =3D r->io_header.dxfer_len - r->io_header.resid; + DPRINTF("Data ready tag=3D0x%x len=3D%d\n", r->tag, len); + + r->len =3D -1; + s->completion(s->opaque, SCSI_REASON_DATA, r->tag, len); } =20 /* Read more data from scsi device into buffer. */ @@ -210,25 +247,40 @@ static void scsi_read_data(SCSIDevice *d { SCSIDeviceState *s =3D d->state; SCSIRequest *r; - int len; + int ret; =20 DPRINTF("scsi_read_data 0x%x\n", tag); r =3D scsi_find_request(s, tag); if (!r) { BADF("Bad read tag 0x%x\n", tag); /* ??? This is the wrong error. */ - scsi_command_complete(r, HARDWARE_ERROR); + scsi_command_complete(r, -EINVAL); return; } =20 if (r->len =3D=3D -1) { - scsi_command_complete(r, scsi_get_sense(r)); + scsi_command_complete(r, 0); return; } =20 - len =3D r->len; - r->len =3D -1; - s->completion(s->opaque, SCSI_REASON_DATA, r->tag, len); + ret =3D execute_command(s->bdrv, r, SG_DXFER_FROM_DEV, scsi_read_compl= ete); + if (ret =3D=3D -1) { + scsi_command_complete(r, -EINVAL); + return; + } +} + +static void scsi_write_complete(void * opaque, int ret) +{ + SCSIRequest *r =3D (SCSIRequest *)opaque; + + if (ret) { + DPRINTF("IO error\n"); + scsi_command_complete(r, ret); + return; + } + + scsi_command_complete(r, ret); } =20 /* Write data to a scsi device. Returns nonzero on failure. @@ -244,7 +296,7 @@ static int scsi_write_data(SCSIDevice *d if (!r) { BADF("Bad write tag 0x%x\n", tag); /* ??? This is the wrong error. */ - scsi_command_complete(r, HARDWARE_ERROR); + scsi_command_complete(r, -EINVAL); return 0; } =20 @@ -254,15 +306,11 @@ static int scsi_write_data(SCSIDevice *d return 0; } =20 - ret =3D execute_command(s->bdrv, r->cmd, r->cmdlen, r->buf, r->len, - r->sensebuf, sizeof(r->sensebuf), - SG_DXFER_TO_DEV, NULL); + ret =3D execute_command(s->bdrv, r, SG_DXFER_TO_DEV, scsi_write_comple= te); if (ret =3D=3D -1) { - scsi_command_complete(r, HARDWARE_ERROR); + scsi_command_complete(r, -EINVAL); return 1; } - r->driver_status =3D ret; - scsi_command_complete(r, scsi_get_sense(r)); =20 return 0; } @@ -416,19 +464,12 @@ static int32_t scsi_send_command(SCSIDev SCSIRequest *r; int ret; =20 - r =3D scsi_find_request(s, tag); - if (r) { - BADF("Tag 0x%x already in use %p\n", tag, r); - scsi_cancel_io(d, tag); - } - r =3D scsi_new_request(s, tag); - /* ??? Tags are not unique for different luns. We only implement a single lun, so this should not matter. */ =20 if (lun !=3D s->lun || (cmd[1] >> 5) !=3D s->lun) { DPRINTF("Unimplemented LUN %d\n", lun ? lun : cmd[1] >> 5); - scsi_command_complete(r, ILLEGAL_REQUEST); + s->completion(s->opaque, SCSI_REASON_DONE, tag, HARDWARE_ERROR); return 0; } =20 @@ -438,21 +479,28 @@ static int32_t scsi_send_command(SCSIDev } =20 DPRINTF("Command: lun=3D%d tag=3D0x%x data=3D0x%02x len %d\n", lun, ta= g, - command, len); + cmd[0], len); + + r =3D scsi_find_request(s, tag); + if (r) { + BADF("Tag 0x%x already in use %p\n", tag, r); + scsi_cancel_io(d, tag); + } + r =3D scsi_new_request(s, tag); =20 memcpy(r->cmd, cmd, cmdlen); r->cmdlen =3D cmdlen; =20 if (len =3D=3D 0) { - ret =3D execute_command(s->bdrv, r->cmd, r->cmdlen, NULL, 0, - r->sensebuf, sizeof(r->sensebuf), - SG_DXFER_NONE, NULL); + if (r->buf !=3D NULL) + free(r->buf); + r->buflen =3D 0; + r->buf =3D NULL; + ret =3D execute_command(s->bdrv, r, SG_DXFER_NONE, NULL); if (ret =3D=3D -1) { - scsi_command_complete(r, HARDWARE_ERROR); + scsi_command_complete(r, -EINVAL); return 0; } - r->driver_status =3D ret; - scsi_command_complete(r, scsi_get_sense(r)); return 0; } @@ -471,16 +519,6 @@ static int32_t scsi_send_command(SCSIDev return -len; } =20 - ret =3D execute_command(s->bdrv, r->cmd, r->cmdlen, r->buf, r->len, - r->sensebuf, sizeof(r->sensebuf), - SG_DXFER_FROM_DEV, &len); - if (ret =3D=3D -1) { - scsi_command_complete(r, HARDWARE_ERROR); - return 0; - } - r->len =3D len; - r->driver_status =3D ret; - return len; } =20 @@ -489,16 +527,34 @@ static int get_blocksize(BlockDriverStat uint8_t cmd[10]; uint8_t buf[8]; uint8_t sensebuf[8]; + sg_io_hdr_t io_header; int ret; =20 memset(cmd, sizeof(cmd), 0); memset(buf, sizeof(buf), 0); cmd[0] =3D READ_CAPACITY; - ret =3D execute_command(bdrv, cmd, sizeof(cmd), buf, sizeof(buf), - sensebuf, sizeof(sensebuf), - SG_DXFER_FROM_DEV, NULL); - if (ret < 0) + + memset(&io_header, 0, sizeof(io_header)); + io_header.interface_id =3D 'S'; + io_header.dxfer_direction =3D SG_DXFER_FROM_DEV; + io_header.dxfer_len =3D sizeof(buf); + io_header.dxferp =3D buf; + io_header.cmdp =3D cmd; + io_header.cmd_len =3D sizeof(cmd); + io_header.mx_sb_len =3D sizeof(sensebuf); + io_header.sbp =3D sensebuf; + io_header.timeout =3D 6000; /* XXX */ + + ret =3D bdrv_pwrite(bdrv, -1, &io_header, sizeof(io_header)); + if (ret =3D=3D -1) + return -1; + + while ((ret =3D bdrv_pread(bdrv, -1, &io_header, sizeof(io_header))) = =3D=3D -1 && + errno =3D=3D EINTR); + + if (ret =3D=3D -1) return -1; + return (buf[4] << 24) | (buf[5] << 16) | (buf[6] << 8) | buf[7]; } =20 Index: qemu/hw/lsi53c895a.c =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D --- qemu.orig/hw/lsi53c895a.c 2007-11-28 13:12:02.000000000 +0100 +++ qemu/hw/lsi53c895a.c 2007-11-28 13:12:22.000000000 +0100 @@ -1225,6 +1225,8 @@ static uint8_t lsi_reg_readb(LSIState *s return s->sdid; case 0x07: /* GPREG0 */ return 0x7f; + case 0x08: /* Revision ID */ + return 0x00; case 0xa: /* SSID */ return s->ssid; case 0xb: /* SBCL */