From: Laurent Vivier <Laurent.Vivier@bull.net>
Cc: qemu-devel@nongnu.org
Subject: [Qemu-devel] [PATCH 3/5] Add block SG interface
Date: Wed, 23 Jan 2008 17:12:54 +0100 [thread overview]
Message-ID: <1201104774984@bull.net> (raw)
In-Reply-To: <120110477478@bull.net>
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 <Laurent.Vivier@bull.net>
+ *
+ * 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 <Laurent.Vivier@bull.net>
+ *
+ * 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;
};
next prev parent reply other threads:[~2008-01-23 16:10 UTC|newest]
Thread overview: 8+ messages / expand[flat|nested] mbox.gz Atom feed top
2008-01-23 16:12 [Qemu-devel] [PATCH 0/5] SCSI passthrough cleanup Laurent Vivier
2008-01-23 16:12 ` [Qemu-devel] [PATCH 1/5] reverse scsi-generic Laurent Vivier
2008-01-23 16:12 ` [Qemu-devel] [PATCH 2/5] Move AIO Laurent Vivier
2008-01-23 16:12 ` Laurent Vivier [this message]
2008-01-23 16:12 ` [Qemu-devel] [PATCH 4/5] DVD movie support Laurent Vivier
2008-01-23 16:12 ` [Qemu-devel] [PATCH 5/5] SCSI device DMA split Laurent Vivier
2008-01-23 20:52 ` [Qemu-devel] [PATCH 0/5] SCSI passthrough cleanup Fabrice Bellard
2008-01-24 8:17 ` Laurent Vivier
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1201104774984@bull.net \
--to=laurent.vivier@bull.net \
--cc=qemu-devel@nongnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.