1 /*
2 * Kernel interface to machine-dependent clock driver.
3 * Garrett Wollman, September 1994.
4 * This file is in the public domain.
5 *
6 * $FreeBSD: src/sys/i386/include/clock.h,v 1.21.2.2 1999/09/05 08:11:41 peter 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 #endif
61 int sysbeep __P((int pitch, int period));
62
63 #ifdef CLOCK_HAIR
64
65 #ifdef PC98
66 #include <pc98/pc98/pc98.h> /* XXX */
67 #else
68 #include <i386/isa/isa.h> /* XXX */
69 #endif
70 #include <i386/isa/timerreg.h> /* XXX */
71
72 static __inline u_int
73 clock_latency(void)
74 {
75 u_char high, low;
76
77 outb(TIMER_MODE, TIMER_SEL0 | TIMER_LATCH);
78 low = inb(TIMER_CNTR0);
79 high = inb(TIMER_CNTR0);
80 return (timer0_prescaler_count + timer0_max_count
81 - ((high << 8) | low));
82 }
83
84 #if defined(I586_CPU) || defined(I686_CPU)
85 /*
86 * When we update `time', on i586's we also update `i586_ctr_bias'
87 * atomically. `i586_ctr_bias' is the best available approximation to
88 * the value of the i586 counter (mod 2^32) at the time of the i8254
89 * counter transition that caused the clock interrupt that caused the
90 * update. clock_latency() gives the time between the transition and
91 * the update to within a few usec provided another such transition
92 * hasn't occurred. We don't bother checking for counter overflow as
93 * in microtime(), since if it occurs then we're close to losing clock
94 * interrupts.
95 */
96 static __inline void
97 cpu_clockupdate(volatile struct timeval *otime, struct timeval *ntime)
98 {
99 if (i586_ctr_freq != 0) {
100 u_int i586_count; /* truncated */
101 u_int i8254_count;
102
103 disable_intr();
104 i8254_count = clock_latency();
105 i586_count = rdtsc();
106 i586_ctr_bias = i586_count
107 - (u_int)
108 (((unsigned long long)i586_ctr_comultiplier
109 * i8254_count)
110 >> I586_CTR_COMULTIPLIER_SHIFT);
111 *otime = *ntime;
112 enable_intr();
113 } else
114 *otime = *ntime;
115 }
116 #endif /* I586_CPU || I686_CPU */
117
118 #endif /* CLOCK_HAIR */
119
120 #endif /* KERNEL */
121
122 #endif /* !_MACHINE_CLOCK_H_ */
Cache object: 8b09cb08d90f5c08c35f1e92df771503
|