From 985a03b0ce38275c2ea355bf29b6d6b5779dbb56 Mon Sep 17 00:00:00 2001 From: ths Date: Mon, 24 Dec 2007 16:10:43 +0000 Subject: [PATCH] Real SCSI device passthrough (v4), by Laurent Vivier. git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@3851 c046a42c-6fe2-441c-8c8c-71466251a162 --- Makefile | 1 + block-raw-posix.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 ++ 8 files changed, 57 insertions(+), 7 deletions(-) diff --git a/Makefile b/Makefile index bc91d29b2..ce76352e6 100644 --- a/Makefile +++ b/Makefile @@ -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 diff --git a/block-raw-posix.c b/block-raw-posix.c index 8ace5ef74..b50da1f7b 100644 --- a/block-raw-posix.c +++ b/block-raw-posix.c @@ -151,7 +151,7 @@ static int raw_pread(BlockDriverState *bs, int64_t offset, 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 @@ -204,7 +204,7 @@ static int raw_pwrite(BlockDriverState *bs, int64_t offset, 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) [%" @@ -276,8 +276,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); } @@ -387,7 +387,10 @@ static RawAIOCB *raw_aio_setup(BlockDriverState *bs, 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; @@ -679,6 +682,8 @@ static int hdev_open(BlockDriverState *bs, const char *filename, int flags) 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); @@ -858,6 +863,12 @@ static int raw_set_locked(BlockDriverState *bs, int locked) 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) @@ -880,6 +891,10 @@ static int raw_set_locked(BlockDriverState *bs, int locked) return -ENOTSUP; } +static int raw_ioctl(BlockDriverState *bs, unsigned long int req, void *buf) +{ + return -ENOTSUP; +} #endif /* !linux */ BlockDriver bdrv_host_device = { @@ -906,4 +921,6 @@ 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, }; diff --git a/block.c b/block.c index a3299b8fb..0f8ad7bce 100644 --- a/block.c +++ b/block.c @@ -786,6 +786,11 @@ int bdrv_is_read_only(BlockDriverState *bs) 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 *bs, int locked) 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; +} diff --git a/block.h b/block.h index b52ee920b..b73050556 100644 --- a/block.h +++ b/block.h @@ -119,6 +119,7 @@ int bdrv_get_type_hint(BlockDriverState *bs); 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_media_changed(BlockDriverState *bs); int bdrv_is_locked(BlockDriverState *bs); @@ -148,6 +149,7 @@ int bdrv_snapshot_delete(BlockDriverState *bs, const char *snapshot_id); int 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); diff --git a/block_int.h b/block_int.h index 9463ea3aa..137000e14 100644 --- a/block_int.h +++ b/block_int.h @@ -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, void *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; diff --git a/hw/esp.c b/hw/esp.c index df7a5e166..fa58c6e6b 100644 --- a/hw/esp.c +++ b/hw/esp.c @@ -615,7 +615,9 @@ void esp_scsi_attach(void *opaque, BlockDriverState *bd, int id) } 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, diff --git a/hw/lsi53c895a.c b/hw/lsi53c895a.c index 3a4ddf7f6..a08cfd9e3 100644 --- a/hw/lsi53c895a.c +++ b/hw/lsi53c895a.c @@ -1236,6 +1236,8 @@ static uint8_t lsi_reg_readb(LSIState *s, int offset) return 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 *s, int offset) return 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, BlockDriverState *bd, int id) 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) diff --git a/hw/scsi-disk.h b/hw/scsi-disk.h index ffe894b76..f42212bc2 100644 --- a/hw/scsi-disk.h +++ b/hw/scsi-disk.h @@ -26,6 +26,8 @@ struct SCSIDevice SCSIDevice *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);