clock.c revision 15508
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 * $Id: clock.c,v 1.57 1996/04/22 19:40:28 nate Exp $ 38 */ 39 40/* 41 * inittodr, settodr and support routines written 42 * by Christoph Robitschko <chmr@edvz.tu-graz.ac.at> 43 * 44 * reintroduced and updated by Chris Stenton <chris@gnome.co.uk> 8/10/94 45 */ 46 47/* 48 * Primitive clock interrupt routines. 49 */ 50#include "opt_ddb.h" 51 52#include <sys/param.h> 53#include <sys/systm.h> 54#include <sys/time.h> 55#include <sys/kernel.h> 56#include <sys/sysctl.h> 57 58#include <machine/clock.h> 59#ifdef CLK_CALIBRATION_LOOP 60#include <machine/cons.h> 61#endif 62#include <machine/cpu.h> 63#include <machine/frame.h> 64 65#include <i386/isa/icu.h> 66#include <i386/isa/isa.h> 67#include <i386/isa/isa_device.h> 68#include <i386/isa/rtc.h> 69#include <i386/isa/timerreg.h> 70 71/* 72 * 32-bit time_t's can't reach leap years before 1904 or after 2036, so we 73 * can use a simple formula for leap years. 74 */ 75#define LEAPYEAR(y) ((u_int)(y) % 4 == 0) 76#define DAYSPERYEAR (31+28+31+30+31+30+31+31+30+31+30+31) 77 78#define TIMER_DIV(x) ((timer_freq + (x) / 2) / (x)) 79 80/* 81 * Time in timer cycles that it takes for microtime() to disable interrupts 82 * and latch the count. microtime() currently uses "cli; outb ..." so it 83 * normally takes less than 2 timer cycles. Add a few for cache misses. 84 * Add a few more to allow for latency in bogus calls to microtime() with 85 * interrupts already disabled. 86 */ 87#define TIMER0_LATCH_COUNT 20 88 89/* 90 * Minimum maximum count that we are willing to program into timer0. 91 * Must be large enough to guarantee that the timer interrupt handler 92 * returns before the next timer interrupt. Must be larger than 93 * TIMER0_LATCH_COUNT so that we don't have to worry about underflow in 94 * the calculation of timer0_overflow_threshold. 95 */ 96#define TIMER0_MIN_MAX_COUNT TIMER_DIV(20000) 97 98int adjkerntz; /* local offset from GMT in seconds */ 99int disable_rtc_set; /* disable resettodr() if != 0 */ 100int wall_cmos_clock; /* wall CMOS clock assumed if != 0 */ 101 102u_int idelayed; 103#if defined(I586_CPU) || defined(I686_CPU) 104unsigned i586_ctr_freq; 105unsigned i586_ctr_rate; 106long long i586_ctr_bias; 107long long i586_last_tick; 108unsigned long i586_avg_tick; 109#endif 110int statclock_disable; 111u_int stat_imask = SWI_CLOCK_MASK; 112int timer0_max_count; 113u_int timer0_overflow_threshold; 114u_int timer0_prescaler_count; 115 116static int beeping = 0; 117static u_int clk_imask = HWI_MASK | SWI_MASK; 118static const u_char daysinmonth[] = {31,28,31,30,31,30,31,31,30,31,30,31}; 119static u_int hardclock_max_count; 120/* 121 * XXX new_function and timer_func should not handle clockframes, but 122 * timer_func currently needs to hold hardclock to handle the 123 * timer0_state == 0 case. We should use register_intr()/unregister_intr() 124 * to switch between clkintr() and a slightly different timerintr(). 125 * This will require locking when acquiring and releasing timer0 - the 126 * current (nonexistent) locking doesn't seem to be adequate even now. 127 */ 128static void (*new_function) __P((struct clockframe *frame)); 129static u_int new_rate; 130static u_char rtc_statusa = RTCSA_DIVIDER | RTCSA_NOPROF; 131static u_char rtc_statusb = RTCSB_24HR | RTCSB_PINTR; 132#ifdef TIMER_FREQ 133static u_int timer_freq = TIMER_FREQ; 134#else 135static u_int timer_freq = 1193182; 136#endif 137static char timer0_state = 0; 138static char timer2_state = 0; 139static void (*timer_func) __P((struct clockframe *frame)) = hardclock; 140 141#if 0 142void 143clkintr(struct clockframe frame) 144{ 145 hardclock(&frame); 146 setdelayed(); 147} 148#else 149static void 150clkintr(struct clockframe frame) 151{ 152 timer_func(&frame); 153 switch (timer0_state) { 154 case 0: 155 setdelayed(); 156 break; 157 case 1: 158 if ((timer0_prescaler_count += timer0_max_count) 159 >= hardclock_max_count) { 160 hardclock(&frame); 161 setdelayed(); 162 timer0_prescaler_count -= hardclock_max_count; 163 } 164 break; 165 case 2: 166 setdelayed(); 167 timer0_max_count = TIMER_DIV(new_rate); 168 timer0_overflow_threshold = 169 timer0_max_count - TIMER0_LATCH_COUNT; 170 disable_intr(); 171 outb(TIMER_MODE, TIMER_SEL0 | TIMER_RATEGEN | TIMER_16BIT); 172 outb(TIMER_CNTR0, timer0_max_count & 0xff); 173 outb(TIMER_CNTR0, timer0_max_count >> 8); 174 enable_intr(); 175 timer0_prescaler_count = 0; 176 timer_func = new_function; 177 timer0_state = 1; 178 break; 179 case 3: 180 if ((timer0_prescaler_count += timer0_max_count) 181 >= hardclock_max_count) { 182 hardclock(&frame); 183 setdelayed(); 184 timer0_max_count = hardclock_max_count; 185 timer0_overflow_threshold = 186 timer0_max_count - TIMER0_LATCH_COUNT; 187 disable_intr(); 188 outb(TIMER_MODE, 189 TIMER_SEL0 | TIMER_RATEGEN | TIMER_16BIT); 190 outb(TIMER_CNTR0, timer0_max_count & 0xff); 191 outb(TIMER_CNTR0, timer0_max_count >> 8); 192 enable_intr(); 193 /* 194 * See microtime.s for this magic. 195 */ 196 time.tv_usec += (27645 * 197 (timer0_prescaler_count - hardclock_max_count)) 198 >> 15; 199 if (time.tv_usec >= 1000000) 200 time.tv_usec -= 1000000; 201 timer0_prescaler_count = 0; 202 timer_func = hardclock;; 203 timer0_state = 0; 204 } 205 break; 206 } 207} 208#endif 209 210int 211acquire_timer0(int rate, void (*function) __P((struct clockframe *frame))) 212{ 213 if (timer0_state || TIMER_DIV(rate) < TIMER0_MIN_MAX_COUNT || 214 !function) 215 return -1; 216 new_function = function; 217 new_rate = rate; 218 timer0_state = 2; 219 return 0; 220} 221 222int 223acquire_timer2(int mode) 224{ 225 if (timer2_state) 226 return -1; 227 timer2_state = 1; 228 outb(TIMER_MODE, TIMER_SEL2 | (mode &0x3f)); 229 return 0; 230} 231 232int 233release_timer0() 234{ 235 if (!timer0_state) 236 return -1; 237 timer0_state = 3; 238 return 0; 239} 240 241int 242release_timer2() 243{ 244 if (!timer2_state) 245 return -1; 246 timer2_state = 0; 247 outb(TIMER_MODE, TIMER_SEL2|TIMER_SQWAVE|TIMER_16BIT); 248 return 0; 249} 250 251/* 252 * This routine receives statistical clock interrupts from the RTC. 253 * As explained above, these occur at 128 interrupts per second. 254 * When profiling, we receive interrupts at a rate of 1024 Hz. 255 * 256 * This does not actually add as much overhead as it sounds, because 257 * when the statistical clock is active, the hardclock driver no longer 258 * needs to keep (inaccurate) statistics on its own. This decouples 259 * statistics gathering from scheduling interrupts. 260 * 261 * The RTC chip requires that we read status register C (RTC_INTR) 262 * to acknowledge an interrupt, before it will generate the next one. 263 */ 264static void 265rtcintr(struct clockframe frame) 266{ 267 u_char stat; 268 stat = rtcin(RTC_INTR); 269 if(stat & RTCIR_PERIOD) { 270 statclock(&frame); 271 } 272} 273 274#ifdef DDB 275static void 276DDB_printrtc(void) 277{ 278 printf("%02x/%02x/%02x %02x:%02x:%02x, A = %02x, B = %02x, C = %02x\n", 279 rtcin(RTC_YEAR), rtcin(RTC_MONTH), rtcin(RTC_DAY), 280 rtcin(RTC_HRS), rtcin(RTC_MIN), rtcin(RTC_SEC), 281 rtcin(RTC_STATUSA), rtcin(RTC_STATUSB), rtcin(RTC_INTR)); 282} 283#endif 284 285static int 286getit(void) 287{ 288 int high, low; 289 290 disable_intr(); 291 /* select timer0 and latch counter value */ 292 outb(TIMER_MODE, TIMER_SEL0); 293 low = inb(TIMER_CNTR0); 294 high = inb(TIMER_CNTR0); 295 enable_intr(); 296 return ((high << 8) | low); 297} 298 299/* 300 * Wait "n" microseconds. 301 * Relies on timer 1 counting down from (timer_freq / hz) 302 * Note: timer had better have been programmed before this is first used! 303 */ 304void 305DELAY(int n) 306{ 307 int prev_tick, tick, ticks_left, sec, usec; 308 309#ifdef DELAYDEBUG 310 int getit_calls = 1; 311 int n1; 312 static int state = 0; 313 314 if (state == 0) { 315 state = 1; 316 for (n1 = 1; n1 <= 10000000; n1 *= 10) 317 DELAY(n1); 318 state = 2; 319 } 320 if (state == 1) 321 printf("DELAY(%d)...", n); 322#endif 323 /* 324 * Read the counter first, so that the rest of the setup overhead is 325 * counted. Guess the initial overhead is 20 usec (on most systems it 326 * takes about 1.5 usec for each of the i/o's in getit(). The loop 327 * takes about 6 usec on a 486/33 and 13 usec on a 386/20. The 328 * multiplications and divisions to scale the count take a while). 329 */ 330 prev_tick = getit(); 331 n -= 20; 332 /* 333 * Calculate (n * (timer_freq / 1e6)) without using floating point 334 * and without any avoidable overflows. 335 */ 336 sec = n / 1000000; 337 usec = n - sec * 1000000; 338 ticks_left = sec * timer_freq 339 + usec * (timer_freq / 1000000) 340 + usec * ((timer_freq % 1000000) / 1000) / 1000 341 + usec * (timer_freq % 1000) / 1000000; 342 if (n < 0) 343 ticks_left = 0; /* XXX timer_freq is unsigned */ 344 345 while (ticks_left > 0) { 346 tick = getit(); 347#ifdef DELAYDEBUG 348 ++getit_calls; 349#endif 350 if (tick > prev_tick) 351 ticks_left -= prev_tick - (tick - timer0_max_count); 352 else 353 ticks_left -= prev_tick - tick; 354 prev_tick = tick; 355 } 356#ifdef DELAYDEBUG 357 if (state == 1) 358 printf(" %d calls to getit() at %d usec each\n", 359 getit_calls, (n + 5) / getit_calls); 360#endif 361} 362 363static void 364sysbeepstop(void *chan) 365{ 366 outb(IO_PPI, inb(IO_PPI)&0xFC); /* disable counter2 output to speaker */ 367 release_timer2(); 368 beeping = 0; 369} 370 371int 372sysbeep(int pitch, int period) 373{ 374 375 if (acquire_timer2(TIMER_SQWAVE|TIMER_16BIT)) 376 return -1; 377 disable_intr(); 378 outb(TIMER_CNTR2, pitch); 379 outb(TIMER_CNTR2, (pitch>>8)); 380 enable_intr(); 381 if (!beeping) { 382 outb(IO_PPI, inb(IO_PPI) | 3); /* enable counter2 output to speaker */ 383 beeping = period; 384 timeout(sysbeepstop, (void *)NULL, period); 385 } 386 return 0; 387} 388 389/* 390 * RTC support routines 391 */ 392 393int 394rtcin(reg) 395 int reg; 396{ 397 u_char val; 398 399 outb(IO_RTC, reg); 400 inb(0x84); 401 val = inb(IO_RTC + 1); 402 inb(0x84); 403 return (val); 404} 405 406static __inline void 407writertc(u_char reg, u_char val) 408{ 409 outb(IO_RTC, reg); 410 outb(IO_RTC + 1, val); 411} 412 413static __inline int 414readrtc(int port) 415{ 416 return(bcd2bin(rtcin(port))); 417} 418 419static u_int 420calibrate_clocks(void) 421{ 422 u_int count, prev_count, tot_count; 423 int sec, start_sec, timeout; 424 425 printf("Calibrating clock(s) relative to mc146818A clock ... "); 426 if (!(rtcin(RTC_STATUSD) & RTCSD_PWR)) 427 goto fail; 428 timeout = 100000000; 429 430 /* Read the mc146818A seconds counter. */ 431 for (;;) { 432 if (!(rtcin(RTC_STATUSA) & RTCSA_TUP)) { 433 sec = rtcin(RTC_SEC); 434 break; 435 } 436 if (--timeout == 0) 437 goto fail; 438 } 439 440 /* Wait for the mC146818A seconds counter to change. */ 441 start_sec = sec; 442 for (;;) { 443 if (!(rtcin(RTC_STATUSA) & RTCSA_TUP)) { 444 sec = rtcin(RTC_SEC); 445 if (sec != start_sec) 446 break; 447 } 448 if (--timeout == 0) 449 goto fail; 450 } 451 452 /* Start keeping track of the i8254 counter. */ 453 prev_count = getit(); 454 if (prev_count == 0 || prev_count > timer0_max_count) 455 goto fail; 456 tot_count = 0; 457 458#if defined(I586_CPU) || defined(I686_CPU) 459 if (cpu_class == CPUCLASS_586 || cpu_class == CPUCLASS_686) 460 wrmsr(0x10, 0LL); /* XXX 0x10 is the MSR for the TSC */ 461#endif 462 463 /* 464 * Wait for the mc146818A seconds counter to change. Read the i8254 465 * counter for each iteration since this is convenient and only 466 * costs a few usec of inaccuracy. The timing of the final reads 467 * of the counters almost matches the timing of the initial reads, 468 * so the main cause of inaccuracy is the varying latency from 469 * inside getit() or rtcin(RTC_STATUSA) to the beginning of the 470 * rtcin(RTC_SEC) that returns a changed seconds count. The 471 * maximum inaccuracy from this cause is < 10 usec on 486's. 472 */ 473 start_sec = sec; 474 for (;;) { 475 if (!(rtcin(RTC_STATUSA) & RTCSA_TUP)) 476 sec = rtcin(RTC_SEC); 477 count = getit(); 478 if (count == 0 || count > timer0_max_count) 479 goto fail; 480 if (count > prev_count) 481 tot_count += prev_count - (count - timer0_max_count); 482 else 483 tot_count += prev_count - count; 484 prev_count = count; 485 if (sec != start_sec) 486 break; 487 if (--timeout == 0) 488 goto fail; 489 } 490 491#if defined(I586_CPU) || defined(I686_CPU) 492 /* 493 * Read the cpu cycle counter. The timing considerations are 494 * similar to those for the i8254 clock. 495 */ 496 if (cpu_class == CPUCLASS_586 || cpu_class == CPUCLASS_686) { 497 unsigned long long i586_count; 498 499 i586_count = rdtsc(); 500 i586_ctr_freq = i586_count; 501 i586_ctr_rate = (i586_count << I586_CTR_RATE_SHIFT) / 1000000; 502 printf("i586 clock: %u Hz, ", i586_ctr_freq); 503 } 504#endif 505 506 printf("i8254 clock: %u Hz\n", tot_count); 507 return (tot_count); 508 509fail: 510 printf("failed, using default i8254 clock of %u Hz\n", timer_freq); 511 return (timer_freq); 512} 513 514static void 515set_timer_freq(u_int freq, int intr_freq) 516{ 517 u_long ef; 518 519 ef = read_eflags(); 520 timer_freq = freq; 521 timer0_max_count = hardclock_max_count = TIMER_DIV(intr_freq); 522 timer0_overflow_threshold = timer0_max_count - TIMER0_LATCH_COUNT; 523 outb(TIMER_MODE, TIMER_SEL0 | TIMER_RATEGEN | TIMER_16BIT); 524 outb(TIMER_CNTR0, timer0_max_count & 0xff); 525 outb(TIMER_CNTR0, timer0_max_count >> 8); 526 write_eflags(ef); 527} 528 529/* 530 * Initialize 8253 timer 0 early so that it can be used in DELAY(). 531 * XXX initialization of other timers is unintentionally left blank. 532 */ 533void 534startrtclock() 535{ 536 u_int delta, freq; 537 538 writertc(RTC_STATUSA, rtc_statusa); 539 writertc(RTC_STATUSB, RTCSB_24HR); 540 541 /* 542 * Temporarily calibrate with a high intr_freq to get a low 543 * timer0_max_count to help detect bogus i8254 counts. 544 */ 545 set_timer_freq(timer_freq, 20000); 546 freq = calibrate_clocks(); 547#ifdef CLK_CALIBRATION_LOOP 548 if (bootverbose) { 549 printf( 550 "Press a key on the console to abort clock calibration\n"); 551 while (!cncheckc()) 552 calibrate_clocks(); 553 } 554#endif 555 556 /* 557 * Use the calibrated i8254 frequency if it seems reasonable. 558 * Otherwise use the default, and don't use the calibrated i586 559 * frequency. 560 */ 561 delta = freq > timer_freq ? freq - timer_freq : timer_freq - freq; 562 if (delta < timer_freq / 100) { 563#ifndef CLK_USE_I8254_CALIBRATION 564 printf( 565"CLK_USE_I8254_CALIBRATION not specified - using default frequency\n"); 566 freq = timer_freq; 567#endif 568 timer_freq = freq; 569 } else { 570 printf("%d Hz differs from default of %d Hz by more than 1%%\n", 571 freq, timer_freq); 572#if defined(I586_CPU) || defined(I686_CPU) 573 i586_ctr_freq = 0; 574 i586_ctr_rate = 0; 575#endif 576 } 577 578 set_timer_freq(timer_freq, hz); 579 580#if defined(I586_CPU) || defined(I686_CPU) 581#ifndef CLK_USE_I586_CALIBRATION 582 if (i586_ctr_rate != 0) { 583 printf( 584"CLK_USE_I586_CALIBRATION not specified - using old calibration method\n"); 585 i586_ctr_freq = 0; 586 i586_ctr_rate = 0; 587 } 588#endif 589 if (i586_ctr_rate == 0 && 590 (cpu_class == CPUCLASS_586 || cpu_class == CPUCLASS_686)) { 591 /* 592 * Calibration of the i586 clock relative to the mc146818A 593 * clock failed. Do a less accurate calibration relative 594 * to the i8254 clock. 595 */ 596 unsigned long long i586_count; 597 598 wrmsr(0x10, 0LL); /* XXX */ 599 DELAY(1000000); 600 i586_count = rdtsc(); 601 i586_ctr_rate = (i586_count << I586_CTR_RATE_SHIFT) / 1000000; 602 printf("i586 clock: %u Hz\n", i586_ctr_freq); 603 } 604#endif 605} 606 607/* 608 * Initialize the time of day register, based on the time base which is, e.g. 609 * from a filesystem. 610 */ 611void 612inittodr(time_t base) 613{ 614 unsigned long sec, days; 615 int yd; 616 int year, month; 617 int y, m, s; 618 619 s = splclock(); 620 time.tv_sec = base; 621 time.tv_usec = 0; 622 splx(s); 623 624 /* Look if we have a RTC present and the time is valid */ 625 if (!(rtcin(RTC_STATUSD) & RTCSD_PWR)) 626 goto wrong_time; 627 628 /* wait for time update to complete */ 629 /* If RTCSA_TUP is zero, we have at least 244us before next update */ 630 while (rtcin(RTC_STATUSA) & RTCSA_TUP); 631 632 days = 0; 633#ifdef USE_RTC_CENTURY 634 year = readrtc(RTC_YEAR) + readrtc(RTC_CENTURY) * 100; 635#else 636 year = readrtc(RTC_YEAR) + 1900; 637 if (year < 1970) 638 year += 100; 639#endif 640 if (year < 1970) 641 goto wrong_time; 642 month = readrtc(RTC_MONTH); 643 for (m = 1; m < month; m++) 644 days += daysinmonth[m-1]; 645 if ((month > 2) && LEAPYEAR(year)) 646 days ++; 647 days += readrtc(RTC_DAY) - 1; 648 yd = days; 649 for (y = 1970; y < year; y++) 650 days += DAYSPERYEAR + LEAPYEAR(y); 651 sec = ((( days * 24 + 652 readrtc(RTC_HRS)) * 60 + 653 readrtc(RTC_MIN)) * 60 + 654 readrtc(RTC_SEC)); 655 /* sec now contains the number of seconds, since Jan 1 1970, 656 in the local time zone */ 657 658 sec += tz.tz_minuteswest * 60 + (wall_cmos_clock ? adjkerntz : 0); 659 660 s = splclock(); 661 time.tv_sec = sec; 662 splx(s); 663 return; 664 665wrong_time: 666 printf("Invalid time in real time clock.\n"); 667 printf("Check and reset the date immediately!\n"); 668} 669 670/* 671 * Write system time back to RTC 672 */ 673void 674resettodr() 675{ 676 unsigned long tm; 677 int y, m, s; 678 679 if (disable_rtc_set) 680 return; 681 682 s = splclock(); 683 tm = time.tv_sec; 684 splx(s); 685 686 /* Disable RTC updates and interrupts. */ 687 writertc(RTC_STATUSB, RTCSB_HALT | RTCSB_24HR); 688 689 /* Calculate local time to put in RTC */ 690 691 tm -= tz.tz_minuteswest * 60 + (wall_cmos_clock ? adjkerntz : 0); 692 693 writertc(RTC_SEC, bin2bcd(tm%60)); tm /= 60; /* Write back Seconds */ 694 writertc(RTC_MIN, bin2bcd(tm%60)); tm /= 60; /* Write back Minutes */ 695 writertc(RTC_HRS, bin2bcd(tm%24)); tm /= 24; /* Write back Hours */ 696 697 /* We have now the days since 01-01-1970 in tm */ 698 writertc(RTC_WDAY, (tm+4)%7); /* Write back Weekday */ 699 for (y = 1970, m = DAYSPERYEAR + LEAPYEAR(y); 700 tm >= m; 701 y++, m = DAYSPERYEAR + LEAPYEAR(y)) 702 tm -= m; 703 704 /* Now we have the years in y and the day-of-the-year in tm */ 705 writertc(RTC_YEAR, bin2bcd(y%100)); /* Write back Year */ 706#ifdef USE_RTC_CENTURY 707 writertc(RTC_CENTURY, bin2bcd(y/100)); /* ... and Century */ 708#endif 709 for (m = 0; ; m++) { 710 int ml; 711 712 ml = daysinmonth[m]; 713 if (m == 1 && LEAPYEAR(y)) 714 ml++; 715 if (tm < ml) 716 break; 717 tm -= ml; 718 } 719 720 writertc(RTC_MONTH, bin2bcd(m + 1)); /* Write back Month */ 721 writertc(RTC_DAY, bin2bcd(tm + 1)); /* Write back Month Day */ 722 723 /* Reenable RTC updates and interrupts. */ 724 writertc(RTC_STATUSB, rtc_statusb); 725} 726 727/* 728 * Start both clocks running. 729 */ 730void 731cpu_initclocks() 732{ 733 int diag; 734 735 if (statclock_disable) { 736 /* 737 * The stat interrupt mask is different without the 738 * statistics clock. Also, don't set the interrupt 739 * flag which would normally cause the RTC to generate 740 * interrupts. 741 */ 742 stat_imask = HWI_MASK | SWI_MASK; 743 rtc_statusb = RTCSB_24HR; 744 } else { 745 /* Setting stathz to nonzero early helps avoid races. */ 746 stathz = RTC_NOPROFRATE; 747 profhz = RTC_PROFRATE; 748 } 749 750 /* Finish initializing 8253 timer 0. */ 751 register_intr(/* irq */ 0, /* XXX id */ 0, /* flags */ 0, 752 /* XXX */ (inthand2_t *)clkintr, &clk_imask, 753 /* unit */ 0); 754 INTREN(IRQ0); 755#if defined(I586_CPU) || defined(I686_CPU) 756 /* 757 * Finish setting up anti-jitter measures. 758 */ 759 if (i586_ctr_rate) { 760 i586_last_tick = rdtsc(); 761 i586_ctr_bias = i586_last_tick; 762 } 763#endif 764 765 /* Initialize RTC. */ 766 writertc(RTC_STATUSA, rtc_statusa); 767 writertc(RTC_STATUSB, RTCSB_24HR); 768 769 /* Don't bother enabling the statistics clock. */ 770 if (statclock_disable) 771 return; 772 diag = rtcin(RTC_DIAG); 773 if (diag != 0) 774 printf("RTC BIOS diagnostic error %b\n", diag, RTCDG_BITS); 775 register_intr(/* irq */ 8, /* XXX id */ 1, /* flags */ 0, 776 /* XXX */ (inthand2_t *)rtcintr, &stat_imask, 777 /* unit */ 0); 778 INTREN(IRQ8); 779 writertc(RTC_STATUSB, rtc_statusb); 780} 781 782void 783setstatclockrate(int newhz) 784{ 785 if (newhz == RTC_PROFRATE) 786 rtc_statusa = RTCSA_DIVIDER | RTCSA_PROF; 787 else 788 rtc_statusa = RTCSA_DIVIDER | RTCSA_NOPROF; 789 writertc(RTC_STATUSA, rtc_statusa); 790} 791 792static int 793sysctl_machdep_i8254_freq SYSCTL_HANDLER_ARGS 794{ 795 int error; 796 u_int freq; 797 798 /* 799 * Use `i8254' instead of `timer' in external names because `timer' 800 * is is too generic. Should use it everywhere. 801 */ 802 freq = timer_freq; 803 error = sysctl_handle_opaque(oidp, &freq, sizeof freq, req); 804 if (error == 0 && freq != timer_freq) { 805 if (timer0_state != 0) 806 return (EBUSY); /* too much trouble to handle */ 807 set_timer_freq(freq, hz); 808 } 809 return (error); 810} 811 812SYSCTL_PROC(_machdep, OID_AUTO, i8254_freq, CTLTYPE_INT | CTLFLAG_RW, 813 0, sizeof(u_int), sysctl_machdep_i8254_freq, "I", ""); 814 815#if defined(I586_CPU) || defined(I686_CPU) 816static int 817sysctl_machdep_i586_freq SYSCTL_HANDLER_ARGS 818{ 819 int error; 820 u_int freq; 821 822 if (i586_ctr_rate == 0) 823 return (EOPNOTSUPP); 824 freq = i586_ctr_freq; 825 error = sysctl_handle_opaque(oidp, &freq, sizeof freq, req); 826 if (error == 0 && freq != i586_ctr_freq) { 827 i586_ctr_freq = freq; 828 i586_ctr_rate = ((unsigned long long)freq << 829 I586_CTR_RATE_SHIFT) / 1000000; 830 } 831 return (error); 832} 833 834SYSCTL_PROC(_machdep, OID_AUTO, i586_freq, CTLTYPE_INT | CTLFLAG_RW, 835 0, sizeof(u_int), sysctl_machdep_i586_freq, "I", ""); 836#endif /* defined(I586_CPU) || defined(I686_CPU) */ 837