Commit 985a03b0ce38275c2ea355bf29b6d6b5779dbb56
1 parent
1b088995
Real SCSI device passthrough (v4), by Laurent Vivier.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@3851 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
8 changed files
with
57 additions
and
7 deletions
Makefile
| @@ -56,6 +56,7 @@ OBJS+=irq.o | @@ -56,6 +56,7 @@ OBJS+=irq.o | ||
| 56 | OBJS+=i2c.o smbus.o smbus_eeprom.o max7310.o max111x.o wm8750.o | 56 | OBJS+=i2c.o smbus.o smbus_eeprom.o max7310.o max111x.o wm8750.o |
| 57 | OBJS+=ssd0303.o ssd0323.o ads7846.o stellaris_input.o | 57 | OBJS+=ssd0303.o ssd0323.o ads7846.o stellaris_input.o |
| 58 | OBJS+=scsi-disk.o cdrom.o | 58 | OBJS+=scsi-disk.o cdrom.o |
| 59 | +OBJS+=scsi-generic.o | ||
| 59 | OBJS+=usb.o usb-hub.o usb-linux.o usb-hid.o usb-msd.o usb-wacom.o | 60 | OBJS+=usb.o usb-hub.o usb-linux.o usb-hid.o usb-msd.o usb-wacom.o |
| 60 | OBJS+=sd.o ssi-sd.o | 61 | OBJS+=sd.o ssi-sd.o |
| 61 | 62 |
block-raw-posix.c
| @@ -151,7 +151,7 @@ static int raw_pread(BlockDriverState *bs, int64_t offset, | @@ -151,7 +151,7 @@ static int raw_pread(BlockDriverState *bs, int64_t offset, | ||
| 151 | if (ret < 0) | 151 | if (ret < 0) |
| 152 | return ret; | 152 | return ret; |
| 153 | 153 | ||
| 154 | - if (lseek(s->fd, offset, SEEK_SET) == (off_t)-1) { | 154 | + if (offset >= 0 && lseek(s->fd, offset, SEEK_SET) == (off_t)-1) { |
| 155 | ++(s->lseek_err_cnt); | 155 | ++(s->lseek_err_cnt); |
| 156 | if(s->lseek_err_cnt <= 10) { | 156 | if(s->lseek_err_cnt <= 10) { |
| 157 | DEBUG_BLOCK_PRINT("raw_pread(%d:%s, %" PRId64 ", %p, %d) [%" PRId64 | 157 | DEBUG_BLOCK_PRINT("raw_pread(%d:%s, %" PRId64 ", %p, %d) [%" PRId64 |
| @@ -204,7 +204,7 @@ static int raw_pwrite(BlockDriverState *bs, int64_t offset, | @@ -204,7 +204,7 @@ static int raw_pwrite(BlockDriverState *bs, int64_t offset, | ||
| 204 | if (ret < 0) | 204 | if (ret < 0) |
| 205 | return ret; | 205 | return ret; |
| 206 | 206 | ||
| 207 | - if (lseek(s->fd, offset, SEEK_SET) == (off_t)-1) { | 207 | + if (offset >= 0 && lseek(s->fd, offset, SEEK_SET) == (off_t)-1) { |
| 208 | ++(s->lseek_err_cnt); | 208 | ++(s->lseek_err_cnt); |
| 209 | if(s->lseek_err_cnt) { | 209 | if(s->lseek_err_cnt) { |
| 210 | DEBUG_BLOCK_PRINT("raw_pwrite(%d:%s, %" PRId64 ", %p, %d) [%" | 210 | DEBUG_BLOCK_PRINT("raw_pwrite(%d:%s, %" PRId64 ", %p, %d) [%" |
| @@ -276,8 +276,8 @@ void qemu_aio_init(void) | @@ -276,8 +276,8 @@ void qemu_aio_init(void) | ||
| 276 | seems to fix the problem. */ | 276 | seems to fix the problem. */ |
| 277 | struct aioinit ai; | 277 | struct aioinit ai; |
| 278 | memset(&ai, 0, sizeof(ai)); | 278 | memset(&ai, 0, sizeof(ai)); |
| 279 | - ai.aio_threads = 1; | ||
| 280 | - ai.aio_num = 1; | 279 | + ai.aio_threads = 16; |
| 280 | + ai.aio_num = 16; | ||
| 281 | ai.aio_idle_time = 365 * 100000; | 281 | ai.aio_idle_time = 365 * 100000; |
| 282 | aio_init(&ai); | 282 | aio_init(&ai); |
| 283 | } | 283 | } |
| @@ -387,7 +387,10 @@ static RawAIOCB *raw_aio_setup(BlockDriverState *bs, | @@ -387,7 +387,10 @@ static RawAIOCB *raw_aio_setup(BlockDriverState *bs, | ||
| 387 | acb->aiocb.aio_sigevent.sigev_signo = aio_sig_num; | 387 | acb->aiocb.aio_sigevent.sigev_signo = aio_sig_num; |
| 388 | acb->aiocb.aio_sigevent.sigev_notify = SIGEV_SIGNAL; | 388 | acb->aiocb.aio_sigevent.sigev_notify = SIGEV_SIGNAL; |
| 389 | acb->aiocb.aio_buf = buf; | 389 | acb->aiocb.aio_buf = buf; |
| 390 | - acb->aiocb.aio_nbytes = nb_sectors * 512; | 390 | + if (nb_sectors < 0) |
| 391 | + acb->aiocb.aio_nbytes = -nb_sectors; | ||
| 392 | + else | ||
| 393 | + acb->aiocb.aio_nbytes = nb_sectors * 512; | ||
| 391 | acb->aiocb.aio_offset = sector_num * 512; | 394 | acb->aiocb.aio_offset = sector_num * 512; |
| 392 | acb->next = first_aio; | 395 | acb->next = first_aio; |
| 393 | first_aio = acb; | 396 | first_aio = acb; |
| @@ -679,6 +682,8 @@ static int hdev_open(BlockDriverState *bs, const char *filename, int flags) | @@ -679,6 +682,8 @@ static int hdev_open(BlockDriverState *bs, const char *filename, int flags) | ||
| 679 | s->fd_open_flags = open_flags; | 682 | s->fd_open_flags = open_flags; |
| 680 | /* open will not fail even if no floppy is inserted */ | 683 | /* open will not fail even if no floppy is inserted */ |
| 681 | open_flags |= O_NONBLOCK; | 684 | open_flags |= O_NONBLOCK; |
| 685 | + } else if (strstart(filename, "/dev/sg", NULL)) { | ||
| 686 | + bs->sg = 1; | ||
| 682 | } | 687 | } |
| 683 | #endif | 688 | #endif |
| 684 | fd = open(filename, open_flags, 0644); | 689 | fd = open(filename, open_flags, 0644); |
| @@ -858,6 +863,12 @@ static int raw_set_locked(BlockDriverState *bs, int locked) | @@ -858,6 +863,12 @@ static int raw_set_locked(BlockDriverState *bs, int locked) | ||
| 858 | return 0; | 863 | return 0; |
| 859 | } | 864 | } |
| 860 | 865 | ||
| 866 | +static int raw_ioctl(BlockDriverState *bs, unsigned long int req, void *buf) | ||
| 867 | +{ | ||
| 868 | + BDRVRawState *s = bs->opaque; | ||
| 869 | + | ||
| 870 | + return ioctl(s->fd, req, buf); | ||
| 871 | +} | ||
| 861 | #else | 872 | #else |
| 862 | 873 | ||
| 863 | static int raw_is_inserted(BlockDriverState *bs) | 874 | static int raw_is_inserted(BlockDriverState *bs) |
| @@ -880,6 +891,10 @@ static int raw_set_locked(BlockDriverState *bs, int locked) | @@ -880,6 +891,10 @@ static int raw_set_locked(BlockDriverState *bs, int locked) | ||
| 880 | return -ENOTSUP; | 891 | return -ENOTSUP; |
| 881 | } | 892 | } |
| 882 | 893 | ||
| 894 | +static int raw_ioctl(BlockDriverState *bs, unsigned long int req, void *buf) | ||
| 895 | +{ | ||
| 896 | + return -ENOTSUP; | ||
| 897 | +} | ||
| 883 | #endif /* !linux */ | 898 | #endif /* !linux */ |
| 884 | 899 | ||
| 885 | BlockDriver bdrv_host_device = { | 900 | BlockDriver bdrv_host_device = { |
| @@ -906,4 +921,6 @@ BlockDriver bdrv_host_device = { | @@ -906,4 +921,6 @@ BlockDriver bdrv_host_device = { | ||
| 906 | .bdrv_media_changed = raw_media_changed, | 921 | .bdrv_media_changed = raw_media_changed, |
| 907 | .bdrv_eject = raw_eject, | 922 | .bdrv_eject = raw_eject, |
| 908 | .bdrv_set_locked = raw_set_locked, | 923 | .bdrv_set_locked = raw_set_locked, |
| 924 | + /* generic scsi device */ | ||
| 925 | + .bdrv_ioctl = raw_ioctl, | ||
| 909 | }; | 926 | }; |
block.c
| @@ -786,6 +786,11 @@ int bdrv_is_read_only(BlockDriverState *bs) | @@ -786,6 +786,11 @@ int bdrv_is_read_only(BlockDriverState *bs) | ||
| 786 | return bs->read_only; | 786 | return bs->read_only; |
| 787 | } | 787 | } |
| 788 | 788 | ||
| 789 | +int bdrv_is_sg(BlockDriverState *bs) | ||
| 790 | +{ | ||
| 791 | + return bs->sg; | ||
| 792 | +} | ||
| 793 | + | ||
| 789 | /* XXX: no longer used */ | 794 | /* XXX: no longer used */ |
| 790 | void bdrv_set_change_cb(BlockDriverState *bs, | 795 | void bdrv_set_change_cb(BlockDriverState *bs, |
| 791 | void (*change_cb)(void *opaque), void *opaque) | 796 | void (*change_cb)(void *opaque), void *opaque) |
| @@ -1394,3 +1399,14 @@ void bdrv_set_locked(BlockDriverState *bs, int locked) | @@ -1394,3 +1399,14 @@ void bdrv_set_locked(BlockDriverState *bs, int locked) | ||
| 1394 | drv->bdrv_set_locked(bs, locked); | 1399 | drv->bdrv_set_locked(bs, locked); |
| 1395 | } | 1400 | } |
| 1396 | } | 1401 | } |
| 1402 | + | ||
| 1403 | +/* needed for generic scsi interface */ | ||
| 1404 | + | ||
| 1405 | +int bdrv_ioctl(BlockDriverState *bs, unsigned long int req, void *buf) | ||
| 1406 | +{ | ||
| 1407 | + BlockDriver *drv = bs->drv; | ||
| 1408 | + | ||
| 1409 | + if (drv && drv->bdrv_ioctl) | ||
| 1410 | + return drv->bdrv_ioctl(bs, req, buf); | ||
| 1411 | + return -ENOTSUP; | ||
| 1412 | +} |
block.h
| @@ -119,6 +119,7 @@ int bdrv_get_type_hint(BlockDriverState *bs); | @@ -119,6 +119,7 @@ int bdrv_get_type_hint(BlockDriverState *bs); | ||
| 119 | int bdrv_get_translation_hint(BlockDriverState *bs); | 119 | int bdrv_get_translation_hint(BlockDriverState *bs); |
| 120 | int bdrv_is_removable(BlockDriverState *bs); | 120 | int bdrv_is_removable(BlockDriverState *bs); |
| 121 | int bdrv_is_read_only(BlockDriverState *bs); | 121 | int bdrv_is_read_only(BlockDriverState *bs); |
| 122 | +int bdrv_is_sg(BlockDriverState *bs); | ||
| 122 | int bdrv_is_inserted(BlockDriverState *bs); | 123 | int bdrv_is_inserted(BlockDriverState *bs); |
| 123 | int bdrv_media_changed(BlockDriverState *bs); | 124 | int bdrv_media_changed(BlockDriverState *bs); |
| 124 | int bdrv_is_locked(BlockDriverState *bs); | 125 | int bdrv_is_locked(BlockDriverState *bs); |
| @@ -148,6 +149,7 @@ int bdrv_snapshot_delete(BlockDriverState *bs, const char *snapshot_id); | @@ -148,6 +149,7 @@ int bdrv_snapshot_delete(BlockDriverState *bs, const char *snapshot_id); | ||
| 148 | int bdrv_snapshot_list(BlockDriverState *bs, | 149 | int bdrv_snapshot_list(BlockDriverState *bs, |
| 149 | QEMUSnapshotInfo **psn_info); | 150 | QEMUSnapshotInfo **psn_info); |
| 150 | char *bdrv_snapshot_dump(char *buf, int buf_size, QEMUSnapshotInfo *sn); | 151 | char *bdrv_snapshot_dump(char *buf, int buf_size, QEMUSnapshotInfo *sn); |
| 152 | +int bdrv_ioctl(BlockDriverState *bs, unsigned long int req, void *buf); | ||
| 151 | 153 | ||
| 152 | char *get_human_readable_size(char *buf, int buf_size, int64_t size); | 154 | char *get_human_readable_size(char *buf, int buf_size, int64_t size); |
| 153 | int path_is_absolute(const char *path); | 155 | int path_is_absolute(const char *path); |
block_int.h
| @@ -82,6 +82,9 @@ struct BlockDriver { | @@ -82,6 +82,9 @@ struct BlockDriver { | ||
| 82 | int (*bdrv_eject)(BlockDriverState *bs, int eject_flag); | 82 | int (*bdrv_eject)(BlockDriverState *bs, int eject_flag); |
| 83 | int (*bdrv_set_locked)(BlockDriverState *bs, int locked); | 83 | int (*bdrv_set_locked)(BlockDriverState *bs, int locked); |
| 84 | 84 | ||
| 85 | + /* to control generic scsi devices */ | ||
| 86 | + int (*bdrv_ioctl)(BlockDriverState *bs, unsigned long int req, void *buf); | ||
| 87 | + | ||
| 85 | BlockDriverAIOCB *free_aiocb; | 88 | BlockDriverAIOCB *free_aiocb; |
| 86 | struct BlockDriver *next; | 89 | struct BlockDriver *next; |
| 87 | }; | 90 | }; |
| @@ -93,6 +96,7 @@ struct BlockDriverState { | @@ -93,6 +96,7 @@ struct BlockDriverState { | ||
| 93 | int removable; /* if true, the media can be removed */ | 96 | int removable; /* if true, the media can be removed */ |
| 94 | int locked; /* if true, the media cannot temporarily be ejected */ | 97 | int locked; /* if true, the media cannot temporarily be ejected */ |
| 95 | int encrypted; /* if true, the media is encrypted */ | 98 | int encrypted; /* if true, the media is encrypted */ |
| 99 | + int sg; /* if true, the device is a /dev/sg* */ | ||
| 96 | /* event callback when inserting/removing */ | 100 | /* event callback when inserting/removing */ |
| 97 | void (*change_cb)(void *opaque); | 101 | void (*change_cb)(void *opaque); |
| 98 | void *change_opaque; | 102 | void *change_opaque; |
hw/esp.c
| @@ -615,7 +615,9 @@ void esp_scsi_attach(void *opaque, BlockDriverState *bd, int id) | @@ -615,7 +615,9 @@ void esp_scsi_attach(void *opaque, BlockDriverState *bd, int id) | ||
| 615 | } | 615 | } |
| 616 | DPRINTF("Attaching block device %d\n", id); | 616 | DPRINTF("Attaching block device %d\n", id); |
| 617 | /* Command queueing is not implemented. */ | 617 | /* Command queueing is not implemented. */ |
| 618 | - s->scsi_dev[id] = scsi_disk_init(bd, 0, esp_command_complete, s); | 618 | + s->scsi_dev[id] = scsi_generic_init(bd, 0, esp_command_complete, s); |
| 619 | + if (s->scsi_dev[id] == NULL) | ||
| 620 | + s->scsi_dev[id] = scsi_disk_init(bd, 0, esp_command_complete, s); | ||
| 619 | } | 621 | } |
| 620 | 622 | ||
| 621 | void *esp_init(target_phys_addr_t espaddr, | 623 | void *esp_init(target_phys_addr_t espaddr, |
hw/lsi53c895a.c
| @@ -1236,6 +1236,8 @@ static uint8_t lsi_reg_readb(LSIState *s, int offset) | @@ -1236,6 +1236,8 @@ static uint8_t lsi_reg_readb(LSIState *s, int offset) | ||
| 1236 | return s->sdid; | 1236 | return s->sdid; |
| 1237 | case 0x07: /* GPREG0 */ | 1237 | case 0x07: /* GPREG0 */ |
| 1238 | return 0x7f; | 1238 | return 0x7f; |
| 1239 | + case 0x08: /* Revision ID */ | ||
| 1240 | + return 0x00; | ||
| 1239 | case 0xa: /* SSID */ | 1241 | case 0xa: /* SSID */ |
| 1240 | return s->ssid; | 1242 | return s->ssid; |
| 1241 | case 0xb: /* SBCL */ | 1243 | case 0xb: /* SBCL */ |
| @@ -1281,6 +1283,8 @@ static uint8_t lsi_reg_readb(LSIState *s, int offset) | @@ -1281,6 +1283,8 @@ static uint8_t lsi_reg_readb(LSIState *s, int offset) | ||
| 1281 | return s->ctest4; | 1283 | return s->ctest4; |
| 1282 | case 0x22: /* CTEST5 */ | 1284 | case 0x22: /* CTEST5 */ |
| 1283 | return s->ctest5; | 1285 | return s->ctest5; |
| 1286 | + case 0x23: /* CTEST6 */ | ||
| 1287 | + return 0; | ||
| 1284 | case 0x24: /* DBC[0:7] */ | 1288 | case 0x24: /* DBC[0:7] */ |
| 1285 | return s->dbc & 0xff; | 1289 | return s->dbc & 0xff; |
| 1286 | case 0x25: /* DBC[8:15] */ | 1290 | case 0x25: /* DBC[8:15] */ |
| @@ -1838,7 +1842,9 @@ void lsi_scsi_attach(void *opaque, BlockDriverState *bd, int id) | @@ -1838,7 +1842,9 @@ void lsi_scsi_attach(void *opaque, BlockDriverState *bd, int id) | ||
| 1838 | s->scsi_dev[id]->destroy(s->scsi_dev[id]); | 1842 | s->scsi_dev[id]->destroy(s->scsi_dev[id]); |
| 1839 | } | 1843 | } |
| 1840 | DPRINTF("Attaching block device %d\n", id); | 1844 | DPRINTF("Attaching block device %d\n", id); |
| 1841 | - s->scsi_dev[id] = scsi_disk_init(bd, 1, lsi_command_complete, s); | 1845 | + s->scsi_dev[id] = scsi_generic_init(bd, 1, lsi_command_complete, s); |
| 1846 | + if (s->scsi_dev[id] == NULL) | ||
| 1847 | + s->scsi_dev[id] = scsi_disk_init(bd, 1, lsi_command_complete, s); | ||
| 1842 | } | 1848 | } |
| 1843 | 1849 | ||
| 1844 | void *lsi_scsi_init(PCIBus *bus, int devfn) | 1850 | void *lsi_scsi_init(PCIBus *bus, int devfn) |
hw/scsi-disk.h
| @@ -26,6 +26,8 @@ struct SCSIDevice | @@ -26,6 +26,8 @@ struct SCSIDevice | ||
| 26 | 26 | ||
| 27 | SCSIDevice *scsi_disk_init(BlockDriverState *bdrv, int tcq, | 27 | SCSIDevice *scsi_disk_init(BlockDriverState *bdrv, int tcq, |
| 28 | scsi_completionfn completion, void *opaque); | 28 | scsi_completionfn completion, void *opaque); |
| 29 | +SCSIDevice *scsi_generic_init(BlockDriverState *bdrv, int tcq, | ||
| 30 | + scsi_completionfn completion, void *opaque); | ||
| 29 | 31 | ||
| 30 | /* cdrom.c */ | 32 | /* cdrom.c */ |
| 31 | int cdrom_read_toc(int nb_sectors, uint8_t *buf, int msf, int start_track); | 33 | int cdrom_read_toc(int nb_sectors, uint8_t *buf, int msf, int start_track); |