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