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