Signed-off-by: Andreas Färber <andreas.faer...@web.de> --- hw/ide.h | 1 + hw/ide/core.c | 8 ++++++++ hw/ide/internal.h | 1 + hw/ide/isa.c | 28 +++++++++++++++++++++++++--- 4 files changed, 35 insertions(+), 3 deletions(-)
diff --git a/hw/ide.h b/hw/ide.h index 34d9394..25b46a7 100644 --- a/hw/ide.h +++ b/hw/ide.h @@ -9,6 +9,7 @@ /* ide-isa.c */ ISADevice *isa_ide_init(int iobase, int iobase2, int isairq, DriveInfo *hd0, DriveInfo *hd1); +void isa_ide_reconfigure_iobase(ISADevice *dev, uint32_t iobase, uint32_t iobase2); /* ide-pci.c */ void pci_cmd646_ide_init(PCIBus *bus, DriveInfo **hd_table, diff --git a/hw/ide/core.c b/hw/ide/core.c index 45410e8..c3b82de 100644 --- a/hw/ide/core.c +++ b/hw/ide/core.c @@ -1760,6 +1760,14 @@ void ide_init_ioport(IDEBus *bus, int iobase, int iobase2) register_ioport_read(iobase, 4, 4, ide_data_readl, bus); } +void ide_discard_ioport(int iobase, int iobase2) +{ + isa_unassign_ioport(iobase, 8); + if (iobase2 != 0) { + isa_unassign_ioport(iobase2, 1); + } +} + static bool is_identify_set(void *opaque, int version_id) { IDEState *s = opaque; diff --git a/hw/ide/internal.h b/hw/ide/internal.h index c2b35ec..dc0a2c9 100644 --- a/hw/ide/internal.h +++ b/hw/ide/internal.h @@ -564,6 +564,7 @@ void ide_init2(IDEBus *bus, qemu_irq irq); void ide_init2_with_non_qdev_drives(IDEBus *bus, DriveInfo *hd0, DriveInfo *hd1, qemu_irq irq); void ide_init_ioport(IDEBus *bus, int iobase, int iobase2); +void ide_discard_ioport(int iobase, int iobase2); void ide_exec_cmd(IDEBus *bus, uint32_t val); void ide_dma_cb(void *opaque, int ret); diff --git a/hw/ide/isa.c b/hw/ide/isa.c index 4ac7453..d1f81d7 100644 --- a/hw/ide/isa.c +++ b/hw/ide/isa.c @@ -62,15 +62,37 @@ static const VMStateDescription vmstate_ide_isa = { } }; +static void isa_ide_init_iobase(ISAIDEState *s) +{ + ide_init_ioport(&s->bus, s->iobase, s->iobase2); + + isa_init_ioport_range(&s->dev, s->iobase, 8); + isa_init_ioport(&s->dev, s->iobase2); +} + +void isa_ide_reconfigure_iobase(ISADevice *dev, uint32_t iobase, uint32_t iobase2) +{ + ISAIDEState *s = DO_UPCAST(ISAIDEState, dev, dev); + + if (iobase != s->iobase || iobase2 != s->iobase2) { + ide_discard_ioport(s->iobase, s->iobase2); + + isa_discard_ioport_range(dev, s->iobase2, 1); + isa_discard_ioport_range(dev, s->iobase, 8); + + s->iobase = iobase; + s->iobase2 = iobase2; + isa_ide_init_iobase(s); + } +} + static int isa_ide_initfn(ISADevice *dev) { ISAIDEState *s = DO_UPCAST(ISAIDEState, dev, dev); ide_bus_new(&s->bus, &s->dev.qdev, 0); - ide_init_ioport(&s->bus, s->iobase, s->iobase2); + isa_ide_init_iobase(s); isa_init_irq(dev, &s->irq, s->isairq); - isa_init_ioport_range(dev, s->iobase, 8); - isa_init_ioport(dev, s->iobase2); ide_init2(&s->bus, s->irq); vmstate_register(&dev->qdev, 0, &vmstate_ide_isa, s); return 0; -- 1.7.5.3