To allow enabling/disabling present ISA devices without hotplug,
keep track of state and add a helper to avoid enabling twice.
Since the properties to be configured are defined at device level,
delegate the actual work to a callback function.

If no callback is supplied, the device can't be disabled.

Prepare VMSTATE_ISA_DEVICE for devices that support disabling.
Legacy devices never change their state and won't need this yet.

Cc: Gerd Hoffmann <kra...@redhat.com>
Signed-off-by: Andreas Färber <andreas.faer...@web.de>
---
 hw/hw.h      |   15 +++++++++++++++
 hw/isa-bus.c |   29 +++++++++++++++++++++++++++++
 hw/isa.h     |    4 ++++
 3 files changed, 48 insertions(+), 0 deletions(-)

diff --git a/hw/hw.h b/hw/hw.h
index 56447a7..07b1e2e 100644
--- a/hw/hw.h
+++ b/hw/hw.h
@@ -628,6 +628,21 @@ extern const VMStateInfo vmstate_info_unused_buffer;
     .info         = &vmstate_info_unused_buffer,                     \
     .flags        = VMS_BUFFER,                                      \
 }
+
+extern const VMStateDescription vmstate_isa_device;
+
+#define VMSTATE_ISA_DEVICE_V(_field, _state, _version) {             \
+    .name       = (stringify(_field)),                               \
+    .version_id   = (_version),                                      \
+    .size       = sizeof(ISADevice),                                 \
+    .vmsd       = &vmstate_isa_device,                               \
+    .flags      = VMS_STRUCT,                                        \
+    .offset     = vmstate_offset_value(_state, _field, ISADevice),   \
+}
+
+#define VMSTATE_ISA_DEVICE(_field, _state) {                         \
+    VMSTATE_ISA_DEVICE_V(_field, _state, 0)
+
 extern const VMStateDescription vmstate_pci_device;
 
 #define VMSTATE_PCI_DEVICE(_field, _state) {                         \
diff --git a/hw/isa-bus.c b/hw/isa-bus.c
index 2765543..d258932 100644
--- a/hw/isa-bus.c
+++ b/hw/isa-bus.c
@@ -112,6 +112,7 @@ static int isa_qdev_init(DeviceState *qdev, DeviceInfo 
*base)
 
     dev->isairq[0] = -1;
     dev->isairq[1] = -1;
+    dev->enabled = true;
 
     return info->init(dev);
 }
@@ -156,6 +157,34 @@ ISADevice *isa_create_simple(const char *name)
     return dev;
 }
 
+const VMStateDescription vmstate_isa_device = {
+    .name = "ISADevice",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .fields = (VMStateField []) {
+        VMSTATE_BOOL(enabled, ISADevice),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+int isa_set_state(ISADevice *dev, bool enabled)
+{
+    ISADeviceInfo *info = DO_UPCAST(ISADeviceInfo, qdev, dev->qdev.info);
+    int err;
+
+    if (dev->enabled == enabled) {
+        return 42;
+    } else if (info->set_state == NULL) {
+        return -1;
+    }
+    err = info->set_state(dev, enabled);
+    if (err < 0) {
+        return err;
+    }
+    dev->enabled = enabled;
+    return err;
+}
+
 static void isabus_dev_print(Monitor *mon, DeviceState *dev, int indent)
 {
     ISADevice *d = DO_UPCAST(ISADevice, qdev, dev);
diff --git a/hw/isa.h b/hw/isa.h
index d2b6126..5d460ab 100644
--- a/hw/isa.h
+++ b/hw/isa.h
@@ -16,12 +16,15 @@ struct ISADevice {
     int nirqs;
     uint16_t ioports[32];
     int nioports;
+    bool enabled;
 };
 
 typedef int (*isa_qdev_initfn)(ISADevice *dev);
+typedef int (*isa_qdev_statefn)(ISADevice *dev, bool enabled);
 struct ISADeviceInfo {
     DeviceInfo qdev;
     isa_qdev_initfn init;
+    isa_qdev_statefn set_state;
 };
 
 ISABus *isa_bus_new(DeviceState *dev);
@@ -34,6 +37,7 @@ void isa_qdev_register(ISADeviceInfo *info);
 ISADevice *isa_create(const char *name);
 ISADevice *isa_try_create(const char *name);
 ISADevice *isa_create_simple(const char *name);
+int isa_set_state(ISADevice *dev, bool enabled);
 
 extern target_phys_addr_t isa_mem_base;
 
-- 
1.7.5.3


Reply via email to