clock.c (15345) | clock.c (15508) |
---|---|
1/*- 2 * Copyright (c) 1990 The Regents of the University of California. 3 * All rights reserved. 4 * 5 * This code is derived from software contributed to Berkeley by 6 * William Jolitz and Don Ahn. 7 * 8 * Redistribution and use in source and binary forms, with or without --- 20 unchanged lines hidden (view full) --- 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 --- 20 unchanged lines hidden (view full) --- 29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 34 * SUCH DAMAGE. 35 * 36 * from: @(#)clock.c 7.2 (Berkeley) 5/12/91 |
37 * $Id: clock.c,v 1.56 1996/04/05 18:56:10 ache Exp $ | 37 * $Id: clock.c,v 1.57 1996/04/22 19:40:28 nate Exp $ |
38 */ 39 40/* 41 * inittodr, settodr and support routines written 42 * by Christoph Robitschko <chmr@edvz.tu-graz.ac.at> 43 * 44 * reintroduced and updated by Chris Stenton <chris@gnome.co.uk> 8/10/94 45 */ 46 47/* 48 * Primitive clock interrupt routines. 49 */ 50#include "opt_ddb.h" 51 52#include <sys/param.h> 53#include <sys/systm.h> 54#include <sys/time.h> 55#include <sys/kernel.h> | 38 */ 39 40/* 41 * inittodr, settodr and support routines written 42 * by Christoph Robitschko <chmr@edvz.tu-graz.ac.at> 43 * 44 * reintroduced and updated by Chris Stenton <chris@gnome.co.uk> 8/10/94 45 */ 46 47/* 48 * Primitive clock interrupt routines. 49 */ 50#include "opt_ddb.h" 51 52#include <sys/param.h> 53#include <sys/systm.h> 54#include <sys/time.h> 55#include <sys/kernel.h> |
56#include <sys/sysctl.h> 57 |
|
56#include <machine/clock.h> | 58#include <machine/clock.h> |
59#ifdef CLK_CALIBRATION_LOOP 60#include <machine/cons.h> 61#endif 62#include <machine/cpu.h> |
|
57#include <machine/frame.h> | 63#include <machine/frame.h> |
64 |
|
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 | 65#include <i386/isa/icu.h> 66#include <i386/isa/isa.h> 67#include <i386/isa/isa_device.h> 68#include <i386/isa/rtc.h> 69#include <i386/isa/timerreg.h> 70 71/* 72 * 32-bit time_t's can't reach leap years before 1904 or after 2036, so we 73 * can use a simple formula for leap years. 74 */ 75#define LEAPYEAR(y) ((u_int)(y) % 4 == 0) 76#define DAYSPERYEAR (31+28+31+30+31+30+31+31+30+31+30+31) 77 |
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)) | 78#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 */ --- 9 unchanged lines hidden (view full) --- 93#define TIMER0_MIN_MAX_COUNT TIMER_DIV(20000) 94 95int adjkerntz; /* local offset from GMT in seconds */ 96int disable_rtc_set; /* disable resettodr() if != 0 */ 97int wall_cmos_clock; /* wall CMOS clock assumed if != 0 */ 98 99u_int idelayed; 100#if defined(I586_CPU) || defined(I686_CPU) | 79 80/* 81 * Time in timer cycles that it takes for microtime() to disable interrupts 82 * and latch the count. microtime() currently uses "cli; outb ..." so it 83 * normally takes less than 2 timer cycles. Add a few for cache misses. 84 * Add a few more to allow for latency in bogus calls to microtime() with 85 * interrupts already disabled. 86 */ --- 9 unchanged lines hidden (view full) --- 96#define TIMER0_MIN_MAX_COUNT TIMER_DIV(20000) 97 98int adjkerntz; /* local offset from GMT in seconds */ 99int disable_rtc_set; /* disable resettodr() if != 0 */ 100int wall_cmos_clock; /* wall CMOS clock assumed if != 0 */ 101 102u_int idelayed; 103#if defined(I586_CPU) || defined(I686_CPU) |
104unsigned i586_ctr_freq; |
|
101unsigned i586_ctr_rate; 102long long i586_ctr_bias; 103long long i586_last_tick; 104unsigned long i586_avg_tick; 105#endif 106int statclock_disable; 107u_int stat_imask = SWI_CLOCK_MASK; 108int timer0_max_count; --- 11 unchanged lines hidden (view full) --- 120 * to switch between clkintr() and a slightly different timerintr(). 121 * This will require locking when acquiring and releasing timer0 - the 122 * current (nonexistent) locking doesn't seem to be adequate even now. 123 */ 124static void (*new_function) __P((struct clockframe *frame)); 125static u_int new_rate; 126static u_char rtc_statusa = RTCSA_DIVIDER | RTCSA_NOPROF; 127static u_char rtc_statusb = RTCSB_24HR | RTCSB_PINTR; | 105unsigned i586_ctr_rate; 106long long i586_ctr_bias; 107long long i586_last_tick; 108unsigned long i586_avg_tick; 109#endif 110int statclock_disable; 111u_int stat_imask = SWI_CLOCK_MASK; 112int timer0_max_count; --- 11 unchanged lines hidden (view full) --- 124 * to switch between clkintr() and a slightly different timerintr(). 125 * This will require locking when acquiring and releasing timer0 - the 126 * current (nonexistent) locking doesn't seem to be adequate even now. 127 */ 128static void (*new_function) __P((struct clockframe *frame)); 129static u_int new_rate; 130static u_char rtc_statusa = RTCSA_DIVIDER | RTCSA_NOPROF; 131static u_char rtc_statusb = RTCSB_24HR | RTCSB_PINTR; |
132#ifdef TIMER_FREQ 133static u_int timer_freq = TIMER_FREQ; 134#else 135static u_int timer_freq = 1193182; 136#endif |
|
128static char timer0_state = 0; 129static char timer2_state = 0; 130static void (*timer_func) __P((struct clockframe *frame)) = hardclock; 131 132#if 0 133void 134clkintr(struct clockframe frame) 135{ --- 146 unchanged lines hidden (view full) --- 282 /* select timer0 and latch counter value */ 283 outb(TIMER_MODE, TIMER_SEL0); 284 low = inb(TIMER_CNTR0); 285 high = inb(TIMER_CNTR0); 286 enable_intr(); 287 return ((high << 8) | low); 288} 289 | 137static char timer0_state = 0; 138static char timer2_state = 0; 139static void (*timer_func) __P((struct clockframe *frame)) = hardclock; 140 141#if 0 142void 143clkintr(struct clockframe frame) 144{ --- 146 unchanged lines hidden (view full) --- 291 /* select timer0 and latch counter value */ 292 outb(TIMER_MODE, TIMER_SEL0); 293 low = inb(TIMER_CNTR0); 294 high = inb(TIMER_CNTR0); 295 enable_intr(); 296 return ((high << 8) | low); 297} 298 |
290#if defined(I586_CPU) || defined(I686_CPU) | |
291/* | 299/* |
292 * Figure out how fast the cyclecounter runs. This must be run with 293 * clock interrupts disabled, but with the timer/counter programmed 294 * and running. 295 */ 296void 297calibrate_cyclecounter(void) 298{ 299 /* 300 * Don't need volatile; should always use unsigned if 2's 301 * complement arithmetic is desired. 302 */ 303 unsigned long long count; 304 305#define howlong 131072UL 306 __asm __volatile(".byte 0x0f, 0x30" : : "A"(0LL), "c" (0x10)); 307 DELAY(howlong); 308 __asm __volatile(".byte 0xf,0x31" : "=A" (count)); 309 310 i586_ctr_rate = (count << I586_CTR_RATE_SHIFT) / howlong; 311#undef howlong 312} 313#endif 314 315/* | |
316 * Wait "n" microseconds. | 300 * Wait "n" microseconds. |
317 * Relies on timer 1 counting down from (TIMER_FREQ / hz) | 301 * Relies on timer 1 counting down from (timer_freq / hz) |
318 * Note: timer had better have been programmed before this is first used! 319 */ 320void 321DELAY(int n) 322{ 323 int prev_tick, tick, ticks_left, sec, usec; 324 325#ifdef DELAYDEBUG --- 15 unchanged lines hidden (view full) --- 341 * counted. Guess the initial overhead is 20 usec (on most systems it 342 * takes about 1.5 usec for each of the i/o's in getit(). The loop 343 * takes about 6 usec on a 486/33 and 13 usec on a 386/20. The 344 * multiplications and divisions to scale the count take a while). 345 */ 346 prev_tick = getit(); 347 n -= 20; 348 /* | 302 * Note: timer had better have been programmed before this is first used! 303 */ 304void 305DELAY(int n) 306{ 307 int prev_tick, tick, ticks_left, sec, usec; 308 309#ifdef DELAYDEBUG --- 15 unchanged lines hidden (view full) --- 325 * counted. Guess the initial overhead is 20 usec (on most systems it 326 * takes about 1.5 usec for each of the i/o's in getit(). The loop 327 * takes about 6 usec on a 486/33 and 13 usec on a 386/20. The 328 * multiplications and divisions to scale the count take a while). 329 */ 330 prev_tick = getit(); 331 n -= 20; 332 /* |
349 * Calculate (n * (TIMER_FREQ / 1e6)) without using floating point | 333 * Calculate (n * (timer_freq / 1e6)) without using floating point |
350 * and without any avoidable overflows. 351 */ 352 sec = n / 1000000; 353 usec = n - sec * 1000000; | 334 * and without any avoidable overflows. 335 */ 336 sec = n / 1000000; 337 usec = n - sec * 1000000; |
354 ticks_left = sec * TIMER_FREQ 355 + usec * (TIMER_FREQ / 1000000) 356 + usec * ((TIMER_FREQ % 1000000) / 1000) / 1000 357 + usec * (TIMER_FREQ % 1000) / 1000000; | 338 ticks_left = sec * timer_freq 339 + usec * (timer_freq / 1000000) 340 + usec * ((timer_freq % 1000000) / 1000) / 1000 341 + usec * (timer_freq % 1000) / 1000000; 342 if (n < 0) 343 ticks_left = 0; /* XXX timer_freq is unsigned */ |
358 359 while (ticks_left > 0) { 360 tick = getit(); 361#ifdef DELAYDEBUG 362 ++getit_calls; 363#endif 364 if (tick > prev_tick) 365 ticks_left -= prev_tick - (tick - timer0_max_count); --- 59 unchanged lines hidden (view full) --- 425} 426 427static __inline int 428readrtc(int port) 429{ 430 return(bcd2bin(rtcin(port))); 431} 432 | 344 345 while (ticks_left > 0) { 346 tick = getit(); 347#ifdef DELAYDEBUG 348 ++getit_calls; 349#endif 350 if (tick > prev_tick) 351 ticks_left -= prev_tick - (tick - timer0_max_count); --- 59 unchanged lines hidden (view full) --- 411} 412 413static __inline int 414readrtc(int port) 415{ 416 return(bcd2bin(rtcin(port))); 417} 418 |
419static u_int 420calibrate_clocks(void) 421{ 422 u_int count, prev_count, tot_count; 423 int sec, start_sec, timeout; 424 425 printf("Calibrating clock(s) relative to mc146818A clock ... "); 426 if (!(rtcin(RTC_STATUSD) & RTCSD_PWR)) 427 goto fail; 428 timeout = 100000000; 429 430 /* Read the mc146818A seconds counter. */ 431 for (;;) { 432 if (!(rtcin(RTC_STATUSA) & RTCSA_TUP)) { 433 sec = rtcin(RTC_SEC); 434 break; 435 } 436 if (--timeout == 0) 437 goto fail; 438 } 439 440 /* Wait for the mC146818A seconds counter to change. */ 441 start_sec = sec; 442 for (;;) { 443 if (!(rtcin(RTC_STATUSA) & RTCSA_TUP)) { 444 sec = rtcin(RTC_SEC); 445 if (sec != start_sec) 446 break; 447 } 448 if (--timeout == 0) 449 goto fail; 450 } 451 452 /* Start keeping track of the i8254 counter. */ 453 prev_count = getit(); 454 if (prev_count == 0 || prev_count > timer0_max_count) 455 goto fail; 456 tot_count = 0; 457 458#if defined(I586_CPU) || defined(I686_CPU) 459 if (cpu_class == CPUCLASS_586 || cpu_class == CPUCLASS_686) 460 wrmsr(0x10, 0LL); /* XXX 0x10 is the MSR for the TSC */ 461#endif 462 463 /* 464 * Wait for the mc146818A seconds counter to change. Read the i8254 465 * counter for each iteration since this is convenient and only 466 * costs a few usec of inaccuracy. The timing of the final reads 467 * of the counters almost matches the timing of the initial reads, 468 * so the main cause of inaccuracy is the varying latency from 469 * inside getit() or rtcin(RTC_STATUSA) to the beginning of the 470 * rtcin(RTC_SEC) that returns a changed seconds count. The 471 * maximum inaccuracy from this cause is < 10 usec on 486's. 472 */ 473 start_sec = sec; 474 for (;;) { 475 if (!(rtcin(RTC_STATUSA) & RTCSA_TUP)) 476 sec = rtcin(RTC_SEC); 477 count = getit(); 478 if (count == 0 || count > timer0_max_count) 479 goto fail; 480 if (count > prev_count) 481 tot_count += prev_count - (count - timer0_max_count); 482 else 483 tot_count += prev_count - count; 484 prev_count = count; 485 if (sec != start_sec) 486 break; 487 if (--timeout == 0) 488 goto fail; 489 } 490 491#if defined(I586_CPU) || defined(I686_CPU) 492 /* 493 * Read the cpu cycle counter. The timing considerations are 494 * similar to those for the i8254 clock. 495 */ 496 if (cpu_class == CPUCLASS_586 || cpu_class == CPUCLASS_686) { 497 unsigned long long i586_count; 498 499 i586_count = rdtsc(); 500 i586_ctr_freq = i586_count; 501 i586_ctr_rate = (i586_count << I586_CTR_RATE_SHIFT) / 1000000; 502 printf("i586 clock: %u Hz, ", i586_ctr_freq); 503 } 504#endif 505 506 printf("i8254 clock: %u Hz\n", tot_count); 507 return (tot_count); 508 509fail: 510 printf("failed, using default i8254 clock of %u Hz\n", timer_freq); 511 return (timer_freq); 512} 513 514static void 515set_timer_freq(u_int freq, int intr_freq) 516{ 517 u_long ef; 518 519 ef = read_eflags(); 520 timer_freq = freq; 521 timer0_max_count = hardclock_max_count = TIMER_DIV(intr_freq); 522 timer0_overflow_threshold = timer0_max_count - TIMER0_LATCH_COUNT; 523 outb(TIMER_MODE, TIMER_SEL0 | TIMER_RATEGEN | TIMER_16BIT); 524 outb(TIMER_CNTR0, timer0_max_count & 0xff); 525 outb(TIMER_CNTR0, timer0_max_count >> 8); 526 write_eflags(ef); 527} 528 |
|
433/* 434 * Initialize 8253 timer 0 early so that it can be used in DELAY(). 435 * XXX initialization of other timers is unintentionally left blank. 436 */ 437void 438startrtclock() 439{ | 529/* 530 * Initialize 8253 timer 0 early so that it can be used in DELAY(). 531 * XXX initialization of other timers is unintentionally left blank. 532 */ 533void 534startrtclock() 535{ |
440 timer0_max_count = hardclock_max_count = TIMER_DIV(hz); 441 timer0_overflow_threshold = timer0_max_count - TIMER0_LATCH_COUNT; 442 outb(TIMER_MODE, TIMER_SEL0 | TIMER_RATEGEN | TIMER_16BIT); 443 outb(TIMER_CNTR0, timer0_max_count & 0xff); 444 outb(TIMER_CNTR0, timer0_max_count >> 8); | 536 u_int delta, freq; 537 538 writertc(RTC_STATUSA, rtc_statusa); 539 writertc(RTC_STATUSB, RTCSB_24HR); 540 541 /* 542 * Temporarily calibrate with a high intr_freq to get a low 543 * timer0_max_count to help detect bogus i8254 counts. 544 */ 545 set_timer_freq(timer_freq, 20000); 546 freq = calibrate_clocks(); 547#ifdef CLK_CALIBRATION_LOOP 548 if (bootverbose) { 549 printf( 550 "Press a key on the console to abort clock calibration\n"); 551 while (!cncheckc()) 552 calibrate_clocks(); 553 } 554#endif 555 556 /* 557 * Use the calibrated i8254 frequency if it seems reasonable. 558 * Otherwise use the default, and don't use the calibrated i586 559 * frequency. 560 */ 561 delta = freq > timer_freq ? freq - timer_freq : timer_freq - freq; 562 if (delta < timer_freq / 100) { 563#ifndef CLK_USE_I8254_CALIBRATION 564 printf( 565"CLK_USE_I8254_CALIBRATION not specified - using default frequency\n"); 566 freq = timer_freq; 567#endif 568 timer_freq = freq; 569 } else { 570 printf("%d Hz differs from default of %d Hz by more than 1%%\n", 571 freq, timer_freq); 572#if defined(I586_CPU) || defined(I686_CPU) 573 i586_ctr_freq = 0; 574 i586_ctr_rate = 0; 575#endif 576 } 577 578 set_timer_freq(timer_freq, hz); 579 580#if defined(I586_CPU) || defined(I686_CPU) 581#ifndef CLK_USE_I586_CALIBRATION 582 if (i586_ctr_rate != 0) { 583 printf( 584"CLK_USE_I586_CALIBRATION not specified - using old calibration method\n"); 585 i586_ctr_freq = 0; 586 i586_ctr_rate = 0; 587 } 588#endif 589 if (i586_ctr_rate == 0 && 590 (cpu_class == CPUCLASS_586 || cpu_class == CPUCLASS_686)) { 591 /* 592 * Calibration of the i586 clock relative to the mc146818A 593 * clock failed. Do a less accurate calibration relative 594 * to the i8254 clock. 595 */ 596 unsigned long long i586_count; 597 598 wrmsr(0x10, 0LL); /* XXX */ 599 DELAY(1000000); 600 i586_count = rdtsc(); 601 i586_ctr_rate = (i586_count << I586_CTR_RATE_SHIFT) / 1000000; 602 printf("i586 clock: %u Hz\n", i586_ctr_freq); 603 } 604#endif |
445} 446 447/* 448 * Initialize the time of day register, based on the time base which is, e.g. 449 * from a filesystem. 450 */ 451void 452inittodr(time_t base) --- 139 unchanged lines hidden (view full) --- 592 /* XXX */ (inthand2_t *)clkintr, &clk_imask, 593 /* unit */ 0); 594 INTREN(IRQ0); 595#if defined(I586_CPU) || defined(I686_CPU) 596 /* 597 * Finish setting up anti-jitter measures. 598 */ 599 if (i586_ctr_rate) { | 605} 606 607/* 608 * Initialize the time of day register, based on the time base which is, e.g. 609 * from a filesystem. 610 */ 611void 612inittodr(time_t base) --- 139 unchanged lines hidden (view full) --- 752 /* XXX */ (inthand2_t *)clkintr, &clk_imask, 753 /* unit */ 0); 754 INTREN(IRQ0); 755#if defined(I586_CPU) || defined(I686_CPU) 756 /* 757 * Finish setting up anti-jitter measures. 758 */ 759 if (i586_ctr_rate) { |
600 I586_CYCLECTR(i586_last_tick); | 760 i586_last_tick = rdtsc(); |
601 i586_ctr_bias = i586_last_tick; 602 } 603#endif 604 605 /* Initialize RTC. */ 606 writertc(RTC_STATUSA, rtc_statusa); 607 writertc(RTC_STATUSB, RTCSB_24HR); 608 --- 14 unchanged lines hidden (view full) --- 623setstatclockrate(int newhz) 624{ 625 if (newhz == RTC_PROFRATE) 626 rtc_statusa = RTCSA_DIVIDER | RTCSA_PROF; 627 else 628 rtc_statusa = RTCSA_DIVIDER | RTCSA_NOPROF; 629 writertc(RTC_STATUSA, rtc_statusa); 630} | 761 i586_ctr_bias = i586_last_tick; 762 } 763#endif 764 765 /* Initialize RTC. */ 766 writertc(RTC_STATUSA, rtc_statusa); 767 writertc(RTC_STATUSB, RTCSB_24HR); 768 --- 14 unchanged lines hidden (view full) --- 783setstatclockrate(int newhz) 784{ 785 if (newhz == RTC_PROFRATE) 786 rtc_statusa = RTCSA_DIVIDER | RTCSA_PROF; 787 else 788 rtc_statusa = RTCSA_DIVIDER | RTCSA_NOPROF; 789 writertc(RTC_STATUSA, rtc_statusa); 790} |
791 792static int 793sysctl_machdep_i8254_freq SYSCTL_HANDLER_ARGS 794{ 795 int error; 796 u_int freq; 797 798 /* 799 * Use `i8254' instead of `timer' in external names because `timer' 800 * is is too generic. Should use it everywhere. 801 */ 802 freq = timer_freq; 803 error = sysctl_handle_opaque(oidp, &freq, sizeof freq, req); 804 if (error == 0 && freq != timer_freq) { 805 if (timer0_state != 0) 806 return (EBUSY); /* too much trouble to handle */ 807 set_timer_freq(freq, hz); 808 } 809 return (error); 810} 811 812SYSCTL_PROC(_machdep, OID_AUTO, i8254_freq, CTLTYPE_INT | CTLFLAG_RW, 813 0, sizeof(u_int), sysctl_machdep_i8254_freq, "I", ""); 814 815#if defined(I586_CPU) || defined(I686_CPU) 816static int 817sysctl_machdep_i586_freq SYSCTL_HANDLER_ARGS 818{ 819 int error; 820 u_int freq; 821 822 if (i586_ctr_rate == 0) 823 return (EOPNOTSUPP); 824 freq = i586_ctr_freq; 825 error = sysctl_handle_opaque(oidp, &freq, sizeof freq, req); 826 if (error == 0 && freq != i586_ctr_freq) { 827 i586_ctr_freq = freq; 828 i586_ctr_rate = ((unsigned long long)freq << 829 I586_CTR_RATE_SHIFT) / 1000000; 830 } 831 return (error); 832} 833 834SYSCTL_PROC(_machdep, OID_AUTO, i586_freq, CTLTYPE_INT | CTLFLAG_RW, 835 0, sizeof(u_int), sysctl_machdep_i586_freq, "I", ""); 836#endif /* defined(I586_CPU) || defined(I686_CPU) */ |
|