freebsd-dev/sys/i386/include/clock.h
Bruce Evans 2dafbfcbab Added calibration the i8254 and the i586 clocks agains the RTC at boot
time.  The results are currently ignored unless certain temporary options
are used.

Added sysctls to support reading and writing the clock frequency variables
(not the frequencies themselves).  Writing is supposed to atomically
adjust all related variables.

machdep.c:
Fixed spelling of a function name in a comment so that I can log this
message which should have been with the previous commit.

Initialize `cpu_class' earlier so that it can be used in startrtclock()
instead of in calibrate_cyclecounter() (which no longer exists).

Removed range checking of `cpu'.  It is always initialized to CPU_XXX
so it is less likely to be out of bounds than most variables.

clock.h:
Removed I586_CYCLECTR().  Use rdtsc() instead.

clock.c:
TIMER_FREQ is now a variable timer_freq that defaults to the old value of
TIMER_FREQ.  #define'ing TIMER_FREQ should still work and may be the best
way of setting the frequency.

Calibration involves counting cycles while watching the RTC for one second.
This gives values correct to within (a few ppm) + (the innaccuracy of the
RTC) on my systems.
1996-05-01 08:39:02 +00:00

102 lines
2.5 KiB
C

/*
* Kernel interface to machine-dependent clock driver.
* Garrett Wollman, September 1994.
* This file is in the public domain.
*
* $Id: clock.h,v 1.12 1996/04/22 19:40:27 nate Exp $
*/
#ifndef _MACHINE_CLOCK_H_
#define _MACHINE_CLOCK_H_
#if defined(I586_CPU) || defined(I686_CPU)
/*
* When we update the clock, we also update this bias value which is
* automatically subtracted in microtime(). We assume that CPU_THISTICKLEN()
* has been called at some point in the past, so that an appropriate value is
* set up in i586_last_tick. (This works even if we are not being called
* from hardclock because hardclock will have run before and will made the
* call.)
*/
#define CPU_CLOCKUPDATE(otime, ntime) \
do { \
if(i586_ctr_rate) { \
disable_intr(); \
i586_ctr_bias = i586_last_tick; \
*(otime) = *(ntime); \
enable_intr(); \
} else { \
*(otime) = *(ntime); \
} \
} while(0)
#define CPU_THISTICKLEN(dflt) cpu_thisticklen(dflt)
#else
#define CPU_CLOCKUPDATE(otime, ntime) \
(*(otime) = *(ntime))
#define CPU_THISTICKLEN(dflt) dflt
#endif
#define I586_CTR_RATE_SHIFT 8
#if defined(KERNEL) && !defined(LOCORE)
#include <sys/cdefs.h>
#include <machine/frame.h>
/*
* i386 to clock driver interface.
* XXX almost all of it is misplaced. i586 stuff is done in isa/clock.c
* and isa stuff is done in i386/microtime.s and i386/support.s.
*/
extern int adjkerntz;
extern int disable_rtc_set;
extern int statclock_disable;
extern int wall_cmos_clock;
#if defined(I586_CPU) || defined(I686_CPU)
extern unsigned i586_ctr_freq;
extern unsigned i586_ctr_rate; /* fixed point */
extern long long i586_last_tick;
extern long long i586_ctr_bias;
extern unsigned long i586_avg_tick;
#endif
extern int timer0_max_count;
extern u_int timer0_overflow_threshold;
extern u_int timer0_prescaler_count;
#if defined(I586_CPU) || defined(I686_CPU)
static __inline u_long
cpu_thisticklen(u_long dflt)
{
long long old;
long len;
if (i586_ctr_rate) {
old = i586_last_tick;
i586_last_tick = rdtsc();
len = ((i586_last_tick - old) << I586_CTR_RATE_SHIFT)
/ i586_ctr_rate;
i586_avg_tick = i586_avg_tick * 15 / 16 + len / 16;
}
return dflt;
}
#endif
/*
* Driver to clock driver interface.
*/
void DELAY __P((int usec));
int acquire_timer0 __P((int rate,
void (*function)(struct clockframe *frame)));
int acquire_timer2 __P((int mode));
int release_timer0 __P((void));
int release_timer2 __P((void));
int rtcin __P((int val));
int sysbeep __P((int pitch, int period));
#endif /* KERNEL && !LOCORE */
#endif /* !_MACHINE_CLOCK_H_ */