ioapic_abi: More consistent function name w/ legacy interrupt
[dragonfly.git] / sys / platform / pc64 / isa / clock.c
index c45267a..13c5589 100644 (file)
 #include <machine/specialreg.h>
 #include <machine/intr_machdep.h>
 
+#include <machine_base/apic/ioapic.h>
+#include <machine_base/apic/ioapic_abi.h>
 #include <machine_base/icu/icu.h>
 #include <bus/isa/isa.h>
 #include <bus/isa/rtc.h>
 #include <machine_base/isa/timerreg.h>
 
-#ifdef SMP /* APIC-IO */
-/* The interrupt triggered by the 8254 (timer) chip */
-static void setup_8254_mixed_mode (void);
-#endif
 static void i8254_restore(void);
 static void resettodr_on_shutdown(void *arg __unused);
 
@@ -133,7 +131,7 @@ static  int rtc_loaded;
 static int i8254_cputimer_div;
 
 static int i8254_nointr;
-static int i8254_intr_disable = 0;
+static int i8254_intr_disable = 1;
 TUNABLE_INT("hw.i8254.intr_disable", &i8254_intr_disable);
 
 static struct callout sysbeepstop_ch;
@@ -211,7 +209,7 @@ clkintr(void *dummy, void *frame_arg)
                continue;
            if (gscan != gd) {
                lwkt_send_ipiq3(gscan, (ipifunc3_t)systimer_intr, 
-                               &sysclock_count, 0);
+                               &sysclock_count, 1);
            } else {
                systimer_intr(&sysclock_count, 0, frame_arg);
            }
@@ -1008,6 +1006,36 @@ resettodr(void)
        crit_exit();
 }
 
+static int
+i8254_ioapic_trial(int irq, struct cputimer_intr *cti)
+{
+       sysclock_t base;
+       long lastcnt;
+
+       /*
+        * Following code assumes the 8254 is the cpu timer,
+        * so make sure it is.
+        */
+       KKASSERT(sys_cputimer == &i8254_cputimer);
+       KKASSERT(cti == &i8254_cputimer_intr);
+
+       lastcnt = get_interrupt_counter(irq, mycpuid);
+
+       /*
+        * Force an 8254 Timer0 interrupt and wait 1/100s for
+        * it to happen, then see if we got it.
+        */
+       kprintf("IOAPIC: testing 8254 interrupt delivery\n");
+
+       i8254_intr_reload(cti, 2);
+       base = sys_cputimer->count();
+       while (sys_cputimer->count() - base < sys_cputimer->freq / 100)
+               ; /* nothing */
+
+       if (get_interrupt_counter(irq, mycpuid) - lastcnt == 0)
+               return ENOENT;
+       return 0;
+}
 
 /*
  * Start both clocks running.  DragonFly note: the stat clock is no longer
@@ -1017,19 +1045,14 @@ resettodr(void)
 static void
 i8254_intr_initclock(struct cputimer_intr *cti, boolean_t selected)
 {
-#ifdef SMP /* APIC-IO */
-       int apic_8254_trial = 0;
        void *clkdesc = NULL;
-       int irq = 0;
-#endif
+       int irq = 0, mixed_mode = 0, error;
 
-       callout_init(&sysbeepstop_ch);
+       KKASSERT(mycpuid == 0);
+       callout_init_mp(&sysbeepstop_ch);
 
-       if (!selected && i8254_intr_disable) {
-               i8254_nointr = 1; /* don't try to register again */
-               cputimer_intr_deregister(cti);
-               return;
-       }
+       if (!selected && i8254_intr_disable)
+               goto nointr;
 
        /*
         * The stat interrupt mask is different without the
@@ -1040,140 +1063,74 @@ i8254_intr_initclock(struct cputimer_intr *cti, boolean_t selected)
        rtc_statusb = RTCSB_24HR;
 
        /* Finish initializing 8254 timer 0. */
-#ifdef SMP /* APIC-IO */
-if (apic_io_enable) {
-       if (ioapic_use_old) {
-               irq = isa_apic_irq(0);
-               if (irq >= 0 ) {
-                       if (apic_int_type(0, 0) == 3)
-                               apic_8254_trial = 1;
-               } else {
-                       /* look for ExtInt on pin 0 */
-                       if (apic_int_type(0, 0) == 3) {
-                               irq = apic_irq(0, 0);
-                               setup_8254_mixed_mode();
-                       } else {
-                               panic("APIC_IO: Cannot route 8254 "
-                                     "interrupt to CPU");
+       if (ioapic_enable) {
+               irq = ioapic_find_legacy_by_irq(0, INTR_TRIGGER_EDGE,
+                       INTR_POLARITY_HIGH);
+               if (irq < 0) {
+mixed_mode_setup:
+                       error = ioapic_conf_legacy_extint(0);
+                       if (!error) {
+                               irq = ioapic_find_legacy_by_irq(0,
+                                   INTR_TRIGGER_EDGE, INTR_POLARITY_HIGH);
+                               if (irq < 0)
+                                       error = ENOENT;
                        }
-               }
 
+                       if (error) {
+                               if (!selected) {
+                                       kprintf("IOAPIC: setup mixed mode for "
+                                               "irq 0 failed: %d\n", error);
+                                       goto nointr;
+                               } else {
+                                       panic("IOAPIC: setup mixed mode for "
+                                             "irq 0 failed: %d\n", error);
+                               }
+                       }
+                       mixed_mode = 1;
+               }
                clkdesc = register_int(irq, clkintr, NULL, "clk",
                                       NULL,
                                       INTR_EXCL | INTR_CLOCK |
-                                      INTR_NOPOLL | INTR_MPSAFE | 
-                                      INTR_NOENTROPY);
-               machintr_intren(irq);
+                                      INTR_NOPOLL | INTR_MPSAFE |
+                                      INTR_NOENTROPY, 0);
+       } else {
+               register_int(0, clkintr, NULL, "clk", NULL,
+                            INTR_EXCL | INTR_CLOCK |
+                            INTR_NOPOLL | INTR_MPSAFE |
+                            INTR_NOENTROPY, 0);
        }
-} else {
-#endif
-       register_int(0, clkintr, NULL, "clk", NULL,
-                    INTR_EXCL | INTR_CLOCK |
-                    INTR_NOPOLL | INTR_MPSAFE |
-                    INTR_NOENTROPY);
-       machintr_intren(0);
-#ifdef SMP /* APIC-IO */
-}
-#endif
 
        /* Initialize RTC. */
        writertc(RTC_STATUSA, rtc_statusa);
        writertc(RTC_STATUSB, RTCSB_24HR);
 
-#ifdef SMP /* APIC-IO */
-if (apic_io_enable && ioapic_use_old) {
-       if (apic_8254_trial) {
-               sysclock_t base;
-               long lastcnt;
-
-               /*
-                * Following code assumes the 8254 is the cpu timer,
-                * so make sure it is.
-                */
-               KKASSERT(sys_cputimer == &i8254_cputimer);
-               KKASSERT(cti == &i8254_cputimer_intr);
-
-               lastcnt = get_interrupt_counter(irq);
-
-               /*
-                * Force an 8254 Timer0 interrupt and wait 1/100s for
-                * it to happen, then see if we got it.
-                */
-               kprintf("APIC_IO: Testing 8254 interrupt delivery\n");
-               i8254_intr_reload(cti, 2);
-               base = sys_cputimer->count();
-               while (sys_cputimer->count() - base < sys_cputimer->freq / 100)
-                       ;       /* nothing */
-               if (get_interrupt_counter(irq) - lastcnt == 0) {
-                       /* 
-                        * The MP table is broken.
-                        * The 8254 was not connected to the specified pin
-                        * on the IO APIC.
-                        * Workaround: Limited variant of mixed mode.
-                        */
-                       machintr_intrdis(irq);
-                       unregister_int(clkdesc);
-                       kprintf("APIC_IO: Broken MP table detected: "
-                              "8254 is not connected to "
-                              "IOAPIC #%d intpin %d\n",
-                              int_to_apicintpin[irq].ioapic,
-                              int_to_apicintpin[irq].int_pin);
-                       /* 
-                        * Revoke current ISA IRQ 0 assignment and 
-                        * configure a fallback interrupt routing from
-                        * the 8254 Timer via the 8259 PIC to the
-                        * an ExtInt interrupt line on IOAPIC #0 intpin 0.
-                        * We reuse the low level interrupt handler number.
-                        */
-                       if (apic_irq(0, 0) < 0) {
-                               revoke_apic_irq(irq);
-                               assign_apic_irq(0, 0, irq);
+       if (ioapic_enable) {
+               error = i8254_ioapic_trial(irq, cti);
+               if (error) {
+                       if (mixed_mode) {
+                               if (!selected) {
+                                       kprintf("IOAPIC: mixed mode for irq %d "
+                                               "trial failed: %d\n",
+                                               irq, error);
+                                       goto nointr;
+                               } else {
+                                       panic("IOAPIC: mixed mode for irq %d "
+                                             "trial failed: %d\n", irq, error);
+                               }
+                       } else {
+                               kprintf("IOAPIC: warning 8254 is not connected "
+                                       "to the correct pin, try mixed mode\n");
+                               unregister_int(clkdesc, 0);
+                               goto mixed_mode_setup;
                        }
-                       irq = apic_irq(0, 0);
-                       setup_8254_mixed_mode();
-                       register_int(irq, clkintr, NULL, "clk",
-                                    NULL,
-                                    INTR_EXCL | INTR_CLOCK |
-                                    INTR_NOPOLL | INTR_MPSAFE |
-                                    INTR_NOENTROPY);
-                       machintr_intren(irq);
                }
        }
-       if (apic_int_type(0, 0) != 3 ||
-           int_to_apicintpin[irq].ioapic != 0 ||
-           int_to_apicintpin[irq].int_pin != 0) {
-               kprintf("APIC_IO: routing 8254 via IOAPIC #%d intpin %d\n",
-                      int_to_apicintpin[irq].ioapic,
-                      int_to_apicintpin[irq].int_pin);
-       } else {
-               kprintf("APIC_IO: "
-                      "routing 8254 via 8259 and IOAPIC #0 intpin 0\n");
-       }
-}
-#endif
-}
-
-#ifdef SMP /* APIC-IO */
+       return;
 
-static void 
-setup_8254_mixed_mode(void)
-{
-       /*
-        * Allow 8254 timer to INTerrupt 8259:
-        *  re-initialize master 8259:
-        *   reset; prog 4 bytes, single ICU, edge triggered
-        */
-       outb(IO_ICU1, 0x13);
-       outb(IO_ICU1 + 1, IDT_OFFSET);  /* start vector (unused) */
-       outb(IO_ICU1 + 1, 0x00);        /* ignore slave */
-       outb(IO_ICU1 + 1, 0x03);        /* auto EOI, 8086 */
-       outb(IO_ICU1 + 1, 0xfe);        /* unmask INT0 */
-       
-       /* program IO APIC for type 3 INT on INT0 */
-       if (ext_int_setup(0, 0) < 0)
-               panic("8254 redirect via APIC pin0 impossible!");
+nointr:
+       i8254_nointr = 1; /* don't try to register again */
+       cputimer_intr_deregister(cti);
 }
-#endif
 
 void
 setstatclockrate(int newhz)