tsc.c revision 19173
14Srgrimes/*- 24Srgrimes * Copyright (c) 1990 The Regents of the University of California. 34Srgrimes * All rights reserved. 44Srgrimes * 54Srgrimes * This code is derived from software contributed to Berkeley by 64Srgrimes * William Jolitz and Don Ahn. 74Srgrimes * 84Srgrimes * Redistribution and use in source and binary forms, with or without 94Srgrimes * modification, are permitted provided that the following conditions 104Srgrimes * are met: 114Srgrimes * 1. Redistributions of source code must retain the above copyright 124Srgrimes * notice, this list of conditions and the following disclaimer. 134Srgrimes * 2. Redistributions in binary form must reproduce the above copyright 144Srgrimes * notice, this list of conditions and the following disclaimer in the 154Srgrimes * documentation and/or other materials provided with the distribution. 164Srgrimes * 3. All advertising materials mentioning features or use of this software 174Srgrimes * must display the following acknowledgement: 184Srgrimes * This product includes software developed by the University of 194Srgrimes * California, Berkeley and its contributors. 204Srgrimes * 4. Neither the name of the University nor the names of its contributors 214Srgrimes * may be used to endorse or promote products derived from this software 224Srgrimes * without specific prior written permission. 234Srgrimes * 244Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 254Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 264Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 274Srgrimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 284Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 294Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 304Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 314Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 324Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 334Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 344Srgrimes * SUCH DAMAGE. 354Srgrimes * 36619Srgrimes * from: @(#)clock.c 7.2 (Berkeley) 5/12/91 3719173Sbde * $Id: clock.c,v 1.70 1996/10/09 19:47:31 bde Exp $ 384Srgrimes */ 394Srgrimes 403185Ssos/* 4119173Sbde * Routines to handle clock hardware. 4219173Sbde */ 4319173Sbde 4419173Sbde/* 453185Ssos * inittodr, settodr and support routines written 463185Ssos * by Christoph Robitschko <chmr@edvz.tu-graz.ac.at> 473185Ssos * 483185Ssos * reintroduced and updated by Chris Stenton <chris@gnome.co.uk> 8/10/94 492913Sache */ 502913Sache 5116299Spst#include "opt_clock.h" 5218842Sbde#include "opt_cpu.h" 5313228Swollman 542056Swollman#include <sys/param.h> 552056Swollman#include <sys/systm.h> 562056Swollman#include <sys/time.h> 572056Swollman#include <sys/kernel.h> 5815508Sbde#include <sys/sysctl.h> 5915508Sbde 604180Sbde#include <machine/clock.h> 6115508Sbde#ifdef CLK_CALIBRATION_LOOP 6215508Sbde#include <machine/cons.h> 6315508Sbde#endif 6415508Sbde#include <machine/cpu.h> 652056Swollman#include <machine/frame.h> 6615508Sbde 672056Swollman#include <i386/isa/icu.h> 682056Swollman#include <i386/isa/isa.h> 697090Sbde#include <i386/isa/isa_device.h> 702056Swollman#include <i386/isa/rtc.h> 712056Swollman#include <i386/isa/timerreg.h> 724Srgrimes 732873Sbde/* 742873Sbde * 32-bit time_t's can't reach leap years before 1904 or after 2036, so we 752873Sbde * can use a simple formula for leap years. 762873Sbde */ 772873Sbde#define LEAPYEAR(y) ((u_int)(y) % 4 == 0) 782913Sache#define DAYSPERYEAR (31+28+31+30+31+30+31+31+30+31+30+31) 792873Sbde 8015508Sbde#define TIMER_DIV(x) ((timer_freq + (x) / 2) / (x)) 814Srgrimes 824180Sbde/* 834180Sbde * Time in timer cycles that it takes for microtime() to disable interrupts 844180Sbde * and latch the count. microtime() currently uses "cli; outb ..." so it 854180Sbde * normally takes less than 2 timer cycles. Add a few for cache misses. 864180Sbde * Add a few more to allow for latency in bogus calls to microtime() with 874180Sbde * interrupts already disabled. 884180Sbde */ 894180Sbde#define TIMER0_LATCH_COUNT 20 904180Sbde 914180Sbde/* 9217236Sjoerg * Maximum frequency that we are willing to allow for timer0. Must be 9317231Sjoerg * low enough to guarantee that the timer interrupt handler returns 9417231Sjoerg * before the next timer interrupt. Must result in a lower TIMER_DIV 9517231Sjoerg * value than TIMER0_LATCH_COUNT so that we don't have to worry about 9617231Sjoerg * underflow in the calculation of timer0_overflow_threshold. 974180Sbde */ 9817231Sjoerg#define TIMER0_MAX_FREQ 20000 994180Sbde 10015045Sacheint adjkerntz; /* local offset from GMT in seconds */ 10115045Sacheint disable_rtc_set; /* disable resettodr() if != 0 */ 1028448Sbdeu_int idelayed; 10313000Sdg#if defined(I586_CPU) || defined(I686_CPU) 10419173Sbdeu_int i586_ctr_bias; 10517353Sbdeu_int i586_ctr_comultiplier; 10617353Sbdeu_int i586_ctr_freq; 10717353Sbdeu_int i586_ctr_multiplier; 1082017Swollman#endif 10915345Snateint statclock_disable; 1105291Sbdeu_int stat_imask = SWI_CLOCK_MASK; 11117236Sjoerg#ifdef TIMER_FREQ 11217236Sjoergu_int timer_freq = TIMER_FREQ; 11317236Sjoerg#else 11417236Sjoergu_int timer_freq = 1193182; 11517236Sjoerg#endif 11619173Sbdeint timer0_max_count; 11719173Sbdeu_int timer0_overflow_threshold; 11819173Sbdeu_int timer0_prescaler_count; 11919173Sbdeint wall_cmos_clock; /* wall CMOS clock assumed if != 0 */ 1201390Ssos 1214180Sbdestatic int beeping = 0; 1225291Sbdestatic u_int clk_imask = HWI_MASK | SWI_MASK; 1234180Sbdestatic const u_char daysinmonth[] = {31,28,31,30,31,30,31,31,30,31,30,31}; 12419173Sbdestatic u_int hardclock_max_count; 1254180Sbde/* 1264180Sbde * XXX new_function and timer_func should not handle clockframes, but 1274180Sbde * timer_func currently needs to hold hardclock to handle the 1284180Sbde * timer0_state == 0 case. We should use register_intr()/unregister_intr() 1294180Sbde * to switch between clkintr() and a slightly different timerintr(). 1304180Sbde */ 13119173Sbdestatic void (*new_function) __P((struct clockframe *frame)); 13219173Sbdestatic u_int new_rate; 1334180Sbdestatic u_char rtc_statusa = RTCSA_DIVIDER | RTCSA_NOPROF; 13415345Snatestatic u_char rtc_statusb = RTCSB_24HR | RTCSB_PINTR; 13517231Sjoerg 13617231Sjoerg/* Values for timerX_state: */ 13717236Sjoerg#define RELEASED 0 13817236Sjoerg#define RELEASE_PENDING 1 13917236Sjoerg#define ACQUIRED 2 14017236Sjoerg#define ACQUIRE_PENDING 3 14117231Sjoerg 14217231Sjoergstatic u_char timer0_state; 14317231Sjoergstatic u_char timer2_state; 14419173Sbdestatic void (*timer_func) __P((struct clockframe *frame)) = hardclock; 1454180Sbde 14617353Sbde#if defined(I586_CPU) || defined(I686_CPU) 14717353Sbdestatic void set_i586_ctr_freq(u_int i586_freq, u_int i8254_freq); 14817353Sbde#endif 14917353Sbde 15012724Sphkstatic void 1513185Ssosclkintr(struct clockframe frame) 1522074Swollman{ 1531549Srgrimes timer_func(&frame); 1541442Ssos switch (timer0_state) { 15517236Sjoerg 15617231Sjoerg case RELEASED: 1578448Sbde setdelayed(); 1581442Ssos break; 15917236Sjoerg 16017231Sjoerg case ACQUIRED: 1614180Sbde if ((timer0_prescaler_count += timer0_max_count) 1624180Sbde >= hardclock_max_count) { 1631549Srgrimes hardclock(&frame); 1648448Sbde setdelayed(); 1654180Sbde timer0_prescaler_count -= hardclock_max_count; 1661390Ssos } 1671442Ssos break; 16817236Sjoerg 16917231Sjoerg case ACQUIRE_PENDING: 1708448Sbde setdelayed(); 1714180Sbde timer0_max_count = TIMER_DIV(new_rate); 1724180Sbde timer0_overflow_threshold = 1734180Sbde timer0_max_count - TIMER0_LATCH_COUNT; 1741442Ssos disable_intr(); 1754180Sbde outb(TIMER_MODE, TIMER_SEL0 | TIMER_RATEGEN | TIMER_16BIT); 1764180Sbde outb(TIMER_CNTR0, timer0_max_count & 0xff); 1774180Sbde outb(TIMER_CNTR0, timer0_max_count >> 8); 1781442Ssos enable_intr(); 1794180Sbde timer0_prescaler_count = 0; 1801442Ssos timer_func = new_function; 18117231Sjoerg timer0_state = ACQUIRED; 1821442Ssos break; 18317236Sjoerg 18417231Sjoerg case RELEASE_PENDING: 1854180Sbde if ((timer0_prescaler_count += timer0_max_count) 1864180Sbde >= hardclock_max_count) { 1871549Srgrimes hardclock(&frame); 1888448Sbde setdelayed(); 1895291Sbde timer0_max_count = hardclock_max_count; 1904180Sbde timer0_overflow_threshold = 1914180Sbde timer0_max_count - TIMER0_LATCH_COUNT; 1921442Ssos disable_intr(); 1934180Sbde outb(TIMER_MODE, 1944180Sbde TIMER_SEL0 | TIMER_RATEGEN | TIMER_16BIT); 1954180Sbde outb(TIMER_CNTR0, timer0_max_count & 0xff); 1964180Sbde outb(TIMER_CNTR0, timer0_max_count >> 8); 1971442Ssos enable_intr(); 1984180Sbde /* 1994180Sbde * See microtime.s for this magic. 2004180Sbde */ 20117194Sbde time.tv_usec += (27465 * 2024180Sbde (timer0_prescaler_count - hardclock_max_count)) 2034180Sbde >> 15; 2044180Sbde if (time.tv_usec >= 1000000) 2054180Sbde time.tv_usec -= 1000000; 2064180Sbde timer0_prescaler_count = 0; 20717231Sjoerg timer_func = hardclock; 20817231Sjoerg timer0_state = RELEASED; 2091442Ssos } 2101442Ssos break; 2111442Ssos } 2121390Ssos} 2131390Ssos 21417231Sjoerg/* 21517236Sjoerg * The acquire and release functions must be called at ipl >= splclock(). 21617231Sjoerg */ 2171390Ssosint 2184180Sbdeacquire_timer0(int rate, void (*function) __P((struct clockframe *frame))) 2191390Ssos{ 22017231Sjoerg static int old_rate; 22117231Sjoerg 22217231Sjoerg if (rate <= 0 || rate > TIMER0_MAX_FREQ) 22317231Sjoerg return (-1); 22417231Sjoerg switch (timer0_state) { 22517231Sjoerg 22617236Sjoerg case RELEASED: 22717236Sjoerg timer0_state = ACQUIRE_PENDING; 22817236Sjoerg break; 22917231Sjoerg 23017236Sjoerg case RELEASE_PENDING: 23117236Sjoerg if (rate != old_rate) 23217236Sjoerg return (-1); 23317236Sjoerg /* 23417236Sjoerg * The timer has been released recently, but is being 23517236Sjoerg * re-acquired before the release completed. In this 23617236Sjoerg * case, we simply reclaim it as if it had not been 23717236Sjoerg * released at all. 23817236Sjoerg */ 23917236Sjoerg timer0_state = ACQUIRED; 24017236Sjoerg break; 24117236Sjoerg 24217236Sjoerg default: 24317236Sjoerg return (-1); /* busy */ 24417231Sjoerg } 2451442Ssos new_function = function; 24617231Sjoerg old_rate = new_rate = rate; 24717231Sjoerg return (0); 2481390Ssos} 2491390Ssos 2501390Ssosint 2511390Ssosacquire_timer2(int mode) 2521390Ssos{ 25317231Sjoerg 25417231Sjoerg if (timer2_state != RELEASED) 25517231Sjoerg return (-1); 25617231Sjoerg timer2_state = ACQUIRED; 25717236Sjoerg 25817236Sjoerg /* 25917236Sjoerg * This access to the timer registers is as atomic as possible 26017236Sjoerg * because it is a single instruction. We could do better if we 26117236Sjoerg * knew the rate. Use of splclock() limits glitches to 10-100us, 26217236Sjoerg * and this is probably good enough for timer2, so we aren't as 26317236Sjoerg * careful with it as with timer0. 26417236Sjoerg */ 26517236Sjoerg outb(TIMER_MODE, TIMER_SEL2 | (mode & 0x3f)); 26617236Sjoerg 26717231Sjoerg return (0); 2681390Ssos} 2691390Ssos 2701390Ssosint 2711390Ssosrelease_timer0() 2721390Ssos{ 27317231Sjoerg switch (timer0_state) { 27417231Sjoerg 27517236Sjoerg case ACQUIRED: 27617236Sjoerg timer0_state = RELEASE_PENDING; 27717236Sjoerg break; 27817231Sjoerg 27917236Sjoerg case ACQUIRE_PENDING: 28017236Sjoerg /* Nothing happened yet, release quickly. */ 28117236Sjoerg timer0_state = RELEASED; 28217236Sjoerg break; 28317236Sjoerg 28417236Sjoerg default: 28517236Sjoerg return (-1); 28617231Sjoerg } 28717231Sjoerg return (0); 2881390Ssos} 2891390Ssos 2901390Ssosint 2911390Ssosrelease_timer2() 2921390Ssos{ 29317231Sjoerg 29417231Sjoerg if (timer2_state != ACQUIRED) 29517231Sjoerg return (-1); 29617231Sjoerg timer2_state = RELEASED; 29717236Sjoerg outb(TIMER_MODE, TIMER_SEL2 | TIMER_SQWAVE | TIMER_16BIT); 29817231Sjoerg return (0); 2991390Ssos} 3001390Ssos 3013185Ssos/* 3023185Ssos * This routine receives statistical clock interrupts from the RTC. 3033185Ssos * As explained above, these occur at 128 interrupts per second. 3043185Ssos * When profiling, we receive interrupts at a rate of 1024 Hz. 3053185Ssos * 3063185Ssos * This does not actually add as much overhead as it sounds, because 3073185Ssos * when the statistical clock is active, the hardclock driver no longer 3083185Ssos * needs to keep (inaccurate) statistics on its own. This decouples 3093185Ssos * statistics gathering from scheduling interrupts. 3103185Ssos * 3113185Ssos * The RTC chip requires that we read status register C (RTC_INTR) 3123185Ssos * to acknowledge an interrupt, before it will generate the next one. 3133185Ssos */ 31412724Sphkstatic void 3153185Ssosrtcintr(struct clockframe frame) 3163185Ssos{ 3173185Ssos u_char stat; 3183185Ssos stat = rtcin(RTC_INTR); 3193185Ssos if(stat & RTCIR_PERIOD) { 3203185Ssos statclock(&frame); 3213185Ssos } 3223185Ssos} 3231390Ssos 32418297Sbde#include "opt_ddb.h" 3255291Sbde#ifdef DDB 32618297Sbde#include <ddb/ddb.h> 32718297Sbde 32818297SbdeDB_SHOW_COMMAND(rtc, rtc) 3293185Ssos{ 3305291Sbde printf("%02x/%02x/%02x %02x:%02x:%02x, A = %02x, B = %02x, C = %02x\n", 3315291Sbde rtcin(RTC_YEAR), rtcin(RTC_MONTH), rtcin(RTC_DAY), 3325291Sbde rtcin(RTC_HRS), rtcin(RTC_MIN), rtcin(RTC_SEC), 3335291Sbde rtcin(RTC_STATUSA), rtcin(RTC_STATUSB), rtcin(RTC_INTR)); 3343185Ssos} 33518297Sbde#endif /* DDB */ 3363185Ssos 3371390Ssosstatic int 33810268Sbdegetit(void) 3391390Ssos{ 34016428Sbde u_long ef; 3411390Ssos int high, low; 3421390Ssos 34316428Sbde ef = read_eflags(); 3441390Ssos disable_intr(); 34516428Sbde 34616428Sbde /* Select timer0 and latch counter value. */ 34719173Sbde outb(TIMER_MODE, TIMER_SEL0 | TIMER_LATCH); 34816428Sbde 3491390Ssos low = inb(TIMER_CNTR0); 3501390Ssos high = inb(TIMER_CNTR0); 35116428Sbde 35216428Sbde write_eflags(ef); 3531390Ssos return ((high << 8) | low); 3541390Ssos} 3551390Ssos 3562017Swollman/* 3571390Ssos * Wait "n" microseconds. 35815508Sbde * Relies on timer 1 counting down from (timer_freq / hz) 3591390Ssos * Note: timer had better have been programmed before this is first used! 3601390Ssos */ 3611390Ssosvoid 3621390SsosDELAY(int n) 3631390Ssos{ 3642873Sbde int prev_tick, tick, ticks_left, sec, usec; 3651390Ssos 3661390Ssos#ifdef DELAYDEBUG 3671390Ssos int getit_calls = 1; 3681390Ssos int n1; 3691390Ssos static int state = 0; 3701390Ssos 3711390Ssos if (state == 0) { 3721390Ssos state = 1; 3731390Ssos for (n1 = 1; n1 <= 10000000; n1 *= 10) 3741390Ssos DELAY(n1); 3751390Ssos state = 2; 3761390Ssos } 3771390Ssos if (state == 1) 3781390Ssos printf("DELAY(%d)...", n); 3791390Ssos#endif 3801390Ssos /* 3811390Ssos * Read the counter first, so that the rest of the setup overhead is 3821390Ssos * counted. Guess the initial overhead is 20 usec (on most systems it 3831390Ssos * takes about 1.5 usec for each of the i/o's in getit(). The loop 3841390Ssos * takes about 6 usec on a 486/33 and 13 usec on a 386/20. The 3851390Ssos * multiplications and divisions to scale the count take a while). 3861390Ssos */ 38710268Sbde prev_tick = getit(); 3881390Ssos n -= 20; 3891390Ssos /* 39015508Sbde * Calculate (n * (timer_freq / 1e6)) without using floating point 3911390Ssos * and without any avoidable overflows. 3921390Ssos */ 3931390Ssos sec = n / 1000000; 3941390Ssos usec = n - sec * 1000000; 39515508Sbde ticks_left = sec * timer_freq 39615508Sbde + usec * (timer_freq / 1000000) 39715508Sbde + usec * ((timer_freq % 1000000) / 1000) / 1000 39815508Sbde + usec * (timer_freq % 1000) / 1000000; 39915508Sbde if (n < 0) 40015508Sbde ticks_left = 0; /* XXX timer_freq is unsigned */ 4011390Ssos 4021390Ssos while (ticks_left > 0) { 40310268Sbde tick = getit(); 4041390Ssos#ifdef DELAYDEBUG 4051390Ssos ++getit_calls; 4061390Ssos#endif 4071390Ssos if (tick > prev_tick) 4084180Sbde ticks_left -= prev_tick - (tick - timer0_max_count); 4091390Ssos else 4101390Ssos ticks_left -= prev_tick - tick; 4111390Ssos prev_tick = tick; 4121390Ssos } 4131390Ssos#ifdef DELAYDEBUG 4141390Ssos if (state == 1) 4151390Ssos printf(" %d calls to getit() at %d usec each\n", 4161390Ssos getit_calls, (n + 5) / getit_calls); 4171390Ssos#endif 4181390Ssos} 4191390Ssos 4201390Ssosstatic void 4213185Ssossysbeepstop(void *chan) 4221390Ssos{ 4231390Ssos outb(IO_PPI, inb(IO_PPI)&0xFC); /* disable counter2 output to speaker */ 4241390Ssos release_timer2(); 4251390Ssos beeping = 0; 4261390Ssos} 4271390Ssos 4288876Srgrimesint 4291390Ssossysbeep(int pitch, int period) 4301390Ssos{ 43117231Sjoerg int x = splclock(); 4321390Ssos 4338876Srgrimes if (acquire_timer2(TIMER_SQWAVE|TIMER_16BIT)) 43417231Sjoerg if (!beeping) { 43517231Sjoerg /* Something else owns it. */ 43617231Sjoerg splx(x); 43717231Sjoerg return (-1); /* XXX Should be EBUSY, but nobody cares anyway. */ 43817231Sjoerg } 4391442Ssos disable_intr(); 4401390Ssos outb(TIMER_CNTR2, pitch); 4411390Ssos outb(TIMER_CNTR2, (pitch>>8)); 4421442Ssos enable_intr(); 4431390Ssos if (!beeping) { 44417231Sjoerg /* enable counter2 output to speaker */ 44517231Sjoerg outb(IO_PPI, inb(IO_PPI) | 3); 4461390Ssos beeping = period; 4472873Sbde timeout(sysbeepstop, (void *)NULL, period); 4481390Ssos } 44917231Sjoerg splx(x); 45017231Sjoerg return (0); 4511390Ssos} 4521390Ssos 4532913Sache/* 4542913Sache * RTC support routines 4552913Sache */ 4562913Sache 45714943Sbdeint 45814943Sbdertcin(reg) 45914943Sbde int reg; 46014943Sbde{ 46114943Sbde u_char val; 46214943Sbde 46314943Sbde outb(IO_RTC, reg); 46414943Sbde inb(0x84); 46514943Sbde val = inb(IO_RTC + 1); 46614943Sbde inb(0x84); 46714943Sbde return (val); 46814943Sbde} 46914943Sbde 47013445Sphkstatic __inline void 4715291Sbdewritertc(u_char reg, u_char val) 4722913Sache{ 4735291Sbde outb(IO_RTC, reg); 4745291Sbde outb(IO_RTC + 1, val); 4752913Sache} 4762913Sache 47713445Sphkstatic __inline int 4782913Sachereadrtc(int port) 4792913Sache{ 48013445Sphk return(bcd2bin(rtcin(port))); 4812913Sache} 4822913Sache 48315508Sbdestatic u_int 48415508Sbdecalibrate_clocks(void) 48515508Sbde{ 48615508Sbde u_int count, prev_count, tot_count; 48715508Sbde int sec, start_sec, timeout; 48815508Sbde 48919173Sbde printf("Calibrating clock(s) relative to mc146818A clock ... "); 49015508Sbde if (!(rtcin(RTC_STATUSD) & RTCSD_PWR)) 49115508Sbde goto fail; 49215508Sbde timeout = 100000000; 49315508Sbde 49415508Sbde /* Read the mc146818A seconds counter. */ 49515508Sbde for (;;) { 49615508Sbde if (!(rtcin(RTC_STATUSA) & RTCSA_TUP)) { 49715508Sbde sec = rtcin(RTC_SEC); 49815508Sbde break; 49915508Sbde } 50015508Sbde if (--timeout == 0) 50115508Sbde goto fail; 50215508Sbde } 50315508Sbde 50415508Sbde /* Wait for the mC146818A seconds counter to change. */ 50515508Sbde start_sec = sec; 50615508Sbde for (;;) { 50715508Sbde if (!(rtcin(RTC_STATUSA) & RTCSA_TUP)) { 50815508Sbde sec = rtcin(RTC_SEC); 50915508Sbde if (sec != start_sec) 51015508Sbde break; 51115508Sbde } 51215508Sbde if (--timeout == 0) 51315508Sbde goto fail; 51415508Sbde } 51515508Sbde 51615508Sbde /* Start keeping track of the i8254 counter. */ 51715508Sbde prev_count = getit(); 51815508Sbde if (prev_count == 0 || prev_count > timer0_max_count) 51915508Sbde goto fail; 52015508Sbde tot_count = 0; 52115508Sbde 52215508Sbde#if defined(I586_CPU) || defined(I686_CPU) 52315508Sbde if (cpu_class == CPUCLASS_586 || cpu_class == CPUCLASS_686) 52415508Sbde wrmsr(0x10, 0LL); /* XXX 0x10 is the MSR for the TSC */ 52515508Sbde#endif 52615508Sbde 52715508Sbde /* 52815508Sbde * Wait for the mc146818A seconds counter to change. Read the i8254 52915508Sbde * counter for each iteration since this is convenient and only 53015508Sbde * costs a few usec of inaccuracy. The timing of the final reads 53115508Sbde * of the counters almost matches the timing of the initial reads, 53215508Sbde * so the main cause of inaccuracy is the varying latency from 53315508Sbde * inside getit() or rtcin(RTC_STATUSA) to the beginning of the 53415508Sbde * rtcin(RTC_SEC) that returns a changed seconds count. The 53515508Sbde * maximum inaccuracy from this cause is < 10 usec on 486's. 53615508Sbde */ 53715508Sbde start_sec = sec; 53815508Sbde for (;;) { 53915508Sbde if (!(rtcin(RTC_STATUSA) & RTCSA_TUP)) 54015508Sbde sec = rtcin(RTC_SEC); 54115508Sbde count = getit(); 54215508Sbde if (count == 0 || count > timer0_max_count) 54315508Sbde goto fail; 54415508Sbde if (count > prev_count) 54515508Sbde tot_count += prev_count - (count - timer0_max_count); 54615508Sbde else 54715508Sbde tot_count += prev_count - count; 54815508Sbde prev_count = count; 54915508Sbde if (sec != start_sec) 55015508Sbde break; 55115508Sbde if (--timeout == 0) 55215508Sbde goto fail; 55315508Sbde } 55415508Sbde 55515508Sbde#if defined(I586_CPU) || defined(I686_CPU) 55615508Sbde /* 55715508Sbde * Read the cpu cycle counter. The timing considerations are 55815508Sbde * similar to those for the i8254 clock. 55915508Sbde */ 56015508Sbde if (cpu_class == CPUCLASS_586 || cpu_class == CPUCLASS_686) { 56117353Sbde set_i586_ctr_freq((u_int)rdtsc(), tot_count); 56215508Sbde printf("i586 clock: %u Hz, ", i586_ctr_freq); 56315508Sbde } 56415508Sbde#endif 56515508Sbde 56615508Sbde printf("i8254 clock: %u Hz\n", tot_count); 56715508Sbde return (tot_count); 56815508Sbde 56915508Sbdefail: 57015508Sbde printf("failed, using default i8254 clock of %u Hz\n", timer_freq); 57115508Sbde return (timer_freq); 57215508Sbde} 57315508Sbde 57415508Sbdestatic void 57515508Sbdeset_timer_freq(u_int freq, int intr_freq) 57615508Sbde{ 57716874Sbde u_long ef; 57815508Sbde 57915508Sbde ef = read_eflags(); 58016874Sbde disable_intr(); 58115508Sbde timer_freq = freq; 58215508Sbde timer0_max_count = hardclock_max_count = TIMER_DIV(intr_freq); 58315508Sbde timer0_overflow_threshold = timer0_max_count - TIMER0_LATCH_COUNT; 58415508Sbde outb(TIMER_MODE, TIMER_SEL0 | TIMER_RATEGEN | TIMER_16BIT); 58515508Sbde outb(TIMER_CNTR0, timer0_max_count & 0xff); 58615508Sbde outb(TIMER_CNTR0, timer0_max_count >> 8); 58715508Sbde write_eflags(ef); 58815508Sbde} 58915508Sbde 5905291Sbde/* 5915291Sbde * Initialize 8253 timer 0 early so that it can be used in DELAY(). 5925291Sbde * XXX initialization of other timers is unintentionally left blank. 5935291Sbde */ 5941390Ssosvoid 5958876Srgrimesstartrtclock() 596798Swollman{ 59715508Sbde u_int delta, freq; 59815508Sbde 59915508Sbde writertc(RTC_STATUSA, rtc_statusa); 60015508Sbde writertc(RTC_STATUSB, RTCSB_24HR); 60115508Sbde 60216874Sbde set_timer_freq(timer_freq, hz); 60315508Sbde freq = calibrate_clocks(); 60415508Sbde#ifdef CLK_CALIBRATION_LOOP 60515508Sbde if (bootverbose) { 60615508Sbde printf( 60715508Sbde "Press a key on the console to abort clock calibration\n"); 60818288Sbde while (cncheckc() == -1) 60915508Sbde calibrate_clocks(); 61015508Sbde } 61115508Sbde#endif 61215508Sbde 61315508Sbde /* 61415508Sbde * Use the calibrated i8254 frequency if it seems reasonable. 61515508Sbde * Otherwise use the default, and don't use the calibrated i586 61615508Sbde * frequency. 61715508Sbde */ 61815508Sbde delta = freq > timer_freq ? freq - timer_freq : timer_freq - freq; 61915508Sbde if (delta < timer_freq / 100) { 62015508Sbde#ifndef CLK_USE_I8254_CALIBRATION 62116300Spst if (bootverbose) 62219173Sbde printf( 62315508Sbde"CLK_USE_I8254_CALIBRATION not specified - using default frequency\n"); 62415508Sbde freq = timer_freq; 62515508Sbde#endif 62615508Sbde timer_freq = freq; 62715508Sbde } else { 62815508Sbde printf("%d Hz differs from default of %d Hz by more than 1%%\n", 62915508Sbde freq, timer_freq); 63015508Sbde#if defined(I586_CPU) || defined(I686_CPU) 63115508Sbde i586_ctr_freq = 0; 63215508Sbde#endif 63315508Sbde } 63415508Sbde 63515508Sbde set_timer_freq(timer_freq, hz); 63615508Sbde 63715508Sbde#if defined(I586_CPU) || defined(I686_CPU) 63815508Sbde#ifndef CLK_USE_I586_CALIBRATION 63917395Sbde if (i586_ctr_freq != 0) { 64016300Spst if (bootverbose) 64119173Sbde printf( 64215508Sbde"CLK_USE_I586_CALIBRATION not specified - using old calibration method\n"); 64315508Sbde i586_ctr_freq = 0; 64415508Sbde } 64515508Sbde#endif 64617395Sbde if (i586_ctr_freq == 0 && 64715508Sbde (cpu_class == CPUCLASS_586 || cpu_class == CPUCLASS_686)) { 64815508Sbde /* 64915508Sbde * Calibration of the i586 clock relative to the mc146818A 65015508Sbde * clock failed. Do a less accurate calibration relative 65115508Sbde * to the i8254 clock. 65215508Sbde */ 65315508Sbde wrmsr(0x10, 0LL); /* XXX */ 65415508Sbde DELAY(1000000); 65517353Sbde set_i586_ctr_freq((u_int)rdtsc(), timer_freq); 65616300Spst#ifdef CLK_USE_I586_CALIBRATION 65715508Sbde printf("i586 clock: %u Hz\n", i586_ctr_freq); 65816300Spst#endif 65915508Sbde } 66015508Sbde#endif 6614Srgrimes} 6624Srgrimes 6632913Sache/* 6642913Sache * Initialize the time of day register, based on the time base which is, e.g. 6652913Sache * from a filesystem. 6662913Sache */ 6672913Sachevoid 6683185Ssosinittodr(time_t base) 6694Srgrimes{ 6702913Sache unsigned long sec, days; 6712913Sache int yd; 6722913Sache int year, month; 6732913Sache int y, m, s; 6744Srgrimes 6752913Sache s = splclock(); 6762913Sache time.tv_sec = base; 6772913Sache time.tv_usec = 0; 6782913Sache splx(s); 6791390Ssos 6802913Sache /* Look if we have a RTC present and the time is valid */ 6819202Srgrimes if (!(rtcin(RTC_STATUSD) & RTCSD_PWR)) 6822913Sache goto wrong_time; 6834Srgrimes 6842913Sache /* wait for time update to complete */ 6852913Sache /* If RTCSA_TUP is zero, we have at least 244us before next update */ 6862913Sache while (rtcin(RTC_STATUSA) & RTCSA_TUP); 6874Srgrimes 6882913Sache days = 0; 6893355Sache#ifdef USE_RTC_CENTURY 6902913Sache year = readrtc(RTC_YEAR) + readrtc(RTC_CENTURY) * 100; 6913355Sache#else 6923355Sache year = readrtc(RTC_YEAR) + 1900; 6932913Sache if (year < 1970) 6943355Sache year += 100; 6953355Sache#endif 6963355Sache if (year < 1970) 6972913Sache goto wrong_time; 6982913Sache month = readrtc(RTC_MONTH); 6992913Sache for (m = 1; m < month; m++) 7002913Sache days += daysinmonth[m-1]; 7012913Sache if ((month > 2) && LEAPYEAR(year)) 7022913Sache days ++; 7032913Sache days += readrtc(RTC_DAY) - 1; 7042913Sache yd = days; 7052913Sache for (y = 1970; y < year; y++) 7062913Sache days += DAYSPERYEAR + LEAPYEAR(y); 7072913Sache sec = ((( days * 24 + 7082913Sache readrtc(RTC_HRS)) * 60 + 7092913Sache readrtc(RTC_MIN)) * 60 + 7102913Sache readrtc(RTC_SEC)); 7112913Sache /* sec now contains the number of seconds, since Jan 1 1970, 7122913Sache in the local time zone */ 7131390Ssos 71415054Sache sec += tz.tz_minuteswest * 60 + (wall_cmos_clock ? adjkerntz : 0); 7154Srgrimes 7162913Sache s = splclock(); 7172913Sache time.tv_sec = sec; 7182913Sache splx(s); 7192913Sache return; 7202913Sache 7212913Sachewrong_time: 7222913Sache printf("Invalid time in real time clock.\n"); 7232913Sache printf("Check and reset the date immediately!\n"); 7244Srgrimes} 7254Srgrimes 7264Srgrimes/* 7272913Sache * Write system time back to RTC 7284Srgrimes */ 7294180Sbdevoid 7304180Sbderesettodr() 7314Srgrimes{ 7322913Sache unsigned long tm; 73311872Sphk int y, m, s; 7344Srgrimes 7353366Sache if (disable_rtc_set) 7363366Sache return; 7373366Sache 7382913Sache s = splclock(); 7392913Sache tm = time.tv_sec; 7402913Sache splx(s); 7414Srgrimes 7425291Sbde /* Disable RTC updates and interrupts. */ 7432913Sache writertc(RTC_STATUSB, RTCSB_HALT | RTCSB_24HR); 7444Srgrimes 7453366Sache /* Calculate local time to put in RTC */ 7461390Ssos 74715054Sache tm -= tz.tz_minuteswest * 60 + (wall_cmos_clock ? adjkerntz : 0); 7482913Sache 74913445Sphk writertc(RTC_SEC, bin2bcd(tm%60)); tm /= 60; /* Write back Seconds */ 75013445Sphk writertc(RTC_MIN, bin2bcd(tm%60)); tm /= 60; /* Write back Minutes */ 75113445Sphk writertc(RTC_HRS, bin2bcd(tm%24)); tm /= 24; /* Write back Hours */ 7522913Sache 7532913Sache /* We have now the days since 01-01-1970 in tm */ 7542913Sache writertc(RTC_WDAY, (tm+4)%7); /* Write back Weekday */ 75513350Sache for (y = 1970, m = DAYSPERYEAR + LEAPYEAR(y); 75613350Sache tm >= m; 75713350Sache y++, m = DAYSPERYEAR + LEAPYEAR(y)) 75813350Sache tm -= m; 7592913Sache 7602913Sache /* Now we have the years in y and the day-of-the-year in tm */ 76113453Sache writertc(RTC_YEAR, bin2bcd(y%100)); /* Write back Year */ 76213350Sache#ifdef USE_RTC_CENTURY 76313445Sphk writertc(RTC_CENTURY, bin2bcd(y/100)); /* ... and Century */ 7643355Sache#endif 76513402Sbde for (m = 0; ; m++) { 76613402Sbde int ml; 7672913Sache 76813402Sbde ml = daysinmonth[m]; 76913402Sbde if (m == 1 && LEAPYEAR(y)) 77013402Sbde ml++; 77113402Sbde if (tm < ml) 77213402Sbde break; 77313402Sbde tm -= ml; 77413402Sbde } 77513402Sbde 77613445Sphk writertc(RTC_MONTH, bin2bcd(m + 1)); /* Write back Month */ 77713445Sphk writertc(RTC_DAY, bin2bcd(tm + 1)); /* Write back Month Day */ 7782913Sache 7795291Sbde /* Reenable RTC updates and interrupts. */ 78015345Snate writertc(RTC_STATUSB, rtc_statusb); 7814Srgrimes} 7824Srgrimes 7834Srgrimes/* 7845291Sbde * Start both clocks running. 7854Srgrimes */ 7865291Sbdevoid 7875291Sbdecpu_initclocks() 7884Srgrimes{ 7895291Sbde int diag; 7904Srgrimes 79115345Snate if (statclock_disable) { 79215345Snate /* 79315345Snate * The stat interrupt mask is different without the 79415345Snate * statistics clock. Also, don't set the interrupt 79515345Snate * flag which would normally cause the RTC to generate 79615345Snate * interrupts. 79715345Snate */ 79815345Snate stat_imask = HWI_MASK | SWI_MASK; 79915345Snate rtc_statusb = RTCSB_24HR; 80015345Snate } else { 80115345Snate /* Setting stathz to nonzero early helps avoid races. */ 80215345Snate stathz = RTC_NOPROFRATE; 80315345Snate profhz = RTC_PROFRATE; 80415345Snate } 8054Srgrimes 8065291Sbde /* Finish initializing 8253 timer 0. */ 8077090Sbde register_intr(/* irq */ 0, /* XXX id */ 0, /* flags */ 0, 8087090Sbde /* XXX */ (inthand2_t *)clkintr, &clk_imask, 8097090Sbde /* unit */ 0); 8104Srgrimes INTREN(IRQ0); 81113000Sdg#if defined(I586_CPU) || defined(I686_CPU) 81211452Swollman /* 81311452Swollman * Finish setting up anti-jitter measures. 81411452Swollman */ 81517395Sbde if (i586_ctr_freq != 0) { 81615508Sbde i586_last_tick = rdtsc(); 81711452Swollman i586_ctr_bias = i586_last_tick; 81811452Swollman } 81911452Swollman#endif 8205291Sbde 8215291Sbde /* Initialize RTC. */ 8225291Sbde writertc(RTC_STATUSA, rtc_statusa); 8235291Sbde writertc(RTC_STATUSB, RTCSB_24HR); 82415345Snate 82515345Snate /* Don't bother enabling the statistics clock. */ 82615345Snate if (statclock_disable) 82715345Snate return; 8285291Sbde diag = rtcin(RTC_DIAG); 8295291Sbde if (diag != 0) 8305291Sbde printf("RTC BIOS diagnostic error %b\n", diag, RTCDG_BITS); 8317090Sbde register_intr(/* irq */ 8, /* XXX id */ 1, /* flags */ 0, 8327090Sbde /* XXX */ (inthand2_t *)rtcintr, &stat_imask, 8337090Sbde /* unit */ 0); 8342074Swollman INTREN(IRQ8); 83515345Snate writertc(RTC_STATUSB, rtc_statusb); 8364Srgrimes} 8374Srgrimes 8384Srgrimesvoid 8391549Srgrimessetstatclockrate(int newhz) 8401549Srgrimes{ 8415291Sbde if (newhz == RTC_PROFRATE) 8422074Swollman rtc_statusa = RTCSA_DIVIDER | RTCSA_PROF; 8435291Sbde else 8442074Swollman rtc_statusa = RTCSA_DIVIDER | RTCSA_NOPROF; 8455291Sbde writertc(RTC_STATUSA, rtc_statusa); 8461549Srgrimes} 84715508Sbde 84815508Sbdestatic int 84915508Sbdesysctl_machdep_i8254_freq SYSCTL_HANDLER_ARGS 85015508Sbde{ 85115508Sbde int error; 85215508Sbde u_int freq; 85315508Sbde 85415508Sbde /* 85515508Sbde * Use `i8254' instead of `timer' in external names because `timer' 85615508Sbde * is is too generic. Should use it everywhere. 85715508Sbde */ 85815508Sbde freq = timer_freq; 85915508Sbde error = sysctl_handle_opaque(oidp, &freq, sizeof freq, req); 86017353Sbde if (error == 0 && req->newptr != NULL) { 86115508Sbde if (timer0_state != 0) 86215508Sbde return (EBUSY); /* too much trouble to handle */ 86315508Sbde set_timer_freq(freq, hz); 86417353Sbde#if defined(I586_CPU) || defined(I686_CPU) 86517353Sbde set_i586_ctr_freq(i586_ctr_freq, timer_freq); 86617353Sbde#endif 86715508Sbde } 86815508Sbde return (error); 86915508Sbde} 87015508Sbde 87115508SbdeSYSCTL_PROC(_machdep, OID_AUTO, i8254_freq, CTLTYPE_INT | CTLFLAG_RW, 87215508Sbde 0, sizeof(u_int), sysctl_machdep_i8254_freq, "I", ""); 87315508Sbde 87415508Sbde#if defined(I586_CPU) || defined(I686_CPU) 87517353Sbdestatic void 87617353Sbdeset_i586_ctr_freq(u_int i586_freq, u_int i8254_freq) 87717353Sbde{ 87817395Sbde u_int comultiplier, multiplier; 87917353Sbde u_long ef; 88017353Sbde 88117353Sbde if (i586_freq == 0) { 88217353Sbde i586_ctr_freq = i586_freq; 88317353Sbde return; 88417353Sbde } 88517353Sbde comultiplier = ((unsigned long long)i586_freq 88617353Sbde << I586_CTR_COMULTIPLIER_SHIFT) / i8254_freq; 88717353Sbde multiplier = (1000000LL << I586_CTR_MULTIPLIER_SHIFT) / i586_freq; 88817353Sbde ef = read_eflags(); 88917353Sbde disable_intr(); 89017353Sbde i586_ctr_freq = i586_freq; 89117353Sbde i586_ctr_comultiplier = comultiplier; 89217353Sbde i586_ctr_multiplier = multiplier; 89317353Sbde write_eflags(ef); 89417353Sbde} 89517353Sbde 89615508Sbdestatic int 89715508Sbdesysctl_machdep_i586_freq SYSCTL_HANDLER_ARGS 89815508Sbde{ 89915508Sbde int error; 90015508Sbde u_int freq; 90115508Sbde 90217353Sbde if (cpu_class != CPUCLASS_586 && cpu_class != CPUCLASS_686) 90315508Sbde return (EOPNOTSUPP); 90415508Sbde freq = i586_ctr_freq; 90515508Sbde error = sysctl_handle_opaque(oidp, &freq, sizeof freq, req); 90617353Sbde if (error == 0 && req->newptr != NULL) 90717353Sbde set_i586_ctr_freq(freq, timer_freq); 90815508Sbde return (error); 90915508Sbde} 91015508Sbde 91115508SbdeSYSCTL_PROC(_machdep, OID_AUTO, i586_freq, CTLTYPE_INT | CTLFLAG_RW, 91215508Sbde 0, sizeof(u_int), sysctl_machdep_i586_freq, "I", ""); 91315508Sbde#endif /* defined(I586_CPU) || defined(I686_CPU) */ 914