#include "qdev.h"
#include "sysemu.h"
#include "monitor.h"
-#include "qerror.h"
static int qdev_hotplug = 0;
assert(bus->allow_hotplug);
dev->hotplugged = 1;
}
+ dev->instance_id_alias = -1;
dev->state = DEV_STATE_CREATED;
return dev;
}
return 0;
if (qdev_prop_parse(dev, name, value) == -1) {
- error_report("can't set property \"%s\" to \"%s\" for \"%s\"",
- name, value, dev->info->name);
return -1;
}
return 0;
driver = qemu_opt_get(opts, "driver");
if (driver && !strcmp(driver, "?")) {
for (info = device_info_list; info != NULL; info = info->next) {
+ if (info->no_user) {
+ continue; /* not available, don't show */
+ }
qdev_print_devinfo(info);
}
return 1;
}
for (prop = info->props; prop && prop->name; prop++) {
+ /*
+ * TODO Properties without a parser are just for dirty hacks.
+ * qdev_prop_ptr is the only such PropertyInfo. It's marked
+ * for removal. This conditional should be removed along with
+ * it.
+ */
+ if (!prop->info->parse) {
+ continue; /* no way to set it, don't show */
+ }
error_printf("%s.%s=%s\n", info->name, prop->name, prop->info->name);
}
return 1;
driver = qemu_opt_get(opts, "driver");
if (!driver) {
- error_report("-device: no driver specified");
+ qerror_report(QERR_MISSING_PARAMETER, "driver");
return NULL;
}
/* find driver */
info = qdev_find_info(NULL, driver);
- if (!info) {
- qerror_report(QERR_DEVICE_NOT_FOUND, driver);
- return NULL;
- }
- if (info->no_user) {
- error_report("device \"%s\" can't be added via command line",
- info->name);
+ if (!info || info->no_user) {
+ qerror_report(QERR_INVALID_PARAMETER_VALUE, "driver", "a driver name");
+ error_printf_unless_qmp("Try with argument '?' for a list.\n");
return NULL;
}
path = qemu_opt_get(opts, "bus");
if (path != NULL) {
bus = qbus_find(path);
- if (bus && bus->info != info->bus_info) {
- error_report("Device '%s' can't go on a %s bus",
- driver, bus->info->name);
+ if (!bus) {
+ return NULL;
+ }
+ if (bus->info != info->bus_info) {
+ qerror_report(QERR_BAD_BUS_FOR_DEVICE,
+ driver, bus->info->name);
return NULL;
}
} else {
bus = qbus_find_recursive(main_system_bus, NULL, info->bus_info);
- }
- if (!bus) {
- error_report("Did not find %s bus for %s",
- path ? path : info->bus_info->name, info->name);
- return NULL;
+ if (!bus) {
+ qerror_report(QERR_NO_BUS_FOR_DEVICE,
+ info->name, info->bus_info->name);
+ return NULL;
+ }
}
if (qdev_hotplug && !bus->allow_hotplug) {
- error_report("Bus %s does not support hotplugging",
- bus->name);
+ qerror_report(QERR_BUS_NO_HOTPLUG, bus->name);
return NULL;
}
return NULL;
}
if (qdev_init(qdev) < 0) {
- error_report("Error initializing device %s", driver);
+ qerror_report(QERR_DEVICE_INIT_FAILED, driver);
return NULL;
}
qdev->opts = opts;
return rc;
}
qemu_register_reset(qdev_reset, dev);
- if (dev->info->vmsd)
- vmstate_register(-1, dev->info->vmsd, dev);
+ if (dev->info->vmsd) {
+ vmstate_register_with_alias_id(-1, dev->info->vmsd, dev,
+ dev->instance_id_alias,
+ dev->alias_required_for_version);
+ }
dev->state = DEV_STATE_INITIALIZED;
return 0;
}
+void qdev_set_legacy_instance_id(DeviceState *dev, int alias_id,
+ int required_for_version)
+{
+ assert(dev->state == DEV_STATE_CREATED);
+ dev->instance_id_alias = alias_id;
+ dev->alias_required_for_version = required_for_version;
+}
+
int qdev_unplug(DeviceState *dev)
{
if (!dev->parent_bus->allow_hotplug) {
- error_report("Bus %s does not support hotplugging",
- dev->parent_bus->name);
+ qerror_report(QERR_BUS_NO_HOTPLUG, dev->parent_bus->name);
return -1;
}
assert(dev->info->unplug != NULL);
void qdev_free(DeviceState *dev)
{
BusState *bus;
+ Property *prop;
if (dev->state == DEV_STATE_INITIALIZED) {
while (dev->num_child_bus) {
}
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);
}
pos = 0;
} else {
if (sscanf(path, "%127[^/]%n", elem, &len) != 1) {
- error_report("path parse error (\"%s\")", path);
- return NULL;
+ assert(!path[0]);
+ elem[0] = len = 0;
}
bus = qbus_find_recursive(main_system_bus, elem, NULL);
if (!bus) {
- error_report("bus \"%s\" not found", elem);
+ qerror_report(QERR_BUS_NOT_FOUND, elem);
return NULL;
}
pos = len;
}
for (;;) {
+ assert(path[pos] == '/' || !path[pos]);
+ while (path[pos] == '/') {
+ pos++;
+ }
if (path[pos] == '\0') {
- /* we are done */
return bus;
}
/* find device */
- if (sscanf(path+pos, "/%127[^/]%n", elem, &len) != 1) {
- error_report("path parse error (\"%s\" pos %d)", path, pos);
- return NULL;
+ if (sscanf(path+pos, "%127[^/]%n", elem, &len) != 1) {
+ assert(0);
+ elem[0] = len = 0;
}
pos += len;
dev = qbus_find_dev(bus, elem);
if (!dev) {
- error_report("device \"%s\" not found", elem);
- qbus_list_dev(bus);
+ qerror_report(QERR_DEVICE_NOT_FOUND, elem);
+ if (!monitor_cur_is_qmp()) {
+ qbus_list_dev(bus);
+ }
return NULL;
}
+
+ assert(path[pos] == '/' || !path[pos]);
+ while (path[pos] == '/') {
+ pos++;
+ }
if (path[pos] == '\0') {
/* last specified element is a device. If it has exactly
* one child bus accept it nevertheless */
switch (dev->num_child_bus) {
case 0:
- error_report("device has no child bus (%s)", path);
+ qerror_report(QERR_DEVICE_NO_BUS, elem);
return NULL;
case 1:
return QLIST_FIRST(&dev->child_bus);
default:
- error_report("device has multiple child busses (%s)", path);
- qbus_list_bus(dev);
+ qerror_report(QERR_DEVICE_MULTIPLE_BUSSES, elem);
+ if (!monitor_cur_is_qmp()) {
+ qbus_list_bus(dev);
+ }
return NULL;
}
}
/* find bus */
- if (sscanf(path+pos, "/%127[^/]%n", elem, &len) != 1) {
- error_report("path parse error (\"%s\" pos %d)", path, pos);
- return NULL;
+ if (sscanf(path+pos, "%127[^/]%n", elem, &len) != 1) {
+ assert(0);
+ elem[0] = len = 0;
}
pos += len;
bus = qbus_find_bus(dev, elem);
if (!bus) {
- error_report("child bus \"%s\" not found", elem);
- qbus_list_bus(dev);
+ qerror_report(QERR_BUS_NOT_FOUND, elem);
+ if (!monitor_cur_is_qmp()) {
+ qbus_list_bus(dev);
+ }
return NULL;
}
}
QLIST_REMOVE(bus, sibling);
bus->parent->num_child_bus--;
}
+ qemu_free((void*)bus->name);
if (bus->qdev_allocated) {
qemu_free(bus);
}
if (!props)
return;
while (props->name) {
+ /*
+ * TODO Properties without a print method are just for dirty
+ * hacks. qdev_prop_ptr is the only such PropertyInfo. It's
+ * marked for removal. The test props->info->print should be
+ * removed along with it.
+ */
if (props->info->print) {
props->info->print(dev, props, buf, sizeof(buf));
qdev_printf("%s-prop: %s = %s\n", prefix, props->name, buf);
}
}
-void do_device_add(Monitor *mon, const QDict *qdict)
+int do_device_add(Monitor *mon, const QDict *qdict, QObject **ret_data)
{
QemuOpts *opts;
- opts = qemu_opts_parse(&qemu_device_opts,
- qdict_get_str(qdict, "config"), "driver");
- if (opts) {
- if (qdev_device_help(opts) || qdev_device_add(opts) == NULL) {
- qemu_opts_del(opts);
- }
+ opts = qemu_opts_from_qdict(&qemu_device_opts, qdict);
+ if (!opts) {
+ return -1;
+ }
+ if (!monitor_cur_is_qmp() && qdev_device_help(opts)) {
+ qemu_opts_del(opts);
+ return 0;
}
+ if (!qdev_device_add(opts)) {
+ qemu_opts_del(opts);
+ return -1;
+ }
+ return 0;
}
-void do_device_del(Monitor *mon, const QDict *qdict)
+int do_device_del(Monitor *mon, const QDict *qdict, QObject **ret_data)
{
const char *id = qdict_get_str(qdict, "id");
DeviceState *dev;
dev = qdev_find_recursive(main_system_bus, id);
if (NULL == dev) {
- error_report("Device '%s' not found", id);
- return;
+ qerror_report(QERR_DEVICE_NOT_FOUND, id);
+ return -1;
}
- qdev_unplug(dev);
+ return qdev_unplug(dev);
}