Applied, thanks!
Mike Kelly, le dim. 26 oct. 2025 16:11:09 +0000, a ecrit:
> General support for applying ACPI data to subordinate buses:
> Parse ACPI tables to find PCI-PCI bridges, their bus numbers and _PRT tables.
> Use the parsed data to apply appropriate _PRT table per GSI lookup.
> Translate PCI pin numbers whilst iterating the bus hierarchy.
> ---
> debian/patches/acpi-init-files.diff | 269 +++++++++++++++++++++++++---
> 1 file changed, 242 insertions(+), 27 deletions(-)
>
> diff --git a/debian/patches/acpi-init-files.diff
> b/debian/patches/acpi-init-files.diff
> index 8f2080b..5ee59dd 100644
> --- a/debian/patches/acpi-init-files.diff
> +++ b/debian/patches/acpi-init-files.diff
> @@ -1,6 +1,8 @@
> ---- /dev/null
> -+++ b/acpi_init.c
> -@@ -0,0 +1,830 @@
> +Index: libacpica/acpi_init.c
> +===================================================================
> +--- /dev/null 1970-01-01 00:00:00.000000000 +0000
> ++++ libacpica/acpi_init.c 2025-10-26 13:07:39.753578190 +0000
> +@@ -0,0 +1,1041 @@
> +// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
> +#include <acpi/acpi.h>
> +
> @@ -33,12 +35,16 @@
> +#define PCI_CFG1_START 0xcf8
> +#define PCI_CFG1_END 0xcff
> +
> -+#define LEGACY_ISA_IRQS 8
> -+#define PCI_IRQ_START 16
> -+
> +#define PCI_INTERRUPT_PIN 0x3d
> +#define BAD_PIC_MODE(m) ((m) < ACPI_PICMODE_PIC || (m) > ACPI_PICMODE_SAPIC)
> +
> ++#define PCI_HDR_TYPE_REG 0x0e
> ++#define PCI_HDR_TYPE_PPB 1
> ++#define PCI_PPB_SECBUS_REG 0x19
> ++#define PCI_MAX_DEV_ID 0x1f
> ++#define PCI_MAX_FUNC_ID 0x7
> ++#define PCI_MULTI_FUNC_MASK 0x80
> ++
> +extern acpi_status acpi_hw_legacy_sleep(u8 sleep_state);
> +
> +// Lets keep the ACPI tables in this module
> @@ -48,6 +54,16 @@
> +static int numdevs = -1;
> +static int pic_mode = -1;
> +
> ++typedef struct acpi_pci_bridge
> ++{
> ++ acpi_handle handle;
> ++ uint8_t up_bus;
> ++ uint8_t down_bus;
> ++ struct acpi_pci_bridge* next;
> ++} acpi_pci_bridge_t;
> ++
> ++static acpi_pci_bridge_t* acpi_pci_bridges;
> ++
> +struct slots {
> + uint8_t bus;
> + uint16_t dev;
> @@ -111,6 +127,17 @@
> + return NULL;
> +}
> +
> ++static void
> ++acpi_unload_pci_bridges(void)
> ++{
> ++ while (acpi_pci_bridges != NULL)
> ++ {
> ++ acpi_pci_bridge_t* bridge = acpi_pci_bridges;
> ++ acpi_pci_bridges = bridge->next;
> ++ free(bridge);
> ++ }
> ++}
> ++
> +void
> +acpi_ds_dump_method_stack(acpi_status status, ...)
> +// struct acpi_walk_state *walk_state, union acpi_parse_object *op)
> @@ -331,6 +358,7 @@
> +acpi_os_terminate(void)
> +{
> + free(pci_devices);
> ++ acpi_unload_pci_bridges();
> + acpi_os_printf("Bye!\n");
> + return AE_OK;
> +}
> @@ -508,29 +536,22 @@
> + : (int)pci_pin);
> +}
> +
> -+int
> -+acpi_get_irq_number(uint16_t bus, uint16_t dev, uint16_t func)
> ++static int
> ++acpi_get_irq_from_handle(acpi_handle handle,
> ++ uint16_t dev, uint16_t func, int pci_pin)
> +{
> + struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
> + struct acpi_buffer srs_buffer = { ACPI_ALLOCATE_BUFFER, NULL };
> + struct acpi_pci_routing_table *entry;
> + struct acpi_resource *res;
> -+ uint8_t *buf;
> + int srs_count;
> -+ int pci_pin;
> +
> -+ acpi_handle handle = ACPI_ROOT_OBJECT;
> -+ acpi_handle parent_handle = NULL;
> + acpi_handle prt = NULL;
> + acpi_handle lnk = NULL;
> + acpi_status err = AE_OK;
> + u16 prt_dev, prt_func;
> +
> -+ err = acpi_get_handle(handle, "\\_SB.PCI0", &parent_handle);
> -+ if (ACPI_FAILURE(err))
> -+ return -EIO;
> -+
> -+ err = acpi_get_handle(parent_handle, METHOD_NAME__PRT, &prt);
> ++ err = acpi_get_handle(handle, METHOD_NAME__PRT, &prt);
> + if (ACPI_FAILURE(err))
> + return -EIO;
> +
> @@ -538,7 +559,7 @@
> + if (ACPI_FAILURE(err))
> + return -EIO;
> +
> -+ err = acpi_get_irq_routing_table(parent_handle, &buffer);
> ++ err = acpi_get_irq_routing_table(handle, &buffer);
> + if (ACPI_FAILURE(err))
> + return -EIO;
> +
> @@ -546,11 +567,6 @@
> + if (BAD_PIC_MODE(pic_mode))
> + return -EIO;
> +
> -+ pci_pin = acpi_pci_get_device_pin(bus, dev, func);
> -+ /* Fail if the device pin used is unknown (0) */
> -+ if (pci_pin <= 0)
> -+ return -EIO;
> -+
> + entry = ACPI_CAST_PTR(struct acpi_pci_routing_table, ACPI_CAST_PTR(u8,
> buffer.pointer));
> + while (entry && (entry->length > 0))
> + {
> @@ -619,7 +635,6 @@
> + acpi_os_printf("Error setting _SRS\n");
> + return -EIO;
> + }
> -+ irq += (irq > LEGACY_ISA_IRQS) ? 0 : PCI_IRQ_START;
> + acpi_os_printf("Final irq %d\n", irq);
> + return irq;
> + }
> @@ -681,7 +696,6 @@
> + return -EIO;
> + }
> + free(res);
> -+ irq += (irq > LEGACY_ISA_IRQS) ? 0 : PCI_IRQ_START;
> + acpi_os_printf("Final irq %d\n", irq);
> + return irq;
> + }
> @@ -708,6 +722,55 @@
> + return -EIO;
> +}
> +
> ++static acpi_pci_bridge_t*
> ++acpi_find_pci_bridge(int bus)
> ++{
> ++ if (bus == 0)
> ++ return NULL;
> ++
> ++ acpi_pci_bridge_t* bridge = acpi_pci_bridges;
> ++
> ++ while (bridge != NULL)
> ++ {
> ++ if (bridge->down_bus == bus)
> ++ return bridge;
> ++
> ++ bridge = bridge->next;
> ++ }
> ++
> ++ return NULL;
> ++}
> ++
> ++int
> ++acpi_get_irq_number(uint16_t bus, uint16_t dev, uint16_t func)
> ++{
> ++ int pci_pin = acpi_pci_get_device_pin(bus, dev, func);
> ++ /* Fail if the device pin used is unknown (0) */
> ++ if (pci_pin <= 0)
> ++ return -EIO;
> ++
> ++ acpi_pci_bridge_t* bridge = acpi_find_pci_bridge(bus);
> ++
> ++ while (bridge != NULL)
> ++ {
> ++ int irq = acpi_get_irq_from_handle(bridge->handle, dev, func,
> pci_pin);
> ++ if (irq >= 0)
> ++ return irq;
> ++
> ++ /* Translate the downstream INTx to the upstream one */
> ++ pci_pin = ((pci_pin + dev) % 4);
> ++ bus = bridge->up_bus;
> ++ bridge = acpi_find_pci_bridge(bus);
> ++ }
> ++
> ++ acpi_handle handle;
> ++ acpi_status err = acpi_get_handle(ACPI_ROOT_OBJECT, "\\_SB.PCI0",
> &handle);
> ++ if (ACPI_FAILURE(err))
> ++ return -EIO;
> ++
> ++ return acpi_get_irq_from_handle(handle, dev, func, pci_pin);
> ++}
> ++
> +/* Fetch the active interrupt mode from GNU mach */
> +static error_t
> +acpi_required_pic_mode (void)
> @@ -792,6 +855,152 @@
> + return err;
> +}
> +
> ++static acpi_status
> ++acpi_pci_bridge_add(acpi_handle handle, uint8_t up_bus, uint8_t down_bus)
> ++{
> ++ acpi_pci_bridge_t* bridge =
> ++ (acpi_pci_bridge_t*)malloc(sizeof(acpi_pci_bridge_t));
> ++
> ++ if (bridge == NULL)
> ++ return AE_NO_MEMORY;
> ++
> ++ bridge->handle = handle;
> ++ bridge->up_bus = up_bus;
> ++ bridge->down_bus = down_bus;
> ++ bridge->next = acpi_pci_bridges;
> ++ acpi_pci_bridges = bridge;
> ++
> ++ return AE_OK;
> ++}
> ++
> ++struct acpi_find_bus_context
> ++{
> ++ int is_bridge; /* Is this level a bridge or not */
> ++ uint8_t down_bus; /* The downstream bus num if a bridge */
> ++ struct acpi_find_bus_context* parent;
> ++};
> ++
> ++static acpi_status
> ++acpi_find_busses_down(acpi_handle handle, uint32_t level,
> ++ void *context_arg, void **status)
> ++{
> ++ struct acpi_find_bus_context** context =
> ++ (struct acpi_find_bus_context**)context_arg;
> ++
> ++ struct acpi_device_info *devinfo;
> ++ acpi_status rv = acpi_get_object_info(handle, &devinfo);
> ++
> ++ if (ACPI_FAILURE(rv))
> ++ return rv;
> ++
> ++ struct acpi_find_bus_context* device_context =
> ++ (struct acpi_find_bus_context*)malloc(sizeof(struct
> acpi_find_bus_context));
> ++
> ++ if (device_context == NULL)
> ++ return AE_NO_MEMORY;
> ++
> ++ device_context->is_bridge = 0;
> ++ device_context->down_bus = 0;
> ++ device_context->parent = *context;
> ++ *context = device_context;
> ++
> ++ if (devinfo->flags & ACPI_PCI_ROOT_BRIDGE)
> ++ {
> ++ device_context->is_bridge = 1;
> ++ }
> ++ else if (device_context->parent->is_bridge && (devinfo->valid &
> ACPI_VALID_ADR))
> ++ {
> ++ uint8_t bus = device_context->parent->down_bus;
> ++ uint32_t devfunc = ACPI_LODWORD(devinfo->address);
> ++ uint16_t dev = ACPI_HIWORD(devfunc);
> ++ uint16_t func = ACPI_LOWORD(devfunc);
> ++
> ++ if (func <= PCI_MAX_FUNC_ID && dev <= PCI_MAX_DEV_ID)
> ++ {
> ++ struct acpi_pci_id pci_id =
> ++ {
> ++ .segment = 0, .bus = bus, .device = dev, .function = func
> ++ };
> ++ u64 val;
> ++
> ++ /* Ignore ACPI entries that refer to absent devices. */
> ++ if (acpi_os_read_pci_configuration(&pci_id, PCI_HDR_TYPE_REG, &val,
> 8))
> ++ goto exit;
> ++
> ++ {
> ++ /* Only 8 bits was read from the PCI configuration so cast OK. */
> ++ uint8_t hdrType = (uint8_t)val;
> ++ uint8_t mask = PCI_MULTI_FUNC_MASK;
> ++
> ++ if ((hdrType & ~mask) != PCI_HDR_TYPE_PPB)
> ++ goto exit;
> ++ }
> ++
> ++ if (acpi_os_read_pci_configuration(&pci_id, PCI_PPB_SECBUS_REG, &val,
> 8))
> ++ {
> ++ acpi_os_printf("Failed to find secondary bus for: %x:%x:%x\n",
> ++ bus, dev, func);
> ++ rv = AE_IO_ERROR;
> ++ goto exit;
> ++ }
> ++
> ++ /* Only 8 bits was read from the PCI configuration so cast OK. */
> ++ device_context->down_bus = (uint8_t)val;
> ++ device_context->is_bridge = 1;
> ++
> ++ rv = acpi_pci_bridge_add(handle, bus, device_context->down_bus);
> ++ }
> ++ }
> ++
> ++ exit:
> ++ ACPI_FREE(devinfo);
> ++
> ++ return rv;
> ++}
> ++
> ++static acpi_status
> ++acpi_find_busses_up(acpi_handle handle, uint32_t level,
> ++ void *context_arg, void **status)
> ++{
> ++ struct acpi_find_bus_context** context =
> ++ (struct acpi_find_bus_context**)context_arg;
> ++
> ++ struct acpi_find_bus_context* entry = *context;
> ++ *context = entry->parent;
> ++
> ++ free(entry);
> ++
> ++ return AE_OK;
> ++}
> ++
> ++static acpi_status
> ++acpi_load_pci_bridges(void)
> ++{
> ++ struct acpi_find_bus_context head_context =
> ++ {
> ++ .is_bridge = 0,
> ++ .down_bus = 0,
> ++ .parent = NULL
> ++ };
> ++
> ++ struct acpi_find_bus_context* context = &head_context;
> ++
> ++ acpi_status rv = acpi_walk_namespace
> ++ (ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT, UINT_MAX,
> ++ acpi_find_busses_down, acpi_find_busses_up, &context, NULL);
> ++
> ++ /* There should only be anything to free here in error cases */
> ++ while (context != &head_context)
> ++ {
> ++ struct acpi_find_bus_context* entry = context;
> ++ context = context->parent;
> ++
> ++ free(entry);
> ++ }
> ++
> ++ return rv;
> ++}
> ++
> +void acpi_init(void)
> +{
> + acpi_status err;
> @@ -815,6 +1024,10 @@
> + if (ACPI_FAILURE (err))
> + goto die;
> +
> ++ err = acpi_load_pci_bridges();
> ++ if (ACPI_FAILURE (err))
> ++ goto die;
> ++
> + /* Ignore return value for old gnumach without irq status */
> + acpi_configure_pic_mode();
> +
> @@ -831,8 +1044,10 @@
> +die:
> + acpi_os_printf("OUCH!\n");
> +}
> ---- /dev/null
> -+++ b/include/acpi/acpi_init.h
> +Index: libacpica/include/acpi/acpi_init.h
> +===================================================================
> +--- /dev/null 1970-01-01 00:00:00.000000000 +0000
> ++++ libacpica/include/acpi/acpi_init.h 2025-10-26 13:07:13.161934280
> +0000
> @@ -0,0 +1,11 @@
> +// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
> +#ifndef ACPI_INIT_H_
> --
> 2.39.5
>
>
--
Samuel
Now, it we had this sort of thing:
yield -a for yield to all traffic
yield -t for yield to trucks
yield -f for yield to people walking (yield foot)
yield -d t* for yield on days starting with t
...you'd have a lot of dead people at intersections, and traffic jams you
wouldn't believe...
(Discussion in comp.os.linux.misc on the intuitiveness of commands.)