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