1 /* $NetBSD: clock.c,v 1.9 2005/12/11 12:19:02 christos 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@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.9 2005/12/11 12:19:02 christos 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 u_int mc146818_read(void *, u_int); 192 __inline void mc146818_write(void *, u_int, u_int); 193 194 #define SECMIN ((unsigned)60) /* seconds per minute */ 195 #define SECHOUR ((unsigned)(60*SECMIN)) /* seconds per hour */ 196 #define SECDAY ((unsigned)(24*SECHOUR)) /* seconds per day */ 197 #define SECYR ((unsigned)(365*SECDAY)) /* seconds per common year */ 198 199 __inline u_int 200 mc146818_read(sc, reg) 201 void *sc; /* XXX use it? */ 202 u_int reg; 203 { 204 205 outb(IO_RTC, reg); 206 return (inb(IO_RTC+1)); 207 } 208 209 __inline void 210 mc146818_write(sc, reg, datum) 211 void *sc; /* XXX use it? */ 212 u_int reg, datum; 213 { 214 215 outb(IO_RTC, reg); 216 outb(IO_RTC+1, datum); 217 } 218 219 unsigned int count1024usec; /* calibrated loop variable (1024 microseconds) */ 220 221 /* number of timer ticks in a Musec = 2^20 usecs */ 222 #define TIMER_MUSECFREQ\ 223 (((((((TIMER_FREQ) * 1024) + 999) / 1000) * 1024) + 999) / 1000) 224 #define TIMER_MUSECDIV(x) ((TIMER_MUSECFREQ+(x)/2)/(x)) 225 226 /* 227 * microtime() makes use of the following globals. 228 * timer_msb_table[] and timer_lsb_table[] are used to compute the 229 * microsecond increment. 230 * 231 * time.tv_usec += isa_timer_msb_table[cnt_msb] + isa_timer_lsb_table[cnt_lsb]; 232 */ 233 234 u_short isa_timer_msb_table[256]; /* timer->usec MSB */ 235 u_short isa_timer_lsb_table[256]; /* timer->usec conversion for LSB */ 236 237 /* 64 bit counts from timer 0 */ 238 struct count64 { 239 unsigned lo; /* low 32 bits */ 240 unsigned hi; /* high 32 bits */ 241 }; 242 243 #define TIMER0_ROLLOVER 0xFFFF /* maximum rollover for 8254 counter */ 244 245 struct count64 timer0count; 246 struct count64 timer0_at_last_clockintr; 247 unsigned timer0last; 248 249 /*#define TESTHAT*/ 250 #ifdef TESTHAT 251 #define HATSTACKSIZE 1024 252 #define HATHZ 50000 253 #define HATHZ2 10000 254 unsigned char hatStack[HATSTACKSIZE]; 255 256 unsigned testHatOn = 0; 257 unsigned nHats = 0; 258 unsigned nHatWedges = 0; 259 unsigned fiqReason = 0; 260 unsigned hatCount = 0; 261 unsigned hatCount2 = 0; 262 263 void hatTest(int testReason) 264 { 265 fiqReason |= testReason; 266 nHats++; 267 268 } 269 270 void hatWedge(int nFIQs) 271 { 272 printf("Unwedging the HAT. fiqs_happened = %d\n", nFIQs); 273 nHatWedges++; 274 } 275 #endif 276 277 void 278 startrtclock() 279 { 280 findcpuspeed(); /* use the clock (while it's free) 281 to find the CPU speed */ 282 283 init_isa_timer_tables(); 284 285 timer0count.lo = 0; 286 timer0count.hi = 0; 287 timer0_at_last_clockintr.lo = 0; 288 timer0_at_last_clockintr.hi = 0; 289 timer0last = 0; 290 291 /* initialize 8253 clock */ 292 outb(IO_TIMER1 + TIMER_MODE, TIMER_SEL0|TIMER_RATEGEN|TIMER_16BIT); 293 outb(IO_TIMER1 + TIMER_CNTR0, TIMER0_ROLLOVER % 256); 294 outb(IO_TIMER1 + TIMER_CNTR0, TIMER0_ROLLOVER / 256); 295 296 #ifdef TESTHAT 297 hatCount = timer_hz_to_count(HATHZ); 298 hatCount2 = timer_hz_to_count(HATHZ2); 299 printf("HAT test on @ %d Hz = %d ticks\n", HATHZ, hatCount); 300 #endif 301 } 302 303 static void 304 init_isa_timer_tables() 305 { 306 int s; 307 u_long t, msbmillion, quotient, remainder; 308 309 for (s = 0; s < 256; s++) { 310 /* LSB table is easy, just divide and round */ 311 t = ((u_long) s * 1000000 * 2) / TIMER_FREQ; 312 isa_timer_lsb_table[s] = (u_short) ((t / 2) + (t & 0x1)); 313 314 msbmillion = s * 1000000; 315 quotient = msbmillion / TIMER_FREQ; 316 remainder = msbmillion % TIMER_FREQ; 317 t = (remainder * 256 * 2) / TIMER_FREQ; 318 isa_timer_msb_table[s] = 319 (u_short)((t / 2) + (t & 1) + (quotient * 256)); 320 321 #ifdef DIAGNOSTIC 322 if ((s > 0) && 323 (isa_timer_msb_table[s] < 324 (isa_timer_msb_table[s - 1] + isa_timer_lsb_table[0xFF]))) 325 panic ("time tables not monotonic %d: %d < (%d + %d) = %d\n", 326 s, isa_timer_msb_table[s], 327 isa_timer_msb_table[s - 1], 328 isa_timer_lsb_table[0xFF], 329 isa_timer_msb_table[s - 1] + 330 isa_timer_lsb_table[0xFF]); 331 #endif 332 } /* END for */ 333 } 334 335 int 336 timer_hz_to_count(timer_hz) 337 int timer_hz; 338 { 339 u_long tval; 340 341 tval = (TIMER_FREQ * 2) / (u_long) timer_hz; 342 tval = (tval / 2) + (tval & 0x1); 343 344 return (int)tval; 345 346 } 347 348 void gettimer0count(struct count64 *); 349 350 /* must be called at SPL_CLOCK or higher */ 351 void gettimer0count(pcount) 352 struct count64 *pcount; 353 { 354 unsigned current, ticks, oldlo; 355 356 /* 357 * Latch the current value of the timer and then read it. 358 * This guarantees an atomic reading of the time. 359 */ 360 361 current = gettick(); 362 363 if (timer0last >= current) 364 ticks = timer0last - current; 365 else 366 ticks = timer0last + (TIMER0_ROLLOVER - current); 367 368 timer0last = current; 369 370 oldlo = timer0count.lo; 371 372 if (oldlo > (timer0count.lo = oldlo + ticks)) /* carry? */ 373 timer0count.hi++; 374 375 *pcount = timer0count; 376 } 377 378 static int 379 clockintr(arg) 380 void *arg; 381 { 382 struct clockframe *frame = arg; /* not strictly necessary */ 383 extern void isa_specific_eoi(int irq); 384 #ifdef TESTHAT 385 static int ticks = 0; 386 #endif 387 static int hatUnwedgeCtr = 0; 388 389 gettimer0count(&timer0_at_last_clockintr); 390 391 mc146818_read(NULL, MC_REGC); /* clear the clock interrupt */ 392 393 /* check to see if the high-availability timer needs to be unwedged */ 394 if (++hatUnwedgeCtr >= (hz / HAT_MIN_FREQ)) { 395 hatUnwedgeCtr = 0; 396 hatUnwedge(); 397 } 398 399 #ifdef TESTHAT 400 ++ticks; 401 402 if (testHatOn && ((ticks & 0x3f) == 0)) { 403 if (testHatOn == 1) { 404 hatClkAdjust(hatCount2); 405 testHatOn = 2; 406 } else { 407 testHatOn = 0; 408 hatClkOff(); 409 printf("hat off status: %d %d %x\n", nHats, nHatWedges, fiqReason); 410 } 411 } else if (!testHatOn && (ticks & 0x1ff) == 0) { 412 printf("hat on status: %d %d %x\n", nHats, nHatWedges, fiqReason); 413 testHatOn = 1; 414 nHats = 0; 415 fiqReason = 0; 416 hatClkOn(hatCount, hatTest, 0xfeedface, 417 hatStack + HATSTACKSIZE - sizeof(unsigned), 418 hatWedge); 419 } 420 #endif 421 hardclock(frame); 422 return(0); 423 } 424 425 static int 426 gettick() 427 { 428 u_char lo, hi; 429 u_int savedints; 430 431 /* Don't want someone screwing with the counter while we're here. */ 432 savedints = disable_interrupts(I32_bit); 433 /* Select counter 0 and latch it. */ 434 outb(IO_TIMER1 + TIMER_MODE, TIMER_SEL0 | TIMER_LATCH); 435 lo = inb(IO_TIMER1 + TIMER_CNTR0); 436 hi = inb(IO_TIMER1 + TIMER_CNTR0); 437 restore_interrupts(savedints); 438 return ((hi << 8) | lo); 439 } 440 441 /* modifications from i386 to shark isa version: 442 - removed hardcoded "n -=" values that approximated the time to 443 calculate delay ticks 444 - made the time to calculate delay ticks almost negligable. 4 multiplies 445 = maximum of 12 cycles = 75ns on a slow SA-110, plus a bunch of shifts; 446 as opposed to 4 multiplies plus a bunch of divides. 447 - removed i386 assembly language hack 448 - put code in findcpuspeed that works even if FIRST_GUESS is orders 449 of magnitude low 450 - put code in delay() to use delayloop() for short delays 451 - microtime no longer in assembly language 452 */ 453 454 /* 455 * Wait "n" microseconds. 456 * Relies on timer 1 counting down from (TIMER_FREQ / hz) at TIMER_FREQ Hz. 457 * Note: timer had better have been programmed before this is first used! 458 * (Note that we use `rate generator' mode, which counts at 1:1; `square 459 * wave' mode counts at 2:1). 460 */ 461 void 462 delay(n) 463 unsigned n; 464 { 465 int ticks, otick; 466 int nticks; 467 468 if (n < 100) { 469 /* it can take a long time (1 usec or longer) just for 1 ISA read, 470 so it's best not to use the timer for short delays */ 471 delayloop((n * count1024usec) >> 10); 472 return; 473 } 474 475 /* 476 * Read the counter first, so that the rest of the setup overhead is 477 * counted. 478 */ 479 otick = gettick(); 480 481 /* 482 * Calculate ((n * TIMER_FREQ) / 1e6) without using floating point and 483 * without any avoidable overflows. 484 */ 485 { 486 /* a Musec = 2^20 usec */ 487 int Musec = n >> 20, 488 usec = n & ((1 << 20) - 1); 489 nticks 490 = (Musec * TIMER_MUSECFREQ) + 491 (usec * (TIMER_MUSECFREQ >> 20)) + 492 ((usec * ((TIMER_MUSECFREQ & ((1 <<20) - 1)) >>10)) >>10) + 493 ((usec * (TIMER_MUSECFREQ & ((1 << 10) - 1))) >> 20); 494 } 495 496 while (nticks > 0) { 497 ticks = gettick(); 498 if (ticks > otick) 499 nticks -= TIMER0_ROLLOVER - (ticks - otick); 500 else 501 nticks -= otick - ticks; 502 otick = ticks; 503 } 504 505 } 506 507 void 508 sysbeepstop(arg) 509 void *arg; 510 { 511 } 512 513 void 514 sysbeep(pitch, period) 515 int pitch, period; 516 { 517 } 518 519 #define FIRST_GUESS 0x2000 520 521 static void 522 findcpuspeed() 523 { 524 int ticks; 525 unsigned int guess = FIRST_GUESS; 526 527 while (1) { /* loop until accurate enough */ 528 /* Put counter in count down mode */ 529 outb(IO_TIMER1 + TIMER_MODE, TIMER_SEL0 | TIMER_16BIT | TIMER_RATEGEN); 530 outb(IO_TIMER1 + TIMER_CNTR0, 0xff); 531 outb(IO_TIMER1 + TIMER_CNTR0, 0xff); 532 delayloop(guess); 533 534 /* Read the value left in the counter */ 535 /* 536 * Formula for delaycount is: 537 * (loopcount * timer clock speed) / (counter ticks * 1000) 538 */ 539 ticks = 0xFFFF - gettick(); 540 if (ticks == 0) ticks = 1; /* just in case */ 541 if (ticks < (TIMER_MUSECDIV(1024))) { /* not accurate enough */ 542 guess *= max(2, (TIMER_MUSECDIV(1024) / ticks)); 543 continue; 544 } 545 count1024usec = (guess * (TIMER_MUSECDIV(1024))) / ticks; 546 return; 547 } 548 } 549 550 static void 551 delayloop(counts) 552 { 553 while (counts--); 554 } 555 556 void 557 cpu_initclocks() 558 { 559 unsigned hzval; 560 561 printf("clock: hz=%d stathz = %d profhz = %d\n", hz, stathz, profhz); 562 563 /* install RTC interrupt handler */ 564 (void)isa_intr_establish(NULL, IRQ_RTC, IST_LEVEL, IPL_CLOCK, 565 clockintr, 0); 566 567 /* code for values of hz that don't divide 1000000 exactly */ 568 tickfix = 1000000 - (hz * tick); 569 if (tickfix) { 570 int ftp; 571 572 ftp = min(ffs(tickfix), ffs(hz)); 573 tickfix >>= (ftp - 1); 574 tickfixinterval = hz >> (ftp - 1); 575 } 576 577 /* set up periodic interrupt @ hz 578 this is the subset of hz values in kern_clock.c that are 579 supported by the ISA RTC */ 580 switch (hz) { 581 case 64: 582 hzval = MC_RATE_64_Hz; 583 break; 584 case 128: 585 hzval = MC_RATE_128_Hz; 586 break; 587 case 256: 588 hzval = MC_RATE_256_Hz; 589 break; 590 case 1024: 591 hzval = MC_RATE_1024_Hz; 592 break; 593 default: 594 panic("cannot configure hz = %d", hz); 595 } 596 597 rtcinit(); /* make sure basics are done by now */ 598 599 /* blast values to set up clock interrupt */ 600 mc146818_write(NULL, MC_REGA, MC_BASE_32_KHz | hzval); 601 /* enable periodic interrupt */ 602 mc146818_write(NULL, MC_REGB, 603 mc146818_read(NULL, MC_REGB) | MC_REGB_PIE); 604 } 605 606 void 607 rtcinit() 608 { 609 static int first_rtcopen_ever = 1; 610 611 if (!first_rtcopen_ever) 612 return; 613 first_rtcopen_ever = 0; 614 615 mc146818_write(NULL, MC_REGA, /* XXX softc */ 616 MC_BASE_32_KHz | MC_RATE_1024_Hz); 617 mc146818_write(NULL, MC_REGB, MC_REGB_24HR); /* XXX softc */ 618 } 619 620 void 621 setstatclockrate(arg) 622 int arg; 623 { 624 } 625 626 /* 627 * void microtime(struct timeval *tvp) 628 * 629 * Fill in the specified timeval struct with the current time 630 * accurate to the microsecond. 631 */ 632 633 void 634 microtime(tvp) 635 struct timeval *tvp; 636 { 637 int s; 638 unsigned lsb, msb; 639 int tm; 640 static struct timeval oldtv; 641 struct count64 timer0current; 642 int ticks; 643 644 s = splstatclock(); 645 646 gettimer0count(&timer0current); 647 648 tm = time.tv_usec; 649 650 /* unsigned arithmetic should take care of overflow */ 651 /* with a >= 32 Hz clock, ticks will always be < 0x7FFF */ 652 ticks = (int)((unsigned) 653 (timer0current.lo - timer0_at_last_clockintr.lo)); 654 655 #ifdef DIAGNOSTIC 656 if ((ticks < 0) || (ticks > 0xffff)) 657 printf("microtime bug: ticks = %x\n", ticks); 658 #endif 659 660 while (ticks > 0) { 661 662 if (ticks < 0xffff) { 663 msb = (ticks >> 8) & 0xFF; 664 lsb = ticks & 0xFF; 665 } else { 666 msb = 0xff; 667 lsb = 0xff; 668 } 669 670 /* see comments above */ 671 tm += isa_timer_msb_table[msb] + isa_timer_lsb_table[lsb]; 672 673 /* for a 64 Hz RTC, ticks will never overflow table */ 674 /* microtime will be less accurate if the RTC is < 36 Hz */ 675 ticks -= 0xffff; 676 } 677 678 tvp->tv_sec = time.tv_sec; 679 if (tm >= 1000000) { 680 tvp->tv_sec += 1; 681 tm -= 1000000; 682 } 683 684 tvp->tv_usec = tm; 685 686 /* Make sure the time has advanced. */ 687 688 if (tvp->tv_sec == oldtv.tv_sec && 689 tvp->tv_usec <= oldtv.tv_usec) { 690 tvp->tv_usec = oldtv.tv_usec + 1; 691 if (tvp->tv_usec >= 1000000) { 692 tvp->tv_usec -= 1000000; 693 ++tvp->tv_sec; 694 } 695 } 696 697 oldtv = *tvp; 698 (void)splx(s); 699 } 700 701 /* End of clock.c */ 702