patch-2.1.123 linux/arch/i386/kernel/io_apic.c

Next file: linux/arch/i386/kernel/process.c
Previous file: linux/arch/i386/kernel/bios32.c
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.1.122/linux/arch/i386/kernel/io_apic.c linux/arch/i386/kernel/io_apic.c
@@ -291,6 +291,43 @@
 }
 
 /*
+ * ISA Edge/Level control register, ELCR
+ */
+static int __init ISA_ELCR(unsigned int irq)
+{
+	if (irq < 16) {
+		unsigned int port = 0x4d0 + (irq >> 3);
+		return (inb(port) >> (irq & 7)) & 1;
+	}
+	printk("Broken MPtable reports ISA irq %d\n", irq);
+	return 0;
+}	
+
+/*
+ * ISA interrupts can be:
+ *  - level triggered, active low (ELCR = 1)
+ *  - edge triggered, active high (ELCR = 0)
+ *  - edge triggered, active low (magic irq 8)
+ */
+static int __init default_ISA_trigger(int idx)
+{
+	unsigned int irq = mp_irqs[idx].mpc_dstirq;
+
+	if (irq == 8)
+		return 0;
+	return ISA_ELCR(irq);
+}
+
+static int __init default_ISA_polarity(int idx)
+{
+	unsigned int irq = mp_irqs[idx].mpc_dstirq;
+
+	if (irq == 8)
+		return 1;
+	return ISA_ELCR(irq);
+}
+
+/*
  * There are broken mptables which register ISA+high-active+level IRQs,
  * these are illegal and are converted here to ISA+high-active+edge
  * IRQ sources. Careful, ISA+low-active+level is another broken entry
@@ -314,7 +351,7 @@
 			{
 				case MP_BUS_ISA: /* ISA pin */
 				{
-					polarity = 0;
+					polarity = default_ISA_polarity(idx);
 					break;
 				}
 				case MP_BUS_PCI: /* PCI pin */
@@ -371,9 +408,9 @@
 		{
 			switch (mp_bus_id_to_type[bus])
 			{
-				case MP_BUS_ISA: /* ISA pin, edge */
+				case MP_BUS_ISA:
 				{
-					trigger = 0;
+					trigger = default_ISA_trigger(idx);
 					break;
 				}
 				case MP_BUS_PCI: /* PCI pin, level */
@@ -549,7 +586,7 @@
 		entry.delivery_mode = dest_LowestPrio;
 		entry.dest_mode = 1;			/* logical delivery */
 		entry.mask = 0;				/* enable IRQ */
-		entry.dest.logical.logical_dest = 0xff;	/* all CPUs */
+		entry.dest.logical.logical_dest = 0;	/* but no route */
 
 		idx = find_irq_entry(pin,mp_INT);
 		if (idx == -1) {
@@ -564,6 +601,12 @@
 		entry.trigger = irq_trigger(idx);
 		entry.polarity = irq_polarity(idx);
 
+		if (irq_trigger(idx)) {
+			entry.trigger = 1;
+			entry.mask = 1;
+			entry.dest.logical.logical_dest = 0xff;
+		}
+
 		irq = pin_2_irq(idx,pin);
 		irq_2_pin[irq] = pin;
 
@@ -577,37 +620,14 @@
 		if (trigger_flag_broken (idx))
 			printk("broken BIOS, changing pin %d to edge\n", pin);
 
-		io_apic_write(0x10+2*pin, *(((int *)&entry)+0));
 		io_apic_write(0x11+2*pin, *(((int *)&entry)+1));
+		io_apic_write(0x10+2*pin, *(((int *)&entry)+0));
 	}
 
 	if (!first_notcon)
 		printk(" not connected.\n");
 }
 
-void __init setup_IO_APIC_irq_ISA_default(unsigned int irq)
-{
-	struct IO_APIC_route_entry entry;
-
-	/*
-	 * add it to the IO-APIC irq-routing table:
-	 */
-	memset(&entry,0,sizeof(entry));
-
-	entry.delivery_mode = dest_LowestPrio;		/* lowest prio */
-	entry.dest_mode = 1;				/* logical delivery */
-	entry.mask = 0;					/* unmask IRQ now */
-	entry.dest.logical.logical_dest = 0xff;		/* all CPUs */
-
-	entry.vector = assign_irq_vector(irq);
-
-	entry.polarity = 0;
-	entry.trigger = 0;
-
-	io_apic_write(0x10+2*irq, *(((int *)&entry)+0));
-	io_apic_write(0x11+2*irq, *(((int *)&entry)+1));
-}
-
 /*
  * Set up a certain pin as ExtINT delivered interrupt
  */
@@ -623,7 +643,7 @@
 	entry.delivery_mode = dest_ExtINT;
 	entry.dest_mode = 1;				/* logical delivery */
 	entry.mask = 0;					/* unmask IRQ now */
-	entry.dest.logical.logical_dest = 0x01;		/* all CPUs */
+	entry.dest.logical.logical_dest = 0x01;		/* logical CPU #0 */
 
 	entry.vector = 0;				/* it's ignored */
 
@@ -1141,8 +1161,9 @@
 
 	pin1 = find_timer_pin(mp_INT);
 	pin2 = find_timer_pin(mp_ExtINT);
-
+	enable_IO_APIC_irq(0);
 	if (!timer_irq_works()) {
+
 		if (pin1 != -1)
 			printk("..MP-BIOS bug: 8254 timer not connected to IO-APIC\n");
 		printk("...trying to set up timer as ExtINT... ");

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov