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