From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mailman by lists.gnu.org with tmda-scanned (Exim 4.43) id 1JHiBA-00058T-7K for qemu-devel@nongnu.org; Wed, 23 Jan 2008 11:10:20 -0500 Received: from exim by lists.gnu.org with spam-scanned (Exim 4.43) id 1JHiB7-00056F-U3 for qemu-devel@nongnu.org; Wed, 23 Jan 2008 11:10:18 -0500 Received: from [199.232.76.173] (helo=monty-python.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1JHiB7-00055v-II for qemu-devel@nongnu.org; Wed, 23 Jan 2008 11:10:17 -0500 Received: from ecfrec.frec.bull.fr ([129.183.4.8]) by monty-python.gnu.org with esmtp (Exim 4.60) (envelope-from ) id 1JHiB6-0005ZZ-6k for qemu-devel@nongnu.org; Wed, 23 Jan 2008 11:10:17 -0500 Received: from localhost (localhost [127.0.0.1]) by ecfrec.frec.bull.fr (Postfix) with ESMTP id 7D7F119D9AE for ; Wed, 23 Jan 2008 17:09:53 +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 12862-06 for ; Wed, 23 Jan 2008 17:09:49 +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 8807319D9B3 for ; Wed, 23 Jan 2008 17:09:24 +0100 (CET) In-Reply-To: <120110477478@bull.net> Date: Wed, 23 Jan 2008 17:12:54 +0100 Message-Id: <1201104774984@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 3/5] Add block SG interface 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 re-implement scsi-generic.c using a new block interface called block-sg.c instead of block-raw-posix.c. It adds a new interface (bdrv_execute) allowing to send command to the devi= ce. Laurent --- Makefile | 2=20 Makefile.target | 2=20 block-sg.c | 194 +++++++++++++++++++++++++++++++++++++++++++++++++= +++++ block-sg.h | 18 +++++ block.c | 21 +++++ block.h | 4 + block_int.h | 4 + hw/scsi-generic.c | 176 +++++++++++++++++------------------------------- 8 files changed, 303 insertions(+), 118 deletions(-) Index: qemu/block.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.c 2008-01-23 16:02:32.000000000 +0100 +++ qemu/block.c 2008-01-23 16:43:01.000000000 +0100 @@ -126,13 +126,14 @@ void path_combine(char *dest, int dest_s =20 static void bdrv_register(BlockDriver *bdrv) { - if (!bdrv->bdrv_aio_read) { + if (!bdrv->bdrv_aio_read && !bdrv->bdrv_execute) { /* add AIO emulation layer */ bdrv->bdrv_aio_read =3D bdrv_aio_read_em; bdrv->bdrv_aio_write =3D bdrv_aio_write_em; bdrv->bdrv_aio_cancel =3D bdrv_aio_cancel_em; bdrv->aiocb_size =3D sizeof(BlockDriverAIOCBSync); - } else if (!bdrv->bdrv_read && !bdrv->bdrv_pread) { + } else if (!bdrv->bdrv_read && !bdrv->bdrv_pread && + !bdrv->bdrv_execute) { /* add synchronous IO emulation layer */ bdrv->bdrv_read =3D bdrv_read_em; bdrv->bdrv_write =3D bdrv_write_em; @@ -267,6 +268,8 @@ static BlockDriver *find_image_format(co struct stat st; if (stat(filename, &st) >=3D 0 && (S_ISCHR(st.st_mode) || S_ISBLK(st.st_mode))) { + if ((st.st_rdev >> 8) =3D=3D 0x15) /* SG device */ + return &bdrv_sg_device; return &bdrv_host_device; } } @@ -1289,6 +1292,7 @@ void bdrv_init(void) bdrv_register(&bdrv_vvfat); bdrv_register(&bdrv_qcow2); bdrv_register(&bdrv_parallels); + bdrv_register(&bdrv_sg_device); } =20 void *qemu_aio_get(BlockDriverState *bs, BlockDriverCompletionFunc *cb, @@ -1394,3 +1398,16 @@ void bdrv_set_locked(BlockDriverState *b drv->bdrv_set_locked(bs, locked); } } + +/* send a command to a device, needed for generic scsi interface */ + +int bdrv_execute(BlockDriverState *bs, void *request, + BlockDriverCompletionFunc *complete) +{ + BlockDriver *drv =3D bs->drv; + + if (drv && drv->bdrv_execute) { + return drv->bdrv_execute(bs, request, complete); + } + return -ENOTSUP; +} Index: qemu/block.h =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.h 2008-01-23 16:02:32.000000000 +0100 +++ qemu/block.h 2008-01-23 16:02:32.000000000 +0100 @@ -16,6 +16,7 @@ extern BlockDriver bdrv_vpc; extern BlockDriver bdrv_vvfat; extern BlockDriver bdrv_qcow2; extern BlockDriver bdrv_parallels; +extern BlockDriver bdrv_sg_device; =20 typedef struct BlockDriverInfo { /* in bytes, 0 if irrelevant */ @@ -148,6 +149,9 @@ int bdrv_snapshot_delete(BlockDriverStat int bdrv_snapshot_list(BlockDriverState *bs, QEMUSnapshotInfo **psn_info); char *bdrv_snapshot_dump(char *buf, int buf_size, QEMUSnapshotInfo *sn); +int bdrv_execute(BlockDriverState *bs, void *request, + BlockDriverCompletionFunc *complete); + =20 char *get_human_readable_size(char *buf, int buf_size, int64_t size); int path_is_absolute(const char *path); Index: qemu/block-sg.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 --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ qemu/block-sg.c 2008-01-23 16:41:58.000000000 +0100 @@ -0,0 +1,194 @@ +/* + * sg driver for RAW files + * + * Copyright (c) 2008 Bull S.A.S. + * Based on code by Fabrice Bellard + * + * Written by Laurent Vivier + * + * Permission is hereby granted, free of charge, to any person obtaining a= copy + * of this software and associated documentation files (the "Software"), t= o deal + * in the Software without restriction, including without limitation the r= ights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or se= ll + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included= in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS= OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OT= HER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING= FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS = IN + * THE SOFTWARE. + */ +#include "qemu-common.h" +#include "block_int.h" +#include "qemu-aio-posix.h" + +#include +#include + +#include "block-sg.h" + +#include + +//#define DEBUG_SG + +#ifdef DEBUG_SG +#define DPRINTF(fmt, args...) \ +do { printf("block-sg: " fmt , ##args); } while (0) +#else +#define DPRINTF(fmt, args...) do {} while(0) +#endif + + +typedef struct BDRVSGState { + int fd; /* must be the first field for qemu-aio-posix.c */ + int lun; +} BDRVSGState; + +#define BADF(fmt, args...) \ +do { fprintf(stderr, "block-sg: " fmt , ##args); } while (0) + +static int sg_read(BlockDriverState *bs, uint8_t *buf, int count) +{ + BDRVSGState *s =3D bs->opaque; + + return read(s->fd, buf, count); +} + +static int sg_write(BlockDriverState *bs, const uint8_t *buf, int count) +{ + BDRVSGState *s =3D bs->opaque; + + return write(s->fd, buf, count); +} + +static BlockDriverAIOCB *sg_aio_read(BlockDriverState *bs, + int64_t offset, uint8_t *buf, int nb_bytes, + BlockDriverCompletionFunc *cb, void *opaque) +{ + RawAIOCB *acb; + + DPRINTF("sg_aio_read: bs %p offset %d buf %p nb_bytes %d cb %p opaque = %p\n", + bs, offset, buf, nb_bytes, cb, opaque); + + acb =3D qemu_aio_read(bs, offset, buf, nb_bytes, + cb, opaque); + + DPRINTF("acb: %p\n", acb); + + return &acb->common; +} + +static void sg_aio_cancel(BlockDriverAIOCB *blockacb) +{ + RawAIOCB *acb =3D (RawAIOCB *)blockacb; + + qemu_aio_cancel(acb); +} + +static void sg_close(BlockDriverState *bs) +{ + BDRVSGState *s =3D bs->opaque; + close(s->fd); +} + +static int sg_open(BlockDriverState *bs, const char *filename, int flags) +{ + BDRVSGState *s =3D bs->opaque; + int fd, open_flags, ret; + int sg_version =3D 0; + struct sg_scsi_id scsiid; + + open_flags =3D O_BINARY; + if ((flags & BDRV_O_ACCESS) =3D=3D O_RDWR) { + open_flags |=3D O_RDWR; + } else { + open_flags |=3D O_RDONLY; + bs->read_only =3D 1; + } + + fd =3D open(filename, open_flags, 0644); + if (fd < 0) { + ret =3D -errno; + if (ret =3D=3D -EROFS) + ret =3D -EACCES; + return ret; + } + + /* check we are using a driver managing SG_IO (version 3 and after */ + + if (ioctl(fd, SG_GET_VERSION_NUM, &sg_version) < 0 || + sg_version < 30000) + return -EINVAL; + + /* get LUN of the /dev/sg? */ + + if (ioctl(fd, SG_GET_SCSI_ID, &scsiid)) + return -EINVAL; + + s->fd =3D fd; + s->lun =3D scsiid.lun; + + return 0; +} + +int sg_execute(BlockDriverState *bs, void *request, + BlockDriverCompletionFunc *complete) +{ + BDRVSGState *s =3D bs->opaque; + SGRequest *r =3D (SGRequest *)request; + + DPRINTF("sg_execute bs %p request %p complete %p\n", + bs, request, complete); + + if (request =3D=3D NULL) + return s->lun; + + if (sg_write(bs, (const uint8_t *)&r->io_header, + sizeof(r->io_header)) =3D=3D -1) { + BADF("execute_command: write failed ! (%d)\n", errno); + return -1; + } + if (complete =3D=3D NULL) { + int ret; + r->aiocb =3D NULL; + while ((ret =3D sg_read(bs, (uint8_t *)&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; + } + + r->aiocb =3D sg_aio_read(bs, 0, (uint8_t*)&r->io_header, + sizeof(r->io_header), complete, r); + if (r->aiocb =3D=3D NULL) { + BADF("execute_command: read failed !\n"); + return -1; + } + + return 0; +} + +BlockDriver bdrv_sg_device =3D { + "sg_device", + sizeof(BDRVSGState), + NULL, + sg_open, + NULL, + NULL, + sg_close, + NULL, + NULL, + .aiocb_size =3D sizeof(RawAIOCB), + .bdrv_aio_cancel =3D sg_aio_cancel, + /* generic scsi device */ + .bdrv_execute =3D sg_execute, +}; 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 2008-01-23 16:02:32.000000000 +0100 +++ qemu/hw/scsi-generic.c 2008-01-23 16:41:58.000000000 +0100 @@ -13,10 +13,10 @@ =20 #include "qemu-common.h" #include "block.h" +#include "block_int.h" #include "scsi-disk.h" =20 -//#ifndef __linux__ -#if 1 +#ifndef __linux__ =20 SCSIDevice *scsi_generic_init(BlockDriverState *bdrv, int tcq, scsi_completionfn completion, void *opaque) @@ -44,6 +44,7 @@ do { fprintf(stderr, "scsi-generic: " fm #include #include #include +#include "block-sg.h" =20 #define LOAD_UNLOAD 0xa6 #define SET_CD_SPEED 0xbb @@ -52,15 +53,12 @@ do { fprintf(stderr, "scsi-generic: " fm #define SCSI_CMD_BUF_SIZE 16 #define SCSI_SENSE_BUF_SIZE 32 =20 -#define SG_ERR_DRIVER_TIMEOUT 0x06 -#define SG_ERR_DRIVER_SENSE 0x08 - #ifndef MAX_UINT #define MAX_UINT ((unsigned int)-1) #endif =20 typedef struct SCSIRequest { - BlockDriverAIOCB *aiocb; + SGRequest sg; struct SCSIRequest *next; SCSIDeviceState *dev; uint32_t tag; @@ -69,7 +67,6 @@ typedef struct SCSIRequest { uint8_t *buf; int buflen; int len; - sg_io_hdr_t io_header; } SCSIRequest; =20 struct SCSIDeviceState @@ -77,9 +74,8 @@ struct SCSIDeviceState SCSIRequest *requests; BlockDriverState *bdrv; int blocksize; - int lun; scsi_completionfn completion; - void *opaque; + void *card; int driver_status; uint8_t sensebuf[SCSI_SENSE_BUF_SIZE]; }; @@ -102,10 +98,8 @@ static SCSIRequest *scsi_new_request(SCS r->dev =3D s; r->tag =3D tag; memset(r->cmd, 0, sizeof(r->cmd)); - memset(&r->io_header, 0, sizeof(r->io_header)); r->cmdlen =3D 0; r->len =3D 0; - r->aiocb =3D NULL; =20 /* link */ =20 @@ -147,14 +141,14 @@ static SCSIRequest *scsi_find_request(SC } =20 /* Helper function for command completion. */ -static void scsi_command_complete(void *opaque, int ret) +static void scsi_command_complete(void *request, int ret) { - SCSIRequest *r =3D (SCSIRequest *)opaque; + SCSIRequest *r =3D (SCSIRequest *)request; SCSIDeviceState *s =3D r->dev; uint32_t tag; int sense; =20 - s->driver_status =3D r->io_header.driver_status; + s->driver_status =3D r->sg.io_header.driver_status; if (ret !=3D 0) sense =3D HARDWARE_ERROR; else { @@ -167,10 +161,10 @@ static void scsi_command_complete(void * sense =3D s->sensebuf[2] & 0x0f; } =20 - DPRINTF("Command complete 0x%p tag=3D0x%x sense=3D%d\n", r, r->tag, se= nse); + DPRINTF("Command complete %p tag=3D0x%x sense=3D%d\n", r, r->tag, sens= e); tag =3D r->tag; scsi_remove_request(r); - s->completion(s->opaque, SCSI_REASON_DONE, tag, sense); + s->completion(s->card, SCSI_REASON_DONE, tag, sense); } =20 /* Cancel a pending data transfer. */ @@ -182,60 +176,35 @@ 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; + if (r->sg.aiocb) + bdrv_aio_cancel(r->sg.aiocb); + r->sg.aiocb =3D NULL; scsi_remove_request(r); } } =20 static int execute_command(BlockDriverState *bdrv, SCSIRequest *r, int direction, - BlockDriverCompletionFunc *complete) + BlockDriverCompletionFunc *complete) { + memset(&r->sg, 0, sizeof(r->sg)); + r->sg.io_header.interface_id =3D 'S'; + r->sg.io_header.dxfer_direction =3D direction; + r->sg.io_header.cmd_len =3D r->cmdlen; + r->sg.io_header.mx_sb_len =3D sizeof(r->dev->sensebuf); + r->sg.io_header.dxfer_len =3D r->buflen; + r->sg.io_header.dxferp =3D r->buf; + r->sg.io_header.cmdp =3D r->cmd; + r->sg.io_header.sbp =3D r->dev->sensebuf; + r->sg.io_header.timeout =3D MAX_UINT; + r->sg.io_header.flags |=3D SG_FLAG_DIRECT_IO; =20 - r->io_header.interface_id =3D 'S'; - r->io_header.dxfer_direction =3D direction; - r->io_header.dxferp =3D r->buf; - r->io_header.dxfer_len =3D r->buflen; - r->io_header.cmdp =3D r->cmd; - r->io_header.cmd_len =3D r->cmdlen; - r->io_header.mx_sb_len =3D sizeof(r->dev->sensebuf); - r->io_header.sbp =3D r->dev->sensebuf; - r->io_header.timeout =3D MAX_UINT; - r->io_header.usr_ptr =3D r; - r->io_header.flags |=3D SG_FLAG_DIRECT_IO; - - 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; - } - 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; - } - - 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; - } - - return 0; + return bdrv_execute(bdrv, &r->sg, complete); } =20 -static void scsi_read_complete(void * opaque, int ret) +static void scsi_read_complete(void *request, int ret) { - SCSIRequest *r =3D (SCSIRequest *)opaque; + SCSIRequest *r =3D (SCSIRequest *)request; SCSIDeviceState *s =3D r->dev; int len; =20 @@ -244,11 +213,11 @@ static void scsi_read_complete(void * op scsi_command_complete(r, ret); return; } - len =3D r->io_header.dxfer_len - r->io_header.resid; + len =3D r->sg.io_header.dxfer_len - r->sg.io_header.resid; DPRINTF("Data ready tag=3D0x%x len=3D%d\n", r->tag, len); =20 r->len =3D -1; - s->completion(s->opaque, SCSI_REASON_DATA, r->tag, len); + s->completion(s->card, SCSI_REASON_DATA, r->tag, len); } =20 /* Read more data from scsi device into buffer. */ @@ -275,9 +244,9 @@ static void scsi_read_data(SCSIDevice *d if (r->cmd[0] =3D=3D REQUEST_SENSE && s->driver_status & SG_ERR_DRIVER= _SENSE) { memcpy(r->buf, s->sensebuf, 16); - r->io_header.driver_status =3D 0; + r->sg.io_header.driver_status =3D 0; r->len =3D -1; - s->completion(s->opaque, SCSI_REASON_DATA, r->tag, 16); + s->completion(s->card, SCSI_REASON_DATA, r->tag, 16); return; } =20 @@ -288,10 +257,9 @@ static void scsi_read_data(SCSIDevice *d } } =20 -static void scsi_write_complete(void * opaque, int ret) +static void scsi_write_complete(void* request, int ret) { - SCSIRequest *r =3D (SCSIRequest *)opaque; - + SCSIRequest* r =3D (SCSIRequest*)request; DPRINTF("scsi_write_complete() ret =3D %d\n", ret); if (ret) { DPRINTF("IO error\n"); @@ -321,7 +289,7 @@ static int scsi_write_data(SCSIDevice *d =20 if (r->len =3D=3D 0) { r->len =3D r->buflen; - s->completion(s->opaque, SCSI_REASON_DATA, r->tag, r->len); + s->completion(s->card, SCSI_REASON_DATA, r->tag, r->len); return 0; } =20 @@ -339,11 +307,13 @@ static uint8_t *scsi_get_buf(SCSIDevice=20 { SCSIDeviceState *s =3D d->state; SCSIRequest *r; + DPRINTF("scsi_get_buf: %d\n", tag); r =3D scsi_find_request(s, tag); if (!r) { BADF("Bad buffer tag 0x%x\n", tag); return NULL; } + DPRINTF("scsi_get_buf: r=3D%p buf=3D%p\n", r, r->buf); return r->buf; } =20 @@ -483,13 +453,16 @@ static int32_t scsi_send_command(SCSIDev int cmdlen; SCSIRequest *r; int ret; + int target_lun; =20 /* ??? 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) { + target_lun =3D bdrv_execute(s->bdrv, NULL, NULL); + + if (lun !=3D target_lun || (cmd[1] >> 5) !=3D target_lun) { DPRINTF("Unimplemented LUN %d\n", lun ? lun : cmd[1] >> 5); - s->completion(s->opaque, SCSI_REASON_DONE, tag, ILLEGAL_REQUEST); + s->completion(s->card, SCSI_REASON_DONE, tag, ILLEGAL_REQUEST); return 0; } =20 @@ -500,7 +473,6 @@ 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, cmd[0], len); - r =3D scsi_find_request(s, tag); if (r) { BADF("Tag 0x%x already in use %p\n", tag, r); @@ -513,20 +485,18 @@ static int32_t scsi_send_command(SCSIDev =20 if (len =3D=3D 0) { if (r->buf !=3D NULL) - free(r->buf); + qemu_free(r->buf); r->buflen =3D 0; r->buf =3D NULL; ret =3D execute_command(s->bdrv, r, SG_DXFER_NONE, scsi_command_co= mplete); - if (ret =3D=3D -1) { + if (ret =3D=3D -1) scsi_command_complete(r, -EINVAL); - return 0; - } return 0; } =20 if (r->buflen !=3D len) { if (r->buf !=3D NULL) - free(r->buf); + qemu_free(r->buf); r->buf =3D qemu_malloc(len); r->buflen =3D len; } @@ -543,34 +513,28 @@ static int32_t scsi_send_command(SCSIDev =20 static int get_blocksize(BlockDriverState *bdrv) { + SGRequest sg; 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); + memset(cmd, 0, sizeof(cmd)); + memset(buf, 0, sizeof(buf)); cmd[0] =3D READ_CAPACITY; =20 - 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); + memset(&sg.io_header, 0, sizeof(sg.io_header)); + sg.io_header.interface_id =3D 'S'; + sg.io_header.dxfer_direction =3D SG_DXFER_FROM_DEV; + sg.io_header.dxfer_len =3D sizeof(buf); + sg.io_header.dxferp =3D buf; + sg.io_header.cmdp =3D cmd; + sg.io_header.cmd_len =3D sizeof(cmd); + sg.io_header.mx_sb_len =3D sizeof(sensebuf); + sg.io_header.sbp =3D sensebuf; + sg.io_header.timeout =3D 6000; /* XXX */ =20 + ret =3D bdrv_execute(bdrv, &sg, NULL); if (ret =3D=3D -1) return -1; =20 @@ -600,27 +564,12 @@ static void scsi_destroy(SCSIDevice *d) } =20 SCSIDevice *scsi_generic_init(BlockDriverState *bdrv, int tcq, - scsi_completionfn completion, void *opaque) + scsi_completionfn completion, void *card) { - int sg_version; SCSIDevice *d; SCSIDeviceState *s; - struct sg_scsi_id scsiid; - - /* check we are really using a /dev/sg* file */ - - if (!bdrv_is_sg(bdrv)) - return NULL; - - /* check we are using a driver managing SG_IO (version 3 and after */ - - if (bdrv_ioctl(bdrv, SG_GET_VERSION_NUM, &sg_version) < 0 || - sg_version < 30000) - return NULL; - - /* get LUN of the /dev/sg? */ =20 - if (bdrv_ioctl(bdrv, SG_GET_SCSI_ID, &scsiid)) + if (bdrv->drv->bdrv_execute =3D=3D NULL) return NULL; =20 /* define device state */ @@ -629,8 +578,7 @@ SCSIDevice *scsi_generic_init(BlockDrive s->bdrv =3D bdrv; s->requests =3D NULL; s->completion =3D completion; - s->opaque =3D opaque; - s->lun =3D scsiid.lun; + s->card =3D card; s->blocksize =3D get_blocksize(s->bdrv); s->driver_status =3D 0; memset(s->sensebuf, 0, sizeof(s->sensebuf)); Index: qemu/Makefile.target =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/Makefile.target 2008-01-23 16:02:32.000000000 +0100 +++ qemu/Makefile.target 2008-01-23 16:02:32.000000000 +0100 @@ -398,7 +398,7 @@ VL_OBJS=3Dvl.o osdep.o monitor.o pci.o loa ifdef CONFIG_WIN32 VL_OBJS+=3Dblock-raw-win32.o else -VL_OBJS+=3Dblock-raw-posix.o qemu-aio-posix.o +VL_OBJS+=3Dblock-raw-posix.o block-sg.o qemu-aio-posix.o endif =20 ifdef CONFIG_ALSA Index: qemu/Makefile =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/Makefile 2008-01-23 16:02:32.000000000 +0100 +++ qemu/Makefile 2008-01-23 16:02:32.000000000 +0100 @@ -40,7 +40,7 @@ recurse-all: $(patsubst %,subdir-%, $(TA BLOCK_OBJS=3Dcutils.o BLOCK_OBJS+=3Dblock-cow.o block-qcow.o aes.o block-vmdk.o block-cloop.o BLOCK_OBJS+=3Dblock-dmg.o block-bochs.o block-vpc.o block-vvfat.o -BLOCK_OBJS+=3Dblock-qcow2.o block-parallels.o +BLOCK_OBJS+=3Dblock-qcow2.o block-parallels.o block-sg.o =20 ###################################################################### # libqemu_common.a: Target indepedent part of system emulation. The Index: qemu/block-sg.h =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 --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ qemu/block-sg.h 2008-01-23 16:02:32.000000000 +0100 @@ -0,0 +1,18 @@ +/* + * Generic SCSI Device support + * + * Copyright (c) 2008 Bull S.A.S. + * + * Written by Laurent Vivier + * + * This code is licenced under the LGPL. + * + */ + +#define SG_ERR_DRIVER_TIMEOUT 0x06 +#define SG_ERR_DRIVER_SENSE 0x08 + +typedef struct SGRequest { + sg_io_hdr_t io_header; + BlockDriverAIOCB *aiocb; +} SGRequest; Index: qemu/block_int.h =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_int.h 2008-01-23 16:02:32.000000000 +0100 +++ qemu/block_int.h 2008-01-23 16:02:32.000000000 +0100 @@ -82,6 +82,10 @@ struct BlockDriver { int (*bdrv_eject)(BlockDriverState *bs, int eject_flag); int (*bdrv_set_locked)(BlockDriverState *bs, int locked); =20 + /* SG device */ + int (*bdrv_execute)(BlockDriverState *bs, void *request, + BlockDriverCompletionFunc *complete); + BlockDriverAIOCB *free_aiocb; struct BlockDriver *next; };