diff options
author | Anthony Liguori <aliguori@us.ibm.com> | 2010-07-06 08:31:43 -0500 |
---|---|---|
committer | Anthony Liguori <aliguori@us.ibm.com> | 2010-07-06 08:31:43 -0500 |
commit | 734003e6153b3552b9406ef598a1e67aac4a899e (patch) | |
tree | 9e4b225de8915dfecaec15356f085f9cb36057f7 /hw | |
parent | 02d0ba1420803562109185f47be6f7430bfdefae (diff) | |
parent | de189a1b4a471d37a2909e97646654fc9751b52f (diff) | |
download | qemu-734003e6153b3552b9406ef598a1e67aac4a899e.zip |
Merge remote branch 'kwolf/for-anthony' into staging
Diffstat (limited to 'hw')
-rw-r--r-- | hw/esp.c | 3 | ||||
-rw-r--r-- | hw/fdc.c | 32 | ||||
-rw-r--r-- | hw/ide.h | 13 | ||||
-rw-r--r-- | hw/ide/core.c | 18 | ||||
-rw-r--r-- | hw/ide/internal.h | 2 | ||||
-rw-r--r-- | hw/ide/isa.c | 8 | ||||
-rw-r--r-- | hw/ide/piix.c | 6 | ||||
-rw-r--r-- | hw/ide/qdev.c | 22 | ||||
-rw-r--r-- | hw/lsi53c895a.c | 2 | ||||
-rw-r--r-- | hw/pc.c | 94 | ||||
-rw-r--r-- | hw/pc.h | 3 | ||||
-rw-r--r-- | hw/pc_piix.c | 16 | ||||
-rw-r--r-- | hw/pci-hotplug.c | 11 | ||||
-rw-r--r-- | hw/qdev-properties.c | 47 | ||||
-rw-r--r-- | hw/qdev.h | 7 | ||||
-rw-r--r-- | hw/s390-virtio.c | 2 | ||||
-rw-r--r-- | hw/scsi-bus.c | 20 | ||||
-rw-r--r-- | hw/scsi-disk.c | 21 | ||||
-rw-r--r-- | hw/scsi-generic.c | 7 | ||||
-rw-r--r-- | hw/scsi.h | 4 | ||||
-rw-r--r-- | hw/usb-msd.c | 30 | ||||
-rw-r--r-- | hw/virtio-blk.c | 3 | ||||
-rw-r--r-- | hw/virtio-pci.c | 4 |
23 files changed, 247 insertions, 128 deletions
@@ -679,8 +679,7 @@ static int esp_init1(SysBusDevice *dev) qdev_init_gpio_in(&dev->qdev, parent_esp_reset, 1); scsi_bus_new(&s->bus, &dev->qdev, 0, ESP_MAX_DEVS, esp_command_complete); - scsi_bus_legacy_handle_cmdline(&s->bus); - return 0; + return scsi_bus_legacy_handle_cmdline(&s->bus); } static SysBusDeviceInfo esp_info = { @@ -80,7 +80,6 @@ typedef enum FDiskFlags { } FDiskFlags; typedef struct FDrive { - DriveInfo *dinfo; BlockDriverState *bs; /* Drive status */ FDriveType drive; @@ -100,7 +99,6 @@ typedef struct FDrive { static void fd_init(FDrive *drv) { /* Drive */ - drv->bs = drv->dinfo ? drv->dinfo->bdrv : NULL; drv->drive = FDRIVE_DRV_NONE; drv->perpendicular = 0; /* Disk */ @@ -1849,10 +1847,16 @@ static void fdctrl_result_timer(void *opaque) static void fdctrl_connect_drives(FDCtrl *fdctrl) { unsigned int i; + FDrive *drive; for (i = 0; i < MAX_FD; i++) { - fd_init(&fdctrl->drives[i]); - fd_revalidate(&fdctrl->drives[i]); + drive = &fdctrl->drives[i]; + + fd_init(drive); + fd_revalidate(drive); + if (drive->bs) { + bdrv_set_removable(drive->bs, 1); + } } } @@ -1862,10 +1866,10 @@ FDCtrl *fdctrl_init_isa(DriveInfo **fds) dev = isa_create("isa-fdc"); if (fds[0]) { - qdev_prop_set_drive(&dev->qdev, "driveA", fds[0]); + qdev_prop_set_drive_nofail(&dev->qdev, "driveA", fds[0]->bdrv); } if (fds[1]) { - qdev_prop_set_drive(&dev->qdev, "driveB", fds[1]); + qdev_prop_set_drive_nofail(&dev->qdev, "driveB", fds[1]->bdrv); } if (qdev_init(&dev->qdev) < 0) return NULL; @@ -1884,10 +1888,10 @@ FDCtrl *fdctrl_init_sysbus(qemu_irq irq, int dma_chann, fdctrl = &sys->state; fdctrl->dma_chann = dma_chann; /* FIXME */ if (fds[0]) { - qdev_prop_set_drive(dev, "driveA", fds[0]); + qdev_prop_set_drive_nofail(dev, "driveA", fds[0]->bdrv); } if (fds[1]) { - qdev_prop_set_drive(dev, "driveB", fds[1]); + qdev_prop_set_drive_nofail(dev, "driveB", fds[1]->bdrv); } qdev_init_nofail(dev); sysbus_connect_irq(&sys->busdev, 0, irq); @@ -1905,7 +1909,7 @@ FDCtrl *sun4m_fdctrl_init(qemu_irq irq, target_phys_addr_t io_base, dev = qdev_create(NULL, "SUNW,fdtwo"); if (fds[0]) { - qdev_prop_set_drive(dev, "drive", fds[0]); + qdev_prop_set_drive_nofail(dev, "drive", fds[0]->bdrv); } qdev_init_nofail(dev); sys = DO_UPCAST(FDCtrlSysBus, busdev.qdev, dev); @@ -2030,8 +2034,8 @@ static ISADeviceInfo isa_fdc_info = { .qdev.vmsd = &vmstate_isa_fdc, .qdev.reset = fdctrl_external_reset_isa, .qdev.props = (Property[]) { - DEFINE_PROP_DRIVE("driveA", FDCtrlISABus, state.drives[0].dinfo), - DEFINE_PROP_DRIVE("driveB", FDCtrlISABus, state.drives[1].dinfo), + DEFINE_PROP_DRIVE("driveA", FDCtrlISABus, state.drives[0].bs), + DEFINE_PROP_DRIVE("driveB", FDCtrlISABus, state.drives[1].bs), DEFINE_PROP_END_OF_LIST(), }, }; @@ -2053,8 +2057,8 @@ static SysBusDeviceInfo sysbus_fdc_info = { .qdev.vmsd = &vmstate_sysbus_fdc, .qdev.reset = fdctrl_external_reset_sysbus, .qdev.props = (Property[]) { - DEFINE_PROP_DRIVE("driveA", FDCtrlSysBus, state.drives[0].dinfo), - DEFINE_PROP_DRIVE("driveB", FDCtrlSysBus, state.drives[1].dinfo), + DEFINE_PROP_DRIVE("driveA", FDCtrlSysBus, state.drives[0].bs), + DEFINE_PROP_DRIVE("driveB", FDCtrlSysBus, state.drives[1].bs), DEFINE_PROP_END_OF_LIST(), }, }; @@ -2066,7 +2070,7 @@ static SysBusDeviceInfo sun4m_fdc_info = { .qdev.vmsd = &vmstate_sysbus_fdc, .qdev.reset = fdctrl_external_reset_sysbus, .qdev.props = (Property[]) { - DEFINE_PROP_DRIVE("drive", FDCtrlSysBus, state.drives[0].dinfo), + DEFINE_PROP_DRIVE("drive", FDCtrlSysBus, state.drives[0].bs), DEFINE_PROP_END_OF_LIST(), }, }; @@ -1,17 +1,18 @@ #ifndef HW_IDE_H #define HW_IDE_H -#include "qdev.h" +#include "isa.h" +#include "pci.h" /* ide-isa.c */ -int isa_ide_init(int iobase, int iobase2, int isairq, - DriveInfo *hd0, DriveInfo *hd1); +ISADevice *isa_ide_init(int iobase, int iobase2, int isairq, + DriveInfo *hd0, DriveInfo *hd1); /* ide-pci.c */ void pci_cmd646_ide_init(PCIBus *bus, DriveInfo **hd_table, int secondary_ide_enabled); -void pci_piix3_ide_init(PCIBus *bus, DriveInfo **hd_table, int devfn); -void pci_piix4_ide_init(PCIBus *bus, DriveInfo **hd_table, int devfn); +PCIDevice *pci_piix3_ide_init(PCIBus *bus, DriveInfo **hd_table, int devfn); +PCIDevice *pci_piix4_ide_init(PCIBus *bus, DriveInfo **hd_table, int devfn); void vt82c686b_ide_init(PCIBus *bus, DriveInfo **hd_table, int devfn); /* ide-macio.c */ @@ -23,4 +24,6 @@ void mmio_ide_init (target_phys_addr_t membase, target_phys_addr_t membase2, qemu_irq irq, int shift, DriveInfo *hd0, DriveInfo *hd1); +void ide_get_bs(BlockDriverState *bs[], BusState *qbus); + #endif /* HW_IDE_H */ diff --git a/hw/ide/core.c b/hw/ide/core.c index 0b3b7c2e69..ebdceb5fec 100644 --- a/hw/ide/core.c +++ b/hw/ide/core.c @@ -2594,15 +2594,15 @@ void ide_bus_reset(IDEBus *bus) ide_clear_hob(bus); } -void ide_init_drive(IDEState *s, DriveInfo *dinfo, +void ide_init_drive(IDEState *s, BlockDriverState *bs, const char *version, const char *serial) { int cylinders, heads, secs; uint64_t nb_sectors; - s->bs = dinfo->bdrv; - bdrv_get_geometry(s->bs, &nb_sectors); - bdrv_guess_geometry(s->bs, &cylinders, &heads, &secs); + s->bs = bs; + bdrv_get_geometry(bs, &nb_sectors); + bdrv_guess_geometry(bs, &cylinders, &heads, &secs); s->cylinders = cylinders; s->heads = heads; s->sectors = secs; @@ -2613,11 +2613,11 @@ void ide_init_drive(IDEState *s, DriveInfo *dinfo, s->smart_autosave = 1; s->smart_errors = 0; s->smart_selftest_count = 0; - if (bdrv_get_type_hint(s->bs) == BDRV_TYPE_CDROM) { + if (bdrv_get_type_hint(bs) == BDRV_TYPE_CDROM) { s->is_cdrom = 1; - bdrv_set_change_cb(s->bs, cdrom_change_cb, s); + bdrv_set_change_cb(bs, cdrom_change_cb, s); } - if (serial && *serial) { + if (serial) { strncpy(s->drive_serial_str, serial, sizeof(s->drive_serial_str)); } else { snprintf(s->drive_serial_str, sizeof(s->drive_serial_str), @@ -2629,6 +2629,7 @@ void ide_init_drive(IDEState *s, DriveInfo *dinfo, pstrcpy(s->version, sizeof(s->version), QEMU_VERSION); } ide_reset(s); + bdrv_set_removable(bs, s->is_cdrom); } static void ide_init1(IDEBus *bus, int unit) @@ -2668,7 +2669,8 @@ void ide_init2_with_non_qdev_drives(IDEBus *bus, DriveInfo *hd0, dinfo = i == 0 ? hd0 : hd1; ide_init1(bus, i); if (dinfo) { - ide_init_drive(&bus->ifs[i], dinfo, NULL, dinfo->serial); + ide_init_drive(&bus->ifs[i], dinfo->bdrv, NULL, + *dinfo->serial ? dinfo->serial : NULL); } else { ide_reset(&bus->ifs[i]); } diff --git a/hw/ide/internal.h b/hw/ide/internal.h index eef1ee141d..0125a9f0b9 100644 --- a/hw/ide/internal.h +++ b/hw/ide/internal.h @@ -555,7 +555,7 @@ 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, +void ide_init_drive(IDEState *s, BlockDriverState *bs, 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, diff --git a/hw/ide/isa.c b/hw/ide/isa.c index b6c6347289..10777caec1 100644 --- a/hw/ide/isa.c +++ b/hw/ide/isa.c @@ -75,8 +75,8 @@ static int isa_ide_initfn(ISADevice *dev) return 0; }; -int isa_ide_init(int iobase, int iobase2, int isairq, - DriveInfo *hd0, DriveInfo *hd1) +ISADevice *isa_ide_init(int iobase, int iobase2, int isairq, + DriveInfo *hd0, DriveInfo *hd1) { ISADevice *dev; ISAIDEState *s; @@ -86,14 +86,14 @@ int isa_ide_init(int iobase, int iobase2, int isairq, qdev_prop_set_uint32(&dev->qdev, "iobase2", iobase2); qdev_prop_set_uint32(&dev->qdev, "irq", isairq); if (qdev_init(&dev->qdev) < 0) - return -1; + return NULL; s = DO_UPCAST(ISAIDEState, dev, dev); if (hd0) ide_create_drive(&s->bus, 0, hd0); if (hd1) ide_create_drive(&s->bus, 1, hd1); - return 0; + return dev; } static ISADeviceInfo isa_ide_info = { diff --git a/hw/ide/piix.c b/hw/ide/piix.c index dad6e86ff6..fa22226dce 100644 --- a/hw/ide/piix.c +++ b/hw/ide/piix.c @@ -160,22 +160,24 @@ static int pci_piix4_ide_initfn(PCIDevice *dev) /* hd_table must contain 4 block drivers */ /* NOTE: for the PIIX3, the IRQs and IOports are hardcoded */ -void pci_piix3_ide_init(PCIBus *bus, DriveInfo **hd_table, int devfn) +PCIDevice *pci_piix3_ide_init(PCIBus *bus, DriveInfo **hd_table, int devfn) { PCIDevice *dev; dev = pci_create_simple(bus, devfn, "piix3-ide"); pci_ide_create_devs(dev, hd_table); + return dev; } /* hd_table must contain 4 block drivers */ /* NOTE: for the PIIX4, the IRQs and IOports are hardcoded */ -void pci_piix4_ide_init(PCIBus *bus, DriveInfo **hd_table, int devfn) +PCIDevice *pci_piix4_ide_init(PCIBus *bus, DriveInfo **hd_table, int devfn) { PCIDevice *dev; dev = pci_create_simple(bus, devfn, "piix4-ide"); pci_ide_create_devs(dev, hd_table); + return dev; } static PCIDeviceInfo piix_ide_info[] = { diff --git a/hw/ide/qdev.c b/hw/ide/qdev.c index 0f9f22e30f..2977a168e5 100644 --- a/hw/ide/qdev.c +++ b/hw/ide/qdev.c @@ -39,7 +39,7 @@ static int ide_qdev_init(DeviceState *qdev, DeviceInfo *base) IDEDeviceInfo *info = DO_UPCAST(IDEDeviceInfo, qdev, base); IDEBus *bus = DO_UPCAST(IDEBus, qbus, qdev->parent_bus); - if (!dev->conf.dinfo) { + if (!dev->conf.bs) { fprintf(stderr, "%s: no drive specified\n", qdev->info->name); goto err; } @@ -83,12 +83,18 @@ IDEDevice *ide_create_drive(IDEBus *bus, int unit, DriveInfo *drive) dev = qdev_create(&bus->qbus, "ide-drive"); qdev_prop_set_uint32(dev, "unit", unit); - qdev_prop_set_drive(dev, "drive", drive); - if (qdev_init(dev) < 0) - return NULL; + qdev_prop_set_drive_nofail(dev, "drive", drive->bdrv); + qdev_init_nofail(dev); return DO_UPCAST(IDEDevice, qdev, dev); } +void ide_get_bs(BlockDriverState *bs[], BusState *qbus) +{ + IDEBus *bus = DO_UPCAST(IDEBus, qbus, qbus); + bs[0] = bus->master ? bus->master->conf.bs : NULL; + bs[1] = bus->slave ? bus->slave->conf.bs : NULL; +} + /* --------------------------------- */ typedef struct IDEDrive { @@ -100,14 +106,18 @@ static int ide_drive_initfn(IDEDevice *dev) IDEBus *bus = DO_UPCAST(IDEBus, qbus, dev->qdev.parent_bus); IDEState *s = bus->ifs + dev->unit; const char *serial; + DriveInfo *dinfo; serial = dev->serial; if (!serial) { /* try to fall back to value set with legacy -drive serial=... */ - serial = dev->conf.dinfo->serial; + dinfo = drive_get_by_blockdev(dev->conf.bs); + if (*dinfo->serial) { + serial = dinfo->serial; + } } - ide_init_drive(s, dev->conf.dinfo, dev->version, serial); + ide_init_drive(s, dev->conf.bs, dev->version, serial); if (!dev->version) { dev->version = qemu_strdup(s->version); diff --git a/hw/lsi53c895a.c b/hw/lsi53c895a.c index 9a37fed3b3..1bb1caf478 100644 --- a/hw/lsi53c895a.c +++ b/hw/lsi53c895a.c @@ -2176,7 +2176,7 @@ static int lsi_scsi_init(PCIDevice *dev) scsi_bus_new(&s->bus, &dev->qdev, 1, LSI_MAX_DEVS, lsi_command_complete); if (!dev->qdev.hotplugged) { - scsi_bus_legacy_handle_cmdline(&s->bus); + return scsi_bus_legacy_handle_cmdline(&s->bus); } return 0; } @@ -25,6 +25,7 @@ #include "pc.h" #include "apic.h" #include "fdc.h" +#include "ide.h" #include "pci.h" #include "vmware_vga.h" #include "monitor.h" @@ -275,14 +276,65 @@ static int pc_boot_set(void *opaque, const char *boot_device) return set_boot_dev(opaque, boot_device, 0); } -/* hd_table must contain 4 block drivers */ +typedef struct pc_cmos_init_late_arg { + ISADevice *rtc_state; + BusState *idebus0, *idebus1; +} pc_cmos_init_late_arg; + +static void pc_cmos_init_late(void *opaque) +{ + pc_cmos_init_late_arg *arg = opaque; + ISADevice *s = arg->rtc_state; + int val; + BlockDriverState *hd_table[4]; + int i; + + ide_get_bs(hd_table, arg->idebus0); + ide_get_bs(hd_table + 2, arg->idebus1); + + rtc_set_memory(s, 0x12, (hd_table[0] ? 0xf0 : 0) | (hd_table[1] ? 0x0f : 0)); + if (hd_table[0]) + cmos_init_hd(0x19, 0x1b, hd_table[0], s); + if (hd_table[1]) + cmos_init_hd(0x1a, 0x24, hd_table[1], s); + + val = 0; + for (i = 0; i < 4; i++) { + if (hd_table[i]) { + int cylinders, heads, sectors, translation; + /* NOTE: bdrv_get_geometry_hint() returns the physical + geometry. It is always such that: 1 <= sects <= 63, 1 + <= heads <= 16, 1 <= cylinders <= 16383. The BIOS + geometry can be different if a translation is done. */ + translation = bdrv_get_translation_hint(hd_table[i]); + if (translation == BIOS_ATA_TRANSLATION_AUTO) { + bdrv_get_geometry_hint(hd_table[i], &cylinders, &heads, §ors); + if (cylinders <= 1024 && heads <= 16 && sectors <= 63) { + /* No translation. */ + translation = 0; + } else { + /* LBA translation. */ + translation = 1; + } + } else { + translation--; + } + val |= translation << (i * 2); + } + } + rtc_set_memory(s, 0x39, val); + + qemu_unregister_reset(pc_cmos_init_late, opaque); +} + void pc_cmos_init(ram_addr_t ram_size, ram_addr_t above_4g_mem_size, - const char *boot_device, DriveInfo **hd_table, + const char *boot_device, + BusState *idebus0, BusState *idebus1, FDCtrl *floppy_controller, ISADevice *s) { int val; int fd0, fd1, nb; - int i; + static pc_cmos_init_late_arg arg; /* various important CMOS locations needed by PC/Bochs bios */ @@ -351,38 +403,10 @@ void pc_cmos_init(ram_addr_t ram_size, ram_addr_t above_4g_mem_size, rtc_set_memory(s, REG_EQUIPMENT_BYTE, val); /* hard drives */ - - rtc_set_memory(s, 0x12, (hd_table[0] ? 0xf0 : 0) | (hd_table[1] ? 0x0f : 0)); - if (hd_table[0]) - cmos_init_hd(0x19, 0x1b, hd_table[0]->bdrv, s); - if (hd_table[1]) - cmos_init_hd(0x1a, 0x24, hd_table[1]->bdrv, s); - - val = 0; - for (i = 0; i < 4; i++) { - if (hd_table[i]) { - int cylinders, heads, sectors, translation; - /* NOTE: bdrv_get_geometry_hint() returns the physical - geometry. It is always such that: 1 <= sects <= 63, 1 - <= heads <= 16, 1 <= cylinders <= 16383. The BIOS - geometry can be different if a translation is done. */ - translation = bdrv_get_translation_hint(hd_table[i]->bdrv); - if (translation == BIOS_ATA_TRANSLATION_AUTO) { - bdrv_get_geometry_hint(hd_table[i]->bdrv, &cylinders, &heads, §ors); - if (cylinders <= 1024 && heads <= 16 && sectors <= 63) { - /* No translation. */ - translation = 0; - } else { - /* LBA translation. */ - translation = 1; - } - } else { - translation--; - } - val |= translation << (i * 2); - } - } - rtc_set_memory(s, 0x39, val); + arg.rtc_state = s; + arg.idebus0 = idebus0; + arg.idebus1 = idebus1; + qemu_register_reset(pc_cmos_init_late, &arg); } static void handle_a20_line_change(void *opaque, int irq, int level) @@ -104,7 +104,8 @@ void pc_init_ne2k_isa(NICInfo *nd); void pc_audio_init (PCIBus *pci_bus, qemu_irq *pic); #endif void pc_cmos_init(ram_addr_t ram_size, ram_addr_t above_4g_mem_size, - const char *boot_device, DriveInfo **hd_table, + const char *boot_device, + BusState *ide0, BusState *ide1, FDCtrl *floppy_controller, ISADevice *s); void pc_pci_device_init(PCIBus *pci_bus); diff --git a/hw/pc_piix.c b/hw/pc_piix.c index f670fd7a78..519e8a5ccb 100644 --- a/hw/pc_piix.c +++ b/hw/pc_piix.c @@ -79,6 +79,7 @@ static void pc_init1(ram_addr_t ram_size, IsaIrqState *isa_irq_state; DriveInfo *hd[MAX_IDE_BUS * MAX_IDE_DEVS]; FDCtrl *floppy_controller; + BusState *idebus[MAX_IDE_BUS]; ISADevice *rtc_state; pc_cpus_init(cpu_model); @@ -132,18 +133,23 @@ static void pc_init1(ram_addr_t ram_size, } if (pci_enabled) { - pci_piix3_ide_init(pci_bus, hd, piix3_devfn + 1); + PCIDevice *dev; + dev = pci_piix3_ide_init(pci_bus, hd, piix3_devfn + 1); + idebus[0] = qdev_get_child_bus(&dev->qdev, "ide.0"); + idebus[1] = qdev_get_child_bus(&dev->qdev, "ide.1"); } else { for(i = 0; i < MAX_IDE_BUS; i++) { - isa_ide_init(ide_iobase[i], ide_iobase2[i], ide_irq[i], - hd[MAX_IDE_DEVS * i], hd[MAX_IDE_DEVS * i + 1]); + ISADevice *dev; + dev = isa_ide_init(ide_iobase[i], ide_iobase2[i], ide_irq[i], + hd[MAX_IDE_DEVS * i], hd[MAX_IDE_DEVS * i + 1]); + idebus[i] = qdev_get_child_bus(&dev->qdev, "ide.0"); } } pc_audio_init(pci_enabled ? pci_bus : NULL, isa_irq); - pc_cmos_init(below_4g_mem_size, above_4g_mem_size, boot_device, hd, - floppy_controller, rtc_state); + pc_cmos_init(below_4g_mem_size, above_4g_mem_size, boot_device, + idebus[0], idebus[1], floppy_controller, rtc_state); if (pci_enabled && usb_enabled) { usb_uhci_piix3_init(pci_bus, piix3_devfn + 2); diff --git a/hw/pci-hotplug.c b/hw/pci-hotplug.c index c39e640089..fe468d646e 100644 --- a/hw/pci-hotplug.c +++ b/hw/pci-hotplug.c @@ -89,7 +89,10 @@ static int scsi_hot_add(Monitor *mon, DeviceState *adapter, * specified). */ dinfo->unit = qemu_opt_get_number(dinfo->opts, "unit", -1); - scsidev = scsi_bus_legacy_add_drive(scsibus, dinfo, dinfo->unit); + scsidev = scsi_bus_legacy_add_drive(scsibus, dinfo->bdrv, dinfo->unit); + if (!scsidev) { + return -1; + } dinfo->unit = scsidev->id; if (printinfo) @@ -211,7 +214,11 @@ static PCIDevice *qemu_pci_hot_add_storage(Monitor *mon, return NULL; } dev = pci_create(bus, devfn, "virtio-blk-pci"); - qdev_prop_set_drive(&dev->qdev, "drive", dinfo); + if (qdev_prop_set_drive(&dev->qdev, "drive", dinfo->bdrv) < 0) { + qdev_free(&dev->qdev); + dev = NULL; + break; + } if (qdev_init(&dev->qdev) < 0) dev = NULL; break; diff --git a/hw/qdev-properties.c b/hw/qdev-properties.c index 5b7fd77d44..7e3e99efcb 100644 --- a/hw/qdev-properties.c +++ b/hw/qdev-properties.c @@ -305,26 +305,42 @@ PropertyInfo qdev_prop_string = { static int parse_drive(DeviceState *dev, Property *prop, const char *str) { - DriveInfo **ptr = qdev_get_prop_ptr(dev, prop); + BlockDriverState **ptr = qdev_get_prop_ptr(dev, prop); + BlockDriverState *bs; - *ptr = drive_get_by_id(str); - if (*ptr == NULL) + bs = bdrv_find(str); + if (bs == NULL) return -ENOENT; + if (bdrv_attach(bs, dev) < 0) + return -EEXIST; + *ptr = bs; return 0; } +static void free_drive(DeviceState *dev, Property *prop) +{ + BlockDriverState **ptr = qdev_get_prop_ptr(dev, prop); + + if (*ptr) { + bdrv_detach(*ptr, dev); + blockdev_auto_del(*ptr); + } +} + static int print_drive(DeviceState *dev, Property *prop, char *dest, size_t len) { - DriveInfo **ptr = qdev_get_prop_ptr(dev, prop); - return snprintf(dest, len, "%s", (*ptr) ? (*ptr)->id : "<null>"); + BlockDriverState **ptr = qdev_get_prop_ptr(dev, prop); + return snprintf(dest, len, "%s", + *ptr ? bdrv_get_device_name(*ptr) : "<null>"); } PropertyInfo qdev_prop_drive = { .name = "drive", .type = PROP_TYPE_DRIVE, - .size = sizeof(DriveInfo*), + .size = sizeof(BlockDriverState *), .parse = parse_drive, .print = print_drive, + .free = free_drive, }; /* --- character device --- */ @@ -647,11 +663,28 @@ 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) +int qdev_prop_set_drive(DeviceState *dev, const char *name, BlockDriverState *value) { + int res; + + res = bdrv_attach(value, dev); + if (res < 0) { + error_report("Can't attach drive %s to %s.%s: %s", + bdrv_get_device_name(value), + dev->id ? dev->id : dev->info->name, + name, strerror(-res)); + return -1; + } qdev_prop_set(dev, name, &value, PROP_TYPE_DRIVE); + return 0; } +void qdev_prop_set_drive_nofail(DeviceState *dev, const char *name, BlockDriverState *value) +{ + if (qdev_prop_set_drive(dev, name, value) < 0) { + exit(1); + } +} void qdev_prop_set_chr(DeviceState *dev, const char *name, CharDriverState *value) { qdev_prop_set(dev, name, &value, PROP_TYPE_CHR); @@ -253,8 +253,8 @@ extern PropertyInfo qdev_prop_pci_devfn; DEFINE_PROP(_n, _s, _f, qdev_prop_netdev, VLANClientState*) #define DEFINE_PROP_VLAN(_n, _s, _f) \ DEFINE_PROP(_n, _s, _f, qdev_prop_vlan, VLANState*) -#define DEFINE_PROP_DRIVE(_n, _s, _f) \ - DEFINE_PROP(_n, _s, _f, qdev_prop_drive, DriveInfo*) +#define DEFINE_PROP_DRIVE(_n, _s, _f) \ + DEFINE_PROP(_n, _s, _f, qdev_prop_drive, BlockDriverState *) #define DEFINE_PROP_MACADDR(_n, _s, _f) \ DEFINE_PROP(_n, _s, _f, qdev_prop_macaddr, MACAddr) @@ -275,7 +275,8 @@ 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); -void qdev_prop_set_drive(DeviceState *dev, const char *name, DriveInfo *value); +int qdev_prop_set_drive(DeviceState *dev, const char *name, BlockDriverState *value) QEMU_WARN_UNUSED_RESULT; +void qdev_prop_set_drive_nofail(DeviceState *dev, const char *name, BlockDriverState *value); void qdev_prop_set_macaddr(DeviceState *dev, const char *name, uint8_t *value); /* FIXME: Remove opaque pointer properties. */ void qdev_prop_set_ptr(DeviceState *dev, const char *name, void *value); diff --git a/hw/s390-virtio.c b/hw/s390-virtio.c index 898f442355..6af58e23af 100644 --- a/hw/s390-virtio.c +++ b/hw/s390-virtio.c @@ -262,7 +262,7 @@ static void s390_init(ram_addr_t ram_size, } dev = qdev_create((BusState *)s390_bus, "virtio-blk-s390"); - qdev_prop_set_drive(dev, "drive", dinfo); + qdev_prop_set_drive_nofail(dev, "drive", dinfo->bdrv); qdev_init_nofail(dev); } } diff --git a/hw/scsi-bus.c b/hw/scsi-bus.c index 24bd0602ef..b84b9b98b5 100644 --- a/hw/scsi-bus.c +++ b/hw/scsi-bus.c @@ -83,33 +83,39 @@ void scsi_qdev_register(SCSIDeviceInfo *info) } /* handle legacy '-drive if=scsi,...' cmd line args */ -/* FIXME callers should check for failure, but don't */ -SCSIDevice *scsi_bus_legacy_add_drive(SCSIBus *bus, DriveInfo *dinfo, int unit) +SCSIDevice *scsi_bus_legacy_add_drive(SCSIBus *bus, BlockDriverState *bdrv, int unit) { const char *driver; DeviceState *dev; - driver = bdrv_is_sg(dinfo->bdrv) ? "scsi-generic" : "scsi-disk"; + driver = bdrv_is_sg(bdrv) ? "scsi-generic" : "scsi-disk"; dev = qdev_create(&bus->qbus, driver); qdev_prop_set_uint32(dev, "scsi-id", unit); - qdev_prop_set_drive(dev, "drive", dinfo); + if (qdev_prop_set_drive(dev, "drive", bdrv) < 0) { + qdev_free(dev); + return NULL; + } if (qdev_init(dev) < 0) return NULL; return DO_UPCAST(SCSIDevice, qdev, dev); } -void scsi_bus_legacy_handle_cmdline(SCSIBus *bus) +int scsi_bus_legacy_handle_cmdline(SCSIBus *bus) { DriveInfo *dinfo; - int unit; + int res = 0, unit; for (unit = 0; unit < MAX_SCSI_DEVS; unit++) { dinfo = drive_get(IF_SCSI, bus->busnr, unit); if (dinfo == NULL) { continue; } - scsi_bus_legacy_add_drive(bus, dinfo, unit); + if (!scsi_bus_legacy_add_drive(bus, dinfo->bdrv, unit)) { + res = -1; + break; + } } + return res; } void scsi_dev_clear_sense(SCSIDevice *dev) diff --git a/hw/scsi-disk.c b/hw/scsi-disk.c index 2b3898435c..3e41011ccb 100644 --- a/hw/scsi-disk.c +++ b/hw/scsi-disk.c @@ -1043,26 +1043,26 @@ static void scsi_destroy(SCSIDevice *dev) SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, dev); scsi_disk_purge_requests(s); - drive_uninit(s->qdev.conf.dinfo); + blockdev_mark_auto_del(s->qdev.conf.bs); } static int scsi_disk_initfn(SCSIDevice *dev) { SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, dev); + int is_cd; + DriveInfo *dinfo; - if (!s->qdev.conf.dinfo || !s->qdev.conf.dinfo->bdrv) { + if (!s->qdev.conf.bs) { error_report("scsi-disk: drive property not set"); return -1; } - s->bs = s->qdev.conf.dinfo->bdrv; + s->bs = s->qdev.conf.bs; + is_cd = bdrv_get_type_hint(s->bs) == BDRV_TYPE_CDROM; 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"); - } + /* try to fall back to value set with legacy -drive serial=... */ + dinfo = drive_get_by_blockdev(s->bs); + s->serial = qemu_strdup(*dinfo->serial ? dinfo->serial : "0"); } if (!s->version) { @@ -1074,7 +1074,7 @@ static int scsi_disk_initfn(SCSIDevice *dev) return -1; } - if (bdrv_get_type_hint(s->bs) == BDRV_TYPE_CDROM) { + if (is_cd) { s->qdev.blocksize = 2048; } else { s->qdev.blocksize = s->qdev.conf.logical_block_size; @@ -1083,6 +1083,7 @@ static int scsi_disk_initfn(SCSIDevice *dev) s->qdev.type = TYPE_DISK; qemu_add_vm_change_state_handler(scsi_dma_restart_cb, s); + bdrv_set_removable(s->bs, is_cd); return 0; } diff --git a/hw/scsi-generic.c b/hw/scsi-generic.c index e31060e944..3915e7844e 100644 --- a/hw/scsi-generic.c +++ b/hw/scsi-generic.c @@ -453,7 +453,7 @@ static void scsi_destroy(SCSIDevice *d) r = DO_UPCAST(SCSIGenericReq, req, QTAILQ_FIRST(&s->qdev.requests)); scsi_remove_request(r); } - drive_uninit(s->qdev.conf.dinfo); + blockdev_mark_auto_del(s->qdev.conf.bs); } static int scsi_generic_initfn(SCSIDevice *dev) @@ -462,11 +462,11 @@ static int scsi_generic_initfn(SCSIDevice *dev) int sg_version; struct sg_scsi_id scsiid; - if (!s->qdev.conf.dinfo || !s->qdev.conf.dinfo->bdrv) { + if (!s->qdev.conf.bs) { error_report("scsi-generic: drive property not set"); return -1; } - s->bs = s->qdev.conf.dinfo->bdrv; + s->bs = s->qdev.conf.bs; /* check we are really using a /dev/sg* file */ if (!bdrv_is_sg(s->bs)) { @@ -509,6 +509,7 @@ static int scsi_generic_initfn(SCSIDevice *dev) DPRINTF("block size %d\n", s->qdev.blocksize); s->driver_status = 0; memset(s->sensebuf, 0, sizeof(s->sensebuf)); + bdrv_set_removable(s->bs, 0); return 0; } @@ -97,8 +97,8 @@ static inline SCSIBus *scsi_bus_from_device(SCSIDevice *d) return DO_UPCAST(SCSIBus, qbus, d->qdev.parent_bus); } -SCSIDevice *scsi_bus_legacy_add_drive(SCSIBus *bus, DriveInfo *dinfo, int unit); -void scsi_bus_legacy_handle_cmdline(SCSIBus *bus); +SCSIDevice *scsi_bus_legacy_add_drive(SCSIBus *bus, BlockDriverState *bdrv, int unit); +int scsi_bus_legacy_handle_cmdline(SCSIBus *bus); void scsi_dev_clear_sense(SCSIDevice *dev); void scsi_dev_set_sense(SCSIDevice *dev, uint8_t key); diff --git a/hw/usb-msd.c b/hw/usb-msd.c index 003bd8a4cd..65e9624e54 100644 --- a/hw/usb-msd.c +++ b/hw/usb-msd.c @@ -522,22 +522,37 @@ static void usb_msd_password_cb(void *opaque, int err) static int usb_msd_initfn(USBDevice *dev) { MSDState *s = DO_UPCAST(MSDState, dev, dev); + BlockDriverState *bs = s->conf.bs; - if (!s->conf.dinfo || !s->conf.dinfo->bdrv) { + if (!bs) { error_report("usb-msd: drive property not set"); return -1; } + /* + * Hack alert: this pretends to be a block device, but it's really + * a SCSI bus that can serve only a single device, which it + * creates automatically. But first it needs to detach from its + * blockdev, or else scsi_bus_legacy_add_drive() dies when it + * attaches again. + * + * The hack is probably a bad idea. + */ + bdrv_detach(bs, &s->dev.qdev); + s->conf.bs = NULL; + s->dev.speed = USB_SPEED_FULL; scsi_bus_new(&s->bus, &s->dev.qdev, 0, 1, usb_msd_command_complete); - s->scsi_dev = scsi_bus_legacy_add_drive(&s->bus, s->conf.dinfo, 0); + s->scsi_dev = scsi_bus_legacy_add_drive(&s->bus, bs, 0); + if (!s->scsi_dev) { + return -1; + } s->bus.qbus.allow_hotplug = 0; usb_msd_handle_reset(dev); - if (bdrv_key_required(s->conf.dinfo->bdrv)) { + if (bdrv_key_required(bs)) { if (cur_mon) { - monitor_read_bdrv_key_start(cur_mon, s->conf.dinfo->bdrv, - usb_msd_password_cb, s); + monitor_read_bdrv_key_start(cur_mon, bs, usb_msd_password_cb, s); s->dev.auto_attach = 0; } else { autostart = 0; @@ -595,7 +610,10 @@ static USBDevice *usb_msd_init(const char *filename) if (!dev) { return NULL; } - qdev_prop_set_drive(&dev->qdev, "drive", dinfo); + if (qdev_prop_set_drive(&dev->qdev, "drive", dinfo->bdrv) < 0) { + qdev_free(&dev->qdev); + return NULL; + } if (qdev_init(&dev->qdev) < 0) return NULL; diff --git a/hw/virtio-blk.c b/hw/virtio-blk.c index 0bf929aba9..f0b3ba5cb1 100644 --- a/hw/virtio-blk.c +++ b/hw/virtio-blk.c @@ -489,7 +489,7 @@ VirtIODevice *virtio_blk_init(DeviceState *dev, BlockConf *conf) s->vdev.get_config = virtio_blk_update_config; s->vdev.get_features = virtio_blk_get_features; s->vdev.reset = virtio_blk_reset; - s->bs = conf->dinfo->bdrv; + s->bs = conf->bs; s->conf = conf; s->rq = NULL; s->sector_mask = (s->conf->logical_block_size / BDRV_SECTOR_SIZE) - 1; @@ -500,6 +500,7 @@ VirtIODevice *virtio_blk_init(DeviceState *dev, BlockConf *conf) qemu_add_vm_change_state_handler(virtio_blk_dma_restart_cb, s); register_savevm("virtio-blk", virtio_blk_id++, 2, virtio_blk_save, virtio_blk_load, s); + bdrv_set_removable(s->bs, 0); return &s->vdev; } diff --git a/hw/virtio-pci.c b/hw/virtio-pci.c index d1303b1a38..c6ef8254e3 100644 --- a/hw/virtio-pci.c +++ b/hw/virtio-pci.c @@ -547,7 +547,7 @@ static int virtio_blk_init_pci(PCIDevice *pci_dev) proxy->class_code != PCI_CLASS_STORAGE_OTHER) proxy->class_code = PCI_CLASS_STORAGE_SCSI; - if (!proxy->block.dinfo) { + if (!proxy->block.bs) { error_report("virtio-blk-pci: drive property not set"); return -1; } @@ -571,7 +571,7 @@ static int virtio_blk_exit_pci(PCIDevice *pci_dev) { VirtIOPCIProxy *proxy = DO_UPCAST(VirtIOPCIProxy, pci_dev, pci_dev); - drive_uninit(proxy->block.dinfo); + blockdev_mark_auto_del(proxy->block.bs); return virtio_exit_pci(pci_dev); } |