[Top][All Lists]
[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;
};
Re: [Qemu-devel] [PATCH 0/5] SCSI passthrough cleanup, Fabrice Bellard, 2008/01/23