qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Qemu-devel] [PATCH 3/5] Add block SG interface


From: Laurent Vivier
Subject: [Qemu-devel] [PATCH 3/5] Add block SG interface
Date: Wed, 23 Jan 2008 17:12:54 +0100

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 device.

Laurent
---
 Makefile          |    2 
 Makefile.target   |    2 
 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
===================================================================
--- 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
 
 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 = bdrv_aio_read_em;
         bdrv->bdrv_aio_write = bdrv_aio_write_em;
         bdrv->bdrv_aio_cancel = bdrv_aio_cancel_em;
         bdrv->aiocb_size = 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 = bdrv_read_em;
         bdrv->bdrv_write = bdrv_write_em;
@@ -267,6 +268,8 @@ static BlockDriver *find_image_format(co
         struct stat st;
         if (stat(filename, &st) >= 0 &&
             (S_ISCHR(st.st_mode) || S_ISBLK(st.st_mode))) {
+            if ((st.st_rdev >> 8) == 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);
 }
 
 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 = bs->drv;
+
+    if (drv && drv->bdrv_execute) {
+        return drv->bdrv_execute(bs, request, complete);
+    }
+    return -ENOTSUP;
+}
Index: qemu/block.h
===================================================================
--- 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;
 
 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);
+
 
 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
===================================================================
--- /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 <address@hidden>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to 
deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * 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 OTHER
+ * 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 <unistd.h>
+#include <scsi/sg.h>
+
+#include "block-sg.h"
+
+#include <sys/ioctl.h>
+
+//#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 = bs->opaque;
+
+    return read(s->fd, buf, count);
+}
+
+static int sg_write(BlockDriverState *bs, const uint8_t *buf, int count)
+{
+    BDRVSGState *s = 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 = 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 = (RawAIOCB *)blockacb;
+
+    qemu_aio_cancel(acb);
+}
+
+static void sg_close(BlockDriverState *bs)
+{
+    BDRVSGState *s = bs->opaque;
+    close(s->fd);
+}
+
+static int sg_open(BlockDriverState *bs, const char *filename, int flags)
+{
+    BDRVSGState *s = bs->opaque;
+    int fd, open_flags, ret;
+    int sg_version = 0;
+    struct sg_scsi_id scsiid;
+
+    open_flags = O_BINARY;
+    if ((flags & BDRV_O_ACCESS) == O_RDWR) {
+        open_flags |= O_RDWR;
+    } else {
+        open_flags |= O_RDONLY;
+        bs->read_only = 1;
+    }
+
+    fd = open(filename, open_flags, 0644);
+    if (fd < 0) {
+        ret = -errno;
+        if (ret == -EROFS)
+            ret = -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 = fd;
+    s->lun = scsiid.lun;
+
+    return 0;
+}
+
+int sg_execute(BlockDriverState *bs, void *request,
+               BlockDriverCompletionFunc *complete)
+{
+    BDRVSGState *s = bs->opaque;
+    SGRequest *r = (SGRequest *)request;
+
+    DPRINTF("sg_execute bs %p request %p complete %p\n",
+            bs, request, complete);
+
+    if (request == NULL)
+        return s->lun;
+
+    if (sg_write(bs, (const uint8_t *)&r->io_header,
+                 sizeof(r->io_header)) == -1) {
+        BADF("execute_command: write failed ! (%d)\n", errno);
+        return -1;
+    }
+    if (complete == NULL) {
+        int ret;
+        r->aiocb = NULL;
+        while ((ret = sg_read(bs, (uint8_t *)&r->io_header,
+                              sizeof(r->io_header))) == -1 &&
+                errno == EINTR);
+        if (ret == -1) {
+            BADF("execute_command: read failed !\n");
+            return -1;
+        }
+        return 0;
+    }
+
+    r->aiocb = sg_aio_read(bs, 0, (uint8_t*)&r->io_header,
+                           sizeof(r->io_header), complete, r);
+    if (r->aiocb == NULL) {
+        BADF("execute_command: read failed !\n");
+        return -1;
+    }
+
+    return 0;
+}
+
+BlockDriver bdrv_sg_device = {
+    "sg_device",
+    sizeof(BDRVSGState),
+    NULL,
+    sg_open,
+    NULL,
+    NULL,
+    sg_close,
+    NULL,
+    NULL,
+    .aiocb_size = sizeof(RawAIOCB),
+    .bdrv_aio_cancel = sg_aio_cancel,
+    /* generic scsi device */
+    .bdrv_execute = sg_execute,
+};
Index: qemu/hw/scsi-generic.c
===================================================================
--- 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 @@
 
 #include "qemu-common.h"
 #include "block.h"
+#include "block_int.h"
 #include "scsi-disk.h"
 
-//#ifndef __linux__
-#if 1
+#ifndef __linux__
 
 SCSIDevice *scsi_generic_init(BlockDriverState *bdrv, int tcq,
                               scsi_completionfn completion, void *opaque)
@@ -44,6 +44,7 @@ do { fprintf(stderr, "scsi-generic: " fm
 #include <unistd.h>
 #include <scsi/sg.h>
 #include <scsi/scsi.h>
+#include "block-sg.h"
 
 #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
 
-#define SG_ERR_DRIVER_TIMEOUT 0x06
-#define SG_ERR_DRIVER_SENSE 0x08
-
 #ifndef MAX_UINT
 #define MAX_UINT ((unsigned int)-1)
 #endif
 
 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;
 
 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 = s;
     r->tag = tag;
     memset(r->cmd, 0, sizeof(r->cmd));
-    memset(&r->io_header, 0, sizeof(r->io_header));
     r->cmdlen = 0;
     r->len = 0;
-    r->aiocb = NULL;
 
     /* link */
 
@@ -147,14 +141,14 @@ static SCSIRequest *scsi_find_request(SC
 }
 
 /* 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 = (SCSIRequest *)opaque;
+    SCSIRequest *r = (SCSIRequest *)request;
     SCSIDeviceState *s = r->dev;
     uint32_t tag;
     int sense;
 
-    s->driver_status = r->io_header.driver_status;
+    s->driver_status = r->sg.io_header.driver_status;
     if (ret != 0)
         sense = HARDWARE_ERROR;
     else {
@@ -167,10 +161,10 @@ static void scsi_command_complete(void *
             sense = s->sensebuf[2] & 0x0f;
     }
 
-    DPRINTF("Command complete 0x%p tag=0x%x sense=%d\n", r, r->tag, sense);
+    DPRINTF("Command complete %p tag=0x%x sense=%d\n", r, r->tag, sense);
     tag = r->tag;
     scsi_remove_request(r);
-    s->completion(s->opaque, SCSI_REASON_DONE, tag, sense);
+    s->completion(s->card, SCSI_REASON_DONE, tag, sense);
 }
 
 /* Cancel a pending data transfer.  */
@@ -182,60 +176,35 @@ static void scsi_cancel_io(SCSIDevice *d
     DPRINTF("Cancel tag=0x%x\n", tag);
     r = scsi_find_request(s, tag);
     if (r) {
-        if (r->aiocb)
-            bdrv_aio_cancel(r->aiocb);
-        r->aiocb = NULL;
+        if (r->sg.aiocb)
+            bdrv_aio_cancel(r->sg.aiocb);
+        r->sg.aiocb = NULL;
         scsi_remove_request(r);
     }
 }
 
 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 = 'S';
+    r->sg.io_header.dxfer_direction = direction;
+    r->sg.io_header.cmd_len = r->cmdlen;
+    r->sg.io_header.mx_sb_len = sizeof(r->dev->sensebuf);
+    r->sg.io_header.dxfer_len = r->buflen;
+    r->sg.io_header.dxferp = r->buf;
+    r->sg.io_header.cmdp = r->cmd;
+    r->sg.io_header.sbp = r->dev->sensebuf;
+    r->sg.io_header.timeout = MAX_UINT;
+    r->sg.io_header.flags |= SG_FLAG_DIRECT_IO;
 
-    r->io_header.interface_id = 'S';
-    r->io_header.dxfer_direction = direction;
-    r->io_header.dxferp = r->buf;
-    r->io_header.dxfer_len = r->buflen;
-    r->io_header.cmdp = r->cmd;
-    r->io_header.cmd_len = r->cmdlen;
-    r->io_header.mx_sb_len = sizeof(r->dev->sensebuf);
-    r->io_header.sbp = r->dev->sensebuf;
-    r->io_header.timeout = MAX_UINT;
-    r->io_header.usr_ptr = r;
-    r->io_header.flags |= SG_FLAG_DIRECT_IO;
-
-    if (bdrv_pwrite(bdrv, -1, &r->io_header, sizeof(r->io_header)) == -1) {
-        BADF("execute_command: write failed ! (%d)\n", errno);
-        return -1;
-    }
-    if (complete == NULL) {
-        int ret;
-        r->aiocb = NULL;
-        while ((ret = bdrv_pread(bdrv, -1, &r->io_header,
-                                           sizeof(r->io_header))) == -1 &&
-                      errno == EINTR);
-        if (ret == -1) {
-            BADF("execute_command: read failed !\n");
-            return -1;
-        }
-        return 0;
-    }
-
-    r->aiocb = bdrv_aio_read(bdrv, 0, (uint8_t*)&r->io_header,
-                          -(int64_t)sizeof(r->io_header), complete, r);
-    if (r->aiocb == NULL) {
-        BADF("execute_command: read failed !\n");
-        return -1;
-    }
-
-    return 0;
+    return bdrv_execute(bdrv, &r->sg, complete);
 }
 
-static void scsi_read_complete(void * opaque, int ret)
+static void scsi_read_complete(void *request, int ret)
 {
-    SCSIRequest *r = (SCSIRequest *)opaque;
+    SCSIRequest *r = (SCSIRequest *)request;
     SCSIDeviceState *s = r->dev;
     int len;
 
@@ -244,11 +213,11 @@ static void scsi_read_complete(void * op
         scsi_command_complete(r, ret);
         return;
     }
-    len = r->io_header.dxfer_len - r->io_header.resid;
+    len = r->sg.io_header.dxfer_len - r->sg.io_header.resid;
     DPRINTF("Data ready tag=0x%x len=%d\n", r->tag, len);
 
     r->len = -1;
-    s->completion(s->opaque, SCSI_REASON_DATA, r->tag, len);
+    s->completion(s->card, SCSI_REASON_DATA, r->tag, len);
 }
 
 /* Read more data from scsi device into buffer.  */
@@ -275,9 +244,9 @@ static void scsi_read_data(SCSIDevice *d
     if (r->cmd[0] == REQUEST_SENSE && s->driver_status & SG_ERR_DRIVER_SENSE)
     {
         memcpy(r->buf, s->sensebuf, 16);
-        r->io_header.driver_status = 0;
+        r->sg.io_header.driver_status = 0;
         r->len = -1;
-        s->completion(s->opaque, SCSI_REASON_DATA, r->tag, 16);
+        s->completion(s->card, SCSI_REASON_DATA, r->tag, 16);
         return;
     }
 
@@ -288,10 +257,9 @@ static void scsi_read_data(SCSIDevice *d
     }
 }
 
-static void scsi_write_complete(void * opaque, int ret)
+static void scsi_write_complete(void* request, int ret)
 {
-    SCSIRequest *r = (SCSIRequest *)opaque;
-
+    SCSIRequest* r = (SCSIRequest*)request;
     DPRINTF("scsi_write_complete() ret = %d\n", ret);
     if (ret) {
         DPRINTF("IO error\n");
@@ -321,7 +289,7 @@ static int scsi_write_data(SCSIDevice *d
 
     if (r->len == 0) {
         r->len = 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;
     }
 
@@ -339,11 +307,13 @@ static uint8_t *scsi_get_buf(SCSIDevice 
 {
     SCSIDeviceState *s = d->state;
     SCSIRequest *r;
+    DPRINTF("scsi_get_buf: %d\n", tag);
     r = scsi_find_request(s, tag);
     if (!r) {
         BADF("Bad buffer tag 0x%x\n", tag);
         return NULL;
     }
+    DPRINTF("scsi_get_buf: r=%p buf=%p\n", r, r->buf);
     return r->buf;
 }
 
@@ -483,13 +453,16 @@ static int32_t scsi_send_command(SCSIDev
     int cmdlen;
     SCSIRequest *r;
     int ret;
+    int target_lun;
 
     /* ??? Tags are not unique for different luns.  We only implement a
        single lun, so this should not matter.  */
 
-    if (lun != s->lun || (cmd[1] >> 5) != s->lun) {
+    target_lun = bdrv_execute(s->bdrv, NULL, NULL);
+
+    if (lun != target_lun || (cmd[1] >> 5) != 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;
     }
 
@@ -500,7 +473,6 @@ static int32_t scsi_send_command(SCSIDev
 
     DPRINTF("Command: lun=%d tag=0x%x data=0x%02x len %d\n", lun, tag,
             cmd[0], len);
-
     r = 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
 
     if (len == 0) {
         if (r->buf != NULL)
-            free(r->buf);
+            qemu_free(r->buf);
         r->buflen = 0;
         r->buf = NULL;
         ret = execute_command(s->bdrv, r, SG_DXFER_NONE, 
scsi_command_complete);
-        if (ret == -1) {
+        if (ret == -1)
             scsi_command_complete(r, -EINVAL);
-            return 0;
-        }
         return 0;
     }
 
     if (r->buflen != len) {
         if (r->buf != NULL)
-            free(r->buf);
+            qemu_free(r->buf);
         r->buf = qemu_malloc(len);
         r->buflen = len;
     }
@@ -543,34 +513,28 @@ static int32_t scsi_send_command(SCSIDev
 
 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;
 
-    memset(cmd, sizeof(cmd), 0);
-    memset(buf, sizeof(buf), 0);
+    memset(cmd, 0, sizeof(cmd));
+    memset(buf, 0, sizeof(buf));
     cmd[0] = READ_CAPACITY;
 
-    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_pwrite(bdrv, -1, &io_header, sizeof(io_header));
-    if (ret == -1)
-        return -1;
-
-    while ((ret = bdrv_pread(bdrv, -1, &io_header, sizeof(io_header))) == -1 &&
-           errno == EINTR);
+    memset(&sg.io_header, 0, sizeof(sg.io_header));
+    sg.io_header.interface_id = 'S';
+    sg.io_header.dxfer_direction = SG_DXFER_FROM_DEV;
+    sg.io_header.dxfer_len = sizeof(buf);
+    sg.io_header.dxferp = buf;
+    sg.io_header.cmdp = cmd;
+    sg.io_header.cmd_len = sizeof(cmd);
+    sg.io_header.mx_sb_len = sizeof(sensebuf);
+    sg.io_header.sbp = sensebuf;
+    sg.io_header.timeout = 6000; /* XXX */
 
+    ret = bdrv_execute(bdrv, &sg, NULL);
     if (ret == -1)
         return -1;
 
@@ -600,27 +564,12 @@ static void scsi_destroy(SCSIDevice *d)
 }
 
 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? */
 
-    if (bdrv_ioctl(bdrv, SG_GET_SCSI_ID, &scsiid))
+    if (bdrv->drv->bdrv_execute == NULL)
         return NULL;
 
     /* define device state */
@@ -629,8 +578,7 @@ SCSIDevice *scsi_generic_init(BlockDrive
     s->bdrv = bdrv;
     s->requests = NULL;
     s->completion = completion;
-    s->opaque = opaque;
-    s->lun = scsiid.lun;
+    s->card = card;
     s->blocksize = get_blocksize(s->bdrv);
     s->driver_status = 0;
     memset(s->sensebuf, 0, sizeof(s->sensebuf));
Index: qemu/Makefile.target
===================================================================
--- 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=vl.o osdep.o monitor.o pci.o loa
 ifdef CONFIG_WIN32
 VL_OBJS+=block-raw-win32.o
 else
-VL_OBJS+=block-raw-posix.o qemu-aio-posix.o
+VL_OBJS+=block-raw-posix.o block-sg.o qemu-aio-posix.o
 endif
 
 ifdef CONFIG_ALSA
Index: qemu/Makefile
===================================================================
--- 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=cutils.o
 BLOCK_OBJS+=block-cow.o block-qcow.o aes.o block-vmdk.o block-cloop.o
 BLOCK_OBJS+=block-dmg.o block-bochs.o block-vpc.o block-vvfat.o
-BLOCK_OBJS+=block-qcow2.o block-parallels.o
+BLOCK_OBJS+=block-qcow2.o block-parallels.o block-sg.o
 
 ######################################################################
 # libqemu_common.a: Target indepedent part of system emulation. The
Index: qemu/block-sg.h
===================================================================
--- /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 <address@hidden>
+ *
+ * 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
===================================================================
--- 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);
 
+    /* SG device */
+    int (*bdrv_execute)(BlockDriverState *bs, void *request,
+                        BlockDriverCompletionFunc *complete);
+
     BlockDriverAIOCB *free_aiocb;
     struct BlockDriver *next;
 };





reply via email to

[Prev in Thread] Current Thread [Next in Thread]