diff options
author | Avi Kivity <avi@redhat.com> | 2009-10-06 10:34:05 +0200 |
---|---|---|
committer | Avi Kivity <avi@redhat.com> | 2009-10-06 10:34:05 +0200 |
commit | ac7e70d61b19ae6971d98424b248b137fbc96272 (patch) | |
tree | 58f5ea42056064ecde22b561716307dd96b03886 | |
parent | Merge commit 'e3936fa574d9fbe241acdc76b5195b048567537e' into upstream-merge (diff) | |
parent | pci: windup acpi-based hotplug (diff) | |
download | qemu-kvm-ac7e70d61b19ae6971d98424b248b137fbc96272.tar.gz qemu-kvm-ac7e70d61b19ae6971d98424b248b137fbc96272.tar.bz2 qemu-kvm-ac7e70d61b19ae6971d98424b248b137fbc96272.zip |
Merge commit '3f84865ade594a2ec1ef613ab5fd11949f3d49de' into upstream-merge
* commit '3f84865ade594a2ec1ef613ab5fd11949f3d49de':
pci: windup acpi-based hotplug
pci: hotplug windup
scsi: hotplug windup
usb: hotplug windup
qdev hotplug: infrastructure and monitor commands.
switch qemu-config to qemu_error
usb: hook unplug into qdev, cleanups + fixes.
Conflicts:
hw/acpi.c
hw/pc.c
hw/pc.h
hw/pci-hotplug.c
sysemu.h
Signed-off-by: Avi Kivity <avi@redhat.com>
-rw-r--r-- | hw/acpi.c | 41 | ||||
-rw-r--r-- | hw/pc.c | 3 | ||||
-rw-r--r-- | hw/pc.h | 2 | ||||
-rw-r--r-- | hw/pci-hotplug.c | 17 | ||||
-rw-r--r-- | hw/pci.c | 25 | ||||
-rw-r--r-- | hw/pci.h | 2 | ||||
-rw-r--r-- | hw/qdev.c | 79 | ||||
-rw-r--r-- | hw/qdev.h | 12 | ||||
-rw-r--r-- | hw/scsi-bus.c | 2 | ||||
-rw-r--r-- | hw/usb-bt.c | 1 | ||||
-rw-r--r-- | hw/usb-bus.c | 59 | ||||
-rw-r--r-- | hw/usb-hid.c | 1 | ||||
-rw-r--r-- | hw/usb-hub.c | 6 | ||||
-rw-r--r-- | hw/usb-msd.c | 3 | ||||
-rw-r--r-- | hw/usb-serial.c | 1 | ||||
-rw-r--r-- | hw/usb-wacom.c | 1 | ||||
-rw-r--r-- | hw/usb.h | 2 | ||||
-rw-r--r-- | qemu-config.c | 9 | ||||
-rw-r--r-- | qemu-monitor.hx | 20 | ||||
-rw-r--r-- | sysemu.h | 5 | ||||
-rw-r--r-- | vl.c | 2 |
21 files changed, 227 insertions, 66 deletions
@@ -713,11 +713,21 @@ static uint32_t pciej_read(void *opaque, uint32_t addr) static void pciej_write(void *opaque, uint32_t addr, uint32_t val) { -#if defined (TARGET_I386) + BusState *bus = opaque; + DeviceState *qdev; + PCIDevice *dev; int slot = ffs(val) - 1; - pci_device_hot_remove_success(0, slot); + QLIST_FOREACH(qdev, &bus->children, sibling) { + dev = DO_UPCAST(PCIDevice, qdev, qdev); + if (PCI_SLOT(dev->devfn) == slot) { +#if defined (TARGET_I386) + pci_device_hot_remove_success(dev); #endif + qdev_free(qdev); + } + } + #if defined(DEBUG) printf("pciej write %x <== %d\n", addr, val); @@ -726,9 +736,9 @@ static void pciej_write(void *opaque, uint32_t addr, uint32_t val) static const char *model; -static void piix4_device_hot_add(int bus, int slot, int state); +static int piix4_device_hotplug(PCIDevice *dev, int state); -void piix4_acpi_system_hot_add_init(const char *cpu_model) +void piix4_acpi_system_hot_add_init(PCIBus *bus, const char *cpu_model) { int i = 0, cpus = smp_cpus; @@ -745,12 +755,12 @@ void piix4_acpi_system_hot_add_init(const char *cpu_model) register_ioport_write(PCI_BASE, 8, 4, pcihotplug_write, &pci0_status); register_ioport_read(PCI_BASE, 8, 4, pcihotplug_read, &pci0_status); - register_ioport_write(PCI_EJ_BASE, 4, 4, pciej_write, NULL); - register_ioport_read(PCI_EJ_BASE, 4, 4, pciej_read, NULL); + register_ioport_write(PCI_EJ_BASE, 4, 4, pciej_write, bus); + register_ioport_read(PCI_EJ_BASE, 4, 4, pciej_read, bus); model = cpu_model; - qemu_system_device_hot_add_register(piix4_device_hot_add); + pci_bus_hotplug(bus, piix4_device_hotplug); } #if defined(TARGET_I386) @@ -802,8 +812,10 @@ static void disable_device(struct pci_status *p, struct gpe_regs *g, int slot) p->down |= (1 << slot); } -static void piix4_device_hot_add(int bus, int slot, int state) +static int piix4_device_hotplug(PCIDevice *dev, int state) { + int slot = PCI_SLOT(dev->devfn); + pci0_status.up = 0; pci0_status.down = 0; if (state) @@ -814,18 +826,7 @@ static void piix4_device_hot_add(int bus, int slot, int state) qemu_set_irq(pm_state->irq, 1); qemu_set_irq(pm_state->irq, 0); } -} - -static qemu_system_device_hot_add_t device_hot_add_callback; -void qemu_system_device_hot_add_register(qemu_system_device_hot_add_t callback) -{ - device_hot_add_callback = callback; -} - -void qemu_system_device_hot_add(int pcibus, int slot, int state) -{ - if (device_hot_add_callback) - device_hot_add_callback(pcibus, slot, state); + return 0; } struct acpi_table_header @@ -1382,8 +1382,6 @@ static void pc_init1(ram_addr_t ram_size, pci_nic_init(nd, "rtl8139", NULL); } - piix4_acpi_system_hot_add_init(cpu_model); - if (drive_get_max_bus(IF_IDE) >= MAX_IDE_BUS) { fprintf(stderr, "qemu: too many IDE bus\n"); exit(1); @@ -1434,6 +1432,7 @@ static void pc_init1(ram_addr_t ram_size, qdev_prop_set_ptr(eeprom, "data", eeprom_buf + (i * 256)); qdev_init(eeprom); } + piix4_acpi_system_hot_add_init(pci_bus, cpu_model); } if (i440fx_state) { @@ -113,7 +113,7 @@ int acpi_table_add(const char *table_desc); i2c_bus *piix4_pm_init(PCIBus *bus, int devfn, uint32_t smb_io_base, qemu_irq sci_irq); void piix4_smbus_register_device(SMBusDevice *dev, uint8_t addr); -void piix4_acpi_system_hot_add_init(const char *model); +void piix4_acpi_system_hot_add_init(PCIBus *bus, const char *model); /* hpet.c */ extern int no_hpet; diff --git a/hw/pci-hotplug.c b/hw/pci-hotplug.c index 7a1fd5bf5..282d15d35 100644 --- a/hw/pci-hotplug.c +++ b/hw/pci-hotplug.c @@ -229,8 +229,6 @@ void pci_device_hot_add(Monitor *mon, const QDict *qdict) monitor_printf(mon, "invalid type: %s\n", type); if (dev) { - qemu_system_device_hot_add(pci_bus_num(dev->bus), - PCI_SLOT(dev->devfn), 1); monitor_printf(mon, "OK domain %d, bus %d, slot %d, function %d\n", 0, pci_bus_num(dev->bus), PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn)); @@ -254,8 +252,7 @@ void pci_device_hot_remove(Monitor *mon, const char *pci_addr) monitor_printf(mon, "slot %d empty\n", slot); return; } - - qemu_system_device_hot_add(bus, slot, 0); + qdev_unplug(&d->qdev); } void do_pci_device_hot_remove(Monitor *mon, const QDict *qdict) @@ -274,21 +271,15 @@ static int pci_match_fn(void *dev_private, void *arg) /* * OS has executed _EJ0 method, we now can remove the device */ -void pci_device_hot_remove_success(int pcibus, int slot) +void pci_device_hot_remove_success(PCIDevice *d) { - PCIDevice *d = pci_find_device(pcibus, slot, 0); int class_code; #ifdef CONFIG_KVM_DEVICE_ASSIGNMENT AssignedDevInfo *adev; #endif - if (!d) { - monitor_printf(cur_mon, "invalid slot %d\n", slot); - return; - } - #ifdef CONFIG_KVM_DEVICE_ASSIGNMENT - adev = get_assigned_device(pcibus, slot); + adev = get_assigned_device(pci_bus_num(d->bus), d->devfn >> 3); if (adev) { qemu_pci_hot_deassign_device(cur_mon, adev); return; @@ -305,7 +296,5 @@ void pci_device_hot_remove_success(int pcibus, int slot) destroy_nic(pci_match_fn, d); break; } - - qdev_free(&d->qdev); } @@ -44,6 +44,7 @@ struct PCIBus { int devfn_min; pci_set_irq_fn set_irq; pci_map_irq_fn map_irq; + pci_hotplug_fn hotplug; uint32_t config_reg; /* XXX: suppress */ void *irq_opaque; PCIDevice *devices[256]; @@ -135,6 +136,12 @@ void pci_bus_irqs(PCIBus *bus, pci_set_irq_fn set_irq, pci_map_irq_fn map_irq, bus->irq_count = qemu_mallocz(nirq * sizeof(bus->irq_count[0])); } +void pci_bus_hotplug(PCIBus *bus, pci_hotplug_fn hotplug) +{ + bus->qbus.allow_hotplug = 1; + bus->hotplug = hotplug; +} + PCIBus *pci_register_bus(DeviceState *parent, const char *name, pci_set_irq_fn set_irq, pci_map_irq_fn map_irq, void *irq_opaque, int devfn_min, int nirq) @@ -1062,19 +1069,33 @@ static int pci_qdev_init(DeviceState *qdev, DeviceInfo *base) PCIDevice *pci_dev = (PCIDevice *)qdev; PCIDeviceInfo *info = container_of(base, PCIDeviceInfo, qdev); PCIBus *bus; - int devfn; + int devfn, rc; bus = FROM_QBUS(PCIBus, qdev_get_parent_bus(qdev)); devfn = pci_dev->devfn; pci_dev = do_pci_register_device(pci_dev, bus, base->name, devfn, info->config_read, info->config_write); assert(pci_dev); - return info->init(pci_dev); + rc = info->init(pci_dev); + if (rc != 0) + return rc; + if (qdev->hotplugged) + bus->hotplug(pci_dev, 1); + return 0; +} + +static int pci_unplug_device(DeviceState *qdev) +{ + PCIDevice *dev = DO_UPCAST(PCIDevice, qdev, qdev); + + dev->bus->hotplug(dev, 0); + return 0; } void pci_qdev_register(PCIDeviceInfo *info) { info->qdev.init = pci_qdev_init; + info->qdev.unplug = pci_unplug_device; info->qdev.exit = pci_unregister_device; info->qdev.bus_info = &pci_bus_info; qdev_register(&info->qdev); @@ -293,11 +293,13 @@ int pci_access_cap_config(PCIDevice *pci_dev, uint32_t address, int len); typedef void (*pci_set_irq_fn)(void *opaque, int irq_num, int level); typedef int (*pci_map_irq_fn)(PCIDevice *pci_dev, int irq_num); +typedef int (*pci_hotplug_fn)(PCIDevice *pci_dev, int state); void pci_bus_new_inplace(PCIBus *bus, DeviceState *parent, const char *name, int devfn_min); PCIBus *pci_bus_new(DeviceState *parent, const char *name, int devfn_min); void pci_bus_irqs(PCIBus *bus, pci_set_irq_fn set_irq, pci_map_irq_fn map_irq, void *irq_opaque, int nirq); +void pci_bus_hotplug(PCIBus *bus, pci_hotplug_fn hotplug); PCIBus *pci_register_bus(DeviceState *parent, const char *name, pci_set_irq_fn set_irq, pci_map_irq_fn map_irq, void *irq_opaque, int devfn_min, int nirq); @@ -31,6 +31,8 @@ #include "monitor.h" /* This is a nasty hack to allow passing a NULL bus to qdev_create. */ +static int qdev_hotplug = 0; + static BusState *main_system_bus; static DeviceInfo *device_info_list; @@ -102,6 +104,10 @@ DeviceState *qdev_create(BusState *bus, const char *name) qdev_prop_set_defaults(dev, dev->parent_bus->info->props); qdev_prop_set_compat(dev); QLIST_INSERT_HEAD(&bus->children, dev, sibling); + if (qdev_hotplug) { + assert(bus->allow_hotplug); + dev->hotplugged = 1; + } dev->state = DEV_STATE_CREATED; return dev; } @@ -192,6 +198,11 @@ DeviceState *qdev_device_add(QemuOpts *opts) path ? path : info->bus_info->name, info->name); return NULL; } + if (qdev_hotplug && !bus->allow_hotplug) { + qemu_error("Bus %s does not support hotplugging\n", + bus->name); + return NULL; + } /* create device, set properties */ qdev = qdev_create(bus, driver); @@ -229,6 +240,24 @@ int qdev_init(DeviceState *dev) return 0; } +int qdev_unplug(DeviceState *dev) +{ + if (!dev->parent_bus->allow_hotplug) { + qemu_error("Bus %s does not support hotplugging\n", + dev->parent_bus->name); + return -1; + } + return dev->info->unplug(dev); +} + +/* can be used as ->unplug() callback for the simple cases */ +int qdev_simple_unplug_cb(DeviceState *dev) +{ + /* just zap it */ + qdev_free(dev); + return 0; +} + /* Unlink device from bus and free the structure. */ void qdev_free(DeviceState *dev) { @@ -252,6 +281,15 @@ void qdev_free(DeviceState *dev) qemu_free(dev); } +void qdev_machine_creation_done(void) +{ + /* + * ok, initial machine setup is done, starting from now we can + * only create hotpluggable devices + */ + qdev_hotplug = 1; +} + /* Get a character (serial) device interface. */ CharDriverState *qdev_init_chardev(DeviceState *dev) { @@ -370,6 +408,24 @@ static BusState *qbus_find_recursive(BusState *bus, const char *name, return NULL; } +static DeviceState *qdev_find_recursive(BusState *bus, const char *id) +{ + DeviceState *dev, *ret; + BusState *child; + + QLIST_FOREACH(dev, &bus->children, sibling) { + if (dev->id && strcmp(dev->id, id) == 0) + return dev; + QLIST_FOREACH(child, &dev->child_bus, sibling) { + ret = qdev_find_recursive(child, id); + if (ret) { + return ret; + } + } + } + return NULL; +} + static void qbus_list_bus(DeviceState *dev, char *dest, int len) { BusState *child; @@ -647,3 +703,26 @@ void do_info_qdm(Monitor *mon) monitor_printf(mon, "%s\n", msg); } } + +void do_device_add(Monitor *mon, const QDict *qdict) +{ + QemuOpts *opts; + + opts = qemu_opts_parse(&qemu_device_opts, + qdict_get_str(qdict, "config"), "driver"); + if (opts) + qdev_device_add(opts); +} + +void do_device_del(Monitor *mon, const QDict *qdict) +{ + const char *id = qdict_get_str(qdict, "id"); + DeviceState *dev; + + dev = qdev_find_recursive(main_system_bus, id); + if (NULL == dev) { + qemu_error("Device '%s' not found\n", id); + return; + } + qdev_unplug(dev); +} @@ -29,6 +29,7 @@ enum DevState { struct DeviceState { const char *id; enum DevState state; + int hotplugged; DeviceInfo *info; BusState *parent_bus; int num_gpio_out; @@ -53,6 +54,7 @@ struct BusState { DeviceState *parent; BusInfo *info; const char *name; + int allow_hotplug; int qdev_allocated; QLIST_HEAD(, DeviceState) children; QLIST_ENTRY(BusState) sibling; @@ -98,7 +100,10 @@ struct CompatProperty { DeviceState *qdev_create(BusState *bus, const char *name); DeviceState *qdev_device_add(QemuOpts *opts); int qdev_init(DeviceState *dev); +int qdev_unplug(DeviceState *dev); void qdev_free(DeviceState *dev); +int qdev_simple_unplug_cb(DeviceState *dev); +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); @@ -108,7 +113,7 @@ BusState *qdev_get_child_bus(DeviceState *dev, const char *name); /*** Device API. ***/ typedef int (*qdev_initfn)(DeviceState *dev, DeviceInfo *info); -typedef int (*qdev_exitfn)(DeviceState *dev); +typedef int (*qdev_event)(DeviceState *dev); struct DeviceInfo { const char *name; @@ -126,7 +131,8 @@ struct DeviceInfo { /* Private to qdev / bus. */ qdev_initfn init; - qdev_exitfn exit; + qdev_event unplug; + qdev_event exit; BusInfo *bus_info; struct DeviceInfo *next; }; @@ -165,6 +171,8 @@ void qbus_free(BusState *bus); void do_info_qtree(Monitor *mon); void do_info_qdm(Monitor *mon); +void do_device_add(Monitor *mon, const QDict *qdict); +void do_device_del(Monitor *mon, const QDict *qdict); /*** qdev-properties.c ***/ diff --git a/hw/scsi-bus.c b/hw/scsi-bus.c index 27defc410..fe8991e9c 100644 --- a/hw/scsi-bus.c +++ b/hw/scsi-bus.c @@ -23,6 +23,7 @@ void scsi_bus_new(SCSIBus *bus, DeviceState *host, int tcq, int ndev, bus->tcq = tcq; bus->ndev = ndev; bus->complete = complete; + bus->qbus.allow_hotplug = 1; } static int scsi_qdev_init(DeviceState *qdev, DeviceInfo *base) @@ -75,6 +76,7 @@ void scsi_qdev_register(SCSIDeviceInfo *info) { info->qdev.bus_info = &scsi_bus_info; info->qdev.init = scsi_qdev_init; + info->qdev.unplug = qdev_simple_unplug_cb; info->qdev.exit = scsi_qdev_exit; qdev_register(&info->qdev); } diff --git a/hw/usb-bt.c b/hw/usb-bt.c index 70fd4dd53..18d7a98b4 100644 --- a/hw/usb-bt.c +++ b/hw/usb-bt.c @@ -614,7 +614,6 @@ static void usb_bt_handle_destroy(USBDevice *dev) s->hci->opaque = NULL; s->hci->evt_recv = NULL; s->hci->acl_recv = NULL; - qemu_free(s); } static int usb_bt_initfn(USBDevice *dev) diff --git a/hw/usb-bus.c b/hw/usb-bus.c index 2cac1e85b..0c6327935 100644 --- a/hw/usb-bus.c +++ b/hw/usb-bus.c @@ -18,6 +18,7 @@ void usb_bus_new(USBBus *bus, DeviceState *host) { qbus_create_inplace(&bus->qbus, &usb_bus_info, host, NULL); bus->busnr = next_usb_bus++; + bus->qbus.allow_hotplug = 1; /* Yes, we can */ QTAILQ_INIT(&bus->free); QTAILQ_INIT(&bus->used); QTAILQ_INSERT_TAIL(&busses, bus, next); @@ -50,10 +51,23 @@ static int usb_qdev_init(DeviceState *qdev, DeviceInfo *base) return rc; } +static int usb_qdev_exit(DeviceState *qdev) +{ + USBDevice *dev = DO_UPCAST(USBDevice, qdev, qdev); + + usb_device_detach(dev); + if (dev->info->handle_destroy) { + dev->info->handle_destroy(dev); + } + return 0; +} + void usb_qdev_register(USBDeviceInfo *info) { info->qdev.bus_info = &usb_bus_info; info->qdev.init = usb_qdev_init; + info->qdev.unplug = qdev_simple_unplug_cb; + info->qdev.exit = usb_qdev_exit; qdev_register(&info->qdev); } @@ -101,6 +115,14 @@ void usb_register_port(USBBus *bus, USBPort *port, void *opaque, int index, bus->nfree++; } +void usb_unregister_port(USBBus *bus, USBPort *port) +{ + if (port->dev) + qdev_free(&port->dev->qdev); + QTAILQ_REMOVE(&bus->free, port, next); + bus->nfree--; +} + static void do_attach(USBDevice *dev) { USBBus *bus = usb_bus_from_device(dev); @@ -136,6 +158,34 @@ int usb_device_attach(USBDevice *dev) return 0; } +int usb_device_detach(USBDevice *dev) +{ + USBBus *bus = usb_bus_from_device(dev); + USBPort *port; + + if (!dev->attached) { + fprintf(stderr, "Warning: tried to detach unattached usb device %s\n", + dev->devname); + return -1; + } + dev->attached--; + + QTAILQ_FOREACH(port, &bus->used, next) { + if (port->dev == dev) + break; + } + assert(port != NULL); + + QTAILQ_REMOVE(&bus->used, port, next); + bus->nused--; + + usb_attach(port, NULL); + + QTAILQ_INSERT_TAIL(&bus->free, port, next); + bus->nfree++; + return 0; +} + int usb_device_delete_addr(int busnr, int addr) { USBBus *bus; @@ -152,16 +202,9 @@ int usb_device_delete_addr(int busnr, int addr) } if (!port) return -1; - dev = port->dev; - QTAILQ_REMOVE(&bus->used, port, next); - bus->nused--; - - usb_attach(port, NULL); - dev->info->handle_destroy(dev); - QTAILQ_INSERT_TAIL(&bus->free, port, next); - bus->nfree++; + qdev_free(&dev->qdev); return 0; } diff --git a/hw/usb-hid.c b/hw/usb-hid.c index 3bf06fa41..d1cc45e02 100644 --- a/hw/usb-hid.c +++ b/hw/usb-hid.c @@ -843,7 +843,6 @@ static void usb_hid_handle_destroy(USBDevice *dev) if (s->kind != USB_KEYBOARD) qemu_remove_mouse_event_handler(s->ptr.eh_entry); /* TODO: else */ - qemu_free(s); } static int usb_hid_initfn(USBDevice *dev, int kind) diff --git a/hw/usb-hub.c b/hw/usb-hub.c index 0a3998646..e5a093877 100644 --- a/hw/usb-hub.c +++ b/hw/usb-hub.c @@ -517,8 +517,12 @@ static int usb_hub_handle_packet(USBDevice *dev, USBPacket *p) static void usb_hub_handle_destroy(USBDevice *dev) { USBHubState *s = (USBHubState *)dev; + int i; - qemu_free(s); + for (i = 0; i < s->nb_ports; i++) { + usb_unregister_port(usb_bus_from_device(dev), + &s->ports[i].port); + } } static int usb_hub_initfn(USBDevice *dev) diff --git a/hw/usb-msd.c b/hw/usb-msd.c index 6b9c8a5bd..a19b31d68 100644 --- a/hw/usb-msd.c +++ b/hw/usb-msd.c @@ -512,9 +512,7 @@ static void usb_msd_handle_destroy(USBDevice *dev) { MSDState *s = (MSDState *)dev; - s->scsi_dev->info->destroy(s->scsi_dev); drive_uninit(s->dinfo->bdrv); - qemu_free(s); } static int usb_msd_initfn(USBDevice *dev) @@ -529,6 +527,7 @@ static int usb_msd_initfn(USBDevice *dev) 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->dinfo, 0); + s->bus.qbus.allow_hotplug = 0; usb_msd_handle_reset(dev); return 0; } diff --git a/hw/usb-serial.c b/hw/usb-serial.c index 091ab2cbc..e2379c4d5 100644 --- a/hw/usb-serial.c +++ b/hw/usb-serial.c @@ -486,7 +486,6 @@ static void usb_serial_handle_destroy(USBDevice *dev) USBSerialState *s = (USBSerialState *)dev; qemu_chr_close(s->cs); - qemu_free(s); } static int usb_serial_can_read(void *opaque) diff --git a/hw/usb-wacom.c b/hw/usb-wacom.c index 55f06bfd9..3ea72411a 100644 --- a/hw/usb-wacom.c +++ b/hw/usb-wacom.c @@ -389,7 +389,6 @@ static void usb_wacom_handle_destroy(USBDevice *dev) USBWacomState *s = (USBWacomState *) dev; qemu_remove_mouse_event_handler(s->eh_entry); - qemu_free(s); } static int usb_wacom_initfn(USBDevice *dev) @@ -311,7 +311,9 @@ USBDevice *usb_create(USBBus *bus, const char *name); USBDevice *usb_create_simple(USBBus *bus, const char *name); void usb_register_port(USBBus *bus, USBPort *port, void *opaque, int index, usb_attachfn attach); +void usb_unregister_port(USBBus *bus, USBPort *port); int usb_device_attach(USBDevice *dev); +int usb_device_detach(USBDevice *dev); int usb_device_delete_addr(int busnr, int addr); static inline USBBus *usb_bus_from_device(USBDevice *d) diff --git a/qemu-config.c b/qemu-config.c index 22baf424b..cfb1d2982 100644 --- a/qemu-config.c +++ b/qemu-config.c @@ -1,6 +1,7 @@ #include "qemu-common.h" #include "qemu-option.h" #include "qemu-config.h" +#include "sysemu.h" QemuOptsList qemu_drive_opts = { .name = "drive", @@ -190,7 +191,7 @@ int qemu_set_option(const char *str) rc = sscanf(str, "%63[^.].%63[^.].%63[^=]%n", group, id, arg, &offset); if (rc < 3 || str[offset] != '=') { - fprintf(stderr, "can't parse: \"%s\"\n", str); + qemu_error("can't parse: \"%s\"\n", str); return -1; } @@ -199,19 +200,19 @@ int qemu_set_option(const char *str) break; } if (lists[i] == NULL) { - fprintf(stderr, "there is no option group \"%s\"\n", group); + qemu_error("there is no option group \"%s\"\n", group); return -1; } opts = qemu_opts_find(lists[i], id); if (!opts) { - fprintf(stderr, "there is no %s \"%s\" defined\n", + qemu_error("there is no %s \"%s\" defined\n", lists[i]->name, id); return -1; } if (qemu_opt_set(opts, arg, str+offset+1) == -1) { - fprintf(stderr, "failed to set \"%s\" for %s \"%s\"\n", + qemu_error("failed to set \"%s\" for %s \"%s\"\n", arg, lists[i]->name, id); return -1; } diff --git a/qemu-monitor.hx b/qemu-monitor.hx index 7ba8c9b21..797746fae 100644 --- a/qemu-monitor.hx +++ b/qemu-monitor.hx @@ -369,8 +369,24 @@ hub. @var{devname} has the syntax @code{bus.addr}. Use the monitor command @code{info usb} to see the devices you can remove. ETEXI - { "cpu", "index:i", do_cpu_set, - "index", "set the default CPU" }, + { "device_add", "config:s", do_device_add, + "device", "add device, like -device on the command line" }, +STEXI +@item device_add @var{config} + +Add device. +ETEXI + + { "device_del", "id:s", do_device_del, + "device", "remove device" }, +STEXI +@item device_del @var{id} + +Remove device @var{id}. +ETEXI + + { "cpu", "index:i", do_cpu_set, "index", "set the default CPU" }, + STEXI Set the default CPU. ETEXI @@ -204,9 +204,6 @@ extern DriveInfo *drive_init(QemuOpts *arg, void *machine, int *fatal_error); /* acpi */ void qemu_system_cpu_hot_add(int cpu, int state); -typedef void (*qemu_system_device_hot_add_t)(int pcibus, int slot, int state); -void qemu_system_device_hot_add_register(qemu_system_device_hot_add_t callback); -void qemu_system_device_hot_add(int pcibus, int slot, int state); /* device-hotplug */ @@ -221,7 +218,7 @@ void pci_device_hot_add(Monitor *mon, const QDict *qdict); void drive_hot_add(Monitor *mon, const QDict *qdict); void pci_device_hot_remove(Monitor *mon, const char *pci_addr); void do_pci_device_hot_remove(Monitor *mon, const QDict *qdict); -void pci_device_hot_remove_success(int pcibus, int slot); +void pci_device_hot_remove_success(PCIDevice *dev); /* serial ports */ @@ -6072,6 +6072,8 @@ int main(int argc, char **argv, char **envp) exit(1); } + qdev_machine_creation_done(); + if (loadvm) { if (load_vmstate(cur_mon, loadvm) < 0) { autostart = 0; |