xref: /freebsd/sys/i386/include/clock.h (revision e30f001135d8f835c2d750ae17c91268fa9d0bb2)
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  */
29 extern int	adjkerntz;
30 extern int	disable_rtc_set;
31 #if defined(I586_CPU) || defined(I686_CPU)
32 extern u_int	i586_ctr_bias;
33 extern u_int	i586_ctr_comultiplier;
34 extern u_int	i586_ctr_freq;
35 extern u_int	i586_ctr_multiplier;
36 #endif
37 extern int	statclock_disable;
38 extern u_int	timer_freq;
39 extern int	timer0_max_count;
40 extern u_int	timer0_overflow_threshold;
41 extern u_int	timer0_prescaler_count;
42 extern int	wall_cmos_clock;
43 
44 /*
45  * Driver to clock driver interface.
46  */
47 struct clockframe;
48 
49 void	DELAY __P((int usec));
50 int	acquire_timer0 __P((int rate,
51 			    void (*function)(struct clockframe *frame)));
52 int	acquire_timer2 __P((int mode));
53 int	release_timer0 __P((void));
54 int	release_timer2 __P((void));
55 #ifndef PC98
56 int	rtcin __P((int val));
57 #else
58 int	acquire_timer1 __P((int mode));
59 int	release_timer1 __P((void));
60 void	rtc_serialcombit __P((int i));
61 void	rtc_serialcom __P((int i));
62 void	rtc_outb __P((int val));
63 #endif
64 int	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 
75 static __inline u_int
76 clock_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  */
99 static __inline void
100 cpu_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