xref: /freebsd/sys/amd64/include/clock.h (revision 835bd1ce62ebd0b706c83528cc57a9f4a005d617)
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.19 1996/10/17 17:31:25 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 #include <i386/isa/isa.h>		/* XXX */
69 #include <i386/isa/timerreg.h>		/* XXX */
70 
71 static __inline u_int
72 clock_latency(void)
73 {
74 	u_char high, low;
75 
76 	outb(TIMER_MODE, TIMER_SEL0 | TIMER_LATCH);
77 	low = inb(TIMER_CNTR0);
78 	high = inb(TIMER_CNTR0);
79 	return (timer0_prescaler_count + timer0_max_count
80 		- ((high << 8) | low));
81 }
82 
83 #if defined(I586_CPU) || defined(I686_CPU)
84 /*
85  * When we update `time', on i586's we also update `i586_ctr_bias'
86  * atomically.  `i586_ctr_bias' is the best available approximation to
87  * the value of the i586 counter (mod 2^32) at the time of the i8254
88  * counter transition that caused the clock interrupt that caused the
89  * update.  clock_latency() gives the time between the transition and
90  * the update to within a few usec provided another such transition
91  * hasn't occurred.  We don't bother checking for counter overflow as
92  * in microtime(), since if it occurs then we're close to losing clock
93  * interrupts.
94  */
95 static __inline void
96 cpu_clockupdate(volatile struct timeval *otime, struct timeval *ntime)
97 {
98 	if (i586_ctr_freq != 0) {
99 		u_int i586_count;	/* truncated */
100 		u_int i8254_count;
101 
102 		disable_intr();
103 		i8254_count = clock_latency();
104 		i586_count = rdtsc();
105 		i586_ctr_bias = i586_count
106 				- (u_int)
107 				  (((unsigned long long)i586_ctr_comultiplier
108 				    * i8254_count)
109 				   >> I586_CTR_COMULTIPLIER_SHIFT);
110 		*otime = *ntime;
111 		enable_intr();
112 	} else
113 		*otime = *ntime;
114 }
115 #endif /* I586_CPU || I686_CPU */
116 
117 #endif /* CLOCK_HAIR */
118 
119 #endif /* KERNEL */
120 
121 #endif /* !_MACHINE_CLOCK_H_ */
122