clock.h revision 33007
1/* 2 * Kernel interface to machine-dependent clock driver. 3 * Garrett Wollman, September 1994. 4 * This file is in the public domain. 5 * 6 * $Id: clock.h,v 1.30 1997/12/28 17:33:08 phk Exp $ 7 */ 8 9#ifndef _MACHINE_CLOCK_H_ 10#define _MACHINE_CLOCK_H_ 11 12#define CPU_CLOCKUPDATE(otime, ntime) cpu_clockupdate((otime), (ntime)) 13 14#define CPU_THISTICKLEN(dflt) dflt 15 16#define TSC_COMULTIPLIER_SHIFT 20 17#define TSC_MULTIPLIER_SHIFT 32 18 19#ifdef KERNEL 20/* 21 * i386 to clock driver interface. 22 * XXX almost all of it is misplaced. i586 stuff is done in isa/clock.c 23 * and isa stuff is done in i386/microtime.s and i386/support.s. 24 */ 25extern int adjkerntz; 26extern int disable_rtc_set; 27extern int statclock_disable; 28extern u_int timer_freq; 29extern int timer0_max_count; 30extern u_int timer0_overflow_threshold; 31extern u_int timer0_prescaler_count; 32extern u_int tsc_bias; 33extern u_int tsc_comultiplier; 34extern u_int tsc_freq; 35extern u_int tsc_multiplier; 36extern int wall_cmos_clock; 37 38/* 39 * Driver to clock driver interface. 40 */ 41struct clockframe; 42 43void DELAY __P((int usec)); 44int acquire_timer0 __P((int rate, 45 void (*function)(struct clockframe *frame))); 46int acquire_timer2 __P((int mode)); 47int release_timer0 __P((void)); 48int release_timer2 __P((void)); 49#ifndef PC98 50int rtcin __P((int val)); 51#else 52int acquire_timer1 __P((int mode)); 53int release_timer1 __P((void)); 54#endif 55int sysbeep __P((int pitch, int period)); 56 57#ifdef CLOCK_HAIR 58 59#ifdef PC98 60#include <pc98/pc98/pc98.h> /* XXX */ 61#else 62#include <i386/isa/isa.h> /* XXX */ 63#endif 64#include <i386/isa/timerreg.h> /* XXX */ 65 66static __inline u_int 67clock_latency(void) 68{ 69 u_char high, low; 70 71 outb(TIMER_MODE, TIMER_SEL0 | TIMER_LATCH); 72 low = inb(TIMER_CNTR0); 73 high = inb(TIMER_CNTR0); 74 return (timer0_prescaler_count + timer0_max_count 75 - ((high << 8) | low)); 76} 77 78/* 79 * When we update `time', we also update `tsc_bias' atomically (if we 80 * are using the TSC). `tsc_bias' is the best available approximation 81 * to the value of the TSC (mod 2^32) at the time of the i8254 82 * counter transition that caused the clock interrupt that caused the 83 * update. clock_latency() gives the time between the transition and 84 * the update to within a few usec provided another such transition 85 * hasn't occurred. We don't bother checking for counter overflow as 86 * in microtime(), since if it occurs then we're close to losing clock 87 * interrupts. 88 */ 89static __inline void 90cpu_clockupdate(volatile struct timeval *otime, struct timeval *ntime) 91{ 92 if (tsc_freq != 0) { 93 u_int tsc_count; /* truncated */ 94 u_int i8254_count; 95 96 disable_intr(); 97 i8254_count = clock_latency(); 98 tsc_count = rdtsc(); 99 tsc_bias = tsc_count 100 - (u_int) 101 (((unsigned long long)tsc_comultiplier 102 * i8254_count) 103 >> TSC_COMULTIPLIER_SHIFT); 104 *otime = *ntime; 105 enable_intr(); 106 } else 107 *otime = *ntime; 108} 109 110#endif /* CLOCK_HAIR */ 111 112#endif /* KERNEL */ 113 114#endif /* !_MACHINE_CLOCK_H_ */ 115