summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile.objs2
-rw-r--r--block.c91
-rw-r--r--block.h1
-rw-r--r--block/raw-posix.c20
-rw-r--r--blockdev.c600
-rw-r--r--blockdev.h71
-rw-r--r--hw/acpi_piix4.c1
-rw-r--r--hw/apb_pci.c1
-rw-r--r--hw/device-hotplug.c4
-rw-r--r--hw/fdc.c1
-rw-r--r--hw/fdc.h2
-rw-r--r--hw/ide/cmd646.c4
-rw-r--r--hw/ide/core.c108
-rw-r--r--hw/ide/internal.h13
-rw-r--r--hw/ide/isa.c2
-rw-r--r--hw/ide/macio.c2
-rw-r--r--hw/ide/microdrive.c3
-rw-r--r--hw/ide/mmio.c2
-rw-r--r--hw/ide/piix.c4
-rw-r--r--hw/ide/qdev.c21
-rw-r--r--hw/lan9118.c1
-rw-r--r--hw/nand.c3
-rw-r--r--hw/omap2.c2
-rw-r--r--hw/onenand.c3
-rw-r--r--hw/parallel.c1
-rw-r--r--hw/pc.c1
-rw-r--r--hw/pc_piix.c1
-rw-r--r--hw/pci-hotplug.c2
-rw-r--r--hw/pcmcia.h2
-rw-r--r--hw/pl181.c1
-rw-r--r--hw/qdev-properties.c12
-rw-r--r--hw/qdev.c6
-rw-r--r--hw/qdev.h6
-rw-r--r--hw/scsi-bus.c1
-rw-r--r--hw/scsi-disk.c26
-rw-r--r--hw/scsi-generic.c1
-rw-r--r--hw/serial.c1
-rw-r--r--hw/ssi-sd.c1
-rw-r--r--hw/usb-hid.c1
-rw-r--r--hw/usb-msd.c4
-rw-r--r--hw/virtio-blk.c9
-rw-r--r--hw/virtio-pci.c1
-rw-r--r--monitor.c104
-rw-r--r--qemu-char.c1
-rw-r--r--qemu-io.c4
-rw-r--r--savevm.c2
-rw-r--r--sysemu.h52
-rw-r--r--vl.c499
48 files changed, 916 insertions, 785 deletions
diff --git a/Makefile.objs b/Makefile.objs
index 2dad0f941..2bfb6d180 100644
--- a/Makefile.objs
+++ b/Makefile.objs
@@ -44,7 +44,7 @@ fsdev-obj-$(CONFIG_LINUX) += $(addprefix fsdev/, $(fsdev-nested-y))
# system emulation, i.e. a single QEMU executable should support all
# CPUs and machines.
-common-obj-y = $(block-obj-y)
+common-obj-y = $(block-obj-y) blockdev.o
common-obj-y += $(net-obj-y)
common-obj-y += $(qobject-obj-y)
common-obj-$(CONFIG_LINUX) += $(fsdev-obj-$(CONFIG_LINUX))
diff --git a/block.c b/block.c
index 39724c17d..cacf11bd9 100644
--- a/block.c
+++ b/block.c
@@ -331,8 +331,8 @@ static BlockDriver *find_image_format(const char *filename)
if (ret < 0)
return NULL;
- /* Return the raw BlockDriver * to scsi-generic devices */
- if (bs->sg) {
+ /* Return the raw BlockDriver * to scsi-generic devices or empty drives */
+ if (bs->sg || !bdrv_is_inserted(bs)) {
bdrv_delete(bs);
return bdrv_find_format("raw");
}
@@ -522,7 +522,7 @@ int bdrv_open(BlockDriverState *bs, const char *filename, int flags,
bdrv_delete(bs1);
return ret;
}
- total_size = bdrv_getlength(bs1) >> BDRV_SECTOR_BITS;
+ total_size = bdrv_getlength(bs1) & BDRV_SECTOR_MASK;
if (bs1->drv && bs1->drv->protocol_name)
is_protocol = 1;
@@ -541,7 +541,7 @@ int bdrv_open(BlockDriverState *bs, const char *filename, int flags,
bdrv_qcow2 = bdrv_find_format("qcow2");
options = parse_option_parameters("", bdrv_qcow2->create_options, NULL);
- set_option_parameter_int(options, BLOCK_OPT_SIZE, total_size * 512);
+ set_option_parameter_int(options, BLOCK_OPT_SIZE, total_size);
set_option_parameter(options, BLOCK_OPT_BACKING_FILE, backing_filename);
if (drv) {
set_option_parameter(options, BLOCK_OPT_BACKING_FMT,
@@ -648,6 +648,15 @@ void bdrv_close(BlockDriverState *bs)
}
}
+void bdrv_close_all(void)
+{
+ BlockDriverState *bs;
+
+ QTAILQ_FOREACH(bs, &bdrv_states, list) {
+ bdrv_close(bs);
+ }
+}
+
void bdrv_delete(BlockDriverState *bs)
{
/* remove from list, if necessary */
@@ -684,7 +693,7 @@ int bdrv_commit(BlockDriverState *bs)
int64_t i, total_sectors;
int n, j, ro, open_flags;
int ret = 0, rw_ret = 0;
- unsigned char sector[512];
+ unsigned char sector[BDRV_SECTOR_SIZE];
char filename[1024];
BlockDriverState *bs_rw, *bs_ro;
@@ -824,7 +833,8 @@ static int bdrv_check_byte_request(BlockDriverState *bs, int64_t offset,
static int bdrv_check_request(BlockDriverState *bs, int64_t sector_num,
int nb_sectors)
{
- return bdrv_check_byte_request(bs, sector_num * 512, nb_sectors * 512);
+ return bdrv_check_byte_request(bs, sector_num * BDRV_SECTOR_SIZE,
+ nb_sectors * BDRV_SECTOR_SIZE);
}
/* return < 0 if error. See bdrv_write() for the return codes */
@@ -1059,7 +1069,7 @@ struct partition {
static int guess_disk_lchs(BlockDriverState *bs,
int *pcylinders, int *pheads, int *psectors)
{
- uint8_t buf[512];
+ uint8_t buf[BDRV_SECTOR_SIZE];
int ret, i, heads, sectors, cylinders;
struct partition *p;
uint32_t nr_sects;
@@ -1535,7 +1545,7 @@ static QObject* bdrv_info_stats_bs(BlockDriverState *bs)
"} }",
bs->rd_bytes, bs->wr_bytes,
bs->rd_ops, bs->wr_ops,
- bs->wr_highest_sector * 512);
+ bs->wr_highest_sector * (long)BDRV_SECTOR_SIZE);
dict = qobject_to_qdict(res);
if (*bs->device_name) {
@@ -1621,9 +1631,11 @@ int bdrv_save_vmstate(BlockDriverState *bs, const uint8_t *buf,
BlockDriver *drv = bs->drv;
if (!drv)
return -ENOMEDIUM;
- if (!drv->bdrv_save_vmstate)
- return -ENOTSUP;
- return drv->bdrv_save_vmstate(bs, buf, pos, size);
+ if (drv->bdrv_save_vmstate)
+ return drv->bdrv_save_vmstate(bs, buf, pos, size);
+ if (bs->file)
+ return bdrv_save_vmstate(bs->file, buf, pos, size);
+ return -ENOTSUP;
}
int bdrv_load_vmstate(BlockDriverState *bs, uint8_t *buf,
@@ -1632,9 +1644,11 @@ int bdrv_load_vmstate(BlockDriverState *bs, uint8_t *buf,
BlockDriver *drv = bs->drv;
if (!drv)
return -ENOMEDIUM;
- if (!drv->bdrv_load_vmstate)
- return -ENOTSUP;
- return drv->bdrv_load_vmstate(bs, buf, pos, size);
+ if (drv->bdrv_load_vmstate)
+ return drv->bdrv_load_vmstate(bs, buf, pos, size);
+ if (bs->file)
+ return bdrv_load_vmstate(bs->file, buf, pos, size);
+ return -ENOTSUP;
}
void bdrv_debug_event(BlockDriverState *bs, BlkDebugEvent event)
@@ -1658,20 +1672,37 @@ int bdrv_snapshot_create(BlockDriverState *bs,
BlockDriver *drv = bs->drv;
if (!drv)
return -ENOMEDIUM;
- if (!drv->bdrv_snapshot_create)
- return -ENOTSUP;
- return drv->bdrv_snapshot_create(bs, sn_info);
+ if (drv->bdrv_snapshot_create)
+ return drv->bdrv_snapshot_create(bs, sn_info);
+ if (bs->file)
+ return bdrv_snapshot_create(bs->file, sn_info);
+ return -ENOTSUP;
}
int bdrv_snapshot_goto(BlockDriverState *bs,
const char *snapshot_id)
{
BlockDriver *drv = bs->drv;
+ int ret, open_ret;
+
if (!drv)
return -ENOMEDIUM;
- if (!drv->bdrv_snapshot_goto)
- return -ENOTSUP;
- return drv->bdrv_snapshot_goto(bs, snapshot_id);
+ if (drv->bdrv_snapshot_goto)
+ return drv->bdrv_snapshot_goto(bs, snapshot_id);
+
+ if (bs->file) {
+ drv->bdrv_close(bs);
+ ret = bdrv_snapshot_goto(bs->file, snapshot_id);
+ open_ret = drv->bdrv_open(bs, bs->open_flags);
+ if (open_ret < 0) {
+ bdrv_delete(bs->file);
+ bs->drv = NULL;
+ return open_ret;
+ }
+ return ret;
+ }
+
+ return -ENOTSUP;
}
int bdrv_snapshot_delete(BlockDriverState *bs, const char *snapshot_id)
@@ -1679,9 +1710,11 @@ int bdrv_snapshot_delete(BlockDriverState *bs, const char *snapshot_id)
BlockDriver *drv = bs->drv;
if (!drv)
return -ENOMEDIUM;
- if (!drv->bdrv_snapshot_delete)
- return -ENOTSUP;
- return drv->bdrv_snapshot_delete(bs, snapshot_id);
+ if (drv->bdrv_snapshot_delete)
+ return drv->bdrv_snapshot_delete(bs, snapshot_id);
+ if (bs->file)
+ return bdrv_snapshot_delete(bs->file, snapshot_id);
+ return -ENOTSUP;
}
int bdrv_snapshot_list(BlockDriverState *bs,
@@ -1690,9 +1723,11 @@ int bdrv_snapshot_list(BlockDriverState *bs,
BlockDriver *drv = bs->drv;
if (!drv)
return -ENOMEDIUM;
- if (!drv->bdrv_snapshot_list)
- return -ENOTSUP;
- return drv->bdrv_snapshot_list(bs, psn_info);
+ if (drv->bdrv_snapshot_list)
+ return drv->bdrv_snapshot_list(bs, psn_info);
+ if (bs->file)
+ return bdrv_snapshot_list(bs->file, psn_info);
+ return -ENOTSUP;
}
#define NB_SUFFIXES 4
@@ -2197,7 +2232,7 @@ static int bdrv_read_em(BlockDriverState *bs, int64_t sector_num,
async_ret = NOT_DONE;
iov.iov_base = (void *)buf;
- iov.iov_len = nb_sectors * 512;
+ iov.iov_len = nb_sectors * BDRV_SECTOR_SIZE;
qemu_iovec_init_external(&qiov, &iov, 1);
acb = bdrv_aio_readv(bs, sector_num, &qiov, nb_sectors,
bdrv_rw_em_cb, &async_ret);
@@ -2228,7 +2263,7 @@ static int bdrv_write_em(BlockDriverState *bs, int64_t sector_num,
async_ret = NOT_DONE;
iov.iov_base = (void *)buf;
- iov.iov_len = nb_sectors * 512;
+ iov.iov_len = nb_sectors * BDRV_SECTOR_SIZE;
qemu_iovec_init_external(&qiov, &iov, 1);
acb = bdrv_aio_writev(bs, sector_num, &qiov, nb_sectors,
bdrv_rw_em_cb, &async_ret);
diff --git a/block.h b/block.h
index 756670d22..25744b134 100644
--- a/block.h
+++ b/block.h
@@ -123,6 +123,7 @@ BlockDriverAIOCB *bdrv_aio_ioctl(BlockDriverState *bs,
/* Ensure contents are flushed to disk. */
void bdrv_flush(BlockDriverState *bs);
void bdrv_flush_all(void);
+void bdrv_close_all(void);
int bdrv_has_zero_init(BlockDriverState *bs);
int bdrv_is_allocated(BlockDriverState *bs, int64_t sector_num, int nb_sectors,
diff --git a/block/raw-posix.c b/block/raw-posix.c
index 7541ed2ab..3f0701b8a 100644
--- a/block/raw-posix.c
+++ b/block/raw-posix.c
@@ -392,8 +392,9 @@ static int raw_read(BlockDriverState *bs, int64_t sector_num,
{
int ret;
- ret = raw_pread(bs, sector_num * 512, buf, nb_sectors * 512);
- if (ret == (nb_sectors * 512))
+ ret = raw_pread(bs, sector_num * BDRV_SECTOR_SIZE, buf,
+ nb_sectors * BDRV_SECTOR_SIZE);
+ if (ret == (nb_sectors * BDRV_SECTOR_SIZE))
ret = 0;
return ret;
}
@@ -480,8 +481,9 @@ static int raw_write(BlockDriverState *bs, int64_t sector_num,
const uint8_t *buf, int nb_sectors)
{
int ret;
- ret = raw_pwrite(bs, sector_num * 512, buf, nb_sectors * 512);
- if (ret == (nb_sectors * 512))
+ ret = raw_pwrite(bs, sector_num * BDRV_SECTOR_SIZE, buf,
+ nb_sectors * BDRV_SECTOR_SIZE);
+ if (ret == (nb_sectors * BDRV_SECTOR_SIZE))
ret = 0;
return ret;
}
@@ -494,7 +496,7 @@ static int qiov_is_aligned(QEMUIOVector *qiov)
int i;
for (i = 0; i < qiov->niov; i++) {
- if ((uintptr_t) qiov->iov[i].iov_base % 512) {
+ if ((uintptr_t) qiov->iov[i].iov_base % BDRV_SECTOR_SIZE) {
return 0;
}
}
@@ -703,7 +705,7 @@ static int raw_create(const char *filename, QEMUOptionParameter *options)
/* Read out options */
while (options && options->name) {
if (!strcmp(options->name, BLOCK_OPT_SIZE)) {
- total_size = options->value.n / 512;
+ total_size = options->value.n / BDRV_SECTOR_SIZE;
}
options++;
}
@@ -713,7 +715,7 @@ static int raw_create(const char *filename, QEMUOptionParameter *options)
if (fd < 0) {
result = -errno;
} else {
- if (ftruncate(fd, total_size * 512) != 0) {
+ if (ftruncate(fd, total_size * BDRV_SECTOR_SIZE) != 0) {
result = -errno;
}
if (close(fd) != 0) {
@@ -976,7 +978,7 @@ static int hdev_create(const char *filename, QEMUOptionParameter *options)
/* Read out options */
while (options && options->name) {
if (!strcmp(options->name, "size")) {
- total_size = options->value.n / 512;
+ total_size = options->value.n / BDRV_SECTOR_SIZE;
}
options++;
}
@@ -989,7 +991,7 @@ static int hdev_create(const char *filename, QEMUOptionParameter *options)
ret = -errno;
else if (!S_ISBLK(stat_buf.st_mode) && !S_ISCHR(stat_buf.st_mode))
ret = -ENODEV;
- else if (lseek(fd, 0, SEEK_END) < total_size * 512)
+ else if (lseek(fd, 0, SEEK_END) < total_size * BDRV_SECTOR_SIZE)
ret = -ENOSPC;
close(fd);
diff --git a/blockdev.c b/blockdev.c
new file mode 100644
index 000000000..642ce756a
--- /dev/null
+++ b/blockdev.c
@@ -0,0 +1,600 @@
+/*
+ * QEMU host block devices
+ *
+ * Copyright (c) 2003-2008 Fabrice Bellard
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or
+ * later. See the COPYING file in the top-level directory.
+ */
+
+#include "block.h"
+#include "blockdev.h"
+#include "monitor.h"
+#include "qerror.h"
+#include "qemu-option.h"
+#include "qemu-config.h"
+#include "sysemu.h"
+
+struct drivelist drives = QTAILQ_HEAD_INITIALIZER(drives);
+
+QemuOpts *drive_add(const char *file, const char *fmt, ...)
+{
+ va_list ap;
+ char optstr[1024];
+ QemuOpts *opts;
+
+ va_start(ap, fmt);
+ vsnprintf(optstr, sizeof(optstr), fmt, ap);
+ va_end(ap);
+
+ opts = qemu_opts_parse(&qemu_drive_opts, optstr, 0);
+ if (!opts) {
+ return NULL;
+ }
+ if (file)
+ qemu_opt_set(opts, "file", file);
+ return opts;
+}
+
+DriveInfo *drive_get(BlockInterfaceType type, int bus, int unit)
+{
+ DriveInfo *dinfo;
+
+ /* seek interface, bus and unit */
+
+ QTAILQ_FOREACH(dinfo, &drives, next) {
+ if (dinfo->type == type &&
+ dinfo->bus == bus &&
+ dinfo->unit == unit)
+ return dinfo;
+ }
+
+ return NULL;
+}
+
+DriveInfo *drive_get_by_id(const char *id)
+{
+ DriveInfo *dinfo;
+
+ QTAILQ_FOREACH(dinfo, &drives, next) {
+ if (strcmp(id, dinfo->id))
+ continue;
+ return dinfo;
+ }
+ return NULL;
+}
+
+int drive_get_max_bus(BlockInterfaceType type)
+{
+ int max_bus;
+ DriveInfo *dinfo;
+
+ max_bus = -1;
+ QTAILQ_FOREACH(dinfo, &drives, next) {
+ if(dinfo->type == type &&
+ dinfo->bus > max_bus)
+ max_bus = dinfo->bus;
+ }
+ return max_bus;
+}
+
+const char *drive_get_serial(BlockDriverState *bdrv)
+{
+ DriveInfo *dinfo;
+
+ QTAILQ_FOREACH(dinfo, &drives, next) {
+ if (dinfo->bdrv == bdrv)
+ return dinfo->serial;
+ }
+
+ return "\0";
+}
+
+BlockInterfaceErrorAction drive_get_on_error(
+ BlockDriverState *bdrv, int is_read)
+{
+ DriveInfo *dinfo;
+
+ QTAILQ_FOREACH(dinfo, &drives, next) {
+ if (dinfo->bdrv == bdrv)
+ return is_read ? dinfo->on_read_error : dinfo->on_write_error;
+ }
+
+ return is_read ? BLOCK_ERR_REPORT : BLOCK_ERR_STOP_ENOSPC;
+}
+
+static void bdrv_format_print(void *opaque, const char *name)
+{
+ fprintf(stderr, " %s", name);
+}
+
+void drive_uninit(DriveInfo *dinfo)
+{
+ qemu_opts_del(dinfo->opts);
+ bdrv_delete(dinfo->bdrv);
+ QTAILQ_REMOVE(&drives, dinfo, next);
+ qemu_free(dinfo);
+}
+
+static int parse_block_error_action(const char *buf, int is_read)
+{
+ if (!strcmp(buf, "ignore")) {
+ return BLOCK_ERR_IGNORE;
+ } else if (!is_read && !strcmp(buf, "enospc")) {
+ return BLOCK_ERR_STOP_ENOSPC;
+ } else if (!strcmp(buf, "stop")) {
+ return BLOCK_ERR_STOP_ANY;
+ } else if (!strcmp(buf, "report")) {
+ return BLOCK_ERR_REPORT;
+ } else {
+ fprintf(stderr, "qemu: '%s' invalid %s error action\n",
+ buf, is_read ? "read" : "write");
+ return -1;
+ }
+}
+
+DriveInfo *drive_init(QemuOpts *opts, int default_to_scsi, int *fatal_error)
+{
+ const char *buf;
+ const char *file = NULL;
+ char devname[128];
+ const char *serial;
+ const char *mediastr = "";
+ BlockInterfaceType type;
+ enum { MEDIA_DISK, MEDIA_CDROM } media;
+ int bus_id, unit_id;
+ int cyls, heads, secs, translation;
+ BlockDriver *drv = NULL;
+ int max_devs;
+ int index;
+ int ro = 0;
+ int bdrv_flags = 0;
+ int on_read_error, on_write_error;
+ const char *devaddr;
+ DriveInfo *dinfo;
+ int snapshot = 0;
+ int ret;
+
+ *fatal_error = 1;
+
+ translation = BIOS_ATA_TRANSLATION_AUTO;
+
+ if (default_to_scsi) {
+ type = IF_SCSI;
+ max_devs = MAX_SCSI_DEVS;
+ pstrcpy(devname, sizeof(devname), "scsi");
+ } else {
+ type = IF_IDE;
+ max_devs = MAX_IDE_DEVS;
+ pstrcpy(devname, sizeof(devname), "ide");
+ }
+ media = MEDIA_DISK;
+
+ /* extract parameters */
+ bus_id = qemu_opt_get_number(opts, "bus", 0);
+ unit_id = qemu_opt_get_number(opts, "unit", -1);
+ index = qemu_opt_get_number(opts, "index", -1);
+
+ cyls = qemu_opt_get_number(opts, "cyls", 0);
+ heads = qemu_opt_get_number(opts, "heads", 0);
+ secs = qemu_opt_get_number(opts, "secs", 0);
+
+ snapshot = qemu_opt_get_bool(opts, "snapshot", 0);
+ ro = qemu_opt_get_bool(opts, "readonly", 0);
+
+ file = qemu_opt_get(opts, "file");
+ serial = qemu_opt_get(opts, "serial");
+
+ if ((buf = qemu_opt_get(opts, "if")) != NULL) {
+ pstrcpy(devname, sizeof(devname), buf);
+ if (!strcmp(buf, "ide")) {
+ type = IF_IDE;
+ max_devs = MAX_IDE_DEVS;
+ } else if (!strcmp(buf, "scsi")) {
+ type = IF_SCSI;
+ max_devs = MAX_SCSI_DEVS;
+ } else if (!strcmp(buf, "floppy")) {
+ type = IF_FLOPPY;
+ max_devs = 0;
+ } else if (!strcmp(buf, "pflash")) {
+ type = IF_PFLASH;
+ max_devs = 0;
+ } else if (!strcmp(buf, "mtd")) {
+ type = IF_MTD;
+ max_devs = 0;
+ } else if (!strcmp(buf, "sd")) {
+ type = IF_SD;
+ max_devs = 0;
+ } else if (!strcmp(buf, "virtio")) {
+ type = IF_VIRTIO;
+ max_devs = 0;
+ } else if (!strcmp(buf, "xen")) {
+ type = IF_XEN;
+ max_devs = 0;
+ } else if (!strcmp(buf, "none")) {
+ type = IF_NONE;
+ max_devs = 0;
+ } else {
+ fprintf(stderr, "qemu: unsupported bus type '%s'\n", buf);
+ return NULL;
+ }
+ }
+
+ if (cyls || heads || secs) {
+ if (cyls < 1 || (type == IF_IDE && cyls > 16383)) {
+ fprintf(stderr, "qemu: '%s' invalid physical cyls number\n", buf);
+ return NULL;
+ }
+ if (heads < 1 || (type == IF_IDE && heads > 16)) {
+ fprintf(stderr, "qemu: '%s' invalid physical heads number\n", buf);
+ return NULL;
+ }
+ if (secs < 1 || (type == IF_IDE && secs > 63)) {
+ fprintf(stderr, "qemu: '%s' invalid physical secs number\n", buf);
+ return NULL;
+ }
+ }
+
+ if ((buf = qemu_opt_get(opts, "trans")) != NULL) {
+ if (!cyls) {
+ fprintf(stderr,
+ "qemu: '%s' trans must be used with cyls,heads and secs\n",
+ buf);
+ return NULL;
+ }
+ if (!strcmp(buf, "none"))
+ translation = BIOS_ATA_TRANSLATION_NONE;
+ else if (!strcmp(buf, "lba"))
+ translation = BIOS_ATA_TRANSLATION_LBA;
+ else if (!strcmp(buf, "auto"))
+ translation = BIOS_ATA_TRANSLATION_AUTO;
+ else {
+ fprintf(stderr, "qemu: '%s' invalid translation type\n", buf);
+ return NULL;
+ }
+ }
+
+ if ((buf = qemu_opt_get(opts, "media")) != NULL) {
+ if (!strcmp(buf, "disk")) {
+ media = MEDIA_DISK;
+ } else if (!strcmp(buf, "cdrom")) {
+ if (cyls || secs || heads) {
+ fprintf(stderr,
+ "qemu: '%s' invalid physical CHS format\n", buf);
+ return NULL;
+ }
+ media = MEDIA_CDROM;
+ } else {
+ fprintf(stderr, "qemu: '%s' invalid media\n", buf);
+ return NULL;
+ }
+ }
+
+ if ((buf = qemu_opt_get(opts, "cache")) != NULL) {
+ if (!strcmp(buf, "off") || !strcmp(buf, "none")) {
+ bdrv_flags |= BDRV_O_NOCACHE;
+ } else if (!strcmp(buf, "writeback")) {
+ bdrv_flags |= BDRV_O_CACHE_WB;
+ } else if (!strcmp(buf, "unsafe")) {
+ bdrv_flags |= BDRV_O_CACHE_WB;
+ bdrv_flags |= BDRV_O_NO_FLUSH;
+ } else if (!strcmp(buf, "writethrough")) {
+ /* this is the default */
+ } else {
+ fprintf(stderr, "qemu: invalid cache option\n");
+ return NULL;
+ }
+ }
+
+#ifdef CONFIG_LINUX_AIO
+ if ((buf = qemu_opt_get(opts, "aio")) != NULL) {
+ if (!strcmp(buf, "native")) {
+ bdrv_flags |= BDRV_O_NATIVE_AIO;
+ } else if (!strcmp(buf, "threads")) {
+ /* this is the default */
+ } else {
+ fprintf(stderr, "qemu: invalid aio option\n");
+ return NULL;
+ }
+ }
+#endif
+
+ if ((buf = qemu_opt_get(opts, "format")) != NULL) {
+ if (strcmp(buf, "?") == 0) {
+ fprintf(stderr, "qemu: Supported formats:");
+ bdrv_iterate_format(bdrv_format_print, NULL);
+ fprintf(stderr, "\n");
+ return NULL;
+ }
+ drv = bdrv_find_whitelisted_format(buf);
+ if (!drv) {
+ fprintf(stderr, "qemu: '%s' invalid format\n", buf);
+ return NULL;
+ }
+ }
+
+ on_write_error = BLOCK_ERR_STOP_ENOSPC;
+ if ((buf = qemu_opt_get(opts, "werror")) != NULL) {
+ if (type != IF_IDE && type != IF_SCSI && type != IF_VIRTIO && type != IF_NONE) {
+ fprintf(stderr, "werror is no supported by this format\n");
+ return NULL;
+ }
+
+ on_write_error = parse_block_error_action(buf, 0);
+ if (on_write_error < 0) {
+ return NULL;
+ }
+ }
+
+ on_read_error = BLOCK_ERR_REPORT;
+ if ((buf = qemu_opt_get(opts, "rerror")) != NULL) {
+ if (type != IF_IDE && type != IF_VIRTIO && type != IF_NONE) {
+ fprintf(stderr, "rerror is no supported by this format\n");
+ return NULL;
+ }
+
+ on_read_error = parse_block_error_action(buf, 1);
+ if (on_read_error < 0) {
+ return NULL;
+ }
+ }
+
+ if ((devaddr = qemu_opt_get(opts, "addr")) != NULL) {
+ if (type != IF_VIRTIO) {
+ fprintf(stderr, "addr is not supported\n");
+ return NULL;
+ }
+ }
+
+ /* compute bus and unit according index */
+
+ if (index != -1) {
+ if (bus_id != 0 || unit_id != -1) {
+ fprintf(stderr,
+ "qemu: index cannot be used with bus and unit\n");
+ return NULL;
+ }
+ if (max_devs == 0)
+ {
+ unit_id = index;
+ bus_id = 0;
+ } else {
+ unit_id = index % max_devs;
+ bus_id = index / max_devs;
+ }
+ }
+
+ /* if user doesn't specify a unit_id,
+ * try to find the first free
+ */
+
+ if (unit_id == -1) {
+ unit_id = 0;
+ while (drive_get(type, bus_id, unit_id) != NULL) {
+ unit_id++;
+ if (max_devs && unit_id >= max_devs) {
+ unit_id -= max_devs;
+ bus_id++;
+ }
+ }
+ }
+
+ /* check unit id */
+
+ if (max_devs && unit_id >= max_devs) {
+ fprintf(stderr, "qemu: unit %d too big (max is %d)\n",
+ unit_id, max_devs - 1);
+ return NULL;
+ }
+
+ /*
+ * ignore multiple definitions
+ */
+
+ if (drive_get(type, bus_id, unit_id) != NULL) {
+ *fatal_error = 0;
+ return NULL;
+ }
+
+ /* init */
+
+ dinfo = qemu_mallocz(sizeof(*dinfo));
+ if ((buf = qemu_opts_id(opts)) != NULL) {
+ dinfo->id = qemu_strdup(buf);
+ } else {
+ /* no id supplied -> create one */
+ dinfo->id = qemu_mallocz(32);
+ if (type == IF_IDE || type == IF_SCSI)
+ mediastr = (media == MEDIA_CDROM) ? "-cd" : "-hd";
+ if (max_devs)
+ snprintf(dinfo->id, 32, "%s%i%s%i",
+ devname, bus_id, mediastr, unit_id);
+ else
+ snprintf(dinfo->id, 32, "%s%s%i",
+ devname, mediastr, unit_id);
+ }
+ dinfo->bdrv = bdrv_new(dinfo->id);
+ dinfo->devaddr = devaddr;
+ dinfo->type = type;
+ dinfo->bus = bus_id;
+ dinfo->unit = unit_id;
+ dinfo->on_read_error = on_read_error;
+ dinfo->on_write_error = on_write_error;
+ dinfo->opts = opts;
+ if (serial)
+ strncpy(dinfo->serial, serial, sizeof(dinfo->serial) - 1);
+ QTAILQ_INSERT_TAIL(&drives, dinfo, next);
+
+ switch(type) {
+ case IF_IDE:
+ case IF_SCSI:
+ case IF_XEN:
+ case IF_NONE:
+ switch(media) {
+ case MEDIA_DISK:
+ if (cyls != 0) {
+ bdrv_set_geometry_hint(dinfo->bdrv, cyls, heads, secs);
+ bdrv_set_translation_hint(dinfo->bdrv, translation);
+ }
+ break;
+ case MEDIA_CDROM:
+ bdrv_set_type_hint(dinfo->bdrv, BDRV_TYPE_CDROM);
+ break;
+ }
+ break;
+ case IF_SD:
+ /* FIXME: This isn't really a floppy, but it's a reasonable
+ approximation. */
+ case IF_FLOPPY:
+ bdrv_set_type_hint(dinfo->bdrv, BDRV_TYPE_FLOPPY);
+ break;
+ case IF_PFLASH:
+ case IF_MTD:
+ break;
+ case IF_VIRTIO:
+ /* add virtio block device */
+ opts = qemu_opts_create(&qemu_device_opts, NULL, 0);
+ qemu_opt_set(opts, "driver", "virtio-blk-pci");
+ qemu_opt_set(opts, "drive", dinfo->id);
+ if (devaddr)
+ qemu_opt_set(opts, "addr", devaddr);
+ break;
+ case IF_COUNT:
+ abort();
+ }
+ if (!file) {
+ *fatal_error = 0;
+ return NULL;
+ }
+ if (snapshot) {
+ /* always use cache=unsafe with snapshot */
+ bdrv_flags &= ~BDRV_O_CACHE_MASK;
+ bdrv_flags |= (BDRV_O_SNAPSHOT|BDRV_O_CACHE_WB|BDRV_O_NO_FLUSH);
+ }
+
+ if (media == MEDIA_CDROM) {
+ /* CDROM is fine for any interface, don't check. */
+ ro = 1;
+ } else if (ro == 1) {
+ if (type != IF_SCSI && type != IF_VIRTIO && type != IF_FLOPPY && type != IF_NONE) {
+ fprintf(stderr, "qemu: readonly flag not supported for drive with this interface\n");
+ return NULL;
+ }
+ }
+
+ bdrv_flags |= ro ? 0 : BDRV_O_RDWR;
+
+ ret = bdrv_open(dinfo->bdrv, file, bdrv_flags, drv);
+ if (ret < 0) {
+ fprintf(stderr, "qemu: could not open disk image %s: %s\n",
+ file, strerror(-ret));
+ return NULL;
+ }
+
+ if (bdrv_key_required(dinfo->bdrv))
+ autostart = 0;
+ *fatal_error = 0;
+ return dinfo;
+}
+
+void do_commit(Monitor *mon, const QDict *qdict)
+{
+ int all_devices;
+ DriveInfo *dinfo;
+ const char *device = qdict_get_str(qdict, "device");
+
+ all_devices = !strcmp(device, "all");
+ QTAILQ_FOREACH(dinfo, &drives, next) {
+ if (!all_devices)
+ if (strcmp(bdrv_get_device_name(dinfo->bdrv), device))
+ continue;
+ bdrv_commit(dinfo->bdrv);
+ }
+}
+
+static int eject_device(Monitor *mon, BlockDriverState *bs, int force)
+{
+ if (bdrv_is_inserted(bs)) {
+ if (!force) {
+ if (!bdrv_is_removable(bs)) {
+ qerror_report(QERR_DEVICE_NOT_REMOVABLE,
+ bdrv_get_device_name(bs));
+ return -1;
+ }
+ if (bdrv_is_locked(bs)) {
+ qerror_report(QERR_DEVICE_LOCKED, bdrv_get_device_name(bs));
+ return -1;
+ }
+ }
+ bdrv_close(bs);
+ }
+ return 0;
+}
+
+int do_eject(Monitor *mon, const QDict *qdict, QObject **ret_data)
+{
+ BlockDriverState *bs;
+ int force = qdict_get_int(qdict, "force");
+ const char *filename = qdict_get_str(qdict, "device");
+
+ bs = bdrv_find(filename);
+ if (!bs) {
+ qerror_report(QERR_DEVICE_NOT_FOUND, filename);
+ return -1;
+ }
+ return eject_device(mon, bs, force);
+}
+
+int do_block_set_passwd(Monitor *mon, const QDict *qdict,
+ QObject **ret_data)
+{
+ BlockDriverState *bs;
+ int err;
+
+ bs = bdrv_find(qdict_get_str(qdict, "device"));
+ if (!bs) {
+ qerror_report(QERR_DEVICE_NOT_FOUND, qdict_get_str(qdict, "device"));
+ return -1;
+ }
+
+ err = bdrv_set_key(bs, qdict_get_str(qdict, "password"));
+ if (err == -EINVAL) {
+ qerror_report(QERR_DEVICE_NOT_ENCRYPTED, bdrv_get_device_name(bs));
+ return -1;
+ } else if (err < 0) {
+ qerror_report(QERR_INVALID_PASSWORD);
+ return -1;
+ }
+
+ return 0;
+}
+
+int do_change_block(Monitor *mon, const char *device,
+ const char *filename, const char *fmt)
+{
+ BlockDriverState *bs;
+ BlockDriver *drv = NULL;
+ int bdrv_flags;
+
+ bs = bdrv_find(device);
+ if (!bs) {
+ qerror_report(QERR_DEVICE_NOT_FOUND, device);
+ return -1;
+ }
+ if (fmt) {
+ drv = bdrv_find_whitelisted_format(fmt);
+ if (!drv) {
+ qerror_report(QERR_INVALID_BLOCK_FORMAT, fmt);
+ return -1;
+ }
+ }
+ if (eject_device(mon, bs, 0) < 0) {
+ return -1;
+ }
+ bdrv_flags = bdrv_get_type_hint(bs) == BDRV_TYPE_CDROM ? 0 : BDRV_O_RDWR;
+ if (bdrv_open(bs, filename, bdrv_flags, drv) < 0) {
+ qerror_report(QERR_OPEN_FILE_FAILED, filename);
+ return -1;
+ }
+ return monitor_read_bdrv_key_start(mon, bs, NULL, NULL);
+}
diff --git a/blockdev.h b/blockdev.h
new file mode 100644
index 000000000..dfc9de19a
--- /dev/null
+++ b/blockdev.h
@@ -0,0 +1,71 @@
+/*
+ * QEMU host block devices
+ *
+ * Copyright (c) 2003-2008 Fabrice Bellard
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or
+ * later. See the COPYING file in the top-level directory.
+ */
+
+#ifndef BLOCKDEV_H
+#define BLOCKDEV_H
+
+#include "block.h"
+#include "qemu-queue.h"
+
+typedef enum {
+ IF_NONE,
+ IF_IDE, IF_SCSI, IF_FLOPPY, IF_PFLASH, IF_MTD, IF_SD, IF_VIRTIO, IF_XEN,
+ IF_COUNT
+} BlockInterfaceType;
+
+typedef enum {
+ BLOCK_ERR_REPORT, BLOCK_ERR_IGNORE, BLOCK_ERR_STOP_ENOSPC,
+ BLOCK_ERR_STOP_ANY
+} BlockInterfaceErrorAction;
+
+#define BLOCK_SERIAL_STRLEN 20
+
+typedef struct DriveInfo {
+ BlockDriverState *bdrv;
+ char *id;
+ const char *devaddr;
+ BlockInterfaceType type;
+ int bus;
+ int unit;
+ QemuOpts *opts;
+ BlockInterfaceErrorAction on_read_error;
+ BlockInterfaceErrorAction on_write_error;
+ char serial[BLOCK_SERIAL_STRLEN + 1];
+ QTAILQ_ENTRY(DriveInfo) next;
+} DriveInfo;
+
+#define MAX_IDE_DEVS 2
+#define MAX_SCSI_DEVS 7
+
+extern QTAILQ_HEAD(drivelist, DriveInfo) drives;
+
+extern DriveInfo *drive_get(BlockInterfaceType type, int bus, int unit);
+extern DriveInfo *drive_get_by_id(const char *id);
+extern int drive_get_max_bus(BlockInterfaceType type);
+extern void drive_uninit(DriveInfo *dinfo);
+extern const char *drive_get_serial(BlockDriverState *bdrv);
+
+extern BlockInterfaceErrorAction drive_get_on_error(
+ BlockDriverState *bdrv, int is_read);
+
+extern QemuOpts *drive_add(const char *file, const char *fmt, ...);
+extern DriveInfo *drive_init(QemuOpts *arg, int default_to_scsi,
+ int *fatal_error);
+
+/* device-hotplug */
+
+DriveInfo *add_init_drive(const char *opts);
+
+void do_commit(Monitor *mon, const QDict *qdict);
+int do_eject(Monitor *mon, const QDict *qdict, QObject **ret_data);
+int do_block_set_passwd(Monitor *mon, const QDict *qdict, QObject **ret_data);
+int do_change_block(Monitor *mon, const char *device,
+ const char *filename, const char *fmt);
+
+#endif
diff --git a/hw/acpi_piix4.c b/hw/acpi_piix4.c
index 0fce958d0..a87286b91 100644
--- a/hw/acpi_piix4.c
+++ b/hw/acpi_piix4.c
@@ -21,6 +21,7 @@
#include "pm_smbus.h"
#include "pci.h"
#include "acpi.h"
+#include "sysemu.h"
//#define DEBUG
diff --git a/hw/apb_pci.c b/hw/apb_pci.c
index b53e3c3bf..31c8d705a 100644
--- a/hw/apb_pci.c
+++ b/hw/apb_pci.c
@@ -31,6 +31,7 @@
#include "pci_host.h"
#include "rwhandler.h"
#include "apb_pci.h"
+#include "sysemu.h"
/* debug APB */
//#define DEBUG_APB
diff --git a/hw/device-hotplug.c b/hw/device-hotplug.c
index 9cc837669..c1a9a561d 100644
--- a/hw/device-hotplug.c
+++ b/hw/device-hotplug.c
@@ -25,8 +25,6 @@
#include "hw.h"
#include "boards.h"
#include "net.h"
-#include "block_int.h"
-#include "sysemu.h"
DriveInfo *add_init_drive(const char *optstr)
{
@@ -38,7 +36,7 @@ DriveInfo *add_init_drive(const char *optstr)
if (!opts)
return NULL;
- dinfo = drive_init(opts, current_machine, &fatal_error);
+ dinfo = drive_init(opts, current_machine->use_scsi, &fatal_error);
if (!dinfo) {
qemu_opts_del(opts);
return NULL;
diff --git a/hw/fdc.c b/hw/fdc.c
index 630649638..b97895786 100644
--- a/hw/fdc.c
+++ b/hw/fdc.c
@@ -29,7 +29,6 @@
#include "hw.h"
#include "fdc.h"
-#include "block.h"
#include "qemu-timer.h"
#include "isa.h"
#include "sysbus.h"
diff --git a/hw/fdc.h b/hw/fdc.h
index c48b5e04d..b6b377259 100644
--- a/hw/fdc.h
+++ b/hw/fdc.h
@@ -2,7 +2,7 @@
#define HW_FDC_H
/* fdc.c */
-#include "sysemu.h"
+#include "blockdev.h"
#define MAX_FD 2
typedef struct FDCtrl FDCtrl;
diff --git a/hw/ide/cmd646.c b/hw/ide/cmd646.c
index cdcc9bf1a..559147ff4 100644
--- a/hw/ide/cmd646.c
+++ b/hw/ide/cmd646.c
@@ -260,8 +260,8 @@ static int pci_cmd646_ide_initfn(PCIDevice *dev)
irq = qemu_allocate_irqs(cmd646_set_irq, d, 2);
ide_bus_new(&d->bus[0], &d->dev.qdev);
ide_bus_new(&d->bus[1], &d->dev.qdev);
- ide_init2(&d->bus[0], NULL, NULL, irq[0]);
- ide_init2(&d->bus[1], NULL, NULL, irq[1]);
+ ide_init2(&d->bus[0], irq[0]);
+ ide_init2(&d->bus[1], irq[1]);
vmstate_register(0, &vmstate_ide_pci, d);
qemu_register_reset(cmd646_reset, d);
diff --git a/hw/ide/core.c b/hw/ide/core.c
index 066fecb0c..045d18db2 100644
--- a/hw/ide/core.c
+++ b/hw/ide/core.c
@@ -26,8 +26,6 @@
#include <hw/pc.h>
#include <hw/pci.h>
#include <hw/scsi.h>
-#include "block.h"
-#include "block_int.h"
#include "qemu-timer.h"
#include "sysemu.h"
#include "dma.h"
@@ -98,6 +96,7 @@ static void ide_identify(IDEState *s)
{
uint16_t *p;
unsigned int oldsize;
+ IDEDevice *dev;
if (s->identify_set) {
memcpy(s->io_buffer, s->identify_data, sizeof(s->identify_data));
@@ -165,8 +164,9 @@ static void ide_identify(IDEState *s)
put_le16(p + 101, s->nb_sectors >> 16);
put_le16(p + 102, s->nb_sectors >> 32);
put_le16(p + 103, s->nb_sectors >> 48);
- if (s->conf && s->conf->physical_block_size)
- put_le16(p + 106, 0x6000 | get_physical_block_exp(s->conf));
+ dev = s->unit ? s->bus->slave : s->bus->master;
+ if (dev && dev->conf.physical_block_size)
+ put_le16(p + 106, 0x6000 | get_physical_block_exp(&dev->conf));
memcpy(s->identify_data, p, sizeof(s->identify_data));
s->identify_set = 1;
@@ -2594,39 +2594,35 @@ void ide_bus_reset(IDEBus *bus)
ide_clear_hob(bus);
}
-void ide_init_drive(IDEState *s, DriveInfo *dinfo, BlockConf *conf,
- const char *version)
+void ide_init_drive(IDEState *s, DriveInfo *dinfo,
+ const char *version, const char *serial)
{
int cylinders, heads, secs;
uint64_t nb_sectors;
- if (dinfo && dinfo->bdrv) {
- s->bs = dinfo->bdrv;
- bdrv_get_geometry(s->bs, &nb_sectors);
- bdrv_guess_geometry(s->bs, &cylinders, &heads, &secs);
- s->cylinders = cylinders;
- s->heads = heads;
- s->sectors = secs;
- s->nb_sectors = nb_sectors;
- /* The SMART values should be preserved across power cycles
- but they aren't. */
- s->smart_enabled = 1;
- s->smart_autosave = 1;
- s->smart_errors = 0;
- s->smart_selftest_count = 0;
- if (bdrv_get_type_hint(s->bs) == BDRV_TYPE_CDROM) {
- s->is_cdrom = 1;
- bdrv_set_change_cb(s->bs, cdrom_change_cb, s);
- }
- strncpy(s->drive_serial_str, drive_get_serial(s->bs),
- sizeof(s->drive_serial_str));
- if (conf) {
- s->conf = conf;
- }
+ s->bs = dinfo->bdrv;
+ bdrv_get_geometry(s->bs, &nb_sectors);
+ bdrv_guess_geometry(s->bs, &cylinders, &heads, &secs);
+ s->cylinders = cylinders;
+ s->heads = heads;
+ s->sectors = secs;
+ s->nb_sectors = nb_sectors;
+ /* The SMART values should be preserved across power cycles
+ but they aren't. */
+ s->smart_enabled = 1;
+ s->smart_autosave = 1;
+ s->smart_errors = 0;
+ s->smart_selftest_count = 0;
+ if (bdrv_get_type_hint(s->bs) == BDRV_TYPE_CDROM) {
+ s->is_cdrom = 1;
+ bdrv_set_change_cb(s->bs, cdrom_change_cb, s);
}
- if (strlen(s->drive_serial_str) == 0)
+ if (serial && *serial) {
+ strncpy(s->drive_serial_str, serial, sizeof(s->drive_serial_str));
+ } else {
snprintf(s->drive_serial_str, sizeof(s->drive_serial_str),
"QM%05d", s->drive_serial);
+ }
if (version) {
pstrcpy(s->version, sizeof(s->version), version);
} else {
@@ -2635,27 +2631,47 @@ void ide_init_drive(IDEState *s, DriveInfo *dinfo, BlockConf *conf,
ide_reset(s);
}
-void ide_init2(IDEBus *bus, DriveInfo *hd0, DriveInfo *hd1,
- qemu_irq irq)
+static void ide_init1(IDEBus *bus, int unit)
{
- IDEState *s;
static int drive_serial = 1;
+ IDEState *s = &bus->ifs[unit];
+
+ s->bus = bus;
+ s->unit = unit;
+ s->drive_serial = drive_serial++;
+ s->io_buffer = qemu_blockalign(s->bs, IDE_DMA_BUF_SECTORS*512 + 4);
+ s->io_buffer_total_len = IDE_DMA_BUF_SECTORS*512 + 4;
+ s->smart_selftest_data = qemu_blockalign(s->bs, 512);
+ s->sector_write_timer = qemu_new_timer(vm_clock,
+ ide_sector_write_timer_cb, s);
+}
+
+void ide_init2(IDEBus *bus, qemu_irq irq)
+{
int i;
for(i = 0; i < 2; i++) {
- s = bus->ifs + i;
- s->bus = bus;
- s->unit = i;
- s->drive_serial = drive_serial++;
- s->io_buffer = qemu_blockalign(s->bs, IDE_DMA_BUF_SECTORS*512 + 4);
- s->io_buffer_total_len = IDE_DMA_BUF_SECTORS*512 + 4;
- s->smart_selftest_data = qemu_blockalign(s->bs, 512);
- s->sector_write_timer = qemu_new_timer(vm_clock,
- ide_sector_write_timer_cb, s);
- if (i == 0)
- ide_init_drive(s, hd0, NULL, NULL);
- if (i == 1)
- ide_init_drive(s, hd1, NULL, NULL);
+ ide_init1(bus, i);
+ ide_reset(&bus->ifs[i]);
+ }
+ bus->irq = irq;
+}
+
+/* TODO convert users to qdev and remove */
+void ide_init2_with_non_qdev_drives(IDEBus *bus, DriveInfo *hd0,
+ DriveInfo *hd1, qemu_irq irq)
+{
+ int i;
+ DriveInfo *dinfo;
+
+ for(i = 0; i < 2; i++) {
+ dinfo = i == 0 ? hd0 : hd1;
+ ide_init1(bus, i);
+ if (dinfo) {
+ ide_init_drive(&bus->ifs[i], dinfo, NULL, dinfo->serial);
+ } else {
+ ide_reset(&bus->ifs[i]);
+ }
}
bus->irq = irq;
}
diff --git a/hw/ide/internal.h b/hw/ide/internal.h
index 2efc7846b..eef1ee141 100644
--- a/hw/ide/internal.h
+++ b/hw/ide/internal.h
@@ -398,7 +398,6 @@ struct IDEState {
/* set for lba48 access */
uint8_t lba48;
BlockDriverState *bs;
- BlockConf *conf;
char version[9];
/* ATAPI specific */
uint8_t sense_key;
@@ -458,14 +457,13 @@ struct IDEDevice {
uint32_t unit;
BlockConf conf;
char *version;
+ char *serial;
};
typedef int (*ide_qdev_initfn)(IDEDevice *dev);
struct IDEDeviceInfo {
DeviceInfo qdev;
ide_qdev_initfn init;
- uint32_t unit;
- DriveInfo *drive;
};
#define BM_STATUS_DMAING 0x01
@@ -557,10 +555,11 @@ uint32_t ide_data_readw(void *opaque, uint32_t addr);
void ide_data_writel(void *opaque, uint32_t addr, uint32_t val);
uint32_t ide_data_readl(void *opaque, uint32_t addr);
-void ide_init_drive(IDEState *s, DriveInfo *dinfo, BlockConf *conf,
- const char *version);
-void ide_init2(IDEBus *bus, DriveInfo *hd0, DriveInfo *hd1,
- qemu_irq irq);
+void ide_init_drive(IDEState *s, DriveInfo *dinfo,
+ const char *version, const char *serial);
+void ide_init2(IDEBus *bus, qemu_irq irq);
+void ide_init2_with_non_qdev_drives(IDEBus *bus, DriveInfo *hd0,
+ DriveInfo *hd1, qemu_irq irq);
void ide_init_ioport(IDEBus *bus, int iobase, int iobase2);
/* hw/ide/qdev.c */
diff --git a/hw/ide/isa.c b/hw/ide/isa.c
index dff7c796f..b6c634728 100644
--- a/hw/ide/isa.c
+++ b/hw/ide/isa.c
@@ -70,7 +70,7 @@ static int isa_ide_initfn(ISADevice *dev)
ide_bus_new(&s->bus, &s->dev.qdev);
ide_init_ioport(&s->bus, s->iobase, s->iobase2);
isa_init_irq(dev, &s->irq, s->isairq);
- ide_init2(&s->bus, NULL, NULL, s->irq);
+ ide_init2(&s->bus, s->irq);
vmstate_register(0, &vmstate_ide_isa, s);
return 0;
};
diff --git a/hw/ide/macio.c b/hw/ide/macio.c
index 639f3f6a6..f76c0fa31 100644
--- a/hw/ide/macio.c
+++ b/hw/ide/macio.c
@@ -314,7 +314,7 @@ int pmac_ide_init (DriveInfo **hd_table, qemu_irq irq,
int pmac_ide_memory;
d = qemu_mallocz(sizeof(MACIOIDEState));
- ide_init2(&d->bus, hd_table[0], hd_table[1], irq);
+ ide_init2_with_non_qdev_drives(&d->bus, hd_table[0], hd_table[1], irq);
if (dbdma)
DBDMA_register_channel(dbdma, channel, dma_irq, pmac_ide_transfer, pmac_ide_flush, d);
diff --git a/hw/ide/microdrive.c b/hw/ide/microdrive.c
index bfdb8c8b0..a7beac552 100644
--- a/hw/ide/microdrive.c
+++ b/hw/ide/microdrive.c
@@ -539,7 +539,8 @@ PCMCIACardState *dscm1xxxx_init(DriveInfo *bdrv)
md->card.cis = dscm1xxxx_cis;
md->card.cis_len = sizeof(dscm1xxxx_cis);
- ide_init2(&md->bus, bdrv, NULL, qemu_allocate_irqs(md_set_irq, md, 1)[0]);
+ ide_init2_with_non_qdev_drives(&md->bus, bdrv, NULL,
+ qemu_allocate_irqs(md_set_irq, md, 1)[0]);
md->bus.ifs[0].is_cf = 1;
md->bus.ifs[0].mdata_size = METADATA_SIZE;
md->bus.ifs[0].mdata_storage = (uint8_t *) qemu_mallocz(METADATA_SIZE);
diff --git a/hw/ide/mmio.c b/hw/ide/mmio.c
index cca883f61..e75cccf56 100644
--- a/hw/ide/mmio.c
+++ b/hw/ide/mmio.c
@@ -125,7 +125,7 @@ void mmio_ide_init (target_phys_addr_t membase, target_phys_addr_t membase2,
MMIOState *s = qemu_mallocz(sizeof(MMIOState));
int mem1, mem2;
- ide_init2(&s->bus, hd0, hd1, irq);
+ ide_init2_with_non_qdev_drives(&s->bus, hd0, hd1, irq);
s->shift = shift;
diff --git a/hw/ide/piix.c b/hw/ide/piix.c
index 4fa38519e..dad6e86ff 100644
--- a/hw/ide/piix.c
+++ b/hw/ide/piix.c
@@ -135,8 +135,8 @@ static int pci_piix_ide_initfn(PCIIDEState *d)
ide_init_ioport(&d->bus[0], 0x1f0, 0x3f6);
ide_init_ioport(&d->bus[1], 0x170, 0x376);
- ide_init2(&d->bus[0], NULL, NULL, isa_reserve_irq(14));
- ide_init2(&d->bus[1], NULL, NULL, isa_reserve_irq(15));
+ ide_init2(&d->bus[0], isa_reserve_irq(14));
+ ide_init2(&d->bus[1], isa_reserve_irq(15));
return 0;
}
diff --git a/hw/ide/qdev.c b/hw/ide/qdev.c
index b18693d94..0f9f22e30 100644
--- a/hw/ide/qdev.c
+++ b/hw/ide/qdev.c
@@ -17,7 +17,6 @@
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
*/
#include <hw/hw.h>
-#include "sysemu.h"
#include "dma.h"
#include <hw/ide/internal.h>
@@ -99,8 +98,23 @@ typedef struct IDEDrive {
static int ide_drive_initfn(IDEDevice *dev)
{
IDEBus *bus = DO_UPCAST(IDEBus, qbus, dev->qdev.parent_bus);
- ide_init_drive(bus->ifs + dev->unit, dev->conf.dinfo, &dev->conf,
- dev->version);
+ IDEState *s = bus->ifs + dev->unit;
+ const char *serial;
+
+ serial = dev->serial;
+ if (!serial) {
+ /* try to fall back to value set with legacy -drive serial=... */
+ serial = dev->conf.dinfo->serial;
+ }
+
+ ide_init_drive(s, dev->conf.dinfo, dev->version, serial);
+
+ if (!dev->version) {
+ dev->version = qemu_strdup(s->version);
+ }
+ if (!dev->serial) {
+ dev->serial = qemu_strdup(s->drive_serial_str);
+ }
return 0;
}
@@ -112,6 +126,7 @@ static IDEDeviceInfo ide_drive_info = {
DEFINE_PROP_UINT32("unit", IDEDrive, dev.unit, -1),
DEFINE_BLOCK_PROPERTIES(IDEDrive, dev.conf),
DEFINE_PROP_STRING("ver", IDEDrive, dev.version),
+ DEFINE_PROP_STRING("serial", IDEDrive, dev.serial),
DEFINE_PROP_END_OF_LIST(),
}
};
diff --git a/hw/lan9118.c b/hw/lan9118.c
index 16d33304d..b996dc4f0 100644
--- a/hw/lan9118.c
+++ b/hw/lan9118.c
@@ -10,6 +10,7 @@
#include "sysbus.h"
#include "net.h"
#include "devices.h"
+#include "sysemu.h"
/* For crc32 */
#include <zlib.h>
diff --git a/hw/nand.c b/hw/nand.c
index 40d5a6a73..cd7444f9a 100644
--- a/hw/nand.c
+++ b/hw/nand.c
@@ -13,9 +13,8 @@
# include "hw.h"
# include "flash.h"
-# include "block.h"
+# include "blockdev.h"
/* FIXME: Pass block device as an argument. */
-# include "sysemu.h"
# define NAND_CMD_READ0 0x00
# define NAND_CMD_READ1 0x01
diff --git a/hw/omap2.c b/hw/omap2.c
index bd1b35e66..666c15adb 100644
--- a/hw/omap2.c
+++ b/hw/omap2.c
@@ -17,6 +17,8 @@
* You should have received a copy of the GNU General Public License along
* with this program; if not, see <http://www.gnu.org/licenses/>.
*/
+
+#include "blockdev.h"
#include "hw.h"
#include "arm-misc.h"
#include "omap.h"
diff --git a/hw/onenand.c b/hw/onenand.c
index c1e7e4d60..4118db922 100644
--- a/hw/onenand.c
+++ b/hw/onenand.c
@@ -21,8 +21,7 @@
#include "qemu-common.h"
#include "flash.h"
#include "irq.h"
-#include "sysemu.h"
-#include "block.h"
+#include "blockdev.h"
/* 11 for 2kB-page OneNAND ("2nd generation") and 10 for 1kB-page chips */
#define PAGE_SHIFT 11
diff --git a/hw/parallel.c b/hw/parallel.c
index be8e2d547..6b11672e1 100644
--- a/hw/parallel.c
+++ b/hw/parallel.c
@@ -26,6 +26,7 @@
#include "qemu-char.h"
#include "isa.h"
#include "pc.h"
+#include "sysemu.h"
//#define DEBUG_PARALLEL
diff --git a/hw/pc.c b/hw/pc.c
index 14911297e..0f7d33060 100644
--- a/hw/pc.c
+++ b/hw/pc.c
@@ -36,6 +36,7 @@
#include "multiboot.h"
#include "mc146818rtc.h"
#include "sysbus.h"
+#include "sysemu.h"
/* output Bochs bios info messages */
//#define DEBUG_BIOS
diff --git a/hw/pc_piix.c b/hw/pc_piix.c
index 70f563a67..dc4684692 100644
--- a/hw/pc_piix.c
+++ b/hw/pc_piix.c
@@ -32,6 +32,7 @@
#include "boards.h"
#include "ide.h"
#include "kvm.h"
+#include "sysemu.h"
#define MAX_IDE_BUS 2
diff --git a/hw/pci-hotplug.c b/hw/pci-hotplug.c
index a8f3df170..c39e64008 100644
--- a/hw/pci-hotplug.c
+++ b/hw/pci-hotplug.c
@@ -26,10 +26,8 @@
#include "boards.h"
#include "pci.h"
#include "net.h"
-#include "sysemu.h"
#include "pc.h"
#include "monitor.h"
-#include "block_int.h"
#include "scsi.h"
#include "virtio-blk.h"
#include "qemu-config.h"
diff --git a/hw/pcmcia.h b/hw/pcmcia.h
index cf2db9d32..360292395 100644
--- a/hw/pcmcia.h
+++ b/hw/pcmcia.h
@@ -1,7 +1,7 @@
/* PCMCIA/Cardbus */
#include "qemu-common.h"
-#include "sysemu.h"
+#include "blockdev.h"
typedef struct {
qemu_irq irq;
diff --git a/hw/pl181.c b/hw/pl181.c
index 192405333..85cadc4fe 100644
--- a/hw/pl181.c
+++ b/hw/pl181.c
@@ -9,7 +9,6 @@
#include "sysbus.h"
#include "sd.h"
-#include "sysemu.h"
//#define DEBUG_PL181 1
diff --git a/hw/qdev-properties.c b/hw/qdev-properties.c
index 9ffdba792..5a8739deb 100644
--- a/hw/qdev-properties.c
+++ b/hw/qdev-properties.c
@@ -1,4 +1,3 @@
-#include "sysemu.h"
#include "net.h"
#include "qdev.h"
#include "qerror.h"
@@ -260,6 +259,11 @@ static int parse_string(DeviceState *dev, Property *prop, const char *str)
return 0;
}
+static void free_string(DeviceState *dev, Property *prop)
+{
+ qemu_free(*(char **)qdev_get_prop_ptr(dev, prop));
+}
+
static int print_string(DeviceState *dev, Property *prop, char *dest, size_t len)
{
char **ptr = qdev_get_prop_ptr(dev, prop);
@@ -274,6 +278,7 @@ PropertyInfo qdev_prop_string = {
.size = sizeof(char*),
.parse = parse_string,
.print = print_string,
+ .free = free_string,
};
/* --- drive --- */
@@ -617,6 +622,11 @@ void qdev_prop_set_uint64(DeviceState *dev, const char *name, uint64_t value)
qdev_prop_set(dev, name, &value, PROP_TYPE_UINT64);
}
+void qdev_prop_set_string(DeviceState *dev, const char *name, char *value)
+{
+ qdev_prop_set(dev, name, &value, PROP_TYPE_STRING);
+}
+
void qdev_prop_set_drive(DeviceState *dev, const char *name, DriveInfo *value)
{
qdev_prop_set(dev, name, &value, PROP_TYPE_DRIVE);
diff --git a/hw/qdev.c b/hw/qdev.c
index 36f29ea79..61f999c02 100644
--- a/hw/qdev.c
+++ b/hw/qdev.c
@@ -334,6 +334,7 @@ void qdev_init_nofail(DeviceState *dev)
void qdev_free(DeviceState *dev)
{
BusState *bus;
+ Property *prop;
if (dev->state == DEV_STATE_INITIALIZED) {
while (dev->num_child_bus) {
@@ -349,6 +350,11 @@ void qdev_free(DeviceState *dev)
}
qemu_unregister_reset(qdev_reset, dev);
QLIST_REMOVE(dev, sibling);
+ for (prop = dev->info->props; prop && prop->name; prop++) {
+ if (prop->info->free) {
+ prop->info->free(dev, prop);
+ }
+ }
qemu_free(dev);
}
diff --git a/hw/qdev.h b/hw/qdev.h
index a44060e54..be5ad671c 100644
--- a/hw/qdev.h
+++ b/hw/qdev.h
@@ -2,7 +2,7 @@
#define QDEV_H
#include "hw.h"
-#include "sysemu.h"
+#include "blockdev.h"
#include "qemu-queue.h"
#include "qemu-char.h"
#include "qemu-option.h"
@@ -98,6 +98,7 @@ struct PropertyInfo {
enum PropertyType type;
int (*parse)(DeviceState *dev, Property *prop, const char *str);
int (*print)(DeviceState *dev, Property *prop, char *dest, size_t len);
+ void (*free)(DeviceState *dev, Property *prop);
};
typedef struct GlobalProperty {
@@ -124,6 +125,8 @@ void qdev_machine_creation_done(void);
qemu_irq qdev_get_gpio_in(DeviceState *dev, int n);
void qdev_connect_gpio_out(DeviceState *dev, int n, qemu_irq pin);
+BlockDriverState *qdev_init_bdrv(DeviceState *dev, BlockInterfaceType type);
+
BusState *qdev_get_child_bus(DeviceState *dev, const char *name);
/*** Device API. ***/
@@ -268,6 +271,7 @@ void qdev_prop_set_uint16(DeviceState *dev, const char *name, uint16_t value);
void qdev_prop_set_uint32(DeviceState *dev, const char *name, uint32_t value);
void qdev_prop_set_int32(DeviceState *dev, const char *name, int32_t value);
void qdev_prop_set_uint64(DeviceState *dev, const char *name, uint64_t value);
+void qdev_prop_set_string(DeviceState *dev, const char *name, char *value);
void qdev_prop_set_chr(DeviceState *dev, const char *name, CharDriverState *value);
void qdev_prop_set_netdev(DeviceState *dev, const char *name, VLANClientState *value);
void qdev_prop_set_vlan(DeviceState *dev, const char *name, VLANState *value);
diff --git a/hw/scsi-bus.c b/hw/scsi-bus.c
index 383240bc0..055a94d25 100644
--- a/hw/scsi-bus.c
+++ b/hw/scsi-bus.c
@@ -2,7 +2,6 @@
#include "qemu-error.h"
#include "scsi.h"
#include "scsi-defs.h"
-#include "block.h"
#include "qdev.h"
static struct BusInfo scsi_bus_info = {
diff --git a/hw/scsi-disk.c b/hw/scsi-disk.c
index 4d209197c..a9bf7d261 100644
--- a/hw/scsi-disk.c
+++ b/hw/scsi-disk.c
@@ -33,9 +33,9 @@ do { fprintf(stderr, "scsi-disk: " fmt , ## __VA_ARGS__); } while (0)
#include "qemu-common.h"
#include "qemu-error.h"
-#include "block.h"
#include "scsi.h"
#include "scsi-defs.h"
+#include "sysemu.h"
#define SCSI_DMA_BUF_SIZE 131072
#define SCSI_MAX_INQUIRY_LEN 256
@@ -66,6 +66,7 @@ struct SCSIDiskState
uint64_t max_lba;
QEMUBH *bh;
char *version;
+ char *serial;
};
static SCSIDiskReq *scsi_new_request(SCSIDevice *d, uint32_t tag, uint32_t lun)
@@ -359,9 +360,7 @@ static int scsi_disk_emulate_inquiry(SCSIRequest *req, uint8_t *outbuf)
case 0x80: /* Device serial number, optional */
{
- const char *serial = req->dev->conf.dinfo->serial ?
- req->dev->conf.dinfo->serial : "0";
- int l = strlen(serial);
+ int l = strlen(s->serial);
if (l > req->cmd.xfer)
l = req->cmd.xfer;
@@ -371,7 +370,7 @@ static int scsi_disk_emulate_inquiry(SCSIRequest *req, uint8_t *outbuf)
DPRINTF("Inquiry EVPD[Serial number] "
"buffer size %zd\n", req->cmd.xfer);
outbuf[buflen++] = l;
- memcpy(outbuf+buflen, serial, l);
+ memcpy(outbuf+buflen, s->serial, l);
buflen += l;
break;
}
@@ -463,8 +462,7 @@ static int scsi_disk_emulate_inquiry(SCSIRequest *req, uint8_t *outbuf)
}
memcpy(&outbuf[8], "QEMU ", 8);
memset(&outbuf[32], 0, 4);
- memcpy(&outbuf[32], s->version ? s->version : QEMU_VERSION,
- MIN(4, strlen(s->version ? s->version : QEMU_VERSION)));
+ memcpy(&outbuf[32], s->version, MIN(4, strlen(s->version)));
/*
* We claim conformance to SPC-3, which is required for guests
* to ask for modern features like READ CAPACITY(16) or the
@@ -1058,6 +1056,19 @@ static int scsi_disk_initfn(SCSIDevice *dev)
}
s->bs = s->qdev.conf.dinfo->bdrv;
+ if (!s->serial) {
+ if (*dev->conf.dinfo->serial) {
+ /* try to fall back to value set with legacy -drive serial=... */
+ s->serial = qemu_strdup(dev->conf.dinfo->serial);
+ } else {
+ s->serial = qemu_strdup("0");
+ }
+ }
+
+ if (!s->version) {
+ s->version = qemu_strdup(QEMU_VERSION);
+ }
+
if (bdrv_is_sg(s->bs)) {
error_report("scsi-disk: unwanted /dev/sg*");
return -1;
@@ -1090,6 +1101,7 @@ static SCSIDeviceInfo scsi_disk_info = {
.qdev.props = (Property[]) {
DEFINE_BLOCK_PROPERTIES(SCSIDiskState, qdev.conf),
DEFINE_PROP_STRING("ver", SCSIDiskState, version),
+ DEFINE_PROP_STRING("serial", SCSIDiskState, serial),
DEFINE_PROP_END_OF_LIST(),
},
};
diff --git a/hw/scsi-generic.c b/hw/scsi-generic.c
index c9aa853cc..e31060e94 100644
--- a/hw/scsi-generic.c
+++ b/hw/scsi-generic.c
@@ -13,7 +13,6 @@
#include "qemu-common.h"
#include "qemu-error.h"
-#include "block.h"
#include "scsi.h"
#ifdef __linux__
diff --git a/hw/serial.c b/hw/serial.c
index 9102edb77..c7e4e77cb 100644
--- a/hw/serial.c
+++ b/hw/serial.c
@@ -27,6 +27,7 @@
#include "isa.h"
#include "pc.h"
#include "qemu-timer.h"
+#include "sysemu.h"
//#define DEBUG_SERIAL
diff --git a/hw/ssi-sd.c b/hw/ssi-sd.c
index 5e74e5d7c..96b33edcb 100644
--- a/hw/ssi-sd.c
+++ b/hw/ssi-sd.c
@@ -9,7 +9,6 @@
#include "ssi.h"
#include "sd.h"
-#include "sysemu.h"
//#define DEBUG_SSI_SD 1
diff --git a/hw/usb-hid.c b/hw/usb-hid.c
index 8e6c6e032..228d0a052 100644
--- a/hw/usb-hid.c
+++ b/hw/usb-hid.c
@@ -25,6 +25,7 @@
#include "hw.h"
#include "console.h"
#include "usb.h"
+#include "sysemu.h"
/* HID interface requests */
#define GET_REPORT 0xa101
diff --git a/hw/usb-msd.c b/hw/usb-msd.c
index c1c253747..003bd8a4c 100644
--- a/hw/usb-msd.c
+++ b/hw/usb-msd.c
@@ -11,10 +11,10 @@
#include "qemu-option.h"
#include "qemu-config.h"
#include "usb.h"
-#include "block.h"
#include "scsi.h"
#include "console.h"
#include "monitor.h"
+#include "sysemu.h"
//#define DEBUG_MSD
@@ -584,7 +584,7 @@ static USBDevice *usb_msd_init(const char *filename)
qemu_opt_set(opts, "if", "none");
/* create host drive */
- dinfo = drive_init(opts, NULL, &fatal_error);
+ dinfo = drive_init(opts, 0, &fatal_error);
if (!dinfo) {
qemu_opts_del(opts);
return NULL;
diff --git a/hw/virtio-blk.c b/hw/virtio-blk.c
index 5d7f1a220..cdcb492c1 100644
--- a/hw/virtio-blk.c
+++ b/hw/virtio-blk.c
@@ -12,9 +12,7 @@
*/
#include <qemu-common.h>
-#include <sysemu.h>
#include "virtio-blk.h"
-#include "block_int.h"
#ifdef __linux__
# include <scsi/sg.h>
#endif
@@ -277,7 +275,7 @@ static void virtio_blk_handle_write(BlockRequest *blkreq, int *num_writes,
}
blkreq[*num_writes].sector = req->out->sector;
- blkreq[*num_writes].nb_sectors = req->qiov.size / 512;
+ blkreq[*num_writes].nb_sectors = req->qiov.size / BDRV_SECTOR_SIZE;
blkreq[*num_writes].qiov = &req->qiov;
blkreq[*num_writes].cb = virtio_blk_rw_complete;
blkreq[*num_writes].opaque = req;
@@ -296,7 +294,8 @@ static void virtio_blk_handle_read(VirtIOBlockReq *req)
}
acb = bdrv_aio_readv(req->dev->bs, req->out->sector, &req->qiov,
- req->qiov.size / 512, virtio_blk_rw_complete, req);
+ req->qiov.size / BDRV_SECTOR_SIZE,
+ virtio_blk_rw_complete, req);
if (!acb) {
virtio_blk_rw_complete(req, -EIO);
}
@@ -505,7 +504,7 @@ VirtIODevice *virtio_blk_init(DeviceState *dev, BlockConf *conf)
s->bs = conf->dinfo->bdrv;
s->conf = conf;
s->rq = NULL;
- s->sector_mask = (s->conf->logical_block_size / 512) - 1;
+ s->sector_mask = (s->conf->logical_block_size / BDRV_SECTOR_SIZE) - 1;
bdrv_guess_geometry(s->bs, &cylinders, &heads, &secs);
s->vq = virtio_add_queue(&s->vdev, 128, virtio_blk_handle_output);
diff --git a/hw/virtio-pci.c b/hw/virtio-pci.c
index 7ddf61228..e101fa0a7 100644
--- a/hw/virtio-pci.c
+++ b/hw/virtio-pci.c
@@ -22,7 +22,6 @@
#include "qemu-error.h"
#include "msix.h"
#include "net.h"
-#include "block_int.h"
#include "loader.h"
#include "kvm.h"
diff --git a/monitor.c b/monitor.c
index 14f77bd47..05a7ed1c4 100644
--- a/monitor.c
+++ b/monitor.c
@@ -38,7 +38,7 @@
#include "monitor.h"
#include "readline.h"
#include "console.h"
-#include "block.h"
+#include "blockdev.h"
#include "audio/audio.h"
#include "disas.h"
#include "balloon.h"
@@ -530,21 +530,6 @@ static void do_help_cmd(Monitor *mon, const QDict *qdict)
help_cmd(mon, qdict_get_try_str(qdict, "name"));
}
-static void do_commit(Monitor *mon, const QDict *qdict)
-{
- int all_devices;
- DriveInfo *dinfo;
- const char *device = qdict_get_str(qdict, "device");
-
- all_devices = !strcmp(device, "all");
- QTAILQ_FOREACH(dinfo, &drives, next) {
- if (!all_devices)
- if (strcmp(bdrv_get_device_name(dinfo->bdrv), device))
- continue;
- bdrv_commit(dinfo->bdrv);
- }
-}
-
static void user_monitor_complete(void *opaque, QObject *ret_data)
{
MonitorCompletionData *data = (MonitorCompletionData *)opaque;
@@ -935,93 +920,6 @@ static int do_quit(Monitor *mon, const QDict *qdict, QObject **ret_data)
return 0;
}
-static int eject_device(Monitor *mon, BlockDriverState *bs, int force)
-{
- if (bdrv_is_inserted(bs)) {
- if (!force) {
- if (!bdrv_is_removable(bs)) {
- qerror_report(QERR_DEVICE_NOT_REMOVABLE,
- bdrv_get_device_name(bs));
- return -1;
- }
- if (bdrv_is_locked(bs)) {
- qerror_report(QERR_DEVICE_LOCKED, bdrv_get_device_name(bs));
- return -1;
- }
- }
- bdrv_close(bs);
- }
- return 0;
-}
-
-static int do_eject(Monitor *mon, const QDict *qdict, QObject **ret_data)
-{
- BlockDriverState *bs;
- int force = qdict_get_int(qdict, "force");
- const char *filename = qdict_get_str(qdict, "device");
-
- bs = bdrv_find(filename);
- if (!bs) {
- qerror_report(QERR_DEVICE_NOT_FOUND, filename);
- return -1;
- }
- return eject_device(mon, bs, force);
-}
-
-static int do_block_set_passwd(Monitor *mon, const QDict *qdict,
- QObject **ret_data)
-{
- BlockDriverState *bs;
- int err;
-
- bs = bdrv_find(qdict_get_str(qdict, "device"));
- if (!bs) {
- qerror_report(QERR_DEVICE_NOT_FOUND, qdict_get_str(qdict, "device"));
- return -1;
- }
-
- err = bdrv_set_key(bs, qdict_get_str(qdict, "password"));
- if (err == -EINVAL) {
- qerror_report(QERR_DEVICE_NOT_ENCRYPTED, bdrv_get_device_name(bs));
- return -1;
- } else if (err < 0) {
- qerror_report(QERR_INVALID_PASSWORD);
- return -1;
- }
-
- return 0;
-}
-
-static int do_change_block(Monitor *mon, const char *device,
- const char *filename, const char *fmt)
-{
- BlockDriverState *bs;
- BlockDriver *drv = NULL;
- int bdrv_flags;
-
- bs = bdrv_find(device);
- if (!bs) {
- qerror_report(QERR_DEVICE_NOT_FOUND, device);
- return -1;
- }
- if (fmt) {
- drv = bdrv_find_whitelisted_format(fmt);
- if (!drv) {
- qerror_report(QERR_INVALID_BLOCK_FORMAT, fmt);
- return -1;
- }
- }
- if (eject_device(mon, bs, 0) < 0) {
- return -1;
- }
- bdrv_flags = bdrv_get_type_hint(bs) == BDRV_TYPE_CDROM ? 0 : BDRV_O_RDWR;
- if (bdrv_open(bs, filename, bdrv_flags, drv) < 0) {
- qerror_report(QERR_OPEN_FILE_FAILED, filename);
- return -1;
- }
- return monitor_read_bdrv_key_start(mon, bs, NULL, NULL);
-}
-
static int change_vnc_password(const char *password)
{
if (vnc_display_password(NULL, password) < 0) {
diff --git a/qemu-char.c b/qemu-char.c
index faaf6248b..87628ea33 100644
--- a/qemu-char.c
+++ b/qemu-char.c
@@ -28,7 +28,6 @@
#include "sysemu.h"
#include "qemu-timer.h"
#include "qemu-char.h"
-#include "block.h"
#include "hw/usb.h"
#include "hw/baum.h"
#include "hw/msmouse.h"
diff --git a/qemu-io.c b/qemu-io.c
index 72a45247d..7c6120b6a 100644
--- a/qemu-io.c
+++ b/qemu-io.c
@@ -1317,7 +1317,7 @@ truncate_f(int argc, char **argv)
ret = bdrv_truncate(bs, offset);
if (ret < 0) {
- printf("truncate: %s", strerror(ret));
+ printf("truncate: %s\n", strerror(-ret));
return 0;
}
@@ -1342,7 +1342,7 @@ length_f(int argc, char **argv)
size = bdrv_getlength(bs);
if (size < 0) {
- printf("getlength: %s", strerror(size));
+ printf("getlength: %s\n", strerror(-size));
return 0;
}
diff --git a/savevm.c b/savevm.c
index af92ba298..1173a22e6 100644
--- a/savevm.c
+++ b/savevm.c
@@ -77,7 +77,7 @@
#include "sysemu.h"
#include "qemu-timer.h"
#include "qemu-char.h"
-#include "block.h"
+#include "blockdev.h"
#include "audio/audio.h"
#include "migration.h"
#include "qemu_socket.h"
diff --git a/sysemu.h b/sysemu.h
index 346cccd76..fbe103bc3 100644
--- a/sysemu.h
+++ b/sysemu.h
@@ -142,58 +142,6 @@ extern int nb_option_roms;
extern const char *prom_envs[MAX_PROM_ENVS];
extern unsigned int nb_prom_envs;
-typedef enum {
- IF_NONE,
- IF_IDE, IF_SCSI, IF_FLOPPY, IF_PFLASH, IF_MTD, IF_SD, IF_VIRTIO, IF_XEN,
- IF_COUNT
-} BlockInterfaceType;
-
-typedef enum {
- BLOCK_ERR_REPORT, BLOCK_ERR_IGNORE, BLOCK_ERR_STOP_ENOSPC,
- BLOCK_ERR_STOP_ANY
-} BlockInterfaceErrorAction;
-
-#define BLOCK_SERIAL_STRLEN 20
-
-typedef struct DriveInfo {
- BlockDriverState *bdrv;
- char *id;
- const char *devaddr;
- BlockInterfaceType type;
- int bus;
- int unit;
- QemuOpts *opts;
- BlockInterfaceErrorAction on_read_error;
- BlockInterfaceErrorAction on_write_error;
- char serial[BLOCK_SERIAL_STRLEN + 1];
- QTAILQ_ENTRY(DriveInfo) next;
-} DriveInfo;
-
-#define MAX_IDE_DEVS 2
-#define MAX_SCSI_DEVS 7
-#define MAX_DRIVES 32
-
-extern QTAILQ_HEAD(drivelist, DriveInfo) drives;
-extern QTAILQ_HEAD(driveoptlist, DriveOpt) driveopts;
-
-extern DriveInfo *drive_get(BlockInterfaceType type, int bus, int unit);
-extern DriveInfo *drive_get_by_id(const char *id);
-extern int drive_get_max_bus(BlockInterfaceType type);
-extern void drive_uninit(DriveInfo *dinfo);
-extern const char *drive_get_serial(BlockDriverState *bdrv);
-
-extern BlockInterfaceErrorAction drive_get_on_error(
- BlockDriverState *bdrv, int is_read);
-
-BlockDriverState *qdev_init_bdrv(DeviceState *dev, BlockInterfaceType type);
-
-extern QemuOpts *drive_add(const char *file, const char *fmt, ...);
-extern DriveInfo *drive_init(QemuOpts *arg, void *machine, int *fatal_error);
-
-/* device-hotplug */
-
-DriveInfo *add_init_drive(const char *opts);
-
/* pci-hotplug */
void pci_device_hot_add(Monitor *mon, const QDict *qdict);
void drive_hot_add(Monitor *mon, const QDict *qdict);
diff --git a/vl.c b/vl.c
index 9cf53347f..df18198a1 100644
--- a/vl.c
+++ b/vl.c
@@ -137,7 +137,7 @@ int main(int argc, char **argv)
#include "qemu-char.h"
#include "cache-utils.h"
#include "block.h"
-#include "block_int.h"
+#include "blockdev.h"
#include "block-migration.h"
#include "dma.h"
#include "audio/audio.h"
@@ -170,10 +170,6 @@ int main(int argc, char **argv)
static const char *data_dir;
const char *bios_name = NULL;
-/* Note: drives_table[MAX_DRIVES] is a dummy block driver if none available
- to store the VM snapshots */
-struct drivelist drives = QTAILQ_HEAD_INITIALIZER(drives);
-struct driveoptlist driveopts = QTAILQ_HEAD_INITIALIZER(driveopts);
enum vga_retrace_method vga_retrace_method = VGA_RETRACE_DUMB;
DisplayType display_type = DT_DEFAULT;
const char* keyboard_layout = NULL;
@@ -633,492 +629,12 @@ static int bt_parse(const char *opt)
#define MTD_ALIAS "if=mtd"
#define SD_ALIAS "index=0,if=sd"
-QemuOpts *drive_add(const char *file, const char *fmt, ...)
-{
- va_list ap;
- char optstr[1024];
- QemuOpts *opts;
-
- va_start(ap, fmt);
- vsnprintf(optstr, sizeof(optstr), fmt, ap);
- va_end(ap);
-
- opts = qemu_opts_parse(&qemu_drive_opts, optstr, 0);
- if (!opts) {
- return NULL;
- }
- if (file)
- qemu_opt_set(opts, "file", file);
- return opts;
-}
-
-DriveInfo *drive_get(BlockInterfaceType type, int bus, int unit)
-{
- DriveInfo *dinfo;
-
- /* seek interface, bus and unit */
-
- QTAILQ_FOREACH(dinfo, &drives, next) {
- if (dinfo->type == type &&
- dinfo->bus == bus &&
- dinfo->unit == unit)
- return dinfo;
- }
-
- return NULL;
-}
-
-DriveInfo *drive_get_by_id(const char *id)
-{
- DriveInfo *dinfo;
-
- QTAILQ_FOREACH(dinfo, &drives, next) {
- if (strcmp(id, dinfo->id))
- continue;
- return dinfo;
- }
- return NULL;
-}
-
-int drive_get_max_bus(BlockInterfaceType type)
-{
- int max_bus;
- DriveInfo *dinfo;
-
- max_bus = -1;
- QTAILQ_FOREACH(dinfo, &drives, next) {
- if(dinfo->type == type &&
- dinfo->bus > max_bus)
- max_bus = dinfo->bus;
- }
- return max_bus;
-}
-
-const char *drive_get_serial(BlockDriverState *bdrv)
-{
- DriveInfo *dinfo;
-
- QTAILQ_FOREACH(dinfo, &drives, next) {
- if (dinfo->bdrv == bdrv)
- return dinfo->serial;
- }
-
- return "\0";
-}
-
-BlockInterfaceErrorAction drive_get_on_error(
- BlockDriverState *bdrv, int is_read)
-{
- DriveInfo *dinfo;
-
- QTAILQ_FOREACH(dinfo, &drives, next) {
- if (dinfo->bdrv == bdrv)
- return is_read ? dinfo->on_read_error : dinfo->on_write_error;
- }
-
- return is_read ? BLOCK_ERR_REPORT : BLOCK_ERR_STOP_ENOSPC;
-}
-
-static void bdrv_format_print(void *opaque, const char *name)
-{
- fprintf(stderr, " %s", name);
-}
-
-void drive_uninit(DriveInfo *dinfo)
-{
- qemu_opts_del(dinfo->opts);
- bdrv_delete(dinfo->bdrv);
- QTAILQ_REMOVE(&drives, dinfo, next);
- qemu_free(dinfo);
-}
-
-static int parse_block_error_action(const char *buf, int is_read)
-{
- if (!strcmp(buf, "ignore")) {
- return BLOCK_ERR_IGNORE;
- } else if (!is_read && !strcmp(buf, "enospc")) {
- return BLOCK_ERR_STOP_ENOSPC;
- } else if (!strcmp(buf, "stop")) {
- return BLOCK_ERR_STOP_ANY;
- } else if (!strcmp(buf, "report")) {
- return BLOCK_ERR_REPORT;
- } else {
- fprintf(stderr, "qemu: '%s' invalid %s error action\n",
- buf, is_read ? "read" : "write");
- return -1;
- }
-}
-
-DriveInfo *drive_init(QemuOpts *opts, void *opaque,
- int *fatal_error)
-{
- const char *buf;
- const char *file = NULL;
- char devname[128];
- const char *serial;
- const char *mediastr = "";
- BlockInterfaceType type;
- enum { MEDIA_DISK, MEDIA_CDROM } media;
- int bus_id, unit_id;
- int cyls, heads, secs, translation;
- BlockDriver *drv = NULL;
- QEMUMachine *machine = opaque;
- int max_devs;
- int index;
- int ro = 0;
- int bdrv_flags = 0;
- int on_read_error, on_write_error;
- const char *devaddr;
- DriveInfo *dinfo;
- int snapshot = 0;
-
- *fatal_error = 1;
-
- translation = BIOS_ATA_TRANSLATION_AUTO;
-
- if (machine && machine->use_scsi) {
- type = IF_SCSI;
- max_devs = MAX_SCSI_DEVS;
- pstrcpy(devname, sizeof(devname), "scsi");
- } else {
- type = IF_IDE;
- max_devs = MAX_IDE_DEVS;
- pstrcpy(devname, sizeof(devname), "ide");
- }
- media = MEDIA_DISK;
-
- /* extract parameters */
- bus_id = qemu_opt_get_number(opts, "bus", 0);
- unit_id = qemu_opt_get_number(opts, "unit", -1);
- index = qemu_opt_get_number(opts, "index", -1);
-
- cyls = qemu_opt_get_number(opts, "cyls", 0);
- heads = qemu_opt_get_number(opts, "heads", 0);
- secs = qemu_opt_get_number(opts, "secs", 0);
-
- snapshot = qemu_opt_get_bool(opts, "snapshot", 0);
- ro = qemu_opt_get_bool(opts, "readonly", 0);
-
- file = qemu_opt_get(opts, "file");
- serial = qemu_opt_get(opts, "serial");
-
- if ((buf = qemu_opt_get(opts, "if")) != NULL) {
- pstrcpy(devname, sizeof(devname), buf);
- if (!strcmp(buf, "ide")) {
- type = IF_IDE;
- max_devs = MAX_IDE_DEVS;
- } else if (!strcmp(buf, "scsi")) {
- type = IF_SCSI;
- max_devs = MAX_SCSI_DEVS;
- } else if (!strcmp(buf, "floppy")) {
- type = IF_FLOPPY;
- max_devs = 0;
- } else if (!strcmp(buf, "pflash")) {
- type = IF_PFLASH;
- max_devs = 0;
- } else if (!strcmp(buf, "mtd")) {
- type = IF_MTD;
- max_devs = 0;
- } else if (!strcmp(buf, "sd")) {
- type = IF_SD;
- max_devs = 0;
- } else if (!strcmp(buf, "virtio")) {
- type = IF_VIRTIO;
- max_devs = 0;
- } else if (!strcmp(buf, "xen")) {
- type = IF_XEN;
- max_devs = 0;
- } else if (!strcmp(buf, "none")) {
- type = IF_NONE;
- max_devs = 0;
- } else {
- fprintf(stderr, "qemu: unsupported bus type '%s'\n", buf);
- return NULL;
- }
- }
-
- if (cyls || heads || secs) {
- if (cyls < 1 || (type == IF_IDE && cyls > 16383)) {
- fprintf(stderr, "qemu: '%s' invalid physical cyls number\n", buf);
- return NULL;
- }
- if (heads < 1 || (type == IF_IDE && heads > 16)) {
- fprintf(stderr, "qemu: '%s' invalid physical heads number\n", buf);
- return NULL;
- }
- if (secs < 1 || (type == IF_IDE && secs > 63)) {
- fprintf(stderr, "qemu: '%s' invalid physical secs number\n", buf);
- return NULL;
- }
- }
-
- if ((buf = qemu_opt_get(opts, "trans")) != NULL) {
- if (!cyls) {
- fprintf(stderr,
- "qemu: '%s' trans must be used with cyls,heads and secs\n",
- buf);
- return NULL;
- }
- if (!strcmp(buf, "none"))
- translation = BIOS_ATA_TRANSLATION_NONE;
- else if (!strcmp(buf, "lba"))
- translation = BIOS_ATA_TRANSLATION_LBA;
- else if (!strcmp(buf, "auto"))
- translation = BIOS_ATA_TRANSLATION_AUTO;
- else {
- fprintf(stderr, "qemu: '%s' invalid translation type\n", buf);
- return NULL;
- }
- }
-
- if ((buf = qemu_opt_get(opts, "media")) != NULL) {
- if (!strcmp(buf, "disk")) {
- media = MEDIA_DISK;
- } else if (!strcmp(buf, "cdrom")) {
- if (cyls || secs || heads) {
- fprintf(stderr,
- "qemu: '%s' invalid physical CHS format\n", buf);
- return NULL;
- }
- media = MEDIA_CDROM;
- } else {
- fprintf(stderr, "qemu: '%s' invalid media\n", buf);
- return NULL;
- }
- }
-
- if ((buf = qemu_opt_get(opts, "cache")) != NULL) {
- if (!strcmp(buf, "off") || !strcmp(buf, "none")) {
- bdrv_flags |= BDRV_O_NOCACHE;
- } else if (!strcmp(buf, "writeback")) {
- bdrv_flags |= BDRV_O_CACHE_WB;
- } else if (!strcmp(buf, "unsafe")) {
- bdrv_flags |= BDRV_O_CACHE_WB;
- bdrv_flags |= BDRV_O_NO_FLUSH;
- } else if (!strcmp(buf, "writethrough")) {
- /* this is the default */
- } else {
- fprintf(stderr, "qemu: invalid cache option\n");
- return NULL;
- }
- }
-
-#ifdef CONFIG_LINUX_AIO
- if ((buf = qemu_opt_get(opts, "aio")) != NULL) {
- if (!strcmp(buf, "native")) {
- bdrv_flags |= BDRV_O_NATIVE_AIO;
- } else if (!strcmp(buf, "threads")) {
- /* this is the default */
- } else {
- fprintf(stderr, "qemu: invalid aio option\n");
- return NULL;
- }
- }
-#endif
-
- if ((buf = qemu_opt_get(opts, "format")) != NULL) {
- if (strcmp(buf, "?") == 0) {
- fprintf(stderr, "qemu: Supported formats:");
- bdrv_iterate_format(bdrv_format_print, NULL);
- fprintf(stderr, "\n");
- return NULL;
- }
- drv = bdrv_find_whitelisted_format(buf);
- if (!drv) {
- fprintf(stderr, "qemu: '%s' invalid format\n", buf);
- return NULL;
- }
- }
-
- on_write_error = BLOCK_ERR_STOP_ENOSPC;
- if ((buf = qemu_opt_get(opts, "werror")) != NULL) {
- if (type != IF_IDE && type != IF_SCSI && type != IF_VIRTIO && type != IF_NONE) {
- fprintf(stderr, "werror is no supported by this format\n");
- return NULL;
- }
-
- on_write_error = parse_block_error_action(buf, 0);
- if (on_write_error < 0) {
- return NULL;
- }
- }
-
- on_read_error = BLOCK_ERR_REPORT;
- if ((buf = qemu_opt_get(opts, "rerror")) != NULL) {
- if (type != IF_IDE && type != IF_VIRTIO && type != IF_NONE) {
- fprintf(stderr, "rerror is no supported by this format\n");
- return NULL;
- }
-
- on_read_error = parse_block_error_action(buf, 1);
- if (on_read_error < 0) {
- return NULL;
- }
- }
-
- if ((devaddr = qemu_opt_get(opts, "addr")) != NULL) {
- if (type != IF_VIRTIO) {
- fprintf(stderr, "addr is not supported\n");
- return NULL;
- }
- }
-
- /* compute bus and unit according index */
-
- if (index != -1) {
- if (bus_id != 0 || unit_id != -1) {
- fprintf(stderr,
- "qemu: index cannot be used with bus and unit\n");
- return NULL;
- }
- if (max_devs == 0)
- {
- unit_id = index;
- bus_id = 0;
- } else {
- unit_id = index % max_devs;
- bus_id = index / max_devs;
- }
- }
-
- /* if user doesn't specify a unit_id,
- * try to find the first free
- */
-
- if (unit_id == -1) {
- unit_id = 0;
- while (drive_get(type, bus_id, unit_id) != NULL) {
- unit_id++;
- if (max_devs && unit_id >= max_devs) {
- unit_id -= max_devs;
- bus_id++;
- }
- }
- }
-
- /* check unit id */
-
- if (max_devs && unit_id >= max_devs) {
- fprintf(stderr, "qemu: unit %d too big (max is %d)\n",
- unit_id, max_devs - 1);
- return NULL;
- }
-
- /*
- * ignore multiple definitions
- */
-
- if (drive_get(type, bus_id, unit_id) != NULL) {
- *fatal_error = 0;
- return NULL;
- }
-
- /* init */
-
- dinfo = qemu_mallocz(sizeof(*dinfo));
- if ((buf = qemu_opts_id(opts)) != NULL) {
- dinfo->id = qemu_strdup(buf);
- } else {
- /* no id supplied -> create one */
- dinfo->id = qemu_mallocz(32);
- if (type == IF_IDE || type == IF_SCSI)
- mediastr = (media == MEDIA_CDROM) ? "-cd" : "-hd";
- if (max_devs)
- snprintf(dinfo->id, 32, "%s%i%s%i",
- devname, bus_id, mediastr, unit_id);
- else
- snprintf(dinfo->id, 32, "%s%s%i",
- devname, mediastr, unit_id);
- }
- dinfo->bdrv = bdrv_new(dinfo->id);
- dinfo->devaddr = devaddr;
- dinfo->type = type;
- dinfo->bus = bus_id;
- dinfo->unit = unit_id;
- dinfo->on_read_error = on_read_error;
- dinfo->on_write_error = on_write_error;
- dinfo->opts = opts;
- if (serial)
- strncpy(dinfo->serial, serial, sizeof(serial));
- QTAILQ_INSERT_TAIL(&drives, dinfo, next);
-
- switch(type) {
- case IF_IDE:
- case IF_SCSI:
- case IF_XEN:
- case IF_NONE:
- switch(media) {
- case MEDIA_DISK:
- if (cyls != 0) {
- bdrv_set_geometry_hint(dinfo->bdrv, cyls, heads, secs);
- bdrv_set_translation_hint(dinfo->bdrv, translation);
- }
- break;
- case MEDIA_CDROM:
- bdrv_set_type_hint(dinfo->bdrv, BDRV_TYPE_CDROM);
- break;
- }
- break;
- case IF_SD:
- /* FIXME: This isn't really a floppy, but it's a reasonable
- approximation. */
- case IF_FLOPPY:
- bdrv_set_type_hint(dinfo->bdrv, BDRV_TYPE_FLOPPY);
- break;
- case IF_PFLASH:
- case IF_MTD:
- break;
- case IF_VIRTIO:
- /* add virtio block device */
- opts = qemu_opts_create(&qemu_device_opts, NULL, 0);
- qemu_opt_set(opts, "driver", "virtio-blk-pci");
- qemu_opt_set(opts, "drive", dinfo->id);
- if (devaddr)
- qemu_opt_set(opts, "addr", devaddr);
- break;
- case IF_COUNT:
- abort();
- }
- if (!file) {
- *fatal_error = 0;
- return NULL;
- }
- if (snapshot) {
- /* always use cache=unsafe with snapshot */
- bdrv_flags &= ~BDRV_O_CACHE_MASK;
- bdrv_flags |= (BDRV_O_SNAPSHOT|BDRV_O_CACHE_WB|BDRV_O_NO_FLUSH);
- }
-
- if (media == MEDIA_CDROM) {
- /* CDROM is fine for any interface, don't check. */
- ro = 1;
- } else if (ro == 1) {
- if (type != IF_SCSI && type != IF_VIRTIO && type != IF_FLOPPY && type != IF_NONE) {
- fprintf(stderr, "qemu: readonly flag not supported for drive with this interface\n");
- return NULL;
- }
- }
-
- bdrv_flags |= ro ? 0 : BDRV_O_RDWR;
-
- if (bdrv_open(dinfo->bdrv, file, bdrv_flags, drv) < 0) {
- fprintf(stderr, "qemu: could not open disk image %s: %s\n",
- file, strerror(errno));
- return NULL;
- }
-
- if (bdrv_key_required(dinfo->bdrv))
- autostart = 0;
- *fatal_error = 0;
- return dinfo;
-}
-
static int drive_init_func(QemuOpts *opts, void *opaque)
{
- QEMUMachine *machine = opaque;
+ int *use_scsi = opaque;
int fatal_error = 0;
- if (drive_init(opts, machine, &fatal_error) == NULL) {
+ if (drive_init(opts, *use_scsi, &fatal_error) == NULL) {
if (fatal_error)
return 1;
}
@@ -1297,7 +813,7 @@ static void smp_parse(const char *optarg)
/***********************************************************/
/* USB devices */
-static int usb_device_add(const char *devname, int is_hotplug)
+static int usb_device_add(const char *devname)
{
const char *p;
USBDevice *dev = NULL;
@@ -1349,7 +865,7 @@ static int usb_device_del(const char *devname)
static int usb_parse(const char *cmdline)
{
int r;
- r = usb_device_add(cmdline, 0);
+ r = usb_device_add(cmdline);
if (r < 0) {
fprintf(stderr, "qemu: could not add USB device '%s'\n", cmdline);
}
@@ -1359,7 +875,7 @@ static int usb_parse(const char *cmdline)
void do_usb_add(Monitor *mon, const QDict *qdict)
{
const char *devname = qdict_get_str(qdict, "devname");
- if (usb_device_add(devname, 1) < 0) {
+ if (usb_device_add(devname) < 0) {
error_report("could not add USB device '%s'", devname);
}
}
@@ -1841,6 +1357,7 @@ static void main_loop(void)
vm_stop(r);
}
}
+ bdrv_close_all();
pause_all_vcpus();
}
@@ -3243,7 +2760,7 @@ int main(int argc, char **argv, char **envp)
/* open the virtual block devices */
if (snapshot)
qemu_opts_foreach(&qemu_drive_opts, drive_enable_snapshot, NULL, 0);
- if (qemu_opts_foreach(&qemu_drive_opts, drive_init_func, machine, 1) != 0)
+ if (qemu_opts_foreach(&qemu_drive_opts, drive_init_func, &machine->use_scsi, 1) != 0)
exit(1);
register_savevm_live("ram", 0, 3, NULL, ram_save_live, NULL,