Now the acpi server can know which interrupt controller is in use,
particularly useful on x86 ISA where there are two different ones.

Requires new device/irq_status.h gnumach header.

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..8f2080b 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>
 +
@@ -23,6 +23,7 @@
 +#include <limits.h>
 +
 +#include <device/device.h>
++#include <device/irq_status.h>
 +#include <hurd.h>
 +#include <pciaccess.h>
 +#include <hurd/irqhelp.h>
@@ -36,6 +37,7 @@
 +#define PCI_IRQ_START 16
 +
 +#define PCI_INTERRUPT_PIN 0x3d
++#define BAD_PIC_MODE(m) ((m) < ACPI_PICMODE_PIC || (m) > ACPI_PICMODE_SAPIC)
 +
 +extern acpi_status acpi_hw_legacy_sleep(u8 sleep_state);
 +
@@ -44,6 +46,7 @@
 +
 +static struct pci_device **pci_devices;
 +static int numdevs = -1;
++static int pic_mode = -1;
 +
 +struct slots {
 +  uint8_t bus;
@@ -539,6 +542,10 @@
 +  if (ACPI_FAILURE(err))
 +    return -EIO;
 +
++  /* If pic_mode is undetermined, ACPI cannot determine pci irq */
++  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)
@@ -701,6 +708,90 @@
 +  return -EIO;
 +}
 +
++/* Fetch the active interrupt mode from GNU mach */
++static error_t
++acpi_required_pic_mode (void)
++{
++  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);
++  mach_port_deallocate (mach_task_self (), devices);
++  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);
++    }
++
++  return err;
++}
++
++static error_t
++acpi_set_pic_mode (void)
++{
++  struct acpi_object_list arg;
++  union acpi_object obj;
++
++  if (BAD_PIC_MODE(pic_mode))
++    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)
++{
++  error_t err = acpi_required_pic_mode ();
++
++  if (err)
++    {
++      acpi_os_printf("Cannot determine PIC mode: %s\n", strerror(err));
++      return err;
++    }
++
++  err = acpi_set_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 +815,9 @@
 +  if (ACPI_FAILURE (err))
 +    goto die;
 +
++  /* Ignore return value for old gnumach without irq status */
++  acpi_configure_pic_mode();
++
 +  err = acpi_enable_subsystem (ACPI_FULL_INITIALIZATION);
 +  if (ACPI_FAILURE (err))
 +    goto die;
-- 
2.45.2



Reply via email to