From d2df27ef794f1c8011d2a131f6d833beadb476cd Mon Sep 17 00:00:00 2001
From: BALATON Zoltan <balaton@eik.bme.hu>
Date: Thu, 27 Jun 2024 14:43:19 +0200
Subject: [PATCH] hw/ppc/pegasos2: Fix IRQ routing from pci.0
To: qemu-devel@nongnu.org,
    qemu-ppc@nongnu.org
Cc: Nicholas Piggin <npiggin@gmail.com>,
    Daniel Henrique Barboza <danielhb413@gmail.com>

The MV64361 has two PCI buses one of which is used for AGP on
PegasosII. So far we only emulated the PCI bus on pci.1 but some
graphics cards are only recognised by some guests when connected to
pci.0 corresponding to the AGP port. But the interrupts were not
routed from pci.0 so this patch fixes that allowing the use of pci.0.
On real board only INTA and INTB are connected for AGP but to avoid
surprises we connect all 4 PCI interuupt lines so pci.0 can be used
for PCI cards as well.

Signed-off-by: BALATON Zoltan <balaton@eik.bme.hu>
---
 hw/pci-host/mv64361.c |  1 +
 hw/ppc/pegasos2.c     | 33 ++++++++++++++++++++++++++++++++-
 2 files changed, 33 insertions(+), 1 deletion(-)

diff --git a/hw/pci-host/mv64361.c b/hw/pci-host/mv64361.c
index 01bd8c887f..24ecd1db61 100644
--- a/hw/pci-host/mv64361.c
+++ b/hw/pci-host/mv64361.c
@@ -95,6 +95,7 @@ static void mv64361_pcihost_realize(DeviceState *dev, Error **errp)
                                    &s->mem, &s->io, 0, 4, TYPE_PCI_BUS);
     g_free(name);
     pci_create_simple(h->bus, 0, TYPE_MV64361_PCI_BRIDGE);
+    qdev_init_gpio_out(dev, s->irq, ARRAY_SIZE(s->irq));
 }
 
 static Property mv64361_pcihost_props[] = {
diff --git a/hw/ppc/pegasos2.c b/hw/ppc/pegasos2.c
index c1bd8dfa21..cd1b5b2330 100644
--- a/hw/ppc/pegasos2.c
+++ b/hw/ppc/pegasos2.c
@@ -14,6 +14,7 @@
 #include "hw/sysbus.h"
 #include "hw/pci/pci_host.h"
 #include "hw/irq.h"
+#include "hw/or-irq.h"
 #include "hw/pci-host/mv64361.h"
 #include "hw/isa/vt82c686.h"
 #include "hw/ide/pci.h"
@@ -73,8 +74,11 @@ OBJECT_DECLARE_TYPE(Pegasos2MachineState, MachineClass, PEGASOS2_MACHINE)
 
 struct Pegasos2MachineState {
     MachineState parent_obj;
+
     PowerPCCPU *cpu;
     DeviceState *mv;
+    OrIRQState orirq[PCI_NUM_PINS];
+    qemu_irq *pci_irqs;
     qemu_irq mv_pirq[PCI_NUM_PINS];
     qemu_irq via_pirq[PCI_NUM_PINS];
     Vof *vof;
@@ -177,7 +181,6 @@ static void pegasos2_init(MachineState *machine)
         pm->mv_pirq[i] = qdev_get_gpio_in_named(pm->mv, "gpp", 12 + i);
     }
     pci_bus = mv64361_get_pci_bus(pm->mv, 1);
-    pci_bus_irqs(pci_bus, pegasos2_pci_irq, pm, PCI_NUM_PINS);
 
     /* VIA VT8231 South Bridge (multifunction PCI device) */
     via = OBJECT(pci_new_multifunction(PCI_DEVFN(12, 0), TYPE_VT8231_ISA));
@@ -209,6 +212,34 @@ static void pegasos2_init(MachineState *machine)
     /* other PC hardware */
     pci_vga_init(pci_bus);
 
+    /* PCI interrupt routing */
+    pm->pci_irqs = qemu_allocate_irqs(pegasos2_pci_irq, pm, PCI_NUM_PINS);
+    if (!pm->pci_irqs) {
+        error_report("Could not allocate PCI IRQs");
+        exit(1);
+    }
+    for (int h = 0; h < 2; h++) {
+        g_autofree const char *pn = g_strdup_printf("pcihost%d", h);
+        DeviceState *pd = DEVICE(object_resolve_path_component(OBJECT(pm->mv),
+                                                               pn));
+        assert(pd);
+        for (i = 0; i < PCI_NUM_PINS; i++) {
+            OrIRQState *ori = &pm->orirq[i];
+
+            if (h == 0) {
+                g_autofree const char *n = g_strdup_printf("pci-orirq[%d]", i);
+
+                object_initialize_child_with_props(OBJECT(pm), n, ori,
+                                                   sizeof(*ori), TYPE_OR_IRQ,
+                                                   &error_fatal,
+                                                   "num-lines", "2", NULL);
+                qdev_realize(DEVICE(ori), NULL, &error_fatal);
+                qdev_connect_gpio_out(DEVICE(ori), 0, pm->pci_irqs[i]);
+            }
+            qdev_connect_gpio_out(pd, i, qdev_get_gpio_in(DEVICE(ori), h));
+        }
+    }
+
     if (machine->kernel_filename) {
         sz = load_elf(machine->kernel_filename, NULL, NULL, NULL,
                       &pm->kernel_entry, &pm->kernel_addr, NULL, NULL, 1,
-- 
2.30.9

