Commit 49531de868 for qemu.org

commit 49531de86850bf042c9782673f7f6b9e1f734160
Author: Craig Lalley <mr_lalley@yahoo.com>
Date:   Mon Sep 28 09:11:59 2026 -0700

    hw/hppa: Rotate Elroy PCI interrupts by pin on the A400

    elroy_pci_map_irq() routes all four interrupt pins of a PCI slot to the
    same IOSAPIC input, so on a multi-function device all functions share
    one line.

    Add an Astro property "rotate-pci-pins" and set it for the A400: INTA
    of slot n then goes to IOSAPIC input n, INTB to n+1, and so on (modulo
    ELROY_IRQS).  The C3700 is unchanged.

    The firmware describes the routing to the OS in the interrupt routing
    table, so this needs the matching SeaBIOS-hppa change "parisc: Rotate
    IRT interrupt lines by PCI pin on the A400".  With only one side
    applied, functions using INTB..INTD on an A400 are described with an
    IOSAPIC input which never fires.

    Signed-off-by: Craig Lalley <mr_lalley@yahoo.com>
    Signed-off-by: Helge Deller <deller@gmx.de>

diff --git a/hw/hppa/machine.c b/hw/hppa/machine.c
index 96133f09ba..df25877cb1 100644
--- a/hw/hppa/machine.c
+++ b/hw/hppa/machine.c
@@ -730,7 +730,7 @@ static void machine_HP_B160L_init(MachineState *machine)
     machine_HP_common_init_tail(machine, pci_bus, translate, false);
 }

-static AstroState *astro_init(void)
+static AstroState *astro_init(bool is_a400)
 {
     DeviceState *dev;

@@ -738,6 +738,8 @@ static AstroState *astro_init(void)
     object_property_set_int(OBJECT(dev), "phys-addr-bits",
                             hppa_phys_addr_bits(&cpu[0]->env),
                             &error_abort);
+    object_property_set_bool(OBJECT(dev), "rotate-pci-pins", is_a400,
+                             &error_abort);
     sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);

     return ASTRO_CHIP(dev);
@@ -753,6 +755,8 @@ static void machine_HP_C3700_init(MachineState *machine)
     DeviceState *astro_dev;
     MemoryRegion *addr_space = get_system_memory();
     TranslateFn *translate;
+    MachineClass *mc = MACHINE_GET_CLASS(machine);
+    bool is_C3700 = strcmp(mc->name, "C3700") == 0;

     /* Create CPUs and RAM.  */
     translate = machine_HP_common_init_cpus(machine);
@@ -764,7 +768,7 @@ static void machine_HP_C3700_init(MachineState *machine)
     }

     /* Init Astro and the Elroys (PCI host bus chips).  */
-    astro = astro_init();
+    astro = astro_init(!is_C3700);
     astro_dev = DEVICE(astro);
     memory_region_add_subregion(addr_space, translate(NULL, ASTRO_HPA),
                                 sysbus_mmio_get_region(
@@ -773,8 +777,6 @@ static void machine_HP_C3700_init(MachineState *machine)
     assert(pci_bus);

     /* The C3700 has a SuperIO chip, while the A400 hasn't. */
-    MachineClass *mc = MACHINE_GET_CLASS(machine);
-    bool is_C3700 = strcmp(mc->name, "C3700") == 0;
     if (is_C3700)  {
         PCIDevice *ide_pdev = pci_create_simple(pci_bus, PCI_DEVFN(2, 0),
                                                 "pc87560-ide");
diff --git a/hw/pci-host/astro.c b/hw/pci-host/astro.c
index fc07608da7..c024dab858 100644
--- a/hw/pci-host/astro.c
+++ b/hw/pci-host/astro.c
@@ -406,9 +406,14 @@ static void elroy_set_irq(void *opaque, int irq, int level)

 static int elroy_pci_map_irq(PCIDevice *d, int irq_num)
 {
+    ElroyState *s = pci_get_bus(d)->irq_opaque;
     int slot = PCI_SLOT(d->devfn);

     assert(irq_num >= 0 && irq_num < ELROY_IRQS);
+    /* INTB..INTD of a slot may be rotated to the following inputs */
+    if (s->astro && s->astro->rotate_pci_pins) {
+        return (slot + irq_num) & (ELROY_IRQS - 1);
+    }
     return slot & (ELROY_IRQS - 1);
 }

@@ -1064,6 +1069,7 @@ static void astro_realize(DeviceState *obj, Error **errp)

 static const Property astro_props[] = {
     DEFINE_PROP_UINT8("phys-addr-bits", AstroState, phys_addr_bits, 32),
+    DEFINE_PROP_BOOL("rotate-pci-pins", AstroState, rotate_pci_pins, false),
 };

 static void astro_class_init(ObjectClass *klass, const void *data)
diff --git a/include/hw/pci-host/astro.h b/include/hw/pci-host/astro.h
index 0cd384bceb..3297cd2e62 100644
--- a/include/hw/pci-host/astro.h
+++ b/include/hw/pci-host/astro.h
@@ -84,6 +84,7 @@ struct AstroState {
     uint64_t tlb_pdir_base;

     uint8_t phys_addr_bits;
+    bool rotate_pci_pins;       /* PCI INTx pin rotation (A400) */

     struct ElroyState *elroy[ELROY_NUM];