@@ -101,8 +101,12 @@ typedef void (*BusUnrealize)(BusState *bus);
* @props: Properties accessing state fields.
* @realize: Callback function invoked when the #DeviceState:realized
* property is changed to %true.
+ * @wire: Callback function called after @realize to connect IRQs,
+ * clocks and map memories. Can not fail.
+ * @unwire: Callback function to undo @wire. Called before @unrealize.
+ * Can not fail.
* @unrealize: Callback function invoked when the #DeviceState:realized
- * property is changed to %false.
+ * property is changed to %false. Can not fail.
* @hotpluggable: indicates if #DeviceClass is hotpluggable, available
* as readonly "hotpluggable" property of #DeviceState instance
*
@@ -161,6 +165,8 @@ struct DeviceClass {
*/
DeviceReset reset;
DeviceRealize realize;
+ void (*wire)(DeviceState *dev);
+ void (*unwire)(DeviceState *dev);
DeviceUnrealize unrealize;
/**
@@ -303,6 +303,16 @@ bool qdev_realize_and_unref(DeviceState *dev, BusState *bus, Error **errp)
void qdev_unrealize(DeviceState *dev)
{
+ DeviceClass *dc = DEVICE_GET_CLASS(dev);
+
+ if (dc->unwire) {
+ if (!dc->wire) {
+ error_report("disconnect() without connect() for type '%s'",
+ object_get_typename(OBJECT(dev)));
+ abort();
+ }
+ dc->unwire(dev);
+ }
object_property_set_bool(OBJECT(dev), "realized", false, &error_abort);
}
@@ -601,8 +611,17 @@ static void device_set_realized(Object *obj, bool value, Error **errp)
dev->pending_deleted_event = true;
DEVICE_LISTENER_CALL(unrealize, Reverse, dev);
}
-
assert(local_err == NULL);
+
+ if (dc->wire) {
+ if (!dc->unwire) {
+ warn_report_once("wire() without unwire() for type '%s'",
+ object_get_typename(OBJECT(dev)));
+ }
+ dc->wire(dev);
+ }
+
+ /* At this point the device is "guest visible". */
return;
child_realize_fail:
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org> --- include/hw/qdev-core.h | 8 +++++++- hw/core/qdev.c | 21 ++++++++++++++++++++- 2 files changed, 27 insertions(+), 2 deletions(-)