clock.h revision 32054
1177997Skib/*
2177997Skib * Kernel interface to machine-dependent clock driver.
3177997Skib * Garrett Wollman, September 1994.
4177997Skib * This file is in the public domain.
5177997Skib *
6177997Skib *	$Id: clock.h,v 1.29 1997/12/28 13:36:06 phk Exp $
7177997Skib */
8177997Skib
9177997Skib#ifndef _MACHINE_CLOCK_H_
10177997Skib#define	_MACHINE_CLOCK_H_
11177997Skib
12177997Skib#define CPU_CLOCKUPDATE(otime, ntime)	cpu_clockupdate((otime), (ntime))
13177997Skib
14177997Skib#define CPU_THISTICKLEN(dflt) dflt
15177997Skib
16177997Skib#define	TSC_COMULTIPLIER_SHIFT	20
17177997Skib#define	TSC_MULTIPLIER_SHIFT	32
18177997Skib
19177997Skib#ifdef KERNEL
20177997Skib/*
21177997Skib * i386 to clock driver interface.
22177997Skib * XXX almost all of it is misplaced.  i586 stuff is done in isa/clock.c
23177997Skib * and isa stuff is done in i386/microtime.s and i386/support.s.
24177997Skib */
25177997Skibextern int	adjkerntz;
26177997Skibextern int	disable_rtc_set;
27177997Skibextern int	statclock_disable;
28177997Skibextern u_int	timer_freq;
29177997Skibextern int	timer0_max_count;
30177997Skibextern u_int	timer0_overflow_threshold;
31177997Skibextern u_int	timer0_prescaler_count;
32177997Skibextern u_int	tsc_bias;
33177997Skibextern u_int	tsc_comultiplier;
34227693Sedextern u_int	tsc_freq;
35177997Skibextern u_int	tsc_multiplier;
36227693Sedextern int	wall_cmos_clock;
37177997Skib
38246085Sjhb/*
39246085Sjhb * Driver to clock driver interface.
40246085Sjhb */
41246085Sjhbstruct clockframe;
42246085Sjhb
43246085Sjhbvoid	DELAY __P((int usec));
44246085Sjhbint	acquire_timer0 __P((int rate,
45246085Sjhb			    void (*function)(struct clockframe *frame)));
46246085Sjhbint	acquire_timer2 __P((int mode));
47246085Sjhbint	release_timer0 __P((void));
48246085Sjhbint	release_timer2 __P((void));
49246085Sjhb#ifndef PC98
50246085Sjhbint	rtcin __P((int val));
51246085Sjhb#else
52246085Sjhbint	acquire_timer1 __P((int mode));
53246085Sjhbint	release_timer1 __P((void));
54246085Sjhb#endif
55246085Sjhbint	sysbeep __P((int pitch, int period));
56246085Sjhb
57283437Sdchagin#ifdef CLOCK_HAIR
58283437Sdchagin
59283437Sdchagin#ifdef PC98
60283437Sdchagin#include <pc98/pc98/pc98.h>		/* XXX */
61283437Sdchagin#else
62283437Sdchagin#include <i386/isa/isa.h>		/* XXX */
63283437Sdchagin#endif
64283437Sdchagin#include <i386/isa/timerreg.h>		/* XXX */
65283437Sdchagin
66283437Sdchaginstatic __inline u_int
67283437Sdchaginclock_latency(void)
68283437Sdchagin{
69283437Sdchagin	u_char high, low;
70283437Sdchagin
71283437Sdchagin	outb(TIMER_MODE, TIMER_SEL0 | TIMER_LATCH);
72283437Sdchagin	low = inb(TIMER_CNTR0);
73283437Sdchagin	high = inb(TIMER_CNTR0);
74283437Sdchagin	return (timer0_prescaler_count + timer0_max_count
75283437Sdchagin		- ((high << 8) | low));
76283437Sdchagin}
77283437Sdchagin
78283437Sdchagin/*
79283437Sdchagin * When we update `time', on we also update `tsc_bias'
80283437Sdchagin * atomically.  `tsc_bias' is the best available approximation to
81283437Sdchagin * the value of the TSC (mod 2^32) at the time of the i8254
82283437Sdchagin * counter transition that caused the clock interrupt that caused the
83283437Sdchagin * update.  clock_latency() gives the time between the transition and
84283437Sdchagin * the update to within a few usec provided another such transition
85283437Sdchagin * hasn't occurred.  We don't bother checking for counter overflow as
86283437Sdchagin * in microtime(), since if it occurs then we're close to losing clock
87283437Sdchagin * interrupts.
88283437Sdchagin */
89283437Sdchaginstatic __inline void
90283437Sdchagincpu_clockupdate(volatile struct timeval *otime, struct timeval *ntime)
91283437Sdchagin{
92283437Sdchagin	if (tsc_freq != 0) {
93283437Sdchagin		u_int tsc_count;	/* truncated */
94283437Sdchagin		u_int i8254_count;
95283437Sdchagin
96283437Sdchagin		disable_intr();
97283437Sdchagin		i8254_count = clock_latency();
98283437Sdchagin		tsc_count = rdtsc();
99283437Sdchagin		tsc_bias = tsc_count
100283437Sdchagin				- (u_int)
101177997Skib				  (((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