[3/3] blockdev: Collect block device code in new blockdev.c

Submitted by Markus Armbruster on June 2, 2010, 11:31 a.m.

Details

Message ID 1275478317-1989-4-git-send-email-armbru@redhat.com
State New
Headers show

Commit Message

Markus Armbruster June 2, 2010, 11:31 a.m.
Anything that moves hundreds of lines out of vl.c can't be all bad.

Signed-off-by: Markus Armbruster <armbru@redhat.com>
---
 Makefile.objs        |    2 +-
 blockdev.c           |  591 ++++++++++++++++++++++++++++++++++++++++++++++++++
 blockdev.h           |   62 ++++++
 hw/acpi_piix4.c      |    1 +
 hw/apb_pci.c         |    1 +
 hw/device-hotplug.c  |    2 -
 hw/fdc.c             |    1 -
 hw/fdc.h             |    2 +-
 hw/ide/core.c        |    2 -
 hw/ide/qdev.c        |    1 -
 hw/lan9118.c         |    1 +
 hw/nand.c            |    3 +-
 hw/omap2.c           |    2 +
 hw/onenand.c         |    3 +-
 hw/parallel.c        |    1 +
 hw/pc.c              |    1 +
 hw/pc_piix.c         |    1 +
 hw/pci-hotplug.c     |    2 -
 hw/pcmcia.h          |    2 +-
 hw/qdev-properties.c |    1 -
 hw/qdev.h            |    2 +-
 hw/scsi-bus.c        |    1 -
 hw/scsi-disk.c       |    2 +-
 hw/scsi-generic.c    |    1 -
 hw/serial.c          |    1 +
 hw/usb-hid.c         |    1 +
 hw/usb-msd.c         |    2 +-
 hw/virtio-blk.c      |    2 -
 hw/virtio-pci.c      |    1 -
 monitor.c            |  104 +---------
 qemu-char.c          |    1 -
 savevm.c             |    2 +-
 sysemu.h             |   49 ----
 vl.c                 |  483 +----------------------------------------
 34 files changed, 674 insertions(+), 660 deletions(-)
 create mode 100644 blockdev.c
 create mode 100644 blockdev.h

Comments

Kevin Wolf June 2, 2010, 3:52 p.m.
Am 02.06.2010 13:31, schrieb Markus Armbruster:
> Anything that moves hundreds of lines out of vl.c can't be all bad.
> 
> Signed-off-by: Markus Armbruster <armbru@redhat.com>

New files need a license header, otherwise it looks ok.

I have applied this patch (and the other ones, too) to the block branch
anyway to avoid conflicts with other people basing their patches on that
branch. However, it requires a v2 before I can propose this to be merged
into master.

Kevin
Markus Armbruster June 2, 2010, 4:16 p.m.
Kevin Wolf <kwolf@redhat.com> writes:

> Am 02.06.2010 13:31, schrieb Markus Armbruster:
>> Anything that moves hundreds of lines out of vl.c can't be all bad.
>> 
>> Signed-off-by: Markus Armbruster <armbru@redhat.com>
>
> New files need a license header, otherwise it looks ok.
>
> I have applied this patch (and the other ones, too) to the block branch
> anyway to avoid conflicts with other people basing their patches on that
> branch. However, it requires a v2 before I can propose this to be merged
> into master.

vl.c has "Copyright (c) 2003-2008 Fabrice Bellard".  monitor.c has
"Copyright (c) 2003-2004 Fabrice Bellard".  Would the following header
do?

/*
 * 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.
 */
Kevin Wolf June 4, 2010, 10:43 a.m.
Am 02.06.2010 18:16, schrieb Markus Armbruster:
> Kevin Wolf <kwolf@redhat.com> writes:
> 
>> Am 02.06.2010 13:31, schrieb Markus Armbruster:
>>> Anything that moves hundreds of lines out of vl.c can't be all bad.
>>>
>>> Signed-off-by: Markus Armbruster <armbru@redhat.com>
>>
>> New files need a license header, otherwise it looks ok.
>>
>> I have applied this patch (and the other ones, too) to the block branch
>> anyway to avoid conflicts with other people basing their patches on that
>> branch. However, it requires a v2 before I can propose this to be merged
>> into master.
> 
> vl.c has "Copyright (c) 2003-2008 Fabrice Bellard".  monitor.c has
> "Copyright (c) 2003-2004 Fabrice Bellard".  Would the following header
> do?
> 
> /*
>  * 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.
>  */

Should be good enough, I think.

vl.c and monitor.c are BSD licensed, though. Not sure if anyone minds if
the license is changed to GPL. Probably not, just want to have it mentioned.

Kevin
Markus Armbruster June 4, 2010, 12:12 p.m.
Kevin Wolf <kwolf@redhat.com> writes:

> Am 02.06.2010 18:16, schrieb Markus Armbruster:
>> Kevin Wolf <kwolf@redhat.com> writes:
>> 
>>> Am 02.06.2010 13:31, schrieb Markus Armbruster:
>>>> Anything that moves hundreds of lines out of vl.c can't be all bad.
>>>>
>>>> Signed-off-by: Markus Armbruster <armbru@redhat.com>
>>>
>>> New files need a license header, otherwise it looks ok.
>>>
>>> I have applied this patch (and the other ones, too) to the block branch
>>> anyway to avoid conflicts with other people basing their patches on that
>>> branch. However, it requires a v2 before I can propose this to be merged
>>> into master.
>> 
>> vl.c has "Copyright (c) 2003-2008 Fabrice Bellard".  monitor.c has
>> "Copyright (c) 2003-2004 Fabrice Bellard".  Would the following header
>> do?
>> 
>> /*
>>  * 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.
>>  */
>
> Should be good enough, I think.
>
> vl.c and monitor.c are BSD licensed, though. Not sure if anyone minds if
> the license is changed to GPL. Probably not, just want to have it mentioned.

If this were not okay, I'd split blockdev.c, because I want my new code
GPL'ed.

Patch hide | download patch | download mbox

diff --git a/Makefile.objs b/Makefile.objs
index 9796dcb..54dec26 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/blockdev.c b/blockdev.c
new file mode 100644
index 0000000..04cfe61
--- /dev/null
+++ b/blockdev.c
@@ -0,0 +1,591 @@ 
+#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(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;
+
+    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 0000000..60a4017
--- /dev/null
+++ b/blockdev.h
@@ -0,0 +1,62 @@ 
+#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 0fce958..a87286b 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 b53e3c3..31c8d70 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 a3fe99e..c1a9a56 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)
 {
diff --git a/hw/fdc.c b/hw/fdc.c
index 6306496..b978957 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 c48b5e0..b6b3772 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/core.c b/hw/ide/core.c
index 70af1b6..045d18d 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"
diff --git a/hw/ide/qdev.c b/hw/ide/qdev.c
index 6231d77..0f9f22e 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>
diff --git a/hw/lan9118.c b/hw/lan9118.c
index 16d3330..b996dc4 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 40d5a6a..cd7444f 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 bd1b35e..666c15a 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 c1e7e4d..4118db9 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 be8e2d5..6b11672 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 9b85c42..6e7c468 100644
--- a/hw/pc.c
+++ b/hw/pc.c
@@ -35,6 +35,7 @@ 
 #include "elf.h"
 #include "multiboot.h"
 #include "mc146818rtc.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 70f563a..dc46846 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 a8f3df1..c39e640 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 cf2db9d..3602923 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/qdev-properties.c b/hw/qdev-properties.c
index 48a6b45..5a8739d 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"
diff --git a/hw/qdev.h b/hw/qdev.h
index 0ad6c95..be5ad67 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"
diff --git a/hw/scsi-bus.c b/hw/scsi-bus.c
index 383240b..055a94d 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 a3559d1..a9bf7d2 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
diff --git a/hw/scsi-generic.c b/hw/scsi-generic.c
index c9aa853..e31060e 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 9102edb..c7e4e77 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/usb-hid.c b/hw/usb-hid.c
index 8e6c6e0..228d0a0 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 0ba4a64..003bd8a 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
 
diff --git a/hw/virtio-blk.c b/hw/virtio-blk.c
index 80d51c4..cdcb492 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
diff --git a/hw/virtio-pci.c b/hw/virtio-pci.c
index 7ddf612..e101fa0 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 15b53b9..57f24ff 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; 
@@ -949,93 +934,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 faaf624..87628ea 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/savevm.c b/savevm.c
index dc20390..18852cd 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 dce13c1..5fa45ed 100644
--- a/sysemu.h
+++ b/sysemu.h
@@ -147,55 +147,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
-
-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);
-
 /* 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 db1fefd..0a9862f 100644
--- a/vl.c
+++ b/vl.c
@@ -140,7 +140,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"
@@ -172,7 +172,6 @@  int main(int argc, char **argv)
 
 static const char *data_dir;
 const char *bios_name = NULL;
-struct drivelist drives = QTAILQ_HEAD_INITIALIZER(drives);
 enum vga_retrace_method vga_retrace_method = VGA_RETRACE_DUMB;
 DisplayType display_type = DT_DEFAULT;
 const char* keyboard_layout = NULL;
@@ -651,486 +650,6 @@  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, 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(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;
-
-    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;
-}
-
 static int drive_init_func(QemuOpts *opts, void *opaque)
 {
     int *use_scsi = opaque;