From 063d297690d04917b56d0fed9c82b92f6aa36c10 Mon Sep 17 00:00:00 2001 From: kettenis Date: Sat, 11 Dec 2021 20:07:27 +0000 Subject: [PATCH] Add support for interrupts represented by ACPI PCI Interrupt Link Devices. This makes PCI interrupts work on QEMU's SBSA target. ok patrick@ --- sys/arch/arm64/dev/acpipci.c | 64 ++++++++++++++++++++++++++++++++---- 1 file changed, 57 insertions(+), 7 deletions(-) diff --git a/sys/arch/arm64/dev/acpipci.c b/sys/arch/arm64/dev/acpipci.c index 28d35d09c87..6528fb229e0 100644 --- a/sys/arch/arm64/dev/acpipci.c +++ b/sys/arch/arm64/dev/acpipci.c @@ -1,4 +1,4 @@ -/* $OpenBSD: acpipci.c,v 1.33 2021/10/24 17:52:28 mpi Exp $ */ +/* $OpenBSD: acpipci.c,v 1.34 2021/12/11 20:07:27 kettenis Exp $ */ /* * Copyright (c) 2018 Mark Kettenis * @@ -461,6 +461,49 @@ acpipci_intr_swizzle(struct pci_attach_args *pa, pci_intr_handle_t *ihp) return 0; } +int +acpipci_getirq(int crsidx, union acpi_resource *crs, void *arg) +{ + int *irq = arg; + + switch (AML_CRSTYPE(crs)) { + case SR_IRQ: + *irq = ffs(letoh16(crs->sr_irq.irq_mask)) - 1; + break; + case LR_EXTIRQ: + *irq = letoh32(crs->lr_extirq.irq[0]); + break; + default: + break; + } + + return 0; +} + +int +acpipci_intr_link(struct acpipci_softc *sc, struct aml_value *val) +{ + struct aml_value res; + int64_t sta; + int irq = -1; + + if (val->type == AML_OBJTYPE_OBJREF) + val = val->v_objref.ref; + if (val->type != AML_OBJTYPE_DEVICE) + return -1; + + sta = acpi_getsta(sc->sc_acpi, val->node); + if ((sta & STA_PRESENT) == 0) + return -1; + + if (aml_evalname(sc->sc_acpi, val->node, "_CRS", 0, NULL, &res)) + return -1; + aml_parse_resource(&res, acpipci_getirq, &irq); + aml_freevalue(&res); + + return irq; +} + int acpipci_intr_map(struct pci_attach_args *pa, pci_intr_handle_t *ihp) { @@ -497,19 +540,26 @@ acpipci_intr_map(struct pci_attach_args *pa, pci_intr_handle_t *ihp) continue; if (val->v_package[0]->type != AML_OBJTYPE_INTEGER || val->v_package[1]->type != AML_OBJTYPE_INTEGER || - val->v_package[2]->type != AML_OBJTYPE_INTEGER || val->v_package[3]->type != AML_OBJTYPE_INTEGER) continue; - + addr = val->v_package[0]->v_integer; pin = val->v_package[1]->v_integer; - source = val->v_package[2]->v_integer; - index = val->v_package[3]->v_integer; if (ACPI_ADR_PCIDEV(addr) != pa->pa_device || ACPI_ADR_PCIFUN(addr) != 0xffff || - pin != pa->pa_intrpin - 1 || source != 0) + pin != pa->pa_intrpin - 1) continue; - + + if (val->v_package[2]->type == AML_OBJTYPE_INTEGER) { + source = val->v_package[2]->v_integer; + index = val->v_package[3]->v_integer; + } else { + source = 0; + index = acpipci_intr_link(sc, val->v_package[2]); + } + if (source != 0 || index == -1) + continue; + ihp->ih_pc = pa->pa_pc; ihp->ih_tag = pa->pa_tag; ihp->ih_intrpin = index; -- 2.20.1