|
@@ -176,6 +176,32 @@ DeviceState *qdev_try_create(BusState *bus, const char *type)
|
|
|
return dev;
|
|
|
}
|
|
|
|
|
|
+/*
|
|
|
+ * Create a device on the heap.
|
|
|
+ * A type @name must exist.
|
|
|
+ * This only initializes the device state structure and allows
|
|
|
+ * properties to be set. The device still needs to be realized. See
|
|
|
+ * qdev-core.h.
|
|
|
+ */
|
|
|
+DeviceState *qdev_new(const char *name)
|
|
|
+{
|
|
|
+ return DEVICE(object_new(name));
|
|
|
+}
|
|
|
+
|
|
|
+/*
|
|
|
+ * Try to create a device on the heap.
|
|
|
+ * This is like qdev_new(), except it returns %NULL when type @name
|
|
|
+ * does not exist.
|
|
|
+ */
|
|
|
+DeviceState *qdev_try_new(const char *name)
|
|
|
+{
|
|
|
+ if (!object_class_by_name(name)) {
|
|
|
+ return NULL;
|
|
|
+ }
|
|
|
+
|
|
|
+ return DEVICE(object_new(name));
|
|
|
+}
|
|
|
+
|
|
|
static QTAILQ_HEAD(, DeviceListener) device_listeners
|
|
|
= QTAILQ_HEAD_INITIALIZER(device_listeners);
|
|
|
|
|
@@ -427,6 +453,66 @@ void qdev_init_nofail(DeviceState *dev)
|
|
|
object_unref(OBJECT(dev));
|
|
|
}
|
|
|
|
|
|
+/*
|
|
|
+ * Realize @dev.
|
|
|
+ * @dev must not be plugged into a bus.
|
|
|
+ * Plug @dev into @bus if non-null, else into the main system bus.
|
|
|
+ * This takes a reference to @dev.
|
|
|
+ * If @dev has no QOM parent, make one up, taking another reference.
|
|
|
+ * On success, return true.
|
|
|
+ * On failure, store an error through @errp and return false.
|
|
|
+ */
|
|
|
+bool qdev_realize(DeviceState *dev, BusState *bus, Error **errp)
|
|
|
+{
|
|
|
+ Error *err = NULL;
|
|
|
+
|
|
|
+ assert(!dev->realized && !dev->parent_bus);
|
|
|
+
|
|
|
+ if (!bus) {
|
|
|
+ /*
|
|
|
+ * Assert that the device really is a SysBusDevice before we
|
|
|
+ * put it onto the sysbus. Non-sysbus devices which aren't
|
|
|
+ * being put onto a bus should be realized with
|
|
|
+ * object_property_set_bool(OBJECT(dev), true, "realized",
|
|
|
+ * errp);
|
|
|
+ */
|
|
|
+ g_assert(object_dynamic_cast(OBJECT(dev), TYPE_SYS_BUS_DEVICE));
|
|
|
+ bus = sysbus_get_default();
|
|
|
+ }
|
|
|
+
|
|
|
+ qdev_set_parent_bus(dev, bus);
|
|
|
+
|
|
|
+ object_property_set_bool(OBJECT(dev), true, "realized", &err);
|
|
|
+ if (err) {
|
|
|
+ error_propagate(errp, err);
|
|
|
+ }
|
|
|
+ return !err;
|
|
|
+}
|
|
|
+
|
|
|
+/*
|
|
|
+ * Realize @dev and drop a reference.
|
|
|
+ * This is like qdev_realize(), except the caller must hold a
|
|
|
+ * (private) reference, which is dropped on return regardless of
|
|
|
+ * success or failure. Intended use:
|
|
|
+ * dev = qdev_new();
|
|
|
+ * [...]
|
|
|
+ * qdev_realize_and_unref(dev, bus, errp);
|
|
|
+ * Now @dev can go away without further ado.
|
|
|
+ */
|
|
|
+bool qdev_realize_and_unref(DeviceState *dev, BusState *bus, Error **errp)
|
|
|
+{
|
|
|
+ bool ret;
|
|
|
+
|
|
|
+ ret = qdev_realize(dev, bus, errp);
|
|
|
+ object_unref(OBJECT(dev));
|
|
|
+ return ret;
|
|
|
+}
|
|
|
+
|
|
|
+void qdev_unrealize(DeviceState *dev)
|
|
|
+{
|
|
|
+ object_property_set_bool(OBJECT(dev), false, "realized", &error_abort);
|
|
|
+}
|
|
|
+
|
|
|
static int qdev_assert_realized_properly(Object *obj, void *opaque)
|
|
|
{
|
|
|
DeviceState *dev = DEVICE(object_dynamic_cast(obj, TYPE_DEVICE));
|
|
@@ -1002,6 +1088,10 @@ post_realize_fail:
|
|
|
fail:
|
|
|
error_propagate(errp, local_err);
|
|
|
if (unattached_parent) {
|
|
|
+ /*
|
|
|
+ * Beware, this doesn't just revert
|
|
|
+ * object_property_add_child(), it also runs bus_remove()!
|
|
|
+ */
|
|
|
object_unparent(OBJECT(dev));
|
|
|
unattached_count--;
|
|
|
}
|