summary refs log tree commit diff stats
path: root/hw
diff options
context:
space:
mode:
Diffstat (limited to 'hw')
-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
36 files changed, 157 insertions, 97 deletions
diff --git a/hw/acpi_piix4.c b/hw/acpi_piix4.c
index 0fce958d07..a87286b917 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 b53e3c3bf9..31c8d705a2 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 9cc8376691..c1a9a561d7 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 6306496383..b97895786a 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 c48b5e04df..b6b3772592 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 cdcc9bf1aa..559147ff43 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 066fecb0c0..045d18db2b 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 2efc7846bc..eef1ee141d 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 dff7c796f7..b6c6347289 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 639f3f6a65..f76c0fa31c 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 bfdb8c8b05..a7beac552a 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 cca883f613..e75cccf56e 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 4fa38519ef..dad6e86ff6 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 b18693d945..0f9f22e30f 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 16d33304d5..b996dc4f0c 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 40d5a6a736..cd7444f9a5 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 bd1b35e661..666c15adb2 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 c1e7e4d608..4118db922d 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 be8e2d5479..6b11672e15 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 14911297ea..0f7d330609 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 70f563a67e..dc46846923 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 a8f3df1701..c39e640089 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 cf2db9d325..360292395b 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 1924053330..85cadc4fe1 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 9ffdba792c..5a8739debe 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 36f29ea79f..61f999c023 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 a44060e54c..be5ad671cc 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 383240bc07..055a94d255 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 4d209197ce..a9bf7d261a 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 c9aa853cc4..e31060e944 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 9102edb77b..c7e4e77cb0 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 5e74e5d7ce..96b33edcbd 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 8e6c6e0322..228d0a052a 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 c1c2537475..003bd8a4cd 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 5d7f1a2200..cdcb492c14 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 7ddf612282..e101fa0a7d 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"