tsc.c revision 48888
14Srgrimes/*-
24Srgrimes * Copyright (c) 1990 The Regents of the University of California.
34Srgrimes * All rights reserved.
44Srgrimes *
54Srgrimes * This code is derived from software contributed to Berkeley by
64Srgrimes * William Jolitz and Don Ahn.
74Srgrimes *
84Srgrimes * Redistribution and use in source and binary forms, with or without
94Srgrimes * modification, are permitted provided that the following conditions
104Srgrimes * are met:
114Srgrimes * 1. Redistributions of source code must retain the above copyright
124Srgrimes *    notice, this list of conditions and the following disclaimer.
134Srgrimes * 2. Redistributions in binary form must reproduce the above copyright
144Srgrimes *    notice, this list of conditions and the following disclaimer in the
154Srgrimes *    documentation and/or other materials provided with the distribution.
164Srgrimes * 3. All advertising materials mentioning features or use of this software
174Srgrimes *    must display the following acknowledgement:
184Srgrimes *	This product includes software developed by the University of
194Srgrimes *	California, Berkeley and its contributors.
204Srgrimes * 4. Neither the name of the University nor the names of its contributors
214Srgrimes *    may be used to endorse or promote products derived from this software
224Srgrimes *    without specific prior written permission.
234Srgrimes *
244Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
254Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
264Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
274Srgrimes * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
284Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
294Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
304Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
314Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
324Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
334Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
344Srgrimes * SUCH DAMAGE.
354Srgrimes *
36619Srgrimes *	from: @(#)clock.c	7.2 (Berkeley) 5/12/91
3748888Sbde *	$Id: clock.c,v 1.138 1999/06/27 09:08:48 peter Exp $
384Srgrimes */
394Srgrimes
403185Ssos/*
4119173Sbde * Routines to handle clock hardware.
4219173Sbde */
4319173Sbde
4419173Sbde/*
453185Ssos * inittodr, settodr and support routines written
463185Ssos * by Christoph Robitschko <chmr@edvz.tu-graz.ac.at>
473185Ssos *
483185Ssos * reintroduced and updated by Chris Stenton <chris@gnome.co.uk> 8/10/94
492913Sache */
502913Sache
5116299Spst#include "opt_clock.h"
5233929Sphk#include "apm.h"
5313228Swollman
542056Swollman#include <sys/param.h>
552056Swollman#include <sys/systm.h>
562056Swollman#include <sys/time.h>
572056Swollman#include <sys/kernel.h>
5831253Sbde#ifndef SMP
5931253Sbde#include <sys/lock.h>
6031253Sbde#endif
6115508Sbde#include <sys/sysctl.h>
6215508Sbde
634180Sbde#include <machine/clock.h>
6415508Sbde#ifdef CLK_CALIBRATION_LOOP
6515508Sbde#include <machine/cons.h>
6615508Sbde#endif
6730805Sbde#include <machine/cputypes.h>
682056Swollman#include <machine/frame.h>
6926309Speter#include <machine/ipl.h>
7028551Sbde#include <machine/limits.h>
7132054Sphk#include <machine/md_var.h>
7247588Sbde#include <machine/psl.h>
7334617Sphk#if NAPM > 0
7434617Sphk#include <machine/apm_bios.h>
7534617Sphk#include <i386/apm/apm_setup.h>
7634617Sphk#endif
7730805Sbde#ifdef APIC_IO
7830805Sbde#include <machine/segments.h>
7930805Sbde#endif
8028921Sfsmp#if defined(SMP) || defined(APIC_IO)
8126949Sfsmp#include <machine/smp.h>
8228921Sfsmp#endif /* SMP || APIC_IO */
8332054Sphk#include <machine/specialreg.h>
8415508Sbde
852056Swollman#include <i386/isa/icu.h>
862056Swollman#include <i386/isa/isa.h>
8747642Sdfr#include <isa/rtc.h>
882056Swollman#include <i386/isa/timerreg.h>
894Srgrimes
9045897Speter#include <i386/isa/intr_machdep.h>
9128487Sfsmp
9228921Sfsmp#ifdef SMP
9329000Sfsmp#define disable_intr()	CLOCK_DISABLE_INTR()
9429000Sfsmp#define enable_intr()	CLOCK_ENABLE_INTR()
9534058Stegge
9634571Stegge#ifdef APIC_IO
9734571Stegge#include <i386/isa/intr_machdep.h>
9834058Stegge/* The interrupt triggered by the 8254 (timer) chip */
9934058Steggeint apic_8254_intr;
10034571Steggestatic u_long read_intr_count __P((int vec));
10134571Steggestatic void setup_8254_mixed_mode __P((void));
10234571Stegge#endif
10328921Sfsmp#endif /* SMP */
10428921Sfsmp
1052873Sbde/*
1062873Sbde * 32-bit time_t's can't reach leap years before 1904 or after 2036, so we
1072873Sbde * can use a simple formula for leap years.
1082873Sbde */
1092873Sbde#define	LEAPYEAR(y) ((u_int)(y) % 4 == 0)
1102913Sache#define DAYSPERYEAR   (31+28+31+30+31+30+31+31+30+31+30+31)
1112873Sbde
11215508Sbde#define	TIMER_DIV(x) ((timer_freq + (x) / 2) / (x))
1134Srgrimes
1144180Sbde/*
1154180Sbde * Time in timer cycles that it takes for microtime() to disable interrupts
1164180Sbde * and latch the count.  microtime() currently uses "cli; outb ..." so it
1174180Sbde * normally takes less than 2 timer cycles.  Add a few for cache misses.
1184180Sbde * Add a few more to allow for latency in bogus calls to microtime() with
1194180Sbde * interrupts already disabled.
1204180Sbde */
1214180Sbde#define	TIMER0_LATCH_COUNT	20
1224180Sbde
1234180Sbde/*
12417236Sjoerg * Maximum frequency that we are willing to allow for timer0.  Must be
12517231Sjoerg * low enough to guarantee that the timer interrupt handler returns
12633690Sphk * before the next timer interrupt.
1274180Sbde */
12817231Sjoerg#define	TIMER0_MAX_FREQ		20000
1294180Sbde
13041787Smckayint	adjkerntz;		/* local offset from GMT in seconds */
13147588Sbdeint	clkintr_pending;
13215045Sacheint	disable_rtc_set;	/* disable resettodr() if != 0 */
13346847Spetervolatile u_int	idelayed;
13432052Sphkint	statclock_disable;
13532052Sphku_int	stat_imask = SWI_CLOCK_MASK;
13633690Sphk#ifndef TIMER_FREQ
13733690Sphk#define TIMER_FREQ   1193182
13833690Sphk#endif
13932052Sphku_int	timer_freq = TIMER_FREQ;
14032052Sphkint	timer0_max_count;
14132005Sphku_int	tsc_freq;
14247592Sphkint	tsc_is_broken;
14341787Smckayint	wall_cmos_clock;	/* wall CMOS clock assumed if != 0 */
1441390Ssos
1454180Sbdestatic	int	beeping = 0;
1465291Sbdestatic	u_int	clk_imask = HWI_MASK | SWI_MASK;
1474180Sbdestatic	const u_char daysinmonth[] = {31,28,31,30,31,30,31,31,30,31,30,31};
14819173Sbdestatic	u_int	hardclock_max_count;
14933690Sphkstatic	u_int32_t i8254_lastcount;
15033690Sphkstatic	u_int32_t i8254_offset;
15133690Sphkstatic	int	i8254_ticked;
1524180Sbde/*
1534180Sbde * XXX new_function and timer_func should not handle clockframes, but
1544180Sbde * timer_func currently needs to hold hardclock to handle the
1554180Sbde * timer0_state == 0 case.  We should use register_intr()/unregister_intr()
1564180Sbde * to switch between clkintr() and a slightly different timerintr().
1574180Sbde */
15819173Sbdestatic	void	(*new_function) __P((struct clockframe *frame));
15919173Sbdestatic	u_int	new_rate;
1604180Sbdestatic	u_char	rtc_statusa = RTCSA_DIVIDER | RTCSA_NOPROF;
16115345Snatestatic	u_char	rtc_statusb = RTCSB_24HR | RTCSB_PINTR;
16233690Sphkstatic	u_int	timer0_prescaler_count;
16317231Sjoerg
16417231Sjoerg/* Values for timerX_state: */
16517236Sjoerg#define	RELEASED	0
16617236Sjoerg#define	RELEASE_PENDING	1
16717236Sjoerg#define	ACQUIRED	2
16817236Sjoerg#define	ACQUIRE_PENDING	3
16917231Sjoerg
17017231Sjoergstatic	u_char	timer0_state;
17117231Sjoergstatic	u_char	timer2_state;
17219173Sbdestatic	void	(*timer_func) __P((struct clockframe *frame)) = hardclock;
17333690Sphkstatic	u_int	tsc_present;
1744180Sbde
17536719Sphkstatic	unsigned i8254_get_timecount __P((struct timecounter *tc));
17636719Sphkstatic	unsigned tsc_get_timecount __P((struct timecounter *tc));
17721783Sbdestatic	void	set_timer_freq(u_int freq, int intr_freq);
17817353Sbde
17940610Sphkstatic struct timecounter tsc_timecounter = {
18033690Sphk	tsc_get_timecount,	/* get_timecount */
18136741Sphk	0,			/* no poll_pps */
18236198Sphk 	~0u,			/* counter_mask */
18333690Sphk	0,			/* frequency */
18433690Sphk	 "TSC"			/* name */
18533690Sphk};
18633690Sphk
18733690SphkSYSCTL_OPAQUE(_debug, OID_AUTO, tsc_timecounter, CTLFLAG_RD,
18840610Sphk	&tsc_timecounter, sizeof(tsc_timecounter), "S,timecounter", "");
18933690Sphk
19040610Sphkstatic struct timecounter i8254_timecounter = {
19133690Sphk	i8254_get_timecount,	/* get_timecount */
19236741Sphk	0,			/* no poll_pps */
19336198Sphk	~0u,			/* counter_mask */
19433690Sphk	0,			/* frequency */
19533690Sphk	"i8254"			/* name */
19633690Sphk};
19733690Sphk
19833690SphkSYSCTL_OPAQUE(_debug, OID_AUTO, i8254_timecounter, CTLFLAG_RD,
19940610Sphk	&i8254_timecounter, sizeof(i8254_timecounter), "S,timecounter", "");
20033690Sphk
20112724Sphkstatic void
2023185Ssosclkintr(struct clockframe frame)
2032074Swollman{
20439503Sbde	if (timecounter->tc_get_timecount == i8254_get_timecount) {
20547588Sbde		disable_intr();
20647588Sbde		if (i8254_ticked)
20739503Sbde			i8254_ticked = 0;
20847588Sbde		else {
20939503Sbde			i8254_offset += timer0_max_count;
21039503Sbde			i8254_lastcount = 0;
21139503Sbde		}
21247588Sbde		clkintr_pending = 0;
21347588Sbde		enable_intr();
21439503Sbde	}
2151549Srgrimes	timer_func(&frame);
2161442Ssos	switch (timer0_state) {
21717236Sjoerg
21817231Sjoerg	case RELEASED:
2198448Sbde		setdelayed();
2201442Ssos		break;
22117236Sjoerg
22217231Sjoerg	case ACQUIRED:
2234180Sbde		if ((timer0_prescaler_count += timer0_max_count)
2244180Sbde		    >= hardclock_max_count) {
22533309Sbde			timer0_prescaler_count -= hardclock_max_count;
2261549Srgrimes			hardclock(&frame);
2278448Sbde			setdelayed();
2281390Ssos		}
2291442Ssos		break;
23017236Sjoerg
23117231Sjoerg	case ACQUIRE_PENDING:
2328448Sbde		setdelayed();
2334180Sbde		timer0_max_count = TIMER_DIV(new_rate);
23429000Sfsmp		disable_intr();
2354180Sbde		outb(TIMER_MODE, TIMER_SEL0 | TIMER_RATEGEN | TIMER_16BIT);
2364180Sbde		outb(TIMER_CNTR0, timer0_max_count & 0xff);
2374180Sbde		outb(TIMER_CNTR0, timer0_max_count >> 8);
23829000Sfsmp		enable_intr();
2394180Sbde		timer0_prescaler_count = 0;
2401442Ssos		timer_func = new_function;
24117231Sjoerg		timer0_state = ACQUIRED;
2421442Ssos		break;
24317236Sjoerg
24417231Sjoerg	case RELEASE_PENDING:
2454180Sbde		if ((timer0_prescaler_count += timer0_max_count)
2464180Sbde		    >= hardclock_max_count) {
24733309Sbde			timer0_prescaler_count -= hardclock_max_count;
24834961Sphk#ifdef FIXME
24933309Sbde			/*
25034961Sphk			 * XXX: This magic doesn't work, but It shouldn't be
25134961Sphk			 * needed now anyway since we will not be able to
25234961Sphk			 * aquire the i8254 if it is used for timecounting.
25334961Sphk			 */
25434961Sphk			/*
25533309Sbde			 * See microtime.s for this magic.
25633309Sbde			 */
25733309Sbde			time.tv_usec += (27465 * timer0_prescaler_count) >> 15;
25833309Sbde			if (time.tv_usec >= 1000000)
25933309Sbde				time.tv_usec -= 1000000;
26034961Sphk#endif
2611549Srgrimes			hardclock(&frame);
2628448Sbde			setdelayed();
2635291Sbde			timer0_max_count = hardclock_max_count;
26429000Sfsmp			disable_intr();
2654180Sbde			outb(TIMER_MODE,
2664180Sbde			     TIMER_SEL0 | TIMER_RATEGEN | TIMER_16BIT);
2674180Sbde			outb(TIMER_CNTR0, timer0_max_count & 0xff);
2684180Sbde			outb(TIMER_CNTR0, timer0_max_count >> 8);
26929000Sfsmp			enable_intr();
2704180Sbde			timer0_prescaler_count = 0;
27117231Sjoerg			timer_func = hardclock;
27217231Sjoerg			timer0_state = RELEASED;
2731442Ssos		}
2741442Ssos		break;
2751442Ssos	}
2761390Ssos}
2771390Ssos
27817231Sjoerg/*
27917236Sjoerg * The acquire and release functions must be called at ipl >= splclock().
28017231Sjoerg */
2811390Ssosint
2824180Sbdeacquire_timer0(int rate, void (*function) __P((struct clockframe *frame)))
2831390Ssos{
28417231Sjoerg	static int old_rate;
28517231Sjoerg
28617231Sjoerg	if (rate <= 0 || rate > TIMER0_MAX_FREQ)
28717231Sjoerg		return (-1);
28836810Sphk	if (strcmp(timecounter->tc_name, "i8254") == 0)
28933690Sphk		return (-1);
29017231Sjoerg	switch (timer0_state) {
29117231Sjoerg
29217236Sjoerg	case RELEASED:
29317236Sjoerg		timer0_state = ACQUIRE_PENDING;
29417236Sjoerg		break;
29517231Sjoerg
29617236Sjoerg	case RELEASE_PENDING:
29717236Sjoerg		if (rate != old_rate)
29817236Sjoerg			return (-1);
29917236Sjoerg		/*
30017236Sjoerg		 * The timer has been released recently, but is being
30117236Sjoerg		 * re-acquired before the release completed.  In this
30217236Sjoerg		 * case, we simply reclaim it as if it had not been
30317236Sjoerg		 * released at all.
30417236Sjoerg		 */
30517236Sjoerg		timer0_state = ACQUIRED;
30617236Sjoerg		break;
30717236Sjoerg
30817236Sjoerg	default:
30917236Sjoerg		return (-1);	/* busy */
31017231Sjoerg	}
3111442Ssos	new_function = function;
31217231Sjoerg	old_rate = new_rate = rate;
31317231Sjoerg	return (0);
3141390Ssos}
3151390Ssos
3161390Ssosint
3171390Ssosacquire_timer2(int mode)
3181390Ssos{
31917231Sjoerg
32017231Sjoerg	if (timer2_state != RELEASED)
32117231Sjoerg		return (-1);
32217231Sjoerg	timer2_state = ACQUIRED;
32317236Sjoerg
32417236Sjoerg	/*
32517236Sjoerg	 * This access to the timer registers is as atomic as possible
32617236Sjoerg	 * because it is a single instruction.  We could do better if we
32717236Sjoerg	 * knew the rate.  Use of splclock() limits glitches to 10-100us,
32817236Sjoerg	 * and this is probably good enough for timer2, so we aren't as
32917236Sjoerg	 * careful with it as with timer0.
33017236Sjoerg	 */
33117236Sjoerg	outb(TIMER_MODE, TIMER_SEL2 | (mode & 0x3f));
33217236Sjoerg
33317231Sjoerg	return (0);
3341390Ssos}
3351390Ssos
3361390Ssosint
3371390Ssosrelease_timer0()
3381390Ssos{
33917231Sjoerg	switch (timer0_state) {
34017231Sjoerg
34117236Sjoerg	case ACQUIRED:
34217236Sjoerg		timer0_state = RELEASE_PENDING;
34317236Sjoerg		break;
34417231Sjoerg
34517236Sjoerg	case ACQUIRE_PENDING:
34617236Sjoerg		/* Nothing happened yet, release quickly. */
34717236Sjoerg		timer0_state = RELEASED;
34817236Sjoerg		break;
34917236Sjoerg
35017236Sjoerg	default:
35117236Sjoerg		return (-1);
35217231Sjoerg	}
35317231Sjoerg	return (0);
3541390Ssos}
3551390Ssos
3561390Ssosint
3571390Ssosrelease_timer2()
3581390Ssos{
35917231Sjoerg
36017231Sjoerg	if (timer2_state != ACQUIRED)
36117231Sjoerg		return (-1);
36217231Sjoerg	timer2_state = RELEASED;
36317236Sjoerg	outb(TIMER_MODE, TIMER_SEL2 | TIMER_SQWAVE | TIMER_16BIT);
36417231Sjoerg	return (0);
3651390Ssos}
3661390Ssos
3673185Ssos/*
3683185Ssos * This routine receives statistical clock interrupts from the RTC.
3693185Ssos * As explained above, these occur at 128 interrupts per second.
3703185Ssos * When profiling, we receive interrupts at a rate of 1024 Hz.
3713185Ssos *
3723185Ssos * This does not actually add as much overhead as it sounds, because
3733185Ssos * when the statistical clock is active, the hardclock driver no longer
3743185Ssos * needs to keep (inaccurate) statistics on its own.  This decouples
3753185Ssos * statistics gathering from scheduling interrupts.
3763185Ssos *
3773185Ssos * The RTC chip requires that we read status register C (RTC_INTR)
3783185Ssos * to acknowledge an interrupt, before it will generate the next one.
37924676Smckay * Under high interrupt load, rtcintr() can be indefinitely delayed and
38024676Smckay * the clock can tick immediately after the read from RTC_INTR.  In this
38124676Smckay * case, the mc146818A interrupt signal will not drop for long enough
38224676Smckay * to register with the 8259 PIC.  If an interrupt is missed, the stat
38324676Smckay * clock will halt, considerably degrading system performance.  This is
38424676Smckay * why we use 'while' rather than a more straightforward 'if' below.
38524676Smckay * Stat clock ticks can still be lost, causing minor loss of accuracy
38624676Smckay * in the statistics, but the stat clock will no longer stop.
3873185Ssos */
38812724Sphkstatic void
3893185Ssosrtcintr(struct clockframe frame)
3903185Ssos{
39124676Smckay	while (rtcin(RTC_INTR) & RTCIR_PERIOD)
3923185Ssos		statclock(&frame);
3933185Ssos}
3941390Ssos
39518297Sbde#include "opt_ddb.h"
3965291Sbde#ifdef DDB
39718297Sbde#include <ddb/ddb.h>
39818297Sbde
39918297SbdeDB_SHOW_COMMAND(rtc, rtc)
4003185Ssos{
4015291Sbde	printf("%02x/%02x/%02x %02x:%02x:%02x, A = %02x, B = %02x, C = %02x\n",
4025291Sbde	       rtcin(RTC_YEAR), rtcin(RTC_MONTH), rtcin(RTC_DAY),
4035291Sbde	       rtcin(RTC_HRS), rtcin(RTC_MIN), rtcin(RTC_SEC),
4045291Sbde	       rtcin(RTC_STATUSA), rtcin(RTC_STATUSB), rtcin(RTC_INTR));
4053185Ssos}
40618297Sbde#endif /* DDB */
4073185Ssos
4081390Ssosstatic int
40910268Sbdegetit(void)
4101390Ssos{
41116428Sbde	u_long ef;
4121390Ssos	int high, low;
4131390Ssos
41416428Sbde	ef = read_eflags();
41529000Sfsmp	disable_intr();
41616428Sbde
41716428Sbde	/* Select timer0 and latch counter value. */
41819173Sbde	outb(TIMER_MODE, TIMER_SEL0 | TIMER_LATCH);
41916428Sbde
4201390Ssos	low = inb(TIMER_CNTR0);
4211390Ssos	high = inb(TIMER_CNTR0);
42216428Sbde
42328921Sfsmp	CLOCK_UNLOCK();
42416428Sbde	write_eflags(ef);
4251390Ssos	return ((high << 8) | low);
4261390Ssos}
4271390Ssos
4282017Swollman/*
4291390Ssos * Wait "n" microseconds.
43015508Sbde * Relies on timer 1 counting down from (timer_freq / hz)
4311390Ssos * Note: timer had better have been programmed before this is first used!
4321390Ssos */
4331390Ssosvoid
4341390SsosDELAY(int n)
4351390Ssos{
43622106Sbde	int delta, prev_tick, tick, ticks_left;
4371390Ssos
4381390Ssos#ifdef DELAYDEBUG
4391390Ssos	int getit_calls = 1;
4401390Ssos	int n1;
4411390Ssos	static int state = 0;
4421390Ssos
4431390Ssos	if (state == 0) {
4441390Ssos		state = 1;
4451390Ssos		for (n1 = 1; n1 <= 10000000; n1 *= 10)
4461390Ssos			DELAY(n1);
4471390Ssos		state = 2;
4481390Ssos	}
4491390Ssos	if (state == 1)
4501390Ssos		printf("DELAY(%d)...", n);
4511390Ssos#endif
4521390Ssos	/*
45321783Sbde	 * Guard against the timer being uninitialized if we are called
45421783Sbde	 * early for console i/o.
45521783Sbde	 */
45621783Sbde	if (timer0_max_count == 0)
45721783Sbde		set_timer_freq(timer_freq, hz);
45821783Sbde
45921783Sbde	/*
4601390Ssos	 * Read the counter first, so that the rest of the setup overhead is
4611390Ssos	 * counted.  Guess the initial overhead is 20 usec (on most systems it
4621390Ssos	 * takes about 1.5 usec for each of the i/o's in getit().  The loop
4631390Ssos	 * takes about 6 usec on a 486/33 and 13 usec on a 386/20.  The
4641390Ssos	 * multiplications and divisions to scale the count take a while).
4651390Ssos	 */
46610268Sbde	prev_tick = getit();
46722106Sbde	n -= 0;			/* XXX actually guess no initial overhead */
4681390Ssos	/*
46915508Sbde	 * Calculate (n * (timer_freq / 1e6)) without using floating point
4701390Ssos	 * and without any avoidable overflows.
4711390Ssos	 */
47222106Sbde	if (n <= 0)
47322106Sbde		ticks_left = 0;
47422106Sbde	else if (n < 256)
47522106Sbde		/*
47622106Sbde		 * Use fixed point to avoid a slow division by 1000000.
47722106Sbde		 * 39099 = 1193182 * 2^15 / 10^6 rounded to nearest.
47822106Sbde		 * 2^15 is the first power of 2 that gives exact results
47922106Sbde		 * for n between 0 and 256.
48022106Sbde		 */
48122106Sbde		ticks_left = ((u_int)n * 39099 + (1 << 15) - 1) >> 15;
48222106Sbde	else
48322106Sbde		/*
48422106Sbde		 * Don't bother using fixed point, although gcc-2.7.2
48522106Sbde		 * generates particularly poor code for the long long
48622106Sbde		 * division, since even the slow way will complete long
48722106Sbde		 * before the delay is up (unless we're interrupted).
48822106Sbde		 */
48922106Sbde		ticks_left = ((u_int)n * (long long)timer_freq + 999999)
49022106Sbde			     / 1000000;
4911390Ssos
4921390Ssos	while (ticks_left > 0) {
49310268Sbde		tick = getit();
4941390Ssos#ifdef DELAYDEBUG
4951390Ssos		++getit_calls;
4961390Ssos#endif
49721783Sbde		delta = prev_tick - tick;
4981390Ssos		prev_tick = tick;
49921783Sbde		if (delta < 0) {
50021783Sbde			delta += timer0_max_count;
50121783Sbde			/*
50221783Sbde			 * Guard against timer0_max_count being wrong.
50321783Sbde			 * This shouldn't happen in normal operation,
50421783Sbde			 * but it may happen if set_timer_freq() is
50521783Sbde			 * traced.
50621783Sbde			 */
50721783Sbde			if (delta < 0)
50821783Sbde				delta = 0;
50921783Sbde		}
51021783Sbde		ticks_left -= delta;
5111390Ssos	}
5121390Ssos#ifdef DELAYDEBUG
5131390Ssos	if (state == 1)
5141390Ssos		printf(" %d calls to getit() at %d usec each\n",
5151390Ssos		       getit_calls, (n + 5) / getit_calls);
5161390Ssos#endif
5171390Ssos}
5181390Ssos
5191390Ssosstatic void
5203185Ssossysbeepstop(void *chan)
5211390Ssos{
5221390Ssos	outb(IO_PPI, inb(IO_PPI)&0xFC);	/* disable counter2 output to speaker */
5231390Ssos	release_timer2();
5241390Ssos	beeping = 0;
5251390Ssos}
5261390Ssos
5278876Srgrimesint
5281390Ssossysbeep(int pitch, int period)
5291390Ssos{
53017231Sjoerg	int x = splclock();
5311390Ssos
5328876Srgrimes	if (acquire_timer2(TIMER_SQWAVE|TIMER_16BIT))
53317231Sjoerg		if (!beeping) {
53417231Sjoerg			/* Something else owns it. */
53517231Sjoerg			splx(x);
53617231Sjoerg			return (-1); /* XXX Should be EBUSY, but nobody cares anyway. */
53717231Sjoerg		}
53829000Sfsmp	disable_intr();
5391390Ssos	outb(TIMER_CNTR2, pitch);
5401390Ssos	outb(TIMER_CNTR2, (pitch>>8));
54129000Sfsmp	enable_intr();
5421390Ssos	if (!beeping) {
54317231Sjoerg		/* enable counter2 output to speaker */
54417231Sjoerg		outb(IO_PPI, inb(IO_PPI) | 3);
5451390Ssos		beeping = period;
5462873Sbde		timeout(sysbeepstop, (void *)NULL, period);
5471390Ssos	}
54817231Sjoerg	splx(x);
54917231Sjoerg	return (0);
5501390Ssos}
5511390Ssos
5522913Sache/*
5532913Sache * RTC support routines
5542913Sache */
5552913Sache
55614943Sbdeint
55714943Sbdertcin(reg)
55814943Sbde	int reg;
55914943Sbde{
56014943Sbde	u_char val;
56114943Sbde
56214943Sbde	outb(IO_RTC, reg);
56314943Sbde	inb(0x84);
56414943Sbde	val = inb(IO_RTC + 1);
56514943Sbde	inb(0x84);
56614943Sbde	return (val);
56714943Sbde}
56814943Sbde
56913445Sphkstatic __inline void
5705291Sbdewritertc(u_char reg, u_char val)
5712913Sache{
57233309Sbde	inb(0x84);
5735291Sbde	outb(IO_RTC, reg);
57433309Sbde	inb(0x84);
5755291Sbde	outb(IO_RTC + 1, val);
57633309Sbde	inb(0x84);		/* XXX work around wrong order in rtcin() */
5772913Sache}
5782913Sache
57913445Sphkstatic __inline int
5802913Sachereadrtc(int port)
5812913Sache{
58213445Sphk	return(bcd2bin(rtcin(port)));
5832913Sache}
5842913Sache
58515508Sbdestatic u_int
58615508Sbdecalibrate_clocks(void)
58715508Sbde{
58848160Sgreen	u_int64_t old_tsc;
58915508Sbde	u_int count, prev_count, tot_count;
59015508Sbde	int sec, start_sec, timeout;
59115508Sbde
59223393Sbde	if (bootverbose)
59323393Sbde	        printf("Calibrating clock(s) ... ");
59415508Sbde	if (!(rtcin(RTC_STATUSD) & RTCSD_PWR))
59515508Sbde		goto fail;
59615508Sbde	timeout = 100000000;
59715508Sbde
59815508Sbde	/* Read the mc146818A seconds counter. */
59915508Sbde	for (;;) {
60015508Sbde		if (!(rtcin(RTC_STATUSA) & RTCSA_TUP)) {
60115508Sbde			sec = rtcin(RTC_SEC);
60215508Sbde			break;
60315508Sbde		}
60415508Sbde		if (--timeout == 0)
60515508Sbde			goto fail;
60615508Sbde	}
60715508Sbde
60815508Sbde	/* Wait for the mC146818A seconds counter to change. */
60915508Sbde	start_sec = sec;
61015508Sbde	for (;;) {
61115508Sbde		if (!(rtcin(RTC_STATUSA) & RTCSA_TUP)) {
61215508Sbde			sec = rtcin(RTC_SEC);
61315508Sbde			if (sec != start_sec)
61415508Sbde				break;
61515508Sbde		}
61615508Sbde		if (--timeout == 0)
61715508Sbde			goto fail;
61815508Sbde	}
61915508Sbde
62015508Sbde	/* Start keeping track of the i8254 counter. */
62115508Sbde	prev_count = getit();
62215508Sbde	if (prev_count == 0 || prev_count > timer0_max_count)
62315508Sbde		goto fail;
62415508Sbde	tot_count = 0;
62515508Sbde
62632054Sphk	if (tsc_present)
62748160Sgreen		old_tsc = rdtsc();
62848266Speter	else
62948266Speter		old_tsc = 0;		/* shut up gcc */
63015508Sbde
63115508Sbde	/*
63215508Sbde	 * Wait for the mc146818A seconds counter to change.  Read the i8254
63315508Sbde	 * counter for each iteration since this is convenient and only
63415508Sbde	 * costs a few usec of inaccuracy. The timing of the final reads
63515508Sbde	 * of the counters almost matches the timing of the initial reads,
63615508Sbde	 * so the main cause of inaccuracy is the varying latency from
63715508Sbde	 * inside getit() or rtcin(RTC_STATUSA) to the beginning of the
63815508Sbde	 * rtcin(RTC_SEC) that returns a changed seconds count.  The
63915508Sbde	 * maximum inaccuracy from this cause is < 10 usec on 486's.
64015508Sbde	 */
64115508Sbde	start_sec = sec;
64215508Sbde	for (;;) {
64315508Sbde		if (!(rtcin(RTC_STATUSA) & RTCSA_TUP))
64415508Sbde			sec = rtcin(RTC_SEC);
64515508Sbde		count = getit();
64615508Sbde		if (count == 0 || count > timer0_max_count)
64715508Sbde			goto fail;
64815508Sbde		if (count > prev_count)
64915508Sbde			tot_count += prev_count - (count - timer0_max_count);
65015508Sbde		else
65115508Sbde			tot_count += prev_count - count;
65215508Sbde		prev_count = count;
65315508Sbde		if (sec != start_sec)
65415508Sbde			break;
65515508Sbde		if (--timeout == 0)
65615508Sbde			goto fail;
65715508Sbde	}
65815508Sbde
65915508Sbde	/*
66015508Sbde	 * Read the cpu cycle counter.  The timing considerations are
66115508Sbde	 * similar to those for the i8254 clock.
66215508Sbde	 */
66333690Sphk	if (tsc_present)
66448160Sgreen		tsc_freq = rdtsc() - old_tsc;
66533690Sphk
66633690Sphk	if (bootverbose) {
66733690Sphk		if (tsc_present)
66832005Sphk		        printf("TSC clock: %u Hz, ", tsc_freq);
66933929Sphk	        printf("i8254 clock: %u Hz\n", tot_count);
67015508Sbde	}
67115508Sbde	return (tot_count);
67215508Sbde
67315508Sbdefail:
67423393Sbde	if (bootverbose)
67523393Sbde	        printf("failed, using default i8254 clock of %u Hz\n",
67623393Sbde		       timer_freq);
67715508Sbde	return (timer_freq);
67815508Sbde}
67915508Sbde
68015508Sbdestatic void
68115508Sbdeset_timer_freq(u_int freq, int intr_freq)
68215508Sbde{
68316874Sbde	u_long ef;
68433309Sbde	int new_timer0_max_count;
68515508Sbde
68615508Sbde	ef = read_eflags();
68729000Sfsmp	disable_intr();
68815508Sbde	timer_freq = freq;
68933309Sbde	new_timer0_max_count = hardclock_max_count = TIMER_DIV(intr_freq);
69033309Sbde	if (new_timer0_max_count != timer0_max_count) {
69133309Sbde		timer0_max_count = new_timer0_max_count;
69233309Sbde		outb(TIMER_MODE, TIMER_SEL0 | TIMER_RATEGEN | TIMER_16BIT);
69333309Sbde		outb(TIMER_CNTR0, timer0_max_count & 0xff);
69433309Sbde		outb(TIMER_CNTR0, timer0_max_count >> 8);
69533309Sbde	}
69628921Sfsmp	CLOCK_UNLOCK();
69715508Sbde	write_eflags(ef);
69815508Sbde}
69915508Sbde
7005291Sbde/*
70133690Sphk * Initialize 8254 timer 0 early so that it can be used in DELAY().
7025291Sbde * XXX initialization of other timers is unintentionally left blank.
7035291Sbde */
7041390Ssosvoid
7058876Srgrimesstartrtclock()
706798Swollman{
70715508Sbde	u_int delta, freq;
70815508Sbde
70932054Sphk	if (cpu_feature & CPUID_TSC)
71032054Sphk		tsc_present = 1;
71132054Sphk	else
71232054Sphk		tsc_present = 0;
71332054Sphk
71415508Sbde	writertc(RTC_STATUSA, rtc_statusa);
71515508Sbde	writertc(RTC_STATUSB, RTCSB_24HR);
71615508Sbde
71716874Sbde	set_timer_freq(timer_freq, hz);
71815508Sbde	freq = calibrate_clocks();
71915508Sbde#ifdef CLK_CALIBRATION_LOOP
72015508Sbde	if (bootverbose) {
72115508Sbde		printf(
72215508Sbde		"Press a key on the console to abort clock calibration\n");
72318288Sbde		while (cncheckc() == -1)
72415508Sbde			calibrate_clocks();
72515508Sbde	}
72615508Sbde#endif
72715508Sbde
72815508Sbde	/*
72915508Sbde	 * Use the calibrated i8254 frequency if it seems reasonable.
73015508Sbde	 * Otherwise use the default, and don't use the calibrated i586
73115508Sbde	 * frequency.
73215508Sbde	 */
73315508Sbde	delta = freq > timer_freq ? freq - timer_freq : timer_freq - freq;
73415508Sbde	if (delta < timer_freq / 100) {
73515508Sbde#ifndef CLK_USE_I8254_CALIBRATION
73616300Spst		if (bootverbose)
73719173Sbde			printf(
73815508Sbde"CLK_USE_I8254_CALIBRATION not specified - using default frequency\n");
73915508Sbde		freq = timer_freq;
74015508Sbde#endif
74115508Sbde		timer_freq = freq;
74215508Sbde	} else {
74323393Sbde		if (bootverbose)
74423393Sbde			printf(
74523393Sbde		    "%d Hz differs from default of %d Hz by more than 1%%\n",
74623393Sbde			       freq, timer_freq);
74732005Sphk		tsc_freq = 0;
74815508Sbde	}
74915508Sbde
75015508Sbde	set_timer_freq(timer_freq, hz);
75140610Sphk	i8254_timecounter.tc_frequency = timer_freq;
75240610Sphk	init_timecounter(&i8254_timecounter);
75315508Sbde
75432005Sphk#ifndef CLK_USE_TSC_CALIBRATION
75532005Sphk	if (tsc_freq != 0) {
75616300Spst		if (bootverbose)
75719173Sbde			printf(
75832005Sphk"CLK_USE_TSC_CALIBRATION not specified - using old calibration method\n");
75932005Sphk		tsc_freq = 0;
76015508Sbde	}
76115508Sbde#endif
76232054Sphk	if (tsc_present && tsc_freq == 0) {
76315508Sbde		/*
76415508Sbde		 * Calibration of the i586 clock relative to the mc146818A
76515508Sbde		 * clock failed.  Do a less accurate calibration relative
76615508Sbde		 * to the i8254 clock.
76715508Sbde		 */
76848160Sgreen		u_int64_t old_tsc = rdtsc();
76948160Sgreen
77015508Sbde		DELAY(1000000);
77148160Sgreen		tsc_freq = rdtsc() - old_tsc;
77232054Sphk#ifdef CLK_USE_TSC_CALIBRATION
77323393Sbde		if (bootverbose)
77433690Sphk			printf("TSC clock: %u Hz (Method B)\n", tsc_freq);
77516300Spst#endif
77615508Sbde	}
77734617Sphk
77834617Sphk#if !defined(SMP)
77934617Sphk	/*
78034617Sphk	 * We can not use the TSC in SMP mode, until we figure out a
78134617Sphk	 * cheap (impossible), reliable and precise (yeah right!)  way
78234617Sphk	 * to synchronize the TSCs of all the CPUs.
78334617Sphk	 * Curse Intel for leaving the counter out of the I/O APIC.
78434617Sphk	 */
78534617Sphk
78634617Sphk#if NAPM > 0
78734617Sphk	/*
78834617Sphk	 * We can not use the TSC if we found an APM bios.  Too many
78934617Sphk	 * of them lie about their ability&intention to fiddle the CPU
79034617Sphk	 * clock for us to rely on this.  Precise timekeeping on an
79134617Sphk	 * APM'ed machine is at best a fools pursuit anyway, since
79234617Sphk	 * any and all of the time spent in various SMM code can't
79334617Sphk	 * be reliably accounted for.  Reading the RTC is your only
79434617Sphk	 * source of reliable time info.  The i8254 looses too of course
79534617Sphk	 * but we need to have some kind of time...
79634617Sphk	 */
79734617Sphk	if (apm_version != APMINI_CANTFIND)
79834617Sphk		return;
79934617Sphk#endif /* NAPM > 0 */
80034617Sphk
80147592Sphk	if (tsc_present && tsc_freq != 0 && !tsc_is_broken) {
80240610Sphk		tsc_timecounter.tc_frequency = tsc_freq;
80340610Sphk		init_timecounter(&tsc_timecounter);
80433690Sphk	}
80534617Sphk
80634617Sphk#endif /* !defined(SMP) */
8074Srgrimes}
8084Srgrimes
8092913Sache/*
81041787Smckay * Initialize the time of day register, based on the time base which is, e.g.
81141787Smckay * from a filesystem.
8122913Sache */
8132913Sachevoid
8143185Ssosinittodr(time_t base)
8154Srgrimes{
8162913Sache	unsigned long	sec, days;
8172913Sache	int		yd;
8182913Sache	int		year, month;
8192913Sache	int		y, m, s;
82033690Sphk	struct timespec ts;
8214Srgrimes
82232850Sphk	if (base) {
82332850Sphk		s = splclock();
82433690Sphk		ts.tv_sec = base;
82533690Sphk		ts.tv_nsec = 0;
82633690Sphk		set_timecounter(&ts);
82732850Sphk		splx(s);
82832850Sphk	}
8291390Ssos
83041787Smckay	/* Look if we have a RTC present and the time is valid */
8319202Srgrimes	if (!(rtcin(RTC_STATUSD) & RTCSD_PWR))
8322913Sache		goto wrong_time;
8334Srgrimes
83441787Smckay	/* wait for time update to complete */
83541787Smckay	/* If RTCSA_TUP is zero, we have at least 244us before next update */
8362913Sache	while (rtcin(RTC_STATUSA) & RTCSA_TUP);
8374Srgrimes
8382913Sache	days = 0;
8393355Sache#ifdef USE_RTC_CENTURY
84041787Smckay	year = readrtc(RTC_YEAR) + readrtc(RTC_CENTURY) * 100;
8413355Sache#else
8423355Sache	year = readrtc(RTC_YEAR) + 1900;
8432913Sache	if (year < 1970)
8443355Sache		year += 100;
8453355Sache#endif
8463355Sache	if (year < 1970)
8472913Sache		goto wrong_time;
84841787Smckay	month = readrtc(RTC_MONTH);
84941787Smckay	for (m = 1; m < month; m++)
85041787Smckay		days += daysinmonth[m-1];
85141787Smckay	if ((month > 2) && LEAPYEAR(year))
8522913Sache		days ++;
85341787Smckay	days += readrtc(RTC_DAY) - 1;
8542913Sache	yd = days;
8552913Sache	for (y = 1970; y < year; y++)
85641787Smckay		days += DAYSPERYEAR + LEAPYEAR(y);
8572913Sache	sec = ((( days * 24 +
8582913Sache		  readrtc(RTC_HRS)) * 60 +
8592913Sache		  readrtc(RTC_MIN)) * 60 +
8602913Sache		  readrtc(RTC_SEC));
86141787Smckay	/* sec now contains the number of seconds, since Jan 1 1970,
86241787Smckay	   in the local time zone */
8631390Ssos
86415054Sache	sec += tz.tz_minuteswest * 60 + (wall_cmos_clock ? adjkerntz : 0);
8654Srgrimes
86634961Sphk	y = time_second - sec;
86733690Sphk	if (y <= -2 || y >= 2) {
86833690Sphk		/* badly off, adjust it */
86933690Sphk		s = splclock();
87033690Sphk		ts.tv_sec = sec;
87133690Sphk		ts.tv_nsec = 0;
87233690Sphk		set_timecounter(&ts);
87333690Sphk		splx(s);
87433690Sphk	}
8752913Sache	return;
8762913Sache
8772913Sachewrong_time:
87841787Smckay	printf("Invalid time in real time clock.\n");
87941787Smckay	printf("Check and reset the date immediately!\n");
8804Srgrimes}
8814Srgrimes
8824Srgrimes/*
88341787Smckay * Write system time back to RTC
8844Srgrimes */
8854180Sbdevoid
8864180Sbderesettodr()
8874Srgrimes{
8882913Sache	unsigned long	tm;
88911872Sphk	int		y, m, s;
8904Srgrimes
8913366Sache	if (disable_rtc_set)
8923366Sache		return;
8933366Sache
8942913Sache	s = splclock();
89534961Sphk	tm = time_second;
8962913Sache	splx(s);
8974Srgrimes
8985291Sbde	/* Disable RTC updates and interrupts. */
8992913Sache	writertc(RTC_STATUSB, RTCSB_HALT | RTCSB_24HR);
9004Srgrimes
90141787Smckay	/* Calculate local time to put in RTC */
9021390Ssos
90315054Sache	tm -= tz.tz_minuteswest * 60 + (wall_cmos_clock ? adjkerntz : 0);
9042913Sache
90513445Sphk	writertc(RTC_SEC, bin2bcd(tm%60)); tm /= 60;	/* Write back Seconds */
90613445Sphk	writertc(RTC_MIN, bin2bcd(tm%60)); tm /= 60;	/* Write back Minutes */
90713445Sphk	writertc(RTC_HRS, bin2bcd(tm%24)); tm /= 24;	/* Write back Hours   */
9082913Sache
90941787Smckay	/* We have now the days since 01-01-1970 in tm */
9102913Sache	writertc(RTC_WDAY, (tm+4)%7);			/* Write back Weekday */
91113350Sache	for (y = 1970, m = DAYSPERYEAR + LEAPYEAR(y);
91213350Sache	     tm >= m;
91313350Sache	     y++,      m = DAYSPERYEAR + LEAPYEAR(y))
91413350Sache	     tm -= m;
9152913Sache
9162913Sache	/* Now we have the years in y and the day-of-the-year in tm */
91713453Sache	writertc(RTC_YEAR, bin2bcd(y%100));		/* Write back Year    */
91813350Sache#ifdef USE_RTC_CENTURY
91913445Sphk	writertc(RTC_CENTURY, bin2bcd(y/100));		/* ... and Century    */
9203355Sache#endif
92113402Sbde	for (m = 0; ; m++) {
92213402Sbde		int ml;
9232913Sache
92413402Sbde		ml = daysinmonth[m];
92513402Sbde		if (m == 1 && LEAPYEAR(y))
92613402Sbde			ml++;
92713402Sbde		if (tm < ml)
92813402Sbde			break;
92913402Sbde		tm -= ml;
93013402Sbde	}
93113402Sbde
93213445Sphk	writertc(RTC_MONTH, bin2bcd(m + 1));            /* Write back Month   */
93313445Sphk	writertc(RTC_DAY, bin2bcd(tm + 1));             /* Write back Month Day */
9342913Sache
9355291Sbde	/* Reenable RTC updates and interrupts. */
93615345Snate	writertc(RTC_STATUSB, rtc_statusb);
9374Srgrimes}
9384Srgrimes
93927560Sfsmp
9404Srgrimes/*
9415291Sbde * Start both clocks running.
9424Srgrimes */
9435291Sbdevoid
9445291Sbdecpu_initclocks()
9454Srgrimes{
9465291Sbde	int diag;
94726949Sfsmp#ifdef APIC_IO
94834571Stegge	int apic_8254_trial;
94945900Speter	struct intrec *clkdesc;
95025164Speter#endif /* APIC_IO */
9514Srgrimes
95215345Snate	if (statclock_disable) {
95315345Snate		/*
95415345Snate		 * The stat interrupt mask is different without the
95515345Snate		 * statistics clock.  Also, don't set the interrupt
95615345Snate		 * flag which would normally cause the RTC to generate
95715345Snate		 * interrupts.
95815345Snate		 */
95915345Snate		stat_imask = HWI_MASK | SWI_MASK;
96015345Snate		rtc_statusb = RTCSB_24HR;
96115345Snate	} else {
96215345Snate	        /* Setting stathz to nonzero early helps avoid races. */
96315345Snate		stathz = RTC_NOPROFRATE;
96415345Snate		profhz = RTC_PROFRATE;
96515345Snate        }
9664Srgrimes
9675291Sbde	/* Finish initializing 8253 timer 0. */
96826949Sfsmp#ifdef APIC_IO
96927563Sfsmp
97038888Stegge	apic_8254_intr = isa_apic_irq(0);
97134571Stegge	apic_8254_trial = 0;
97234571Stegge	if (apic_8254_intr >= 0 ) {
97334571Stegge		if (apic_int_type(0, 0) == 3)
97434571Stegge			apic_8254_trial = 1;
97534571Stegge	} else {
97634571Stegge		/* look for ExtInt on pin 0 */
97734571Stegge		if (apic_int_type(0, 0) == 3) {
97834571Stegge			apic_8254_intr = 0;
97934571Stegge			setup_8254_mixed_mode();
98034571Stegge		} else
98134571Stegge			panic("APIC_IO: Cannot route 8254 interrupt to CPU");
98227563Sfsmp	}
98327563Sfsmp
98445897Speter	clkdesc = inthand_add("clk", apic_8254_intr, (inthand2_t *)clkintr,
98545897Speter			      NULL, &clk_imask, INTR_EXCL);
98634571Stegge	INTREN(1 << apic_8254_intr);
98734571Stegge
98827696Sfsmp#else /* APIC_IO */
98927563Sfsmp
99045897Speter	inthand_add("clk", 0, (inthand2_t *)clkintr, NULL, &clk_imask,
99145897Speter		    INTR_EXCL);
9924Srgrimes	INTREN(IRQ0);
99327696Sfsmp
99425164Speter#endif /* APIC_IO */
99526949Sfsmp
9965291Sbde	/* Initialize RTC. */
9975291Sbde	writertc(RTC_STATUSA, rtc_statusa);
9985291Sbde	writertc(RTC_STATUSB, RTCSB_24HR);
99915345Snate
100015345Snate	/* Don't bother enabling the statistics clock. */
100115345Snate	if (statclock_disable)
100215345Snate		return;
10035291Sbde	diag = rtcin(RTC_DIAG);
10045291Sbde	if (diag != 0)
10055291Sbde		printf("RTC BIOS diagnostic error %b\n", diag, RTCDG_BITS);
100627520Sfsmp
100726949Sfsmp#ifdef APIC_IO
100838888Stegge	if (isa_apic_irq(8) != 8)
100927520Sfsmp		panic("APIC RTC != 8");
101027563Sfsmp#endif /* APIC_IO */
101128487Sfsmp
101245897Speter	inthand_add("rtc", 8, (inthand2_t *)rtcintr, NULL, &stat_imask,
101345897Speter		    INTR_EXCL);
101428487Sfsmp
101527616Sfsmp#ifdef APIC_IO
101627616Sfsmp	INTREN(APIC_IRQ8);
101727616Sfsmp#else
10182074Swollman	INTREN(IRQ8);
101927616Sfsmp#endif /* APIC_IO */
102027520Sfsmp
102115345Snate	writertc(RTC_STATUSB, rtc_statusb);
102234571Stegge
102334571Stegge#ifdef APIC_IO
102434571Stegge	if (apic_8254_trial) {
102534571Stegge
102634571Stegge		printf("APIC_IO: Testing 8254 interrupt delivery\n");
102734571Stegge		while (read_intr_count(8) < 6)
102835035Stegge			;	/* nothing */
102934571Stegge		if (read_intr_count(apic_8254_intr) < 3) {
103034571Stegge			/*
103134571Stegge			 * The MP table is broken.
103234571Stegge			 * The 8254 was not connected to the specified pin
103334571Stegge			 * on the IO APIC.
103434571Stegge			 * Workaround: Limited variant of mixed mode.
103534571Stegge			 */
103634571Stegge			INTRDIS(1 << apic_8254_intr);
103745897Speter			inthand_remove(clkdesc);
103834571Stegge			printf("APIC_IO: Broken MP table detected: "
103934571Stegge			       "8254 is not connected to IO APIC int pin %d\n",
104034571Stegge			       apic_8254_intr);
104134571Stegge
104234571Stegge			apic_8254_intr = 0;
104334571Stegge			setup_8254_mixed_mode();
104445897Speter			inthand_add("clk", apic_8254_intr,(inthand2_t *)clkintr,
104545897Speter				    NULL, &clk_imask, INTR_EXCL);
104634571Stegge			INTREN(1 << apic_8254_intr);
104734571Stegge		}
104834571Stegge
104934571Stegge	}
105034571Stegge	if (apic_8254_intr)
105134571Stegge		printf("APIC_IO: routing 8254 via pin %d\n",apic_8254_intr);
105234571Stegge	else
105334571Stegge		printf("APIC_IO: routing 8254 via 8259 on pin 0\n");
105434571Stegge#endif
105534571Stegge
10564Srgrimes}
10574Srgrimes
105834571Stegge#ifdef APIC_IO
105934571Steggestatic u_long
106034571Steggeread_intr_count(int vec)
106134571Stegge{
106234571Stegge	u_long *up;
106334571Stegge	up = intr_countp[vec];
106434571Stegge	if (up)
106534571Stegge		return *up;
106634571Stegge	return 0UL;
106734571Stegge}
106834571Stegge
106934571Steggestatic void
107034571Steggesetup_8254_mixed_mode()
107134571Stegge{
107234571Stegge	/*
107334571Stegge	 * Allow 8254 timer to INTerrupt 8259:
107434571Stegge	 *  re-initialize master 8259:
107534571Stegge	 *   reset; prog 4 bytes, single ICU, edge triggered
107634571Stegge	 */
107734571Stegge	outb(IO_ICU1, 0x13);
107834571Stegge	outb(IO_ICU1 + 1, NRSVIDT);	/* start vector (unused) */
107934571Stegge	outb(IO_ICU1 + 1, 0x00);	/* ignore slave */
108034571Stegge	outb(IO_ICU1 + 1, 0x03);	/* auto EOI, 8086 */
108134571Stegge	outb(IO_ICU1 + 1, 0xfe);	/* unmask INT0 */
108234571Stegge
108334571Stegge	/* program IO APIC for type 3 INT on INT0 */
108434571Stegge	if (ext_int_setup(0, 0) < 0)
108534571Stegge		panic("8254 redirect via APIC pin0 impossible!");
108634571Stegge}
108734571Stegge#endif
108834571Stegge
10894Srgrimesvoid
10901549Srgrimessetstatclockrate(int newhz)
10911549Srgrimes{
10925291Sbde	if (newhz == RTC_PROFRATE)
10932074Swollman		rtc_statusa = RTCSA_DIVIDER | RTCSA_PROF;
10945291Sbde	else
10952074Swollman		rtc_statusa = RTCSA_DIVIDER | RTCSA_NOPROF;
10965291Sbde	writertc(RTC_STATUSA, rtc_statusa);
10971549Srgrimes}
109815508Sbde
109915508Sbdestatic int
110015508Sbdesysctl_machdep_i8254_freq SYSCTL_HANDLER_ARGS
110115508Sbde{
110215508Sbde	int error;
110315508Sbde	u_int freq;
110415508Sbde
110515508Sbde	/*
110615508Sbde	 * Use `i8254' instead of `timer' in external names because `timer'
110715508Sbde	 * is is too generic.  Should use it everywhere.
110815508Sbde	 */
110915508Sbde	freq = timer_freq;
111048888Sbde	error = sysctl_handle_int(oidp, &freq, sizeof(freq), req);
111117353Sbde	if (error == 0 && req->newptr != NULL) {
111233690Sphk		if (timer0_state != RELEASED)
111315508Sbde			return (EBUSY);	/* too much trouble to handle */
111415508Sbde		set_timer_freq(freq, hz);
111540610Sphk		i8254_timecounter.tc_frequency = freq;
111646054Sphk		update_timecounter(&i8254_timecounter);
111715508Sbde	}
111815508Sbde	return (error);
111915508Sbde}
112015508Sbde
112115508SbdeSYSCTL_PROC(_machdep, OID_AUTO, i8254_freq, CTLTYPE_INT | CTLFLAG_RW,
112248888Sbde    0, sizeof(u_int), sysctl_machdep_i8254_freq, "I", "");
112315508Sbde
112415508Sbdestatic int
112532054Sphksysctl_machdep_tsc_freq SYSCTL_HANDLER_ARGS
112615508Sbde{
112715508Sbde	int error;
112815508Sbde	u_int freq;
112915508Sbde
113048888Sbde	if (tsc_timecounter.tc_frequency == 0)
113115508Sbde		return (EOPNOTSUPP);
113232005Sphk	freq = tsc_freq;
113348888Sbde	error = sysctl_handle_int(oidp, &freq, sizeof(freq), req);
113433690Sphk	if (error == 0 && req->newptr != NULL) {
113533690Sphk		tsc_freq = freq;
113640610Sphk		tsc_timecounter.tc_frequency = tsc_freq;
113746054Sphk		update_timecounter(&tsc_timecounter);
113833690Sphk	}
113915508Sbde	return (error);
114015508Sbde}
114115508Sbde
114232054SphkSYSCTL_PROC(_machdep, OID_AUTO, tsc_freq, CTLTYPE_INT | CTLFLAG_RW,
114348888Sbde    0, sizeof(u_int), sysctl_machdep_tsc_freq, "I", "");
114433690Sphk
114536441Sphkstatic unsigned
114636719Sphki8254_get_timecount(struct timecounter *tc)
114733690Sphk{
114836198Sphk	u_int count;
114933690Sphk	u_long ef;
115033690Sphk	u_int high, low;
115133690Sphk
115233690Sphk	ef = read_eflags();
115333690Sphk	disable_intr();
115433690Sphk
115533690Sphk	/* Select timer0 and latch counter value. */
115633690Sphk	outb(TIMER_MODE, TIMER_SEL0 | TIMER_LATCH);
115733690Sphk
115833690Sphk	low = inb(TIMER_CNTR0);
115933690Sphk	high = inb(TIMER_CNTR0);
116047588Sbde	count = timer0_max_count - ((high << 8) | low);
116147588Sbde	if (count < i8254_lastcount ||
116247588Sbde	    (!i8254_ticked && (clkintr_pending ||
116347588Sbde	    ((count < 20 || (!(ef & PSL_I) && count < timer0_max_count / 2u)) &&
116447588Sbde#ifdef APIC_IO
116547588Sbde#define	lapic_irr1	((volatile u_int *)&lapic)[0x210 / 4]	/* XXX XXX */
116647588Sbde	    /* XXX this assumes that apic_8254_intr is < 24. */
116747588Sbde	    (lapic_irr1 & (1 << apic_8254_intr))))
116847588Sbde#else
116947588Sbde	    (inb(IO_ICU1) & 1)))
117047588Sbde#endif
117147588Sbde	    )) {
117233690Sphk		i8254_ticked = 1;
117347588Sbde		i8254_offset += timer0_max_count;
117433690Sphk	}
117533690Sphk	i8254_lastcount = count;
117633690Sphk	count += i8254_offset;
117733727Sjkh	CLOCK_UNLOCK();
117833690Sphk	write_eflags(ef);
117933690Sphk	return (count);
118033690Sphk}
118133690Sphk
118236441Sphkstatic unsigned
118336719Sphktsc_get_timecount(struct timecounter *tc)
118433690Sphk{
118536198Sphk	return (rdtsc());
118633690Sphk}
1187