hw/ide/piix.c calls ide_init_ioport() with a NULL ISADevice because
the PIIX IDE function is a PCI device, not an ISA one.  That NULL
propagates to isa_register_portio_list() and from there to
portio_list_init() as owner==NULL, which the following commit turns
into a hard error.

Change ide_init_ioport() to take an Object *owner directly.  When the
owner is an ISADevice, keep the existing isa_register_portio_list()
path so isa_init_ioport() still records the base I/O port for firmware
paths.  When it is not (the PIIX case), register the port lists with
the given owner directly.

Assisted-by: Kiro
Signed-off-by: Alexander Graf <[email protected]>
---
 hw/ide/ide-internal.h |  2 +-
 hw/ide/ioport.c       | 37 ++++++++++++++++++++++++++-----------
 hw/ide/isa.c          |  2 +-
 hw/ide/piix.c         |  2 +-
 4 files changed, 29 insertions(+), 14 deletions(-)

diff --git a/hw/ide/ide-internal.h b/hw/ide/ide-internal.h
index 281d07c9d5..3f48335cdf 100644
--- a/hw/ide/ide-internal.h
+++ b/hw/ide/ide-internal.h
@@ -419,7 +419,7 @@ uint32_t ide_data_readl(void *opaque, uint32_t addr);
 int ide_init_drive(IDEState *s, IDEDevice *dev, IDEDriveKind kind, Error 
**errp);
 void ide_exit(IDEState *s);
 void ide_bus_init_output_irq(IDEBus *bus, qemu_irq irq_out);
-int ide_init_ioport(IDEBus *bus, ISADevice *isa, int iobase, int iobase2);
+int ide_init_ioport(IDEBus *bus, Object *owner, int iobase, int iobase2);
 void ide_bus_set_irq(IDEBus *bus);
 void ide_bus_register_restart_cb(IDEBus *bus);
 
diff --git a/hw/ide/ioport.c b/hw/ide/ioport.c
index a2f457f0bd..afafe6844c 100644
--- a/hw/ide/ioport.c
+++ b/hw/ide/ioport.c
@@ -1,5 +1,5 @@
 /*
- * QEMU IDE disk and CD/DVD-ROM Emulator
+ * QEMU IDE Emulation: PIO ioport registration.
  *
  * Copyright (c) 2003 Fabrice Bellard
  * Copyright (c) 2006 Openedhand Ltd.
@@ -28,19 +28,34 @@
 #include "ide-internal.h"
 #include "trace.h"
 
-int ide_init_ioport(IDEBus *bus, ISADevice *dev, int iobase, int iobase2)
+int ide_init_ioport(IDEBus *bus, Object *owner, int iobase, int iobase2)
 {
+    ISADevice *isa = ISA_DEVICE(object_dynamic_cast(owner, TYPE_ISA_DEVICE));
     int ret;
 
-    /* ??? Assume only ISA and PCI configurations, and that the PCI-ISA
-       bridge has been setup properly to always register with ISA.  */
-    ret = isa_register_portio_list(dev, &bus->portio_list,
-                                   iobase, ide_portio_list, bus, "ide");
-
-    if (ret == 0 && iobase2) {
-        ret = isa_register_portio_list(dev, &bus->portio2_list,
-                                       iobase2, ide_portio2_list, bus, "ide");
+    if (isa) {
+        ret = isa_register_portio_list(isa, &bus->portio_list,
+                                       iobase, ide_portio_list, bus, "ide");
+        if (ret == 0 && iobase2) {
+            ret = isa_register_portio_list(isa, &bus->portio2_list,
+                                           iobase2, ide_portio2_list, bus,
+                                           "ide");
+        }
+        return ret;
     }
 
-    return ret;
+    /* PIIX3/4: no ISADevice, but ISA I/O space is set up by the PCI-ISA */
+    /* bridge; register the port lists directly with the given owner.   */
+    if (!isa_address_space_io(NULL)) {
+        return -ENODEV;
+    }
+    portio_list_init(&bus->portio_list, owner, ide_portio_list, bus, "ide");
+    portio_list_add(&bus->portio_list, isa_address_space_io(NULL), iobase);
+    if (iobase2) {
+        portio_list_init(&bus->portio2_list, owner,
+                         ide_portio2_list, bus, "ide");
+        portio_list_add(&bus->portio2_list,
+                        isa_address_space_io(NULL), iobase2);
+    }
+    return 0;
 }
diff --git a/hw/ide/isa.c b/hw/ide/isa.c
index 37457be035..7949625e00 100644
--- a/hw/ide/isa.c
+++ b/hw/ide/isa.c
@@ -71,7 +71,7 @@ static void isa_ide_realizefn(DeviceState *dev, Error **errp)
     ISAIDEState *s = ISA_IDE(dev);
 
     ide_bus_init(&s->bus, sizeof(s->bus), dev, 0, 2);
-    ide_init_ioport(&s->bus, isadev, s->iobase, s->iobase2);
+    ide_init_ioport(&s->bus, OBJECT(isadev), s->iobase, s->iobase2);
     ide_bus_init_output_irq(&s->bus, isa_get_irq(isadev, s->irqnum));
     vmstate_register_any(VMSTATE_IF(dev), &vmstate_ide_isa, s);
     ide_bus_register_restart_cb(&s->bus);
diff --git a/hw/ide/piix.c b/hw/ide/piix.c
index a0f2709c69..5c5b91fa52 100644
--- a/hw/ide/piix.c
+++ b/hw/ide/piix.c
@@ -134,7 +134,7 @@ static bool pci_piix_init_bus(PCIIDEState *d, unsigned i, 
Error **errp)
     int ret;
 
     ide_bus_init(&d->bus[i], sizeof(d->bus[i]), DEVICE(d), i, 2);
-    ret = ide_init_ioport(&d->bus[i], NULL, port_info[i].iobase,
+    ret = ide_init_ioport(&d->bus[i], OBJECT(d), port_info[i].iobase,
                           port_info[i].iobase2);
     if (ret) {
         error_setg_errno(errp, -ret, "Failed to realize %s port %u",
-- 
2.47.1


Reply via email to