tsc.c revision 92765
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 3750477Speter * $FreeBSD: head/sys/i386/i386/tsc.c 92765 2002-03-20 07:51:46Z alfred $ 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" 5289980Sbde#include "opt_isa.h" 5371797Speter#include "opt_mca.h" 5413228Swollman 552056Swollman#include <sys/param.h> 562056Swollman#include <sys/systm.h> 5761994Smsmith#include <sys/bus.h> 5874914Sjhb#include <sys/lock.h> 5967356Sjhb#include <sys/mutex.h> 6065557Sjasone#include <sys/proc.h> 612056Swollman#include <sys/time.h> 6258377Sphk#include <sys/timetc.h> 632056Swollman#include <sys/kernel.h> 6415508Sbde#include <sys/sysctl.h> 6549558Sphk#include <sys/cons.h> 6685835Siwasaki#include <sys/power.h> 6715508Sbde 684180Sbde#include <machine/clock.h> 6915508Sbde#ifdef CLK_CALIBRATION_LOOP 7015508Sbde#endif 7130805Sbde#include <machine/cputypes.h> 722056Swollman#include <machine/frame.h> 7328551Sbde#include <machine/limits.h> 7432054Sphk#include <machine/md_var.h> 7547588Sbde#include <machine/psl.h> 7630805Sbde#ifdef APIC_IO 7730805Sbde#include <machine/segments.h> 7830805Sbde#endif 7928921Sfsmp#if defined(SMP) || defined(APIC_IO) 8026949Sfsmp#include <machine/smp.h> 8128921Sfsmp#endif /* SMP || APIC_IO */ 8232054Sphk#include <machine/specialreg.h> 8315508Sbde 842056Swollman#include <i386/isa/icu.h> 852056Swollman#include <i386/isa/isa.h> 8647642Sdfr#include <isa/rtc.h> 8789980Sbde#ifdef DEV_ISA 8861994Smsmith#include <isa/isavar.h> 8989980Sbde#endif 902056Swollman#include <i386/isa/timerreg.h> 914Srgrimes 9245897Speter#include <i386/isa/intr_machdep.h> 9328487Sfsmp 9471797Speter#ifdef DEV_MCA 9550823Smdodd#include <i386/isa/mca_machdep.h> 9650823Smdodd#endif 9750823Smdodd 9834571Stegge#ifdef APIC_IO 9934571Stegge#include <i386/isa/intr_machdep.h> 10034058Stegge/* The interrupt triggered by the 8254 (timer) chip */ 10134058Steggeint apic_8254_intr; 10292765Salfredstatic u_long read_intr_count(int vec); 10392765Salfredstatic void setup_8254_mixed_mode(void); 10434571Stegge#endif 10528921Sfsmp 1062873Sbde/* 1072873Sbde * 32-bit time_t's can't reach leap years before 1904 or after 2036, so we 1082873Sbde * can use a simple formula for leap years. 1092873Sbde */ 1102873Sbde#define LEAPYEAR(y) ((u_int)(y) % 4 == 0) 1112913Sache#define DAYSPERYEAR (31+28+31+30+31+30+31+31+30+31+30+31) 1122873Sbde 11315508Sbde#define TIMER_DIV(x) ((timer_freq + (x) / 2) / (x)) 1144Srgrimes 1154180Sbde/* 1164180Sbde * Time in timer cycles that it takes for microtime() to disable interrupts 1174180Sbde * and latch the count. microtime() currently uses "cli; outb ..." so it 1184180Sbde * normally takes less than 2 timer cycles. Add a few for cache misses. 1194180Sbde * Add a few more to allow for latency in bogus calls to microtime() with 1204180Sbde * interrupts already disabled. 1214180Sbde */ 1224180Sbde#define TIMER0_LATCH_COUNT 20 1234180Sbde 1244180Sbde/* 12517236Sjoerg * Maximum frequency that we are willing to allow for timer0. Must be 12617231Sjoerg * low enough to guarantee that the timer interrupt handler returns 12733690Sphk * before the next timer interrupt. 1284180Sbde */ 12917231Sjoerg#define TIMER0_MAX_FREQ 20000 1304180Sbde 13141787Smckayint adjkerntz; /* local offset from GMT in seconds */ 13247588Sbdeint clkintr_pending; 13315045Sacheint disable_rtc_set; /* disable resettodr() if != 0 */ 13432052Sphkint statclock_disable; 13533690Sphk#ifndef TIMER_FREQ 13633690Sphk#define TIMER_FREQ 1193182 13733690Sphk#endif 13832052Sphku_int timer_freq = TIMER_FREQ; 13932052Sphkint timer0_max_count; 14032005Sphku_int tsc_freq; 14147592Sphkint tsc_is_broken; 14272678Sbdeu_int tsc_present; 14341787Smckayint wall_cmos_clock; /* wall CMOS clock assumed if != 0 */ 14471320Sjasonestruct mtx clock_lock; 1451390Ssos 1464180Sbdestatic int beeping = 0; 1474180Sbdestatic const u_char daysinmonth[] = {31,28,31,30,31,30,31,31,30,31,30,31}; 14819173Sbdestatic u_int hardclock_max_count; 14933690Sphkstatic u_int32_t i8254_lastcount; 15033690Sphkstatic u_int32_t i8254_offset; 15133690Sphkstatic int i8254_ticked; 1524180Sbde/* 1534180Sbde * XXX new_function and timer_func should not handle clockframes, but 1544180Sbde * timer_func currently needs to hold hardclock to handle the 15554890Speter * timer0_state == 0 case. We should use inthand_add()/inthand_remove() 1564180Sbde * to switch between clkintr() and a slightly different timerintr(). 1574180Sbde */ 15892765Salfredstatic void (*new_function)(struct clockframe *frame); 15919173Sbdestatic u_int new_rate; 1604180Sbdestatic u_char rtc_statusa = RTCSA_DIVIDER | RTCSA_NOPROF; 16115345Snatestatic u_char rtc_statusb = RTCSB_24HR | RTCSB_PINTR; 16233690Sphkstatic u_int timer0_prescaler_count; 16317231Sjoerg 16417231Sjoerg/* Values for timerX_state: */ 16517236Sjoerg#define RELEASED 0 16617236Sjoerg#define RELEASE_PENDING 1 16717236Sjoerg#define ACQUIRED 2 16817236Sjoerg#define ACQUIRE_PENDING 3 16917231Sjoerg 17017231Sjoergstatic u_char timer0_state; 17117231Sjoergstatic u_char timer2_state; 17292765Salfredstatic void (*timer_func)(struct clockframe *frame) = hardclock; 1734180Sbde 17492765Salfredstatic unsigned i8254_get_timecount(struct timecounter *tc); 17592765Salfredstatic unsigned tsc_get_timecount(struct timecounter *tc); 17621783Sbdestatic void set_timer_freq(u_int freq, int intr_freq); 17717353Sbde 17840610Sphkstatic struct timecounter tsc_timecounter = { 17933690Sphk tsc_get_timecount, /* get_timecount */ 18036741Sphk 0, /* no poll_pps */ 18136198Sphk ~0u, /* counter_mask */ 18233690Sphk 0, /* frequency */ 18333690Sphk "TSC" /* name */ 18433690Sphk}; 18533690Sphk 18633690SphkSYSCTL_OPAQUE(_debug, OID_AUTO, tsc_timecounter, CTLFLAG_RD, 18740610Sphk &tsc_timecounter, sizeof(tsc_timecounter), "S,timecounter", ""); 18833690Sphk 18940610Sphkstatic struct timecounter i8254_timecounter = { 19033690Sphk i8254_get_timecount, /* get_timecount */ 19136741Sphk 0, /* no poll_pps */ 19267759Sphk ~0u, /* counter_mask */ 19333690Sphk 0, /* frequency */ 19433690Sphk "i8254" /* name */ 19533690Sphk}; 19633690Sphk 19733690SphkSYSCTL_OPAQUE(_debug, OID_AUTO, i8254_timecounter, CTLFLAG_RD, 19840610Sphk &i8254_timecounter, sizeof(i8254_timecounter), "S,timecounter", ""); 19933690Sphk 20012724Sphkstatic void 2013185Ssosclkintr(struct clockframe frame) 2022074Swollman{ 20365557Sjasone 20439503Sbde if (timecounter->tc_get_timecount == i8254_get_timecount) { 20572200Sbmilekic mtx_lock_spin(&clock_lock); 20647588Sbde if (i8254_ticked) 20739503Sbde i8254_ticked = 0; 20847588Sbde else { 20939503Sbde i8254_offset += timer0_max_count; 21039503Sbde i8254_lastcount = 0; 21139503Sbde } 21247588Sbde clkintr_pending = 0; 21372200Sbmilekic mtx_unlock_spin(&clock_lock); 21439503Sbde } 2151549Srgrimes timer_func(&frame); 21676078Sjhb#ifdef SMP 21776078Sjhb if (timer_func == hardclock) 21876078Sjhb forward_hardclock(); 21976078Sjhb#endif 2201442Ssos switch (timer0_state) { 22117236Sjoerg 22217231Sjoerg case RELEASED: 2231442Ssos break; 22417236Sjoerg 22517231Sjoerg case ACQUIRED: 2264180Sbde if ((timer0_prescaler_count += timer0_max_count) 2274180Sbde >= hardclock_max_count) { 22833309Sbde timer0_prescaler_count -= hardclock_max_count; 2291549Srgrimes hardclock(&frame); 23076089Sjhb#ifdef SMP 23176089Sjhb forward_hardclock(); 23276089Sjhb#endif 2331390Ssos } 2341442Ssos break; 23517236Sjoerg 23617231Sjoerg case ACQUIRE_PENDING: 23772200Sbmilekic mtx_lock_spin(&clock_lock); 23848889Sbde i8254_offset = i8254_get_timecount(NULL); 23948889Sbde i8254_lastcount = 0; 2404180Sbde timer0_max_count = TIMER_DIV(new_rate); 2414180Sbde outb(TIMER_MODE, TIMER_SEL0 | TIMER_RATEGEN | TIMER_16BIT); 2424180Sbde outb(TIMER_CNTR0, timer0_max_count & 0xff); 2434180Sbde outb(TIMER_CNTR0, timer0_max_count >> 8); 24472200Sbmilekic mtx_unlock_spin(&clock_lock); 2451442Ssos timer_func = new_function; 24617231Sjoerg timer0_state = ACQUIRED; 2471442Ssos break; 24817236Sjoerg 24917231Sjoerg case RELEASE_PENDING: 2504180Sbde if ((timer0_prescaler_count += timer0_max_count) 2514180Sbde >= hardclock_max_count) { 25272200Sbmilekic mtx_lock_spin(&clock_lock); 25348889Sbde i8254_offset = i8254_get_timecount(NULL); 25448889Sbde i8254_lastcount = 0; 2555291Sbde timer0_max_count = hardclock_max_count; 2564180Sbde outb(TIMER_MODE, 2574180Sbde TIMER_SEL0 | TIMER_RATEGEN | TIMER_16BIT); 2584180Sbde outb(TIMER_CNTR0, timer0_max_count & 0xff); 2594180Sbde outb(TIMER_CNTR0, timer0_max_count >> 8); 26072200Sbmilekic mtx_unlock_spin(&clock_lock); 2614180Sbde timer0_prescaler_count = 0; 26217231Sjoerg timer_func = hardclock; 26317231Sjoerg timer0_state = RELEASED; 26448889Sbde hardclock(&frame); 26576078Sjhb#ifdef SMP 26676078Sjhb forward_hardclock(); 26776078Sjhb#endif 2681442Ssos } 2691442Ssos break; 2701442Ssos } 27171797Speter#ifdef DEV_MCA 27250823Smdodd /* Reset clock interrupt by asserting bit 7 of port 0x61 */ 27350823Smdodd if (MCA_system) 27450823Smdodd outb(0x61, inb(0x61) | 0x80); 27550823Smdodd#endif 2761390Ssos} 2771390Ssos 27817231Sjoerg/* 27917236Sjoerg * The acquire and release functions must be called at ipl >= splclock(). 28017231Sjoerg */ 2811390Ssosint 28292765Salfredacquire_timer0(int rate, void (*function)(struct clockframe *frame)) 2831390Ssos{ 28417231Sjoerg static int old_rate; 28517231Sjoerg 28617231Sjoerg if (rate <= 0 || rate > TIMER0_MAX_FREQ) 28717231Sjoerg return (-1); 28817231Sjoerg switch (timer0_state) { 28917231Sjoerg 29017236Sjoerg case RELEASED: 29117236Sjoerg timer0_state = ACQUIRE_PENDING; 29217236Sjoerg break; 29317231Sjoerg 29417236Sjoerg case RELEASE_PENDING: 29517236Sjoerg if (rate != old_rate) 29617236Sjoerg return (-1); 29717236Sjoerg /* 29817236Sjoerg * The timer has been released recently, but is being 29917236Sjoerg * re-acquired before the release completed. In this 30017236Sjoerg * case, we simply reclaim it as if it had not been 30117236Sjoerg * released at all. 30217236Sjoerg */ 30317236Sjoerg timer0_state = ACQUIRED; 30417236Sjoerg break; 30517236Sjoerg 30617236Sjoerg default: 30717236Sjoerg return (-1); /* busy */ 30817231Sjoerg } 3091442Ssos new_function = function; 31017231Sjoerg old_rate = new_rate = rate; 31117231Sjoerg return (0); 3121390Ssos} 3131390Ssos 3141390Ssosint 3151390Ssosacquire_timer2(int mode) 3161390Ssos{ 31717231Sjoerg 31817231Sjoerg if (timer2_state != RELEASED) 31917231Sjoerg return (-1); 32017231Sjoerg timer2_state = ACQUIRED; 32117236Sjoerg 32217236Sjoerg /* 32317236Sjoerg * This access to the timer registers is as atomic as possible 32417236Sjoerg * because it is a single instruction. We could do better if we 32517236Sjoerg * knew the rate. Use of splclock() limits glitches to 10-100us, 32617236Sjoerg * and this is probably good enough for timer2, so we aren't as 32717236Sjoerg * careful with it as with timer0. 32817236Sjoerg */ 32917236Sjoerg outb(TIMER_MODE, TIMER_SEL2 | (mode & 0x3f)); 33017236Sjoerg 33117231Sjoerg return (0); 3321390Ssos} 3331390Ssos 3341390Ssosint 3351390Ssosrelease_timer0() 3361390Ssos{ 33717231Sjoerg switch (timer0_state) { 33817231Sjoerg 33917236Sjoerg case ACQUIRED: 34017236Sjoerg timer0_state = RELEASE_PENDING; 34117236Sjoerg break; 34217231Sjoerg 34317236Sjoerg case ACQUIRE_PENDING: 34417236Sjoerg /* Nothing happened yet, release quickly. */ 34517236Sjoerg timer0_state = RELEASED; 34617236Sjoerg break; 34717236Sjoerg 34817236Sjoerg default: 34917236Sjoerg return (-1); 35017231Sjoerg } 35117231Sjoerg return (0); 3521390Ssos} 3531390Ssos 3541390Ssosint 3551390Ssosrelease_timer2() 3561390Ssos{ 35717231Sjoerg 35817231Sjoerg if (timer2_state != ACQUIRED) 35917231Sjoerg return (-1); 36017231Sjoerg timer2_state = RELEASED; 36117236Sjoerg outb(TIMER_MODE, TIMER_SEL2 | TIMER_SQWAVE | TIMER_16BIT); 36217231Sjoerg return (0); 3631390Ssos} 3641390Ssos 3653185Ssos/* 3663185Ssos * This routine receives statistical clock interrupts from the RTC. 3673185Ssos * As explained above, these occur at 128 interrupts per second. 3683185Ssos * When profiling, we receive interrupts at a rate of 1024 Hz. 3693185Ssos * 3703185Ssos * This does not actually add as much overhead as it sounds, because 3713185Ssos * when the statistical clock is active, the hardclock driver no longer 3723185Ssos * needs to keep (inaccurate) statistics on its own. This decouples 3733185Ssos * statistics gathering from scheduling interrupts. 3743185Ssos * 3753185Ssos * The RTC chip requires that we read status register C (RTC_INTR) 3763185Ssos * to acknowledge an interrupt, before it will generate the next one. 37724676Smckay * Under high interrupt load, rtcintr() can be indefinitely delayed and 37824676Smckay * the clock can tick immediately after the read from RTC_INTR. In this 37924676Smckay * case, the mc146818A interrupt signal will not drop for long enough 38024676Smckay * to register with the 8259 PIC. If an interrupt is missed, the stat 38124676Smckay * clock will halt, considerably degrading system performance. This is 38224676Smckay * why we use 'while' rather than a more straightforward 'if' below. 38324676Smckay * Stat clock ticks can still be lost, causing minor loss of accuracy 38424676Smckay * in the statistics, but the stat clock will no longer stop. 3853185Ssos */ 38612724Sphkstatic void 3873185Ssosrtcintr(struct clockframe frame) 3883185Ssos{ 38976078Sjhb while (rtcin(RTC_INTR) & RTCIR_PERIOD) { 3903185Ssos statclock(&frame); 39176078Sjhb#ifdef SMP 39276078Sjhb forward_statclock(); 39376078Sjhb#endif 39476078Sjhb } 3953185Ssos} 3961390Ssos 39718297Sbde#include "opt_ddb.h" 3985291Sbde#ifdef DDB 39918297Sbde#include <ddb/ddb.h> 40018297Sbde 40118297SbdeDB_SHOW_COMMAND(rtc, rtc) 4023185Ssos{ 4035291Sbde printf("%02x/%02x/%02x %02x:%02x:%02x, A = %02x, B = %02x, C = %02x\n", 4045291Sbde rtcin(RTC_YEAR), rtcin(RTC_MONTH), rtcin(RTC_DAY), 4055291Sbde rtcin(RTC_HRS), rtcin(RTC_MIN), rtcin(RTC_SEC), 4065291Sbde rtcin(RTC_STATUSA), rtcin(RTC_STATUSB), rtcin(RTC_INTR)); 4073185Ssos} 40818297Sbde#endif /* DDB */ 4093185Ssos 4101390Ssosstatic int 41110268Sbdegetit(void) 4121390Ssos{ 41366716Sjhb int high, low; 4141390Ssos 41572200Sbmilekic mtx_lock_spin(&clock_lock); 41616428Sbde 41716428Sbde /* Select timer0 and latch counter value. */ 41819173Sbde outb(TIMER_MODE, TIMER_SEL0 | TIMER_LATCH); 41916428Sbde 4201390Ssos low = inb(TIMER_CNTR0); 4211390Ssos high = inb(TIMER_CNTR0); 42216428Sbde 42372200Sbmilekic mtx_unlock_spin(&clock_lock); 4241390Ssos return ((high << 8) | low); 4251390Ssos} 4261390Ssos 4272017Swollman/* 4281390Ssos * Wait "n" microseconds. 42915508Sbde * Relies on timer 1 counting down from (timer_freq / hz) 4301390Ssos * Note: timer had better have been programmed before this is first used! 4311390Ssos */ 4321390Ssosvoid 4331390SsosDELAY(int n) 4341390Ssos{ 43522106Sbde int delta, prev_tick, tick, ticks_left; 4361390Ssos 4371390Ssos#ifdef DELAYDEBUG 4381390Ssos int getit_calls = 1; 4391390Ssos int n1; 4401390Ssos static int state = 0; 4411390Ssos 4421390Ssos if (state == 0) { 4431390Ssos state = 1; 4441390Ssos for (n1 = 1; n1 <= 10000000; n1 *= 10) 4451390Ssos DELAY(n1); 4461390Ssos state = 2; 4471390Ssos } 4481390Ssos if (state == 1) 4491390Ssos printf("DELAY(%d)...", n); 4501390Ssos#endif 4511390Ssos /* 45221783Sbde * Guard against the timer being uninitialized if we are called 45321783Sbde * early for console i/o. 45421783Sbde */ 45521783Sbde if (timer0_max_count == 0) 45621783Sbde set_timer_freq(timer_freq, hz); 45721783Sbde 45821783Sbde /* 4591390Ssos * Read the counter first, so that the rest of the setup overhead is 4601390Ssos * counted. Guess the initial overhead is 20 usec (on most systems it 4611390Ssos * takes about 1.5 usec for each of the i/o's in getit(). The loop 4621390Ssos * takes about 6 usec on a 486/33 and 13 usec on a 386/20. The 4631390Ssos * multiplications and divisions to scale the count take a while). 4641390Ssos */ 46510268Sbde prev_tick = getit(); 46622106Sbde n -= 0; /* XXX actually guess no initial overhead */ 4671390Ssos /* 46815508Sbde * Calculate (n * (timer_freq / 1e6)) without using floating point 4691390Ssos * and without any avoidable overflows. 4701390Ssos */ 47122106Sbde if (n <= 0) 47222106Sbde ticks_left = 0; 47322106Sbde else if (n < 256) 47422106Sbde /* 47522106Sbde * Use fixed point to avoid a slow division by 1000000. 47622106Sbde * 39099 = 1193182 * 2^15 / 10^6 rounded to nearest. 47722106Sbde * 2^15 is the first power of 2 that gives exact results 47822106Sbde * for n between 0 and 256. 47922106Sbde */ 48022106Sbde ticks_left = ((u_int)n * 39099 + (1 << 15) - 1) >> 15; 48122106Sbde else 48222106Sbde /* 48322106Sbde * Don't bother using fixed point, although gcc-2.7.2 48422106Sbde * generates particularly poor code for the long long 48522106Sbde * division, since even the slow way will complete long 48622106Sbde * before the delay is up (unless we're interrupted). 48722106Sbde */ 48822106Sbde ticks_left = ((u_int)n * (long long)timer_freq + 999999) 48922106Sbde / 1000000; 4901390Ssos 4911390Ssos while (ticks_left > 0) { 49210268Sbde tick = getit(); 4931390Ssos#ifdef DELAYDEBUG 4941390Ssos ++getit_calls; 4951390Ssos#endif 49621783Sbde delta = prev_tick - tick; 4971390Ssos prev_tick = tick; 49821783Sbde if (delta < 0) { 49921783Sbde delta += timer0_max_count; 50021783Sbde /* 50121783Sbde * Guard against timer0_max_count being wrong. 50221783Sbde * This shouldn't happen in normal operation, 50321783Sbde * but it may happen if set_timer_freq() is 50421783Sbde * traced. 50521783Sbde */ 50621783Sbde if (delta < 0) 50721783Sbde delta = 0; 50821783Sbde } 50921783Sbde ticks_left -= delta; 5101390Ssos } 5111390Ssos#ifdef DELAYDEBUG 5121390Ssos if (state == 1) 5131390Ssos printf(" %d calls to getit() at %d usec each\n", 5141390Ssos getit_calls, (n + 5) / getit_calls); 5151390Ssos#endif 5161390Ssos} 5171390Ssos 5181390Ssosstatic void 5193185Ssossysbeepstop(void *chan) 5201390Ssos{ 5211390Ssos outb(IO_PPI, inb(IO_PPI)&0xFC); /* disable counter2 output to speaker */ 5221390Ssos release_timer2(); 5231390Ssos beeping = 0; 5241390Ssos} 5251390Ssos 5268876Srgrimesint 5271390Ssossysbeep(int pitch, int period) 5281390Ssos{ 52917231Sjoerg int x = splclock(); 5301390Ssos 5318876Srgrimes if (acquire_timer2(TIMER_SQWAVE|TIMER_16BIT)) 53217231Sjoerg if (!beeping) { 53317231Sjoerg /* Something else owns it. */ 53417231Sjoerg splx(x); 53517231Sjoerg return (-1); /* XXX Should be EBUSY, but nobody cares anyway. */ 53617231Sjoerg } 53772200Sbmilekic mtx_lock_spin(&clock_lock); 5381390Ssos outb(TIMER_CNTR2, pitch); 5391390Ssos outb(TIMER_CNTR2, (pitch>>8)); 54072200Sbmilekic mtx_unlock_spin(&clock_lock); 5411390Ssos if (!beeping) { 54217231Sjoerg /* enable counter2 output to speaker */ 54317231Sjoerg outb(IO_PPI, inb(IO_PPI) | 3); 5441390Ssos beeping = period; 5452873Sbde timeout(sysbeepstop, (void *)NULL, period); 5461390Ssos } 54717231Sjoerg splx(x); 54817231Sjoerg return (0); 5491390Ssos} 5501390Ssos 5512913Sache/* 5522913Sache * RTC support routines 5532913Sache */ 5542913Sache 55514943Sbdeint 55614943Sbdertcin(reg) 55714943Sbde int reg; 55814943Sbde{ 55955098Sbde int s; 56014943Sbde u_char val; 56114943Sbde 56255098Sbde s = splhigh(); 56314943Sbde outb(IO_RTC, reg); 56414943Sbde inb(0x84); 56514943Sbde val = inb(IO_RTC + 1); 56614943Sbde inb(0x84); 56755098Sbde splx(s); 56814943Sbde return (val); 56914943Sbde} 57014943Sbde 57113445Sphkstatic __inline void 5725291Sbdewritertc(u_char reg, u_char val) 5732913Sache{ 57455098Sbde int s; 57555098Sbde 57655098Sbde s = splhigh(); 57733309Sbde inb(0x84); 5785291Sbde outb(IO_RTC, reg); 57933309Sbde inb(0x84); 5805291Sbde outb(IO_RTC + 1, val); 58133309Sbde inb(0x84); /* XXX work around wrong order in rtcin() */ 58255098Sbde splx(s); 5832913Sache} 5842913Sache 58513445Sphkstatic __inline int 5862913Sachereadrtc(int port) 5872913Sache{ 58813445Sphk return(bcd2bin(rtcin(port))); 5892913Sache} 5902913Sache 59115508Sbdestatic u_int 59215508Sbdecalibrate_clocks(void) 59315508Sbde{ 59448160Sgreen u_int64_t old_tsc; 59515508Sbde u_int count, prev_count, tot_count; 59615508Sbde int sec, start_sec, timeout; 59715508Sbde 59823393Sbde if (bootverbose) 59923393Sbde printf("Calibrating clock(s) ... "); 60015508Sbde if (!(rtcin(RTC_STATUSD) & RTCSD_PWR)) 60115508Sbde goto fail; 60215508Sbde timeout = 100000000; 60315508Sbde 60415508Sbde /* Read the mc146818A seconds counter. */ 60515508Sbde for (;;) { 60615508Sbde if (!(rtcin(RTC_STATUSA) & RTCSA_TUP)) { 60715508Sbde sec = rtcin(RTC_SEC); 60815508Sbde break; 60915508Sbde } 61015508Sbde if (--timeout == 0) 61115508Sbde goto fail; 61215508Sbde } 61315508Sbde 61415508Sbde /* Wait for the mC146818A seconds counter to change. */ 61515508Sbde start_sec = sec; 61615508Sbde for (;;) { 61715508Sbde if (!(rtcin(RTC_STATUSA) & RTCSA_TUP)) { 61815508Sbde sec = rtcin(RTC_SEC); 61915508Sbde if (sec != start_sec) 62015508Sbde break; 62115508Sbde } 62215508Sbde if (--timeout == 0) 62315508Sbde goto fail; 62415508Sbde } 62515508Sbde 62615508Sbde /* Start keeping track of the i8254 counter. */ 62715508Sbde prev_count = getit(); 62815508Sbde if (prev_count == 0 || prev_count > timer0_max_count) 62915508Sbde goto fail; 63015508Sbde tot_count = 0; 63115508Sbde 63232054Sphk if (tsc_present) 63348160Sgreen old_tsc = rdtsc(); 63448266Speter else 63548266Speter old_tsc = 0; /* shut up gcc */ 63615508Sbde 63715508Sbde /* 63815508Sbde * Wait for the mc146818A seconds counter to change. Read the i8254 63915508Sbde * counter for each iteration since this is convenient and only 64015508Sbde * costs a few usec of inaccuracy. The timing of the final reads 64115508Sbde * of the counters almost matches the timing of the initial reads, 64215508Sbde * so the main cause of inaccuracy is the varying latency from 64315508Sbde * inside getit() or rtcin(RTC_STATUSA) to the beginning of the 64415508Sbde * rtcin(RTC_SEC) that returns a changed seconds count. The 64515508Sbde * maximum inaccuracy from this cause is < 10 usec on 486's. 64615508Sbde */ 64715508Sbde start_sec = sec; 64815508Sbde for (;;) { 64915508Sbde if (!(rtcin(RTC_STATUSA) & RTCSA_TUP)) 65015508Sbde sec = rtcin(RTC_SEC); 65115508Sbde count = getit(); 65215508Sbde if (count == 0 || count > timer0_max_count) 65315508Sbde goto fail; 65415508Sbde if (count > prev_count) 65515508Sbde tot_count += prev_count - (count - timer0_max_count); 65615508Sbde else 65715508Sbde tot_count += prev_count - count; 65815508Sbde prev_count = count; 65915508Sbde if (sec != start_sec) 66015508Sbde break; 66115508Sbde if (--timeout == 0) 66215508Sbde goto fail; 66315508Sbde } 66415508Sbde 66515508Sbde /* 66615508Sbde * Read the cpu cycle counter. The timing considerations are 66715508Sbde * similar to those for the i8254 clock. 66815508Sbde */ 66933690Sphk if (tsc_present) 67048160Sgreen tsc_freq = rdtsc() - old_tsc; 67133690Sphk 67233690Sphk if (bootverbose) { 67333690Sphk if (tsc_present) 67432005Sphk printf("TSC clock: %u Hz, ", tsc_freq); 67533929Sphk printf("i8254 clock: %u Hz\n", tot_count); 67615508Sbde } 67715508Sbde return (tot_count); 67815508Sbde 67915508Sbdefail: 68023393Sbde if (bootverbose) 68123393Sbde printf("failed, using default i8254 clock of %u Hz\n", 68223393Sbde timer_freq); 68315508Sbde return (timer_freq); 68415508Sbde} 68515508Sbde 68615508Sbdestatic void 68715508Sbdeset_timer_freq(u_int freq, int intr_freq) 68815508Sbde{ 68933309Sbde int new_timer0_max_count; 69015508Sbde 69172200Sbmilekic mtx_lock_spin(&clock_lock); 69215508Sbde timer_freq = freq; 69333309Sbde new_timer0_max_count = hardclock_max_count = TIMER_DIV(intr_freq); 69433309Sbde if (new_timer0_max_count != timer0_max_count) { 69533309Sbde timer0_max_count = new_timer0_max_count; 69633309Sbde outb(TIMER_MODE, TIMER_SEL0 | TIMER_RATEGEN | TIMER_16BIT); 69733309Sbde outb(TIMER_CNTR0, timer0_max_count & 0xff); 69833309Sbde outb(TIMER_CNTR0, timer0_max_count >> 8); 69933309Sbde } 70072200Sbmilekic mtx_unlock_spin(&clock_lock); 70115508Sbde} 70215508Sbde 7035291Sbde/* 70452669Siwasaki * i8254_restore is called from apm_default_resume() to reload 70552669Siwasaki * the countdown register. 70652669Siwasaki * this should not be necessary but there are broken laptops that 70752669Siwasaki * do not restore the countdown register on resume. 70852669Siwasaki * when it happnes, it messes up the hardclock interval and system clock, 70952669Siwasaki * which leads to the infamous "calcru: negative time" problem. 71052669Siwasaki */ 71182971Siwasakistatic void 71252669Siwasakii8254_restore(void) 71352669Siwasaki{ 71452669Siwasaki 71572200Sbmilekic mtx_lock_spin(&clock_lock); 71652669Siwasaki outb(TIMER_MODE, TIMER_SEL0 | TIMER_RATEGEN | TIMER_16BIT); 71752669Siwasaki outb(TIMER_CNTR0, timer0_max_count & 0xff); 71852669Siwasaki outb(TIMER_CNTR0, timer0_max_count >> 8); 71972200Sbmilekic mtx_unlock_spin(&clock_lock); 72052669Siwasaki} 72152669Siwasaki 72282971Siwasakistatic void 72382971Siwasakirtc_restore(void) 72482971Siwasaki{ 72582971Siwasaki 72682971Siwasaki /* Reenable RTC updates and interrupts. */ 72782971Siwasaki /* XXX locking is needed for RTC access? */ 72882971Siwasaki writertc(RTC_STATUSB, RTCSB_HALT | RTCSB_24HR); 72982971Siwasaki writertc(RTC_STATUSB, rtc_statusb); 73082971Siwasaki} 73182971Siwasaki 73252669Siwasaki/* 73382971Siwasaki * Restore all the timers atomically. 73482971Siwasaki */ 73582971Siwasakivoid 73682971Siwasakitimer_restore(void) 73782971Siwasaki{ 73882971Siwasaki 73982971Siwasaki i8254_restore(); /* restore timer_freq and hz */ 74082971Siwasaki rtc_restore(); /* reenable RTC interrupts */ 74182971Siwasaki} 74282971Siwasaki 74382971Siwasaki/* 74433690Sphk * Initialize 8254 timer 0 early so that it can be used in DELAY(). 7455291Sbde * XXX initialization of other timers is unintentionally left blank. 7465291Sbde */ 7471390Ssosvoid 7488876Srgrimesstartrtclock() 749798Swollman{ 75015508Sbde u_int delta, freq; 75115508Sbde 75232054Sphk if (cpu_feature & CPUID_TSC) 75332054Sphk tsc_present = 1; 75432054Sphk else 75532054Sphk tsc_present = 0; 75632054Sphk 75715508Sbde writertc(RTC_STATUSA, rtc_statusa); 75815508Sbde writertc(RTC_STATUSB, RTCSB_24HR); 75915508Sbde 76016874Sbde set_timer_freq(timer_freq, hz); 76115508Sbde freq = calibrate_clocks(); 76215508Sbde#ifdef CLK_CALIBRATION_LOOP 76315508Sbde if (bootverbose) { 76415508Sbde printf( 76515508Sbde "Press a key on the console to abort clock calibration\n"); 76618288Sbde while (cncheckc() == -1) 76715508Sbde calibrate_clocks(); 76815508Sbde } 76915508Sbde#endif 77015508Sbde 77115508Sbde /* 77215508Sbde * Use the calibrated i8254 frequency if it seems reasonable. 77315508Sbde * Otherwise use the default, and don't use the calibrated i586 77415508Sbde * frequency. 77515508Sbde */ 77615508Sbde delta = freq > timer_freq ? freq - timer_freq : timer_freq - freq; 77715508Sbde if (delta < timer_freq / 100) { 77815508Sbde#ifndef CLK_USE_I8254_CALIBRATION 77916300Spst if (bootverbose) 78019173Sbde printf( 78115508Sbde"CLK_USE_I8254_CALIBRATION not specified - using default frequency\n"); 78215508Sbde freq = timer_freq; 78315508Sbde#endif 78415508Sbde timer_freq = freq; 78515508Sbde } else { 78623393Sbde if (bootverbose) 78723393Sbde printf( 78823393Sbde "%d Hz differs from default of %d Hz by more than 1%%\n", 78923393Sbde freq, timer_freq); 79032005Sphk tsc_freq = 0; 79115508Sbde } 79215508Sbde 79315508Sbde set_timer_freq(timer_freq, hz); 79440610Sphk i8254_timecounter.tc_frequency = timer_freq; 79558377Sphk tc_init(&i8254_timecounter); 79615508Sbde 79732005Sphk#ifndef CLK_USE_TSC_CALIBRATION 79832005Sphk if (tsc_freq != 0) { 79916300Spst if (bootverbose) 80019173Sbde printf( 80132005Sphk"CLK_USE_TSC_CALIBRATION not specified - using old calibration method\n"); 80232005Sphk tsc_freq = 0; 80315508Sbde } 80415508Sbde#endif 80532054Sphk if (tsc_present && tsc_freq == 0) { 80615508Sbde /* 80715508Sbde * Calibration of the i586 clock relative to the mc146818A 80815508Sbde * clock failed. Do a less accurate calibration relative 80915508Sbde * to the i8254 clock. 81015508Sbde */ 81148160Sgreen u_int64_t old_tsc = rdtsc(); 81248160Sgreen 81315508Sbde DELAY(1000000); 81448160Sgreen tsc_freq = rdtsc() - old_tsc; 81532054Sphk#ifdef CLK_USE_TSC_CALIBRATION 81623393Sbde if (bootverbose) 81733690Sphk printf("TSC clock: %u Hz (Method B)\n", tsc_freq); 81816300Spst#endif 81915508Sbde } 82034617Sphk 82134617Sphk#if !defined(SMP) 82234617Sphk /* 82334617Sphk * We can not use the TSC in SMP mode, until we figure out a 82434617Sphk * cheap (impossible), reliable and precise (yeah right!) way 82534617Sphk * to synchronize the TSCs of all the CPUs. 82634617Sphk * Curse Intel for leaving the counter out of the I/O APIC. 82734617Sphk */ 82834617Sphk 82934617Sphk /* 83049186Smsmith * We can not use the TSC if we support APM. Precise timekeeping 83149186Smsmith * on an APM'ed machine is at best a fools pursuit, since 83234617Sphk * any and all of the time spent in various SMM code can't 83334617Sphk * be reliably accounted for. Reading the RTC is your only 83434617Sphk * source of reliable time info. The i8254 looses too of course 83534617Sphk * but we need to have some kind of time... 83649186Smsmith * We don't know at this point whether APM is going to be used 83749186Smsmith * or not, nor when it might be activated. Play it safe. 83834617Sphk */ 83985835Siwasaki if (power_pm_get_type() == POWER_PM_TYPE_APM) { 84085835Siwasaki if (bootverbose) 84185835Siwasaki printf("TSC initialization skipped: APM enabled.\n"); 84264031Sphk return; 84364031Sphk } 84434617Sphk 84547592Sphk if (tsc_present && tsc_freq != 0 && !tsc_is_broken) { 84640610Sphk tsc_timecounter.tc_frequency = tsc_freq; 84758377Sphk tc_init(&tsc_timecounter); 84833690Sphk } 84934617Sphk 85034617Sphk#endif /* !defined(SMP) */ 8514Srgrimes} 8524Srgrimes 8532913Sache/* 85441787Smckay * Initialize the time of day register, based on the time base which is, e.g. 85541787Smckay * from a filesystem. 8562913Sache */ 8572913Sachevoid 8583185Ssosinittodr(time_t base) 8594Srgrimes{ 8602913Sache unsigned long sec, days; 8612913Sache int year, month; 8622913Sache int y, m, s; 86333690Sphk struct timespec ts; 8644Srgrimes 86532850Sphk if (base) { 86632850Sphk s = splclock(); 86733690Sphk ts.tv_sec = base; 86833690Sphk ts.tv_nsec = 0; 86958377Sphk tc_setclock(&ts); 87032850Sphk splx(s); 87132850Sphk } 8721390Ssos 87341787Smckay /* Look if we have a RTC present and the time is valid */ 8749202Srgrimes if (!(rtcin(RTC_STATUSD) & RTCSD_PWR)) 8752913Sache goto wrong_time; 8764Srgrimes 87741787Smckay /* wait for time update to complete */ 87841787Smckay /* If RTCSA_TUP is zero, we have at least 244us before next update */ 87955098Sbde s = splhigh(); 88055098Sbde while (rtcin(RTC_STATUSA) & RTCSA_TUP) { 88155098Sbde splx(s); 88255098Sbde s = splhigh(); 88355098Sbde } 8844Srgrimes 8852913Sache days = 0; 8863355Sache#ifdef USE_RTC_CENTURY 88741787Smckay year = readrtc(RTC_YEAR) + readrtc(RTC_CENTURY) * 100; 8883355Sache#else 8893355Sache year = readrtc(RTC_YEAR) + 1900; 8902913Sache if (year < 1970) 8913355Sache year += 100; 8923355Sache#endif 89355098Sbde if (year < 1970) { 89455098Sbde splx(s); 8952913Sache goto wrong_time; 89655098Sbde } 89741787Smckay month = readrtc(RTC_MONTH); 89841787Smckay for (m = 1; m < month; m++) 89941787Smckay days += daysinmonth[m-1]; 90041787Smckay if ((month > 2) && LEAPYEAR(year)) 9012913Sache days ++; 90241787Smckay days += readrtc(RTC_DAY) - 1; 9032913Sache for (y = 1970; y < year; y++) 90441787Smckay days += DAYSPERYEAR + LEAPYEAR(y); 9052913Sache sec = ((( days * 24 + 9062913Sache readrtc(RTC_HRS)) * 60 + 9072913Sache readrtc(RTC_MIN)) * 60 + 9082913Sache readrtc(RTC_SEC)); 90941787Smckay /* sec now contains the number of seconds, since Jan 1 1970, 91041787Smckay in the local time zone */ 9111390Ssos 91215054Sache sec += tz.tz_minuteswest * 60 + (wall_cmos_clock ? adjkerntz : 0); 9134Srgrimes 91434961Sphk y = time_second - sec; 91533690Sphk if (y <= -2 || y >= 2) { 91633690Sphk /* badly off, adjust it */ 91733690Sphk ts.tv_sec = sec; 91833690Sphk ts.tv_nsec = 0; 91958377Sphk tc_setclock(&ts); 92033690Sphk } 92155098Sbde splx(s); 9222913Sache return; 9232913Sache 9242913Sachewrong_time: 92541787Smckay printf("Invalid time in real time clock.\n"); 92641787Smckay printf("Check and reset the date immediately!\n"); 9274Srgrimes} 9284Srgrimes 9294Srgrimes/* 93041787Smckay * Write system time back to RTC 9314Srgrimes */ 9324180Sbdevoid 9334180Sbderesettodr() 9344Srgrimes{ 9352913Sache unsigned long tm; 93611872Sphk int y, m, s; 9374Srgrimes 9383366Sache if (disable_rtc_set) 9393366Sache return; 9403366Sache 9412913Sache s = splclock(); 94234961Sphk tm = time_second; 9432913Sache splx(s); 9444Srgrimes 9455291Sbde /* Disable RTC updates and interrupts. */ 9462913Sache writertc(RTC_STATUSB, RTCSB_HALT | RTCSB_24HR); 9474Srgrimes 94841787Smckay /* Calculate local time to put in RTC */ 9491390Ssos 95015054Sache tm -= tz.tz_minuteswest * 60 + (wall_cmos_clock ? adjkerntz : 0); 9512913Sache 95213445Sphk writertc(RTC_SEC, bin2bcd(tm%60)); tm /= 60; /* Write back Seconds */ 95313445Sphk writertc(RTC_MIN, bin2bcd(tm%60)); tm /= 60; /* Write back Minutes */ 95413445Sphk writertc(RTC_HRS, bin2bcd(tm%24)); tm /= 24; /* Write back Hours */ 9552913Sache 95641787Smckay /* We have now the days since 01-01-1970 in tm */ 9572913Sache writertc(RTC_WDAY, (tm+4)%7); /* Write back Weekday */ 95813350Sache for (y = 1970, m = DAYSPERYEAR + LEAPYEAR(y); 95913350Sache tm >= m; 96013350Sache y++, m = DAYSPERYEAR + LEAPYEAR(y)) 96113350Sache tm -= m; 9622913Sache 9632913Sache /* Now we have the years in y and the day-of-the-year in tm */ 96413453Sache writertc(RTC_YEAR, bin2bcd(y%100)); /* Write back Year */ 96513350Sache#ifdef USE_RTC_CENTURY 96613445Sphk writertc(RTC_CENTURY, bin2bcd(y/100)); /* ... and Century */ 9673355Sache#endif 96813402Sbde for (m = 0; ; m++) { 96913402Sbde int ml; 9702913Sache 97113402Sbde ml = daysinmonth[m]; 97213402Sbde if (m == 1 && LEAPYEAR(y)) 97313402Sbde ml++; 97413402Sbde if (tm < ml) 97513402Sbde break; 97613402Sbde tm -= ml; 97713402Sbde } 97813402Sbde 97913445Sphk writertc(RTC_MONTH, bin2bcd(m + 1)); /* Write back Month */ 98013445Sphk writertc(RTC_DAY, bin2bcd(tm + 1)); /* Write back Month Day */ 9812913Sache 9825291Sbde /* Reenable RTC updates and interrupts. */ 98315345Snate writertc(RTC_STATUSB, rtc_statusb); 9844Srgrimes} 9854Srgrimes 98627560Sfsmp 9874Srgrimes/* 9885291Sbde * Start both clocks running. 9894Srgrimes */ 9905291Sbdevoid 9915291Sbdecpu_initclocks() 9924Srgrimes{ 9935291Sbde int diag; 99426949Sfsmp#ifdef APIC_IO 99566716Sjhb int apic_8254_trial; 99672240Sjhb void *clkdesc; 99725164Speter#endif /* APIC_IO */ 9984Srgrimes 99915345Snate if (statclock_disable) { 100015345Snate /* 100115345Snate * The stat interrupt mask is different without the 100215345Snate * statistics clock. Also, don't set the interrupt 100315345Snate * flag which would normally cause the RTC to generate 100415345Snate * interrupts. 100515345Snate */ 100615345Snate rtc_statusb = RTCSB_24HR; 100715345Snate } else { 100815345Snate /* Setting stathz to nonzero early helps avoid races. */ 100915345Snate stathz = RTC_NOPROFRATE; 101015345Snate profhz = RTC_PROFRATE; 101115345Snate } 10124Srgrimes 10135291Sbde /* Finish initializing 8253 timer 0. */ 101426949Sfsmp#ifdef APIC_IO 101527563Sfsmp 101638888Stegge apic_8254_intr = isa_apic_irq(0); 101734571Stegge apic_8254_trial = 0; 101834571Stegge if (apic_8254_intr >= 0 ) { 101934571Stegge if (apic_int_type(0, 0) == 3) 102034571Stegge apic_8254_trial = 1; 102134571Stegge } else { 102234571Stegge /* look for ExtInt on pin 0 */ 102334571Stegge if (apic_int_type(0, 0) == 3) { 102455420Stegge apic_8254_intr = apic_irq(0, 0); 102534571Stegge setup_8254_mixed_mode(); 102634571Stegge } else 102734571Stegge panic("APIC_IO: Cannot route 8254 interrupt to CPU"); 102827563Sfsmp } 102966716Sjhb 103072240Sjhb inthand_add("clk", apic_8254_intr, (driver_intr_t *)clkintr, NULL, 103172240Sjhb INTR_TYPE_CLK | INTR_FAST, &clkdesc); 103288322Sjhb mtx_lock_spin(&icu_lock); 103366716Sjhb INTREN(1 << apic_8254_intr); 103488322Sjhb mtx_unlock_spin(&icu_lock); 103566716Sjhb 103627696Sfsmp#else /* APIC_IO */ 103727563Sfsmp 103865557Sjasone /* 103965557Sjasone * XXX Check the priority of this interrupt handler. I 104065557Sjasone * couldn't find anything suitable in the BSD/OS code (grog, 104165557Sjasone * 19 July 2000). 104265557Sjasone */ 104372240Sjhb inthand_add("clk", 0, (driver_intr_t *)clkintr, NULL, 104472240Sjhb INTR_TYPE_CLK | INTR_FAST, NULL); 104588322Sjhb mtx_lock_spin(&icu_lock); 10464Srgrimes INTREN(IRQ0); 104788322Sjhb mtx_unlock_spin(&icu_lock); 104827696Sfsmp 104925164Speter#endif /* APIC_IO */ 105026949Sfsmp 10515291Sbde /* Initialize RTC. */ 10525291Sbde writertc(RTC_STATUSA, rtc_statusa); 10535291Sbde writertc(RTC_STATUSB, RTCSB_24HR); 105415345Snate 105515345Snate /* Don't bother enabling the statistics clock. */ 105666716Sjhb if (statclock_disable) 105715345Snate return; 10585291Sbde diag = rtcin(RTC_DIAG); 10595291Sbde if (diag != 0) 10605291Sbde printf("RTC BIOS diagnostic error %b\n", diag, RTCDG_BITS); 106127520Sfsmp 106226949Sfsmp#ifdef APIC_IO 106338888Stegge if (isa_apic_irq(8) != 8) 106427520Sfsmp panic("APIC RTC != 8"); 106566716Sjhb#endif /* APIC_IO */ 106628487Sfsmp 106772240Sjhb inthand_add("rtc", 8, (driver_intr_t *)rtcintr, NULL, 106872240Sjhb INTR_TYPE_CLK | INTR_FAST, NULL); 106966716Sjhb 107088322Sjhb mtx_lock_spin(&icu_lock); 107166716Sjhb#ifdef APIC_IO 107266716Sjhb INTREN(APIC_IRQ8); 107366716Sjhb#else 107466716Sjhb INTREN(IRQ8); 107566716Sjhb#endif /* APIC_IO */ 107688322Sjhb mtx_unlock_spin(&icu_lock); 107766716Sjhb 107866716Sjhb writertc(RTC_STATUSB, rtc_statusb); 107966716Sjhb 108066716Sjhb#ifdef APIC_IO 108165557Sjasone if (apic_8254_trial) { 108228487Sfsmp 108334571Stegge printf("APIC_IO: Testing 8254 interrupt delivery\n"); 108434571Stegge while (read_intr_count(8) < 6) 108535035Stegge ; /* nothing */ 108666716Sjhb if (read_intr_count(apic_8254_intr) < 3) { 108734571Stegge /* 108834571Stegge * The MP table is broken. 108934571Stegge * The 8254 was not connected to the specified pin 109034571Stegge * on the IO APIC. 109134571Stegge * Workaround: Limited variant of mixed mode. 109234571Stegge */ 109388322Sjhb mtx_lock_spin(&icu_lock); 109466716Sjhb INTRDIS(1 << apic_8254_intr); 109588322Sjhb mtx_unlock_spin(&icu_lock); 109666716Sjhb inthand_remove(clkdesc); 109734571Stegge printf("APIC_IO: Broken MP table detected: " 109855420Stegge "8254 is not connected to " 109955420Stegge "IOAPIC #%d intpin %d\n", 110055420Stegge int_to_apicintpin[apic_8254_intr].ioapic, 110155420Stegge int_to_apicintpin[apic_8254_intr].int_pin); 110255420Stegge /* 110355420Stegge * Revoke current ISA IRQ 0 assignment and 110455420Stegge * configure a fallback interrupt routing from 110555420Stegge * the 8254 Timer via the 8259 PIC to the 110655420Stegge * an ExtInt interrupt line on IOAPIC #0 intpin 0. 110755420Stegge * We reuse the low level interrupt handler number. 110855420Stegge */ 110955420Stegge if (apic_irq(0, 0) < 0) { 111055420Stegge revoke_apic_irq(apic_8254_intr); 111155420Stegge assign_apic_irq(0, 0, apic_8254_intr); 111255420Stegge } 111355420Stegge apic_8254_intr = apic_irq(0, 0); 111434571Stegge setup_8254_mixed_mode(); 111566716Sjhb inthand_add("clk", apic_8254_intr, 111666716Sjhb (driver_intr_t *)clkintr, NULL, 111772240Sjhb INTR_TYPE_CLK | INTR_FAST, NULL); 111888322Sjhb mtx_lock_spin(&icu_lock); 111966716Sjhb INTREN(1 << apic_8254_intr); 112088322Sjhb mtx_unlock_spin(&icu_lock); 112134571Stegge } 112234571Stegge 112334571Stegge } 112455420Stegge if (apic_int_type(0, 0) != 3 || 112555420Stegge int_to_apicintpin[apic_8254_intr].ioapic != 0 || 112655420Stegge int_to_apicintpin[apic_8254_intr].int_pin != 0) 112755420Stegge printf("APIC_IO: routing 8254 via IOAPIC #%d intpin %d\n", 112855420Stegge int_to_apicintpin[apic_8254_intr].ioapic, 112955420Stegge int_to_apicintpin[apic_8254_intr].int_pin); 113034571Stegge else 113155420Stegge printf("APIC_IO: " 113255420Stegge "routing 8254 via 8259 and IOAPIC #0 intpin 0\n"); 113334571Stegge#endif 113434571Stegge 11354Srgrimes} 11364Srgrimes 113734571Stegge#ifdef APIC_IO 113834571Steggestatic u_long 113934571Steggeread_intr_count(int vec) 114034571Stegge{ 114134571Stegge u_long *up; 114234571Stegge up = intr_countp[vec]; 114334571Stegge if (up) 114434571Stegge return *up; 114534571Stegge return 0UL; 114634571Stegge} 114734571Stegge 114834571Steggestatic void 114934571Steggesetup_8254_mixed_mode() 115034571Stegge{ 115134571Stegge /* 115234571Stegge * Allow 8254 timer to INTerrupt 8259: 115334571Stegge * re-initialize master 8259: 115434571Stegge * reset; prog 4 bytes, single ICU, edge triggered 115534571Stegge */ 115634571Stegge outb(IO_ICU1, 0x13); 115734571Stegge outb(IO_ICU1 + 1, NRSVIDT); /* start vector (unused) */ 115834571Stegge outb(IO_ICU1 + 1, 0x00); /* ignore slave */ 115934571Stegge outb(IO_ICU1 + 1, 0x03); /* auto EOI, 8086 */ 116034571Stegge outb(IO_ICU1 + 1, 0xfe); /* unmask INT0 */ 116134571Stegge 116234571Stegge /* program IO APIC for type 3 INT on INT0 */ 116334571Stegge if (ext_int_setup(0, 0) < 0) 116434571Stegge panic("8254 redirect via APIC pin0 impossible!"); 116534571Stegge} 116634571Stegge#endif 116734571Stegge 11684Srgrimesvoid 11691549Srgrimessetstatclockrate(int newhz) 11701549Srgrimes{ 11715291Sbde if (newhz == RTC_PROFRATE) 11722074Swollman rtc_statusa = RTCSA_DIVIDER | RTCSA_PROF; 11735291Sbde else 11742074Swollman rtc_statusa = RTCSA_DIVIDER | RTCSA_NOPROF; 11755291Sbde writertc(RTC_STATUSA, rtc_statusa); 11761549Srgrimes} 117715508Sbde 117815508Sbdestatic int 117962573Sphksysctl_machdep_i8254_freq(SYSCTL_HANDLER_ARGS) 118015508Sbde{ 118115508Sbde int error; 118215508Sbde u_int freq; 118315508Sbde 118415508Sbde /* 118515508Sbde * Use `i8254' instead of `timer' in external names because `timer' 118615508Sbde * is is too generic. Should use it everywhere. 118715508Sbde */ 118815508Sbde freq = timer_freq; 118948888Sbde error = sysctl_handle_int(oidp, &freq, sizeof(freq), req); 119017353Sbde if (error == 0 && req->newptr != NULL) { 119133690Sphk if (timer0_state != RELEASED) 119215508Sbde return (EBUSY); /* too much trouble to handle */ 119315508Sbde set_timer_freq(freq, hz); 119440610Sphk i8254_timecounter.tc_frequency = freq; 119558377Sphk tc_update(&i8254_timecounter); 119615508Sbde } 119715508Sbde return (error); 119815508Sbde} 119915508Sbde 120015508SbdeSYSCTL_PROC(_machdep, OID_AUTO, i8254_freq, CTLTYPE_INT | CTLFLAG_RW, 120148888Sbde 0, sizeof(u_int), sysctl_machdep_i8254_freq, "I", ""); 120215508Sbde 120315508Sbdestatic int 120462573Sphksysctl_machdep_tsc_freq(SYSCTL_HANDLER_ARGS) 120515508Sbde{ 120615508Sbde int error; 120715508Sbde u_int freq; 120815508Sbde 120948888Sbde if (tsc_timecounter.tc_frequency == 0) 121015508Sbde return (EOPNOTSUPP); 121132005Sphk freq = tsc_freq; 121248888Sbde error = sysctl_handle_int(oidp, &freq, sizeof(freq), req); 121333690Sphk if (error == 0 && req->newptr != NULL) { 121433690Sphk tsc_freq = freq; 121540610Sphk tsc_timecounter.tc_frequency = tsc_freq; 121658377Sphk tc_update(&tsc_timecounter); 121733690Sphk } 121815508Sbde return (error); 121915508Sbde} 122015508Sbde 122132054SphkSYSCTL_PROC(_machdep, OID_AUTO, tsc_freq, CTLTYPE_INT | CTLFLAG_RW, 122248888Sbde 0, sizeof(u_int), sysctl_machdep_tsc_freq, "I", ""); 122333690Sphk 122436441Sphkstatic unsigned 122536719Sphki8254_get_timecount(struct timecounter *tc) 122633690Sphk{ 122736198Sphk u_int count; 122833690Sphk u_int high, low; 122966716Sjhb u_int eflags; 123033690Sphk 123166716Sjhb eflags = read_eflags(); 123272200Sbmilekic mtx_lock_spin(&clock_lock); 123333690Sphk 123433690Sphk /* Select timer0 and latch counter value. */ 123533690Sphk outb(TIMER_MODE, TIMER_SEL0 | TIMER_LATCH); 123633690Sphk 123733690Sphk low = inb(TIMER_CNTR0); 123833690Sphk high = inb(TIMER_CNTR0); 123947588Sbde count = timer0_max_count - ((high << 8) | low); 124047588Sbde if (count < i8254_lastcount || 124147588Sbde (!i8254_ticked && (clkintr_pending || 124266716Sjhb ((count < 20 || (!(eflags & PSL_I) && count < timer0_max_count / 2u)) && 124347588Sbde#ifdef APIC_IO 124447588Sbde#define lapic_irr1 ((volatile u_int *)&lapic)[0x210 / 4] /* XXX XXX */ 124547588Sbde /* XXX this assumes that apic_8254_intr is < 24. */ 124647588Sbde (lapic_irr1 & (1 << apic_8254_intr)))) 124747588Sbde#else 124847588Sbde (inb(IO_ICU1) & 1))) 124947588Sbde#endif 125047588Sbde )) { 125133690Sphk i8254_ticked = 1; 125247588Sbde i8254_offset += timer0_max_count; 125333690Sphk } 125433690Sphk i8254_lastcount = count; 125533690Sphk count += i8254_offset; 125672200Sbmilekic mtx_unlock_spin(&clock_lock); 125733690Sphk return (count); 125833690Sphk} 125933690Sphk 126036441Sphkstatic unsigned 126136719Sphktsc_get_timecount(struct timecounter *tc) 126233690Sphk{ 126336198Sphk return (rdtsc()); 126433690Sphk} 126561994Smsmith 126689980Sbde#ifdef DEV_ISA 126761994Smsmith/* 126861994Smsmith * Attach to the ISA PnP descriptors for the timer and realtime clock. 126961994Smsmith */ 127061994Smsmithstatic struct isa_pnp_id attimer_ids[] = { 127161994Smsmith { 0x0001d041 /* PNP0100 */, "AT timer" }, 127261994Smsmith { 0x000bd041 /* PNP0B00 */, "AT realtime clock" }, 127361994Smsmith { 0 } 127461994Smsmith}; 127561994Smsmith 127661994Smsmithstatic int 127761994Smsmithattimer_probe(device_t dev) 127861994Smsmith{ 127961994Smsmith int result; 128061994Smsmith 128161994Smsmith if ((result = ISA_PNP_PROBE(device_get_parent(dev), dev, attimer_ids)) <= 0) 128261994Smsmith device_quiet(dev); 128361994Smsmith return(result); 128461994Smsmith} 128561994Smsmith 128661994Smsmithstatic int 128761994Smsmithattimer_attach(device_t dev) 128861994Smsmith{ 128961994Smsmith return(0); 129061994Smsmith} 129161994Smsmith 129261994Smsmithstatic device_method_t attimer_methods[] = { 129361994Smsmith /* Device interface */ 129461994Smsmith DEVMETHOD(device_probe, attimer_probe), 129561994Smsmith DEVMETHOD(device_attach, attimer_attach), 129661994Smsmith DEVMETHOD(device_detach, bus_generic_detach), 129761994Smsmith DEVMETHOD(device_shutdown, bus_generic_shutdown), 129861994Smsmith DEVMETHOD(device_suspend, bus_generic_suspend), /* XXX stop statclock? */ 129961994Smsmith DEVMETHOD(device_resume, bus_generic_resume), /* XXX restart statclock? */ 130061994Smsmith { 0, 0 } 130161994Smsmith}; 130261994Smsmith 130361994Smsmithstatic driver_t attimer_driver = { 130461994Smsmith "attimer", 130561994Smsmith attimer_methods, 130661994Smsmith 1, /* no softc */ 130761994Smsmith}; 130861994Smsmith 130961994Smsmithstatic devclass_t attimer_devclass; 131061994Smsmith 131161994SmsmithDRIVER_MODULE(attimer, isa, attimer_driver, attimer_devclass, 0, 0); 131282555SmsmithDRIVER_MODULE(attimer, acpi, attimer_driver, attimer_devclass, 0, 0); 131389980Sbde#endif /* DEV_ISA */ 1314