diff options
Diffstat (limited to 'sys/i386/isa/clock.c')
-rw-r--r-- | sys/i386/isa/clock.c | 157 |
1 files changed, 51 insertions, 106 deletions
diff --git a/sys/i386/isa/clock.c b/sys/i386/isa/clock.c index 0e630d9..a164288 100644 --- a/sys/i386/isa/clock.c +++ b/sys/i386/isa/clock.c @@ -72,6 +72,7 @@ #include <machine/ipl.h> #include <machine/limits.h> #include <machine/md_var.h> +#include <machine/mutex.h> #include <machine/psl.h> #ifdef APIC_IO #include <machine/segments.h> @@ -139,6 +140,7 @@ int timer0_max_count; u_int tsc_freq; int tsc_is_broken; int wall_cmos_clock; /* wall CMOS clock assumed if != 0 */ +struct mtx clock_lock; static int beeping = 0; static const u_char daysinmonth[] = {31,28,31,30,31,30,31,31,30,31,30,31}; @@ -198,12 +200,9 @@ SYSCTL_OPAQUE(_debug, OID_AUTO, i8254_timecounter, CTLFLAG_RD, static void clkintr(struct clockframe frame) { - int intrsave; if (timecounter->tc_get_timecount == i8254_get_timecount) { - intrsave = save_intr(); - disable_intr(); - CLOCK_LOCK(); + mtx_enter(&clock_lock, MTX_SPIN); if (i8254_ticked) i8254_ticked = 0; else { @@ -211,8 +210,7 @@ clkintr(struct clockframe frame) i8254_lastcount = 0; } clkintr_pending = 0; - CLOCK_UNLOCK(); - restore_intr(intrsave); + mtx_exit(&clock_lock, MTX_SPIN); } timer_func(&frame); switch (timer0_state) { @@ -231,17 +229,14 @@ clkintr(struct clockframe frame) break; case ACQUIRE_PENDING: - intrsave = save_intr(); - disable_intr(); - CLOCK_LOCK(); + mtx_enter(&clock_lock, MTX_SPIN); i8254_offset = i8254_get_timecount(NULL); i8254_lastcount = 0; timer0_max_count = TIMER_DIV(new_rate); outb(TIMER_MODE, TIMER_SEL0 | TIMER_RATEGEN | TIMER_16BIT); outb(TIMER_CNTR0, timer0_max_count & 0xff); outb(TIMER_CNTR0, timer0_max_count >> 8); - CLOCK_UNLOCK(); - restore_intr(intrsave); + mtx_exit(&clock_lock, MTX_SPIN); timer_func = new_function; timer0_state = ACQUIRED; setdelayed(); @@ -250,9 +245,7 @@ clkintr(struct clockframe frame) case RELEASE_PENDING: if ((timer0_prescaler_count += timer0_max_count) >= hardclock_max_count) { - intrsave = save_intr(); - disable_intr(); - CLOCK_LOCK(); + mtx_enter(&clock_lock, MTX_SPIN); i8254_offset = i8254_get_timecount(NULL); i8254_lastcount = 0; timer0_max_count = hardclock_max_count; @@ -260,8 +253,7 @@ clkintr(struct clockframe frame) TIMER_SEL0 | TIMER_RATEGEN | TIMER_16BIT); outb(TIMER_CNTR0, timer0_max_count & 0xff); outb(TIMER_CNTR0, timer0_max_count >> 8); - CLOCK_UNLOCK(); - restore_intr(intrsave); + mtx_exit(&clock_lock, MTX_SPIN); timer0_prescaler_count = 0; timer_func = hardclock; timer0_state = RELEASED; @@ -408,11 +400,9 @@ DB_SHOW_COMMAND(rtc, rtc) static int getit(void) { - int high, low, intrsave; + int high, low; - intrsave = save_intr(); - disable_intr(); - CLOCK_LOCK(); + mtx_enter(&clock_lock, MTX_SPIN); /* Select timer0 and latch counter value. */ outb(TIMER_MODE, TIMER_SEL0 | TIMER_LATCH); @@ -420,8 +410,7 @@ getit(void) low = inb(TIMER_CNTR0); high = inb(TIMER_CNTR0); - CLOCK_UNLOCK(); - restore_intr(intrsave); + mtx_exit(&clock_lock, MTX_SPIN); return ((high << 8) | low); } @@ -527,7 +516,6 @@ sysbeepstop(void *chan) int sysbeep(int pitch, int period) { - int intrsave; int x = splclock(); if (acquire_timer2(TIMER_SQWAVE|TIMER_16BIT)) @@ -536,13 +524,10 @@ sysbeep(int pitch, int period) splx(x); return (-1); /* XXX Should be EBUSY, but nobody cares anyway. */ } - intrsave = save_intr(); - disable_intr(); - CLOCK_LOCK(); + mtx_enter(&clock_lock, MTX_SPIN); outb(TIMER_CNTR2, pitch); outb(TIMER_CNTR2, (pitch>>8)); - CLOCK_UNLOCK(); - restore_intr(intrsave); + mtx_exit(&clock_lock, MTX_SPIN); if (!beeping) { /* enable counter2 output to speaker */ outb(IO_PPI, inb(IO_PPI) | 3); @@ -691,12 +676,9 @@ fail: static void set_timer_freq(u_int freq, int intr_freq) { - int intrsave; int new_timer0_max_count; - intrsave = save_intr(); - disable_intr(); - CLOCK_LOCK(); + mtx_enter(&clock_lock, MTX_SPIN); timer_freq = freq; new_timer0_max_count = hardclock_max_count = TIMER_DIV(intr_freq); if (new_timer0_max_count != timer0_max_count) { @@ -705,8 +687,7 @@ set_timer_freq(u_int freq, int intr_freq) outb(TIMER_CNTR0, timer0_max_count & 0xff); outb(TIMER_CNTR0, timer0_max_count >> 8); } - CLOCK_UNLOCK(); - restore_intr(intrsave); + mtx_exit(&clock_lock, MTX_SPIN); } /* @@ -720,16 +701,12 @@ set_timer_freq(u_int freq, int intr_freq) void i8254_restore(void) { - int intrsave; - intrsave = save_intr(); - disable_intr(); - CLOCK_LOCK(); + mtx_enter(&clock_lock, MTX_SPIN); outb(TIMER_MODE, TIMER_SEL0 | TIMER_RATEGEN | TIMER_16BIT); outb(TIMER_CNTR0, timer0_max_count & 0xff); outb(TIMER_CNTR0, timer0_max_count >> 8); - CLOCK_UNLOCK(); - restore_intr(intrsave); + mtx_exit(&clock_lock, MTX_SPIN); } /* @@ -989,8 +966,8 @@ cpu_initclocks() { int diag; #ifdef APIC_IO - int apic_8254_trial, num_8254_ticks; - struct intrec *clkdesc, *rtcdesc; + int apic_8254_trial; + struct intrec *clkdesc; #endif /* APIC_IO */ if (statclock_disable) { @@ -1023,6 +1000,11 @@ cpu_initclocks() } else panic("APIC_IO: Cannot route 8254 interrupt to CPU"); } + + clkdesc = inthand_add("clk", apic_8254_intr, (driver_intr_t *)clkintr, + NULL, PI_REALTIME, INTR_FAST); + INTREN(1 << apic_8254_intr); + #else /* APIC_IO */ /* @@ -1030,9 +1012,8 @@ cpu_initclocks() * couldn't find anything suitable in the BSD/OS code (grog, * 19 July 2000). */ - /* Setup the PIC clk handler. The APIC handler is setup later */ inthand_add("clk", 0, (driver_intr_t *)clkintr, NULL, PI_REALTIME, - INTR_EXCL); + INTR_FAST); INTREN(IRQ0); #endif /* APIC_IO */ @@ -1042,18 +1023,8 @@ cpu_initclocks() writertc(RTC_STATUSB, RTCSB_24HR); /* Don't bother enabling the statistics clock. */ - if (statclock_disable) { -#ifdef APIC_IO - /* - * XXX - if statclock is disabled, don't attempt the APIC - * trial. Not sure this is sane for APIC_IO. - */ - inthand_add("clk", apic_8254_intr, (driver_intr_t *)clkintr, - NULL, PI_REALTIME, INTR_EXCL); - INTREN(1 << apic_8254_intr); -#endif /* APIC_IO */ + if (statclock_disable) return; - } diag = rtcin(RTC_DIAG); if (diag != 0) printf("RTC BIOS diagnostic error %b\n", diag, RTCDG_BITS); @@ -1061,44 +1032,34 @@ cpu_initclocks() #ifdef APIC_IO if (isa_apic_irq(8) != 8) panic("APIC RTC != 8"); +#endif /* APIC_IO */ - if (apic_8254_trial) { - /* - * XXX - We use fast interrupts for clk and rtc long enough to - * perform the APIC probe and then revert to exclusive - * interrupts. - */ - clkdesc = inthand_add("clk", apic_8254_intr, - (driver_intr_t *)clkintr, NULL, PI_REALTIME, INTR_FAST); - INTREN(1 << apic_8254_intr); + inthand_add("rtc", 8, (driver_intr_t *)rtcintr, NULL, PI_REALTIME, + INTR_FAST); - rtcdesc = inthand_add("rtc", 8, (driver_intr_t *)rtcintr, NULL, - PI_REALTIME, INTR_FAST); /* XXX */ - INTREN(APIC_IRQ8); - writertc(RTC_STATUSB, rtc_statusb); +#ifdef APIC_IO + INTREN(APIC_IRQ8); +#else + INTREN(IRQ8); +#endif /* APIC_IO */ + + writertc(RTC_STATUSB, rtc_statusb); + +#ifdef APIC_IO + if (apic_8254_trial) { printf("APIC_IO: Testing 8254 interrupt delivery\n"); while (read_intr_count(8) < 6) ; /* nothing */ - num_8254_ticks = read_intr_count(apic_8254_intr); - - /* disable and remove our fake handlers */ - INTRDIS(1 << apic_8254_intr); - inthand_remove(clkdesc); - - writertc(RTC_STATUSA, rtc_statusa); - writertc(RTC_STATUSB, RTCSB_24HR); - - INTRDIS(APIC_IRQ8); - inthand_remove(rtcdesc); - - if (num_8254_ticks < 3) { + if (read_intr_count(apic_8254_intr) < 3) { /* * The MP table is broken. * The 8254 was not connected to the specified pin * on the IO APIC. * Workaround: Limited variant of mixed mode. */ + INTRDIS(1 << apic_8254_intr); + inthand_remove(clkdesc); printf("APIC_IO: Broken MP table detected: " "8254 is not connected to " "IOAPIC #%d intpin %d\n", @@ -1117,27 +1078,13 @@ cpu_initclocks() } apic_8254_intr = apic_irq(0, 0); setup_8254_mixed_mode(); + inthand_add("clk", apic_8254_intr, + (driver_intr_t *)clkintr, NULL, + PI_REALTIME, INTR_FAST); + INTREN(1 << apic_8254_intr); } } - - /* Finally, setup the real clock handlers */ - inthand_add("clk", apic_8254_intr, (driver_intr_t *)clkintr, NULL, - PI_REALTIME, INTR_EXCL); - INTREN(1 << apic_8254_intr); -#endif - - inthand_add("rtc", 8, (driver_intr_t *)rtcintr, NULL, PI_REALTIME, - INTR_EXCL); -#ifdef APIC_IO - INTREN(APIC_IRQ8); -#else - INTREN(IRQ8); -#endif - - writertc(RTC_STATUSB, rtc_statusb); - -#ifdef APIC_IO if (apic_int_type(0, 0) != 3 || int_to_apicintpin[apic_8254_intr].ioapic != 0 || int_to_apicintpin[apic_8254_intr].int_pin != 0) @@ -1242,12 +1189,11 @@ static unsigned i8254_get_timecount(struct timecounter *tc) { u_int count; - int intrsave; u_int high, low; + u_int eflags; - intrsave = save_intr(); - disable_intr(); - CLOCK_LOCK(); + eflags = read_eflags(); + mtx_enter(&clock_lock, MTX_SPIN); /* Select timer0 and latch counter value. */ outb(TIMER_MODE, TIMER_SEL0 | TIMER_LATCH); @@ -1257,7 +1203,7 @@ i8254_get_timecount(struct timecounter *tc) count = timer0_max_count - ((high << 8) | low); if (count < i8254_lastcount || (!i8254_ticked && (clkintr_pending || - ((count < 20 || (!(intrsave & PSL_I) && count < timer0_max_count / 2u)) && + ((count < 20 || (!(eflags & PSL_I) && count < timer0_max_count / 2u)) && #ifdef APIC_IO #define lapic_irr1 ((volatile u_int *)&lapic)[0x210 / 4] /* XXX XXX */ /* XXX this assumes that apic_8254_intr is < 24. */ @@ -1271,8 +1217,7 @@ i8254_get_timecount(struct timecounter *tc) } i8254_lastcount = count; count += i8254_offset; - CLOCK_UNLOCK(); - restore_intr(intrsave); + mtx_exit(&clock_lock, MTX_SPIN); return (count); } |