pcrtc.c revision 112550
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 * $FreeBSD: head/sys/pc98/cbus/pcrtc.c 112550 2003-03-24 19:10:33Z mdodd $ 38 */ 39 40/* 41 * Routines to handle clock hardware. 42 */ 43 44/* 45 * inittodr, settodr and support routines written 46 * by Christoph Robitschko <chmr@edvz.tu-graz.ac.at> 47 * 48 * reintroduced and updated by Chris Stenton <chris@gnome.co.uk> 8/10/94 49 */ 50 51/* 52 * modified for PC98 by Kakefuda 53 */ 54 55#include "opt_clock.h" 56#include "opt_isa.h" 57#include "opt_mca.h" 58 59#include <sys/param.h> 60#include <sys/systm.h> 61#include <sys/bus.h> 62#include <sys/lock.h> 63#include <sys/mutex.h> 64#include <sys/proc.h> 65#include <sys/time.h> 66#include <sys/timetc.h> 67#include <sys/kernel.h> 68#include <sys/sysctl.h> 69#include <sys/cons.h> 70#include <sys/power.h> 71 72#include <machine/clock.h> 73#include <machine/cputypes.h> 74#include <machine/frame.h> 75#include <machine/limits.h> 76#include <machine/md_var.h> 77#include <machine/psl.h> 78#ifdef APIC_IO 79#include <machine/segments.h> 80#endif 81#if defined(SMP) || defined(APIC_IO) 82#include <machine/smp.h> 83#endif /* SMP || APIC_IO */ 84#include <machine/specialreg.h> 85 86#include <i386/isa/icu.h> 87#include <pc98/pc98/pc98.h> 88#include <pc98/pc98/pc98_machdep.h> 89#include <i386/isa/isa_device.h> 90#ifdef DEV_ISA 91#include <isa/isavar.h> 92#endif 93#include <i386/isa/timerreg.h> 94 95#include <i386/isa/intr_machdep.h> 96 97#ifdef APIC_IO 98#include <i386/isa/intr_machdep.h> 99/* The interrupt triggered by the 8254 (timer) chip */ 100int apic_8254_intr; 101static u_long read_intr_count(int vec); 102static void setup_8254_mixed_mode(void); 103#endif 104 105/* 106 * 32-bit time_t's can't reach leap years before 1904 or after 2036, so we 107 * can use a simple formula for leap years. 108 */ 109#define LEAPYEAR(y) ((u_int)(y) % 4 == 0) 110#define DAYSPERYEAR (31+28+31+30+31+30+31+31+30+31+30+31) 111 112#define TIMER_DIV(x) ((timer_freq + (x) / 2) / (x)) 113 114/* 115 * Time in timer cycles that it takes for microtime() to disable interrupts 116 * and latch the count. microtime() currently uses "cli; outb ..." so it 117 * normally takes less than 2 timer cycles. Add a few for cache misses. 118 * Add a few more to allow for latency in bogus calls to microtime() with 119 * interrupts already disabled. 120 */ 121#define TIMER0_LATCH_COUNT 20 122 123/* 124 * Maximum frequency that we are willing to allow for timer0. Must be 125 * low enough to guarantee that the timer interrupt handler returns 126 * before the next timer interrupt. 127 */ 128#define TIMER0_MAX_FREQ 20000 129 130int adjkerntz; /* local offset from GMT in seconds */ 131int clkintr_pending; 132int disable_rtc_set; /* disable resettodr() if != 0 */ 133int pscnt = 1; 134int psdiv = 1; 135int statclock_disable; 136#ifndef TIMER_FREQ 137#define TIMER_FREQ 2457600 138#endif 139u_int timer_freq = TIMER_FREQ; 140int timer0_max_count; 141int wall_cmos_clock; /* wall CMOS clock assumed if != 0 */ 142struct mtx clock_lock; 143 144static int beeping = 0; 145static const u_char daysinmonth[] = {31,28,31,30,31,30,31,31,30,31,30,31}; 146static u_int hardclock_max_count; 147static u_int32_t i8254_lastcount; 148static u_int32_t i8254_offset; 149static int i8254_ticked; 150/* 151 * XXX new_function and timer_func should not handle clockframes, but 152 * timer_func currently needs to hold hardclock to handle the 153 * timer0_state == 0 case. We should use inthand_add()/inthand_remove() 154 * to switch between clkintr() and a slightly different timerintr(). 155 */ 156static void (*new_function)(struct clockframe *frame); 157static u_int new_rate; 158static u_int timer0_prescaler_count; 159 160/* Values for timerX_state: */ 161#define RELEASED 0 162#define RELEASE_PENDING 1 163#define ACQUIRED 2 164#define ACQUIRE_PENDING 3 165 166static u_char timer0_state; 167static u_char timer1_state; 168static u_char timer2_state; 169static void (*timer_func)(struct clockframe *frame) = hardclock; 170static void rtc_serialcombit(int); 171static void rtc_serialcom(int); 172static int rtc_inb(void); 173static void rtc_outb(int); 174 175static unsigned i8254_get_timecount(struct timecounter *tc); 176static void set_timer_freq(u_int freq, int intr_freq); 177 178static struct timecounter i8254_timecounter = { 179 i8254_get_timecount, /* get_timecount */ 180 0, /* no poll_pps */ 181 ~0u, /* counter_mask */ 182 0, /* frequency */ 183 "i8254" /* name */ 184}; 185 186static void 187clkintr(struct clockframe frame) 188{ 189 190 if (timecounter->tc_get_timecount == i8254_get_timecount) { 191 mtx_lock_spin(&clock_lock); 192 if (i8254_ticked) 193 i8254_ticked = 0; 194 else { 195 i8254_offset += timer0_max_count; 196 i8254_lastcount = 0; 197 } 198 clkintr_pending = 0; 199 mtx_unlock_spin(&clock_lock); 200 } 201 timer_func(&frame); 202#ifdef SMP 203 if (timer_func == hardclock) 204 forward_hardclock(); 205#endif 206 switch (timer0_state) { 207 208 case RELEASED: 209 break; 210 211 case ACQUIRED: 212 if ((timer0_prescaler_count += timer0_max_count) 213 >= hardclock_max_count) { 214 timer0_prescaler_count -= hardclock_max_count; 215 hardclock(&frame); 216#ifdef SMP 217 forward_hardclock(); 218#endif 219 } 220 break; 221 222 case ACQUIRE_PENDING: 223 mtx_lock_spin(&clock_lock); 224 i8254_offset = i8254_get_timecount(NULL); 225 i8254_lastcount = 0; 226 timer0_max_count = TIMER_DIV(new_rate); 227 outb(TIMER_MODE, TIMER_SEL0 | TIMER_RATEGEN | TIMER_16BIT); 228 outb(TIMER_CNTR0, timer0_max_count & 0xff); 229 outb(TIMER_CNTR0, timer0_max_count >> 8); 230 mtx_unlock_spin(&clock_lock); 231 timer_func = new_function; 232 timer0_state = ACQUIRED; 233 break; 234 235 case RELEASE_PENDING: 236 if ((timer0_prescaler_count += timer0_max_count) 237 >= hardclock_max_count) { 238 mtx_lock_spin(&clock_lock); 239 i8254_offset = i8254_get_timecount(NULL); 240 i8254_lastcount = 0; 241 timer0_max_count = hardclock_max_count; 242 outb(TIMER_MODE, 243 TIMER_SEL0 | TIMER_RATEGEN | TIMER_16BIT); 244 outb(TIMER_CNTR0, timer0_max_count & 0xff); 245 outb(TIMER_CNTR0, timer0_max_count >> 8); 246 mtx_unlock_spin(&clock_lock); 247 timer0_prescaler_count = 0; 248 timer_func = hardclock; 249 timer0_state = RELEASED; 250 hardclock(&frame); 251#ifdef SMP 252 forward_hardclock(); 253#endif 254 } 255 break; 256 } 257} 258 259/* 260 * The acquire and release functions must be called at ipl >= splclock(). 261 */ 262int 263acquire_timer0(int rate, void (*function)(struct clockframe *frame)) 264{ 265 static int old_rate; 266 267 if (rate <= 0 || rate > TIMER0_MAX_FREQ) 268 return (-1); 269 switch (timer0_state) { 270 271 case RELEASED: 272 timer0_state = ACQUIRE_PENDING; 273 break; 274 275 case RELEASE_PENDING: 276 if (rate != old_rate) 277 return (-1); 278 /* 279 * The timer has been released recently, but is being 280 * re-acquired before the release completed. In this 281 * case, we simply reclaim it as if it had not been 282 * released at all. 283 */ 284 timer0_state = ACQUIRED; 285 break; 286 287 default: 288 return (-1); /* busy */ 289 } 290 new_function = function; 291 old_rate = new_rate = rate; 292 return (0); 293} 294 295int 296acquire_timer1(int mode) 297{ 298 299 if (timer1_state != RELEASED) 300 return (-1); 301 timer1_state = ACQUIRED; 302 303 /* 304 * This access to the timer registers is as atomic as possible 305 * because it is a single instruction. We could do better if we 306 * knew the rate. Use of splclock() limits glitches to 10-100us, 307 * and this is probably good enough for timer2, so we aren't as 308 * careful with it as with timer0. 309 */ 310 outb(TIMER_MODE, TIMER_SEL1 | (mode & 0x3f)); 311 312 return (0); 313} 314 315int 316acquire_timer2(int mode) 317{ 318 319 if (timer2_state != RELEASED) 320 return (-1); 321 timer2_state = ACQUIRED; 322 323 /* 324 * This access to the timer registers is as atomic as possible 325 * because it is a single instruction. We could do better if we 326 * knew the rate. Use of splclock() limits glitches to 10-100us, 327 * and this is probably good enough for timer2, so we aren't as 328 * careful with it as with timer0. 329 */ 330 outb(TIMER_MODE, TIMER_SEL2 | (mode & 0x3f)); 331 332 return (0); 333} 334 335int 336release_timer0() 337{ 338 switch (timer0_state) { 339 340 case ACQUIRED: 341 timer0_state = RELEASE_PENDING; 342 break; 343 344 case ACQUIRE_PENDING: 345 /* Nothing happened yet, release quickly. */ 346 timer0_state = RELEASED; 347 break; 348 349 default: 350 return (-1); 351 } 352 return (0); 353} 354 355int 356release_timer1() 357{ 358 359 if (timer1_state != ACQUIRED) 360 return (-1); 361 timer1_state = RELEASED; 362 outb(TIMER_MODE, TIMER_SEL1 | TIMER_SQWAVE | TIMER_16BIT); 363 return (0); 364} 365 366int 367release_timer2() 368{ 369 370 if (timer2_state != ACQUIRED) 371 return (-1); 372 timer2_state = RELEASED; 373 outb(TIMER_MODE, TIMER_SEL2 | TIMER_SQWAVE | TIMER_16BIT); 374 return (0); 375} 376 377 378static int 379getit(void) 380{ 381 int high, low; 382 383 mtx_lock_spin(&clock_lock); 384 385 /* Select timer0 and latch counter value. */ 386 outb(TIMER_MODE, TIMER_SEL0 | TIMER_LATCH); 387 388 low = inb(TIMER_CNTR0); 389 high = inb(TIMER_CNTR0); 390 391 mtx_unlock_spin(&clock_lock); 392 return ((high << 8) | low); 393} 394 395/* 396 * Wait "n" microseconds. 397 * Relies on timer 1 counting down from (timer_freq / hz) 398 * Note: timer had better have been programmed before this is first used! 399 */ 400void 401DELAY(int n) 402{ 403 int delta, prev_tick, tick, ticks_left; 404 405#ifdef DELAYDEBUG 406 int getit_calls = 1; 407 int n1; 408 static int state = 0; 409 410 if (state == 0) { 411 state = 1; 412 for (n1 = 1; n1 <= 10000000; n1 *= 10) 413 DELAY(n1); 414 state = 2; 415 } 416 if (state == 1) 417 printf("DELAY(%d)...", n); 418#endif 419 /* 420 * Guard against the timer being uninitialized if we are called 421 * early for console i/o. 422 */ 423 if (timer0_max_count == 0) 424 set_timer_freq(timer_freq, hz); 425 426 /* 427 * Read the counter first, so that the rest of the setup overhead is 428 * counted. Guess the initial overhead is 20 usec (on most systems it 429 * takes about 1.5 usec for each of the i/o's in getit(). The loop 430 * takes about 6 usec on a 486/33 and 13 usec on a 386/20. The 431 * multiplications and divisions to scale the count take a while). 432 */ 433 prev_tick = getit(); 434 n -= 0; /* XXX actually guess no initial overhead */ 435 /* 436 * Calculate (n * (timer_freq / 1e6)) without using floating point 437 * and without any avoidable overflows. 438 */ 439 if (n <= 0) 440 ticks_left = 0; 441 else if (n < 256) 442 /* 443 * Use fixed point to avoid a slow division by 1000000. 444 * 39099 = 1193182 * 2^15 / 10^6 rounded to nearest. 445 * 2^15 is the first power of 2 that gives exact results 446 * for n between 0 and 256. 447 */ 448 ticks_left = ((u_int)n * 39099 + (1 << 15) - 1) >> 15; 449 else 450 /* 451 * Don't bother using fixed point, although gcc-2.7.2 452 * generates particularly poor code for the long long 453 * division, since even the slow way will complete long 454 * before the delay is up (unless we're interrupted). 455 */ 456 ticks_left = ((u_int)n * (long long)timer_freq + 999999) 457 / 1000000; 458 459 while (ticks_left > 0) { 460 tick = getit(); 461#ifdef DELAYDEBUG 462 ++getit_calls; 463#endif 464 delta = prev_tick - tick; 465 prev_tick = tick; 466 if (delta < 0) { 467 delta += timer0_max_count; 468 /* 469 * Guard against timer0_max_count being wrong. 470 * This shouldn't happen in normal operation, 471 * but it may happen if set_timer_freq() is 472 * traced. 473 */ 474 if (delta < 0) 475 delta = 0; 476 } 477 ticks_left -= delta; 478 } 479#ifdef DELAYDEBUG 480 if (state == 1) 481 printf(" %d calls to getit() at %d usec each\n", 482 getit_calls, (n + 5) / getit_calls); 483#endif 484} 485 486static void 487sysbeepstop(void *chan) 488{ 489 outb(IO_PPI, inb(IO_PPI)|0x08); /* disable counter1 output to speaker */ 490 release_timer1(); 491 beeping = 0; 492} 493 494int 495sysbeep(int pitch, int period) 496{ 497 int x = splclock(); 498 499 if (acquire_timer1(TIMER_SQWAVE|TIMER_16BIT)) 500 if (!beeping) { 501 /* Something else owns it. */ 502 splx(x); 503 return (-1); /* XXX Should be EBUSY, but nobody cares anyway. */ 504 } 505 disable_intr(); 506 outb(0x3fdb, pitch); 507 outb(0x3fdb, (pitch>>8)); 508 enable_intr(); 509 if (!beeping) { 510 /* enable counter1 output to speaker */ 511 outb(IO_PPI, (inb(IO_PPI) & 0xf7)); 512 beeping = period; 513 timeout(sysbeepstop, (void *)NULL, period); 514 } 515 splx(x); 516 return (0); 517} 518 519 520unsigned int delaycount; 521#define FIRST_GUESS 0x2000 522static void findcpuspeed(void) 523{ 524 int i; 525 int remainder; 526 527 /* Put counter in count down mode */ 528 outb(TIMER_MODE, TIMER_SEL0 | TIMER_16BIT | TIMER_RATEGEN); 529 outb(TIMER_CNTR0, 0xff); 530 outb(TIMER_CNTR0, 0xff); 531 for (i = FIRST_GUESS; i; i--) 532 ; 533 remainder = getit(); 534 delaycount = (FIRST_GUESS * TIMER_DIV(1000)) / (0xffff - remainder); 535} 536 537static u_int 538calibrate_clocks(void) 539{ 540 int timeout; 541 u_int count, prev_count, tot_count; 542 u_short sec, start_sec; 543 544 if (bootverbose) 545 printf("Calibrating clock(s) ... "); 546 /* Check ARTIC. */ 547 if (!(PC98_SYSTEM_PARAMETER(0x458) & 0x80) && 548 !(PC98_SYSTEM_PARAMETER(0x45b) & 0x04)) 549 goto fail; 550 timeout = 100000000; 551 552 /* Read the ARTIC. */ 553 sec = inw(0x5e); 554 555 /* Wait for the ARTIC to changes. */ 556 start_sec = sec; 557 for (;;) { 558 sec = inw(0x5e); 559 if (sec != start_sec) 560 break; 561 if (--timeout == 0) 562 goto fail; 563 } 564 prev_count = getit(); 565 if (prev_count == 0 || prev_count > timer0_max_count) 566 goto fail; 567 tot_count = 0; 568 569 start_sec = sec; 570 for (;;) { 571 sec = inw(0x5e); 572 count = getit(); 573 if (count == 0 || count > timer0_max_count) 574 goto fail; 575 if (count > prev_count) 576 tot_count += prev_count - (count - timer0_max_count); 577 else 578 tot_count += prev_count - count; 579 prev_count = count; 580 if ((sec == start_sec + 1200) || 581 (sec < start_sec && 582 (u_int)sec + 0x10000 == (u_int)start_sec + 1200)) 583 break; 584 if (--timeout == 0) 585 goto fail; 586 } 587 588 if (bootverbose) { 589 printf("i8254 clock: %u Hz\n", tot_count); 590 } 591 return (tot_count); 592 593fail: 594 if (bootverbose) 595 printf("failed, using default i8254 clock of %u Hz\n", 596 timer_freq); 597 return (timer_freq); 598} 599 600static void 601set_timer_freq(u_int freq, int intr_freq) 602{ 603 int new_timer0_max_count; 604 605 mtx_lock_spin(&clock_lock); 606 timer_freq = freq; 607 new_timer0_max_count = hardclock_max_count = TIMER_DIV(intr_freq); 608 if (new_timer0_max_count != timer0_max_count) { 609 timer0_max_count = new_timer0_max_count; 610 outb(TIMER_MODE, TIMER_SEL0 | TIMER_RATEGEN | TIMER_16BIT); 611 outb(TIMER_CNTR0, timer0_max_count & 0xff); 612 outb(TIMER_CNTR0, timer0_max_count >> 8); 613 } 614 mtx_unlock_spin(&clock_lock); 615} 616 617static void 618i8254_restore(void) 619{ 620 621 mtx_lock_spin(&clock_lock); 622 outb(TIMER_MODE, TIMER_SEL0 | TIMER_RATEGEN | TIMER_16BIT); 623 outb(TIMER_CNTR0, timer0_max_count & 0xff); 624 outb(TIMER_CNTR0, timer0_max_count >> 8); 625 mtx_unlock_spin(&clock_lock); 626} 627 628 629/* 630 * Restore all the timers non-atomically (XXX: should be atomically). 631 * 632 * This function is called from pmtimer_resume() to restore all the timers. 633 * This should not be necessary, but there are broken laptops that do not 634 * restore all the timers on resume. 635 */ 636void 637timer_restore(void) 638{ 639 640 i8254_restore(); /* restore timer_freq and hz */ 641} 642 643/* 644 * Initialize 8254 timer 0 early so that it can be used in DELAY(). 645 * XXX initialization of other timers is unintentionally left blank. 646 */ 647void 648startrtclock() 649{ 650 u_int delta, freq; 651 652 findcpuspeed(); 653 if (pc98_machine_type & M_8M) 654 timer_freq = 1996800L; /* 1.9968 MHz */ 655 else 656 timer_freq = 2457600L; /* 2.4576 MHz */ 657 658 set_timer_freq(timer_freq, hz); 659 freq = calibrate_clocks(); 660#ifdef CLK_CALIBRATION_LOOP 661 if (bootverbose) { 662 printf( 663 "Press a key on the console to abort clock calibration\n"); 664 while (cncheckc() == -1) 665 calibrate_clocks(); 666 } 667#endif 668 669 /* 670 * Use the calibrated i8254 frequency if it seems reasonable. 671 * Otherwise use the default, and don't use the calibrated i586 672 * frequency. 673 */ 674 delta = freq > timer_freq ? freq - timer_freq : timer_freq - freq; 675 if (delta < timer_freq / 100) { 676#ifndef CLK_USE_I8254_CALIBRATION 677 if (bootverbose) 678 printf( 679"CLK_USE_I8254_CALIBRATION not specified - using default frequency\n"); 680 freq = timer_freq; 681#endif 682 timer_freq = freq; 683 } else { 684 if (bootverbose) 685 printf( 686 "%d Hz differs from default of %d Hz by more than 1%%\n", 687 freq, timer_freq); 688 } 689 690 set_timer_freq(timer_freq, hz); 691 i8254_timecounter.tc_frequency = timer_freq; 692 tc_init(&i8254_timecounter); 693 694 init_TSC(); 695} 696 697static void 698rtc_serialcombit(int i) 699{ 700 outb(IO_RTC, ((i&0x01)<<5)|0x07); 701 DELAY(1); 702 outb(IO_RTC, ((i&0x01)<<5)|0x17); 703 DELAY(1); 704 outb(IO_RTC, ((i&0x01)<<5)|0x07); 705 DELAY(1); 706} 707 708static void 709rtc_serialcom(int i) 710{ 711 rtc_serialcombit(i&0x01); 712 rtc_serialcombit((i&0x02)>>1); 713 rtc_serialcombit((i&0x04)>>2); 714 rtc_serialcombit((i&0x08)>>3); 715 outb(IO_RTC, 0x07); 716 DELAY(1); 717 outb(IO_RTC, 0x0f); 718 DELAY(1); 719 outb(IO_RTC, 0x07); 720 DELAY(1); 721} 722 723static void 724rtc_outb(int val) 725{ 726 int s; 727 int sa = 0; 728 729 for (s=0;s<8;s++) { 730 sa = ((val >> s) & 0x01) ? 0x27 : 0x07; 731 outb(IO_RTC, sa); /* set DI & CLK 0 */ 732 DELAY(1); 733 outb(IO_RTC, sa | 0x10); /* CLK 1 */ 734 DELAY(1); 735 } 736 outb(IO_RTC, sa & 0xef); /* CLK 0 */ 737} 738 739static int 740rtc_inb(void) 741{ 742 int s; 743 int sa = 0; 744 745 for (s=0;s<8;s++) { 746 sa |= ((inb(0x33) & 0x01) << s); 747 outb(IO_RTC, 0x17); /* CLK 1 */ 748 DELAY(1); 749 outb(IO_RTC, 0x07); /* CLK 0 */ 750 DELAY(2); 751 } 752 return sa; 753} 754 755/* 756 * Initialize the time of day register, based on the time base which is, e.g. 757 * from a filesystem. 758 */ 759void 760inittodr(time_t base) 761{ 762 unsigned long sec, days; 763 int year, month; 764 int y, m, s; 765 struct timespec ts; 766 int second, min, hour; 767 768 if (base) { 769 s = splclock(); 770 ts.tv_sec = base; 771 ts.tv_nsec = 0; 772 tc_setclock(&ts); 773 splx(s); 774 } 775 776 rtc_serialcom(0x03); /* Time Read */ 777 rtc_serialcom(0x01); /* Register shift command. */ 778 DELAY(20); 779 780 second = bcd2bin(rtc_inb() & 0xff); /* sec */ 781 min = bcd2bin(rtc_inb() & 0xff); /* min */ 782 hour = bcd2bin(rtc_inb() & 0xff); /* hour */ 783 days = bcd2bin(rtc_inb() & 0xff) - 1; /* date */ 784 785 month = (rtc_inb() >> 4) & 0x0f; /* month */ 786 for (m = 1; m < month; m++) 787 days += daysinmonth[m-1]; 788 year = bcd2bin(rtc_inb() & 0xff) + 1900; /* year */ 789 /* 2000 year problem */ 790 if (year < 1995) 791 year += 100; 792 if (year < 1970) 793 goto wrong_time; 794 for (y = 1970; y < year; y++) 795 days += DAYSPERYEAR + LEAPYEAR(y); 796 if ((month > 2) && LEAPYEAR(year)) 797 days ++; 798 sec = ((( days * 24 + 799 hour) * 60 + 800 min) * 60 + 801 second); 802 /* sec now contains the number of seconds, since Jan 1 1970, 803 in the local time zone */ 804 805 s = splhigh(); 806 807 sec += tz_minuteswest * 60 + (wall_cmos_clock ? adjkerntz : 0); 808 809 y = time_second - sec; 810 if (y <= -2 || y >= 2) { 811 /* badly off, adjust it */ 812 ts.tv_sec = sec; 813 ts.tv_nsec = 0; 814 tc_setclock(&ts); 815 } 816 splx(s); 817 return; 818 819wrong_time: 820 printf("Invalid time in real time clock.\n"); 821 printf("Check and reset the date immediately!\n"); 822} 823 824/* 825 * Write system time back to RTC 826 */ 827void 828resettodr() 829{ 830 unsigned long tm; 831 int y, m, s; 832 int wd; 833 834 if (disable_rtc_set) 835 return; 836 837 s = splclock(); 838 tm = time_second; 839 splx(s); 840 841 rtc_serialcom(0x01); /* Register shift command. */ 842 843 /* Calculate local time to put in RTC */ 844 845 tm -= tz_minuteswest * 60 + (wall_cmos_clock ? adjkerntz : 0); 846 847 rtc_outb(bin2bcd(tm%60)); tm /= 60; /* Write back Seconds */ 848 rtc_outb(bin2bcd(tm%60)); tm /= 60; /* Write back Minutes */ 849 rtc_outb(bin2bcd(tm%24)); tm /= 24; /* Write back Hours */ 850 851 /* We have now the days since 01-01-1970 in tm */ 852 wd = (tm + 4) % 7 + 1; /* Write back Weekday */ 853 for (y = 1970, m = DAYSPERYEAR + LEAPYEAR(y); 854 tm >= m; 855 y++, m = DAYSPERYEAR + LEAPYEAR(y)) 856 tm -= m; 857 858 /* Now we have the years in y and the day-of-the-year in tm */ 859 for (m = 0; ; m++) { 860 int ml; 861 862 ml = daysinmonth[m]; 863 if (m == 1 && LEAPYEAR(y)) 864 ml++; 865 if (tm < ml) 866 break; 867 tm -= ml; 868 } 869 870 m++; 871 rtc_outb(bin2bcd(tm+1)); /* Write back Day */ 872 rtc_outb((m << 4) | wd); /* Write back Month & Weekday */ 873 rtc_outb(bin2bcd(y%100)); /* Write back Year */ 874 875 rtc_serialcom(0x02); /* Time set & Counter hold command. */ 876 rtc_serialcom(0x00); /* Register hold command. */ 877} 878 879 880/* 881 * Start both clocks running. 882 */ 883void 884cpu_initclocks() 885{ 886#ifdef APIC_IO 887 int apic_8254_trial; 888 void *clkdesc; 889#endif /* APIC_IO */ 890 register_t crit; 891 892 893 /* Finish initializing 8253 timer 0. */ 894#ifdef APIC_IO 895 896 apic_8254_intr = isa_apic_irq(0); 897 apic_8254_trial = 0; 898 if (apic_8254_intr >= 0 ) { 899 if (apic_int_type(0, 0) == 3) 900 apic_8254_trial = 1; 901 } else { 902 /* look for ExtInt on pin 0 */ 903 if (apic_int_type(0, 0) == 3) { 904 apic_8254_intr = apic_irq(0, 0); 905 setup_8254_mixed_mode(); 906 } else 907 panic("APIC_IO: Cannot route 8254 interrupt to CPU"); 908 } 909 910 inthand_add("clk", apic_8254_intr, (driver_intr_t *)clkintr, NULL, 911 INTR_TYPE_CLK | INTR_FAST, &clkdesc); 912 crit = intr_disable(); 913 mtx_lock_spin(&icu_lock); 914 INTREN(1 << apic_8254_intr); 915 mtx_unlock_spin(&icu_lock); 916 intr_restore(crit); 917 918#else /* APIC_IO */ 919 920 /* 921 * XXX Check the priority of this interrupt handler. I 922 * couldn't find anything suitable in the BSD/OS code (grog, 923 * 19 July 2000). 924 */ 925 inthand_add("clk", 0, (driver_intr_t *)clkintr, NULL, 926 INTR_TYPE_CLK | INTR_FAST, NULL); 927 crit = intr_disable(); 928 mtx_lock_spin(&icu_lock); 929 INTREN(IRQ0); 930 mtx_unlock_spin(&icu_lock); 931 intr_restore(crit); 932 933#endif /* APIC_IO */ 934 935 936 937#ifdef APIC_IO 938 if (apic_8254_trial) { 939 940 printf("APIC_IO: Testing 8254 interrupt delivery\n"); 941 while (read_intr_count(8) < 6) 942 ; /* nothing */ 943 if (read_intr_count(apic_8254_intr) < 3) { 944 /* 945 * The MP table is broken. 946 * The 8254 was not connected to the specified pin 947 * on the IO APIC. 948 * Workaround: Limited variant of mixed mode. 949 */ 950 951 crit = intr_disable(); 952 mtx_lock_spin(&icu_lock); 953 INTRDIS(1 << apic_8254_intr); 954 mtx_unlock_spin(&icu_lock); 955 intr_restore(crit); 956 inthand_remove(clkdesc); 957 printf("APIC_IO: Broken MP table detected: " 958 "8254 is not connected to " 959 "IOAPIC #%d intpin %d\n", 960 int_to_apicintpin[apic_8254_intr].ioapic, 961 int_to_apicintpin[apic_8254_intr].int_pin); 962 /* 963 * Revoke current ISA IRQ 0 assignment and 964 * configure a fallback interrupt routing from 965 * the 8254 Timer via the 8259 PIC to the 966 * an ExtInt interrupt line on IOAPIC #0 intpin 0. 967 * We reuse the low level interrupt handler number. 968 */ 969 if (apic_irq(0, 0) < 0) { 970 revoke_apic_irq(apic_8254_intr); 971 assign_apic_irq(0, 0, apic_8254_intr); 972 } 973 apic_8254_intr = apic_irq(0, 0); 974 setup_8254_mixed_mode(); 975 inthand_add("clk", apic_8254_intr, 976 (driver_intr_t *)clkintr, NULL, 977 INTR_TYPE_CLK | INTR_FAST, NULL); 978 crit = intr_disable(); 979 mtx_lock_spin(&icu_lock); 980 INTREN(1 << apic_8254_intr); 981 mtx_unlock_spin(&icu_lock); 982 intr_restore(crit); 983 } 984 985 } 986 if (apic_int_type(0, 0) != 3 || 987 int_to_apicintpin[apic_8254_intr].ioapic != 0 || 988 int_to_apicintpin[apic_8254_intr].int_pin != 0) 989 printf("APIC_IO: routing 8254 via IOAPIC #%d intpin %d\n", 990 int_to_apicintpin[apic_8254_intr].ioapic, 991 int_to_apicintpin[apic_8254_intr].int_pin); 992 else 993 printf("APIC_IO: " 994 "routing 8254 via 8259 and IOAPIC #0 intpin 0\n"); 995#endif 996 997} 998 999#ifdef APIC_IO 1000static u_long 1001read_intr_count(int vec) 1002{ 1003 u_long *up; 1004 up = intr_countp[vec]; 1005 if (up) 1006 return *up; 1007 return 0UL; 1008} 1009 1010static void 1011setup_8254_mixed_mode() 1012{ 1013 /* 1014 * Allow 8254 timer to INTerrupt 8259: 1015 * re-initialize master 8259: 1016 * reset; prog 4 bytes, single ICU, edge triggered 1017 */ 1018 outb(IO_ICU1, 0x13); 1019 outb(IO_ICU1 + 2, NRSVIDT); /* start vector (unused) */ 1020 outb(IO_ICU1 + 2, 0x00); /* ignore slave */ 1021 outb(IO_ICU1 + 2, 0x03); /* auto EOI, 8086 */ 1022 outb(IO_ICU1 + 2, 0xfe); /* unmask INT0 */ 1023 1024 /* program IO APIC for type 3 INT on INT0 */ 1025 if (ext_int_setup(0, 0) < 0) 1026 panic("8254 redirect via APIC pin0 impossible!"); 1027} 1028#endif 1029 1030void 1031cpu_startprofclock(void) 1032{ 1033} 1034 1035void 1036cpu_stopprofclock(void) 1037{ 1038} 1039 1040static int 1041sysctl_machdep_i8254_freq(SYSCTL_HANDLER_ARGS) 1042{ 1043 int error; 1044 u_int freq; 1045 1046 /* 1047 * Use `i8254' instead of `timer' in external names because `timer' 1048 * is is too generic. Should use it everywhere. 1049 */ 1050 freq = timer_freq; 1051 error = sysctl_handle_int(oidp, &freq, sizeof(freq), req); 1052 if (error == 0 && req->newptr != NULL) { 1053 if (timer0_state != RELEASED) 1054 return (EBUSY); /* too much trouble to handle */ 1055 set_timer_freq(freq, hz); 1056 i8254_timecounter.tc_frequency = freq; 1057 } 1058 return (error); 1059} 1060 1061SYSCTL_PROC(_machdep, OID_AUTO, i8254_freq, CTLTYPE_INT | CTLFLAG_RW, 1062 0, sizeof(u_int), sysctl_machdep_i8254_freq, "IU", ""); 1063 1064static unsigned 1065i8254_get_timecount(struct timecounter *tc) 1066{ 1067 u_int count; 1068 u_int high, low; 1069 u_int eflags; 1070 1071 eflags = read_eflags(); 1072 mtx_lock_spin(&clock_lock); 1073 1074 /* Select timer0 and latch counter value. */ 1075 outb(TIMER_MODE, TIMER_SEL0 | TIMER_LATCH); 1076 1077 low = inb(TIMER_CNTR0); 1078 high = inb(TIMER_CNTR0); 1079 count = timer0_max_count - ((high << 8) | low); 1080 if (count < i8254_lastcount || 1081 (!i8254_ticked && (clkintr_pending || 1082 ((count < 20 || (!(eflags & PSL_I) && count < timer0_max_count / 2u)) && 1083#ifdef APIC_IO 1084#define lapic_irr1 ((volatile u_int *)&lapic)[0x210 / 4] /* XXX XXX */ 1085 /* XXX this assumes that apic_8254_intr is < 24. */ 1086 (lapic_irr1 & (1 << apic_8254_intr)))) 1087#else 1088 (inb(IO_ICU1) & 1))) 1089#endif 1090 )) { 1091 i8254_ticked = 1; 1092 i8254_offset += timer0_max_count; 1093 } 1094 i8254_lastcount = count; 1095 count += i8254_offset; 1096 mtx_unlock_spin(&clock_lock); 1097 return (count); 1098} 1099 1100#ifdef DEV_ISA 1101/* 1102 * Attach to the ISA PnP descriptors for the timer and realtime clock. 1103 */ 1104static struct isa_pnp_id attimer_ids[] = { 1105 { 0x0001d041 /* PNP0100 */, "AT timer" }, 1106 { 0x000bd041 /* PNP0B00 */, "AT realtime clock" }, 1107 { 0 } 1108}; 1109 1110static int 1111attimer_probe(device_t dev) 1112{ 1113 int result; 1114 1115 if ((result = ISA_PNP_PROBE(device_get_parent(dev), dev, attimer_ids)) <= 0) 1116 device_quiet(dev); 1117 return(result); 1118} 1119 1120static int 1121attimer_attach(device_t dev) 1122{ 1123 return(0); 1124} 1125 1126static device_method_t attimer_methods[] = { 1127 /* Device interface */ 1128 DEVMETHOD(device_probe, attimer_probe), 1129 DEVMETHOD(device_attach, attimer_attach), 1130 DEVMETHOD(device_detach, bus_generic_detach), 1131 DEVMETHOD(device_shutdown, bus_generic_shutdown), 1132 DEVMETHOD(device_suspend, bus_generic_suspend), /* XXX stop statclock? */ 1133 DEVMETHOD(device_resume, bus_generic_resume), /* XXX restart statclock? */ 1134 { 0, 0 } 1135}; 1136 1137static driver_t attimer_driver = { 1138 "attimer", 1139 attimer_methods, 1140 1, /* no softc */ 1141}; 1142 1143static devclass_t attimer_devclass; 1144 1145DRIVER_MODULE(attimer, isa, attimer_driver, attimer_devclass, 0, 0); 1146#endif /* DEV_ISA */ 1147