Real SCSI device passthrough (v4)
PATCH 1/1 Real SCSI device passthrough (v4)
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.
v4 improves Windows support.
Laurent
--- Makefile | 1 block-raw.c | 27 +- 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 | 653 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 9 files changed, 710 insertions(+), 7 deletions(-)
Makefile +1 -0
@@ -56,6 +56,7 @@ OBJS+=irq.o OBJS+=i2c.o smbus.o smbus_eeprom.o max7310.o max111x.o wm8750.o OBJS+=ssd0303.o ssd0323.o ads7846.o stellaris_input.o OBJS+=scsi-disk.o cdrom.o +OBJS+=scsi-generic.o OBJS+=usb.o usb-hub.o usb-linux.o usb-hid.o usb-msd.o usb-wacom.o OBJS+=sd.o ssi-sd.o
block-raw.c +22 -5
@@ -148,7 +148,7 @@ static int raw_pread(BlockDriverState *bif (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
@@ -201,7 +201,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) [%"
@@ -273,8 +273,8 @@ void qemu_aio_init(void)seems to fix the problem. */ struct aioinit ai;memset (&ai,0 ,sizeof (ai)); - ai.aio_threads =1 ; - ai.aio_num =1 ; + ai.aio_threads =16 ; + ai.aio_num =16 ; ai.aio_idle_time =365 *100000 ;aio_init (&ai); }
@@ -384,7 +384,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;
@@ -672,6 +675,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 );
@@ -851,6 +856,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)
@@ -873,6 +884,10 @@ static int raw_set_locked(BlockDriverStareturn -ENOTSUP ; } +static int raw_ioctl (BlockDriverState *bs,unsigned long int req,void *buf) +{ +return -ENOTSUP ; +}#endif /* !linux */ BlockDriver bdrv_host_device = {
@@ -899,6 +914,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 */
block.c +16 -0
@@ -786,6 +786,11 @@ int bdrv_is_read_only(BlockDriverState *return bs->read_only; } +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)
@@ -1394,3 +1399,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 ; +}
block.h +2 -0
@@ -118,6 +118,7 @@ int bdrv_get_type_hint(BlockDriverStateint 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_media_changed (BlockDriverState *bs);int bdrv_is_locked (BlockDriverState *bs);
@@ -147,6 +148,7 @@ int bdrv_snapshot_delete(BlockDriverStatint bdrv_snapshot_list (BlockDriverState *bs,QEMUSnapshotInfo **psn_info);char *bdrv_snapshot_dump (char *buf,int buf_size,QEMUSnapshotInfo *sn); +int bdrv_ioctl (BlockDriverState *bs,unsigned long int req,void *buf);char *get_human_readable_size (char *buf,int buf_size,int64_t size);int path_is_absolute (const char *path);
block_int.h +4 -0
@@ -82,6 +82,9 @@ struct BlockDriver {int (*bdrv_eject)(BlockDriverState *bs,int eject_flag);int (*bdrv_set_locked)(BlockDriverState *bs,int locked); +/* to control generic scsi devices */ +int (*bdrv_ioctl)(BlockDriverState *bs,unsigned long int req,char *buf); +BlockDriverAIOCB *free_aiocb;struct BlockDriver *next; };
@@ -93,6 +96,7 @@ struct BlockDriverState {int removable;/* if true, the media can be removed */ int locked;/* if true, the media cannot temporarily be ejected */ int encrypted;/* if true, the media is encrypted */ +int sg;/* if true, the device is a /dev/sg* */ /* event callback when inserting/removing */ void (*change_cb)(void *opaque);void *change_opaque;
hw/esp.c +3 -1
@@ -615,7 +615,9 @@ void esp_scsi_attach(void *opaque, Block }DPRINTF ("Attaching block device %d\n" , id);/* Command queueing is not implemented. */ - s->scsi_dev[id] =scsi_disk_init (bd,0 , esp_command_complete, s); + s->scsi_dev[id] =scsi_generic_init (bd,0 , esp_command_complete, s); +if (s->scsi_dev[id] ==NULL ) + s->scsi_dev[id] =scsi_disk_init (bd,0 , esp_command_complete, s); } void *esp_init(target_phys_addr_t espaddr,
hw/lsi53c895a.c +7 -1
@@ -1236,6 +1236,8 @@ static uint8_t lsi_reg_readb(LSIState *sreturn s->sdid;case 0x07 :/* GPREG0 */ return 0x7f ; +case 0x08 :/* Revision ID */ +return 0x00 ;case 0xa :/* SSID */ return s->ssid;case 0xb :/* SBCL */
@@ -1281,6 +1283,8 @@ static uint8_t lsi_reg_readb(LSIState *sreturn s->ctest4;case 0x22 :/* CTEST5 */ return s->ctest5; +case 0x23 :/* CTEST6 */ +return 0 ;case 0x24 :/* DBC[0:7] */ return s->dbc &0xff ;case 0x25 :/* DBC[8:15] */
@@ -1838,7 +1842,9 @@ void lsi_scsi_attach(void *opaque, Block s->scsi_dev[id]->destroy (s->scsi_dev[id]); }DPRINTF ("Attaching block device %d\n" , id); - s->scsi_dev[id] =scsi_disk_init (bd,1 , lsi_command_complete, s); + s->scsi_dev[id] =scsi_generic_init (bd,1 , lsi_command_complete, s); +if (s->scsi_dev[id] ==NULL ) + s->scsi_dev[id] =scsi_disk_init (bd,1 , lsi_command_complete, s); }void *lsi_scsi_init (PCIBus *bus,int devfn)
hw/scsi-disk.h +2 -0
@@ -26,6 +26,8 @@ struct SCSIDeviceSCSIDevice *scsi_disk_init (BlockDriverState *bdrv,int tcq,scsi_completionfn completion,void *opaque); +SCSIDevice *scsi_generic_init (BlockDriverState *bdrv,int tcq, +scsi_completionfn completion,void *opaque);/* cdrom.c */ int cdrom_read_toc (int nb_sectors,uint8_t *buf,int msf,int start_track);
hw/scsi-generic.c new file +653 -0
653 lines not on this page · raw message