pcrtc.c revision 72792
119304Speter/*-
219304Speter * Copyright (c) 1990 The Regents of the University of California.
319304Speter * All rights reserved.
419304Speter *
519304Speter * This code is derived from software contributed to Berkeley by
619304Speter * William Jolitz and Don Ahn.
719304Speter *
819304Speter * Redistribution and use in source and binary forms, with or without
919304Speter * modification, are permitted provided that the following conditions
1019304Speter * are met:
1119304Speter * 1. Redistributions of source code must retain the above copyright
1219304Speter *    notice, this list of conditions and the following disclaimer.
13254225Speter * 2. Redistributions in binary form must reproduce the above copyright
1419304Speter *    notice, this list of conditions and the following disclaimer in the
1519304Speter *    documentation and/or other materials provided with the distribution.
1619304Speter * 3. All advertising materials mentioning features or use of this software
1719304Speter *    must display the following acknowledgement:
1819304Speter *	This product includes software developed by the University of
1919304Speter *	California, Berkeley and its contributors.
2019304Speter * 4. Neither the name of the University nor the names of its contributors
2119304Speter *    may be used to endorse or promote products derived from this software
2219304Speter *    without specific prior written permission.
2319304Speter *
2419304Speter * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
2519304Speter * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2619304Speter * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2719304Speter * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
2819304Speter * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2919304Speter * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
3019304Speter * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
3119304Speter * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
3219304Speter * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
3319304Speter * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3419304Speter * SUCH DAMAGE.
35254225Speter *
3619304Speter *	from: @(#)clock.c	7.2 (Berkeley) 5/12/91
3719304Speter * $FreeBSD: head/sys/pc98/cbus/pcrtc.c 72792 2001-02-21 10:22:22Z kato $
38254225Speter */
39254225Speter
40254225Speter/*
41254225Speter * Routines to handle clock hardware.
42254225Speter */
43254225Speter
4419304Speter/*
4519304Speter * inittodr, settodr and support routines written
4619304Speter * by Christoph Robitschko <chmr@edvz.tu-graz.ac.at>
4719304Speter *
4819304Speter * reintroduced and updated by Chris Stenton <chris@gnome.co.uk> 8/10/94
4919304Speter */
5019304Speter
5119304Speter/*
5219304Speter * modified for PC98 by Kakefuda
5319304Speter */
5419304Speter
5519304Speter#include "opt_clock.h"
5619304Speter#include "opt_apm.h"
5719304Speter#include "opt_mca.h"
5819304Speter
5919304Speter#include <sys/param.h>
6019304Speter#include <sys/systm.h>
6119304Speter#include <sys/bus.h>
6219304Speter#include <sys/ipl.h>
63254225Speter#include <sys/mutex.h>
6419304Speter#include <sys/proc.h>
6519304Speter#include <sys/time.h>
6619304Speter#include <sys/timetc.h>
6719304Speter#include <sys/kernel.h>
6819304Speter#ifndef SMP
6919304Speter#include <sys/lock.h>
7019304Speter#endif
7119304Speter#include <sys/sysctl.h>
7219304Speter#include <sys/cons.h>
7319304Speter
7419304Speter#include <machine/clock.h>
7519304Speter#ifdef CLK_CALIBRATION_LOOP
7619304Speter#endif
7719304Speter#include <machine/cputypes.h>
7819304Speter#include <machine/frame.h>
79254225Speter#include <machine/limits.h>
8019304Speter#include <machine/md_var.h>
8119304Speter#include <machine/psl.h>
82254225Speter#ifdef APIC_IO
83254225Speter#include <machine/segments.h>
84254225Speter#endif
85254225Speter#if defined(SMP) || defined(APIC_IO)
86254225Speter#include <machine/smp.h>
87254225Speter#endif /* SMP || APIC_IO */
8819304Speter#include <machine/specialreg.h>
8919304Speter
9019304Speter#include <i386/isa/icu.h>
9119304Speter#ifdef PC98
9219304Speter#include <pc98/pc98/pc98.h>
93254225Speter#include <pc98/pc98/pc98_machdep.h>
94254225Speter#include <i386/isa/isa_device.h>
95254225Speter#else
9619304Speter#include <i386/isa/isa.h>
9719304Speter#include <isa/rtc.h>
9819304Speter#endif
9919304Speter#include <isa/isavar.h>
10019304Speter#include <i386/isa/timerreg.h>
10119304Speter
10219304Speter#include <i386/isa/intr_machdep.h>
10319304Speter
10419304Speter#ifdef DEV_MCA
10519304Speter#include <i386/isa/mca_machdep.h>
10619304Speter#endif
10719304Speter
10819304Speter#ifdef APIC_IO
10919304Speter#include <i386/isa/intr_machdep.h>
11019304Speter/* The interrupt triggered by the 8254 (timer) chip */
11119304Speterint apic_8254_intr;
11219304Speterstatic u_long read_intr_count __P((int vec));
11319304Speterstatic void setup_8254_mixed_mode __P((void));
11419304Speter#endif
11519304Speter
11619304Speter/*
11719304Speter * 32-bit time_t's can't reach leap years before 1904 or after 2036, so we
11819304Speter * can use a simple formula for leap years.
119254225Speter */
120254225Speter#define	LEAPYEAR(y) ((u_int)(y) % 4 == 0)
12119304Speter#define DAYSPERYEAR   (31+28+31+30+31+30+31+31+30+31+30+31)
12219304Speter
12319304Speter#define	TIMER_DIV(x) ((timer_freq + (x) / 2) / (x))
12419304Speter
125254225Speter/*
126254225Speter * Time in timer cycles that it takes for microtime() to disable interrupts
12719304Speter * and latch the count.  microtime() currently uses "cli; outb ..." so it
12819304Speter * normally takes less than 2 timer cycles.  Add a few for cache misses.
12919304Speter * Add a few more to allow for latency in bogus calls to microtime() with
13019304Speter * interrupts already disabled.
13119304Speter */
13219304Speter#define	TIMER0_LATCH_COUNT	20
13319304Speter
13419304Speter/*
13519304Speter * Maximum frequency that we are willing to allow for timer0.  Must be
13619304Speter * low enough to guarantee that the timer interrupt handler returns
13719304Speter * before the next timer interrupt.
13819304Speter */
13919304Speter#define	TIMER0_MAX_FREQ		20000
14019304Speter
14119304Speterint	adjkerntz;		/* local offset from GMT in seconds */
14219304Speterint	clkintr_pending;
14319304Speterint	disable_rtc_set;	/* disable resettodr() if != 0 */
14419304Speterint	statclock_disable;
14519304Speter#ifndef TIMER_FREQ
14619304Speter#ifdef PC98
14719304Speter#define	TIMER_FREQ	2457600;
14819304Speter#else /* IBM-PC */
14919304Speter#define	TIMER_FREQ	1193182;
15019304Speter#endif /* PC98 */
15119304Speter#endif
15219304Speteru_int	timer_freq = TIMER_FREQ;
15319304Speterint	timer0_max_count;
15419304Speteru_int	tsc_freq;
155254225Speterint	tsc_is_broken;
156254225Speteru_int	tsc_present;
15719304Speterint	wall_cmos_clock;	/* wall CMOS clock assumed if != 0 */
15819304Speterstruct mtx clock_lock;
15919304Speter
16019304Speterstatic	int	beeping = 0;
161254225Speterstatic	const u_char daysinmonth[] = {31,28,31,30,31,30,31,31,30,31,30,31};
16219304Speterstatic	u_int	hardclock_max_count;
16319304Speterstatic	u_int32_t i8254_lastcount;
16419304Speterstatic	u_int32_t i8254_offset;
16519304Speterstatic	int	i8254_ticked;
166254225Speter/*
16719304Speter * XXX new_function and timer_func should not handle clockframes, but
16819304Speter * timer_func currently needs to hold hardclock to handle the
16919304Speter * timer0_state == 0 case.  We should use inthand_add()/inthand_remove()
17019304Speter * to switch between clkintr() and a slightly different timerintr().
17119304Speter */
172254225Speterstatic	void	(*new_function) __P((struct clockframe *frame));
173254225Speterstatic	u_int	new_rate;
174254225Speter#ifndef PC98
175254225Speterstatic	u_char	rtc_statusa = RTCSA_DIVIDER | RTCSA_NOPROF;
176254225Speterstatic	u_char	rtc_statusb = RTCSB_24HR | RTCSB_PINTR;
17719304Speter#endif
17819304Speterstatic	u_int	timer0_prescaler_count;
179254225Speter
180254225Speter/* Values for timerX_state: */
181254225Speter#define	RELEASED	0
182254225Speter#define	RELEASE_PENDING	1
183254225Speter#define	ACQUIRED	2
184254225Speter#define	ACQUIRE_PENDING	3
185254225Speter
186254225Speterstatic	u_char	timer0_state;
18719304Speter#ifdef	PC98
188254225Speterstatic 	u_char	timer1_state;
189254225Speter#endif
190254225Speterstatic	u_char	timer2_state;
191254225Speterstatic	void	(*timer_func) __P((struct clockframe *frame)) = hardclock;
192254225Speter#ifdef PC98
19319304Speterstatic void rtc_serialcombit __P((int));
194254225Speterstatic void rtc_serialcom __P((int));
19519304Speterstatic int rtc_inb __P((void));
19619304Speterstatic void rtc_outb __P((int));
19719304Speter#endif
19819304Speter
19919304Speterstatic	unsigned i8254_get_timecount __P((struct timecounter *tc));
200254225Speterstatic	unsigned tsc_get_timecount __P((struct timecounter *tc));
20119304Speterstatic	void	set_timer_freq(u_int freq, int intr_freq);
20219304Speter
20319304Speterstatic struct timecounter tsc_timecounter = {
20419304Speter	tsc_get_timecount,	/* get_timecount */
20519304Speter	0,			/* no poll_pps */
20619304Speter 	~0u,			/* counter_mask */
20719304Speter	0,			/* frequency */
20819304Speter	 "TSC"			/* name */
20919304Speter};
21019304Speter
21119304SpeterSYSCTL_OPAQUE(_debug, OID_AUTO, tsc_timecounter, CTLFLAG_RD,
21219304Speter	&tsc_timecounter, sizeof(tsc_timecounter), "S,timecounter", "");
213254225Speter
214254225Speterstatic struct timecounter i8254_timecounter = {
215254225Speter	i8254_get_timecount,	/* get_timecount */
21619304Speter	0,			/* no poll_pps */
21719304Speter	~0u,			/* counter_mask */
21819304Speter	0,			/* frequency */
21919304Speter	"i8254"			/* name */
22019304Speter};
22119304Speter
22219304SpeterSYSCTL_OPAQUE(_debug, OID_AUTO, i8254_timecounter, CTLFLAG_RD,
22319304Speter	&i8254_timecounter, sizeof(i8254_timecounter), "S,timecounter", "");
22419304Speter
22519304Speterstatic void
22619304Speterclkintr(struct clockframe frame)
22719304Speter{
22819304Speter
22919304Speter	if (timecounter->tc_get_timecount == i8254_get_timecount) {
23019304Speter		mtx_lock_spin(&clock_lock);
23119304Speter		if (i8254_ticked)
23219304Speter			i8254_ticked = 0;
23319304Speter		else {
23419304Speter			i8254_offset += timer0_max_count;
23519304Speter			i8254_lastcount = 0;
23619304Speter		}
23719304Speter		clkintr_pending = 0;
23819304Speter		mtx_unlock_spin(&clock_lock);
23919304Speter	}
24019304Speter	timer_func(&frame);
24119304Speter	switch (timer0_state) {
24219304Speter
24319304Speter	case RELEASED:
24419304Speter		break;
24519304Speter
24619304Speter	case ACQUIRED:
24719304Speter		if ((timer0_prescaler_count += timer0_max_count)
24819304Speter		    >= hardclock_max_count) {
24919304Speter			timer0_prescaler_count -= hardclock_max_count;
25019304Speter			hardclock(&frame);
25119304Speter		}
25219304Speter		break;
25319304Speter
25419304Speter	case ACQUIRE_PENDING:
25519304Speter		mtx_lock_spin(&clock_lock);
25619304Speter		i8254_offset = i8254_get_timecount(NULL);
25719304Speter		i8254_lastcount = 0;
25819304Speter		timer0_max_count = TIMER_DIV(new_rate);
25919304Speter		outb(TIMER_MODE, TIMER_SEL0 | TIMER_RATEGEN | TIMER_16BIT);
26019304Speter		outb(TIMER_CNTR0, timer0_max_count & 0xff);
26119304Speter		outb(TIMER_CNTR0, timer0_max_count >> 8);
26219304Speter		mtx_unlock_spin(&clock_lock);
26319304Speter		timer_func = new_function;
26419304Speter		timer0_state = ACQUIRED;
26519304Speter		break;
26619304Speter
26719304Speter	case RELEASE_PENDING:
268254225Speter		if ((timer0_prescaler_count += timer0_max_count)
26919304Speter		    >= hardclock_max_count) {
27019304Speter			mtx_lock_spin(&clock_lock);
271254225Speter			i8254_offset = i8254_get_timecount(NULL);
272254225Speter			i8254_lastcount = 0;
273254225Speter			timer0_max_count = hardclock_max_count;
274254225Speter			outb(TIMER_MODE,
275254225Speter			     TIMER_SEL0 | TIMER_RATEGEN | TIMER_16BIT);
276254225Speter			outb(TIMER_CNTR0, timer0_max_count & 0xff);
27719304Speter			outb(TIMER_CNTR0, timer0_max_count >> 8);
27819304Speter			mtx_unlock_spin(&clock_lock);
27919304Speter			timer0_prescaler_count = 0;
280254225Speter			timer_func = hardclock;
281254225Speter			timer0_state = RELEASED;
28219304Speter			hardclock(&frame);
28319304Speter		}
28419304Speter		break;
28519304Speter	}
28619304Speter#ifdef DEV_MCA
28719304Speter	/* Reset clock interrupt by asserting bit 7 of port 0x61 */
28819304Speter	if (MCA_system)
28919304Speter		outb(0x61, inb(0x61) | 0x80);
29019304Speter#endif
29119304Speter}
29219304Speter
293254225Speter/*
294254225Speter * The acquire and release functions must be called at ipl >= splclock().
29519304Speter */
29619304Speterint
29719304Speteracquire_timer0(int rate, void (*function) __P((struct clockframe *frame)))
298254225Speter{
299254225Speter	static int old_rate;
30019304Speter
30119304Speter	if (rate <= 0 || rate > TIMER0_MAX_FREQ)
30219304Speter		return (-1);
30319304Speter	switch (timer0_state) {
30419304Speter
30519304Speter	case RELEASED:
30619304Speter		timer0_state = ACQUIRE_PENDING;
30719304Speter		break;
30819304Speter
30919304Speter	case RELEASE_PENDING:
31019304Speter		if (rate != old_rate)
31119304Speter			return (-1);
31219304Speter		/*
31319304Speter		 * The timer has been released recently, but is being
31419304Speter		 * re-acquired before the release completed.  In this
31519304Speter		 * case, we simply reclaim it as if it had not been
31619304Speter		 * released at all.
31719304Speter		 */
31819304Speter		timer0_state = ACQUIRED;
31919304Speter		break;
32019304Speter
32119304Speter	default:
32219304Speter		return (-1);	/* busy */
32319304Speter	}
32419304Speter	new_function = function;
32519304Speter	old_rate = new_rate = rate;
32619304Speter	return (0);
32719304Speter}
32819304Speter
32919304Speter#ifdef PC98
33019304Speterint
33119304Speteracquire_timer1(int mode)
33219304Speter{
33319304Speter
33419304Speter	if (timer1_state != RELEASED)
33519304Speter		return (-1);
33619304Speter	timer1_state = ACQUIRED;
33719304Speter
33819304Speter	/*
33919304Speter	 * This access to the timer registers is as atomic as possible
34019304Speter	 * because it is a single instruction.  We could do better if we
34119304Speter	 * knew the rate.  Use of splclock() limits glitches to 10-100us,
34219304Speter	 * and this is probably good enough for timer2, so we aren't as
34319304Speter	 * careful with it as with timer0.
34419304Speter	 */
34519304Speter	outb(TIMER_MODE, TIMER_SEL1 | (mode & 0x3f));
346254225Speter
34719304Speter	return (0);
34819304Speter}
349254225Speter#endif
350254225Speter
351254225Speterint
352254225Speteracquire_timer2(int mode)
353254225Speter{
35419304Speter
35519304Speter	if (timer2_state != RELEASED)
35619304Speter		return (-1);
357254225Speter	timer2_state = ACQUIRED;
358254225Speter
35919304Speter	/*
36019304Speter	 * This access to the timer registers is as atomic as possible
36119304Speter	 * because it is a single instruction.  We could do better if we
36219304Speter	 * knew the rate.  Use of splclock() limits glitches to 10-100us,
36319304Speter	 * and this is probably good enough for timer2, so we aren't as
36419304Speter	 * careful with it as with timer0.
36519304Speter	 */
36619304Speter	outb(TIMER_MODE, TIMER_SEL2 | (mode & 0x3f));
36719304Speter
36819304Speter	return (0);
36919304Speter}
37019304Speter
371254225Speterint
372254225Speterrelease_timer0()
37319304Speter{
37419304Speter	switch (timer0_state) {
37519304Speter
376254225Speter	case ACQUIRED:
377254225Speter		timer0_state = RELEASE_PENDING;
37819304Speter		break;
37919304Speter
38019304Speter	case ACQUIRE_PENDING:
38119304Speter		/* Nothing happened yet, release quickly. */
38219304Speter		timer0_state = RELEASED;
38319304Speter		break;
38419304Speter
38519304Speter	default:
38619304Speter		return (-1);
38719304Speter	}
38819304Speter	return (0);
38919304Speter}
39019304Speter
39119304Speter#ifdef PC98
39219304Speterint
39319304Speterrelease_timer1()
39419304Speter{
39519304Speter
39619304Speter	if (timer1_state != ACQUIRED)
39719304Speter		return (-1);
39819304Speter	timer1_state = RELEASED;
39919304Speter	outb(TIMER_MODE, TIMER_SEL1 | TIMER_SQWAVE | TIMER_16BIT);
40019304Speter	return (0);
40119304Speter}
40219304Speter#endif
40319304Speter
40419304Speterint
40519304Speterrelease_timer2()
40619304Speter{
40719304Speter
40819304Speter	if (timer2_state != ACQUIRED)
40919304Speter		return (-1);
41019304Speter	timer2_state = RELEASED;
41119304Speter	outb(TIMER_MODE, TIMER_SEL2 | TIMER_SQWAVE | TIMER_16BIT);
41219304Speter	return (0);
41319304Speter}
41419304Speter
415254225Speter#ifndef PC98
41619304Speter/*
41719304Speter * This routine receives statistical clock interrupts from the RTC.
418254225Speter * As explained above, these occur at 128 interrupts per second.
419254225Speter * When profiling, we receive interrupts at a rate of 1024 Hz.
420254225Speter *
421254225Speter * This does not actually add as much overhead as it sounds, because
422254225Speter * when the statistical clock is active, the hardclock driver no longer
42319304Speter * needs to keep (inaccurate) statistics on its own.  This decouples
42419304Speter * statistics gathering from scheduling interrupts.
42519304Speter *
426254225Speter * The RTC chip requires that we read status register C (RTC_INTR)
427254225Speter * to acknowledge an interrupt, before it will generate the next one.
42819304Speter * Under high interrupt load, rtcintr() can be indefinitely delayed and
42919304Speter * the clock can tick immediately after the read from RTC_INTR.  In this
43019304Speter * case, the mc146818A interrupt signal will not drop for long enough
43119304Speter * to register with the 8259 PIC.  If an interrupt is missed, the stat
43219304Speter * clock will halt, considerably degrading system performance.  This is
43319304Speter * why we use 'while' rather than a more straightforward 'if' below.
43419304Speter * Stat clock ticks can still be lost, causing minor loss of accuracy
43519304Speter * in the statistics, but the stat clock will no longer stop.
43619304Speter */
43719304Speterstatic void
43819304Speterrtcintr(struct clockframe frame)
43919304Speter{
44019304Speter	while (rtcin(RTC_INTR) & RTCIR_PERIOD)
44119304Speter		statclock(&frame);
442254225Speter}
443254225Speter
44419304Speter#include "opt_ddb.h"
44519304Speter#ifdef DDB
44619304Speter#include <ddb/ddb.h>
447254225Speter
448254225SpeterDB_SHOW_COMMAND(rtc, rtc)
44919304Speter{
45019304Speter	printf("%02x/%02x/%02x %02x:%02x:%02x, A = %02x, B = %02x, C = %02x\n",
45119304Speter	       rtcin(RTC_YEAR), rtcin(RTC_MONTH), rtcin(RTC_DAY),
45219304Speter	       rtcin(RTC_HRS), rtcin(RTC_MIN), rtcin(RTC_SEC),
45319304Speter	       rtcin(RTC_STATUSA), rtcin(RTC_STATUSB), rtcin(RTC_INTR));
45419304Speter}
45519304Speter#endif /* DDB */
45619304Speter#endif /* for PC98 */
45719304Speter
45819304Speterstatic int
45919304Spetergetit(void)
46019304Speter{
46119304Speter	int high, low;
46219304Speter
46319304Speter	mtx_lock_spin(&clock_lock);
46419304Speter
46519304Speter	/* Select timer0 and latch counter value. */
46619304Speter	outb(TIMER_MODE, TIMER_SEL0 | TIMER_LATCH);
46719304Speter
46819304Speter	low = inb(TIMER_CNTR0);
46919304Speter	high = inb(TIMER_CNTR0);
47019304Speter
47119304Speter	mtx_unlock_spin(&clock_lock);
47219304Speter	return ((high << 8) | low);
47319304Speter}
47419304Speter
47519304Speter/*
47619304Speter * Wait "n" microseconds.
47719304Speter * Relies on timer 1 counting down from (timer_freq / hz)
47819304Speter * Note: timer had better have been programmed before this is first used!
47919304Speter */
480254225Spetervoid
481254225SpeterDELAY(int n)
482254225Speter{
48319304Speter	int delta, prev_tick, tick, ticks_left;
48419304Speter
48519304Speter#ifdef DELAYDEBUG
48619304Speter	int getit_calls = 1;
48719304Speter	int n1;
48819304Speter	static int state = 0;
48919304Speter
49019304Speter	if (state == 0) {
49119304Speter		state = 1;
49219304Speter		for (n1 = 1; n1 <= 10000000; n1 *= 10)
49319304Speter			DELAY(n1);
49419304Speter		state = 2;
49519304Speter	}
49619304Speter	if (state == 1)
49719304Speter		printf("DELAY(%d)...", n);
49819304Speter#endif
49919304Speter	/*
50019304Speter	 * Guard against the timer being uninitialized if we are called
501254225Speter	 * early for console i/o.
502254225Speter	 */
50319304Speter	if (timer0_max_count == 0)
50419304Speter		set_timer_freq(timer_freq, hz);
50519304Speter
50619304Speter	/*
50719304Speter	 * Read the counter first, so that the rest of the setup overhead is
50819304Speter	 * counted.  Guess the initial overhead is 20 usec (on most systems it
50919304Speter	 * takes about 1.5 usec for each of the i/o's in getit().  The loop
51019304Speter	 * takes about 6 usec on a 486/33 and 13 usec on a 386/20.  The
51119304Speter	 * multiplications and divisions to scale the count take a while).
51219304Speter	 */
51319304Speter	prev_tick = getit();
51419304Speter	n -= 0;			/* XXX actually guess no initial overhead */
515254225Speter	/*
516254225Speter	 * Calculate (n * (timer_freq / 1e6)) without using floating point
517254225Speter	 * and without any avoidable overflows.
51819304Speter	 */
51919304Speter	if (n <= 0)
52019304Speter		ticks_left = 0;
52119304Speter	else if (n < 256)
522254225Speter		/*
523254225Speter		 * Use fixed point to avoid a slow division by 1000000.
52419304Speter		 * 39099 = 1193182 * 2^15 / 10^6 rounded to nearest.
52519304Speter		 * 2^15 is the first power of 2 that gives exact results
52619304Speter		 * for n between 0 and 256.
52719304Speter		 */
52819304Speter		ticks_left = ((u_int)n * 39099 + (1 << 15) - 1) >> 15;
52919304Speter	else
53019304Speter		/*
53119304Speter		 * Don't bother using fixed point, although gcc-2.7.2
53219304Speter		 * generates particularly poor code for the long long
53319304Speter		 * division, since even the slow way will complete long
53419304Speter		 * before the delay is up (unless we're interrupted).
53519304Speter		 */
53619304Speter		ticks_left = ((u_int)n * (long long)timer_freq + 999999)
53719304Speter			     / 1000000;
538254225Speter
539254225Speter	while (ticks_left > 0) {
54019304Speter		tick = getit();
54119304Speter#ifdef DELAYDEBUG
54219304Speter		++getit_calls;
54319304Speter#endif
54419304Speter		delta = prev_tick - tick;
54519304Speter		prev_tick = tick;
54619304Speter		if (delta < 0) {
547254225Speter			delta += timer0_max_count;
548254225Speter			/*
54919304Speter			 * Guard against timer0_max_count being wrong.
55019304Speter			 * This shouldn't happen in normal operation,
55119304Speter			 * but it may happen if set_timer_freq() is
552254225Speter			 * traced.
55319304Speter			 */
55419304Speter			if (delta < 0)
555254225Speter				delta = 0;
556254225Speter		}
55719304Speter		ticks_left -= delta;
55819304Speter	}
55919304Speter#ifdef DELAYDEBUG
56019304Speter	if (state == 1)
561254225Speter		printf(" %d calls to getit() at %d usec each\n",
562254225Speter		       getit_calls, (n + 5) / getit_calls);
563254225Speter#endif
564254225Speter}
565254225Speter
566254225Speterstatic void
567254225Spetersysbeepstop(void *chan)
568254225Speter{
569254225Speter#ifdef PC98	/* PC98 */
570254225Speter	outb(IO_PPI, inb(IO_PPI)|0x08);	/* disable counter1 output to speaker */
571254225Speter	release_timer1();
572254225Speter#else
573254225Speter	outb(IO_PPI, inb(IO_PPI)&0xFC);	/* disable counter2 output to speaker */
574254225Speter	release_timer2();
57519304Speter#endif
57619304Speter	beeping = 0;
577254225Speter}
578254225Speter
57919304Speterint
58019304Spetersysbeep(int pitch, int period)
58119304Speter{
58219304Speter	int x = splclock();
583254225Speter
584254225Speter#ifdef PC98
585254225Speter	if (acquire_timer1(TIMER_SQWAVE|TIMER_16BIT))
586254225Speter		if (!beeping) {
587254225Speter			/* Something else owns it. */
588254225Speter			splx(x);
589254225Speter			return (-1); /* XXX Should be EBUSY, but nobody cares anyway. */
590254225Speter		}
591254225Speter	disable_intr();
592254225Speter	outb(0x3fdb, pitch);
593254225Speter	outb(0x3fdb, (pitch>>8));
594254225Speter	enable_intr();
595254225Speter	if (!beeping) {
596254225Speter		/* enable counter1 output to speaker */
597254225Speter		outb(IO_PPI, (inb(IO_PPI) & 0xf7));
598254225Speter		beeping = period;
599254225Speter		timeout(sysbeepstop, (void *)NULL, period);
600254225Speter	}
601254225Speter#else
602254225Speter	if (acquire_timer2(TIMER_SQWAVE|TIMER_16BIT))
603254225Speter		if (!beeping) {
604254225Speter			/* Something else owns it. */
605254225Speter			splx(x);
606254225Speter			return (-1); /* XXX Should be EBUSY, but nobody cares anyway. */
607254225Speter		}
608254225Speter	mtx_lock_spin(&clock_lock);
609254225Speter	outb(TIMER_CNTR2, pitch);
610254225Speter	outb(TIMER_CNTR2, (pitch>>8));
611254225Speter	mtx_unlock_spin(&clock_lock);
612254225Speter	if (!beeping) {
613254225Speter		/* enable counter2 output to speaker */
614254225Speter		outb(IO_PPI, inb(IO_PPI) | 3);
615254225Speter		beeping = period;
616254225Speter		timeout(sysbeepstop, (void *)NULL, period);
617254225Speter	}
618254225Speter#endif
619254225Speter	splx(x);
620254225Speter	return (0);
621254225Speter}
622254225Speter
623254225Speter#ifndef PC98
624254225Speter/*
625254225Speter * RTC support routines
626254225Speter */
627254225Speter
628254225Speterint
629254225Speterrtcin(reg)
630254225Speter	int reg;
631254225Speter{
632254225Speter	int s;
633254225Speter	u_char val;
634254225Speter
635254225Speter	s = splhigh();
636254225Speter	outb(IO_RTC, reg);
637254225Speter	inb(0x84);
638254225Speter	val = inb(IO_RTC + 1);
639254225Speter	inb(0x84);
640254225Speter	splx(s);
641254225Speter	return (val);
642254225Speter}
643254225Speter
644254225Speterstatic __inline void
645254225Speterwritertc(u_char reg, u_char val)
646254225Speter{
647254225Speter	int s;
648254225Speter
64919304Speter	s = splhigh();
65019304Speter	inb(0x84);
65119304Speter	outb(IO_RTC, reg);
65219304Speter	inb(0x84);
65319304Speter	outb(IO_RTC + 1, val);
65419304Speter	inb(0x84);		/* XXX work around wrong order in rtcin() */
655254225Speter	splx(s);
656254225Speter}
657254225Speter
65819304Speterstatic __inline int
65919304Speterreadrtc(int port)
66019304Speter{
66119304Speter	return(bcd2bin(rtcin(port)));
66219304Speter}
66319304Speter#endif
66419304Speter
66519304Speter#ifdef PC98
66619304Speterunsigned int delaycount;
66719304Speter#define FIRST_GUESS	0x2000
66819304Speterstatic void findcpuspeed(void)
669254225Speter{
670254225Speter	int i;
671254225Speter	int remainder;
672254225Speter
673254225Speter	/* Put counter in count down mode */
67419304Speter	outb(TIMER_MODE, TIMER_SEL0 | TIMER_16BIT | TIMER_RATEGEN);
67519304Speter	outb(TIMER_CNTR0, 0xff);
67619304Speter	outb(TIMER_CNTR0, 0xff);
67719304Speter	for (i = FIRST_GUESS; i; i--)
67819304Speter		;
67919304Speter	remainder = getit();
68019304Speter	delaycount = (FIRST_GUESS * TIMER_DIV(1000)) / (0xffff - remainder);
68119304Speter}
68219304Speter#endif
683254225Speter
68419304Speter#ifdef PC98
68519304Speterstatic u_int
68619304Spetercalibrate_clocks(void)
68719304Speter{
68819304Speter	int	timeout;
689	u_int	count, prev_count, tot_count;
690	u_short	sec, start_sec;
691
692	if (bootverbose)
693	        printf("Calibrating clock(s) ... ");
694	/* Check ARTIC. */
695	if (!(PC98_SYSTEM_PARAMETER(0x458) & 0x80) &&
696	    !(PC98_SYSTEM_PARAMETER(0x45b) & 0x04))
697		goto fail;
698	timeout = 100000000;
699
700	/* Read the ARTIC. */
701	sec = inw(0x5e);
702
703	/* Wait for the ARTIC to changes. */
704	start_sec = sec;
705	for (;;) {
706		sec = inw(0x5e);
707		if (sec != start_sec)
708			break;
709		if (--timeout == 0)
710			goto fail;
711	}
712	prev_count = getit();
713	if (prev_count == 0 || prev_count > timer0_max_count)
714		goto fail;
715	tot_count = 0;
716
717	if (tsc_present)
718		wrmsr(0x10, 0LL);	/* XXX 0x10 is the MSR for the TSC */
719	start_sec = sec;
720	for (;;) {
721		sec = inw(0x5e);
722		count = getit();
723		if (count == 0 || count > timer0_max_count)
724			goto fail;
725		if (count > prev_count)
726			tot_count += prev_count - (count - timer0_max_count);
727		else
728			tot_count += prev_count - count;
729		prev_count = count;
730		if ((sec == start_sec + 1200) ||
731		    (sec < start_sec &&
732		        (u_int)sec + 0x10000 == (u_int)start_sec + 1200))
733			break;
734		if (--timeout == 0)
735			goto fail;
736	}
737	/*
738	 * Read the cpu cycle counter.  The timing considerations are
739	 * similar to those for the i8254 clock.
740	 */
741	if (tsc_present)
742		tsc_freq = rdtsc();
743
744	if (bootverbose) {
745		if (tsc_present)
746		        printf("TSC clock: %u Hz, ", tsc_freq);
747	        printf("i8254 clock: %u Hz\n", tot_count);
748	}
749	return (tot_count);
750
751fail:
752	if (bootverbose)
753	        printf("failed, using default i8254 clock of %u Hz\n",
754		       timer_freq);
755	return (timer_freq);
756}
757#else
758static u_int
759calibrate_clocks(void)
760{
761	u_int64_t old_tsc;
762	u_int count, prev_count, tot_count;
763	int sec, start_sec, timeout;
764
765	if (bootverbose)
766	        printf("Calibrating clock(s) ... ");
767	if (!(rtcin(RTC_STATUSD) & RTCSD_PWR))
768		goto fail;
769	timeout = 100000000;
770
771	/* Read the mc146818A seconds counter. */
772	for (;;) {
773		if (!(rtcin(RTC_STATUSA) & RTCSA_TUP)) {
774			sec = rtcin(RTC_SEC);
775			break;
776		}
777		if (--timeout == 0)
778			goto fail;
779	}
780
781	/* Wait for the mC146818A seconds counter to change. */
782	start_sec = sec;
783	for (;;) {
784		if (!(rtcin(RTC_STATUSA) & RTCSA_TUP)) {
785			sec = rtcin(RTC_SEC);
786			if (sec != start_sec)
787				break;
788		}
789		if (--timeout == 0)
790			goto fail;
791	}
792
793	/* Start keeping track of the i8254 counter. */
794	prev_count = getit();
795	if (prev_count == 0 || prev_count > timer0_max_count)
796		goto fail;
797	tot_count = 0;
798
799	if (tsc_present)
800		old_tsc = rdtsc();
801	else
802		old_tsc = 0;		/* shut up gcc */
803
804	/*
805	 * Wait for the mc146818A seconds counter to change.  Read the i8254
806	 * counter for each iteration since this is convenient and only
807	 * costs a few usec of inaccuracy. The timing of the final reads
808	 * of the counters almost matches the timing of the initial reads,
809	 * so the main cause of inaccuracy is the varying latency from
810	 * inside getit() or rtcin(RTC_STATUSA) to the beginning of the
811	 * rtcin(RTC_SEC) that returns a changed seconds count.  The
812	 * maximum inaccuracy from this cause is < 10 usec on 486's.
813	 */
814	start_sec = sec;
815	for (;;) {
816		if (!(rtcin(RTC_STATUSA) & RTCSA_TUP))
817			sec = rtcin(RTC_SEC);
818		count = getit();
819		if (count == 0 || count > timer0_max_count)
820			goto fail;
821		if (count > prev_count)
822			tot_count += prev_count - (count - timer0_max_count);
823		else
824			tot_count += prev_count - count;
825		prev_count = count;
826		if (sec != start_sec)
827			break;
828		if (--timeout == 0)
829			goto fail;
830	}
831
832	/*
833	 * Read the cpu cycle counter.  The timing considerations are
834	 * similar to those for the i8254 clock.
835	 */
836	if (tsc_present)
837		tsc_freq = rdtsc() - old_tsc;
838
839	if (bootverbose) {
840		if (tsc_present)
841		        printf("TSC clock: %u Hz, ", tsc_freq);
842	        printf("i8254 clock: %u Hz\n", tot_count);
843	}
844	return (tot_count);
845
846fail:
847	if (bootverbose)
848	        printf("failed, using default i8254 clock of %u Hz\n",
849		       timer_freq);
850	return (timer_freq);
851}
852#endif	/* !PC98 */
853
854static void
855set_timer_freq(u_int freq, int intr_freq)
856{
857	int new_timer0_max_count;
858
859	mtx_lock_spin(&clock_lock);
860	timer_freq = freq;
861	new_timer0_max_count = hardclock_max_count = TIMER_DIV(intr_freq);
862	if (new_timer0_max_count != timer0_max_count) {
863		timer0_max_count = new_timer0_max_count;
864		outb(TIMER_MODE, TIMER_SEL0 | TIMER_RATEGEN | TIMER_16BIT);
865		outb(TIMER_CNTR0, timer0_max_count & 0xff);
866		outb(TIMER_CNTR0, timer0_max_count >> 8);
867	}
868	mtx_unlock_spin(&clock_lock);
869}
870
871/*
872 * i8254_restore is called from apm_default_resume() to reload
873 * the countdown register.
874 * this should not be necessary but there are broken laptops that
875 * do not restore the countdown register on resume.
876 * when it happnes, it messes up the hardclock interval and system clock,
877 * which leads to the infamous "calcru: negative time" problem.
878 */
879void
880i8254_restore(void)
881{
882
883	mtx_lock_spin(&clock_lock);
884	outb(TIMER_MODE, TIMER_SEL0 | TIMER_RATEGEN | TIMER_16BIT);
885	outb(TIMER_CNTR0, timer0_max_count & 0xff);
886	outb(TIMER_CNTR0, timer0_max_count >> 8);
887	mtx_unlock_spin(&clock_lock);
888}
889
890/*
891 * Initialize 8254 timer 0 early so that it can be used in DELAY().
892 * XXX initialization of other timers is unintentionally left blank.
893 */
894void
895startrtclock()
896{
897	u_int delta, freq;
898
899#ifdef PC98
900	findcpuspeed();
901	if (pc98_machine_type & M_8M)
902		timer_freq = 1996800L; /* 1.9968 MHz */
903	else
904		timer_freq = 2457600L; /* 2.4576 MHz */
905#endif /* PC98 */
906
907	if (cpu_feature & CPUID_TSC)
908		tsc_present = 1;
909	else
910		tsc_present = 0;
911
912#ifndef PC98
913	writertc(RTC_STATUSA, rtc_statusa);
914	writertc(RTC_STATUSB, RTCSB_24HR);
915#endif
916
917	set_timer_freq(timer_freq, hz);
918	freq = calibrate_clocks();
919#ifdef CLK_CALIBRATION_LOOP
920	if (bootverbose) {
921		printf(
922		"Press a key on the console to abort clock calibration\n");
923		while (cncheckc() == -1)
924			calibrate_clocks();
925	}
926#endif
927
928	/*
929	 * Use the calibrated i8254 frequency if it seems reasonable.
930	 * Otherwise use the default, and don't use the calibrated i586
931	 * frequency.
932	 */
933	delta = freq > timer_freq ? freq - timer_freq : timer_freq - freq;
934	if (delta < timer_freq / 100) {
935#ifndef CLK_USE_I8254_CALIBRATION
936		if (bootverbose)
937			printf(
938"CLK_USE_I8254_CALIBRATION not specified - using default frequency\n");
939		freq = timer_freq;
940#endif
941		timer_freq = freq;
942	} else {
943		if (bootverbose)
944			printf(
945		    "%d Hz differs from default of %d Hz by more than 1%%\n",
946			       freq, timer_freq);
947		tsc_freq = 0;
948	}
949
950	set_timer_freq(timer_freq, hz);
951	i8254_timecounter.tc_frequency = timer_freq;
952	tc_init(&i8254_timecounter);
953
954#ifndef CLK_USE_TSC_CALIBRATION
955	if (tsc_freq != 0) {
956		if (bootverbose)
957			printf(
958"CLK_USE_TSC_CALIBRATION not specified - using old calibration method\n");
959		tsc_freq = 0;
960	}
961#endif
962	if (tsc_present && tsc_freq == 0) {
963		/*
964		 * Calibration of the i586 clock relative to the mc146818A
965		 * clock failed.  Do a less accurate calibration relative
966		 * to the i8254 clock.
967		 */
968		u_int64_t old_tsc = rdtsc();
969
970		DELAY(1000000);
971		tsc_freq = rdtsc() - old_tsc;
972#ifdef CLK_USE_TSC_CALIBRATION
973		if (bootverbose)
974			printf("TSC clock: %u Hz (Method B)\n", tsc_freq);
975#endif
976	}
977
978#if !defined(SMP)
979	/*
980	 * We can not use the TSC in SMP mode, until we figure out a
981	 * cheap (impossible), reliable and precise (yeah right!)  way
982	 * to synchronize the TSCs of all the CPUs.
983	 * Curse Intel for leaving the counter out of the I/O APIC.
984	 */
985
986#ifdef DEV_APM
987	/*
988	 * We can not use the TSC if we support APM. Precise timekeeping
989	 * on an APM'ed machine is at best a fools pursuit, since
990	 * any and all of the time spent in various SMM code can't
991	 * be reliably accounted for.  Reading the RTC is your only
992	 * source of reliable time info.  The i8254 looses too of course
993	 * but we need to have some kind of time...
994	 * We don't know at this point whether APM is going to be used
995	 * or not, nor when it might be activated.  Play it safe.
996	 */
997	{
998	int disabled = 0;
999	resource_int_value("apm", 0, "disabled", &disabled);
1000	if (disabled == 0)
1001		return;
1002	}
1003#endif /* DEV_APM */
1004
1005	if (tsc_present && tsc_freq != 0 && !tsc_is_broken) {
1006		tsc_timecounter.tc_frequency = tsc_freq;
1007		tc_init(&tsc_timecounter);
1008	}
1009
1010#endif /* !defined(SMP) */
1011}
1012
1013#ifdef PC98
1014static void
1015rtc_serialcombit(int i)
1016{
1017	outb(IO_RTC, ((i&0x01)<<5)|0x07);
1018	DELAY(1);
1019	outb(IO_RTC, ((i&0x01)<<5)|0x17);
1020	DELAY(1);
1021	outb(IO_RTC, ((i&0x01)<<5)|0x07);
1022	DELAY(1);
1023}
1024
1025static void
1026rtc_serialcom(int i)
1027{
1028	rtc_serialcombit(i&0x01);
1029	rtc_serialcombit((i&0x02)>>1);
1030	rtc_serialcombit((i&0x04)>>2);
1031	rtc_serialcombit((i&0x08)>>3);
1032	outb(IO_RTC, 0x07);
1033	DELAY(1);
1034	outb(IO_RTC, 0x0f);
1035	DELAY(1);
1036	outb(IO_RTC, 0x07);
1037 	DELAY(1);
1038}
1039
1040static void
1041rtc_outb(int val)
1042{
1043	int s;
1044	int sa = 0;
1045
1046	for (s=0;s<8;s++) {
1047	    sa = ((val >> s) & 0x01) ? 0x27 : 0x07;
1048	    outb(IO_RTC, sa);		/* set DI & CLK 0 */
1049	    DELAY(1);
1050	    outb(IO_RTC, sa | 0x10);	/* CLK 1 */
1051	    DELAY(1);
1052	}
1053	outb(IO_RTC, sa & 0xef);	/* CLK 0 */
1054}
1055
1056static int
1057rtc_inb(void)
1058{
1059	int s;
1060	int sa = 0;
1061
1062	for (s=0;s<8;s++) {
1063	    sa |= ((inb(0x33) & 0x01) << s);
1064	    outb(IO_RTC, 0x17);	/* CLK 1 */
1065	    DELAY(1);
1066	    outb(IO_RTC, 0x07);	/* CLK 0 */
1067	    DELAY(2);
1068	}
1069	return sa;
1070}
1071#endif /* PC-98 */
1072
1073/*
1074 * Initialize the time of day register, based on the time base which is, e.g.
1075 * from a filesystem.
1076 */
1077void
1078inittodr(time_t base)
1079{
1080	unsigned long	sec, days;
1081#ifndef PC98
1082	int		yd;
1083#endif
1084	int		year, month;
1085	int		y, m, s;
1086	struct timespec ts;
1087#ifdef PC98
1088	int		second, min, hour;
1089#endif
1090
1091	if (base) {
1092		s = splclock();
1093		ts.tv_sec = base;
1094		ts.tv_nsec = 0;
1095		tc_setclock(&ts);
1096		splx(s);
1097	}
1098
1099#ifdef PC98
1100	rtc_serialcom(0x03);	/* Time Read */
1101	rtc_serialcom(0x01);	/* Register shift command. */
1102	DELAY(20);
1103
1104	second = bcd2bin(rtc_inb() & 0xff);	/* sec */
1105	min = bcd2bin(rtc_inb() & 0xff);	/* min */
1106	hour = bcd2bin(rtc_inb() & 0xff);	/* hour */
1107	days = bcd2bin(rtc_inb() & 0xff) - 1;	/* date */
1108
1109	month = (rtc_inb() >> 4) & 0x0f;	/* month */
1110	for (m = 1; m <	month; m++)
1111		days +=	daysinmonth[m-1];
1112	year = bcd2bin(rtc_inb() & 0xff) + 1900;	/* year */
1113	/* 2000 year problem */
1114	if (year < 1995)
1115		year += 100;
1116	if (year < 1970)
1117		goto wrong_time;
1118	for (y = 1970; y < year; y++)
1119		days +=	DAYSPERYEAR + LEAPYEAR(y);
1120	if ((month > 2)	&& LEAPYEAR(year))
1121		days ++;
1122	sec = ((( days * 24 +
1123		  hour) * 60 +
1124		  min) * 60 +
1125		  second);
1126	/* sec now contains the	number of seconds, since Jan 1 1970,
1127	   in the local	time zone */
1128
1129	s = splhigh();
1130#else	/* IBM-PC */
1131	/* Look if we have a RTC present and the time is valid */
1132	if (!(rtcin(RTC_STATUSD) & RTCSD_PWR))
1133		goto wrong_time;
1134
1135	/* wait for time update to complete */
1136	/* If RTCSA_TUP is zero, we have at least 244us before next update */
1137	s = splhigh();
1138	while (rtcin(RTC_STATUSA) & RTCSA_TUP) {
1139		splx(s);
1140		s = splhigh();
1141	}
1142
1143	days = 0;
1144#ifdef USE_RTC_CENTURY
1145	year = readrtc(RTC_YEAR) + readrtc(RTC_CENTURY) * 100;
1146#else
1147	year = readrtc(RTC_YEAR) + 1900;
1148	if (year < 1970)
1149		year += 100;
1150#endif
1151	if (year < 1970) {
1152		splx(s);
1153		goto wrong_time;
1154	}
1155	month = readrtc(RTC_MONTH);
1156	for (m = 1; m < month; m++)
1157		days += daysinmonth[m-1];
1158	if ((month > 2) && LEAPYEAR(year))
1159		days ++;
1160	days += readrtc(RTC_DAY) - 1;
1161	yd = days;
1162	for (y = 1970; y < year; y++)
1163		days += DAYSPERYEAR + LEAPYEAR(y);
1164	sec = ((( days * 24 +
1165		  readrtc(RTC_HRS)) * 60 +
1166		  readrtc(RTC_MIN)) * 60 +
1167		  readrtc(RTC_SEC));
1168	/* sec now contains the number of seconds, since Jan 1 1970,
1169	   in the local time zone */
1170#endif
1171
1172	sec += tz.tz_minuteswest * 60 + (wall_cmos_clock ? adjkerntz : 0);
1173
1174	y = time_second - sec;
1175	if (y <= -2 || y >= 2) {
1176		/* badly off, adjust it */
1177		ts.tv_sec = sec;
1178		ts.tv_nsec = 0;
1179		tc_setclock(&ts);
1180	}
1181	splx(s);
1182	return;
1183
1184wrong_time:
1185	printf("Invalid time in real time clock.\n");
1186	printf("Check and reset the date immediately!\n");
1187}
1188
1189/*
1190 * Write system time back to RTC
1191 */
1192void
1193resettodr()
1194{
1195	unsigned long	tm;
1196	int		y, m, s;
1197#ifdef PC98
1198	int		wd;
1199#endif
1200
1201	if (disable_rtc_set)
1202		return;
1203
1204	s = splclock();
1205	tm = time_second;
1206	splx(s);
1207
1208#ifdef PC98
1209	rtc_serialcom(0x01);	/* Register shift command. */
1210
1211	/* Calculate local time	to put in RTC */
1212
1213	tm -= tz.tz_minuteswest * 60 + (wall_cmos_clock ? adjkerntz : 0);
1214
1215	rtc_outb(bin2bcd(tm%60)); tm /= 60;	/* Write back Seconds */
1216	rtc_outb(bin2bcd(tm%60)); tm /= 60;	/* Write back Minutes */
1217	rtc_outb(bin2bcd(tm%24)); tm /= 24;	/* Write back Hours   */
1218
1219	/* We have now the days	since 01-01-1970 in tm */
1220	wd = (tm+4)%7;
1221	for (y = 1970, m = DAYSPERYEAR + LEAPYEAR(y);
1222	     tm >= m;
1223	     y++,      m = DAYSPERYEAR + LEAPYEAR(y))
1224	     tm -= m;
1225
1226	/* Now we have the years in y and the day-of-the-year in tm */
1227	for (m = 0; ; m++) {
1228		int ml;
1229
1230		ml = daysinmonth[m];
1231		if (m == 1 && LEAPYEAR(y))
1232			ml++;
1233		if (tm < ml)
1234			break;
1235		tm -= ml;
1236	}
1237
1238	m++;
1239	rtc_outb(bin2bcd(tm+1));		/* Write back Day     */
1240	rtc_outb((m << 4) | wd);		/* Write back Month & Weekday  */
1241	rtc_outb(bin2bcd(y%100));		/* Write back Year    */
1242
1243	rtc_serialcom(0x02);	/* Time set & Counter hold command. */
1244	rtc_serialcom(0x00);	/* Register hold command. */
1245#else
1246	/* Disable RTC updates and interrupts. */
1247	writertc(RTC_STATUSB, RTCSB_HALT | RTCSB_24HR);
1248
1249	/* Calculate local time to put in RTC */
1250
1251	tm -= tz.tz_minuteswest * 60 + (wall_cmos_clock ? adjkerntz : 0);
1252
1253	writertc(RTC_SEC, bin2bcd(tm%60)); tm /= 60;	/* Write back Seconds */
1254	writertc(RTC_MIN, bin2bcd(tm%60)); tm /= 60;	/* Write back Minutes */
1255	writertc(RTC_HRS, bin2bcd(tm%24)); tm /= 24;	/* Write back Hours   */
1256
1257	/* We have now the days since 01-01-1970 in tm */
1258	writertc(RTC_WDAY, (tm+4)%7);			/* Write back Weekday */
1259	for (y = 1970, m = DAYSPERYEAR + LEAPYEAR(y);
1260	     tm >= m;
1261	     y++,      m = DAYSPERYEAR + LEAPYEAR(y))
1262	     tm -= m;
1263
1264	/* Now we have the years in y and the day-of-the-year in tm */
1265	writertc(RTC_YEAR, bin2bcd(y%100));		/* Write back Year    */
1266#ifdef USE_RTC_CENTURY
1267	writertc(RTC_CENTURY, bin2bcd(y/100));		/* ... and Century    */
1268#endif
1269	for (m = 0; ; m++) {
1270		int ml;
1271
1272		ml = daysinmonth[m];
1273		if (m == 1 && LEAPYEAR(y))
1274			ml++;
1275		if (tm < ml)
1276			break;
1277		tm -= ml;
1278	}
1279
1280	writertc(RTC_MONTH, bin2bcd(m + 1));            /* Write back Month   */
1281	writertc(RTC_DAY, bin2bcd(tm + 1));             /* Write back Month Day */
1282
1283	/* Reenable RTC updates and interrupts. */
1284	writertc(RTC_STATUSB, rtc_statusb);
1285#endif /* PC98 */
1286}
1287
1288
1289/*
1290 * Start both clocks running.
1291 */
1292void
1293cpu_initclocks()
1294{
1295#ifdef APIC_IO
1296	int apic_8254_trial;
1297	void *clkdesc;
1298#endif /* APIC_IO */
1299#ifndef PC98
1300	int diag;
1301
1302	if (statclock_disable) {
1303		/*
1304		 * The stat interrupt mask is different without the
1305		 * statistics clock.  Also, don't set the interrupt
1306		 * flag which would normally cause the RTC to generate
1307		 * interrupts.
1308		 */
1309		rtc_statusb = RTCSB_24HR;
1310	} else {
1311	        /* Setting stathz to nonzero early helps avoid races. */
1312		stathz = RTC_NOPROFRATE;
1313		profhz = RTC_PROFRATE;
1314        }
1315#endif
1316
1317	/* Finish initializing 8253 timer 0. */
1318#ifdef APIC_IO
1319
1320	apic_8254_intr = isa_apic_irq(0);
1321	apic_8254_trial = 0;
1322	if (apic_8254_intr >= 0 ) {
1323		if (apic_int_type(0, 0) == 3)
1324			apic_8254_trial = 1;
1325	} else {
1326		/* look for ExtInt on pin 0 */
1327		if (apic_int_type(0, 0) == 3) {
1328			apic_8254_intr = apic_irq(0, 0);
1329			setup_8254_mixed_mode();
1330		} else
1331			panic("APIC_IO: Cannot route 8254 interrupt to CPU");
1332	}
1333
1334	inthand_add("clk", apic_8254_intr, (driver_intr_t *)clkintr, NULL,
1335	    INTR_TYPE_CLK | INTR_FAST, &clkdesc);
1336	INTREN(1 << apic_8254_intr);
1337
1338#else /* APIC_IO */
1339
1340	/*
1341	 * XXX Check the priority of this interrupt handler.  I
1342	 * couldn't find anything suitable in the BSD/OS code (grog,
1343	 * 19 July 2000).
1344	 */
1345	inthand_add("clk", 0, (driver_intr_t *)clkintr, NULL,
1346	    INTR_TYPE_CLK | INTR_FAST, NULL);
1347	INTREN(IRQ0);
1348
1349#endif /* APIC_IO */
1350
1351#ifndef PC98
1352	/* Initialize RTC. */
1353	writertc(RTC_STATUSA, rtc_statusa);
1354	writertc(RTC_STATUSB, RTCSB_24HR);
1355
1356	/* Don't bother enabling the statistics clock. */
1357	if (statclock_disable)
1358		return;
1359	diag = rtcin(RTC_DIAG);
1360	if (diag != 0)
1361		printf("RTC BIOS diagnostic error %b\n", diag, RTCDG_BITS);
1362#endif /* !PC98 */
1363
1364#ifndef PC98
1365#ifdef APIC_IO
1366	if (isa_apic_irq(8) != 8)
1367		panic("APIC RTC != 8");
1368#endif /* APIC_IO */
1369
1370	inthand_add("rtc", 8, (driver_intr_t *)rtcintr, NULL,
1371	    INTR_TYPE_CLK | INTR_FAST, NULL);
1372
1373#ifdef APIC_IO
1374	INTREN(APIC_IRQ8);
1375#else
1376	INTREN(IRQ8);
1377#endif /* APIC_IO */
1378
1379	writertc(RTC_STATUSB, rtc_statusb);
1380#endif /* PC98 */
1381
1382#ifdef APIC_IO
1383	if (apic_8254_trial) {
1384
1385		printf("APIC_IO: Testing 8254 interrupt delivery\n");
1386		while (read_intr_count(8) < 6)
1387			;	/* nothing */
1388		if (read_intr_count(apic_8254_intr) < 3) {
1389			/*
1390			 * The MP table is broken.
1391			 * The 8254 was not connected to the specified pin
1392			 * on the IO APIC.
1393			 * Workaround: Limited variant of mixed mode.
1394			 */
1395			INTRDIS(1 << apic_8254_intr);
1396			inthand_remove(clkdesc);
1397			printf("APIC_IO: Broken MP table detected: "
1398			       "8254 is not connected to "
1399			       "IOAPIC #%d intpin %d\n",
1400			       int_to_apicintpin[apic_8254_intr].ioapic,
1401			       int_to_apicintpin[apic_8254_intr].int_pin);
1402			/*
1403			 * Revoke current ISA IRQ 0 assignment and
1404			 * configure a fallback interrupt routing from
1405			 * the 8254 Timer via the 8259 PIC to the
1406			 * an ExtInt interrupt line on IOAPIC #0 intpin 0.
1407			 * We reuse the low level interrupt handler number.
1408			 */
1409			if (apic_irq(0, 0) < 0) {
1410				revoke_apic_irq(apic_8254_intr);
1411				assign_apic_irq(0, 0, apic_8254_intr);
1412			}
1413			apic_8254_intr = apic_irq(0, 0);
1414			setup_8254_mixed_mode();
1415			inthand_add("clk", apic_8254_intr,
1416				    (driver_intr_t *)clkintr, NULL,
1417				    INTR_TYPE_CLK | INTR_FAST, NULL);
1418			INTREN(1 << apic_8254_intr);
1419		}
1420
1421	}
1422	if (apic_int_type(0, 0) != 3 ||
1423	    int_to_apicintpin[apic_8254_intr].ioapic != 0 ||
1424	    int_to_apicintpin[apic_8254_intr].int_pin != 0)
1425		printf("APIC_IO: routing 8254 via IOAPIC #%d intpin %d\n",
1426		       int_to_apicintpin[apic_8254_intr].ioapic,
1427		       int_to_apicintpin[apic_8254_intr].int_pin);
1428	else
1429		printf("APIC_IO: "
1430		       "routing 8254 via 8259 and IOAPIC #0 intpin 0\n");
1431#endif
1432
1433}
1434
1435#ifdef APIC_IO
1436static u_long
1437read_intr_count(int vec)
1438{
1439	u_long *up;
1440	up = intr_countp[vec];
1441	if (up)
1442		return *up;
1443	return 0UL;
1444}
1445
1446static void
1447setup_8254_mixed_mode()
1448{
1449	/*
1450	 * Allow 8254 timer to INTerrupt 8259:
1451	 *  re-initialize master 8259:
1452	 *   reset; prog 4 bytes, single ICU, edge triggered
1453	 */
1454	outb(IO_ICU1, 0x13);
1455#ifdef PC98
1456	outb(IO_ICU1 + 2, NRSVIDT);	/* start vector (unused) */
1457	outb(IO_ICU1 + 2, 0x00);	/* ignore slave */
1458	outb(IO_ICU1 + 2, 0x03);	/* auto EOI, 8086 */
1459	outb(IO_ICU1 + 2, 0xfe);	/* unmask INT0 */
1460#else
1461	outb(IO_ICU1 + 1, NRSVIDT);	/* start vector (unused) */
1462	outb(IO_ICU1 + 1, 0x00);	/* ignore slave */
1463	outb(IO_ICU1 + 1, 0x03);	/* auto EOI, 8086 */
1464	outb(IO_ICU1 + 1, 0xfe);	/* unmask INT0 */
1465#endif
1466	/* program IO APIC for type 3 INT on INT0 */
1467	if (ext_int_setup(0, 0) < 0)
1468		panic("8254 redirect via APIC pin0 impossible!");
1469}
1470#endif
1471
1472void
1473setstatclockrate(int newhz)
1474{
1475#ifndef PC98
1476	if (newhz == RTC_PROFRATE)
1477		rtc_statusa = RTCSA_DIVIDER | RTCSA_PROF;
1478	else
1479		rtc_statusa = RTCSA_DIVIDER | RTCSA_NOPROF;
1480	writertc(RTC_STATUSA, rtc_statusa);
1481#endif
1482}
1483
1484static int
1485sysctl_machdep_i8254_freq(SYSCTL_HANDLER_ARGS)
1486{
1487	int error;
1488	u_int freq;
1489
1490	/*
1491	 * Use `i8254' instead of `timer' in external names because `timer'
1492	 * is is too generic.  Should use it everywhere.
1493	 */
1494	freq = timer_freq;
1495	error = sysctl_handle_int(oidp, &freq, sizeof(freq), req);
1496	if (error == 0 && req->newptr != NULL) {
1497		if (timer0_state != RELEASED)
1498			return (EBUSY);	/* too much trouble to handle */
1499		set_timer_freq(freq, hz);
1500		i8254_timecounter.tc_frequency = freq;
1501		tc_update(&i8254_timecounter);
1502	}
1503	return (error);
1504}
1505
1506SYSCTL_PROC(_machdep, OID_AUTO, i8254_freq, CTLTYPE_INT | CTLFLAG_RW,
1507    0, sizeof(u_int), sysctl_machdep_i8254_freq, "I", "");
1508
1509static int
1510sysctl_machdep_tsc_freq(SYSCTL_HANDLER_ARGS)
1511{
1512	int error;
1513	u_int freq;
1514
1515	if (tsc_timecounter.tc_frequency == 0)
1516		return (EOPNOTSUPP);
1517	freq = tsc_freq;
1518	error = sysctl_handle_int(oidp, &freq, sizeof(freq), req);
1519	if (error == 0 && req->newptr != NULL) {
1520		tsc_freq = freq;
1521		tsc_timecounter.tc_frequency = tsc_freq;
1522		tc_update(&tsc_timecounter);
1523	}
1524	return (error);
1525}
1526
1527SYSCTL_PROC(_machdep, OID_AUTO, tsc_freq, CTLTYPE_INT | CTLFLAG_RW,
1528    0, sizeof(u_int), sysctl_machdep_tsc_freq, "I", "");
1529
1530static unsigned
1531i8254_get_timecount(struct timecounter *tc)
1532{
1533	u_int count;
1534	u_int high, low;
1535	u_int eflags;
1536
1537	eflags = read_eflags();
1538	mtx_lock_spin(&clock_lock);
1539
1540	/* Select timer0 and latch counter value. */
1541	outb(TIMER_MODE, TIMER_SEL0 | TIMER_LATCH);
1542
1543	low = inb(TIMER_CNTR0);
1544	high = inb(TIMER_CNTR0);
1545	count = timer0_max_count - ((high << 8) | low);
1546	if (count < i8254_lastcount ||
1547	    (!i8254_ticked && (clkintr_pending ||
1548	    ((count < 20 || (!(eflags & PSL_I) && count < timer0_max_count / 2u)) &&
1549#ifdef APIC_IO
1550#define	lapic_irr1	((volatile u_int *)&lapic)[0x210 / 4]	/* XXX XXX */
1551	    /* XXX this assumes that apic_8254_intr is < 24. */
1552	    (lapic_irr1 & (1 << apic_8254_intr))))
1553#else
1554	    (inb(IO_ICU1) & 1)))
1555#endif
1556	    )) {
1557		i8254_ticked = 1;
1558		i8254_offset += timer0_max_count;
1559	}
1560	i8254_lastcount = count;
1561	count += i8254_offset;
1562	mtx_unlock_spin(&clock_lock);
1563	return (count);
1564}
1565
1566static unsigned
1567tsc_get_timecount(struct timecounter *tc)
1568{
1569	return (rdtsc());
1570}
1571
1572/*
1573 * Attach to the ISA PnP descriptors for the timer and realtime clock.
1574 */
1575static struct isa_pnp_id attimer_ids[] = {
1576	{ 0x0001d041 /* PNP0100 */, "AT timer" },
1577	{ 0x000bd041 /* PNP0B00 */, "AT realtime clock" },
1578	{ 0 }
1579};
1580
1581static int
1582attimer_probe(device_t dev)
1583{
1584	int result;
1585
1586	if ((result = ISA_PNP_PROBE(device_get_parent(dev), dev, attimer_ids)) <= 0)
1587		device_quiet(dev);
1588	return(result);
1589}
1590
1591static int
1592attimer_attach(device_t dev)
1593{
1594	return(0);
1595}
1596
1597static device_method_t attimer_methods[] = {
1598	/* Device interface */
1599	DEVMETHOD(device_probe,		attimer_probe),
1600	DEVMETHOD(device_attach,	attimer_attach),
1601	DEVMETHOD(device_detach,	bus_generic_detach),
1602	DEVMETHOD(device_shutdown,	bus_generic_shutdown),
1603	DEVMETHOD(device_suspend,	bus_generic_suspend),	/* XXX stop statclock? */
1604	DEVMETHOD(device_resume,	bus_generic_resume),	/* XXX restart statclock? */
1605	{ 0, 0 }
1606};
1607
1608static driver_t attimer_driver = {
1609	"attimer",
1610	attimer_methods,
1611	1,		/* no softc */
1612};
1613
1614static devclass_t attimer_devclass;
1615
1616DRIVER_MODULE(attimer, isa, attimer_driver, attimer_devclass, 0, 0);
1617