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