From 918338e3f37f91a14d230a9ccf3c3387a2b58617 Mon Sep 17 00:00:00 2001
From: Guido Guenther <guido.guenther@diplo.de>
Date: Fri, 4 Jan 2008 19:26:33 +0100
Subject: [PATCH] add interrupt override entries for IRQs 5,9,10,11 to the MADT

so the OS knows that they're active high, level triggered. This fixes the ACPI
power button and should also fix the ACPI timer.

diff --git a/bios/rombios32.c b/bios/rombios32.c
index 7a96ece..e5a9bd5 100755
--- a/bios/rombios32.c
+++ b/bios/rombios32.c
@@ -55,6 +55,9 @@ typedef unsigned long long uint64_t;
 #define APIC_ID      0x020
 #define APIC_LVT3    0x370
 
+/* IRQs 5,9,10,11 */
+#define PCI_ISA_IRQ_MASK    0x0e20U
+
 #define APIC_ENABLED 0x0100
 
 #define AP_BOOT_ADDR 0x10000
@@ -1181,6 +1184,14 @@ struct madt_io_apic
 			  * lines start */
 };
 
+struct madt_intsrcovr {
+	APIC_HEADER_DEF
+	uint8_t  bus;
+	uint8_t  source;
+	uint32_t gsi;
+	uint16_t flags;
+};
+
 #include "acpi-dsdt.hex"
 
 static inline uint16_t cpu_to_le16(uint16_t x)
@@ -1271,7 +1282,7 @@ void acpi_bios_init(void)
 
     addr = (addr + 7) & ~7;
     madt_addr = addr;
-    madt_size = sizeof(*madt) + 
+    madt_size = sizeof(*madt) +
         sizeof(struct madt_processor_apic) * smp_cpus +
         sizeof(struct madt_io_apic);
     madt = (void *)(addr);
@@ -1335,6 +1346,7 @@ void acpi_bios_init(void)
     {
         struct madt_processor_apic *apic;
         struct madt_io_apic *io_apic;
+        struct madt_intsrcovr *intsrcovr;
 
         memset(madt, 0, madt_size);
         madt->local_apic_address = cpu_to_le32(0xfee00000);
@@ -1355,6 +1367,23 @@ void acpi_bios_init(void)
         io_apic->address = cpu_to_le32(0xfec00000);
         io_apic->interrupt = cpu_to_le32(0);
 
+	/* PCI IRQs are active high atm */
+        intsrcovr = (struct madt_intsrcovr*)(io_apic + 1);
+        for ( i = 0; i < 16; i++ ) {
+            if ( PCI_ISA_IRQ_MASK & (1U << i) ) {
+                memset(intsrcovr, 0, sizeof(*intsrcovr));
+                intsrcovr->type   = APIC_XRUPT_OVERRIDE;
+                intsrcovr->length = sizeof(*intsrcovr);
+                intsrcovr->source = i;
+                intsrcovr->gsi    = i;
+                intsrcovr->flags  = 0xd; /* active high, level triggered */
+            } else {
+                /* No need for a INT source override structure. */
+                continue;
+            }
+            intsrcovr++;
+            madt_size += sizeof(struct madt_intsrcovr);
+        }
         acpi_build_table_header((struct acpi_table_header *)madt, 
                                 "APIC", madt_size);
     }
