Now the acpi server can know which interrupt controller is in use, particularly useful on x86 ISA where there are two different ones.
TESTED: With this patch, 1/2 and the gnumach irq device patch, Hurd i386 boots with apic on Thinkpad W530. Also still boots on qemu (with different irq numbers detected). Also-by: Michael Kelly <[email protected]> --- debian/patches/acpi-init-files.diff | 96 ++++++++++++++++++++++++++++- 1 file changed, 95 insertions(+), 1 deletion(-) diff --git a/debian/patches/acpi-init-files.diff b/debian/patches/acpi-init-files.diff index 3f95537..aad4c95 100644 --- a/debian/patches/acpi-init-files.diff +++ b/debian/patches/acpi-init-files.diff @@ -1,6 +1,6 @@ --- /dev/null +++ b/acpi_init.c -@@ -0,0 +1,736 @@ +@@ -0,0 +1,830 @@ +// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0 +#include <acpi/acpi.h> + @@ -701,6 +701,96 @@ + return -EIO; +} + ++#define IRQGETPICMODE 0 ++# define ACPI_PICMODE_PIC 0 ++# define ACPI_PICMODE_APIC 1 ++# define ACPI_PICMODE_SAPIC 2 ++ ++/* Fetch the active interrupt mode from GNU mach */ ++static error_t ++acpi_required_pic_mode (int* pic_mode) ++{ ++ mach_port_t devices = MACH_PORT_NULL, irq; ++ mach_msg_type_number_t cnt = 0; ++ ++ error_t err = get_privileged_ports(NULL, &devices); ++ if (err) ++ return err; ++ ++ if (devices == MACH_PORT_NULL) ++ return ENODEV; ++ ++ err = device_open(devices, D_READ, "irq", &irq); ++ if (!err) ++ { ++ /* Determine if the IRQGETPICMODE feature is available in the ++ running kernel by specifying a NULL array for 'status'. If ++ the feature is available then MIG_ARRAY_TOO_LARGE is returned ++ as the returned status cannot fit in the result. ++ */ ++ if (device_get_status(irq, IRQGETPICMODE, NULL, &cnt) ++ != MIG_ARRAY_TOO_LARGE) ++ err = ENOSYS; ++ else ++ { ++ cnt = 1; ++ err = device_get_status(irq, IRQGETPICMODE, pic_mode, &cnt); ++ } ++ ++ device_close(irq); ++ } ++ ++ mach_port_deallocate (mach_task_self (), devices); ++ return err; ++} ++ ++static error_t ++acpi_set_pic_mode (int pic_mode) ++{ ++ struct acpi_object_list arg; ++ union acpi_object obj; ++ ++ if (pic_mode < ACPI_PICMODE_PIC || pic_mode > ACPI_PICMODE_SAPIC) ++ return EINVAL; ++ ++ obj.type = ACPI_TYPE_INTEGER; ++ obj.integer.value = pic_mode; ++ ++ arg.count = 1; ++ arg.pointer = &obj; ++ ++ acpi_handle handle = ACPI_ROOT_OBJECT; ++ acpi_status rv = acpi_evaluate_object(handle, "\\_PIC", &arg, NULL); ++ ++ /* A failure of AE_NOT_FOUND means the \_PIC method is not supported. ++ The default for the system in this case is ACPI_PICMODE_PIC, so ++ it is only a concern if an attempt is made to set a different mode. ++ */ ++ return (ACPI_FAILURE(rv) ++ && (rv != AE_NOT_FOUND || (pic_mode != ACPI_PICMODE_PIC)) ++ ? EIO ++ : 0); ++} ++ ++static error_t ++acpi_configure_pic_mode (void) ++{ ++ int pic_mode = -1; ++ error_t err = acpi_required_pic_mode (&pic_mode); ++ ++ if (err) ++ { ++ acpi_os_printf("Cannot determine PIC mode: %s\n", strerror(err)); ++ return err; ++ } ++ ++ err = acpi_set_pic_mode (pic_mode); ++ if (err) ++ acpi_os_printf("Failed to set ACPI PIC mode: %s\n", strerror(err)); ++ ++ return err; ++} ++ +void acpi_init(void) +{ + acpi_status err; @@ -724,6 +814,10 @@ + if (ACPI_FAILURE (err)) + goto die; + ++ err = acpi_configure_pic_mode(); ++ if (err) ++ goto die; ++ + err = acpi_enable_subsystem (ACPI_FULL_INITIALIZATION); + if (ACPI_FAILURE (err)) + goto die; -- 2.45.2
