File:  [DragonFly] / src / sys / i386 / isa / Attic / clock.c
Revision 1.14: download - view: text, annotated - select for diffs
Sun Apr 4 08:00:06 2004 UTC (10 years, 8 months ago) by dillon
Branches: MAIN
CVS tags: HEAD, DragonFly_1_0_REL, DragonFly_1_0_RC1, DragonFly_1_0A_REL
Setting the date/time does not always properly write-back the RTC, causing
the date/time to be wrong again after a reboot.  This was due to the recent
systimer changes which updated the 'time_second' global via hardclock() only.
Change the writeback code to use microtime() instead of time_second.

Reported-by: esmith <esmith@patmedia.net>

    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:  * $FreeBSD: src/sys/i386/isa/clock.c,v 1.149.2.6 2002/11/02 04:41:50 iwasaki Exp $
   38:  * $DragonFly: src/sys/i386/isa/clock.c,v 1.14 2004/04/04 08:00:06 dillon Exp $
   39:  */
   40: 
   41: /*
   42:  * Routines to handle clock hardware.
   43:  */
   44: 
   45: /*
   46:  * inittodr, settodr and support routines written
   47:  * by Christoph Robitschko <chmr@edvz.tu-graz.ac.at>
   48:  *
   49:  * reintroduced and updated by Chris Stenton <chris@gnome.co.uk> 8/10/94
   50:  */
   51: 
   52: #include "use_apm.h"
   53: #include "use_mca.h"
   54: #include "opt_clock.h"
   55: 
   56: #include <sys/param.h>
   57: #include <sys/systm.h>
   58: #include <sys/time.h>
   59: #include <sys/kernel.h>
   60: #include <sys/bus.h>
   61: #ifndef SMP
   62: #include <sys/lock.h>
   63: #endif
   64: #include <sys/sysctl.h>
   65: #include <sys/cons.h>
   66: #include <sys/systimer.h>
   67: #include <sys/globaldata.h>
   68: #include <sys/thread2.h>
   69: #include <sys/systimer.h>
   70: 
   71: #include <machine/clock.h>
   72: #ifdef CLK_CALIBRATION_LOOP
   73: #endif
   74: #include <machine/cputypes.h>
   75: #include <machine/frame.h>
   76: #include <machine/ipl.h>
   77: #include <machine/limits.h>
   78: #include <machine/md_var.h>
   79: #include <machine/psl.h>
   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: #include <bus/isa/i386/isa.h>
   90: #include <bus/isa/rtc.h>
   91: #include <i386/isa/timerreg.h>
   92: 
   93: #include <i386/isa/intr_machdep.h>
   94: 
   95: #if NMCA > 0
   96: #include <bus/mca/i386/mca_machdep.h>
   97: #endif
   98: 
   99: #ifdef APIC_IO
  100: #include <i386/isa/intr_machdep.h>
  101: /* The interrupt triggered by the 8254 (timer) chip */
  102: int apic_8254_intr;
  103: static u_long read_intr_count (int vec);
  104: static void setup_8254_mixed_mode (void);
  105: #endif
  106: static void i8254_restore(void);
  107: 
  108: /*
  109:  * 32-bit time_t's can't reach leap years before 1904 or after 2036, so we
  110:  * can use a simple formula for leap years.
  111:  */
  112: #define	LEAPYEAR(y) ((u_int)(y) % 4 == 0)
  113: #define DAYSPERYEAR   (31+28+31+30+31+30+31+31+30+31+30+31)
  114: 
  115: #ifndef TIMER_FREQ
  116: #define TIMER_FREQ   1193182
  117: #endif
  118: 
  119: #define TIMER_SELX	TIMER_SEL2
  120: #define TIMER_CNTRX	TIMER_CNTR2
  121: 
  122: int	adjkerntz;		/* local offset from GMT in seconds */
  123: int	disable_rtc_set;	/* disable resettodr() if != 0 */
  124: volatile u_int	idelayed;
  125: int	statclock_disable = 1;	/* we don't use the statclock right now */
  126: u_int	stat_imask = SWI_CLOCK_MASK;
  127: u_int	cputimer_freq = TIMER_FREQ;
  128: #if 0
  129: int64_t	cputimer_freq64_usec = ((int64_t)TIMER_FREQ << 32) / 1000000;
  130: int64_t	cputimer_freq64_nsec = ((int64_t)TIMER_FREQ << 32) / 1000000000LL;
  131: #endif
  132: int64_t	cputimer_freq64_usec = (1000000LL << 32) / TIMER_FREQ;
  133: int64_t	cputimer_freq64_nsec = (1000000000LL << 32) / TIMER_FREQ;
  134: u_int	tsc_freq;
  135: int	tsc_is_broken;
  136: int	wall_cmos_clock;	/* wall CMOS clock assumed if != 0 */
  137: int	timer0_running;
  138: enum tstate { RELEASED, ACQUIRED };
  139: enum tstate timer0_state;
  140: enum tstate timer1_state;
  141: enum tstate timer2_state;
  142: 
  143: static	int	beeping = 0;
  144: static	u_int	clk_imask = HWI_MASK | SWI_MASK;
  145: static	const u_char daysinmonth[] = {31,28,31,30,31,30,31,31,30,31,30,31};
  146: static	u_char	rtc_statusa = RTCSA_DIVIDER | RTCSA_NOPROF;
  147: static	u_char	rtc_statusb = RTCSB_24HR | RTCSB_PINTR;
  148: static	u_int	tsc_present;
  149: 
  150: /*
  151:  * timer0 clock interrupt.  Timer0 is in one-shot mode and has stopped
  152:  * counting as of this interrupt.  We use timer1 in free-running mode (not
  153:  * generating any interrupts) as our main counter.  Each cpu has timeouts
  154:  * pending.
  155:  */
  156: static void
  157: clkintr(struct intrframe frame)
  158: {
  159: 	static sysclock_t timer1_count;
  160: 	struct globaldata *gd = mycpu;
  161: 	struct globaldata *gscan;
  162: 	int n;
  163: 
  164: 	/*
  165: 	 * SWSTROBE mode is a one-shot, the timer is no longer running
  166: 	 */
  167: 	timer0_running = 0;
  168: 
  169: 	/*
  170: 	 * XXX this could be done more efficiently by using a bitmask?
  171: 	 */
  172: 	timer1_count = cputimer_count();
  173: 	for (n = 0; n < ncpus; ++n) {
  174: 	    gscan = globaldata_find(n);
  175: 	    if (gscan->gd_nextclock == 0)
  176: 		continue;
  177: 	    if (gscan != gd) {
  178: 		lwkt_send_ipiq(gscan, (ipifunc_t)systimer_intr, &timer1_count);
  179: 	    } else {
  180: 		systimer_intr(&timer1_count, &frame);
  181: 	    }
  182: 	}
  183: #if NMCA > 0
  184: 	/* Reset clock interrupt by asserting bit 7 of port 0x61 */
  185: 	if (MCA_system)
  186: 		outb(0x61, inb(0x61) | 0x80);
  187: #endif
  188: }
  189: 
  190: 
  191: /*
  192:  * NOTE! not MP safe.
  193:  */
  194: int
  195: acquire_timer2(int mode)
  196: {
  197: 	/* Timer2 is being used for time count operation */
  198: 	return(-1);
  199: #if 0
  200: 	if (timer2_state != RELEASED)
  201: 		return (-1);
  202: 	timer2_state = ACQUIRED;
  203: 
  204: 	/*
  205: 	 * This access to the timer registers is as atomic as possible
  206: 	 * because it is a single instruction.  We could do better if we
  207: 	 * knew the rate.
  208: 	 */
  209: 	outb(TIMER_MODE, TIMER_SEL2 | (mode & 0x3f));
  210: 	return (0);
  211: #endif
  212: }
  213: 
  214: int
  215: release_timer2()
  216: {
  217: 	if (timer2_state != ACQUIRED)
  218: 		return (-1);
  219: 	outb(TIMER_MODE, TIMER_SEL2 | TIMER_SQWAVE | TIMER_16BIT);
  220: 	timer2_state = RELEASED;
  221: 	return (0);
  222: }
  223: 
  224: /*
  225:  * This routine receives statistical clock interrupts from the RTC.
  226:  * As explained above, these occur at 128 interrupts per second.
  227:  * When profiling, we receive interrupts at a rate of 1024 Hz.
  228:  *
  229:  * This does not actually add as much overhead as it sounds, because
  230:  * when the statistical clock is active, the hardclock driver no longer
  231:  * needs to keep (inaccurate) statistics on its own.  This decouples
  232:  * statistics gathering from scheduling interrupts.
  233:  *
  234:  * The RTC chip requires that we read status register C (RTC_INTR)
  235:  * to acknowledge an interrupt, before it will generate the next one.
  236:  * Under high interrupt load, rtcintr() can be indefinitely delayed and
  237:  * the clock can tick immediately after the read from RTC_INTR.  In this
  238:  * case, the mc146818A interrupt signal will not drop for long enough
  239:  * to register with the 8259 PIC.  If an interrupt is missed, the stat
  240:  * clock will halt, considerably degrading system performance.  This is
  241:  * why we use 'while' rather than a more straightforward 'if' below.
  242:  * Stat clock ticks can still be lost, causing minor loss of accuracy
  243:  * in the statistics, but the stat clock will no longer stop.
  244:  */
  245: static void
  246: rtcintr(struct intrframe frame)
  247: {
  248: 	while (rtcin(RTC_INTR) & RTCIR_PERIOD)
  249: 		;
  250: 		/* statclock(&frame); no longer used */
  251: }
  252: 
  253: #include "opt_ddb.h"
  254: #ifdef DDB
  255: #include <ddb/ddb.h>
  256: 
  257: DB_SHOW_COMMAND(rtc, rtc)
  258: {
  259: 	printf("%02x/%02x/%02x %02x:%02x:%02x, A = %02x, B = %02x, C = %02x\n",
  260: 	       rtcin(RTC_YEAR), rtcin(RTC_MONTH), rtcin(RTC_DAY),
  261: 	       rtcin(RTC_HRS), rtcin(RTC_MIN), rtcin(RTC_SEC),
  262: 	       rtcin(RTC_STATUSA), rtcin(RTC_STATUSB), rtcin(RTC_INTR));
  263: }
  264: #endif /* DDB */
  265: 
  266: /*
  267:  * Convert a frequency to a cpu timer count.
  268:  */
  269: sysclock_t
  270: cputimer_fromhz(int freq)
  271: {
  272: 	return(cputimer_freq / freq + 1);
  273: }
  274: 
  275: sysclock_t
  276: cputimer_fromus(int us)
  277: {
  278: 	return((int64_t)cputimer_freq * us / 1000000);
  279: }
  280: 
  281: /*
  282:  * Return the current cpu timer count as a 32 bit integer.
  283:  */
  284: sysclock_t
  285: cputimer_count(void)
  286: {
  287: 	static sysclock_t cputimer_base;
  288: 	static __uint16_t cputimer_last;
  289: 	__uint16_t count;
  290: 	sysclock_t ret;
  291: 
  292: 	clock_lock();
  293: 	outb(TIMER_MODE, TIMER_SELX | TIMER_LATCH);
  294: 	count = (__uint8_t)inb(TIMER_CNTRX);		/* get countdown */
  295: 	count |= ((__uint8_t)inb(TIMER_CNTRX) << 8);
  296: 	count = -count;					/* -> countup */
  297: 	if (count < cputimer_last)			/* rollover */
  298: 		cputimer_base += 0x00010000;
  299: 	ret = cputimer_base | count;
  300: 	cputimer_last = count;
  301: 	clock_unlock();
  302: 	return(ret);
  303: }
  304: 
  305: /*
  306:  * Reload for the next timeout.  It is possible for the reload value
  307:  * to be 0 or negative, indicating that an immediate timer interrupt
  308:  * is desired.  For now make the minimum 2 ticks.
  309:  */
  310: void
  311: cputimer_intr_reload(sysclock_t reload)
  312: {
  313:     __uint16_t count;
  314: 
  315:     if ((int)reload < 2)
  316: 	reload = 2;
  317: 
  318:     clock_lock();
  319:     if (timer0_running) {
  320: 	outb(TIMER_MODE, TIMER_SEL0 | TIMER_LATCH);	/* count-down timer */
  321: 	count = (__uint8_t)inb(TIMER_CNTR0);		/* lsb */
  322: 	count |= ((__uint8_t)inb(TIMER_CNTR0) << 8);	/* msb */
  323: 	if (reload < count) {
  324: 	    outb(TIMER_MODE, TIMER_SEL0 | TIMER_SWSTROBE | TIMER_16BIT);
  325: 	    outb(TIMER_CNTR0, (__uint8_t)reload); 	/* lsb */
  326: 	    outb(TIMER_CNTR0, (__uint8_t)(reload >> 8)); /* msb */
  327: 	}
  328:     } else {
  329: 	timer0_running = 1;
  330: 	if (reload > 0xFFFF)
  331: 	    reload = 0;		/* full count */
  332: 	outb(TIMER_MODE, TIMER_SEL0 | TIMER_SWSTROBE | TIMER_16BIT);
  333: 	outb(TIMER_CNTR0, (__uint8_t)reload); 		/* lsb */
  334: 	outb(TIMER_CNTR0, (__uint8_t)(reload >> 8));	/* msb */
  335:     }
  336:     clock_unlock();
  337: }
  338: 
  339: /*
  340:  * Wait "n" microseconds.
  341:  * Relies on timer 1 counting down from (cputimer_freq / hz)
  342:  * Note: timer had better have been programmed before this is first used!
  343:  */
  344: void
  345: DELAY(int n)
  346: {
  347: 	int delta, prev_tick, tick, ticks_left;
  348: 
  349: #ifdef DELAYDEBUG
  350: 	int getit_calls = 1;
  351: 	int n1;
  352: 	static int state = 0;
  353: 
  354: 	if (state == 0) {
  355: 		state = 1;
  356: 		for (n1 = 1; n1 <= 10000000; n1 *= 10)
  357: 			DELAY(n1);
  358: 		state = 2;
  359: 	}
  360: 	if (state == 1)
  361: 		printf("DELAY(%d)...", n);
  362: #endif
  363: 	/*
  364: 	 * Guard against the timer being uninitialized if we are called
  365: 	 * early for console i/o.
  366: 	 */
  367: 	if (timer0_state == RELEASED)
  368: 		i8254_restore();
  369: 
  370: 	/*
  371: 	 * Read the counter first, so that the rest of the setup overhead is
  372: 	 * counted.  Guess the initial overhead is 20 usec (on most systems it
  373: 	 * takes about 1.5 usec for each of the i/o's in getit().  The loop
  374: 	 * takes about 6 usec on a 486/33 and 13 usec on a 386/20.  The
  375: 	 * multiplications and divisions to scale the count take a while).
  376: 	 */
  377: 	prev_tick = cputimer_count();
  378: 	n -= 0;			/* XXX actually guess no initial overhead */
  379: 	/*
  380: 	 * Calculate (n * (cputimer_freq / 1e6)) without using floating point
  381: 	 * and without any avoidable overflows.
  382: 	 */
  383: 	if (n <= 0) {
  384: 		ticks_left = 0;
  385: 	} else if (n < 256) {
  386: 		/*
  387: 		 * Use fixed point to avoid a slow division by 1000000.
  388: 		 * 39099 = 1193182 * 2^15 / 10^6 rounded to nearest.
  389: 		 * 2^15 is the first power of 2 that gives exact results
  390: 		 * for n between 0 and 256.
  391: 		 */
  392: 		ticks_left = ((u_int)n * 39099 + (1 << 15) - 1) >> 15;
  393: 	} else {
  394: 		/*
  395: 		 * Don't bother using fixed point, although gcc-2.7.2
  396: 		 * generates particularly poor code for the long long
  397: 		 * division, since even the slow way will complete long
  398: 		 * before the delay is up (unless we're interrupted).
  399: 		 */
  400: 		ticks_left = ((u_int)n * (long long)cputimer_freq + 999999)
  401: 			     / 1000000;
  402: 	}
  403: 
  404: 	while (ticks_left > 0) {
  405: 		tick = cputimer_count();
  406: #ifdef DELAYDEBUG
  407: 		++getit_calls;
  408: #endif
  409: 		delta = tick - prev_tick;
  410: 		prev_tick = tick;
  411: 		if (delta < 0)
  412: 			delta = 0;
  413: 		ticks_left -= delta;
  414: 	}
  415: #ifdef DELAYDEBUG
  416: 	if (state == 1)
  417: 		printf(" %d calls to getit() at %d usec each\n",
  418: 		       getit_calls, (n + 5) / getit_calls);
  419: #endif
  420: }
  421: 
  422: static void
  423: sysbeepstop(void *chan)
  424: {
  425: 	outb(IO_PPI, inb(IO_PPI)&0xFC);	/* disable counter2 output to speaker */
  426: 	beeping = 0;
  427: 	release_timer2();
  428: }
  429: 
  430: int
  431: sysbeep(int pitch, int period)
  432: {
  433: 	if (acquire_timer2(TIMER_SQWAVE|TIMER_16BIT))
  434: 		return(-1);
  435: 	/*
  436: 	 * Nobody else is using timer2, we do not need the clock lock
  437: 	 */
  438: 	outb(TIMER_CNTR2, pitch);
  439: 	outb(TIMER_CNTR2, (pitch>>8));
  440: 	if (!beeping) {
  441: 		/* enable counter2 output to speaker */
  442: 		outb(IO_PPI, inb(IO_PPI) | 3);
  443: 		beeping = period;
  444: 		timeout(sysbeepstop, (void *)NULL, period);
  445: 	}
  446: 	return (0);
  447: }
  448: 
  449: /*
  450:  * RTC support routines
  451:  */
  452: 
  453: int
  454: rtcin(reg)
  455: 	int reg;
  456: {
  457: 	int s;
  458: 	u_char val;
  459: 
  460: 	s = splhigh();
  461: 	outb(IO_RTC, reg);
  462: 	inb(0x84);
  463: 	val = inb(IO_RTC + 1);
  464: 	inb(0x84);
  465: 	splx(s);
  466: 	return (val);
  467: }
  468: 
  469: static __inline void
  470: writertc(u_char reg, u_char val)
  471: {
  472: 	int s;
  473: 
  474: 	s = splhigh();
  475: 	inb(0x84);
  476: 	outb(IO_RTC, reg);
  477: 	inb(0x84);
  478: 	outb(IO_RTC + 1, val);
  479: 	inb(0x84);		/* XXX work around wrong order in rtcin() */
  480: 	splx(s);
  481: }
  482: 
  483: static __inline int
  484: readrtc(int port)
  485: {
  486: 	return(bcd2bin(rtcin(port)));
  487: }
  488: 
  489: static u_int
  490: calibrate_clocks(void)
  491: {
  492: 	u_int64_t old_tsc;
  493: 	u_int count, prev_count, tot_count;
  494: 	int sec, start_sec, timeout;
  495: 
  496: 	if (bootverbose)
  497: 	        printf("Calibrating clock(s) ... ");
  498: 	if (!(rtcin(RTC_STATUSD) & RTCSD_PWR))
  499: 		goto fail;
  500: 	timeout = 100000000;
  501: 
  502: 	/* Read the mc146818A seconds counter. */
  503: 	for (;;) {
  504: 		if (!(rtcin(RTC_STATUSA) & RTCSA_TUP)) {
  505: 			sec = rtcin(RTC_SEC);
  506: 			break;
  507: 		}
  508: 		if (--timeout == 0)
  509: 			goto fail;
  510: 	}
  511: 
  512: 	/* Wait for the mC146818A seconds counter to change. */
  513: 	start_sec = sec;
  514: 	for (;;) {
  515: 		if (!(rtcin(RTC_STATUSA) & RTCSA_TUP)) {
  516: 			sec = rtcin(RTC_SEC);
  517: 			if (sec != start_sec)
  518: 				break;
  519: 		}
  520: 		if (--timeout == 0)
  521: 			goto fail;
  522: 	}
  523: 
  524: 	/* Start keeping track of the i8254 counter. */
  525: 	prev_count = cputimer_count();
  526: 	tot_count = 0;
  527: 
  528: 	if (tsc_present) 
  529: 		old_tsc = rdtsc();
  530: 	else
  531: 		old_tsc = 0;		/* shut up gcc */
  532: 
  533: 	/*
  534: 	 * Wait for the mc146818A seconds counter to change.  Read the i8254
  535: 	 * counter for each iteration since this is convenient and only
  536: 	 * costs a few usec of inaccuracy. The timing of the final reads
  537: 	 * of the counters almost matches the timing of the initial reads,
  538: 	 * so the main cause of inaccuracy is the varying latency from 
  539: 	 * inside getit() or rtcin(RTC_STATUSA) to the beginning of the
  540: 	 * rtcin(RTC_SEC) that returns a changed seconds count.  The
  541: 	 * maximum inaccuracy from this cause is < 10 usec on 486's.
  542: 	 */
  543: 	start_sec = sec;
  544: 	for (;;) {
  545: 		if (!(rtcin(RTC_STATUSA) & RTCSA_TUP))
  546: 			sec = rtcin(RTC_SEC);
  547: 		count = cputimer_count();
  548: 		tot_count += (int)(count - prev_count);
  549: 		prev_count = count;
  550: 		if (sec != start_sec)
  551: 			break;
  552: 		if (--timeout == 0)
  553: 			goto fail;
  554: 	}
  555: 
  556: 	/*
  557: 	 * Read the cpu cycle counter.  The timing considerations are
  558: 	 * similar to those for the i8254 clock.
  559: 	 */
  560: 	if (tsc_present) 
  561: 		tsc_freq = rdtsc() - old_tsc;
  562: 
  563: 	if (bootverbose) {
  564: 		if (tsc_present)
  565: 		        printf("TSC clock: %u Hz, ", tsc_freq);
  566: 	        printf("i8254 clock: %u Hz\n", tot_count);
  567: 	}
  568: 	return (tot_count);
  569: 
  570: fail:
  571: 	if (bootverbose)
  572: 	        printf("failed, using default i8254 clock of %u Hz\n",
  573: 		       cputimer_freq);
  574: 	return (cputimer_freq);
  575: }
  576: 
  577: static void
  578: i8254_restore(void)
  579: {
  580: 	timer0_state = ACQUIRED;
  581: 	timer1_state = ACQUIRED;
  582: 	clock_lock();
  583: 	outb(TIMER_MODE, TIMER_SEL0 | TIMER_SWSTROBE | TIMER_16BIT);
  584: 	outb(TIMER_CNTR0, 2);	/* lsb */
  585: 	outb(TIMER_CNTR0, 0);	/* msb */
  586: 	outb(TIMER_MODE, TIMER_SELX | TIMER_RATEGEN | TIMER_16BIT);
  587: 	outb(TIMER_CNTRX, 0);	/* lsb */
  588: 	outb(TIMER_CNTRX, 0);	/* msb */
  589: 	outb(IO_PPI, inb(IO_PPI) | 1);	/* bit 0: enable gate, bit 1: spkr */
  590: 	clock_unlock();
  591: }
  592: 
  593: static void
  594: rtc_restore(void)
  595: {
  596: 	/* Restore all of the RTC's "status" (actually, control) registers. */
  597: 	writertc(RTC_STATUSB, RTCSB_24HR);
  598: 	writertc(RTC_STATUSA, rtc_statusa);
  599: 	writertc(RTC_STATUSB, rtc_statusb);
  600: }
  601: 
  602: /*
  603:  * Restore all the timers non-atomically (XXX: should be atomically).
  604:  *
  605:  * This function is called from apm_default_resume() to restore all the timers.
  606:  * This should not be necessary, but there are broken laptops that do not
  607:  * restore all the timers on resume.
  608:  */
  609: void
  610: timer_restore(void)
  611: {
  612: 	i8254_restore();		/* restore timer_freq and hz */
  613: 	rtc_restore();			/* reenable RTC interrupts */
  614: }
  615: 
  616: /*
  617:  * Initialize 8254 timer 0 early so that it can be used in DELAY().
  618:  */
  619: void
  620: startrtclock()
  621: {
  622: 	u_int delta, freq;
  623: 
  624: 	/* 
  625: 	 * Can we use the TSC?
  626: 	 */
  627: 	if (cpu_feature & CPUID_TSC)
  628: 		tsc_present = 1;
  629: 	else
  630: 		tsc_present = 0;
  631: 
  632: 	/*
  633: 	 * Initial RTC state, don't do anything unexpected
  634: 	 */
  635: 	writertc(RTC_STATUSA, rtc_statusa);
  636: 	writertc(RTC_STATUSB, RTCSB_24HR);
  637: 
  638: 	/*
  639: 	 * Set the 8254 timer0 in TIMER_SWSTROBE mode and cause it to 
  640: 	 * generate an interrupt, which we will ignore for now.
  641: 	 *
  642: 	 * Set the 8254 timer1 in TIMER_RATEGEN mode and load 0x0000
  643: 	 * (so it counts a full 2^16 and repeats).  We will use this timer
  644: 	 * for our counting.
  645: 	 */
  646: 	i8254_restore();
  647: 	freq = calibrate_clocks();
  648: #ifdef CLK_CALIBRATION_LOOP
  649: 	if (bootverbose) {
  650: 		printf(
  651: 		"Press a key on the console to abort clock calibration\n");
  652: 		while (cncheckc() == -1)
  653: 			calibrate_clocks();
  654: 	}
  655: #endif
  656: 
  657: 	/*
  658: 	 * Use the calibrated i8254 frequency if it seems reasonable.
  659: 	 * Otherwise use the default, and don't use the calibrated i586
  660: 	 * frequency.
  661: 	 */
  662: 	delta = freq > cputimer_freq ? 
  663: 			freq - cputimer_freq : cputimer_freq - freq;
  664: 	if (delta < cputimer_freq / 100) {
  665: #ifndef CLK_USE_I8254_CALIBRATION
  666: 		if (bootverbose)
  667: 			printf(
  668: "CLK_USE_I8254_CALIBRATION not specified - using default frequency\n");
  669: 		freq = cputimer_freq;
  670: #endif
  671: 		cputimer_freq = freq;
  672: 		cputimer_freq64_usec = (1000000LL << 32) / freq;
  673: 		cputimer_freq64_nsec = (1000000000LL << 32) / freq;
  674: 	} else {
  675: 		if (bootverbose)
  676: 			printf(
  677: 		    "%d Hz differs from default of %d Hz by more than 1%%\n",
  678: 			       freq, cputimer_freq);
  679: 		tsc_freq = 0;
  680: 	}
  681: 
  682: #ifndef CLK_USE_TSC_CALIBRATION
  683: 	if (tsc_freq != 0) {
  684: 		if (bootverbose)
  685: 			printf(
  686: "CLK_USE_TSC_CALIBRATION not specified - using old calibration method\n");
  687: 		tsc_freq = 0;
  688: 	}
  689: #endif
  690: 	if (tsc_present && tsc_freq == 0) {
  691: 		/*
  692: 		 * Calibration of the i586 clock relative to the mc146818A
  693: 		 * clock failed.  Do a less accurate calibration relative
  694: 		 * to the i8254 clock.
  695: 		 */
  696: 		u_int64_t old_tsc = rdtsc();
  697: 
  698: 		DELAY(1000000);
  699: 		tsc_freq = rdtsc() - old_tsc;
  700: #ifdef CLK_USE_TSC_CALIBRATION
  701: 		if (bootverbose)
  702: 			printf("TSC clock: %u Hz (Method B)\n", tsc_freq);
  703: #endif
  704: 	}
  705: 
  706: #if !defined(SMP)
  707: 	/*
  708: 	 * We can not use the TSC in SMP mode, until we figure out a
  709: 	 * cheap (impossible), reliable and precise (yeah right!)  way
  710: 	 * to synchronize the TSCs of all the CPUs.
  711: 	 * Curse Intel for leaving the counter out of the I/O APIC.
  712: 	 */
  713: 
  714: #if NAPM > 0
  715: 	/*
  716: 	 * We can not use the TSC if we support APM. Precise timekeeping
  717: 	 * on an APM'ed machine is at best a fools pursuit, since 
  718: 	 * any and all of the time spent in various SMM code can't 
  719: 	 * be reliably accounted for.  Reading the RTC is your only
  720: 	 * source of reliable time info.  The i8254 looses too of course
  721: 	 * but we need to have some kind of time...
  722: 	 * We don't know at this point whether APM is going to be used
  723: 	 * or not, nor when it might be activated.  Play it safe.
  724: 	 */
  725: 	return;
  726: #endif /* NAPM > 0 */
  727: 
  728: #endif /* !defined(SMP) */
  729: }
  730: 
  731: /*
  732:  * Initialize the time of day register, based on the time base which is, e.g.
  733:  * from a filesystem.
  734:  */
  735: void
  736: inittodr(time_t base)
  737: {
  738: 	unsigned long	sec, days;
  739: 	int		yd;
  740: 	int		year, month;
  741: 	int		y, m;
  742: 	struct timespec ts;
  743: 
  744: 	if (base) {
  745: 		ts.tv_sec = base;
  746: 		ts.tv_nsec = 0;
  747: 		set_timeofday(&ts);
  748: 	}
  749: 
  750: 	/* Look if we have a RTC present and the time is valid */
  751: 	if (!(rtcin(RTC_STATUSD) & RTCSD_PWR))
  752: 		goto wrong_time;
  753: 
  754: 	/* wait for time update to complete */
  755: 	/* If RTCSA_TUP is zero, we have at least 244us before next update */
  756: 	crit_enter();
  757: 	while (rtcin(RTC_STATUSA) & RTCSA_TUP) {
  758: 		crit_exit();
  759: 		crit_enter();
  760: 	}
  761: 
  762: 	days = 0;
  763: #ifdef USE_RTC_CENTURY
  764: 	year = readrtc(RTC_YEAR) + readrtc(RTC_CENTURY) * 100;
  765: #else
  766: 	year = readrtc(RTC_YEAR) + 1900;
  767: 	if (year < 1970)
  768: 		year += 100;
  769: #endif
  770: 	if (year < 1970) {
  771: 		crit_exit();
  772: 		goto wrong_time;
  773: 	}
  774: 	month = readrtc(RTC_MONTH);
  775: 	for (m = 1; m < month; m++)
  776: 		days += daysinmonth[m-1];
  777: 	if ((month > 2) && LEAPYEAR(year))
  778: 		days ++;
  779: 	days += readrtc(RTC_DAY) - 1;
  780: 	yd = days;
  781: 	for (y = 1970; y < year; y++)
  782: 		days += DAYSPERYEAR + LEAPYEAR(y);
  783: 	sec = ((( days * 24 +
  784: 		  readrtc(RTC_HRS)) * 60 +
  785: 		  readrtc(RTC_MIN)) * 60 +
  786: 		  readrtc(RTC_SEC));
  787: 	/* sec now contains the number of seconds, since Jan 1 1970,
  788: 	   in the local time zone */
  789: 
  790: 	sec += tz.tz_minuteswest * 60 + (wall_cmos_clock ? adjkerntz : 0);
  791: 
  792: 	y = time_second - sec;
  793: 	if (y <= -2 || y >= 2) {
  794: 		/* badly off, adjust it */
  795: 		ts.tv_sec = sec;
  796: 		ts.tv_nsec = 0;
  797: 		set_timeofday(&ts);
  798: 	}
  799: 	crit_exit();
  800: 	return;
  801: 
  802: wrong_time:
  803: 	printf("Invalid time in real time clock.\n");
  804: 	printf("Check and reset the date immediately!\n");
  805: }
  806: 
  807: /*
  808:  * Write system time back to RTC
  809:  */
  810: void
  811: resettodr()
  812: {
  813: 	struct timeval tv;
  814: 	unsigned long tm;
  815: 	int m;
  816: 	int y;
  817: 
  818: 	if (disable_rtc_set)
  819: 		return;
  820: 
  821: 	microtime(&tv);
  822: 	tm = tv.tv_sec;
  823: 
  824: 	crit_enter();
  825: 	/* Disable RTC updates and interrupts. */
  826: 	writertc(RTC_STATUSB, RTCSB_HALT | RTCSB_24HR);
  827: 
  828: 	/* Calculate local time to put in RTC */
  829: 
  830: 	tm -= tz.tz_minuteswest * 60 + (wall_cmos_clock ? adjkerntz : 0);
  831: 
  832: 	writertc(RTC_SEC, bin2bcd(tm%60)); tm /= 60;	/* Write back Seconds */
  833: 	writertc(RTC_MIN, bin2bcd(tm%60)); tm /= 60;	/* Write back Minutes */
  834: 	writertc(RTC_HRS, bin2bcd(tm%24)); tm /= 24;	/* Write back Hours   */
  835: 
  836: 	/* We have now the days since 01-01-1970 in tm */
  837: 	writertc(RTC_WDAY, (tm+4)%7);			/* Write back Weekday */
  838: 	for (y = 1970, m = DAYSPERYEAR + LEAPYEAR(y);
  839: 	     tm >= m;
  840: 	     y++,      m = DAYSPERYEAR + LEAPYEAR(y))
  841: 	     tm -= m;
  842: 
  843: 	/* Now we have the years in y and the day-of-the-year in tm */
  844: 	writertc(RTC_YEAR, bin2bcd(y%100));		/* Write back Year    */
  845: #ifdef USE_RTC_CENTURY
  846: 	writertc(RTC_CENTURY, bin2bcd(y/100));		/* ... and Century    */
  847: #endif
  848: 	for (m = 0; ; m++) {
  849: 		int ml;
  850: 
  851: 		ml = daysinmonth[m];
  852: 		if (m == 1 && LEAPYEAR(y))
  853: 			ml++;
  854: 		if (tm < ml)
  855: 			break;
  856: 		tm -= ml;
  857: 	}
  858: 
  859: 	writertc(RTC_MONTH, bin2bcd(m + 1));            /* Write back Month   */
  860: 	writertc(RTC_DAY, bin2bcd(tm + 1));             /* Write back Month Day */
  861: 
  862: 	/* Reenable RTC updates and interrupts. */
  863: 	writertc(RTC_STATUSB, rtc_statusb);
  864: 	crit_exit();
  865: }
  866: 
  867: 
  868: /*
  869:  * Start both clocks running.  DragonFly note: the stat clock is no longer
  870:  * used.  Instead, 8254 based systimers are used for all major clock
  871:  * interrupts.  statclock_disable is set by default.
  872:  */
  873: void
  874: cpu_initclocks()
  875: {
  876: 	int diag;
  877: #ifdef APIC_IO
  878: 	int apic_8254_trial;
  879: 	struct intrec *clkdesc;
  880: #endif /* APIC_IO */
  881: 
  882: 	if (statclock_disable) {
  883: 		/*
  884: 		 * The stat interrupt mask is different without the
  885: 		 * statistics clock.  Also, don't set the interrupt
  886: 		 * flag which would normally cause the RTC to generate
  887: 		 * interrupts.
  888: 		 */
  889: 		stat_imask = HWI_MASK | SWI_MASK;
  890: 		rtc_statusb = RTCSB_24HR;
  891: 	} else {
  892: 	        /* Setting stathz to nonzero early helps avoid races. */
  893: 		stathz = RTC_NOPROFRATE;
  894: 		profhz = RTC_PROFRATE;
  895:         }
  896: 
  897: 	/* Finish initializing 8253 timer 0. */
  898: #ifdef APIC_IO
  899: 
  900: 	apic_8254_intr = isa_apic_irq(0);
  901: 	apic_8254_trial = 0;
  902: 	if (apic_8254_intr >= 0 ) {
  903: 		if (apic_int_type(0, 0) == 3)
  904: 			apic_8254_trial = 1;
  905: 	} else {
  906: 		/* look for ExtInt on pin 0 */
  907: 		if (apic_int_type(0, 0) == 3) {
  908: 			apic_8254_intr = apic_irq(0, 0);
  909: 			setup_8254_mixed_mode();
  910: 		} else 
  911: 			panic("APIC_IO: Cannot route 8254 interrupt to CPU");
  912: 	}
  913: 
  914: 	clkdesc = inthand_add("clk", apic_8254_intr, (inthand2_t *)clkintr,
  915: 			      NULL, &clk_imask, INTR_EXCL | INTR_FAST);
  916: 	INTREN(1 << apic_8254_intr);
  917: 	
  918: #else /* APIC_IO */
  919: 
  920: 	inthand_add("clk", 0, (inthand2_t *)clkintr, NULL, &clk_imask,
  921: 		    INTR_EXCL | INTR_FAST);
  922: 	INTREN(IRQ0);
  923: 
  924: #endif /* APIC_IO */
  925: 
  926: 	/* Initialize RTC. */
  927: 	writertc(RTC_STATUSA, rtc_statusa);
  928: 	writertc(RTC_STATUSB, RTCSB_24HR);
  929: 
  930: 	if (statclock_disable == 0) {
  931: 		diag = rtcin(RTC_DIAG);
  932: 		if (diag != 0)
  933: 			printf("RTC BIOS diagnostic error %b\n", diag, RTCDG_BITS);
  934: 
  935: #ifdef APIC_IO
  936: 		if (isa_apic_irq(8) != 8)
  937: 			panic("APIC RTC != 8");
  938: #endif /* APIC_IO */
  939: 
  940: 		inthand_add("rtc", 8, (inthand2_t *)rtcintr, NULL, &stat_imask,
  941: 			    INTR_EXCL | INTR_FAST);
  942: 
  943: #ifdef APIC_IO
  944: 		INTREN(APIC_IRQ8);
  945: #else
  946: 		INTREN(IRQ8);
  947: #endif /* APIC_IO */
  948: 
  949: 		writertc(RTC_STATUSB, rtc_statusb);
  950: 	}
  951: 
  952: #ifdef APIC_IO
  953: 	if (apic_8254_trial) {
  954: 		sysclock_t base;
  955: 		int lastcnt = read_intr_count(apic_8254_intr);
  956: 
  957: 		/*
  958: 		 * XXX this assumes the 8254 is the cpu timer.  Force an
  959: 		 * 8254 Timer0 interrupt and wait 1/100s for it to happen,
  960: 		 * then see if we got it.
  961: 		 */
  962: 		printf("APIC_IO: Testing 8254 interrupt delivery\n");
  963: 		cputimer_intr_reload(2);	/* XXX assumes 8254 */
  964: 		base = cputimer_count();
  965: 		while (cputimer_count() - base < cputimer_freq / 100)
  966: 			;	/* nothing */
  967: 		if (read_intr_count(apic_8254_intr) - lastcnt == 0) {
  968: 			/* 
  969: 			 * The MP table is broken.
  970: 			 * The 8254 was not connected to the specified pin
  971: 			 * on the IO APIC.
  972: 			 * Workaround: Limited variant of mixed mode.
  973: 			 */
  974: 			INTRDIS(1 << apic_8254_intr);
  975: 			inthand_remove(clkdesc);
  976: 			printf("APIC_IO: Broken MP table detected: "
  977: 			       "8254 is not connected to "
  978: 			       "IOAPIC #%d intpin %d\n",
  979: 			       int_to_apicintpin[apic_8254_intr].ioapic,
  980: 			       int_to_apicintpin[apic_8254_intr].int_pin);
  981: 			/* 
  982: 			 * Revoke current ISA IRQ 0 assignment and 
  983: 			 * configure a fallback interrupt routing from
  984: 			 * the 8254 Timer via the 8259 PIC to the
  985: 			 * an ExtInt interrupt line on IOAPIC #0 intpin 0.
  986: 			 * We reuse the low level interrupt handler number.
  987: 			 */
  988: 			if (apic_irq(0, 0) < 0) {
  989: 				revoke_apic_irq(apic_8254_intr);
  990: 				assign_apic_irq(0, 0, apic_8254_intr);
  991: 			}
  992: 			apic_8254_intr = apic_irq(0, 0);
  993: 			setup_8254_mixed_mode();
  994: 			inthand_add("clk", apic_8254_intr,
  995: 				    (inthand2_t *)clkintr,
  996: 				    NULL, &clk_imask, INTR_EXCL | INTR_FAST);
  997: 			INTREN(1 << apic_8254_intr);
  998: 		}
  999: 		
 1000: 	}
 1001: 	if (apic_int_type(0, 0) != 3 ||
 1002: 	    int_to_apicintpin[apic_8254_intr].ioapic != 0 ||
 1003: 	    int_to_apicintpin[apic_8254_intr].int_pin != 0) {
 1004: 		printf("APIC_IO: routing 8254 via IOAPIC #%d intpin %d\n",
 1005: 		       int_to_apicintpin[apic_8254_intr].ioapic,
 1006: 		       int_to_apicintpin[apic_8254_intr].int_pin);
 1007: 	} else {
 1008: 		printf("APIC_IO: "
 1009: 		       "routing 8254 via 8259 and IOAPIC #0 intpin 0\n");
 1010: 	}
 1011: #endif
 1012: 	
 1013: }
 1014: 
 1015: #ifdef APIC_IO
 1016: static u_long
 1017: read_intr_count(int vec)
 1018: {
 1019: 	u_long *up;
 1020: 	up = intr_countp[vec];
 1021: 	if (up)
 1022: 		return *up;
 1023: 	return 0UL;
 1024: }
 1025: 
 1026: static void 
 1027: setup_8254_mixed_mode()
 1028: {
 1029: 	/*
 1030: 	 * Allow 8254 timer to INTerrupt 8259:
 1031: 	 *  re-initialize master 8259:
 1032: 	 *   reset; prog 4 bytes, single ICU, edge triggered
 1033: 	 */
 1034: 	outb(IO_ICU1, 0x13);
 1035: 	outb(IO_ICU1 + 1, NRSVIDT);	/* start vector (unused) */
 1036: 	outb(IO_ICU1 + 1, 0x00);	/* ignore slave */
 1037: 	outb(IO_ICU1 + 1, 0x03);	/* auto EOI, 8086 */
 1038: 	outb(IO_ICU1 + 1, 0xfe);	/* unmask INT0 */
 1039: 	
 1040: 	/* program IO APIC for type 3 INT on INT0 */
 1041: 	if (ext_int_setup(0, 0) < 0)
 1042: 		panic("8254 redirect via APIC pin0 impossible!");
 1043: }
 1044: #endif
 1045: 
 1046: void
 1047: setstatclockrate(int newhz)
 1048: {
 1049: 	if (newhz == RTC_PROFRATE)
 1050: 		rtc_statusa = RTCSA_DIVIDER | RTCSA_PROF;
 1051: 	else
 1052: 		rtc_statusa = RTCSA_DIVIDER | RTCSA_NOPROF;
 1053: 	writertc(RTC_STATUSA, rtc_statusa);
 1054: }
 1055: 
 1056: #if 0
 1057: static unsigned
 1058: tsc_get_timecount(struct timecounter *tc)
 1059: {
 1060: 	return (rdtsc());
 1061: }
 1062: #endif
 1063: 
 1064: #ifdef KERN_TIMESTAMP
 1065: #define KERN_TIMESTAMP_SIZE 16384
 1066: static u_long tsc[KERN_TIMESTAMP_SIZE] ;
 1067: SYSCTL_OPAQUE(_debug, OID_AUTO, timestamp, CTLFLAG_RD, tsc,
 1068: 	sizeof(tsc), "LU", "Kernel timestamps");
 1069: void  
 1070: _TSTMP(u_int32_t x)
 1071: {
 1072: 	static int i;
 1073: 
 1074: 	tsc[i] = (u_int32_t)rdtsc();
 1075: 	tsc[i+1] = x;
 1076: 	i = i + 2;
 1077: 	if (i >= KERN_TIMESTAMP_SIZE)
 1078: 		i = 0;
 1079: 	tsc[i] = 0; /* mark last entry */
 1080: }
 1081: #endif /* KERN_TIMESTAMP */
 1082: