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.29 1997/12/28 13:36:06 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 */ 25 extern int adjkerntz; 26 extern int disable_rtc_set; 27 extern int statclock_disable; 28 extern u_int timer_freq; 29 extern int timer0_max_count; 30 extern u_int timer0_overflow_threshold; 31 extern u_int timer0_prescaler_count; 32 extern u_int tsc_bias; 33 extern u_int tsc_comultiplier; 34 extern u_int tsc_freq; 35 extern u_int tsc_multiplier; 36 extern int wall_cmos_clock; 37 38 /* 39 * Driver to clock driver interface. 40 */ 41 struct clockframe; 42 43 void DELAY __P((int usec)); 44 int acquire_timer0 __P((int rate, 45 void (*function)(struct clockframe *frame))); 46 int acquire_timer2 __P((int mode)); 47 int release_timer0 __P((void)); 48 int release_timer2 __P((void)); 49 #ifndef PC98 50 int rtcin __P((int val)); 51 #else 52 int acquire_timer1 __P((int mode)); 53 int release_timer1 __P((void)); 54 #endif 55 int 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 66 static __inline u_int 67 clock_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', on we also update `tsc_bias' 80 * atomically. `tsc_bias' is the best available approximation to 81 * 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 */ 89 static __inline void 90 cpu_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