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
| 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
|
50#include <sys/param.h> 51#include <sys/systm.h> 52#include <sys/time.h> 53#include <sys/kernel.h> 54#include <machine/clock.h> 55#include <machine/frame.h> 56#include <i386/isa/icu.h> 57#include <i386/isa/isa.h> 58#include <i386/isa/isa_device.h> 59#include <i386/isa/rtc.h> 60#include <i386/isa/timerreg.h> 61 62/* 63 * 32-bit time_t's can't reach leap years before 1904 or after 2036, so we 64 * can use a simple formula for leap years. 65 */ 66#define LEAPYEAR(y) ((u_int)(y) % 4 == 0) 67#define DAYSPERYEAR (31+28+31+30+31+30+31+31+30+31+30+31) 68 69/* X-tals being what they are, it's nice to be able to fudge this one... */ 70#ifndef TIMER_FREQ 71#define TIMER_FREQ 1193182 /* XXX - should be in isa.h */ 72#endif 73#define TIMER_DIV(x) ((TIMER_FREQ+(x)/2)/(x)) 74 75/* 76 * Time in timer cycles that it takes for microtime() to disable interrupts 77 * and latch the count. microtime() currently uses "cli; outb ..." so it 78 * normally takes less than 2 timer cycles. Add a few for cache misses. 79 * Add a few more to allow for latency in bogus calls to microtime() with 80 * interrupts already disabled. 81 */ 82#define TIMER0_LATCH_COUNT 20 83 84/* 85 * Minimum maximum count that we are willing to program into timer0. 86 * Must be large enough to guarantee that the timer interrupt handler 87 * returns before the next timer interrupt. Must be larger than 88 * TIMER0_LATCH_COUNT so that we don't have to worry about underflow in 89 * the calculation of timer0_overflow_threshold. 90 */ 91#define TIMER0_MIN_MAX_COUNT TIMER_DIV(20000) 92 93int adjkerntz = 0; /* offset from CMOS clock */ 94int disable_rtc_set = 0; /* disable resettodr() if != 0 */ 95u_int idelayed; 96#if defined(I586_CPU) || defined(I686_CPU) 97unsigned i586_ctr_rate; 98long long i586_ctr_bias; 99long long i586_last_tick; 100#endif 101u_int stat_imask = SWI_CLOCK_MASK; 102int timer0_max_count; 103u_int timer0_overflow_threshold; 104u_int timer0_prescaler_count; 105 106static int beeping = 0; 107static u_int clk_imask = HWI_MASK | SWI_MASK; 108static const u_char daysinmonth[] = {31,28,31,30,31,30,31,31,30,31,30,31}; 109static u_int hardclock_max_count; 110/* 111 * XXX new_function and timer_func should not handle clockframes, but 112 * timer_func currently needs to hold hardclock to handle the 113 * timer0_state == 0 case. We should use register_intr()/unregister_intr() 114 * to switch between clkintr() and a slightly different timerintr(). 115 * This will require locking when acquiring and releasing timer0 - the 116 * current (nonexistent) locking doesn't seem to be adequate even now. 117 */ 118static void (*new_function) __P((struct clockframe *frame)); 119static u_int new_rate; 120static u_char rtc_statusa = RTCSA_DIVIDER | RTCSA_NOPROF; 121static char timer0_state = 0; 122static char timer2_state = 0; 123static void (*timer_func) __P((struct clockframe *frame)) = hardclock; 124 125#if 0 126void 127clkintr(struct clockframe frame) 128{ 129 hardclock(&frame); 130 setdelayed(); 131} 132#else 133static void 134clkintr(struct clockframe frame) 135{ 136 timer_func(&frame); 137 switch (timer0_state) { 138 case 0: 139 setdelayed(); 140 break; 141 case 1: 142 if ((timer0_prescaler_count += timer0_max_count) 143 >= hardclock_max_count) { 144 hardclock(&frame); 145 setdelayed(); 146 timer0_prescaler_count -= hardclock_max_count; 147 } 148 break; 149 case 2: 150 setdelayed(); 151 timer0_max_count = TIMER_DIV(new_rate); 152 timer0_overflow_threshold = 153 timer0_max_count - TIMER0_LATCH_COUNT; 154 disable_intr(); 155 outb(TIMER_MODE, TIMER_SEL0 | TIMER_RATEGEN | TIMER_16BIT); 156 outb(TIMER_CNTR0, timer0_max_count & 0xff); 157 outb(TIMER_CNTR0, timer0_max_count >> 8); 158 enable_intr(); 159 timer0_prescaler_count = 0; 160 timer_func = new_function; 161 timer0_state = 1; 162 break; 163 case 3: 164 if ((timer0_prescaler_count += timer0_max_count) 165 >= hardclock_max_count) { 166 hardclock(&frame); 167 setdelayed(); 168 timer0_max_count = hardclock_max_count; 169 timer0_overflow_threshold = 170 timer0_max_count - TIMER0_LATCH_COUNT; 171 disable_intr(); 172 outb(TIMER_MODE, 173 TIMER_SEL0 | TIMER_RATEGEN | TIMER_16BIT); 174 outb(TIMER_CNTR0, timer0_max_count & 0xff); 175 outb(TIMER_CNTR0, timer0_max_count >> 8); 176 enable_intr(); 177 /* 178 * See microtime.s for this magic. 179 */ 180 time.tv_usec += (27645 * 181 (timer0_prescaler_count - hardclock_max_count)) 182 >> 15; 183 if (time.tv_usec >= 1000000) 184 time.tv_usec -= 1000000; 185 timer0_prescaler_count = 0; 186 timer_func = hardclock;; 187 timer0_state = 0; 188 } 189 break; 190 } 191} 192#endif 193 194int 195acquire_timer0(int rate, void (*function) __P((struct clockframe *frame))) 196{ 197 if (timer0_state || TIMER_DIV(rate) < TIMER0_MIN_MAX_COUNT || 198 !function) 199 return -1; 200 new_function = function; 201 new_rate = rate; 202 timer0_state = 2; 203 return 0; 204} 205 206int 207acquire_timer2(int mode) 208{ 209 if (timer2_state) 210 return -1; 211 timer2_state = 1; 212 outb(TIMER_MODE, TIMER_SEL2 | (mode &0x3f)); 213 return 0; 214} 215 216int 217release_timer0() 218{ 219 if (!timer0_state) 220 return -1; 221 timer0_state = 3; 222 return 0; 223} 224 225int 226release_timer2() 227{ 228 if (!timer2_state) 229 return -1; 230 timer2_state = 0; 231 outb(TIMER_MODE, TIMER_SEL2|TIMER_SQWAVE|TIMER_16BIT); 232 return 0; 233} 234 235/* 236 * This routine receives statistical clock interrupts from the RTC. 237 * As explained above, these occur at 128 interrupts per second. 238 * When profiling, we receive interrupts at a rate of 1024 Hz. 239 * 240 * This does not actually add as much overhead as it sounds, because 241 * when the statistical clock is active, the hardclock driver no longer 242 * needs to keep (inaccurate) statistics on its own. This decouples 243 * statistics gathering from scheduling interrupts. 244 * 245 * The RTC chip requires that we read status register C (RTC_INTR) 246 * to acknowledge an interrupt, before it will generate the next one. 247 */ 248static void 249rtcintr(struct clockframe frame) 250{ 251 u_char stat; 252 stat = rtcin(RTC_INTR); 253 if(stat & RTCIR_PERIOD) { 254 statclock(&frame); 255 } 256} 257 258#ifdef DDB 259static void 260DDB_printrtc(void) 261{ 262 printf("%02x/%02x/%02x %02x:%02x:%02x, A = %02x, B = %02x, C = %02x\n", 263 rtcin(RTC_YEAR), rtcin(RTC_MONTH), rtcin(RTC_DAY), 264 rtcin(RTC_HRS), rtcin(RTC_MIN), rtcin(RTC_SEC), 265 rtcin(RTC_STATUSA), rtcin(RTC_STATUSB), rtcin(RTC_INTR)); 266} 267#endif 268 269static int 270getit(void) 271{ 272 int high, low; 273 274 disable_intr(); 275 /* select timer0 and latch counter value */ 276 outb(TIMER_MODE, TIMER_SEL0); 277 low = inb(TIMER_CNTR0); 278 high = inb(TIMER_CNTR0); 279 enable_intr(); 280 return ((high << 8) | low); 281} 282 283#if defined(I586_CPU) || defined(I686_CPU) 284/* 285 * Figure out how fast the cyclecounter runs. This must be run with 286 * clock interrupts disabled, but with the timer/counter programmed 287 * and running. 288 */ 289void 290calibrate_cyclecounter(void) 291{ 292 /* 293 * Don't need volatile; should always use unsigned if 2's 294 * complement arithmetic is desired. 295 */ 296 unsigned long long count; 297 298#define howlong 131072UL 299 __asm __volatile(".byte 0x0f, 0x30" : : "A"(0LL), "c" (0x10)); 300 DELAY(howlong); 301 __asm __volatile(".byte 0xf,0x31" : "=A" (count)); 302 303 i586_ctr_rate = (count << I586_CTR_RATE_SHIFT) / howlong; 304#undef howlong 305} 306#endif 307 308/* 309 * Wait "n" microseconds. 310 * Relies on timer 1 counting down from (TIMER_FREQ / hz) 311 * Note: timer had better have been programmed before this is first used! 312 */ 313void 314DELAY(int n) 315{ 316 int prev_tick, tick, ticks_left, sec, usec; 317 318#ifdef DELAYDEBUG 319 int getit_calls = 1; 320 int n1; 321 static int state = 0; 322 323 if (state == 0) { 324 state = 1; 325 for (n1 = 1; n1 <= 10000000; n1 *= 10) 326 DELAY(n1); 327 state = 2; 328 } 329 if (state == 1) 330 printf("DELAY(%d)...", n); 331#endif 332 /* 333 * Read the counter first, so that the rest of the setup overhead is 334 * counted. Guess the initial overhead is 20 usec (on most systems it 335 * takes about 1.5 usec for each of the i/o's in getit(). The loop 336 * takes about 6 usec on a 486/33 and 13 usec on a 386/20. The 337 * multiplications and divisions to scale the count take a while). 338 */ 339 prev_tick = getit(); 340 n -= 20; 341 /* 342 * Calculate (n * (TIMER_FREQ / 1e6)) without using floating point 343 * and without any avoidable overflows. 344 */ 345 sec = n / 1000000; 346 usec = n - sec * 1000000; 347 ticks_left = sec * TIMER_FREQ 348 + usec * (TIMER_FREQ / 1000000) 349 + usec * ((TIMER_FREQ % 1000000) / 1000) / 1000 350 + usec * (TIMER_FREQ % 1000) / 1000000; 351 352 while (ticks_left > 0) { 353 tick = getit(); 354#ifdef DELAYDEBUG 355 ++getit_calls; 356#endif 357 if (tick > prev_tick) 358 ticks_left -= prev_tick - (tick - timer0_max_count); 359 else 360 ticks_left -= prev_tick - tick; 361 prev_tick = tick; 362 } 363#ifdef DELAYDEBUG 364 if (state == 1) 365 printf(" %d calls to getit() at %d usec each\n", 366 getit_calls, (n + 5) / getit_calls); 367#endif 368} 369 370static void 371sysbeepstop(void *chan) 372{ 373 outb(IO_PPI, inb(IO_PPI)&0xFC); /* disable counter2 output to speaker */ 374 release_timer2(); 375 beeping = 0; 376} 377 378int 379sysbeep(int pitch, int period) 380{ 381 382 if (acquire_timer2(TIMER_SQWAVE|TIMER_16BIT)) 383 return -1; 384 disable_intr(); 385 outb(TIMER_CNTR2, pitch); 386 outb(TIMER_CNTR2, (pitch>>8)); 387 enable_intr(); 388 if (!beeping) { 389 outb(IO_PPI, inb(IO_PPI) | 3); /* enable counter2 output to speaker */ 390 beeping = period; 391 timeout(sysbeepstop, (void *)NULL, period); 392 } 393 return 0; 394} 395 396/* 397 * RTC support routines 398 */ 399static int 400bcd2int(int bcd) 401{ 402 return(bcd/16 * 10 + bcd%16); 403} 404 405static int 406int2bcd(int dez) 407{ 408 return(dez/10 * 16 + dez%10); 409} 410 411static inline void 412writertc(u_char reg, u_char val) 413{ 414 outb(IO_RTC, reg); 415 outb(IO_RTC + 1, val); 416} 417 418static int 419readrtc(int port) 420{ 421 return(bcd2int(rtcin(port))); 422} 423 424/* 425 * Initialize 8253 timer 0 early so that it can be used in DELAY(). 426 * XXX initialization of other timers is unintentionally left blank. 427 */ 428void 429startrtclock() 430{ 431 timer0_max_count = hardclock_max_count = TIMER_DIV(hz); 432 timer0_overflow_threshold = timer0_max_count - TIMER0_LATCH_COUNT; 433 outb(TIMER_MODE, TIMER_SEL0 | TIMER_RATEGEN | TIMER_16BIT); 434 outb(TIMER_CNTR0, timer0_max_count & 0xff); 435 outb(TIMER_CNTR0, timer0_max_count >> 8); 436} 437 438/* 439 * Initialize the time of day register, based on the time base which is, e.g. 440 * from a filesystem. 441 */ 442void 443inittodr(time_t base) 444{ 445 unsigned long sec, days; 446 int yd; 447 int year, month; 448 int y, m, s; 449 450 s = splclock(); 451 time.tv_sec = base; 452 time.tv_usec = 0; 453 splx(s); 454 455 /* Look if we have a RTC present and the time is valid */ 456 if (!(rtcin(RTC_STATUSD) & RTCSD_PWR)) 457 goto wrong_time; 458 459 /* wait for time update to complete */ 460 /* If RTCSA_TUP is zero, we have at least 244us before next update */ 461 while (rtcin(RTC_STATUSA) & RTCSA_TUP); 462 463 days = 0; 464#ifdef USE_RTC_CENTURY 465 year = readrtc(RTC_YEAR) + readrtc(RTC_CENTURY) * 100; 466#else 467 year = readrtc(RTC_YEAR) + 1900; 468 if (year < 1970) 469 year += 100; 470#endif 471 if (year < 1970) 472 goto wrong_time; 473 month = readrtc(RTC_MONTH); 474 for (m = 1; m < month; m++) 475 days += daysinmonth[m-1]; 476 if ((month > 2) && LEAPYEAR(year)) 477 days ++; 478 days += readrtc(RTC_DAY) - 1; 479 yd = days; 480 for (y = 1970; y < year; y++) 481 days += DAYSPERYEAR + LEAPYEAR(y); 482 sec = ((( days * 24 + 483 readrtc(RTC_HRS)) * 60 + 484 readrtc(RTC_MIN)) * 60 + 485 readrtc(RTC_SEC)); 486 /* sec now contains the number of seconds, since Jan 1 1970, 487 in the local time zone */ 488 489 sec += tz.tz_minuteswest * 60 + adjkerntz; 490 491 s = splclock(); 492 time.tv_sec = sec; 493 splx(s); 494 return; 495 496wrong_time: 497 printf("Invalid time in real time clock.\n"); 498 printf("Check and reset the date immediately!\n"); 499} 500 501/* 502 * Write system time back to RTC 503 */ 504void 505resettodr() 506{ 507 unsigned long tm; 508 int y, m, s; 509 510 if (disable_rtc_set) 511 return; 512 513 s = splclock(); 514 tm = time.tv_sec; 515 splx(s); 516 517 /* Disable RTC updates and interrupts. */ 518 writertc(RTC_STATUSB, RTCSB_HALT | RTCSB_24HR); 519 520 /* Calculate local time to put in RTC */ 521 522 tm -= tz.tz_minuteswest * 60 + adjkerntz; 523 524 writertc(RTC_SEC, int2bcd(tm%60)); tm /= 60; /* Write back Seconds */ 525 writertc(RTC_MIN, int2bcd(tm%60)); tm /= 60; /* Write back Minutes */ 526 writertc(RTC_HRS, int2bcd(tm%24)); tm /= 24; /* Write back Hours */ 527 528 /* We have now the days since 01-01-1970 in tm */ 529 writertc(RTC_WDAY, (tm+4)%7); /* Write back Weekday */ 530 for (y=1970;; y++) 531 if ((tm - DAYSPERYEAR - LEAPYEAR(y)) > tm) 532 break; 533 else 534 tm -= DAYSPERYEAR + LEAPYEAR(y); 535 536 /* Now we have the years in y and the day-of-the-year in tm */ 537 writertc(RTC_YEAR, int2bcd(y%100)); /* Write back Year */ 538#ifdef USE_RTC_CENTURY 539 writertc(RTC_CENTURY, int2bcd(y/100)); /* ... and Century */ 540#endif 541 if (LEAPYEAR(y) && (tm >= 31+29)) 542 tm--; /* Subtract Feb-29 */ 543 for (m=1;; m++) 544 if (tm - daysinmonth[m-1] > tm) 545 break; 546 else 547 tm -= daysinmonth[m-1]; 548 549 writertc(RTC_MONTH, int2bcd(m)); /* Write back Month */ 550 writertc(RTC_DAY, int2bcd(tm+1)); /* Write back Day */ 551 552 /* Reenable RTC updates and interrupts. */ 553 writertc(RTC_STATUSB, RTCSB_24HR | RTCSB_PINTR); 554} 555 556/* 557 * Start both clocks running. 558 */ 559void 560cpu_initclocks() 561{ 562 int diag; 563 564 stathz = RTC_NOPROFRATE; 565 profhz = RTC_PROFRATE; 566 567 /* Finish initializing 8253 timer 0. */ 568 register_intr(/* irq */ 0, /* XXX id */ 0, /* flags */ 0, 569 /* XXX */ (inthand2_t *)clkintr, &clk_imask, 570 /* unit */ 0); 571 INTREN(IRQ0); 572#if defined(I586_CPU) || defined(I686_CPU) 573 /* 574 * Finish setting up anti-jitter measures. 575 */ 576 if (i586_ctr_rate) { 577 I586_CYCLECTR(i586_last_tick); 578 i586_ctr_bias = i586_last_tick; 579 } 580#endif 581 582 /* Initialize RTC. */ 583 writertc(RTC_STATUSA, rtc_statusa); 584 writertc(RTC_STATUSB, RTCSB_24HR); 585 diag = rtcin(RTC_DIAG); 586 if (diag != 0) 587 printf("RTC BIOS diagnostic error %b\n", diag, RTCDG_BITS); 588 register_intr(/* irq */ 8, /* XXX id */ 1, /* flags */ 0, 589 /* XXX */ (inthand2_t *)rtcintr, &stat_imask, 590 /* unit */ 0); 591 INTREN(IRQ8); 592 writertc(RTC_STATUSB, RTCSB_24HR | RTCSB_PINTR); 593} 594 595void 596setstatclockrate(int newhz) 597{ 598 if (newhz == RTC_PROFRATE) 599 rtc_statusa = RTCSA_DIVIDER | RTCSA_PROF; 600 else 601 rtc_statusa = RTCSA_DIVIDER | RTCSA_NOPROF; 602 writertc(RTC_STATUSA, rtc_statusa); 603}
| 52#include <sys/param.h> 53#include <sys/systm.h> 54#include <sys/time.h> 55#include <sys/kernel.h> 56#include <machine/clock.h> 57#include <machine/frame.h> 58#include <i386/isa/icu.h> 59#include <i386/isa/isa.h> 60#include <i386/isa/isa_device.h> 61#include <i386/isa/rtc.h> 62#include <i386/isa/timerreg.h> 63 64/* 65 * 32-bit time_t's can't reach leap years before 1904 or after 2036, so we 66 * can use a simple formula for leap years. 67 */ 68#define LEAPYEAR(y) ((u_int)(y) % 4 == 0) 69#define DAYSPERYEAR (31+28+31+30+31+30+31+31+30+31+30+31) 70 71/* X-tals being what they are, it's nice to be able to fudge this one... */ 72#ifndef TIMER_FREQ 73#define TIMER_FREQ 1193182 /* XXX - should be in isa.h */ 74#endif 75#define TIMER_DIV(x) ((TIMER_FREQ+(x)/2)/(x)) 76 77/* 78 * Time in timer cycles that it takes for microtime() to disable interrupts 79 * and latch the count. microtime() currently uses "cli; outb ..." so it 80 * normally takes less than 2 timer cycles. Add a few for cache misses. 81 * Add a few more to allow for latency in bogus calls to microtime() with 82 * interrupts already disabled. 83 */ 84#define TIMER0_LATCH_COUNT 20 85 86/* 87 * Minimum maximum count that we are willing to program into timer0. 88 * Must be large enough to guarantee that the timer interrupt handler 89 * returns before the next timer interrupt. Must be larger than 90 * TIMER0_LATCH_COUNT so that we don't have to worry about underflow in 91 * the calculation of timer0_overflow_threshold. 92 */ 93#define TIMER0_MIN_MAX_COUNT TIMER_DIV(20000) 94 95int adjkerntz = 0; /* offset from CMOS clock */ 96int disable_rtc_set = 0; /* disable resettodr() if != 0 */ 97u_int idelayed; 98#if defined(I586_CPU) || defined(I686_CPU) 99unsigned i586_ctr_rate; 100long long i586_ctr_bias; 101long long i586_last_tick; 102#endif 103u_int stat_imask = SWI_CLOCK_MASK; 104int timer0_max_count; 105u_int timer0_overflow_threshold; 106u_int timer0_prescaler_count; 107 108static int beeping = 0; 109static u_int clk_imask = HWI_MASK | SWI_MASK; 110static const u_char daysinmonth[] = {31,28,31,30,31,30,31,31,30,31,30,31}; 111static u_int hardclock_max_count; 112/* 113 * XXX new_function and timer_func should not handle clockframes, but 114 * timer_func currently needs to hold hardclock to handle the 115 * timer0_state == 0 case. We should use register_intr()/unregister_intr() 116 * to switch between clkintr() and a slightly different timerintr(). 117 * This will require locking when acquiring and releasing timer0 - the 118 * current (nonexistent) locking doesn't seem to be adequate even now. 119 */ 120static void (*new_function) __P((struct clockframe *frame)); 121static u_int new_rate; 122static u_char rtc_statusa = RTCSA_DIVIDER | RTCSA_NOPROF; 123static char timer0_state = 0; 124static char timer2_state = 0; 125static void (*timer_func) __P((struct clockframe *frame)) = hardclock; 126 127#if 0 128void 129clkintr(struct clockframe frame) 130{ 131 hardclock(&frame); 132 setdelayed(); 133} 134#else 135static void 136clkintr(struct clockframe frame) 137{ 138 timer_func(&frame); 139 switch (timer0_state) { 140 case 0: 141 setdelayed(); 142 break; 143 case 1: 144 if ((timer0_prescaler_count += timer0_max_count) 145 >= hardclock_max_count) { 146 hardclock(&frame); 147 setdelayed(); 148 timer0_prescaler_count -= hardclock_max_count; 149 } 150 break; 151 case 2: 152 setdelayed(); 153 timer0_max_count = TIMER_DIV(new_rate); 154 timer0_overflow_threshold = 155 timer0_max_count - TIMER0_LATCH_COUNT; 156 disable_intr(); 157 outb(TIMER_MODE, TIMER_SEL0 | TIMER_RATEGEN | TIMER_16BIT); 158 outb(TIMER_CNTR0, timer0_max_count & 0xff); 159 outb(TIMER_CNTR0, timer0_max_count >> 8); 160 enable_intr(); 161 timer0_prescaler_count = 0; 162 timer_func = new_function; 163 timer0_state = 1; 164 break; 165 case 3: 166 if ((timer0_prescaler_count += timer0_max_count) 167 >= hardclock_max_count) { 168 hardclock(&frame); 169 setdelayed(); 170 timer0_max_count = hardclock_max_count; 171 timer0_overflow_threshold = 172 timer0_max_count - TIMER0_LATCH_COUNT; 173 disable_intr(); 174 outb(TIMER_MODE, 175 TIMER_SEL0 | TIMER_RATEGEN | TIMER_16BIT); 176 outb(TIMER_CNTR0, timer0_max_count & 0xff); 177 outb(TIMER_CNTR0, timer0_max_count >> 8); 178 enable_intr(); 179 /* 180 * See microtime.s for this magic. 181 */ 182 time.tv_usec += (27645 * 183 (timer0_prescaler_count - hardclock_max_count)) 184 >> 15; 185 if (time.tv_usec >= 1000000) 186 time.tv_usec -= 1000000; 187 timer0_prescaler_count = 0; 188 timer_func = hardclock;; 189 timer0_state = 0; 190 } 191 break; 192 } 193} 194#endif 195 196int 197acquire_timer0(int rate, void (*function) __P((struct clockframe *frame))) 198{ 199 if (timer0_state || TIMER_DIV(rate) < TIMER0_MIN_MAX_COUNT || 200 !function) 201 return -1; 202 new_function = function; 203 new_rate = rate; 204 timer0_state = 2; 205 return 0; 206} 207 208int 209acquire_timer2(int mode) 210{ 211 if (timer2_state) 212 return -1; 213 timer2_state = 1; 214 outb(TIMER_MODE, TIMER_SEL2 | (mode &0x3f)); 215 return 0; 216} 217 218int 219release_timer0() 220{ 221 if (!timer0_state) 222 return -1; 223 timer0_state = 3; 224 return 0; 225} 226 227int 228release_timer2() 229{ 230 if (!timer2_state) 231 return -1; 232 timer2_state = 0; 233 outb(TIMER_MODE, TIMER_SEL2|TIMER_SQWAVE|TIMER_16BIT); 234 return 0; 235} 236 237/* 238 * This routine receives statistical clock interrupts from the RTC. 239 * As explained above, these occur at 128 interrupts per second. 240 * When profiling, we receive interrupts at a rate of 1024 Hz. 241 * 242 * This does not actually add as much overhead as it sounds, because 243 * when the statistical clock is active, the hardclock driver no longer 244 * needs to keep (inaccurate) statistics on its own. This decouples 245 * statistics gathering from scheduling interrupts. 246 * 247 * The RTC chip requires that we read status register C (RTC_INTR) 248 * to acknowledge an interrupt, before it will generate the next one. 249 */ 250static void 251rtcintr(struct clockframe frame) 252{ 253 u_char stat; 254 stat = rtcin(RTC_INTR); 255 if(stat & RTCIR_PERIOD) { 256 statclock(&frame); 257 } 258} 259 260#ifdef DDB 261static void 262DDB_printrtc(void) 263{ 264 printf("%02x/%02x/%02x %02x:%02x:%02x, A = %02x, B = %02x, C = %02x\n", 265 rtcin(RTC_YEAR), rtcin(RTC_MONTH), rtcin(RTC_DAY), 266 rtcin(RTC_HRS), rtcin(RTC_MIN), rtcin(RTC_SEC), 267 rtcin(RTC_STATUSA), rtcin(RTC_STATUSB), rtcin(RTC_INTR)); 268} 269#endif 270 271static int 272getit(void) 273{ 274 int high, low; 275 276 disable_intr(); 277 /* select timer0 and latch counter value */ 278 outb(TIMER_MODE, TIMER_SEL0); 279 low = inb(TIMER_CNTR0); 280 high = inb(TIMER_CNTR0); 281 enable_intr(); 282 return ((high << 8) | low); 283} 284 285#if defined(I586_CPU) || defined(I686_CPU) 286/* 287 * Figure out how fast the cyclecounter runs. This must be run with 288 * clock interrupts disabled, but with the timer/counter programmed 289 * and running. 290 */ 291void 292calibrate_cyclecounter(void) 293{ 294 /* 295 * Don't need volatile; should always use unsigned if 2's 296 * complement arithmetic is desired. 297 */ 298 unsigned long long count; 299 300#define howlong 131072UL 301 __asm __volatile(".byte 0x0f, 0x30" : : "A"(0LL), "c" (0x10)); 302 DELAY(howlong); 303 __asm __volatile(".byte 0xf,0x31" : "=A" (count)); 304 305 i586_ctr_rate = (count << I586_CTR_RATE_SHIFT) / howlong; 306#undef howlong 307} 308#endif 309 310/* 311 * Wait "n" microseconds. 312 * Relies on timer 1 counting down from (TIMER_FREQ / hz) 313 * Note: timer had better have been programmed before this is first used! 314 */ 315void 316DELAY(int n) 317{ 318 int prev_tick, tick, ticks_left, sec, usec; 319 320#ifdef DELAYDEBUG 321 int getit_calls = 1; 322 int n1; 323 static int state = 0; 324 325 if (state == 0) { 326 state = 1; 327 for (n1 = 1; n1 <= 10000000; n1 *= 10) 328 DELAY(n1); 329 state = 2; 330 } 331 if (state == 1) 332 printf("DELAY(%d)...", n); 333#endif 334 /* 335 * Read the counter first, so that the rest of the setup overhead is 336 * counted. Guess the initial overhead is 20 usec (on most systems it 337 * takes about 1.5 usec for each of the i/o's in getit(). The loop 338 * takes about 6 usec on a 486/33 and 13 usec on a 386/20. The 339 * multiplications and divisions to scale the count take a while). 340 */ 341 prev_tick = getit(); 342 n -= 20; 343 /* 344 * Calculate (n * (TIMER_FREQ / 1e6)) without using floating point 345 * and without any avoidable overflows. 346 */ 347 sec = n / 1000000; 348 usec = n - sec * 1000000; 349 ticks_left = sec * TIMER_FREQ 350 + usec * (TIMER_FREQ / 1000000) 351 + usec * ((TIMER_FREQ % 1000000) / 1000) / 1000 352 + usec * (TIMER_FREQ % 1000) / 1000000; 353 354 while (ticks_left > 0) { 355 tick = getit(); 356#ifdef DELAYDEBUG 357 ++getit_calls; 358#endif 359 if (tick > prev_tick) 360 ticks_left -= prev_tick - (tick - timer0_max_count); 361 else 362 ticks_left -= prev_tick - tick; 363 prev_tick = tick; 364 } 365#ifdef DELAYDEBUG 366 if (state == 1) 367 printf(" %d calls to getit() at %d usec each\n", 368 getit_calls, (n + 5) / getit_calls); 369#endif 370} 371 372static void 373sysbeepstop(void *chan) 374{ 375 outb(IO_PPI, inb(IO_PPI)&0xFC); /* disable counter2 output to speaker */ 376 release_timer2(); 377 beeping = 0; 378} 379 380int 381sysbeep(int pitch, int period) 382{ 383 384 if (acquire_timer2(TIMER_SQWAVE|TIMER_16BIT)) 385 return -1; 386 disable_intr(); 387 outb(TIMER_CNTR2, pitch); 388 outb(TIMER_CNTR2, (pitch>>8)); 389 enable_intr(); 390 if (!beeping) { 391 outb(IO_PPI, inb(IO_PPI) | 3); /* enable counter2 output to speaker */ 392 beeping = period; 393 timeout(sysbeepstop, (void *)NULL, period); 394 } 395 return 0; 396} 397 398/* 399 * RTC support routines 400 */ 401static int 402bcd2int(int bcd) 403{ 404 return(bcd/16 * 10 + bcd%16); 405} 406 407static int 408int2bcd(int dez) 409{ 410 return(dez/10 * 16 + dez%10); 411} 412 413static inline void 414writertc(u_char reg, u_char val) 415{ 416 outb(IO_RTC, reg); 417 outb(IO_RTC + 1, val); 418} 419 420static int 421readrtc(int port) 422{ 423 return(bcd2int(rtcin(port))); 424} 425 426/* 427 * Initialize 8253 timer 0 early so that it can be used in DELAY(). 428 * XXX initialization of other timers is unintentionally left blank. 429 */ 430void 431startrtclock() 432{ 433 timer0_max_count = hardclock_max_count = TIMER_DIV(hz); 434 timer0_overflow_threshold = timer0_max_count - TIMER0_LATCH_COUNT; 435 outb(TIMER_MODE, TIMER_SEL0 | TIMER_RATEGEN | TIMER_16BIT); 436 outb(TIMER_CNTR0, timer0_max_count & 0xff); 437 outb(TIMER_CNTR0, timer0_max_count >> 8); 438} 439 440/* 441 * Initialize the time of day register, based on the time base which is, e.g. 442 * from a filesystem. 443 */ 444void 445inittodr(time_t base) 446{ 447 unsigned long sec, days; 448 int yd; 449 int year, month; 450 int y, m, s; 451 452 s = splclock(); 453 time.tv_sec = base; 454 time.tv_usec = 0; 455 splx(s); 456 457 /* Look if we have a RTC present and the time is valid */ 458 if (!(rtcin(RTC_STATUSD) & RTCSD_PWR)) 459 goto wrong_time; 460 461 /* wait for time update to complete */ 462 /* If RTCSA_TUP is zero, we have at least 244us before next update */ 463 while (rtcin(RTC_STATUSA) & RTCSA_TUP); 464 465 days = 0; 466#ifdef USE_RTC_CENTURY 467 year = readrtc(RTC_YEAR) + readrtc(RTC_CENTURY) * 100; 468#else 469 year = readrtc(RTC_YEAR) + 1900; 470 if (year < 1970) 471 year += 100; 472#endif 473 if (year < 1970) 474 goto wrong_time; 475 month = readrtc(RTC_MONTH); 476 for (m = 1; m < month; m++) 477 days += daysinmonth[m-1]; 478 if ((month > 2) && LEAPYEAR(year)) 479 days ++; 480 days += readrtc(RTC_DAY) - 1; 481 yd = days; 482 for (y = 1970; y < year; y++) 483 days += DAYSPERYEAR + LEAPYEAR(y); 484 sec = ((( days * 24 + 485 readrtc(RTC_HRS)) * 60 + 486 readrtc(RTC_MIN)) * 60 + 487 readrtc(RTC_SEC)); 488 /* sec now contains the number of seconds, since Jan 1 1970, 489 in the local time zone */ 490 491 sec += tz.tz_minuteswest * 60 + adjkerntz; 492 493 s = splclock(); 494 time.tv_sec = sec; 495 splx(s); 496 return; 497 498wrong_time: 499 printf("Invalid time in real time clock.\n"); 500 printf("Check and reset the date immediately!\n"); 501} 502 503/* 504 * Write system time back to RTC 505 */ 506void 507resettodr() 508{ 509 unsigned long tm; 510 int y, m, s; 511 512 if (disable_rtc_set) 513 return; 514 515 s = splclock(); 516 tm = time.tv_sec; 517 splx(s); 518 519 /* Disable RTC updates and interrupts. */ 520 writertc(RTC_STATUSB, RTCSB_HALT | RTCSB_24HR); 521 522 /* Calculate local time to put in RTC */ 523 524 tm -= tz.tz_minuteswest * 60 + adjkerntz; 525 526 writertc(RTC_SEC, int2bcd(tm%60)); tm /= 60; /* Write back Seconds */ 527 writertc(RTC_MIN, int2bcd(tm%60)); tm /= 60; /* Write back Minutes */ 528 writertc(RTC_HRS, int2bcd(tm%24)); tm /= 24; /* Write back Hours */ 529 530 /* We have now the days since 01-01-1970 in tm */ 531 writertc(RTC_WDAY, (tm+4)%7); /* Write back Weekday */ 532 for (y=1970;; y++) 533 if ((tm - DAYSPERYEAR - LEAPYEAR(y)) > tm) 534 break; 535 else 536 tm -= DAYSPERYEAR + LEAPYEAR(y); 537 538 /* Now we have the years in y and the day-of-the-year in tm */ 539 writertc(RTC_YEAR, int2bcd(y%100)); /* Write back Year */ 540#ifdef USE_RTC_CENTURY 541 writertc(RTC_CENTURY, int2bcd(y/100)); /* ... and Century */ 542#endif 543 if (LEAPYEAR(y) && (tm >= 31+29)) 544 tm--; /* Subtract Feb-29 */ 545 for (m=1;; m++) 546 if (tm - daysinmonth[m-1] > tm) 547 break; 548 else 549 tm -= daysinmonth[m-1]; 550 551 writertc(RTC_MONTH, int2bcd(m)); /* Write back Month */ 552 writertc(RTC_DAY, int2bcd(tm+1)); /* Write back Day */ 553 554 /* Reenable RTC updates and interrupts. */ 555 writertc(RTC_STATUSB, RTCSB_24HR | RTCSB_PINTR); 556} 557 558/* 559 * Start both clocks running. 560 */ 561void 562cpu_initclocks() 563{ 564 int diag; 565 566 stathz = RTC_NOPROFRATE; 567 profhz = RTC_PROFRATE; 568 569 /* Finish initializing 8253 timer 0. */ 570 register_intr(/* irq */ 0, /* XXX id */ 0, /* flags */ 0, 571 /* XXX */ (inthand2_t *)clkintr, &clk_imask, 572 /* unit */ 0); 573 INTREN(IRQ0); 574#if defined(I586_CPU) || defined(I686_CPU) 575 /* 576 * Finish setting up anti-jitter measures. 577 */ 578 if (i586_ctr_rate) { 579 I586_CYCLECTR(i586_last_tick); 580 i586_ctr_bias = i586_last_tick; 581 } 582#endif 583 584 /* Initialize RTC. */ 585 writertc(RTC_STATUSA, rtc_statusa); 586 writertc(RTC_STATUSB, RTCSB_24HR); 587 diag = rtcin(RTC_DIAG); 588 if (diag != 0) 589 printf("RTC BIOS diagnostic error %b\n", diag, RTCDG_BITS); 590 register_intr(/* irq */ 8, /* XXX id */ 1, /* flags */ 0, 591 /* XXX */ (inthand2_t *)rtcintr, &stat_imask, 592 /* unit */ 0); 593 INTREN(IRQ8); 594 writertc(RTC_STATUSB, RTCSB_24HR | RTCSB_PINTR); 595} 596 597void 598setstatclockrate(int newhz) 599{ 600 if (newhz == RTC_PROFRATE) 601 rtc_statusa = RTCSA_DIVIDER | RTCSA_PROF; 602 else 603 rtc_statusa = RTCSA_DIVIDER | RTCSA_NOPROF; 604 writertc(RTC_STATUSA, rtc_statusa); 605}
|