clock.c revision 1.14 1 1.14 matt /* $NetBSD: clock.c,v 1.14 2007/03/08 20:48:39 matt Exp $ */
2 1.1 thorpej
3 1.1 thorpej /*
4 1.1 thorpej * Copyright 1997
5 1.1 thorpej * Digital Equipment Corporation. All rights reserved.
6 1.1 thorpej *
7 1.1 thorpej * This software is furnished under license and may be used and
8 1.1 thorpej * copied only in accordance with the following terms and conditions.
9 1.1 thorpej * Subject to these conditions, you may download, copy, install,
10 1.1 thorpej * use, modify and distribute this software in source and/or binary
11 1.1 thorpej * form. No title or ownership is transferred hereby.
12 1.1 thorpej *
13 1.1 thorpej * 1) Any source code used, modified or distributed must reproduce
14 1.1 thorpej * and retain this copyright notice and list of conditions as
15 1.1 thorpej * they appear in the source file.
16 1.1 thorpej *
17 1.1 thorpej * 2) No right is granted to use any trade name, trademark, or logo of
18 1.1 thorpej * Digital Equipment Corporation. Neither the "Digital Equipment
19 1.1 thorpej * Corporation" name nor any trademark or logo of Digital Equipment
20 1.1 thorpej * Corporation may be used to endorse or promote products derived
21 1.1 thorpej * from this software without the prior written permission of
22 1.1 thorpej * Digital Equipment Corporation.
23 1.1 thorpej *
24 1.1 thorpej * 3) This software is provided "AS-IS" and any express or implied
25 1.1 thorpej * warranties, including but not limited to, any implied warranties
26 1.1 thorpej * of merchantability, fitness for a particular purpose, or
27 1.1 thorpej * non-infringement are disclaimed. In no event shall DIGITAL be
28 1.1 thorpej * liable for any damages whatsoever, and in particular, DIGITAL
29 1.1 thorpej * shall not be liable for special, indirect, consequential, or
30 1.1 thorpej * incidental damages or damages for lost profits, loss of
31 1.1 thorpej * revenue or loss of use, whether such damages arise in contract,
32 1.1 thorpej * negligence, tort, under statute, in equity, at law or otherwise,
33 1.1 thorpej * even if advised of the possibility of such damage.
34 1.1 thorpej */
35 1.1 thorpej
36 1.1 thorpej /*-
37 1.1 thorpej * Copyright (c) 1990 The Regents of the University of California.
38 1.1 thorpej * All rights reserved.
39 1.1 thorpej *
40 1.1 thorpej * This code is derived from software contributed to Berkeley by
41 1.1 thorpej * William Jolitz and Don Ahn.
42 1.1 thorpej *
43 1.1 thorpej * Redistribution and use in source and binary forms, with or without
44 1.1 thorpej * modification, are permitted provided that the following conditions
45 1.1 thorpej * are met:
46 1.1 thorpej * 1. Redistributions of source code must retain the above copyright
47 1.1 thorpej * notice, this list of conditions and the following disclaimer.
48 1.1 thorpej * 2. Redistributions in binary form must reproduce the above copyright
49 1.1 thorpej * notice, this list of conditions and the following disclaimer in the
50 1.1 thorpej * documentation and/or other materials provided with the distribution.
51 1.6 agc * 3. Neither the name of the University nor the names of its contributors
52 1.6 agc * may be used to endorse or promote products derived from this software
53 1.6 agc * without specific prior written permission.
54 1.6 agc *
55 1.6 agc * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
56 1.6 agc * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
57 1.6 agc * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
58 1.6 agc * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
59 1.6 agc * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
60 1.6 agc * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
61 1.6 agc * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
62 1.6 agc * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
63 1.6 agc * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
64 1.6 agc * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
65 1.6 agc * SUCH DAMAGE.
66 1.6 agc *
67 1.6 agc * @(#)clock.c 7.2 (Berkeley) 5/12/91
68 1.6 agc */
69 1.6 agc /*-
70 1.6 agc * Copyright (c) 1993, 1994 Charles M. Hannum.
71 1.6 agc *
72 1.6 agc * This code is derived from software contributed to Berkeley by
73 1.6 agc * William Jolitz and Don Ahn.
74 1.6 agc *
75 1.6 agc * Redistribution and use in source and binary forms, with or without
76 1.6 agc * modification, are permitted provided that the following conditions
77 1.6 agc * are met:
78 1.6 agc * 1. Redistributions of source code must retain the above copyright
79 1.6 agc * notice, this list of conditions and the following disclaimer.
80 1.6 agc * 2. Redistributions in binary form must reproduce the above copyright
81 1.6 agc * notice, this list of conditions and the following disclaimer in the
82 1.6 agc * documentation and/or other materials provided with the distribution.
83 1.1 thorpej * 3. All advertising materials mentioning features or use of this software
84 1.1 thorpej * must display the following acknowledgement:
85 1.1 thorpej * This product includes software developed by the University of
86 1.1 thorpej * California, Berkeley and its contributors.
87 1.1 thorpej * 4. Neither the name of the University nor the names of its contributors
88 1.1 thorpej * may be used to endorse or promote products derived from this software
89 1.1 thorpej * without specific prior written permission.
90 1.1 thorpej *
91 1.1 thorpej * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
92 1.1 thorpej * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
93 1.1 thorpej * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
94 1.1 thorpej * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
95 1.1 thorpej * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
96 1.1 thorpej * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
97 1.1 thorpej * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
98 1.1 thorpej * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
99 1.1 thorpej * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
100 1.1 thorpej * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
101 1.1 thorpej * SUCH DAMAGE.
102 1.1 thorpej *
103 1.1 thorpej * @(#)clock.c 7.2 (Berkeley) 5/12/91
104 1.1 thorpej */
105 1.1 thorpej /*
106 1.1 thorpej * Mach Operating System
107 1.1 thorpej * Copyright (c) 1991,1990,1989 Carnegie Mellon University
108 1.1 thorpej * All Rights Reserved.
109 1.1 thorpej *
110 1.1 thorpej * Permission to use, copy, modify and distribute this software and its
111 1.1 thorpej * documentation is hereby granted, provided that both the copyright
112 1.1 thorpej * notice and this permission notice appear in all copies of the
113 1.1 thorpej * software, derivative works or modified versions, and any portions
114 1.1 thorpej * thereof, and that both notices appear in supporting documentation.
115 1.1 thorpej *
116 1.1 thorpej * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
117 1.1 thorpej * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
118 1.1 thorpej * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
119 1.1 thorpej *
120 1.1 thorpej * Carnegie Mellon requests users of this software to return to
121 1.1 thorpej *
122 1.1 thorpej * Software Distribution Coordinator or Software.Distribution (at) CS.CMU.EDU
123 1.1 thorpej * School of Computer Science
124 1.1 thorpej * Carnegie Mellon University
125 1.1 thorpej * Pittsburgh PA 15213-3890
126 1.1 thorpej *
127 1.1 thorpej * any improvements or extensions that they make and grant Carnegie Mellon
128 1.1 thorpej * the rights to redistribute these changes.
129 1.1 thorpej */
130 1.1 thorpej /*
131 1.1 thorpej Copyright 1988, 1989 by Intel Corporation, Santa Clara, California.
132 1.1 thorpej
133 1.1 thorpej All Rights Reserved
134 1.1 thorpej
135 1.1 thorpej Permission to use, copy, modify, and distribute this software and
136 1.1 thorpej its documentation for any purpose and without fee is hereby
137 1.1 thorpej granted, provided that the above copyright notice appears in all
138 1.1 thorpej copies and that both the copyright notice and this permission notice
139 1.1 thorpej appear in supporting documentation, and that the name of Intel
140 1.1 thorpej not be used in advertising or publicity pertaining to distribution
141 1.1 thorpej of the software without specific, written prior permission.
142 1.1 thorpej
143 1.1 thorpej INTEL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE
144 1.1 thorpej INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS,
145 1.1 thorpej IN NO EVENT SHALL INTEL BE LIABLE FOR ANY SPECIAL, INDIRECT, OR
146 1.1 thorpej CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
147 1.1 thorpej LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT,
148 1.1 thorpej NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
149 1.1 thorpej WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
150 1.1 thorpej */
151 1.1 thorpej
152 1.1 thorpej /*
153 1.1 thorpej * Primitive clock interrupt routines.
154 1.1 thorpej */
155 1.5 lukem
156 1.5 lukem #include <sys/cdefs.h>
157 1.14 matt __KERNEL_RCSID(0, "$NetBSD: clock.c,v 1.14 2007/03/08 20:48:39 matt Exp $");
158 1.5 lukem
159 1.1 thorpej #include <sys/param.h>
160 1.1 thorpej #include <sys/systm.h>
161 1.1 thorpej #include <sys/time.h>
162 1.13 gdamore #include <sys/timetc.h>
163 1.1 thorpej #include <sys/kernel.h>
164 1.1 thorpej #include <sys/device.h>
165 1.1 thorpej
166 1.1 thorpej #include <machine/cpu.h>
167 1.1 thorpej #include <machine/intr.h>
168 1.14 matt #include <machine/irqhandler.h>
169 1.1 thorpej #include <machine/pio.h>
170 1.1 thorpej #include <arm/cpufunc.h>
171 1.1 thorpej
172 1.1 thorpej #include <dev/isa/isareg.h>
173 1.1 thorpej #include <dev/isa/isavar.h>
174 1.1 thorpej #include <dev/ic/mc146818reg.h>
175 1.1 thorpej #include <dev/ic/i8253reg.h>
176 1.1 thorpej #include <shark/isa/nvram.h>
177 1.1 thorpej #include <shark/isa/spkrreg.h>
178 1.1 thorpej #include <shark/shark/hat.h>
179 1.1 thorpej
180 1.3 chs void sysbeepstop(void *);
181 1.3 chs void sysbeep(int, int);
182 1.3 chs void rtcinit(void);
183 1.1 thorpej int timer_hz_to_count(int);
184 1.1 thorpej
185 1.3 chs static void findcpuspeed(void);
186 1.1 thorpej static void delayloop(int);
187 1.3 chs static int clockintr(void *);
188 1.3 chs static int gettick(void);
189 1.13 gdamore static void tc_init_i8253(void);
190 1.3 chs
191 1.3 chs void startrtclock(void);
192 1.1 thorpej
193 1.12 gdamore inline unsigned mc146818_read(void *, unsigned);
194 1.12 gdamore inline void mc146818_write(void *, unsigned, unsigned);
195 1.1 thorpej
196 1.12 gdamore inline unsigned
197 1.12 gdamore mc146818_read(void *sc, unsigned reg)
198 1.1 thorpej {
199 1.1 thorpej
200 1.1 thorpej outb(IO_RTC, reg);
201 1.1 thorpej return (inb(IO_RTC+1));
202 1.1 thorpej }
203 1.1 thorpej
204 1.10 perry inline void
205 1.12 gdamore mc146818_write(void *sc, unsigned reg, unsigned datum)
206 1.1 thorpej {
207 1.1 thorpej
208 1.1 thorpej outb(IO_RTC, reg);
209 1.1 thorpej outb(IO_RTC+1, datum);
210 1.1 thorpej }
211 1.1 thorpej
212 1.1 thorpej unsigned int count1024usec; /* calibrated loop variable (1024 microseconds) */
213 1.1 thorpej
214 1.1 thorpej /* number of timer ticks in a Musec = 2^20 usecs */
215 1.1 thorpej #define TIMER_MUSECFREQ\
216 1.1 thorpej (((((((TIMER_FREQ) * 1024) + 999) / 1000) * 1024) + 999) / 1000)
217 1.1 thorpej #define TIMER_MUSECDIV(x) ((TIMER_MUSECFREQ+(x)/2)/(x))
218 1.1 thorpej
219 1.1 thorpej /*
220 1.1 thorpej * microtime() makes use of the following globals.
221 1.1 thorpej * timer_msb_table[] and timer_lsb_table[] are used to compute the
222 1.1 thorpej * microsecond increment.
223 1.1 thorpej *
224 1.1 thorpej * time.tv_usec += isa_timer_msb_table[cnt_msb] + isa_timer_lsb_table[cnt_lsb];
225 1.1 thorpej */
226 1.1 thorpej
227 1.1 thorpej u_short isa_timer_lsb_table[256]; /* timer->usec conversion for LSB */
228 1.1 thorpej
229 1.1 thorpej /* 64 bit counts from timer 0 */
230 1.1 thorpej struct count64 {
231 1.12 gdamore unsigned lo; /* low 32 bits */
232 1.12 gdamore unsigned hi; /* high 32 bits */
233 1.1 thorpej };
234 1.1 thorpej
235 1.1 thorpej #define TIMER0_ROLLOVER 0xFFFF /* maximum rollover for 8254 counter */
236 1.1 thorpej
237 1.1 thorpej struct count64 timer0count;
238 1.1 thorpej struct count64 timer0_at_last_clockintr;
239 1.1 thorpej unsigned timer0last;
240 1.1 thorpej
241 1.1 thorpej /*#define TESTHAT*/
242 1.1 thorpej #ifdef TESTHAT
243 1.1 thorpej #define HATSTACKSIZE 1024
244 1.1 thorpej #define HATHZ 50000
245 1.1 thorpej #define HATHZ2 10000
246 1.1 thorpej unsigned char hatStack[HATSTACKSIZE];
247 1.1 thorpej
248 1.1 thorpej unsigned testHatOn = 0;
249 1.1 thorpej unsigned nHats = 0;
250 1.1 thorpej unsigned nHatWedges = 0;
251 1.1 thorpej unsigned fiqReason = 0;
252 1.1 thorpej unsigned hatCount = 0;
253 1.1 thorpej unsigned hatCount2 = 0;
254 1.1 thorpej
255 1.1 thorpej void hatTest(int testReason)
256 1.1 thorpej {
257 1.1 thorpej
258 1.12 gdamore fiqReason |= testReason;
259 1.12 gdamore nHats++;
260 1.1 thorpej }
261 1.1 thorpej
262 1.1 thorpej void hatWedge(int nFIQs)
263 1.1 thorpej {
264 1.12 gdamore
265 1.12 gdamore printf("Unwedging the HAT. fiqs_happened = %d\n", nFIQs);
266 1.12 gdamore nHatWedges++;
267 1.1 thorpej }
268 1.1 thorpej #endif
269 1.1 thorpej
270 1.1 thorpej void
271 1.12 gdamore startrtclock(void)
272 1.1 thorpej {
273 1.12 gdamore
274 1.12 gdamore findcpuspeed(); /* use the clock (while it's free) to
275 1.12 gdamore find the CPU speed */
276 1.1 thorpej
277 1.1 thorpej timer0count.lo = 0;
278 1.1 thorpej timer0count.hi = 0;
279 1.1 thorpej timer0_at_last_clockintr.lo = 0;
280 1.1 thorpej timer0_at_last_clockintr.hi = 0;
281 1.1 thorpej timer0last = 0;
282 1.1 thorpej
283 1.1 thorpej /* initialize 8253 clock */
284 1.1 thorpej outb(IO_TIMER1 + TIMER_MODE, TIMER_SEL0|TIMER_RATEGEN|TIMER_16BIT);
285 1.1 thorpej outb(IO_TIMER1 + TIMER_CNTR0, TIMER0_ROLLOVER % 256);
286 1.1 thorpej outb(IO_TIMER1 + TIMER_CNTR0, TIMER0_ROLLOVER / 256);
287 1.1 thorpej
288 1.1 thorpej #ifdef TESTHAT
289 1.1 thorpej hatCount = timer_hz_to_count(HATHZ);
290 1.1 thorpej hatCount2 = timer_hz_to_count(HATHZ2);
291 1.1 thorpej printf("HAT test on @ %d Hz = %d ticks\n", HATHZ, hatCount);
292 1.1 thorpej #endif
293 1.1 thorpej }
294 1.1 thorpej
295 1.1 thorpej int
296 1.12 gdamore timer_hz_to_count(int timer_hz)
297 1.1 thorpej {
298 1.1 thorpej u_long tval;
299 1.1 thorpej
300 1.1 thorpej tval = (TIMER_FREQ * 2) / (u_long) timer_hz;
301 1.1 thorpej tval = (tval / 2) + (tval & 0x1);
302 1.1 thorpej
303 1.1 thorpej return (int)tval;
304 1.1 thorpej }
305 1.1 thorpej
306 1.3 chs void gettimer0count(struct count64 *);
307 1.3 chs
308 1.1 thorpej /* must be called at SPL_CLOCK or higher */
309 1.12 gdamore void gettimer0count(struct count64 *pcount)
310 1.1 thorpej {
311 1.1 thorpej unsigned current, ticks, oldlo;
312 1.1 thorpej
313 1.1 thorpej /*
314 1.1 thorpej * Latch the current value of the timer and then read it.
315 1.4 wiz * This guarantees an atomic reading of the time.
316 1.1 thorpej */
317 1.1 thorpej
318 1.1 thorpej current = gettick();
319 1.1 thorpej
320 1.1 thorpej if (timer0last >= current)
321 1.12 gdamore ticks = timer0last - current;
322 1.1 thorpej else
323 1.12 gdamore ticks = timer0last + (TIMER0_ROLLOVER - current);
324 1.1 thorpej
325 1.1 thorpej timer0last = current;
326 1.1 thorpej
327 1.1 thorpej oldlo = timer0count.lo;
328 1.1 thorpej
329 1.1 thorpej if (oldlo > (timer0count.lo = oldlo + ticks)) /* carry? */
330 1.12 gdamore timer0count.hi++;
331 1.1 thorpej
332 1.1 thorpej *pcount = timer0count;
333 1.1 thorpej }
334 1.1 thorpej
335 1.1 thorpej static int
336 1.12 gdamore clockintr(void *arg)
337 1.1 thorpej {
338 1.1 thorpej struct clockframe *frame = arg; /* not strictly necessary */
339 1.1 thorpej extern void isa_specific_eoi(int irq);
340 1.1 thorpej #ifdef TESTHAT
341 1.1 thorpej static int ticks = 0;
342 1.1 thorpej #endif
343 1.1 thorpej static int hatUnwedgeCtr = 0;
344 1.1 thorpej
345 1.1 thorpej gettimer0count(&timer0_at_last_clockintr);
346 1.1 thorpej
347 1.1 thorpej mc146818_read(NULL, MC_REGC); /* clear the clock interrupt */
348 1.1 thorpej
349 1.1 thorpej /* check to see if the high-availability timer needs to be unwedged */
350 1.1 thorpej if (++hatUnwedgeCtr >= (hz / HAT_MIN_FREQ)) {
351 1.12 gdamore hatUnwedgeCtr = 0;
352 1.12 gdamore hatUnwedge();
353 1.1 thorpej }
354 1.1 thorpej
355 1.1 thorpej #ifdef TESTHAT
356 1.1 thorpej ++ticks;
357 1.1 thorpej
358 1.1 thorpej if (testHatOn && ((ticks & 0x3f) == 0)) {
359 1.12 gdamore if (testHatOn == 1) {
360 1.12 gdamore hatClkAdjust(hatCount2);
361 1.12 gdamore testHatOn = 2;
362 1.12 gdamore } else {
363 1.12 gdamore testHatOn = 0;
364 1.12 gdamore hatClkOff();
365 1.12 gdamore printf("hat off status: %d %d %x\n", nHats,
366 1.12 gdamore nHatWedges, fiqReason);
367 1.12 gdamore }
368 1.1 thorpej } else if (!testHatOn && (ticks & 0x1ff) == 0) {
369 1.12 gdamore printf("hat on status: %d %d %x\n",
370 1.12 gdamore nHats, nHatWedges, fiqReason);
371 1.12 gdamore testHatOn = 1;
372 1.12 gdamore nHats = 0;
373 1.12 gdamore fiqReason = 0;
374 1.12 gdamore hatClkOn(hatCount, hatTest, 0xfeedface,
375 1.12 gdamore hatStack + HATSTACKSIZE - sizeof(unsigned),
376 1.12 gdamore hatWedge);
377 1.1 thorpej }
378 1.1 thorpej #endif
379 1.1 thorpej hardclock(frame);
380 1.1 thorpej return(0);
381 1.1 thorpej }
382 1.1 thorpej
383 1.1 thorpej static int
384 1.12 gdamore gettick(void)
385 1.1 thorpej {
386 1.1 thorpej u_char lo, hi;
387 1.1 thorpej u_int savedints;
388 1.1 thorpej
389 1.1 thorpej /* Don't want someone screwing with the counter while we're here. */
390 1.1 thorpej savedints = disable_interrupts(I32_bit);
391 1.1 thorpej /* Select counter 0 and latch it. */
392 1.1 thorpej outb(IO_TIMER1 + TIMER_MODE, TIMER_SEL0 | TIMER_LATCH);
393 1.1 thorpej lo = inb(IO_TIMER1 + TIMER_CNTR0);
394 1.1 thorpej hi = inb(IO_TIMER1 + TIMER_CNTR0);
395 1.1 thorpej restore_interrupts(savedints);
396 1.1 thorpej return ((hi << 8) | lo);
397 1.1 thorpej }
398 1.1 thorpej
399 1.1 thorpej /* modifications from i386 to shark isa version:
400 1.1 thorpej - removed hardcoded "n -=" values that approximated the time to
401 1.1 thorpej calculate delay ticks
402 1.1 thorpej - made the time to calculate delay ticks almost negligable. 4 multiplies
403 1.1 thorpej = maximum of 12 cycles = 75ns on a slow SA-110, plus a bunch of shifts;
404 1.1 thorpej as opposed to 4 multiplies plus a bunch of divides.
405 1.1 thorpej - removed i386 assembly language hack
406 1.1 thorpej - put code in findcpuspeed that works even if FIRST_GUESS is orders
407 1.1 thorpej of magnitude low
408 1.1 thorpej - put code in delay() to use delayloop() for short delays
409 1.1 thorpej - microtime no longer in assembly language
410 1.1 thorpej */
411 1.1 thorpej
412 1.1 thorpej /*
413 1.1 thorpej * Wait "n" microseconds.
414 1.1 thorpej * Relies on timer 1 counting down from (TIMER_FREQ / hz) at TIMER_FREQ Hz.
415 1.1 thorpej * Note: timer had better have been programmed before this is first used!
416 1.1 thorpej * (Note that we use `rate generator' mode, which counts at 1:1; `square
417 1.1 thorpej * wave' mode counts at 2:1).
418 1.1 thorpej */
419 1.1 thorpej void
420 1.12 gdamore delay(unsigned n)
421 1.1 thorpej {
422 1.8 scw int ticks, otick;
423 1.1 thorpej int nticks;
424 1.1 thorpej
425 1.1 thorpej if (n < 100) {
426 1.12 gdamore /* it can take a long time (1 usec or longer) just for
427 1.12 gdamore 1 ISA read, so it's best not to use the timer for
428 1.12 gdamore short delays */
429 1.12 gdamore delayloop((n * count1024usec) >> 10);
430 1.12 gdamore return;
431 1.1 thorpej }
432 1.1 thorpej
433 1.1 thorpej /*
434 1.1 thorpej * Read the counter first, so that the rest of the setup overhead is
435 1.1 thorpej * counted.
436 1.1 thorpej */
437 1.1 thorpej otick = gettick();
438 1.1 thorpej
439 1.1 thorpej /*
440 1.1 thorpej * Calculate ((n * TIMER_FREQ) / 1e6) without using floating point and
441 1.1 thorpej * without any avoidable overflows.
442 1.1 thorpej */
443 1.1 thorpej {
444 1.1 thorpej /* a Musec = 2^20 usec */
445 1.1 thorpej int Musec = n >> 20,
446 1.1 thorpej usec = n & ((1 << 20) - 1);
447 1.1 thorpej nticks
448 1.1 thorpej = (Musec * TIMER_MUSECFREQ) +
449 1.1 thorpej (usec * (TIMER_MUSECFREQ >> 20)) +
450 1.1 thorpej ((usec * ((TIMER_MUSECFREQ & ((1 <<20) - 1)) >>10)) >>10) +
451 1.1 thorpej ((usec * (TIMER_MUSECFREQ & ((1 << 10) - 1))) >> 20);
452 1.1 thorpej }
453 1.1 thorpej
454 1.1 thorpej while (nticks > 0) {
455 1.8 scw ticks = gettick();
456 1.8 scw if (ticks > otick)
457 1.8 scw nticks -= TIMER0_ROLLOVER - (ticks - otick);
458 1.1 thorpej else
459 1.8 scw nticks -= otick - ticks;
460 1.8 scw otick = ticks;
461 1.1 thorpej }
462 1.1 thorpej
463 1.1 thorpej }
464 1.1 thorpej
465 1.1 thorpej void
466 1.12 gdamore sysbeepstop(void *arg)
467 1.1 thorpej {
468 1.1 thorpej }
469 1.1 thorpej
470 1.1 thorpej void
471 1.12 gdamore sysbeep(int pitch, int period)
472 1.1 thorpej {
473 1.1 thorpej }
474 1.1 thorpej
475 1.1 thorpej #define FIRST_GUESS 0x2000
476 1.1 thorpej
477 1.1 thorpej static void
478 1.12 gdamore findcpuspeed(void)
479 1.1 thorpej {
480 1.1 thorpej int ticks;
481 1.1 thorpej unsigned int guess = FIRST_GUESS;
482 1.1 thorpej
483 1.1 thorpej while (1) { /* loop until accurate enough */
484 1.12 gdamore /* Put counter in count down mode */
485 1.12 gdamore outb(IO_TIMER1 + TIMER_MODE,
486 1.12 gdamore TIMER_SEL0 | TIMER_16BIT | TIMER_RATEGEN);
487 1.12 gdamore outb(IO_TIMER1 + TIMER_CNTR0, 0xff);
488 1.12 gdamore outb(IO_TIMER1 + TIMER_CNTR0, 0xff);
489 1.12 gdamore delayloop(guess);
490 1.12 gdamore
491 1.12 gdamore /* Read the value left in the counter */
492 1.12 gdamore /*
493 1.12 gdamore * Formula for delaycount is:
494 1.12 gdamore * (loopcount * timer clock speed) / (counter ticks * 1000)
495 1.12 gdamore */
496 1.12 gdamore ticks = 0xFFFF - gettick();
497 1.12 gdamore if (ticks == 0) ticks = 1; /* just in case */
498 1.12 gdamore if (ticks < (TIMER_MUSECDIV(1024))) { /* not accurate enough */
499 1.12 gdamore guess *= max(2, (TIMER_MUSECDIV(1024) / ticks));
500 1.12 gdamore continue;
501 1.12 gdamore }
502 1.12 gdamore count1024usec = (guess * (TIMER_MUSECDIV(1024))) / ticks;
503 1.12 gdamore return;
504 1.1 thorpej }
505 1.1 thorpej }
506 1.1 thorpej
507 1.1 thorpej static void
508 1.12 gdamore delayloop(int counts)
509 1.1 thorpej {
510 1.12 gdamore while (counts--)
511 1.12 gdamore __insn_barrier();
512 1.1 thorpej }
513 1.1 thorpej
514 1.1 thorpej void
515 1.12 gdamore cpu_initclocks(void)
516 1.1 thorpej {
517 1.1 thorpej unsigned hzval;
518 1.1 thorpej
519 1.1 thorpej printf("clock: hz=%d stathz = %d profhz = %d\n", hz, stathz, profhz);
520 1.1 thorpej
521 1.1 thorpej /* install RTC interrupt handler */
522 1.1 thorpej (void)isa_intr_establish(NULL, IRQ_RTC, IST_LEVEL, IPL_CLOCK,
523 1.1 thorpej clockintr, 0);
524 1.1 thorpej
525 1.1 thorpej /* set up periodic interrupt @ hz
526 1.1 thorpej this is the subset of hz values in kern_clock.c that are
527 1.1 thorpej supported by the ISA RTC */
528 1.1 thorpej switch (hz) {
529 1.1 thorpej case 64:
530 1.1 thorpej hzval = MC_RATE_64_Hz;
531 1.1 thorpej break;
532 1.1 thorpej case 128:
533 1.1 thorpej hzval = MC_RATE_128_Hz;
534 1.1 thorpej break;
535 1.1 thorpej case 256:
536 1.1 thorpej hzval = MC_RATE_256_Hz;
537 1.1 thorpej break;
538 1.1 thorpej case 1024:
539 1.1 thorpej hzval = MC_RATE_1024_Hz;
540 1.1 thorpej break;
541 1.1 thorpej default:
542 1.2 provos panic("cannot configure hz = %d", hz);
543 1.1 thorpej }
544 1.1 thorpej
545 1.1 thorpej rtcinit(); /* make sure basics are done by now */
546 1.1 thorpej
547 1.1 thorpej /* blast values to set up clock interrupt */
548 1.1 thorpej mc146818_write(NULL, MC_REGA, MC_BASE_32_KHz | hzval);
549 1.1 thorpej /* enable periodic interrupt */
550 1.1 thorpej mc146818_write(NULL, MC_REGB,
551 1.1 thorpej mc146818_read(NULL, MC_REGB) | MC_REGB_PIE);
552 1.13 gdamore
553 1.13 gdamore tc_init_i8253();
554 1.1 thorpej }
555 1.1 thorpej
556 1.1 thorpej void
557 1.12 gdamore rtcinit(void)
558 1.1 thorpej {
559 1.1 thorpej static int first_rtcopen_ever = 1;
560 1.1 thorpej
561 1.1 thorpej if (!first_rtcopen_ever)
562 1.1 thorpej return;
563 1.1 thorpej first_rtcopen_ever = 0;
564 1.1 thorpej
565 1.1 thorpej mc146818_write(NULL, MC_REGA, /* XXX softc */
566 1.1 thorpej MC_BASE_32_KHz | MC_RATE_1024_Hz);
567 1.1 thorpej mc146818_write(NULL, MC_REGB, MC_REGB_24HR); /* XXX softc */
568 1.1 thorpej }
569 1.1 thorpej
570 1.1 thorpej void
571 1.12 gdamore setstatclockrate(int arg)
572 1.1 thorpej {
573 1.1 thorpej }
574 1.1 thorpej
575 1.13 gdamore static uint32_t
576 1.13 gdamore i8253_get_timecount(struct timecounter *tc)
577 1.13 gdamore {
578 1.13 gdamore return (TIMER0_ROLLOVER - gettick());
579 1.13 gdamore }
580 1.1 thorpej
581 1.1 thorpej void
582 1.13 gdamore tc_init_i8253(void)
583 1.1 thorpej {
584 1.13 gdamore static struct timecounter i8253_tc = {
585 1.13 gdamore .tc_get_timecount = i8253_get_timecount,
586 1.13 gdamore .tc_counter_mask = TIMER0_ROLLOVER,
587 1.13 gdamore .tc_frequency = TIMER_FREQ,
588 1.13 gdamore .tc_name = "i8253",
589 1.13 gdamore .tc_quality = 100
590 1.13 gdamore };
591 1.1 thorpej
592 1.13 gdamore tc_init(&i8253_tc);
593 1.1 thorpej }
594 1.1 thorpej
595 1.1 thorpej /* End of clock.c */
596