This patch allows to connect the virtual SCSI interface of Qemu to
a real SCSI device of the host.
Using the devices /dev/sg, it allows to send the SCSI commands from the
virtual SCSI interface to the real device.
It has been tested with a SATA disk and an ATA CD burner with ide-scsi module
and wodim to burn a CD-RW.
v3 has moved SCSI clenup to a separate patch.
Laurent
---
Makefile |1
block-raw.c | 23 +
block.c | 16 +
block.h |2
block_int.h |4
hw/esp.c |4
hw/lsi53c895a.c |8
hw/scsi-disk.h|2
hw/scsi-generic.c | 667 ++
9 files changed, 722 insertions(+), 5 deletions(-)
Index: qemu/block-raw.c
===
--- qemu.orig/block-raw.c 2007-12-07 13:40:36.0 +0100
+++ qemu/block-raw.c2007-12-07 14:22:05.0 +0100
@@ -152,7 +152,7 @@ static int raw_pread(BlockDriverState *b
if (ret 0)
return ret;
-if (lseek(s-fd, offset, SEEK_SET) == (off_t)-1) {
+if (offset = 0 lseek(s-fd, offset, SEEK_SET) == (off_t)-1) {
++(s-lseek_err_cnt);
if(s-lseek_err_cnt = 10) {
DEBUG_BLOCK_PRINT(raw_pread(%d:%s, % PRId64 , %p, %d) [% PRId64
@@ -205,7 +205,7 @@ static int raw_pwrite(BlockDriverState *
if (ret 0)
return ret;
-if (lseek(s-fd, offset, SEEK_SET) == (off_t)-1) {
+if (offset = 0 lseek(s-fd, offset, SEEK_SET) == (off_t)-1) {
++(s-lseek_err_cnt);
if(s-lseek_err_cnt) {
DEBUG_BLOCK_PRINT(raw_pwrite(%d:%s, % PRId64 , %p, %d) [%
@@ -388,7 +388,10 @@ static RawAIOCB *raw_aio_setup(BlockDriv
acb-aiocb.aio_sigevent.sigev_signo = aio_sig_num;
acb-aiocb.aio_sigevent.sigev_notify = SIGEV_SIGNAL;
acb-aiocb.aio_buf = buf;
-acb-aiocb.aio_nbytes = nb_sectors * 512;
+if (nb_sectors 0)
+acb-aiocb.aio_nbytes = -nb_sectors;
+else
+acb-aiocb.aio_nbytes = nb_sectors * 512;
acb-aiocb.aio_offset = sector_num * 512;
acb-next = first_aio;
first_aio = acb;
@@ -680,6 +683,8 @@ static int hdev_open(BlockDriverState *b
s-fd_open_flags = open_flags;
/* open will not fail even if no floppy is inserted */
open_flags |= O_NONBLOCK;
+} else if (strstart(filename, /dev/sg, NULL)) {
+bs-sg = 1;
}
#endif
fd = open(filename, open_flags, 0644);
@@ -859,6 +864,12 @@ static int raw_set_locked(BlockDriverSta
return 0;
}
+static int raw_ioctl(BlockDriverState *bs, unsigned long int req, void *buf)
+{
+BDRVRawState *s = bs-opaque;
+
+return ioctl(s-fd, req, buf);
+}
#else
static int raw_is_inserted(BlockDriverState *bs)
@@ -881,6 +892,10 @@ static int raw_set_locked(BlockDriverSta
return -ENOTSUP;
}
+static int raw_ioctl(BlockDriverState *bs, unsigned long int req, void *buf)
+{
+return -ENOTSUP;
+}
#endif /* !linux */
BlockDriver bdrv_host_device = {
@@ -907,6 +922,8 @@ BlockDriver bdrv_host_device = {
.bdrv_media_changed = raw_media_changed,
.bdrv_eject = raw_eject,
.bdrv_set_locked = raw_set_locked,
+/* generic scsi device */
+.bdrv_ioctl = raw_ioctl,
};
#else /* _WIN32 */
Index: qemu/block.c
===
--- qemu.orig/block.c 2007-12-07 13:40:36.0 +0100
+++ qemu/block.c2007-12-07 13:40:41.0 +0100
@@ -796,6 +796,11 @@ int bdrv_is_cached(BlockDriverState *bs)
return bs-cache;
}
+int bdrv_is_sg(BlockDriverState *bs)
+{
+return bs-sg;
+}
+
/* XXX: no longer used */
void bdrv_set_change_cb(BlockDriverState *bs,
void (*change_cb)(void *opaque), void *opaque)
@@ -1404,3 +1409,14 @@ void bdrv_set_locked(BlockDriverState *b
drv-bdrv_set_locked(bs, locked);
}
}
+
+/* needed for generic scsi interface */
+
+int bdrv_ioctl(BlockDriverState *bs, unsigned long int req, void *buf)
+{
+BlockDriver *drv = bs-drv;
+
+if (drv drv-bdrv_ioctl)
+return drv-bdrv_ioctl(bs, req, buf);
+return -ENOTSUP;
+}
Index: qemu/block.h
===
--- qemu.orig/block.h 2007-12-07 13:40:36.0 +0100
+++ qemu/block.h2007-12-07 13:40:41.0 +0100
@@ -120,6 +120,7 @@ int bdrv_get_type_hint(BlockDriverState
int bdrv_get_translation_hint(BlockDriverState *bs);
int bdrv_is_removable(BlockDriverState *bs);
int bdrv_is_read_only(BlockDriverState *bs);
+int bdrv_is_sg(BlockDriverState *bs);
int bdrv_is_inserted(BlockDriverState *bs);
int bdrv_is_cached(BlockDriverState *bs);
int bdrv_media_changed(BlockDriverState *bs);
@@ -150,6 +151,7 @@ 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