aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorths <ths@c046a42c-6fe2-441c-8c8c-71466251a162>2007-12-24 16:10:43 +0000
committerths <ths@c046a42c-6fe2-441c-8c8c-71466251a162>2007-12-24 16:10:43 +0000
commit985a03b0ce38275c2ea355bf29b6d6b5779dbb56 (patch)
tree22eac188d157768555e44f33f2eca5be2508c10b
parent1b0889958e875df85c7b2353498ed2cac16415ce (diff)
downloadqemu-985a03b0ce38275c2ea355bf29b6d6b5779dbb56.zip
qemu-985a03b0ce38275c2ea355bf29b6d6b5779dbb56.tar.gz
qemu-985a03b0ce38275c2ea355bf29b6d6b5779dbb56.tar.bz2
Real SCSI device passthrough (v4), by Laurent Vivier.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@3851 c046a42c-6fe2-441c-8c8c-71466251a162
-rw-r--r--Makefile1
-rw-r--r--block-raw-posix.c27
-rw-r--r--block.c16
-rw-r--r--block.h2
-rw-r--r--block_int.h4
-rw-r--r--hw/esp.c4
-rw-r--r--hw/lsi53c895a.c8
-rw-r--r--hw/scsi-disk.h2
8 files changed, 57 insertions, 7 deletions
diff --git a/Makefile b/Makefile
index bc91d29..ce76352 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 8ace5ef..b50da1f 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 a3299b8..0f8ad7b 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 b52ee92..b730505 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 9463ea3..137000e 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 df7a5e1..fa58c6e 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 3a4ddf7..a08cfd9 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 ffe894b..f42212b 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);