pcrtc.c revision 16359
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.58 1996/05/01 08:39:02 bde 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 * modified for PC98 49 * $Id: clock.c,v 1.7 1994/03/26 22:56:13 kakefuda Exp kakefuda $ 50 */ 51 52/* 53 * Primitive clock interrupt routines. 54 */ 55#include "opt_ddb.h" 56 57#include <sys/param.h> 58#include <sys/systm.h> 59#include <sys/time.h> 60#include <sys/kernel.h> 61#include <sys/sysctl.h> 62 63#include <machine/clock.h> 64#ifdef CLK_CALIBRATION_LOOP 65#include <machine/cons.h> 66#endif 67#include <machine/cpu.h> 68#include <machine/frame.h> 69 70#ifdef PC98 71#include <sys/syslog.h> 72#include <pc98/pc98/icu.h> 73#include <pc98/pc98/pc98.h> 74#include <pc98/pc98/pc98_device.h> 75#include <pc98/pc98/timerreg.h> 76#else 77#include <i386/isa/icu.h> 78#include <i386/isa/isa.h> 79#include <i386/isa/isa_device.h> 80#include <i386/isa/rtc.h> 81#include <i386/isa/timerreg.h> 82#endif 83 84/* 85 * 32-bit time_t's can't reach leap years before 1904 or after 2036, so we 86 * can use a simple formula for leap years. 87 */ 88#define LEAPYEAR(y) ((u_int)(y) % 4 == 0) 89#define DAYSPERYEAR (31+28+31+30+31+30+31+31+30+31+30+31) 90 91#define TIMER_DIV(x) ((timer_freq + (x) / 2) / (x)) 92 93/* 94 * Time in timer cycles that it takes for microtime() to disable interrupts 95 * and latch the count. microtime() currently uses "cli; outb ..." so it 96 * normally takes less than 2 timer cycles. Add a few for cache misses. 97 * Add a few more to allow for latency in bogus calls to microtime() with 98 * interrupts already disabled. 99 */ 100#define TIMER0_LATCH_COUNT 20 101 102/* 103 * Minimum maximum count that we are willing to program into timer0. 104 * Must be large enough to guarantee that the timer interrupt handler 105 * returns before the next timer interrupt. Must be larger than 106 * TIMER0_LATCH_COUNT so that we don't have to worry about underflow in 107 * the calculation of timer0_overflow_threshold. 108 */ 109#define TIMER0_MIN_MAX_COUNT TIMER_DIV(20000) 110 111int adjkerntz; /* local offset from GMT in seconds */ 112int disable_rtc_set; /* disable resettodr() if != 0 */ 113int wall_cmos_clock; /* wall CMOS clock assumed if != 0 */ 114 115u_int idelayed; 116#if defined(I586_CPU) || defined(I686_CPU) 117unsigned i586_ctr_freq; 118unsigned i586_ctr_rate; 119long long i586_ctr_bias; 120long long i586_last_tick; 121unsigned long i586_avg_tick; 122#endif 123int statclock_disable; 124u_int stat_imask = SWI_CLOCK_MASK; 125int timer0_max_count; 126u_int timer0_overflow_threshold; 127u_int timer0_prescaler_count; 128 129static int beeping = 0; 130static u_int clk_imask = HWI_MASK | SWI_MASK; 131static const u_char daysinmonth[] = {31,28,31,30,31,30,31,31,30,31,30,31}; 132static u_int hardclock_max_count; 133/* 134 * XXX new_function and timer_func should not handle clockframes, but 135 * timer_func currently needs to hold hardclock to handle the 136 * timer0_state == 0 case. We should use register_intr()/unregister_intr() 137 * to switch between clkintr() and a slightly different timerintr(). 138 * This will require locking when acquiring and releasing timer0 - the 139 * current (nonexistent) locking doesn't seem to be adequate even now. 140 */ 141static void (*new_function) __P((struct clockframe *frame)); 142static u_int new_rate; 143#ifndef PC98 144static u_char rtc_statusa = RTCSA_DIVIDER | RTCSA_NOPROF; 145static u_char rtc_statusb = RTCSB_24HR | RTCSB_PINTR; 146#endif 147#ifdef TIMER_FREQ 148static u_int timer_freq = TIMER_FREQ; 149#else 150#ifdef PC98 151#ifndef AUTO_CLOCK 152#ifndef PC98_8M 153static u_int timer_freq = 2457600; 154#else /* !PC98_8M */ 155static u_int timer_freq = 1996800; 156#endif /* PC98_8M */ 157#else /* AUTO_CLOCK */ 158static u_int timer_freq = 2457600; 159#endif /* AUTO_CLOCK */ 160#else /* IBM-PC */ 161static u_int timer_freq = 1193182; 162#endif /* PC98 */ 163#endif 164static char timer0_state = 0; 165#ifdef PC98 166static char timer1_state = 0; 167#endif 168static char timer2_state = 0; 169static void (*timer_func) __P((struct clockframe *frame)) = hardclock; 170int rtc_inb __P((void)); 171 172#if 0 173void 174clkintr(struct clockframe frame) 175{ 176 hardclock(&frame); 177 setdelayed(); 178} 179#else 180static void 181clkintr(struct clockframe frame) 182{ 183 timer_func(&frame); 184 switch (timer0_state) { 185 case 0: 186 setdelayed(); 187 break; 188 case 1: 189 if ((timer0_prescaler_count += timer0_max_count) 190 >= hardclock_max_count) { 191 hardclock(&frame); 192 setdelayed(); 193 timer0_prescaler_count -= hardclock_max_count; 194 } 195 break; 196 case 2: 197 setdelayed(); 198 timer0_max_count = TIMER_DIV(new_rate); 199 timer0_overflow_threshold = 200 timer0_max_count - TIMER0_LATCH_COUNT; 201 disable_intr(); 202 outb(TIMER_MODE, TIMER_SEL0 | TIMER_RATEGEN | TIMER_16BIT); 203 outb(TIMER_CNTR0, timer0_max_count & 0xff); 204 outb(TIMER_CNTR0, timer0_max_count >> 8); 205 enable_intr(); 206 timer0_prescaler_count = 0; 207 timer_func = new_function; 208 timer0_state = 1; 209 break; 210 case 3: 211 if ((timer0_prescaler_count += timer0_max_count) 212 >= hardclock_max_count) { 213 hardclock(&frame); 214 setdelayed(); 215 timer0_max_count = hardclock_max_count; 216 timer0_overflow_threshold = 217 timer0_max_count - TIMER0_LATCH_COUNT; 218 disable_intr(); 219 outb(TIMER_MODE, 220 TIMER_SEL0 | TIMER_RATEGEN | TIMER_16BIT); 221 outb(TIMER_CNTR0, timer0_max_count & 0xff); 222 outb(TIMER_CNTR0, timer0_max_count >> 8); 223 enable_intr(); 224 /* 225 * See microtime.s for this magic. 226 */ 227#ifdef PC98 228#ifndef AUTO_CLOCK 229#ifndef PC98_8M 230 time.tv_usec += (6667 * 231 (timer0_prescaler_count - hardclock_max_count)) 232 >> 14; 233#else /* PC98_8M */ 234 time.tv_usec += (16411 * 235 (timer0_prescaler_count - hardclock_max_count)) 236 >> 15; 237#endif /* PC98_8M */ 238#else /* AUTO_CLOCK */ 239 if (pc98_machine_type & M_8M) { 240 /* PC98_8M */ 241 time.tv_usec += (16411 * 242 (timer0_prescaler_count - 243 hardclock_max_count)) >> 15; 244 } else { 245 time.tv_usec += (6667 * 246 (timer0_prescaler_count - 247 hardclock_max_count)) >> 14; 248 } 249#endif /* AUTO_CLOCK */ 250#else /* IBM-PC */ 251 time.tv_usec += (27645 * 252 (timer0_prescaler_count - hardclock_max_count)) 253 >> 15; 254#endif /* PC98 */ 255 if (time.tv_usec >= 1000000) 256 time.tv_usec -= 1000000; 257 timer0_prescaler_count = 0; 258 timer_func = hardclock;; 259 timer0_state = 0; 260 } 261 break; 262 } 263} 264#endif 265 266int 267acquire_timer0(int rate, void (*function) __P((struct clockframe *frame))) 268{ 269 if (timer0_state || TIMER_DIV(rate) < TIMER0_MIN_MAX_COUNT || 270 !function) 271 return -1; 272 new_function = function; 273 new_rate = rate; 274 timer0_state = 2; 275 return 0; 276} 277 278#ifdef PC98 279int 280acquire_timer1(int mode) 281{ 282 if (timer1_state) 283 return -1; 284 timer1_state = 1; 285 outb(TIMER_MODE, TIMER_SEL1 | (mode &0x3f)); 286 return 0; 287} 288#endif 289 290int 291acquire_timer2(int mode) 292{ 293 if (timer2_state) 294 return -1; 295 timer2_state = 1; 296 outb(TIMER_MODE, TIMER_SEL2 | (mode &0x3f)); 297 return 0; 298} 299 300int 301release_timer0() 302{ 303 if (!timer0_state) 304 return -1; 305 timer0_state = 3; 306 return 0; 307} 308 309#ifdef PC98 310int 311release_timer1() 312{ 313 if (!timer1_state) 314 return -1; 315 timer1_state = 0; 316 outb(TIMER_MODE, TIMER_SEL1|TIMER_SQWAVE|TIMER_16BIT); 317 return 0; 318} 319#endif 320 321int 322release_timer2() 323{ 324 if (!timer2_state) 325 return -1; 326 timer2_state = 0; 327 outb(TIMER_MODE, TIMER_SEL2|TIMER_SQWAVE|TIMER_16BIT); 328 return 0; 329} 330 331#ifndef PC98 332/* 333 * This routine receives statistical clock interrupts from the RTC. 334 * As explained above, these occur at 128 interrupts per second. 335 * When profiling, we receive interrupts at a rate of 1024 Hz. 336 * 337 * This does not actually add as much overhead as it sounds, because 338 * when the statistical clock is active, the hardclock driver no longer 339 * needs to keep (inaccurate) statistics on its own. This decouples 340 * statistics gathering from scheduling interrupts. 341 * 342 * The RTC chip requires that we read status register C (RTC_INTR) 343 * to acknowledge an interrupt, before it will generate the next one. 344 */ 345static void 346rtcintr(struct clockframe frame) 347{ 348 u_char stat; 349 stat = rtcin(RTC_INTR); 350 if(stat & RTCIR_PERIOD) { 351 statclock(&frame); 352 } 353} 354 355#ifdef DDB 356static void 357DDB_printrtc(void) 358{ 359 printf("%02x/%02x/%02x %02x:%02x:%02x, A = %02x, B = %02x, C = %02x\n", 360 rtcin(RTC_YEAR), rtcin(RTC_MONTH), rtcin(RTC_DAY), 361 rtcin(RTC_HRS), rtcin(RTC_MIN), rtcin(RTC_SEC), 362 rtcin(RTC_STATUSA), rtcin(RTC_STATUSB), rtcin(RTC_INTR)); 363} 364#endif 365#endif /* for PC98 */ 366 367static int 368getit(void) 369{ 370 int high, low; 371 372 disable_intr(); 373 /* select timer0 and latch counter value */ 374 outb(TIMER_MODE, TIMER_SEL0); 375 low = inb(TIMER_CNTR0); 376 high = inb(TIMER_CNTR0); 377 enable_intr(); 378 return ((high << 8) | low); 379} 380 381/* 382 * Wait "n" microseconds. 383 * Relies on timer 1 counting down from (timer_freq / hz) 384 * Note: timer had better have been programmed before this is first used! 385 */ 386void 387DELAY(int n) 388{ 389 int prev_tick, tick, ticks_left, sec, usec; 390 391#ifdef DELAYDEBUG 392 int getit_calls = 1; 393 int n1; 394 static int state = 0; 395 396 if (state == 0) { 397 state = 1; 398 for (n1 = 1; n1 <= 10000000; n1 *= 10) 399 DELAY(n1); 400 state = 2; 401 } 402 if (state == 1) 403 printf("DELAY(%d)...", n); 404#endif 405 /* 406 * Read the counter first, so that the rest of the setup overhead is 407 * counted. Guess the initial overhead is 20 usec (on most systems it 408 * takes about 1.5 usec for each of the i/o's in getit(). The loop 409 * takes about 6 usec on a 486/33 and 13 usec on a 386/20. The 410 * multiplications and divisions to scale the count take a while). 411 */ 412 prev_tick = getit(); 413 n -= 20; 414 /* 415 * Calculate (n * (timer_freq / 1e6)) without using floating point 416 * Calculate (n * (TIMER_FREQ / 1e6)) without using floating point 417 * and without any avoidable overflows. 418 */ 419 sec = n / 1000000; 420 usec = n - sec * 1000000; 421 ticks_left = sec * timer_freq 422 + usec * (timer_freq / 1000000) 423 + usec * ((timer_freq % 1000000) / 1000) / 1000 424 + usec * (timer_freq % 1000) / 1000000; 425 if (n < 0) 426 ticks_left = 0; /* XXX timer_freq is unsigned */ 427 428 while (ticks_left > 0) { 429 tick = getit(); 430#ifdef DELAYDEBUG 431 ++getit_calls; 432#endif 433 if (tick > prev_tick) 434 ticks_left -= prev_tick - (tick - timer0_max_count); 435 else 436 ticks_left -= prev_tick - tick; 437 prev_tick = tick; 438 } 439#ifdef DELAYDEBUG 440 if (state == 1) 441 printf(" %d calls to getit() at %d usec each\n", 442 getit_calls, (n + 5) / getit_calls); 443#endif 444} 445 446static void 447sysbeepstop(void *chan) 448{ 449#ifdef PC98 /* PC98 */ 450 outb(IO_PPI, inb(IO_PPI)|0x08); /* disable counter1 output to speaker */ 451 release_timer1(); 452#else 453 outb(IO_PPI, inb(IO_PPI)&0xFC); /* disable counter2 output to speaker */ 454 release_timer2(); 455#endif 456 beeping = 0; 457} 458 459int 460sysbeep(int pitch, int period) 461{ 462#ifdef PC98 463 if (acquire_timer1(TIMER_SQWAVE|TIMER_16BIT)) 464 return -1; 465 disable_intr(); 466 outb(0x3fdb, pitch); 467 outb(0x3fdb, (pitch>>8)); 468 enable_intr(); 469 if (!beeping) { 470 outb(IO_PPI, (inb(IO_PPI) & 0xf7)); /* enable counter1 output to speaker */ 471 beeping = period; 472 timeout(sysbeepstop, (void *)NULL, period); 473 } 474#else 475 476 if (acquire_timer2(TIMER_SQWAVE|TIMER_16BIT)) 477 return -1; 478 disable_intr(); 479 outb(TIMER_CNTR2, pitch); 480 outb(TIMER_CNTR2, (pitch>>8)); 481 enable_intr(); 482 if (!beeping) { 483 outb(IO_PPI, inb(IO_PPI) | 3); /* enable counter2 output to speaker */ 484 beeping = period; 485 timeout(sysbeepstop, (void *)NULL, period); 486 } 487#endif 488 return 0; 489} 490 491#ifndef PC98 492/* 493 * RTC support routines 494 */ 495 496int 497rtcin(reg) 498 int reg; 499{ 500 u_char val; 501 502 outb(IO_RTC, reg); 503 inb(0x84); 504 val = inb(IO_RTC + 1); 505 inb(0x84); 506 return (val); 507} 508 509static __inline void 510writertc(u_char reg, u_char val) 511{ 512 outb(IO_RTC, reg); 513 outb(IO_RTC + 1, val); 514} 515 516static __inline int 517readrtc(int port) 518{ 519 return(bcd2bin(rtcin(port))); 520} 521#endif 522 523#ifdef PC98 524unsigned int delaycount; 525#define FIRST_GUESS 0x2000 526static void findcpuspeed(void) 527{ 528 int i; 529 int remainder; 530 531 /* Put counter in count down mode */ 532 outb(TIMER_MODE, TIMER_SEL0 | TIMER_16BIT | TIMER_RATEGEN); 533 outb(TIMER_CNTR0, 0xff); 534 outb(TIMER_CNTR0, 0xff); 535 for (i = FIRST_GUESS; i; i--) 536 ; 537 remainder = getit(); 538 delaycount = (FIRST_GUESS * TIMER_DIV(1000)) / (0xffff - remainder); 539} 540#endif 541 542#ifndef PC98 543static u_int 544calibrate_clocks(void) 545{ 546 u_int count, prev_count, tot_count; 547 int sec, start_sec, timeout; 548 549 printf("Calibrating clock(s) relative to mc146818A clock ... "); 550 if (!(rtcin(RTC_STATUSD) & RTCSD_PWR)) 551 goto fail; 552 timeout = 100000000; 553 554 /* Read the mc146818A seconds counter. */ 555 for (;;) { 556 if (!(rtcin(RTC_STATUSA) & RTCSA_TUP)) { 557 sec = rtcin(RTC_SEC); 558 break; 559 } 560 if (--timeout == 0) 561 goto fail; 562 } 563 564 /* Wait for the mC146818A seconds counter to change. */ 565 start_sec = sec; 566 for (;;) { 567 if (!(rtcin(RTC_STATUSA) & RTCSA_TUP)) { 568 sec = rtcin(RTC_SEC); 569 if (sec != start_sec) 570 break; 571 } 572 if (--timeout == 0) 573 goto fail; 574 } 575 576 /* Start keeping track of the i8254 counter. */ 577 prev_count = getit(); 578 if (prev_count == 0 || prev_count > timer0_max_count) 579 goto fail; 580 tot_count = 0; 581 582#if defined(I586_CPU) || defined(I686_CPU) 583 if (cpu_class == CPUCLASS_586 || cpu_class == CPUCLASS_686) 584 wrmsr(0x10, 0LL); /* XXX 0x10 is the MSR for the TSC */ 585#endif 586 587 /* 588 * Wait for the mc146818A seconds counter to change. Read the i8254 589 * counter for each iteration since this is convenient and only 590 * costs a few usec of inaccuracy. The timing of the final reads 591 * of the counters almost matches the timing of the initial reads, 592 * so the main cause of inaccuracy is the varying latency from 593 * inside getit() or rtcin(RTC_STATUSA) to the beginning of the 594 * rtcin(RTC_SEC) that returns a changed seconds count. The 595 * maximum inaccuracy from this cause is < 10 usec on 486's. 596 */ 597 start_sec = sec; 598 for (;;) { 599 if (!(rtcin(RTC_STATUSA) & RTCSA_TUP)) 600 sec = rtcin(RTC_SEC); 601 count = getit(); 602 if (count == 0 || count > timer0_max_count) 603 goto fail; 604 if (count > prev_count) 605 tot_count += prev_count - (count - timer0_max_count); 606 else 607 tot_count += prev_count - count; 608 prev_count = count; 609 if (sec != start_sec) 610 break; 611 if (--timeout == 0) 612 goto fail; 613 } 614 615#if defined(I586_CPU) || defined(I686_CPU) 616 /* 617 * Read the cpu cycle counter. The timing considerations are 618 * similar to those for the i8254 clock. 619 */ 620 if (cpu_class == CPUCLASS_586 || cpu_class == CPUCLASS_686) { 621 unsigned long long i586_count; 622 623 i586_count = rdtsc(); 624 i586_ctr_freq = i586_count; 625 i586_ctr_rate = (i586_count << I586_CTR_RATE_SHIFT) / 1000000; 626 printf("i586 clock: %u Hz, ", i586_ctr_freq); 627 } 628#endif 629 630 printf("i8254 clock: %u Hz\n", tot_count); 631 return (tot_count); 632 633fail: 634 printf("failed, using default i8254 clock of %u Hz\n", timer_freq); 635 return (timer_freq); 636} 637#endif /* !PC98 */ 638 639static void 640set_timer_freq(u_int freq, int intr_freq) 641{ 642 u_long ef; 643 644 ef = read_eflags(); 645 timer_freq = freq; 646 timer0_max_count = hardclock_max_count = TIMER_DIV(intr_freq); 647 timer0_overflow_threshold = timer0_max_count - TIMER0_LATCH_COUNT; 648 outb(TIMER_MODE, TIMER_SEL0 | TIMER_RATEGEN | TIMER_16BIT); 649 outb(TIMER_CNTR0, timer0_max_count & 0xff); 650 outb(TIMER_CNTR0, timer0_max_count >> 8); 651 write_eflags(ef); 652} 653 654/* 655 * Initialize 8253 timer 0 early so that it can be used in DELAY(). 656 * XXX initialization of other timers is unintentionally left blank. 657 */ 658void 659startrtclock() 660{ 661 u_int delta, freq; 662 663#ifdef PC98 664 findcpuspeed(); 665#ifndef AUTO_CLOCK 666 if (pc98_machine_type & M_8M) { 667#ifndef PC98_8M 668 log(LOG_EMERG, 669 "you must reconfig a kernel with \"PC98_8M\" option.\n"); 670#endif 671 } else { 672#ifdef PC98_8M 673 log(LOG_EMERG, 674 "You must reconfig a kernel without \"PC98_8M\" option.\n"); 675#endif 676 } 677#else /* AUTO_CLOCK */ 678 if (pc98_machine_type & M_8M) 679 timer_freq = 1996800L; /* 1.9968 MHz */ 680 else 681 timer_freq = 2457600L; /* 2.4576 MHz */ 682#endif /* AUTO_CLOCK */ 683#endif /* PC98 */ 684 685#ifndef PC98 686 writertc(RTC_STATUSA, rtc_statusa); 687 writertc(RTC_STATUSB, RTCSB_24HR); 688#endif 689 690#ifndef PC98 691 /* 692 * Temporarily calibrate with a high intr_freq to get a low 693 * timer0_max_count to help detect bogus i8254 counts. 694 */ 695 set_timer_freq(timer_freq, 20000); 696 freq = calibrate_clocks(); 697#ifdef CLK_CALIBRATION_LOOP 698 if (bootverbose) { 699 printf( 700 "Press a key on the console to abort clock calibration\n"); 701 while (!cncheckc()) 702 calibrate_clocks(); 703 } 704#endif 705 706 /* 707 * Use the calibrated i8254 frequency if it seems reasonable. 708 * Otherwise use the default, and don't use the calibrated i586 709 * frequency. 710 */ 711 delta = freq > timer_freq ? freq - timer_freq : timer_freq - freq; 712 if (delta < timer_freq / 100) { 713#ifndef CLK_USE_I8254_CALIBRATION 714 printf( 715"CLK_USE_I8254_CALIBRATION not specified - using default frequency\n"); 716 freq = timer_freq; 717#endif 718 timer_freq = freq; 719 } else { 720 printf("%d Hz differs from default of %d Hz by more than 1%%\n", 721 freq, timer_freq); 722#if defined(I586_CPU) || defined(I686_CPU) 723 i586_ctr_freq = 0; 724 i586_ctr_rate = 0; 725#endif 726 } 727#endif 728 729 set_timer_freq(timer_freq, hz); 730 731#if defined(I586_CPU) || defined(I686_CPU) 732#ifndef CLK_USE_I586_CALIBRATION 733 if (i586_ctr_rate != 0) { 734 printf( 735"CLK_USE_I586_CALIBRATION not specified - using old calibration method\n"); 736 i586_ctr_freq = 0; 737 i586_ctr_rate = 0; 738 } 739#endif 740 if (i586_ctr_rate == 0 && 741 (cpu_class == CPUCLASS_586 || cpu_class == CPUCLASS_686)) { 742 /* 743 * Calibration of the i586 clock relative to the mc146818A 744 * clock failed. Do a less accurate calibration relative 745 * to the i8254 clock. 746 */ 747 unsigned long long i586_count; 748 749 wrmsr(0x10, 0LL); /* XXX */ 750 DELAY(1000000); 751 i586_count = rdtsc(); 752 i586_ctr_rate = (i586_count << I586_CTR_RATE_SHIFT) / 1000000; 753 printf("i586 clock: %u Hz\n", i586_ctr_freq); 754 } 755#endif 756} 757 758#ifdef PC98 759void 760rtc_serialcombit(int i) 761{ 762 outb(IO_RTC, ((i&0x01)<<5)|0x07); 763 DELAY(1); 764 outb(IO_RTC, ((i&0x01)<<5)|0x17); 765 DELAY(1); 766 outb(IO_RTC, ((i&0x01)<<5)|0x07); 767 DELAY(1); 768} 769 770void 771rtc_serialcom(int i) 772{ 773 rtc_serialcombit(i&0x01); 774 rtc_serialcombit((i&0x02)>>1); 775 rtc_serialcombit((i&0x04)>>2); 776 rtc_serialcombit((i&0x08)>>3); 777 outb(IO_RTC, 0x07); 778 DELAY(1); 779 outb(IO_RTC, 0x0f); 780 DELAY(1); 781 outb(IO_RTC, 0x07); 782 DELAY(1); 783} 784 785void 786rtc_outb(int val) 787{ 788 int s; 789 int sa = 0; 790 791 for (s=0;s<8;s++) { 792 sa = ((val >> s) & 0x01) ? 0x27 : 0x07; 793 outb(IO_RTC, sa); /* set DI & CLK 0 */ 794 DELAY(1); 795 outb(IO_RTC, sa | 0x10); /* CLK 1 */ 796 DELAY(1); 797 } 798 outb(IO_RTC, sa & 0xef); /* CLK 0 */ 799} 800 801int 802rtc_inb(void) 803{ 804 int s; 805 int sa = 0; 806 807 for (s=0;s<8;s++) { 808 sa |= ((inb(0x33) & 0x01) << s); 809 outb(IO_RTC, 0x17); /* CLK 1 */ 810 DELAY(1); 811 outb(IO_RTC, 0x07); /* CLK 0 */ 812 DELAY(2); 813 } 814 return sa; 815} 816#endif /* PC-98 */ 817 818/* 819 * Initialize the time of day register, based on the time base which is, e.g. 820 * from a filesystem. 821 */ 822void 823inittodr(time_t base) 824{ 825 unsigned long sec, days; 826 int yd; 827 int year, month; 828 int y, m, s; 829#ifdef PC98 830 int second, min, hour; 831#endif 832 833 s = splclock(); 834 time.tv_sec = base; 835 time.tv_usec = 0; 836 splx(s); 837 838#ifdef PC98 839 rtc_serialcom(0x03); /* Time Read */ 840 rtc_serialcom(0x01); /* Register shift command. */ 841 DELAY(20); 842 843 second = bcd2bin(rtc_inb() & 0xff); /* sec */ 844 min = bcd2bin(rtc_inb() & 0xff); /* min */ 845 hour = bcd2bin(rtc_inb() & 0xff); /* hour */ 846 days = bcd2bin(rtc_inb() & 0xff) - 1; /* date */ 847 848 month = (rtc_inb() >> 4) & 0x0f; /* month */ 849 for (m = 1; m < month; m++) 850 days += daysinmonth[m-1]; 851 year = bcd2bin(rtc_inb() & 0xff) + 1900; /* year */ 852 /* 2000 year problem */ 853 if (year < 1995) 854 year += 100; 855 if (year < 1970) 856 goto wrong_time; 857 for (y = 1970; y < year; y++) 858 days += DAYSPERYEAR + LEAPYEAR(y); 859 if ((month > 2) && LEAPYEAR(year)) 860 days ++; 861 sec = ((( days * 24 + 862 hour) * 60 + 863 min) * 60 + 864 second); 865 /* sec now contains the number of seconds, since Jan 1 1970, 866 in the local time zone */ 867#else /* IBM-PC */ 868 /* Look if we have a RTC present and the time is valid */ 869 if (!(rtcin(RTC_STATUSD) & RTCSD_PWR)) 870 goto wrong_time; 871 872 /* wait for time update to complete */ 873 /* If RTCSA_TUP is zero, we have at least 244us before next update */ 874 while (rtcin(RTC_STATUSA) & RTCSA_TUP); 875 876 days = 0; 877#ifdef USE_RTC_CENTURY 878 year = readrtc(RTC_YEAR) + readrtc(RTC_CENTURY) * 100; 879#else 880 year = readrtc(RTC_YEAR) + 1900; 881 if (year < 1970) 882 year += 100; 883#endif 884 if (year < 1970) 885 goto wrong_time; 886 month = readrtc(RTC_MONTH); 887 for (m = 1; m < month; m++) 888 days += daysinmonth[m-1]; 889 if ((month > 2) && LEAPYEAR(year)) 890 days ++; 891 days += readrtc(RTC_DAY) - 1; 892 yd = days; 893 for (y = 1970; y < year; y++) 894 days += DAYSPERYEAR + LEAPYEAR(y); 895 sec = ((( days * 24 + 896 readrtc(RTC_HRS)) * 60 + 897 readrtc(RTC_MIN)) * 60 + 898 readrtc(RTC_SEC)); 899 /* sec now contains the number of seconds, since Jan 1 1970, 900 in the local time zone */ 901#endif 902 903 sec += tz.tz_minuteswest * 60 + (wall_cmos_clock ? adjkerntz : 0); 904 905 s = splclock(); 906 time.tv_sec = sec; 907 splx(s); 908 return; 909 910wrong_time: 911 printf("Invalid time in real time clock.\n"); 912 printf("Check and reset the date immediately!\n"); 913} 914 915/* 916 * Write system time back to RTC 917 */ 918void 919resettodr() 920{ 921 unsigned long tm; 922 int y, m, s; 923#ifdef PC98 924 int wd; 925#endif 926 927 if (disable_rtc_set) 928 return; 929 930 s = splclock(); 931 tm = time.tv_sec; 932 splx(s); 933 934#ifdef PC98 935 rtc_serialcom(0x01); /* Register shift command. */ 936 937 /* Calculate local time to put in RTC */ 938 939 tm -= tz.tz_minuteswest * 60 + (wall_cmos_clock ? adjkerntz : 0); 940 941 rtc_outb(bin2bcd(tm%60)); tm /= 60; /* Write back Seconds */ 942 rtc_outb(bin2bcd(tm%60)); tm /= 60; /* Write back Minutes */ 943 rtc_outb(bin2bcd(tm%24)); tm /= 24; /* Write back Hours */ 944 945 /* We have now the days since 01-01-1970 in tm */ 946 wd = (tm+4)%7; 947 for (y = 1970, m = DAYSPERYEAR + LEAPYEAR(y); 948 tm >= m; 949 y++, m = DAYSPERYEAR + LEAPYEAR(y)) 950 tm -= m; 951 952 /* Now we have the years in y and the day-of-the-year in tm */ 953 for (m = 0; ; m++) { 954 int ml; 955 956 ml = daysinmonth[m]; 957 if (m == 1 && LEAPYEAR(y)) 958 ml++; 959 if (tm < ml) 960 break; 961 tm -= ml; 962 } 963 964 m++; 965 rtc_outb(bin2bcd(tm+1)); /* Write back Day */ 966 rtc_outb((m << 4) | wd); /* Write back Month & Weekday */ 967 rtc_outb(bin2bcd(y%100)); /* Write back Year */ 968 969 rtc_serialcom(0x02); /* Time set & Counter hold command. */ 970 rtc_serialcom(0x00); /* Register hold command. */ 971#else 972 /* Disable RTC updates and interrupts. */ 973 writertc(RTC_STATUSB, RTCSB_HALT | RTCSB_24HR); 974 975 /* Calculate local time to put in RTC */ 976 977 tm -= tz.tz_minuteswest * 60 + (wall_cmos_clock ? adjkerntz : 0); 978 979 writertc(RTC_SEC, bin2bcd(tm%60)); tm /= 60; /* Write back Seconds */ 980 writertc(RTC_MIN, bin2bcd(tm%60)); tm /= 60; /* Write back Minutes */ 981 writertc(RTC_HRS, bin2bcd(tm%24)); tm /= 24; /* Write back Hours */ 982 983 /* We have now the days since 01-01-1970 in tm */ 984 writertc(RTC_WDAY, (tm+4)%7); /* Write back Weekday */ 985 for (y = 1970, m = DAYSPERYEAR + LEAPYEAR(y); 986 tm >= m; 987 y++, m = DAYSPERYEAR + LEAPYEAR(y)) 988 tm -= m; 989 990 /* Now we have the years in y and the day-of-the-year in tm */ 991 writertc(RTC_YEAR, bin2bcd(y%100)); /* Write back Year */ 992#ifdef USE_RTC_CENTURY 993 writertc(RTC_CENTURY, bin2bcd(y/100)); /* ... and Century */ 994#endif 995 for (m = 0; ; m++) { 996 int ml; 997 998 ml = daysinmonth[m]; 999 if (m == 1 && LEAPYEAR(y)) 1000 ml++; 1001 if (tm < ml) 1002 break; 1003 tm -= ml; 1004 } 1005 1006 writertc(RTC_MONTH, bin2bcd(m + 1)); /* Write back Month */ 1007 writertc(RTC_DAY, bin2bcd(tm + 1)); /* Write back Month Day */ 1008 1009 /* Reenable RTC updates and interrupts. */ 1010 writertc(RTC_STATUSB, rtc_statusb); 1011#endif 1012} 1013 1014/* 1015 * Start both clocks running. 1016 */ 1017void 1018cpu_initclocks() 1019{ 1020#ifndef PC98 1021 int diag; 1022 1023 if (statclock_disable) { 1024 /* 1025 * The stat interrupt mask is different without the 1026 * statistics clock. Also, don't set the interrupt 1027 * flag which would normally cause the RTC to generate 1028 * interrupts. 1029 */ 1030 stat_imask = HWI_MASK | SWI_MASK; 1031 rtc_statusb = RTCSB_24HR; 1032 } else { 1033 /* Setting stathz to nonzero early helps avoid races. */ 1034 stathz = RTC_NOPROFRATE; 1035 profhz = RTC_PROFRATE; 1036 } 1037#endif 1038 1039 /* Finish initializing 8253 timer 0. */ 1040 register_intr(/* irq */ 0, /* XXX id */ 0, /* flags */ 0, 1041 /* XXX */ (inthand2_t *)clkintr, &clk_imask, 1042 /* unit */ 0); 1043 INTREN(IRQ0); 1044#if defined(I586_CPU) || defined(I686_CPU) 1045 /* 1046 * Finish setting up anti-jitter measures. 1047 */ 1048 if (i586_ctr_rate) { 1049 i586_last_tick = rdtsc(); 1050 i586_ctr_bias = i586_last_tick; 1051 } 1052#endif 1053 1054#ifndef PC98 1055 /* Initialize RTC. */ 1056 writertc(RTC_STATUSA, rtc_statusa); 1057 writertc(RTC_STATUSB, RTCSB_24HR); 1058 1059static int 1060sysctl_machdep_i8254_freq SYSCTL_HANDLER_ARGS 1061{ 1062 int error; 1063 u_int freq; 1064 1065 /* 1066 * Use `i8254' instead of `timer' in external names because `timer' 1067 * is is too generic. Should use it everywhere. 1068 */ 1069 freq = timer_freq; 1070 error = sysctl_handle_opaque(oidp, &freq, sizeof freq, req); 1071 if (error == 0 && freq != timer_freq) { 1072 if (timer0_state != 0) 1073 return (EBUSY); /* too much trouble to handle */ 1074 set_timer_freq(freq, hz); 1075 } 1076 return (error); 1077} 1078 1079SYSCTL_PROC(_machdep, OID_AUTO, i8254_freq, CTLTYPE_INT | CTLFLAG_RW, 1080 0, sizeof(u_int), sysctl_machdep_i8254_freq, "I", ""); 1081 1082#if defined(I586_CPU) || defined(I686_CPU) 1083static int 1084sysctl_machdep_i586_freq SYSCTL_HANDLER_ARGS 1085{ 1086 int error; 1087 u_int freq; 1088 1089 if (i586_ctr_rate == 0) 1090 return (EOPNOTSUPP); 1091 freq = i586_ctr_freq; 1092 error = sysctl_handle_opaque(oidp, &freq, sizeof freq, req); 1093 if (error == 0 && freq != i586_ctr_freq) { 1094 i586_ctr_freq = freq; 1095 i586_ctr_rate = ((unsigned long long)freq << 1096 I586_CTR_RATE_SHIFT) / 1000000; 1097 } 1098 return (error); 1099} 1100 1101SYSCTL_PROC(_machdep, OID_AUTO, i586_freq, CTLTYPE_INT | CTLFLAG_RW, 1102 0, sizeof(u_int), sysctl_machdep_i586_freq, "I", ""); 1103#endif /* defined(I586_CPU) || defined(I686_CPU) */ 1104 1105 /* Don't bother enabling the statistics clock. */ 1106 if (statclock_disable) 1107 return; 1108 diag = rtcin(RTC_DIAG); 1109 if (diag != 0) 1110 printf("RTC BIOS diagnostic error %b\n", diag, RTCDG_BITS); 1111 register_intr(/* irq */ 8, /* XXX id */ 1, /* flags */ 0, 1112 /* XXX */ (inthand2_t *)rtcintr, &stat_imask, 1113 /* unit */ 0); 1114 INTREN(IRQ8); 1115 writertc(RTC_STATUSB, rtc_statusb); 1116#endif 1117} 1118 1119void 1120setstatclockrate(int newhz) 1121{ 1122#ifndef PC98 1123 if (newhz == RTC_PROFRATE) 1124 rtc_statusa = RTCSA_DIVIDER | RTCSA_PROF; 1125 else 1126 rtc_statusa = RTCSA_DIVIDER | RTCSA_NOPROF; 1127 writertc(RTC_STATUSA, rtc_statusa); 1128#endif 1129} 1130