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