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
- Lines: 146
- Date:
Sun Sep 27 19:20:20 1998
- Orig file:
v2.1.122/linux/arch/i386/kernel/io_apic.c
- Orig date:
Thu Sep 17 17:53:34 1998
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