Add "enabled" qdev property, and implement enable and disable callbacks.
Incorporate ISA VMState as well as I/O bases and IRQ as subsection, and implement pre_load and post_load callbacks. Cc: Gerd Hoffmann <kra...@redhat.com> Cc: Markus Armbruster <arm...@redhat.com> Cc: Juan Quintela <quint...@redhat.com> Signed-off-by: Andreas Färber <andreas.faer...@web.de> --- hw/ide/isa.c | 98 +++++++++++++++++++++++++++++++++++++++++++++++++++++++--- 1 files changed, 93 insertions(+), 5 deletions(-) diff --git a/hw/ide/isa.c b/hw/ide/isa.c index 4ac7453..de8b949 100644 --- a/hw/ide/isa.c +++ b/hw/ide/isa.c @@ -41,6 +41,9 @@ typedef struct ISAIDEState { uint32_t iobase2; uint32_t isairq; qemu_irq irq; + uint32_t initial_iobase; + uint32_t initial_iobase2; + uint32_t initial_isairq; } ISAIDEState; static void isa_ide_reset(DeviceState *d) @@ -50,27 +53,109 @@ static void isa_ide_reset(DeviceState *d) ide_bus_reset(&s->bus); } +static int isa_ide_enable(ISADevice *dev) +{ + ISAIDEState *s = DO_UPCAST(ISAIDEState, dev, dev); + + ide_init_ioport(&s->bus, s->iobase, s->iobase2); + + isa_init_ioport_range(dev, s->iobase, 8); + isa_init_ioport(dev, s->iobase2); + + isa_init_irq(dev, &s->irq, s->isairq); + + return 0; +} + +static int isa_ide_disable(ISADevice *dev) +{ + ISAIDEState *s = DO_UPCAST(ISAIDEState, dev, dev); + + ide_discard_ioport(s->iobase, s->iobase2); + + isa_discard_ioport_range(dev, s->iobase2, 1); + isa_discard_ioport_range(dev, s->iobase, 8); + + isa_uninit_irq(dev, &s->irq, s->isairq); + + return 0; +} + +static int isa_ide_pre_load(void *opaque) +{ + ISAIDEState *s = opaque; + + isa_set_state(&s->dev, false); + return 0; +} + +static int isa_ide_post_load(void *opaque, int version_id) +{ + ISAIDEState *s = opaque; + ISADevice *dev = &s->dev; + + if (dev->enabled) { + isa_ide_enable(dev); + } + return 0; +} + +static bool isa_ide_isaconfig_needed(void *opaque) +{ + ISAIDEState *s = opaque; + + return isa_vmstate_needed(&s->dev) || + s->initial_iobase != s->iobase || + s->initial_iobase2 != s->iobase2 || + s->initial_isairq != s->isairq; +} + +static const VMStateDescription vmstate_ide_isa_config = { + .name = "isa-ide/isa-config", + .version_id = 1, + .minimum_version_id = 1, + .fields = (VMStateField []) { + VMSTATE_ISA_DEVICE(dev, ISAIDEState), + VMSTATE_UINT32(iobase, ISAIDEState), + VMSTATE_UINT32(iobase2, ISAIDEState), + VMSTATE_UINT32(isairq, ISAIDEState), + VMSTATE_END_OF_LIST() + }, +}; + static const VMStateDescription vmstate_ide_isa = { .name = "isa-ide", .version_id = 3, .minimum_version_id = 0, .minimum_version_id_old = 0, + .pre_load = isa_ide_pre_load, + .post_load = isa_ide_post_load, .fields = (VMStateField []) { VMSTATE_IDE_BUS(bus, ISAIDEState), VMSTATE_IDE_DRIVES(bus.ifs, ISAIDEState), VMSTATE_END_OF_LIST() - } + }, + .subsections = (VMStateSubsection []) { + { + .vmsd = &vmstate_ide_isa_config, + .needed = isa_ide_isaconfig_needed, + }, { + } + }, }; static int isa_ide_initfn(ISADevice *dev) { ISAIDEState *s = DO_UPCAST(ISAIDEState, dev, dev); + s->initial_iobase = s->iobase; + s->initial_iobase2 = s->iobase2; + s->initial_isairq = s->isairq; + ide_bus_new(&s->bus, &s->dev.qdev, 0); - ide_init_ioport(&s->bus, s->iobase, s->iobase2); - isa_init_irq(dev, &s->irq, s->isairq); - isa_init_ioport_range(dev, s->iobase, 8); - isa_init_ioport(dev, s->iobase2); + if (dev->enabled) { + isa_ide_enable(dev); + } ide_init2(&s->bus, s->irq); vmstate_register(&dev->qdev, 0, &vmstate_ide_isa, s); return 0; @@ -102,11 +187,14 @@ static ISADeviceInfo isa_ide_info = { .qdev.fw_name = "ide", .qdev.size = sizeof(ISAIDEState), .init = isa_ide_initfn, + .enable = isa_ide_enable, + .disable = isa_ide_disable, .qdev.reset = isa_ide_reset, .qdev.props = (Property[]) { DEFINE_PROP_HEX32("iobase", ISAIDEState, iobase, 0x1f0), DEFINE_PROP_HEX32("iobase2", ISAIDEState, iobase2, 0x3f6), DEFINE_PROP_UINT32("irq", ISAIDEState, isairq, 14), + DEFINE_PROP_BOOL("enabled", ISAIDEState, dev.enabled, true), DEFINE_PROP_END_OF_LIST(), }, }; -- 1.7.5.3