# This is a BitKeeper generated diff -Nru style patch.
#
# ChangeSet
#   2004/03/22 03:07:07-05:00 len.brown@intel.com 
#   [ACPI] ACPI SCI shall be level/low when compatible or absent override
#   http://bugzilla.kernel.org/show_bug.cgi?id=1622
# 
# include/asm-i386/mpspec.h
#   2004/03/22 03:05:10-05:00 len.brown@intel.com +0 -7
#   delete mp_config_ioapic_for_sci()
# 
# drivers/acpi/bus.c
#   2004/03/22 03:05:10-05:00 len.brown@intel.com +6 -6
#   delete mp_config_ioapic_for_sci()
#   add param to acpi_pic_sci_set_trigger.
# 
# arch/i386/kernel/setup.c
#   2004/03/22 03:05:10-05:00 len.brown@intel.com +13 -0
#   add acpi_sci= -- they need to be early to preceed MADT table parsing
# 
# arch/i386/kernel/mpparse.c
#   2004/03/22 03:05:10-05:00 len.brown@intel.com +0 -63
#   delete mp_config_ioapic_for_sci() -- it had several problems.
#   walking the MADT was redundant
#   not setting flags for no-override case to level/low was incorrect
#   calling io_apic_set_pci_routing() on a legacy IRQ was incorrect
# 
# arch/i386/kernel/acpi/boot.c
#   2004/03/22 03:05:10-05:00 len.brown@intel.com +63 -33
#   add acpi_parse_sci_int_src_ovr() for handling SCI interrupt flags
#   grab the SCI from the early FADT parse
#   fix typo in acpi_pic_sci_set_triger() that allowed it only to set for level trigger
# 
# Documentation/kernel-parameters.txt
#   2004/03/22 03:05:10-05:00 len.brown@intel.com +2 -4
#   replace acpi_pic_sci= with acpi_sci=
# 
diff -Nru a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
--- a/Documentation/kernel-parameters.txt	Mon Mar 22 03:07:18 2004
+++ b/Documentation/kernel-parameters.txt	Mon Mar 22 03:07:18 2004
@@ -99,10 +99,8 @@
 
 			See also Documentation/pm.txt.
  
-	acpi_pic_sci=	[HW,ACPI] ACPI System Control Interrupt trigger mode
-			Format: { level | edge }
-			level   Force PIC-mode SCI to Level Trigger (default)
-			edge    Force PIC-mode SCI to Edge Trigge
+	acpi_sci=	[HW,ACPI] ACPI System Control Interrupt trigger mode
+			Format: { level | edge |  high | low }
 
 	acpi_irq_balance	[HW,ACPI] ACPI will balance active IRQs
 				default in APIC mode
diff -Nru a/arch/i386/kernel/acpi/boot.c b/arch/i386/kernel/acpi/boot.c
--- a/arch/i386/kernel/acpi/boot.c	Mon Mar 22 03:07:18 2004
+++ b/arch/i386/kernel/acpi/boot.c	Mon Mar 22 03:07:18 2004
@@ -50,6 +50,8 @@
 int acpi_ioapic;
 int acpi_strict;
 
+acpi_interrupt_flags __initdata acpi_sci_flags;
+
 #ifdef CONFIG_X86_LOCAL_APIC
 static u64 acpi_lapic_addr __initdata = APIC_DEFAULT_PHYS_BASE;
 #endif
@@ -244,6 +246,33 @@
 	return 0;
 }
 
+static int __initdata acpi_sci_int_src_ovr_parsed;
+
+/*
+ * Parse Interrupt Source Override for the ACPI SCI
+ */
+static void
+acpi_parse_sci_int_src_ovr(u8 bus_irq, u16 polarity, u16 trigger, u32 global_irq)
+{
+	if (trigger == 0)	/* compatible SCI trigger is level */
+		trigger = 3;
+
+	if (polarity == 0)	/* compatible SCI polarity is low */
+		polarity = 3;
+
+	/* Command-line over-ride via acpi_sci= */
+	if (acpi_sci_flags.trigger)
+		trigger = acpi_sci_flags.trigger;
+
+	if (acpi_sci_flags.polarity)
+		polarity = acpi_sci_flags.polarity;
+
+	mp_override_legacy_irq(bus_irq, polarity, trigger, global_irq);
+
+	acpi_fadt.sci_int = global_irq;
+	acpi_sci_int_src_ovr_parsed = 1;
+	return;
+}
 
 static int __init
 acpi_parse_int_src_ovr (
@@ -257,6 +286,13 @@
 
 	acpi_table_print_madt_entry(header);
 
+	if (intsrc->bus_irq == acpi_fadt.sci_int) {
+		acpi_parse_sci_int_src_ovr(intsrc->bus_irq,
+			intsrc->flags.polarity, intsrc->flags.trigger,
+			intsrc->global_irq);
+		return 0;
+	}
+
 	mp_override_legacy_irq (
 		intsrc->bus_irq,
 		intsrc->flags.polarity,
@@ -287,14 +323,14 @@
 #endif /* CONFIG_X86_IO_APIC */
 
 #ifdef	CONFIG_ACPI_BUS
+
 /*
- * "acpi_pic_sci=level" (current default)
- * programs the PIC-mode SCI to Level Trigger.
- * (NO-OP if the BIOS set Level Trigger already)
+ * acpi_pic_sci_set_trigger()
+ * 
+ * use ELCR to set PIC-mode trigger type for SCI
  *
  * If a PIC-mode SCI is not recognized or gives spurious IRQ7's
- * it may require Edge Trigger -- use "acpi_pic_sci=edge"
- * (NO-OP if the BIOS set Edge Trigger already)
+ * it may require Edge Trigger -- use "acpi_sci=edge"
  *
  * Port 0x4d0-4d1 are ECLR1 and ECLR2, the Edge/Level Control Registers
  * for the 8259 PIC.  bit[n] = 1 means irq[n] is Level, otherwise Edge.
@@ -302,10 +338,8 @@
  * ECLR2 is IRQ's 8-15 (IRQ 8, 13 must be 0)
  */
 
-static int __initdata	acpi_pic_sci_trigger;	/* 0: level, 1: edge */
-
 void __init
-acpi_pic_sci_set_trigger(unsigned int irq)
+acpi_pic_sci_set_trigger(unsigned int irq, u16 trigger)
 {
 	unsigned char mask = 1 << (irq & 7);
 	unsigned int port = 0x4d0 + (irq >> 3);
@@ -316,37 +350,21 @@
 	if (!(val & mask)) {
 		printk(" Edge");
 
-		if (!acpi_pic_sci_trigger) {
+		if (trigger == 3) {
 			printk(" set to Level");
 			outb(val | mask, port);
 		}
 	} else {
 		printk(" Level");
 
-		if (acpi_pic_sci_trigger) {
+		if (trigger == 1) {
 			printk(" set to Edge");
-			outb(val | mask, port);
+			outb(val & ~mask, port);
 		}
 	}
 	printk(" Trigger.\n");
 }
 
-int __init
-acpi_pic_sci_setup(char *str)
-{
-	while (str && *str) {
-		if (strncmp(str, "level", 5) == 0)
-			acpi_pic_sci_trigger = 0;	/* force level trigger */
-		if (strncmp(str, "edge", 4) == 0)
-			acpi_pic_sci_trigger = 1;	/* force edge trigger */
-		str = strchr(str, ',');
-		if (str)
-			str += strspn(str, ", \t");
-	}
-	return 1;
-}
-
-__setup("acpi_pic_sci=", acpi_pic_sci_setup);
 
 #endif /* CONFIG_ACPI_BUS */
 
@@ -442,8 +460,6 @@
 #define	acpi_parse_hpet	NULL
 #endif
 
-/* detect the location of the ACPI PM Timer */
-#ifdef CONFIG_X86_PM_TIMER
 extern u32 pmtmr_ioport;
 
 static int __init acpi_parse_fadt(unsigned long phys, unsigned long size)
@@ -456,6 +472,11 @@
 		return 0;
 	}
 
+	/* get sci_int */
+	acpi_fadt.sci_int = fadt->sci_int;
+
+#ifdef CONFIG_X86_PM_TIMER
+	/* detect the location of the ACPI PM Timer */
 	if (fadt->revision >= FADT2_REVISION_ID) {
 		/* FADT rev. 2 */
 		if (fadt->xpm_tmr_blk.address_space_id != ACPI_ADR_SPACE_SYSTEM_IO)
@@ -468,11 +489,9 @@
 	}
 	if (pmtmr_ioport)
 		printk(KERN_INFO PREFIX "PM-Timer IO Port: %#x\n", pmtmr_ioport);
+#endif
 	return 0;
 }
-#else
-#define	acpi_parse_fadt	NULL
-#endif
 
 
 unsigned long __init
@@ -592,6 +611,13 @@
 		return count;
 	}
 
+	/*
+	 * If BIOS did not supply an INT_SRC_OVR for the SCI
+	 * set SCI to defaults.
+	 */
+	if (!acpi_sci_int_src_ovr_parsed)
+		acpi_parse_sci_int_src_ovr(acpi_fadt.sci_int, 0, 0, acpi_fadt.sci_int);
+
 	count = acpi_table_parse_madt(ACPI_MADT_NMI_SRC, acpi_parse_nmi_src, NR_IRQ_VECTORS);
 	if (count < 0) {
 		printk(KERN_ERR PREFIX "Error parsing NMI SRC entry\n");
@@ -697,11 +723,15 @@
 	}
 
 	/*
+	 * set sci_int and PM timer address
+	 */
+	acpi_table_parse(ACPI_FADT, acpi_parse_fadt);
+
+	/*
 	 * Process the Multiple APIC Description Table (MADT), if present
 	 */
 	acpi_process_madt();
 
-	acpi_table_parse(ACPI_FADT, acpi_parse_fadt);
 	acpi_table_parse(ACPI_HPET, acpi_parse_hpet);
 	acpi_table_parse(ACPI_MCFG, acpi_parse_mcfg);
 
diff -Nru a/arch/i386/kernel/mpparse.c b/arch/i386/kernel/mpparse.c
--- a/arch/i386/kernel/mpparse.c	Mon Mar 22 03:07:18 2004
+++ b/arch/i386/kernel/mpparse.c	Mon Mar 22 03:07:18 2004
@@ -1036,69 +1036,6 @@
 
 extern FADT_DESCRIPTOR acpi_fadt;
 
-void __init mp_config_ioapic_for_sci(u32 gsi)
-{
-	int ioapic;
-	int ioapic_pin;
-	struct acpi_table_madt *madt;
-	struct acpi_table_int_src_ovr *entry = NULL;
-	acpi_interrupt_flags flags;
-	void *madt_end;
-	acpi_status status;
-
-	/*
-	 * Ensure that if there is an interrupt source override entry
-	 * for the ACPI SCI, we leave it as is. Unfortunately this involves
-	 * walking the MADT again.
-	 */
-	status = acpi_get_firmware_table("APIC", 1, ACPI_LOGICAL_ADDRESSING,
-		(struct acpi_table_header **) &madt);
-	if (ACPI_SUCCESS(status)) {
-		madt_end = (void *) (unsigned long)madt + madt->header.length;
-
-		entry = (struct acpi_table_int_src_ovr *)
-                ((unsigned long) madt + sizeof(struct acpi_table_madt));
-
-		while ((void *) entry < madt_end) {
-                	if (entry->header.type == ACPI_MADT_INT_SRC_OVR &&
-			    acpi_fadt.sci_int == entry->bus_irq)
-				goto found;
-			
-                	entry = (struct acpi_table_int_src_ovr *)
-                	        ((unsigned long) entry + entry->header.length);
-        	}
-	}
-	/*
-	 * Although the ACPI spec says that the SCI should be level/low
-	 * don't reprogram it unless there is an explicit MADT OVR entry
-	 * instructing us to do so -- otherwise we break Tyan boards which
-	 * have the SCI wired edge/high but no MADT OVR.
-	 */
-	return;
-
-found:
-	/*
-	 * See the note at the end of ACPI 2.0b section
-	 * 5.2.10.8 for what this is about.
-	 */
-	flags = entry->flags;
-	acpi_fadt.sci_int = entry->global_irq;
-	gsi = entry->global_irq;
-
-	ioapic = mp_find_ioapic(gsi);
-
-	ioapic_pin = gsi - mp_ioapic_routing[ioapic].gsi_base;
-
-	/*
-	 * MPS INTI flags:
-	 *  trigger: 0=default, 1=edge, 3=level
-	 *  polarity: 0=default, 1=high, 3=low
-	 * Per ACPI spec, default for SCI means level/low.
-	 */
-	io_apic_set_pci_routing(ioapic, ioapic_pin, gsi, 
-		(flags.trigger == 1 ? 0 : 1), (flags.polarity == 1 ? 0 : 1));
-}
-
 #ifdef CONFIG_ACPI_PCI
 
 void __init mp_parse_prt (void)
diff -Nru a/arch/i386/kernel/setup.c b/arch/i386/kernel/setup.c
--- a/arch/i386/kernel/setup.c	Mon Mar 22 03:07:18 2004
+++ b/arch/i386/kernel/setup.c	Mon Mar 22 03:07:18 2004
@@ -79,6 +79,7 @@
 
 #ifdef	CONFIG_ACPI_BOOT
 int __initdata acpi_force = 0;
+extern acpi_interrupt_flags	acpi_sci_flags;
 #endif
 
 int MCA_bus;
@@ -595,6 +596,18 @@
 		else if (!memcmp(from, "pci=noacpi", 10)) {
 			acpi_noirq_set();
 		}
+
+		else if (!memcmp(from, "acpi_sci=edge", 13))
+			acpi_sci_flags.trigger =  1;
+
+		else if (!memcmp(from, "acpi_sci=level", 14))
+			acpi_sci_flags.trigger = 3;
+
+		else if (!memcmp(from, "acpi_sci=high", 13))
+			acpi_sci_flags.polarity = 1;
+
+		else if (!memcmp(from, "acpi_sci=low", 12))
+			acpi_sci_flags.polarity = 3;
 
 #ifdef CONFIG_X86_LOCAL_APIC
 		/* disable IO-APIC */
diff -Nru a/drivers/acpi/bus.c b/drivers/acpi/bus.c
--- a/drivers/acpi/bus.c	Mon Mar 22 03:07:18 2004
+++ b/drivers/acpi/bus.c	Mon Mar 22 03:07:18 2004
@@ -39,7 +39,7 @@
 #define _COMPONENT		ACPI_BUS_COMPONENT
 ACPI_MODULE_NAME		("acpi_bus")
 
-extern void __init acpi_pic_sci_set_trigger(unsigned int irq);
+extern void __init acpi_pic_sci_set_trigger(unsigned int irq, u16 trigger);
 
 FADT_DESCRIPTOR			acpi_fadt;
 struct acpi_device		*acpi_root;
@@ -611,11 +611,11 @@
 	}
 
 #ifdef CONFIG_X86
-	/* Ensure the SCI is set to level-triggered, active-low */
-	if (acpi_ioapic)
-		mp_config_ioapic_for_sci(acpi_fadt.sci_int);
-	else
-		acpi_pic_sci_set_trigger(acpi_fadt.sci_int);
+	/* For PIC, set Edge/Level for SCI */
+	if (!acpi_ioapic) {
+		extern acpi_interrupt_flags acpi_sci_flags;
+		acpi_pic_sci_set_trigger(acpi_fadt.sci_int, acpi_sci_flags.trigger);
+	}
 #endif
 
 	status = acpi_enable_subsystem(ACPI_FULL_INITIALIZATION);
diff -Nru a/include/asm-i386/mpspec.h b/include/asm-i386/mpspec.h
--- a/include/asm-i386/mpspec.h	Mon Mar 22 03:07:18 2004
+++ b/include/asm-i386/mpspec.h	Mon Mar 22 03:07:18 2004
@@ -34,13 +34,6 @@
 extern void mp_override_legacy_irq (u8 bus_irq, u8 polarity, u8 trigger, u32 gsi);
 extern void mp_config_acpi_legacy_irqs (void);
 extern void mp_parse_prt (void);
-
-#ifdef CONFIG_X86_IO_APIC
-extern void mp_config_ioapic_for_sci(u32 gsi);
-#else
-static inline void mp_config_ioapic_for_sci(u32 gsi)
-{ }
-#endif
 #endif /*CONFIG_ACPI_BOOT*/
 
 #define PHYSID_ARRAY_SIZE	BITS_TO_LONGS(MAX_APICS)