pcrtc.c revision 153682
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 * 4. Neither the name of the University nor the names of its contributors
17 *    may be used to endorse or promote products derived from this software
18 *    without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * SUCH DAMAGE.
31 *
32 *	from: @(#)clock.c	7.2 (Berkeley) 5/12/91
33 * $FreeBSD: head/sys/pc98/cbus/pcrtc.c 153682 2005-12-23 12:14:55Z nyan $
34 */
35
36/*
37 * Routines to handle clock hardware.
38 */
39
40/*
41 * inittodr, settodr and support routines written
42 * by Christoph Robitschko <chmr@edvz.tu-graz.ac.at>
43 *
44 * reintroduced and updated by Chris Stenton <chris@gnome.co.uk> 8/10/94
45 */
46
47/*
48 * modified for PC98 by Kakefuda
49 */
50
51#include "opt_apic.h"
52#include "opt_clock.h"
53#include "opt_isa.h"
54#include "opt_mca.h"
55
56#include <sys/param.h>
57#include <sys/systm.h>
58#include <sys/bus.h>
59#include <sys/lock.h>
60#include <sys/kdb.h>
61#include <sys/mutex.h>
62#include <sys/proc.h>
63#include <sys/time.h>
64#include <sys/timetc.h>
65#include <sys/kernel.h>
66#include <sys/limits.h>
67#include <sys/module.h>
68#include <sys/sysctl.h>
69#include <sys/cons.h>
70#include <sys/power.h>
71
72#include <machine/clock.h>
73#include <machine/cpu.h>
74#include <machine/cputypes.h>
75#include <machine/frame.h>
76#include <machine/intr_machdep.h>
77#include <machine/md_var.h>
78#include <machine/psl.h>
79#ifdef DEV_APIC
80#include <machine/apicvar.h>
81#endif
82#include <machine/specialreg.h>
83#include <machine/ppireg.h>
84#include <machine/timerreg.h>
85
86#include <i386/isa/icu.h>
87#include <pc98/cbus/cbus.h>
88#include <pc98/pc98/pc98_machdep.h>
89#ifdef DEV_ISA
90#include <isa/isavar.h>
91#endif
92
93/*
94 * 32-bit time_t's can't reach leap years before 1904 or after 2036, so we
95 * can use a simple formula for leap years.
96 */
97#define	LEAPYEAR(y) (((u_int)(y) % 4 == 0) ? 1 : 0)
98#define DAYSPERYEAR   (31+28+31+30+31+30+31+31+30+31+30+31)
99
100#define	TIMER_DIV(x) ((timer_freq + (x) / 2) / (x))
101
102int	adjkerntz;		/* local offset from GMT in seconds */
103int	clkintr_pending;
104int	disable_rtc_set;	/* disable resettodr() if != 0 */
105int	pscnt = 1;
106int	psdiv = 1;
107int	statclock_disable;
108#ifndef TIMER_FREQ
109#define TIMER_FREQ   2457600
110#endif
111u_int	timer_freq = TIMER_FREQ;
112int	timer0_max_count;
113int	timer0_real_max_count;
114int	wall_cmos_clock;	/* wall CMOS clock assumed if != 0 */
115struct mtx clock_lock;
116
117static	int	beeping = 0;
118static	const u_char daysinmonth[] = {31,28,31,30,31,30,31,31,30,31,30,31};
119static	struct intsrc *i8254_intsrc;
120static	u_int32_t i8254_lastcount;
121static	u_int32_t i8254_offset;
122static	int	(*i8254_pending)(struct intsrc *);
123static	int	i8254_ticked;
124static	int	using_lapic_timer;
125
126/* Values for timerX_state: */
127#define	RELEASED	0
128#define	RELEASE_PENDING	1
129#define	ACQUIRED	2
130#define	ACQUIRE_PENDING	3
131
132static 	u_char	timer1_state;
133static	u_char	timer2_state;
134static void rtc_serialcombit(int);
135static void rtc_serialcom(int);
136static int rtc_inb(void);
137static void rtc_outb(int);
138
139static	unsigned i8254_get_timecount(struct timecounter *tc);
140static	unsigned i8254_simple_get_timecount(struct timecounter *tc);
141static	void	set_timer_freq(u_int freq, int intr_freq);
142
143static struct timecounter i8254_timecounter = {
144	i8254_get_timecount,	/* get_timecount */
145	0,			/* no poll_pps */
146	~0u,			/* counter_mask */
147	0,			/* frequency */
148	"i8254",		/* name */
149	0			/* quality */
150};
151
152static void
153clkintr(struct trapframe *frame)
154{
155
156	if (timecounter->tc_get_timecount == i8254_get_timecount) {
157		mtx_lock_spin(&clock_lock);
158		if (i8254_ticked)
159			i8254_ticked = 0;
160		else {
161			i8254_offset += timer0_max_count;
162			i8254_lastcount = 0;
163		}
164		clkintr_pending = 0;
165		mtx_unlock_spin(&clock_lock);
166	}
167	KASSERT(!using_lapic_timer, ("clk interrupt enabled with lapic timer"));
168	hardclock(TRAPF_USERMODE(frame), TRAPF_PC(frame));
169}
170
171int
172acquire_timer1(int mode)
173{
174
175	if (timer1_state != RELEASED)
176		return (-1);
177	timer1_state = ACQUIRED;
178
179	/*
180	 * This access to the timer registers is as atomic as possible
181	 * because it is a single instruction.  We could do better if we
182	 * knew the rate.  Use of splclock() limits glitches to 10-100us,
183	 * and this is probably good enough for timer2, so we aren't as
184	 * careful with it as with timer0.
185	 */
186	outb(TIMER_MODE, TIMER_SEL1 | (mode & 0x3f));
187
188	return (0);
189}
190
191int
192acquire_timer2(int mode)
193{
194
195	if (timer2_state != RELEASED)
196		return (-1);
197	timer2_state = ACQUIRED;
198
199	/*
200	 * This access to the timer registers is as atomic as possible
201	 * because it is a single instruction.  We could do better if we
202	 * knew the rate.  Use of splclock() limits glitches to 10-100us,
203	 * and this is probably good enough for timer2, so we aren't as
204	 * careful with it as with timer0.
205	 */
206	outb(TIMER_MODE, TIMER_SEL2 | (mode & 0x3f));
207
208	return (0);
209}
210
211int
212release_timer1()
213{
214
215	if (timer1_state != ACQUIRED)
216		return (-1);
217	timer1_state = RELEASED;
218	outb(TIMER_MODE, TIMER_SEL1 | TIMER_SQWAVE | TIMER_16BIT);
219	return (0);
220}
221
222int
223release_timer2()
224{
225
226	if (timer2_state != ACQUIRED)
227		return (-1);
228	timer2_state = RELEASED;
229	outb(TIMER_MODE, TIMER_SEL2 | TIMER_SQWAVE | TIMER_16BIT);
230	return (0);
231}
232
233
234static int
235getit(void)
236{
237	int high, low;
238
239	mtx_lock_spin(&clock_lock);
240
241	/* Select timer0 and latch counter value. */
242	outb(TIMER_MODE, TIMER_SEL0 | TIMER_LATCH);
243
244	low = inb(TIMER_CNTR0);
245	high = inb(TIMER_CNTR0);
246
247	mtx_unlock_spin(&clock_lock);
248	return ((high << 8) | low);
249}
250
251/*
252 * Wait "n" microseconds.
253 * Relies on timer 1 counting down from (timer_freq / hz)
254 * Note: timer had better have been programmed before this is first used!
255 */
256void
257DELAY(int n)
258{
259	int delta, prev_tick, tick, ticks_left;
260
261#ifdef DELAYDEBUG
262	int getit_calls = 1;
263	int n1;
264	static int state = 0;
265
266	if (state == 0) {
267		state = 1;
268		for (n1 = 1; n1 <= 10000000; n1 *= 10)
269			DELAY(n1);
270		state = 2;
271	}
272	if (state == 1)
273		printf("DELAY(%d)...", n);
274#endif
275	/*
276	 * Guard against the timer being uninitialized if we are called
277	 * early for console i/o.
278	 */
279	if (timer0_max_count == 0)
280		set_timer_freq(timer_freq, hz);
281
282	/*
283	 * Read the counter first, so that the rest of the setup overhead is
284	 * counted.  Guess the initial overhead is 20 usec (on most systems it
285	 * takes about 1.5 usec for each of the i/o's in getit().  The loop
286	 * takes about 6 usec on a 486/33 and 13 usec on a 386/20.  The
287	 * multiplications and divisions to scale the count take a while).
288	 *
289	 * However, if ddb is active then use a fake counter since reading
290	 * the i8254 counter involves acquiring a lock.  ddb must not do
291	 * locking for many reasons, but it calls here for at least atkbd
292	 * input.
293	 */
294#ifdef KDB
295	if (kdb_active)
296		prev_tick = 1;
297	else
298#endif
299		prev_tick = getit();
300	n -= 0;			/* XXX actually guess no initial overhead */
301	/*
302	 * Calculate (n * (timer_freq / 1e6)) without using floating point
303	 * and without any avoidable overflows.
304	 */
305	if (n <= 0)
306		ticks_left = 0;
307	else if (n < 256)
308		/*
309		 * Use fixed point to avoid a slow division by 1000000.
310		 * 39099 = 1193182 * 2^15 / 10^6 rounded to nearest.
311		 * 2^15 is the first power of 2 that gives exact results
312		 * for n between 0 and 256.
313		 */
314		ticks_left = ((u_int)n * 39099 + (1 << 15) - 1) >> 15;
315	else
316		/*
317		 * Don't bother using fixed point, although gcc-2.7.2
318		 * generates particularly poor code for the long long
319		 * division, since even the slow way will complete long
320		 * before the delay is up (unless we're interrupted).
321		 */
322		ticks_left = ((u_int)n * (long long)timer_freq + 999999)
323			     / 1000000;
324
325	while (ticks_left > 0) {
326#ifdef KDB
327		if (kdb_active) {
328			outb(0x5f, 0);
329			tick = prev_tick - 1;
330			if (tick <= 0)
331				tick = timer0_max_count;
332		} else
333#endif
334			tick = getit();
335#ifdef DELAYDEBUG
336		++getit_calls;
337#endif
338		delta = prev_tick - tick;
339		prev_tick = tick;
340		if (delta < 0) {
341			delta += timer0_max_count;
342			/*
343			 * Guard against timer0_max_count being wrong.
344			 * This shouldn't happen in normal operation,
345			 * but it may happen if set_timer_freq() is
346			 * traced.
347			 */
348			if (delta < 0)
349				delta = 0;
350		}
351		ticks_left -= delta;
352	}
353#ifdef DELAYDEBUG
354	if (state == 1)
355		printf(" %d calls to getit() at %d usec each\n",
356		       getit_calls, (n + 5) / getit_calls);
357#endif
358}
359
360static void
361sysbeepstop(void *chan)
362{
363	ppi_spkr_off();		/* disable counter1 output to speaker */
364	timer_spkr_release();
365	beeping = 0;
366}
367
368int
369sysbeep(int pitch, int period)
370{
371	int x = splclock();
372
373	if (timer_spkr_acquire())
374		if (!beeping) {
375			/* Something else owns it. */
376			splx(x);
377			return (-1); /* XXX Should be EBUSY, but nobody cares anyway. */
378		}
379	disable_intr();
380	spkr_set_pitch(pitch);
381	enable_intr();
382	if (!beeping) {
383		/* enable counter1 output to speaker */
384		ppi_spkr_on();
385		beeping = period;
386		timeout(sysbeepstop, (void *)NULL, period);
387	}
388	splx(x);
389	return (0);
390}
391
392
393unsigned int delaycount;
394#define FIRST_GUESS	0x2000
395static void findcpuspeed(void)
396{
397	int i;
398	int remainder;
399
400	/* Put counter in count down mode */
401	outb(TIMER_MODE, TIMER_SEL0 | TIMER_16BIT | TIMER_RATEGEN);
402	outb(TIMER_CNTR0, 0xff);
403	outb(TIMER_CNTR0, 0xff);
404	for (i = FIRST_GUESS; i; i--)
405		;
406	remainder = getit();
407	delaycount = (FIRST_GUESS * TIMER_DIV(1000)) / (0xffff - remainder);
408}
409
410static u_int
411calibrate_clocks(void)
412{
413	int	timeout;
414	u_int	count, prev_count, tot_count;
415	u_short	sec, start_sec;
416
417	if (bootverbose)
418	        printf("Calibrating clock(s) ... ");
419	/* Check ARTIC. */
420	if (!(PC98_SYSTEM_PARAMETER(0x458) & 0x80) &&
421	    !(PC98_SYSTEM_PARAMETER(0x45b) & 0x04))
422		goto fail;
423	timeout = 100000000;
424
425	/* Read the ARTIC. */
426	sec = inw(0x5e);
427
428	/* Wait for the ARTIC to changes. */
429	start_sec = sec;
430	for (;;) {
431		sec = inw(0x5e);
432		if (sec != start_sec)
433			break;
434		if (--timeout == 0)
435			goto fail;
436	}
437	prev_count = getit();
438	if (prev_count == 0 || prev_count > timer0_max_count)
439		goto fail;
440	tot_count = 0;
441
442	start_sec = sec;
443	for (;;) {
444		sec = inw(0x5e);
445		count = getit();
446		if (count == 0 || count > timer0_max_count)
447			goto fail;
448		if (count > prev_count)
449			tot_count += prev_count - (count - timer0_max_count);
450		else
451			tot_count += prev_count - count;
452		prev_count = count;
453		if ((sec == start_sec + 1200) || /* 1200 = 307.2KHz >> 8 */
454		    (sec < start_sec &&
455		        (u_int)sec + 0x10000 == (u_int)start_sec + 1200))
456			break;
457		if (--timeout == 0)
458			goto fail;
459	}
460
461	if (bootverbose) {
462	        printf("i8254 clock: %u Hz\n", tot_count);
463	}
464	return (tot_count);
465
466fail:
467	if (bootverbose)
468	        printf("failed, using default i8254 clock of %u Hz\n",
469		       timer_freq);
470	return (timer_freq);
471}
472
473static void
474set_timer_freq(u_int freq, int intr_freq)
475{
476	int new_timer0_real_max_count;
477
478	i8254_timecounter.tc_frequency = freq;
479	mtx_lock_spin(&clock_lock);
480	timer_freq = freq;
481	if (using_lapic_timer)
482		new_timer0_real_max_count = 0x10000;
483	else
484		new_timer0_real_max_count = TIMER_DIV(intr_freq);
485	if (new_timer0_real_max_count != timer0_real_max_count) {
486		timer0_real_max_count = new_timer0_real_max_count;
487		if (timer0_real_max_count == 0x10000)
488			timer0_max_count = 0xffff;
489		else
490			timer0_max_count = timer0_real_max_count;
491		outb(TIMER_MODE, TIMER_SEL0 | TIMER_RATEGEN | TIMER_16BIT);
492		outb(TIMER_CNTR0, timer0_real_max_count & 0xff);
493		outb(TIMER_CNTR0, timer0_real_max_count >> 8);
494	}
495	mtx_unlock_spin(&clock_lock);
496}
497
498static void
499i8254_restore(void)
500{
501
502	mtx_lock_spin(&clock_lock);
503	outb(TIMER_MODE, TIMER_SEL0 | TIMER_RATEGEN | TIMER_16BIT);
504	outb(TIMER_CNTR0, timer0_real_max_count & 0xff);
505	outb(TIMER_CNTR0, timer0_real_max_count >> 8);
506	mtx_unlock_spin(&clock_lock);
507}
508
509
510/*
511 * Restore all the timers non-atomically (XXX: should be atomically).
512 *
513 * This function is called from pmtimer_resume() to restore all the timers.
514 * This should not be necessary, but there are broken laptops that do not
515 * restore all the timers on resume.
516 */
517void
518timer_restore(void)
519{
520
521	i8254_restore();		/* restore timer_freq and hz */
522}
523
524/*
525 * Initialize 8254 timer 0 early so that it can be used in DELAY().
526 * XXX initialization of other timers is unintentionally left blank.
527 */
528void
529startrtclock()
530{
531	u_int delta, freq;
532
533	findcpuspeed();
534	if (pc98_machine_type & M_8M)
535		timer_freq = 1996800L; /* 1.9968 MHz */
536	else
537		timer_freq = 2457600L; /* 2.4576 MHz */
538
539	set_timer_freq(timer_freq, hz);
540	freq = calibrate_clocks();
541#ifdef CLK_CALIBRATION_LOOP
542	if (bootverbose) {
543		printf(
544		"Press a key on the console to abort clock calibration\n");
545		while (cncheckc() == -1)
546			calibrate_clocks();
547	}
548#endif
549
550	/*
551	 * Use the calibrated i8254 frequency if it seems reasonable.
552	 * Otherwise use the default, and don't use the calibrated i586
553	 * frequency.
554	 */
555	delta = freq > timer_freq ? freq - timer_freq : timer_freq - freq;
556	if (delta < timer_freq / 100) {
557#ifndef CLK_USE_I8254_CALIBRATION
558		if (bootverbose)
559			printf(
560"CLK_USE_I8254_CALIBRATION not specified - using default frequency\n");
561		freq = timer_freq;
562#endif
563		timer_freq = freq;
564	} else {
565		if (bootverbose)
566			printf(
567		    "%d Hz differs from default of %d Hz by more than 1%%\n",
568			       freq, timer_freq);
569	}
570
571	set_timer_freq(timer_freq, hz);
572	tc_init(&i8254_timecounter);
573
574	init_TSC();
575}
576
577static void
578rtc_serialcombit(int i)
579{
580	outb(IO_RTC, ((i&0x01)<<5)|0x07);
581	DELAY(1);
582	outb(IO_RTC, ((i&0x01)<<5)|0x17);
583	DELAY(1);
584	outb(IO_RTC, ((i&0x01)<<5)|0x07);
585	DELAY(1);
586}
587
588static void
589rtc_serialcom(int i)
590{
591	rtc_serialcombit(i&0x01);
592	rtc_serialcombit((i&0x02)>>1);
593	rtc_serialcombit((i&0x04)>>2);
594	rtc_serialcombit((i&0x08)>>3);
595	outb(IO_RTC, 0x07);
596	DELAY(1);
597	outb(IO_RTC, 0x0f);
598	DELAY(1);
599	outb(IO_RTC, 0x07);
600 	DELAY(1);
601}
602
603static void
604rtc_outb(int val)
605{
606	int s;
607	int sa = 0;
608
609	for (s=0;s<8;s++) {
610	    sa = ((val >> s) & 0x01) ? 0x27 : 0x07;
611	    outb(IO_RTC, sa);		/* set DI & CLK 0 */
612	    DELAY(1);
613	    outb(IO_RTC, sa | 0x10);	/* CLK 1 */
614	    DELAY(1);
615	}
616	outb(IO_RTC, sa & 0xef);	/* CLK 0 */
617}
618
619static int
620rtc_inb(void)
621{
622	int s;
623	int sa = 0;
624
625	for (s=0;s<8;s++) {
626	    sa |= ((inb(0x33) & 0x01) << s);
627	    outb(IO_RTC, 0x17);	/* CLK 1 */
628	    DELAY(1);
629	    outb(IO_RTC, 0x07);	/* CLK 0 */
630	    DELAY(2);
631	}
632	return sa;
633}
634
635/*
636 * Initialize the time of day register, based on the time base which is, e.g.
637 * from a filesystem.
638 */
639void
640inittodr(time_t base)
641{
642	unsigned long	sec, days;
643	int		year, month;
644	int		y, m, s;
645	struct timespec ts;
646	int		second, min, hour;
647
648	if (base) {
649		s = splclock();
650		ts.tv_sec = base;
651		ts.tv_nsec = 0;
652		tc_setclock(&ts);
653		splx(s);
654	}
655
656	rtc_serialcom(0x03);	/* Time Read */
657	rtc_serialcom(0x01);	/* Register shift command. */
658	DELAY(20);
659
660	second = bcd2bin(rtc_inb() & 0xff);	/* sec */
661	min = bcd2bin(rtc_inb() & 0xff);	/* min */
662	hour = bcd2bin(rtc_inb() & 0xff);	/* hour */
663	days = bcd2bin(rtc_inb() & 0xff) - 1;	/* date */
664
665	month = (rtc_inb() >> 4) & 0x0f;	/* month */
666	for (m = 1; m <	month; m++)
667		days +=	daysinmonth[m-1];
668	year = bcd2bin(rtc_inb() & 0xff) + 1900;	/* year */
669	/* 2000 year problem */
670	if (year < 1995)
671		year += 100;
672	if (year < 1970)
673		goto wrong_time;
674	for (y = 1970; y < year; y++)
675		days +=	DAYSPERYEAR + LEAPYEAR(y);
676	if ((month > 2)	&& LEAPYEAR(year))
677		days ++;
678	sec = ((( days * 24 +
679		  hour) * 60 +
680		  min) * 60 +
681		  second);
682	/* sec now contains the	number of seconds, since Jan 1 1970,
683	   in the local	time zone */
684
685	s = splhigh();
686
687	sec += tz_minuteswest * 60 + (wall_cmos_clock ? adjkerntz : 0);
688
689	y = time_second - sec;
690	if (y <= -2 || y >= 2) {
691		/* badly off, adjust it */
692		ts.tv_sec = sec;
693		ts.tv_nsec = 0;
694		tc_setclock(&ts);
695	}
696	splx(s);
697	return;
698
699wrong_time:
700	printf("Invalid time in real time clock.\n");
701	printf("Check and reset the date immediately!\n");
702}
703
704/*
705 * Write system time back to RTC
706 */
707void
708resettodr()
709{
710	unsigned long	tm;
711	int		y, m, s;
712	int		wd;
713
714	if (disable_rtc_set)
715		return;
716
717	s = splclock();
718	tm = time_second;
719	splx(s);
720
721	rtc_serialcom(0x01);	/* Register shift command. */
722
723	/* Calculate local time	to put in RTC */
724
725	tm -= tz_minuteswest * 60 + (wall_cmos_clock ? adjkerntz : 0);
726
727	rtc_outb(bin2bcd(tm%60)); tm /= 60;	/* Write back Seconds */
728	rtc_outb(bin2bcd(tm%60)); tm /= 60;	/* Write back Minutes */
729	rtc_outb(bin2bcd(tm%24)); tm /= 24;	/* Write back Hours   */
730
731	/* We have now the days	since 01-01-1970 in tm */
732	wd = (tm + 4) % 7 + 1;			/* Write back Weekday */
733	for (y = 1970, m = DAYSPERYEAR + LEAPYEAR(y);
734	     tm >= m;
735	     y++,      m = DAYSPERYEAR + LEAPYEAR(y))
736	     tm -= m;
737
738	/* Now we have the years in y and the day-of-the-year in tm */
739	for (m = 0; ; m++) {
740		int ml;
741
742		ml = daysinmonth[m];
743		if (m == 1 && LEAPYEAR(y))
744			ml++;
745		if (tm < ml)
746			break;
747		tm -= ml;
748	}
749
750	m++;
751	rtc_outb(bin2bcd(tm+1));		/* Write back Day     */
752	rtc_outb((m << 4) | wd);		/* Write back Month & Weekday  */
753	rtc_outb(bin2bcd(y%100));		/* Write back Year    */
754
755	rtc_serialcom(0x02);	/* Time set & Counter hold command. */
756	rtc_serialcom(0x00);	/* Register hold command. */
757}
758
759
760/*
761 * Start both clocks running.
762 */
763void
764cpu_initclocks()
765{
766
767#ifdef DEV_APIC
768	using_lapic_timer = lapic_setup_clock();
769#endif
770	/*
771	 * If we aren't using the local APIC timer to drive the kernel
772	 * clocks, setup the interrupt handler for the 8254 timer 0 so
773	 * that it can drive hardclock().  Otherwise, change the 8254
774	 * timecounter to user a simpler algorithm.
775	 */
776	if (!using_lapic_timer) {
777		intr_add_handler("clk", 0, (driver_intr_t *)clkintr, NULL,
778		    INTR_TYPE_CLK | INTR_FAST, NULL);
779		i8254_intsrc = intr_lookup_source(0);
780		if (i8254_intsrc != NULL)
781			i8254_pending =
782			    i8254_intsrc->is_pic->pic_source_pending;
783	} else {
784		i8254_timecounter.tc_get_timecount =
785		    i8254_simple_get_timecount;
786		i8254_timecounter.tc_counter_mask = 0xffff;
787		set_timer_freq(timer_freq, hz);
788	}
789
790	init_TSC_tc();
791}
792
793void
794cpu_startprofclock(void)
795{
796}
797
798void
799cpu_stopprofclock(void)
800{
801}
802
803static int
804sysctl_machdep_i8254_freq(SYSCTL_HANDLER_ARGS)
805{
806	int error;
807	u_int freq;
808
809	/*
810	 * Use `i8254' instead of `timer' in external names because `timer'
811	 * is is too generic.  Should use it everywhere.
812	 */
813	freq = timer_freq;
814	error = sysctl_handle_int(oidp, &freq, sizeof(freq), req);
815	if (error == 0 && req->newptr != NULL)
816		set_timer_freq(freq, hz);
817	return (error);
818}
819
820SYSCTL_PROC(_machdep, OID_AUTO, i8254_freq, CTLTYPE_INT | CTLFLAG_RW,
821    0, sizeof(u_int), sysctl_machdep_i8254_freq, "IU", "");
822
823static unsigned
824i8254_simple_get_timecount(struct timecounter *tc)
825{
826
827	return (timer0_max_count - getit());
828}
829
830static unsigned
831i8254_get_timecount(struct timecounter *tc)
832{
833	u_int count;
834	u_int high, low;
835	u_int eflags;
836
837	eflags = read_eflags();
838	mtx_lock_spin(&clock_lock);
839
840	/* Select timer0 and latch counter value. */
841	outb(TIMER_MODE, TIMER_SEL0 | TIMER_LATCH);
842
843	low = inb(TIMER_CNTR0);
844	high = inb(TIMER_CNTR0);
845	count = timer0_max_count - ((high << 8) | low);
846	if (count < i8254_lastcount ||
847	    (!i8254_ticked && (clkintr_pending ||
848	    ((count < 20 || (!(eflags & PSL_I) && count < timer0_max_count / 2u)) &&
849	    i8254_pending != NULL && i8254_pending(i8254_intsrc))))) {
850		i8254_ticked = 1;
851		i8254_offset += timer0_max_count;
852	}
853	i8254_lastcount = count;
854	count += i8254_offset;
855	mtx_unlock_spin(&clock_lock);
856	return (count);
857}
858
859#ifdef DEV_ISA
860/*
861 * Attach to the ISA PnP descriptors for the timer and realtime clock.
862 */
863static struct isa_pnp_id attimer_ids[] = {
864	{ 0x0001d041 /* PNP0100 */, "AT timer" },
865	{ 0x000bd041 /* PNP0B00 */, "AT realtime clock" },
866	{ 0 }
867};
868
869static int
870attimer_probe(device_t dev)
871{
872	int result;
873
874	if ((result = ISA_PNP_PROBE(device_get_parent(dev), dev, attimer_ids)) <= 0)
875		device_quiet(dev);
876	return(result);
877}
878
879static int
880attimer_attach(device_t dev)
881{
882	return(0);
883}
884
885static device_method_t attimer_methods[] = {
886	/* Device interface */
887	DEVMETHOD(device_probe,		attimer_probe),
888	DEVMETHOD(device_attach,	attimer_attach),
889	DEVMETHOD(device_detach,	bus_generic_detach),
890	DEVMETHOD(device_shutdown,	bus_generic_shutdown),
891	DEVMETHOD(device_suspend,	bus_generic_suspend),	/* XXX stop statclock? */
892	DEVMETHOD(device_resume,	bus_generic_resume),	/* XXX restart statclock? */
893	{ 0, 0 }
894};
895
896static driver_t attimer_driver = {
897	"attimer",
898	attimer_methods,
899	1,		/* no softc */
900};
901
902static devclass_t attimer_devclass;
903
904DRIVER_MODULE(attimer, isa, attimer_driver, attimer_devclass, 0, 0);
905#endif /* DEV_ISA */
906