From ae692d88c4853625d6ea730968a3e98667238887 Mon Sep 17 00:00:00 2001 From: Peter Wemm Date: Fri, 15 Apr 2005 18:46:53 +0000 Subject: MFi386: sync rtc code - don't setup an interrupt handler for irq0 when the lapic timer is active. Don't enable periodic interrupts unless we are using them. Replace spl protection with a spinlock. --- sys/amd64/isa/clock.c | 60 +++++++++++++++++++++++++++------------------------ 1 file changed, 32 insertions(+), 28 deletions(-) (limited to 'sys/amd64') diff --git a/sys/amd64/isa/clock.c b/sys/amd64/isa/clock.c index a2f3e2f9127a..f1f3e94236cd 100644 --- a/sys/amd64/isa/clock.c +++ b/sys/amd64/isa/clock.c @@ -102,6 +102,8 @@ u_int timer_freq = TIMER_FREQ; int timer0_max_count; int wall_cmos_clock; /* wall CMOS clock assumed if != 0 */ struct mtx clock_lock; +#define RTC_LOCK mtx_lock_spin(&clock_lock) +#define RTC_UNLOCK mtx_unlock_spin(&clock_lock) static int beeping = 0; static const u_char daysinmonth[] = {31,28,31,30,31,30,31,31,30,31,30,31}; @@ -113,7 +115,7 @@ static int (*i8254_pending)(struct intsrc *); static int i8254_ticked; static int using_lapic_timer; static u_char rtc_statusa = RTCSA_DIVIDER | RTCSA_NOPROF; -static u_char rtc_statusb = RTCSB_24HR | RTCSB_PINTR; +static u_char rtc_statusb = RTCSB_24HR; /* Values for timerX_state: */ #define RELEASED 0 @@ -401,30 +403,28 @@ int rtcin(reg) int reg; { - int s; u_char val; - s = splhigh(); + RTC_LOCK; outb(IO_RTC, reg); inb(0x84); val = inb(IO_RTC + 1); inb(0x84); - splx(s); + RTC_UNLOCK; return (val); } static __inline void writertc(u_char reg, u_char val) { - int s; - s = splhigh(); + RTC_LOCK; inb(0x84); outb(IO_RTC, reg); inb(0x84); outb(IO_RTC + 1, val); inb(0x84); /* XXX work around wrong order in rtcin() */ - splx(s); + RTC_UNLOCK; } static __inline int @@ -725,37 +725,41 @@ cpu_initclocks() int diag; using_lapic_timer = lapic_setup_clock(); - if (statclock_disable || using_lapic_timer) { - /* - * The stat interrupt mask is different without the - * statistics clock. Also, don't set the interrupt - * flag which would normally cause the RTC to generate - * interrupts. - */ - rtc_statusb = RTCSB_24HR; - } else { - /* Setting stathz to nonzero early helps avoid races. */ - stathz = RTC_NOPROFRATE; - profhz = RTC_PROFRATE; - } - - /* Finish initializing 8254 timer 0. */ - intr_add_handler("clk", 0, (driver_intr_t *)clkintr, NULL, - INTR_TYPE_CLK | INTR_FAST, NULL); - i8254_intsrc = intr_lookup_source(0); - if (i8254_intsrc != NULL) - i8254_pending = i8254_intsrc->is_pic->pic_source_pending; + /* + * If we aren't using the local APIC timer to drive the kernel + * clocks, setup the interrupt handler for the 8254 timer 0 so + * that it can drive hardclock(). + */ + if (!using_lapic_timer) { + intr_add_handler("clk", 0, (driver_intr_t *)clkintr, NULL, + INTR_TYPE_CLK | INTR_FAST, NULL); + i8254_intsrc = intr_lookup_source(0); + if (i8254_intsrc != NULL) + i8254_pending = + i8254_intsrc->is_pic->pic_source_pending; + } /* Initialize RTC. */ writertc(RTC_STATUSA, rtc_statusa); writertc(RTC_STATUSB, RTCSB_24HR); - /* Don't bother enabling the statistics clock. */ + /* + * If the separate statistics clock hasn't been explicility disabled + * and we aren't already using the local APIC timer to drive the + * kernel clocks, then setup the RTC to periodically interrupt to + * drive statclock() and profclock(). + */ if (!statclock_disable && !using_lapic_timer) { diag = rtcin(RTC_DIAG); if (diag != 0) printf("RTC BIOS diagnostic error %b\n", diag, RTCDG_BITS); + /* Setting stathz to nonzero early helps avoid races. */ + stathz = RTC_NOPROFRATE; + profhz = RTC_PROFRATE; + + /* Enable periodic interrupts from the RTC. */ + rtc_statusb |= RTCSB_PINTR; intr_add_handler("rtc", 8, (driver_intr_t *)rtcintr, NULL, INTR_TYPE_CLK | INTR_FAST, NULL); -- cgit v1.2.3