pcrtc.c revision 36763
1/*-
2 * Copyright (c) 1990 The Regents of the University of California.
3 * All rights reserved.
4 *
5 * This code is derived from software contributed to Berkeley by
6 * William Jolitz and Don Ahn.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 *    notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 *    notice, this list of conditions and the following disclaimer in the
15 *    documentation and/or other materials provided with the distribution.
16 * 3. All advertising materials mentioning features or use of this software
17 *    must display the following acknowledgement:
18 *	This product includes software developed by the University of
19 *	California, Berkeley and its contributors.
20 * 4. Neither the name of the University nor the names of its contributors
21 *    may be used to endorse or promote products derived from this software
22 *    without specific prior written permission.
23 *
24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 * SUCH DAMAGE.
35 *
36 *	from: @(#)clock.c	7.2 (Berkeley) 5/12/91
37 *	$Id: clock.c,v 1.56 1998/06/07 09:51:08 kato Exp $
38 */
39
40/*
41 * Routines to handle clock hardware.
42 */
43
44/*
45 * inittodr, settodr and support routines written
46 * by Christoph Robitschko <chmr@edvz.tu-graz.ac.at>
47 *
48 * reintroduced and updated by Chris Stenton <chris@gnome.co.uk> 8/10/94
49 */
50
51/*
52 * modified for PC98 by Kakefuda
53 */
54
55#include "opt_clock.h"
56#include "apm.h"
57
58#include <sys/param.h>
59#include <sys/systm.h>
60#include <sys/time.h>
61#include <sys/kernel.h>
62#ifndef SMP
63#include <sys/lock.h>
64#endif
65#include <sys/sysctl.h>
66
67#include <machine/clock.h>
68#ifdef CLK_CALIBRATION_LOOP
69#include <machine/cons.h>
70#endif
71#include <machine/cputypes.h>
72#include <machine/frame.h>
73#include <machine/ipl.h>
74#include <machine/limits.h>
75#include <machine/md_var.h>
76#if NAPM > 0
77#include <machine/apm_bios.h>
78#include <i386/apm/apm_setup.h>
79#endif
80#ifdef APIC_IO
81#include <machine/segments.h>
82#endif
83#if defined(SMP) || defined(APIC_IO)
84#include <machine/smp.h>
85#endif /* SMP || APIC_IO */
86#include <machine/specialreg.h>
87
88#include <i386/isa/icu.h>
89#ifdef PC98
90#include <pc98/pc98/pc98.h>
91#include <pc98/pc98/pc98_machdep.h>
92#include <i386/isa/isa_device.h>
93#else
94#include <i386/isa/isa.h>
95#include <i386/isa/rtc.h>
96#endif
97#include <i386/isa/timerreg.h>
98
99#include <sys/interrupt.h>
100
101#ifdef SMP
102#define disable_intr()	CLOCK_DISABLE_INTR()
103#define enable_intr()	CLOCK_ENABLE_INTR()
104
105#ifdef APIC_IO
106#include <i386/isa/intr_machdep.h>
107/* The interrupt triggered by the 8254 (timer) chip */
108int apic_8254_intr;
109static u_long read_intr_count __P((int vec));
110static void setup_8254_mixed_mode __P((void));
111#endif
112#endif /* SMP */
113
114/*
115 * 32-bit time_t's can't reach leap years before 1904 or after 2036, so we
116 * can use a simple formula for leap years.
117 */
118#define	LEAPYEAR(y) ((u_int)(y) % 4 == 0)
119#define DAYSPERYEAR   (31+28+31+30+31+30+31+31+30+31+30+31)
120
121#define	TIMER_DIV(x) ((timer_freq + (x) / 2) / (x))
122
123/*
124 * Time in timer cycles that it takes for microtime() to disable interrupts
125 * and latch the count.  microtime() currently uses "cli; outb ..." so it
126 * normally takes less than 2 timer cycles.  Add a few for cache misses.
127 * Add a few more to allow for latency in bogus calls to microtime() with
128 * interrupts already disabled.
129 */
130#define	TIMER0_LATCH_COUNT	20
131
132/*
133 * Maximum frequency that we are willing to allow for timer0.  Must be
134 * low enough to guarantee that the timer interrupt handler returns
135 * before the next timer interrupt.
136 */
137#define	TIMER0_MAX_FREQ		20000
138
139int	adjkerntz;		/* local offset	from GMT in seconds */
140int	disable_rtc_set;	/* disable resettodr() if != 0 */
141u_int	idelayed;
142int	statclock_disable;
143u_int	stat_imask = SWI_CLOCK_MASK;
144#ifndef TIMER_FREQ
145#ifdef PC98
146#define	TIMER_FREQ	2457600;
147#else /* IBM-PC */
148#define	TIMER_FREQ	1193182;
149#endif /* PC98 */
150#endif
151u_int	timer_freq = TIMER_FREQ;
152int	timer0_max_count;
153u_int	tsc_freq;
154int	wall_cmos_clock;	/* wall	CMOS clock assumed if != 0 */
155
156static	int	beeping = 0;
157static	u_int	clk_imask = HWI_MASK | SWI_MASK;
158static	const u_char daysinmonth[] = {31,28,31,30,31,30,31,31,30,31,30,31};
159static	u_int	hardclock_max_count;
160static	u_int32_t i8254_lastcount;
161static	u_int32_t i8254_offset;
162static	int	i8254_ticked;
163/*
164 * XXX new_function and timer_func should not handle clockframes, but
165 * timer_func currently needs to hold hardclock to handle the
166 * timer0_state == 0 case.  We should use register_intr()/unregister_intr()
167 * to switch between clkintr() and a slightly different timerintr().
168 */
169static	void	(*new_function) __P((struct clockframe *frame));
170static	u_int	new_rate;
171#ifndef PC98
172static	u_char	rtc_statusa = RTCSA_DIVIDER | RTCSA_NOPROF;
173static	u_char	rtc_statusb = RTCSB_24HR | RTCSB_PINTR;
174#endif
175static	u_int	timer0_prescaler_count;
176
177/* Values for timerX_state: */
178#define	RELEASED	0
179#define	RELEASE_PENDING	1
180#define	ACQUIRED	2
181#define	ACQUIRE_PENDING	3
182
183static	u_char	timer0_state;
184#ifdef	PC98
185static 	u_char	timer1_state;
186#endif
187static	u_char	timer2_state;
188static	void	(*timer_func) __P((struct clockframe *frame)) = hardclock;
189#ifdef PC98
190static void rtc_serialcombit __P((int));
191static void rtc_serialcom __P((int));
192static int rtc_inb __P((void));
193static void rtc_outb __P((int));
194#endif
195static	u_int	tsc_present;
196
197static	unsigned i8254_get_timecount __P((struct timecounter *tc));
198static	unsigned tsc_get_timecount __P((struct timecounter *tc));
199static	void	set_timer_freq(u_int freq, int intr_freq);
200
201static struct timecounter tsc_timecounter[3] = {
202	tsc_get_timecount,	/* get_timecount */
203	0,			/* no poll_pps */
204 	~0u,			/* counter_mask */
205	0,			/* frequency */
206	 "TSC"			/* name */
207};
208
209SYSCTL_OPAQUE(_debug, OID_AUTO, tsc_timecounter, CTLFLAG_RD,
210	tsc_timecounter, sizeof(tsc_timecounter), "S,timecounter", "");
211
212static struct timecounter i8254_timecounter[3] = {
213	i8254_get_timecount,	/* get_timecount */
214	0,			/* no poll_pps */
215	~0u,			/* counter_mask */
216	0,			/* frequency */
217	"i8254"			/* name */
218};
219
220SYSCTL_OPAQUE(_debug, OID_AUTO, i8254_timecounter, CTLFLAG_RD,
221	i8254_timecounter, sizeof(i8254_timecounter), "S,timecounter", "");
222
223static void
224clkintr(struct clockframe frame)
225{
226	if (!i8254_ticked)
227		i8254_offset += timer0_max_count;
228	else
229		i8254_ticked = 0;
230	i8254_lastcount = 0;
231	timer_func(&frame);
232	switch (timer0_state) {
233
234	case RELEASED:
235		setdelayed();
236		break;
237
238	case ACQUIRED:
239		if ((timer0_prescaler_count += timer0_max_count)
240		    >= hardclock_max_count) {
241			timer0_prescaler_count -= hardclock_max_count;
242			hardclock(&frame);
243			setdelayed();
244		}
245		break;
246
247	case ACQUIRE_PENDING:
248		setdelayed();
249		timer0_max_count = TIMER_DIV(new_rate);
250		disable_intr();
251		outb(TIMER_MODE, TIMER_SEL0 | TIMER_RATEGEN | TIMER_16BIT);
252		outb(TIMER_CNTR0, timer0_max_count & 0xff);
253		outb(TIMER_CNTR0, timer0_max_count >> 8);
254		enable_intr();
255		timer0_prescaler_count = 0;
256		timer_func = new_function;
257		timer0_state = ACQUIRED;
258		break;
259
260	case RELEASE_PENDING:
261		if ((timer0_prescaler_count += timer0_max_count)
262		    >= hardclock_max_count) {
263			timer0_prescaler_count -= hardclock_max_count;
264#ifdef FIXME
265			/*
266			 * XXX: This magic doesn't work, but It shouldn't be
267			 * needed now anyway since we will not be able to
268			 * aquire the i8254 if it is used for timecounting.
269			 */
270			/*
271			 * See microtime.s for this magic.
272			 */
273#ifdef PC98
274			if (pc98_machine_type & M_8M) {
275				/* PC98_8M */
276				time.tv_usec += (16411 * timer0_prescaler_count) >> 15;
277			} else {
278				time.tv_usec += (6667 * timer0_prescaler_count) >> 14;
279			}
280#else /* IBM-PC */
281			time.tv_usec += (27465 * timer0_prescaler_count) >> 15;
282#endif
283			if (time.tv_usec >= 1000000)
284				time.tv_usec -= 1000000;
285#endif
286			hardclock(&frame);
287			setdelayed();
288			timer0_max_count = hardclock_max_count;
289			disable_intr();
290			outb(TIMER_MODE,
291			     TIMER_SEL0 | TIMER_RATEGEN | TIMER_16BIT);
292			outb(TIMER_CNTR0, timer0_max_count & 0xff);
293			outb(TIMER_CNTR0, timer0_max_count >> 8);
294			enable_intr();
295			timer0_prescaler_count = 0;
296			timer_func = hardclock;
297			timer0_state = RELEASED;
298		}
299		break;
300	}
301}
302
303/*
304 * The acquire and release functions must be called at ipl >= splclock().
305 */
306int
307acquire_timer0(int rate, void (*function) __P((struct clockframe *frame)))
308{
309	static int old_rate;
310
311	if (rate <= 0 || rate > TIMER0_MAX_FREQ)
312		return (-1);
313	if (strcmp(timecounter->name, "i8254") == 0)
314		return (-1);
315	switch (timer0_state) {
316
317	case RELEASED:
318		timer0_state = ACQUIRE_PENDING;
319		break;
320
321	case RELEASE_PENDING:
322		if (rate != old_rate)
323			return (-1);
324		/*
325		 * The timer has been released recently, but is being
326		 * re-acquired before the release completed.  In this
327		 * case, we simply reclaim it as if it had not been
328		 * released at all.
329		 */
330		timer0_state = ACQUIRED;
331		break;
332
333	default:
334		return (-1);	/* busy */
335	}
336	new_function = function;
337	old_rate = new_rate = rate;
338	return (0);
339}
340
341#ifdef PC98
342int
343acquire_timer1(int mode)
344{
345
346	if (timer1_state != RELEASED)
347		return (-1);
348	timer1_state = ACQUIRED;
349
350	/*
351	 * This access to the timer registers is as atomic as possible
352	 * because it is a single instruction.  We could do better if we
353	 * knew the rate.  Use of splclock() limits glitches to 10-100us,
354	 * and this is probably good enough for timer2, so we aren't as
355	 * careful with it as with timer0.
356	 */
357	outb(TIMER_MODE, TIMER_SEL1 | (mode & 0x3f));
358
359	return (0);
360}
361#endif
362
363int
364acquire_timer2(int mode)
365{
366
367	if (timer2_state != RELEASED)
368		return (-1);
369	timer2_state = ACQUIRED;
370
371	/*
372	 * This access to the timer registers is as atomic as possible
373	 * because it is a single instruction.  We could do better if we
374	 * knew the rate.  Use of splclock() limits glitches to 10-100us,
375	 * and this is probably good enough for timer2, so we aren't as
376	 * careful with it as with timer0.
377	 */
378	outb(TIMER_MODE, TIMER_SEL2 | (mode & 0x3f));
379
380	return (0);
381}
382
383int
384release_timer0()
385{
386	switch (timer0_state) {
387
388	case ACQUIRED:
389		timer0_state = RELEASE_PENDING;
390		break;
391
392	case ACQUIRE_PENDING:
393		/* Nothing happened yet, release quickly. */
394		timer0_state = RELEASED;
395		break;
396
397	default:
398		return (-1);
399	}
400	return (0);
401}
402
403#ifdef PC98
404int
405release_timer1()
406{
407
408	if (timer1_state != ACQUIRED)
409		return (-1);
410	timer1_state = RELEASED;
411	outb(TIMER_MODE, TIMER_SEL1 | TIMER_SQWAVE | TIMER_16BIT);
412	return (0);
413}
414#endif
415
416int
417release_timer2()
418{
419
420	if (timer2_state != ACQUIRED)
421		return (-1);
422	timer2_state = RELEASED;
423	outb(TIMER_MODE, TIMER_SEL2 | TIMER_SQWAVE | TIMER_16BIT);
424	return (0);
425}
426
427#ifndef PC98
428/*
429 * This routine receives statistical clock interrupts from the RTC.
430 * As explained above, these occur at 128 interrupts per second.
431 * When profiling, we receive interrupts at a rate of 1024 Hz.
432 *
433 * This does not actually add as much overhead as it sounds, because
434 * when the statistical clock is active, the hardclock driver no longer
435 * needs to keep (inaccurate) statistics on its own.  This decouples
436 * statistics gathering from scheduling interrupts.
437 *
438 * The RTC chip requires that we read status register C (RTC_INTR)
439 * to acknowledge an interrupt, before it will generate the next one.
440 * Under high interrupt load, rtcintr() can be indefinitely delayed and
441 * the clock can tick immediately after the read from RTC_INTR.  In this
442 * case, the mc146818A interrupt signal will not drop for long enough
443 * to register with the 8259 PIC.  If an interrupt is missed, the stat
444 * clock will halt, considerably degrading system performance.  This is
445 * why we use 'while' rather than a more straightforward 'if' below.
446 * Stat clock ticks can still be lost, causing minor loss of accuracy
447 * in the statistics, but the stat clock will no longer stop.
448 */
449static void
450rtcintr(struct clockframe frame)
451{
452	while (rtcin(RTC_INTR) & RTCIR_PERIOD)
453		statclock(&frame);
454}
455
456#include "opt_ddb.h"
457#ifdef DDB
458#include <ddb/ddb.h>
459
460DB_SHOW_COMMAND(rtc, rtc)
461{
462	printf("%02x/%02x/%02x %02x:%02x:%02x, A = %02x, B = %02x, C = %02x\n",
463	       rtcin(RTC_YEAR), rtcin(RTC_MONTH), rtcin(RTC_DAY),
464	       rtcin(RTC_HRS), rtcin(RTC_MIN), rtcin(RTC_SEC),
465	       rtcin(RTC_STATUSA), rtcin(RTC_STATUSB), rtcin(RTC_INTR));
466}
467#endif /* DDB */
468#endif /* for PC98 */
469
470static int
471getit(void)
472{
473	u_long ef;
474	int high, low;
475
476	ef = read_eflags();
477	disable_intr();
478
479	/* Select timer0 and latch counter value. */
480	outb(TIMER_MODE, TIMER_SEL0 | TIMER_LATCH);
481
482	low = inb(TIMER_CNTR0);
483	high = inb(TIMER_CNTR0);
484
485	CLOCK_UNLOCK();
486	write_eflags(ef);
487	return ((high << 8) | low);
488}
489
490/*
491 * Wait "n" microseconds.
492 * Relies on timer 1 counting down from (timer_freq / hz)
493 * Note: timer had better have been programmed before this is first used!
494 */
495void
496DELAY(int n)
497{
498	int delta, prev_tick, tick, ticks_left;
499
500#ifdef DELAYDEBUG
501	int getit_calls = 1;
502	int n1;
503	static int state = 0;
504
505	if (state == 0) {
506		state = 1;
507		for (n1 = 1; n1 <= 10000000; n1 *= 10)
508			DELAY(n1);
509		state = 2;
510	}
511	if (state == 1)
512		printf("DELAY(%d)...", n);
513#endif
514	/*
515	 * Guard against the timer being uninitialized if we are called
516	 * early for console i/o.
517	 */
518	if (timer0_max_count == 0)
519		set_timer_freq(timer_freq, hz);
520
521	/*
522	 * Read the counter first, so that the rest of the setup overhead is
523	 * counted.  Guess the initial overhead is 20 usec (on most systems it
524	 * takes about 1.5 usec for each of the i/o's in getit().  The loop
525	 * takes about 6 usec on a 486/33 and 13 usec on a 386/20.  The
526	 * multiplications and divisions to scale the count take a while).
527	 */
528	prev_tick = getit();
529	n -= 0;			/* XXX actually guess no initial overhead */
530	/*
531	 * Calculate (n * (timer_freq / 1e6)) without using floating point
532	 * and without any avoidable overflows.
533	 */
534	if (n <= 0)
535		ticks_left = 0;
536	else if (n < 256)
537		/*
538		 * Use fixed point to avoid a slow division by 1000000.
539		 * 39099 = 1193182 * 2^15 / 10^6 rounded to nearest.
540		 * 2^15 is the first power of 2 that gives exact results
541		 * for n between 0 and 256.
542		 */
543		ticks_left = ((u_int)n * 39099 + (1 << 15) - 1) >> 15;
544	else
545		/*
546		 * Don't bother using fixed point, although gcc-2.7.2
547		 * generates particularly poor code for the long long
548		 * division, since even the slow way will complete long
549		 * before the delay is up (unless we're interrupted).
550		 */
551		ticks_left = ((u_int)n * (long long)timer_freq + 999999)
552			     / 1000000;
553
554	while (ticks_left > 0) {
555		tick = getit();
556#ifdef DELAYDEBUG
557		++getit_calls;
558#endif
559		delta = prev_tick - tick;
560		prev_tick = tick;
561		if (delta < 0) {
562			delta += timer0_max_count;
563			/*
564			 * Guard against timer0_max_count being wrong.
565			 * This shouldn't happen in normal operation,
566			 * but it may happen if set_timer_freq() is
567			 * traced.
568			 */
569			if (delta < 0)
570				delta = 0;
571		}
572		ticks_left -= delta;
573	}
574#ifdef DELAYDEBUG
575	if (state == 1)
576		printf(" %d calls to getit() at %d usec each\n",
577		       getit_calls, (n + 5) / getit_calls);
578#endif
579}
580
581static void
582sysbeepstop(void *chan)
583{
584#ifdef PC98	/* PC98 */
585	outb(IO_PPI, inb(IO_PPI)|0x08);	/* disable counter1 output to speaker */
586	release_timer1();
587#else
588	outb(IO_PPI, inb(IO_PPI)&0xFC);	/* disable counter2 output to speaker */
589	release_timer2();
590#endif
591	beeping = 0;
592}
593
594int
595sysbeep(int pitch, int period)
596{
597	int x = splclock();
598
599#ifdef PC98
600	if (acquire_timer1(TIMER_SQWAVE|TIMER_16BIT))
601		if (!beeping) {
602			/* Something else owns it. */
603			splx(x);
604			return (-1); /* XXX Should be EBUSY, but nobody cares anyway. */
605		}
606	disable_intr();
607	outb(0x3fdb, pitch);
608	outb(0x3fdb, (pitch>>8));
609	enable_intr();
610	if (!beeping) {
611		/* enable counter1 output to speaker */
612		outb(IO_PPI, (inb(IO_PPI) & 0xf7));
613		beeping = period;
614		timeout(sysbeepstop, (void *)NULL, period);
615	}
616#else
617	if (acquire_timer2(TIMER_SQWAVE|TIMER_16BIT))
618		if (!beeping) {
619			/* Something else owns it. */
620			splx(x);
621			return (-1); /* XXX Should be EBUSY, but nobody cares anyway. */
622		}
623	disable_intr();
624	outb(TIMER_CNTR2, pitch);
625	outb(TIMER_CNTR2, (pitch>>8));
626	enable_intr();
627	if (!beeping) {
628		/* enable counter2 output to speaker */
629		outb(IO_PPI, inb(IO_PPI) | 3);
630		beeping = period;
631		timeout(sysbeepstop, (void *)NULL, period);
632	}
633#endif
634	splx(x);
635	return (0);
636}
637
638#ifndef PC98
639/*
640 * RTC support routines
641 */
642
643int
644rtcin(reg)
645	int reg;
646{
647	u_char val;
648
649	outb(IO_RTC, reg);
650	inb(0x84);
651	val = inb(IO_RTC + 1);
652	inb(0x84);
653	return (val);
654}
655
656static __inline void
657writertc(u_char reg, u_char val)
658{
659	inb(0x84);
660	outb(IO_RTC, reg);
661	inb(0x84);
662	outb(IO_RTC + 1, val);
663	inb(0x84);		/* XXX work around wrong order in rtcin() */
664}
665
666static __inline int
667readrtc(int port)
668{
669	return(bcd2bin(rtcin(port)));
670}
671#endif
672
673#ifdef PC98
674unsigned int delaycount;
675#define FIRST_GUESS	0x2000
676static void findcpuspeed(void)
677{
678	int i;
679	int remainder;
680
681	/* Put counter in count down mode */
682	outb(TIMER_MODE, TIMER_SEL0 | TIMER_16BIT | TIMER_RATEGEN);
683	outb(TIMER_CNTR0, 0xff);
684	outb(TIMER_CNTR0, 0xff);
685	for (i = FIRST_GUESS; i; i--)
686		;
687	remainder = getit();
688	delaycount = (FIRST_GUESS * TIMER_DIV(1000)) / (0xffff - remainder);
689}
690#endif
691
692#ifndef PC98
693static u_int
694calibrate_clocks(void)
695{
696	u_int count, prev_count, tot_count;
697	int sec, start_sec, timeout;
698
699	if (bootverbose)
700	        printf("Calibrating clock(s) ... ");
701	if (!(rtcin(RTC_STATUSD) & RTCSD_PWR))
702		goto fail;
703	timeout = 100000000;
704
705	/* Read the mc146818A seconds counter. */
706	for (;;) {
707		if (!(rtcin(RTC_STATUSA) & RTCSA_TUP)) {
708			sec = rtcin(RTC_SEC);
709			break;
710		}
711		if (--timeout == 0)
712			goto fail;
713	}
714
715	/* Wait for the mC146818A seconds counter to change. */
716	start_sec = sec;
717	for (;;) {
718		if (!(rtcin(RTC_STATUSA) & RTCSA_TUP)) {
719			sec = rtcin(RTC_SEC);
720			if (sec != start_sec)
721				break;
722		}
723		if (--timeout == 0)
724			goto fail;
725	}
726
727	/* Start keeping track of the i8254 counter. */
728	prev_count = getit();
729	if (prev_count == 0 || prev_count > timer0_max_count)
730		goto fail;
731	tot_count = 0;
732
733	if (tsc_present)
734		wrmsr(0x10, 0LL);	/* XXX 0x10 is the MSR for the TSC */
735
736	/*
737	 * Wait for the mc146818A seconds counter to change.  Read the i8254
738	 * counter for each iteration since this is convenient and only
739	 * costs a few usec of inaccuracy. The timing of the final reads
740	 * of the counters almost matches the timing of the initial reads,
741	 * so the main cause of inaccuracy is the varying latency from
742	 * inside getit() or rtcin(RTC_STATUSA) to the beginning of the
743	 * rtcin(RTC_SEC) that returns a changed seconds count.  The
744	 * maximum inaccuracy from this cause is < 10 usec on 486's.
745	 */
746	start_sec = sec;
747	for (;;) {
748		if (!(rtcin(RTC_STATUSA) & RTCSA_TUP))
749			sec = rtcin(RTC_SEC);
750		count = getit();
751		if (count == 0 || count > timer0_max_count)
752			goto fail;
753		if (count > prev_count)
754			tot_count += prev_count - (count - timer0_max_count);
755		else
756			tot_count += prev_count - count;
757		prev_count = count;
758		if (sec != start_sec)
759			break;
760		if (--timeout == 0)
761			goto fail;
762	}
763
764	/*
765	 * Read the cpu cycle counter.  The timing considerations are
766	 * similar to those for the i8254 clock.
767	 */
768	if (tsc_present)
769		tsc_freq = rdtsc();
770
771	if (bootverbose) {
772		if (tsc_present)
773		        printf("TSC clock: %u Hz, ", tsc_freq);
774	        printf("i8254 clock: %u Hz\n", tot_count);
775	}
776	return (tot_count);
777
778fail:
779	if (bootverbose)
780	        printf("failed, using default i8254 clock of %u Hz\n",
781		       timer_freq);
782	return (timer_freq);
783}
784#endif	/* !PC98 */
785
786static void
787set_timer_freq(u_int freq, int intr_freq)
788{
789	u_long ef;
790	int new_timer0_max_count;
791
792	ef = read_eflags();
793	disable_intr();
794	timer_freq = freq;
795	new_timer0_max_count = hardclock_max_count = TIMER_DIV(intr_freq);
796	if (new_timer0_max_count != timer0_max_count) {
797		timer0_max_count = new_timer0_max_count;
798		outb(TIMER_MODE, TIMER_SEL0 | TIMER_RATEGEN | TIMER_16BIT);
799		outb(TIMER_CNTR0, timer0_max_count & 0xff);
800		outb(TIMER_CNTR0, timer0_max_count >> 8);
801	}
802	CLOCK_UNLOCK();
803	write_eflags(ef);
804}
805
806/*
807 * Initialize 8254 timer 0 early so that it can be used in DELAY().
808 * XXX initialization of other timers is unintentionally left blank.
809 */
810void
811startrtclock()
812{
813	u_int delta, freq;
814
815#ifdef PC98
816	findcpuspeed();
817	if (pc98_machine_type & M_8M)
818		timer_freq = 1996800L; /* 1.9968 MHz */
819	else
820		timer_freq = 2457600L; /* 2.4576 MHz */
821#endif /* PC98 */
822
823	if (cpu_feature & CPUID_TSC)
824		tsc_present = 1;
825	else
826		tsc_present = 0;
827
828#ifndef PC98
829	writertc(RTC_STATUSA, rtc_statusa);
830	writertc(RTC_STATUSB, RTCSB_24HR);
831#endif
832
833#ifndef PC98
834	set_timer_freq(timer_freq, hz);
835	freq = calibrate_clocks();
836#ifdef CLK_CALIBRATION_LOOP
837	if (bootverbose) {
838		printf(
839		"Press a key on the console to abort clock calibration\n");
840		while (cncheckc() == -1)
841			calibrate_clocks();
842	}
843#endif
844
845	/*
846	 * Use the calibrated i8254 frequency if it seems reasonable.
847	 * Otherwise use the default, and don't use the calibrated i586
848	 * frequency.
849	 */
850	delta = freq > timer_freq ? freq - timer_freq : timer_freq - freq;
851	if (delta < timer_freq / 100) {
852#ifndef CLK_USE_I8254_CALIBRATION
853		if (bootverbose)
854			printf(
855"CLK_USE_I8254_CALIBRATION not specified - using default frequency\n");
856		freq = timer_freq;
857#endif
858		timer_freq = freq;
859	} else {
860		if (bootverbose)
861			printf(
862		    "%d Hz differs from default of %d Hz by more than 1%%\n",
863			       freq, timer_freq);
864		tsc_freq = 0;
865	}
866#endif
867
868	set_timer_freq(timer_freq, hz);
869	i8254_timecounter[0].frequency = timer_freq;
870	init_timecounter(i8254_timecounter);
871
872#ifndef CLK_USE_TSC_CALIBRATION
873	if (tsc_freq != 0) {
874		if (bootverbose)
875			printf(
876"CLK_USE_TSC_CALIBRATION not specified - using old calibration method\n");
877		tsc_freq = 0;
878	}
879#endif
880	if (tsc_present && tsc_freq == 0) {
881		/*
882		 * Calibration of the i586 clock relative to the mc146818A
883		 * clock failed.  Do a less accurate calibration relative
884		 * to the i8254 clock.
885		 */
886		wrmsr(0x10, 0LL);	/* XXX */
887		DELAY(1000000);
888		tsc_freq = rdtsc();
889#ifdef CLK_USE_TSC_CALIBRATION
890		if (bootverbose)
891			printf("TSC clock: %u Hz (Method B)\n", tsc_freq);
892#endif
893	}
894
895#if !defined(SMP)
896	/*
897	 * We can not use the TSC in SMP mode, until we figure out a
898	 * cheap (impossible), reliable and precise (yeah right!)  way
899	 * to synchronize the TSCs of all the CPUs.
900	 * Curse Intel for leaving the counter out of the I/O APIC.
901	 */
902
903#if NAPM > 0
904	/*
905	 * We can not use the TSC if we found an APM bios.  Too many
906	 * of them lie about their ability&intention to fiddle the CPU
907	 * clock for us to rely on this.  Precise timekeeping on an
908	 * APM'ed machine is at best a fools pursuit anyway, since
909	 * any and all of the time spent in various SMM code can't
910	 * be reliably accounted for.  Reading the RTC is your only
911	 * source of reliable time info.  The i8254 looses too of course
912	 * but we need to have some kind of time...
913	 */
914	if (apm_version != APMINI_CANTFIND)
915		return;
916#endif /* NAPM > 0 */
917
918	if (tsc_present && tsc_freq != 0) {
919		tsc_timecounter[0].frequency = tsc_freq;
920		init_timecounter(tsc_timecounter);
921	}
922
923#endif /* !defined(SMP) */
924}
925
926#ifdef PC98
927static void
928rtc_serialcombit(int i)
929{
930	outb(IO_RTC, ((i&0x01)<<5)|0x07);
931	DELAY(1);
932	outb(IO_RTC, ((i&0x01)<<5)|0x17);
933	DELAY(1);
934	outb(IO_RTC, ((i&0x01)<<5)|0x07);
935	DELAY(1);
936}
937
938static void
939rtc_serialcom(int i)
940{
941	rtc_serialcombit(i&0x01);
942	rtc_serialcombit((i&0x02)>>1);
943	rtc_serialcombit((i&0x04)>>2);
944	rtc_serialcombit((i&0x08)>>3);
945	outb(IO_RTC, 0x07);
946	DELAY(1);
947	outb(IO_RTC, 0x0f);
948	DELAY(1);
949	outb(IO_RTC, 0x07);
950 	DELAY(1);
951}
952
953static void
954rtc_outb(int val)
955{
956	int s;
957	int sa = 0;
958
959	for (s=0;s<8;s++) {
960	    sa = ((val >> s) & 0x01) ? 0x27 : 0x07;
961	    outb(IO_RTC, sa);		/* set DI & CLK 0 */
962	    DELAY(1);
963	    outb(IO_RTC, sa | 0x10);	/* CLK 1 */
964	    DELAY(1);
965	}
966	outb(IO_RTC, sa & 0xef);	/* CLK 0 */
967}
968
969static int
970rtc_inb(void)
971{
972	int s;
973	int sa = 0;
974
975	for (s=0;s<8;s++) {
976	    sa |= ((inb(0x33) & 0x01) << s);
977	    outb(IO_RTC, 0x17);	/* CLK 1 */
978	    DELAY(1);
979	    outb(IO_RTC, 0x07);	/* CLK 0 */
980	    DELAY(2);
981	}
982	return sa;
983}
984#endif /* PC-98 */
985
986/*
987 * Initialize the time of day register,	based on the time base which is, e.g.
988 * from	a filesystem.
989 */
990void
991inittodr(time_t base)
992{
993	unsigned long	sec, days;
994	int		yd;
995	int		year, month;
996	int		y, m, s;
997	struct timespec ts;
998#ifdef PC98
999	int		second, min, hour;
1000#endif
1001
1002	if (base) {
1003		s = splclock();
1004		ts.tv_sec = base;
1005		ts.tv_nsec = 0;
1006		set_timecounter(&ts);
1007		splx(s);
1008	}
1009
1010#ifdef PC98
1011	rtc_serialcom(0x03);	/* Time Read */
1012	rtc_serialcom(0x01);	/* Register shift command. */
1013	DELAY(20);
1014
1015	second = bcd2bin(rtc_inb() & 0xff);	/* sec */
1016	min = bcd2bin(rtc_inb() & 0xff);	/* min */
1017	hour = bcd2bin(rtc_inb() & 0xff);	/* hour */
1018	days = bcd2bin(rtc_inb() & 0xff) - 1;	/* date */
1019
1020	month = (rtc_inb() >> 4) & 0x0f;	/* month */
1021	for (m = 1; m <	month; m++)
1022		days +=	daysinmonth[m-1];
1023	year = bcd2bin(rtc_inb() & 0xff) + 1900;	/* year */
1024	/* 2000 year problem */
1025	if (year < 1995)
1026		year += 100;
1027	if (year < 1970)
1028		goto wrong_time;
1029	for (y = 1970; y < year; y++)
1030		days +=	DAYSPERYEAR + LEAPYEAR(y);
1031	if ((month > 2)	&& LEAPYEAR(year))
1032		days ++;
1033	sec = ((( days * 24 +
1034		  hour) * 60 +
1035		  min) * 60 +
1036		  second);
1037	/* sec now contains the	number of seconds, since Jan 1 1970,
1038	   in the local	time zone */
1039#else	/* IBM-PC */
1040	/* Look	if we have a RTC present and the time is valid */
1041	if (!(rtcin(RTC_STATUSD) & RTCSD_PWR))
1042		goto wrong_time;
1043
1044	/* wait	for time update	to complete */
1045	/* If RTCSA_TUP	is zero, we have at least 244us	before next update */
1046	while (rtcin(RTC_STATUSA) & RTCSA_TUP);
1047
1048	days = 0;
1049#ifdef USE_RTC_CENTURY
1050	year = readrtc(RTC_YEAR) + readrtc(RTC_CENTURY)	* 100;
1051#else
1052	year = readrtc(RTC_YEAR) + 1900;
1053	if (year < 1970)
1054		year += 100;
1055#endif
1056	if (year < 1970)
1057		goto wrong_time;
1058	month =	readrtc(RTC_MONTH);
1059	for (m = 1; m <	month; m++)
1060		days +=	daysinmonth[m-1];
1061	if ((month > 2)	&& LEAPYEAR(year))
1062		days ++;
1063	days +=	readrtc(RTC_DAY) - 1;
1064	yd = days;
1065	for (y = 1970; y < year; y++)
1066		days +=	DAYSPERYEAR + LEAPYEAR(y);
1067	sec = ((( days * 24 +
1068		  readrtc(RTC_HRS)) * 60 +
1069		  readrtc(RTC_MIN)) * 60 +
1070		  readrtc(RTC_SEC));
1071	/* sec now contains the	number of seconds, since Jan 1 1970,
1072	   in the local	time zone */
1073#endif
1074
1075	sec += tz.tz_minuteswest * 60 + (wall_cmos_clock ? adjkerntz : 0);
1076
1077	y = time_second - sec;
1078	if (y <= -2 || y >= 2) {
1079		/* badly off, adjust it */
1080		s = splclock();
1081		ts.tv_sec = sec;
1082		ts.tv_nsec = 0;
1083		set_timecounter(&ts);
1084		splx(s);
1085	}
1086	return;
1087
1088wrong_time:
1089	printf("Invalid	time in	real time clock.\n");
1090	printf("Check and reset	the date immediately!\n");
1091}
1092
1093/*
1094 * Write system	time back to RTC
1095 */
1096void
1097resettodr()
1098{
1099	unsigned long	tm;
1100	int		y, m, s;
1101#ifdef PC98
1102	int		wd;
1103#endif
1104
1105	if (disable_rtc_set)
1106		return;
1107
1108	s = splclock();
1109	tm = time_second;
1110	splx(s);
1111
1112#ifdef PC98
1113	rtc_serialcom(0x01);	/* Register shift command. */
1114
1115	/* Calculate local time	to put in RTC */
1116
1117	tm -= tz.tz_minuteswest * 60 + (wall_cmos_clock ? adjkerntz : 0);
1118
1119	rtc_outb(bin2bcd(tm%60)); tm /= 60;	/* Write back Seconds */
1120	rtc_outb(bin2bcd(tm%60)); tm /= 60;	/* Write back Minutes */
1121	rtc_outb(bin2bcd(tm%24)); tm /= 24;	/* Write back Hours   */
1122
1123	/* We have now the days	since 01-01-1970 in tm */
1124	wd = (tm+4)%7;
1125	for (y = 1970, m = DAYSPERYEAR + LEAPYEAR(y);
1126	     tm >= m;
1127	     y++,      m = DAYSPERYEAR + LEAPYEAR(y))
1128	     tm -= m;
1129
1130	/* Now we have the years in y and the day-of-the-year in tm */
1131	for (m = 0; ; m++) {
1132		int ml;
1133
1134		ml = daysinmonth[m];
1135		if (m == 1 && LEAPYEAR(y))
1136			ml++;
1137		if (tm < ml)
1138			break;
1139		tm -= ml;
1140	}
1141
1142	m++;
1143	rtc_outb(bin2bcd(tm+1));		/* Write back Day     */
1144	rtc_outb((m << 4) | wd);		/* Write back Month & Weekday  */
1145	rtc_outb(bin2bcd(y%100));		/* Write back Year    */
1146
1147	rtc_serialcom(0x02);	/* Time set & Counter hold command. */
1148	rtc_serialcom(0x00);	/* Register hold command. */
1149#else
1150	/* Disable RTC updates and interrupts. */
1151	writertc(RTC_STATUSB, RTCSB_HALT | RTCSB_24HR);
1152
1153	/* Calculate local time	to put in RTC */
1154
1155	tm -= tz.tz_minuteswest * 60 + (wall_cmos_clock ? adjkerntz : 0);
1156
1157	writertc(RTC_SEC, bin2bcd(tm%60)); tm /= 60;	/* Write back Seconds */
1158	writertc(RTC_MIN, bin2bcd(tm%60)); tm /= 60;	/* Write back Minutes */
1159	writertc(RTC_HRS, bin2bcd(tm%24)); tm /= 24;	/* Write back Hours   */
1160
1161	/* We have now the days	since 01-01-1970 in tm */
1162	writertc(RTC_WDAY, (tm+4)%7);			/* Write back Weekday */
1163	for (y = 1970, m = DAYSPERYEAR + LEAPYEAR(y);
1164	     tm >= m;
1165	     y++,      m = DAYSPERYEAR + LEAPYEAR(y))
1166	     tm -= m;
1167
1168	/* Now we have the years in y and the day-of-the-year in tm */
1169	writertc(RTC_YEAR, bin2bcd(y%100));		/* Write back Year    */
1170#ifdef USE_RTC_CENTURY
1171	writertc(RTC_CENTURY, bin2bcd(y/100));		/* ... and Century    */
1172#endif
1173	for (m = 0; ; m++) {
1174		int ml;
1175
1176		ml = daysinmonth[m];
1177		if (m == 1 && LEAPYEAR(y))
1178			ml++;
1179		if (tm < ml)
1180			break;
1181		tm -= ml;
1182	}
1183
1184	writertc(RTC_MONTH, bin2bcd(m + 1));            /* Write back Month   */
1185	writertc(RTC_DAY, bin2bcd(tm + 1));             /* Write back Month Day */
1186
1187	/* Reenable RTC updates and interrupts. */
1188	writertc(RTC_STATUSB, rtc_statusb);
1189#endif
1190}
1191
1192
1193/*
1194 * Start both clocks running.
1195 */
1196void
1197cpu_initclocks()
1198{
1199#ifdef APIC_IO
1200	int apic_8254_trial;
1201#endif /* APIC_IO */
1202#ifndef PC98
1203	int diag;
1204
1205	if (statclock_disable) {
1206		/*
1207		 * The stat interrupt mask is different without the
1208		 * statistics clock.  Also, don't set the interrupt
1209		 * flag which would normally cause the RTC to generate
1210		 * interrupts.
1211		 */
1212		stat_imask = HWI_MASK | SWI_MASK;
1213		rtc_statusb = RTCSB_24HR;
1214	} else {
1215	        /* Setting stathz to nonzero early helps avoid races. */
1216		stathz = RTC_NOPROFRATE;
1217		profhz = RTC_PROFRATE;
1218        }
1219#endif
1220
1221	/* Finish initializing 8253 timer 0. */
1222#ifdef APIC_IO
1223
1224	apic_8254_intr = isa_apic_pin(0);
1225	apic_8254_trial = 0;
1226	if (apic_8254_intr >= 0 ) {
1227		if (apic_int_type(0, 0) == 3)
1228			apic_8254_trial = 1;
1229	} else {
1230		/* look for ExtInt on pin 0 */
1231		if (apic_int_type(0, 0) == 3) {
1232			apic_8254_intr = 0;
1233			setup_8254_mixed_mode();
1234		} else
1235			panic("APIC_IO: Cannot route 8254 interrupt to CPU");
1236	}
1237
1238	register_intr(/* irq */ apic_8254_intr, /* XXX id */ 0, /* flags */ 0,
1239		      /* XXX */ (inthand2_t *)clkintr, &clk_imask,
1240		      /* unit */ 0);
1241	INTREN(1 << apic_8254_intr);
1242
1243#else /* APIC_IO */
1244
1245	register_intr(/* irq */ 0, /* XXX id */ 0, /* flags */ 0,
1246		      /* XXX */ (inthand2_t *)clkintr, &clk_imask,
1247		      /* unit */ 0);
1248	INTREN(IRQ0);
1249
1250#endif /* APIC_IO */
1251
1252#ifndef PC98
1253	/* Initialize RTC. */
1254	writertc(RTC_STATUSA, rtc_statusa);
1255	writertc(RTC_STATUSB, RTCSB_24HR);
1256
1257	/* Don't bother enabling the statistics clock. */
1258	if (statclock_disable)
1259		return;
1260	diag = rtcin(RTC_DIAG);
1261	if (diag != 0)
1262		printf("RTC BIOS diagnostic error %b\n", diag, RTCDG_BITS);
1263
1264#ifdef APIC_IO
1265	if (isa_apic_pin(8) != 8)
1266		panic("APIC RTC != 8");
1267#endif /* APIC_IO */
1268
1269	register_intr(/* irq */ 8, /* XXX id */ 1, /* flags */ 0,
1270		      /* XXX */ (inthand2_t *)rtcintr, &stat_imask,
1271		      /* unit */ 0);
1272
1273#ifdef APIC_IO
1274	INTREN(APIC_IRQ8);
1275#else
1276	INTREN(IRQ8);
1277#endif /* APIC_IO */
1278
1279	writertc(RTC_STATUSB, rtc_statusb);
1280#endif /* !PC98 */
1281
1282#ifdef APIC_IO
1283	if (apic_8254_trial) {
1284
1285		printf("APIC_IO: Testing 8254 interrupt delivery\n");
1286		while (read_intr_count(8) < 6)
1287			;	/* nothing */
1288		if (read_intr_count(apic_8254_intr) < 3) {
1289			/*
1290			 * The MP table is broken.
1291			 * The 8254 was not connected to the specified pin
1292			 * on the IO APIC.
1293			 * Workaround: Limited variant of mixed mode.
1294			 */
1295			INTRDIS(1 << apic_8254_intr);
1296			unregister_intr(apic_8254_intr,
1297					/* XXX */ (inthand2_t *) clkintr);
1298			printf("APIC_IO: Broken MP table detected: "
1299			       "8254 is not connected to IO APIC int pin %d\n",
1300			       apic_8254_intr);
1301
1302			apic_8254_intr = 0;
1303			setup_8254_mixed_mode();
1304			register_intr(/* irq */ apic_8254_intr, /* XXX id */ 0, /* flags */ 0,
1305				      /* XXX */ (inthand2_t *)clkintr, &clk_imask,
1306				      /* unit */ 0);
1307			INTREN(1 << apic_8254_intr);
1308		}
1309
1310	}
1311	if (apic_8254_intr)
1312		printf("APIC_IO: routing 8254 via pin %d\n",apic_8254_intr);
1313	else
1314		printf("APIC_IO: routing 8254 via 8259 on pin 0\n");
1315#endif
1316
1317}
1318
1319#ifdef APIC_IO
1320static u_long
1321read_intr_count(int vec)
1322{
1323	u_long *up;
1324	up = intr_countp[vec];
1325	if (up)
1326		return *up;
1327	return 0UL;
1328}
1329
1330static void
1331setup_8254_mixed_mode()
1332{
1333	/*
1334	 * Allow 8254 timer to INTerrupt 8259:
1335	 *  re-initialize master 8259:
1336	 *   reset; prog 4 bytes, single ICU, edge triggered
1337	 */
1338	outb(IO_ICU1, 0x13);
1339#ifdef PC98
1340	outb(IO_ICU1 + 2, NRSVIDT);	/* start vector (unused) */
1341	outb(IO_ICU1 + 2, 0x00);	/* ignore slave */
1342	outb(IO_ICU1 + 2, 0x03);	/* auto EOI, 8086 */
1343	outb(IO_ICU1 + 2, 0xfe);	/* unmask INT0 */
1344#else
1345	outb(IO_ICU1 + 1, NRSVIDT);	/* start vector (unused) */
1346	outb(IO_ICU1 + 1, 0x00);	/* ignore slave */
1347	outb(IO_ICU1 + 1, 0x03);	/* auto EOI, 8086 */
1348	outb(IO_ICU1 + 1, 0xfe);	/* unmask INT0 */
1349#endif
1350	/* program IO APIC for type 3 INT on INT0 */
1351	if (ext_int_setup(0, 0) < 0)
1352		panic("8254 redirect via APIC pin0 impossible!");
1353}
1354#endif
1355
1356void
1357setstatclockrate(int newhz)
1358{
1359#ifndef PC98
1360	if (newhz == RTC_PROFRATE)
1361		rtc_statusa = RTCSA_DIVIDER | RTCSA_PROF;
1362	else
1363		rtc_statusa = RTCSA_DIVIDER | RTCSA_NOPROF;
1364	writertc(RTC_STATUSA, rtc_statusa);
1365#endif
1366}
1367
1368static int
1369sysctl_machdep_i8254_freq SYSCTL_HANDLER_ARGS
1370{
1371	int error;
1372	u_int freq;
1373
1374	/*
1375	 * Use `i8254' instead of `timer' in external names because `timer'
1376	 * is is too generic.  Should use it everywhere.
1377	 */
1378	freq = timer_freq;
1379	error = sysctl_handle_opaque(oidp, &freq, sizeof freq, req);
1380	if (error == 0 && req->newptr != NULL) {
1381		if (timer0_state != RELEASED)
1382			return (EBUSY);	/* too much trouble to handle */
1383		set_timer_freq(freq, hz);
1384		i8254_timecounter[0].frequency = freq;
1385	}
1386	return (error);
1387}
1388
1389SYSCTL_PROC(_machdep, OID_AUTO, i8254_freq, CTLTYPE_INT | CTLFLAG_RW,
1390	    0, sizeof(u_int), sysctl_machdep_i8254_freq, "I", "");
1391
1392static int
1393sysctl_machdep_tsc_freq SYSCTL_HANDLER_ARGS
1394{
1395	int error;
1396	u_int freq;
1397
1398	if (!tsc_present)
1399		return (EOPNOTSUPP);
1400	freq = tsc_freq;
1401	error = sysctl_handle_opaque(oidp, &freq, sizeof freq, req);
1402	if (error == 0 && req->newptr != NULL) {
1403		tsc_freq = freq;
1404		tsc_timecounter[0].frequency = tsc_freq;
1405	}
1406	return (error);
1407}
1408
1409SYSCTL_PROC(_machdep, OID_AUTO, tsc_freq, CTLTYPE_INT | CTLFLAG_RW,
1410	    0, sizeof(u_int), sysctl_machdep_tsc_freq, "I", "");
1411
1412static unsigned
1413i8254_get_timecount(struct timecounter *tc)
1414{
1415	u_int count;
1416	u_long ef;
1417	u_int high, low;
1418
1419	ef = read_eflags();
1420	disable_intr();
1421
1422	/* Select timer0 and latch counter value. */
1423	outb(TIMER_MODE, TIMER_SEL0 | TIMER_LATCH);
1424
1425	low = inb(TIMER_CNTR0);
1426	high = inb(TIMER_CNTR0);
1427
1428	count = hardclock_max_count - ((high << 8) | low);
1429	if (count < i8254_lastcount) {
1430		i8254_ticked = 1;
1431		i8254_offset += hardclock_max_count;
1432	}
1433
1434	i8254_lastcount = count;
1435	count += i8254_offset;
1436	CLOCK_UNLOCK();
1437	write_eflags(ef);
1438	return (count);
1439}
1440
1441static unsigned
1442tsc_get_timecount(struct timecounter *tc)
1443{
1444	return (rdtsc());
1445}
1446