1 1.20 andvar /* $NetBSD: clock.c,v 1.20 2023/12/09 00:02:10 andvar 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.20 andvar __KERNEL_RCSID(0, "$NetBSD: clock.c,v 1.20 2023/12/09 00:02:10 andvar 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.20 andvar static 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.20 andvar static 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.17 msaitoh 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.15 tsutsui return(1); 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.19 andvar - made the time to calculate delay ticks almost negligible. 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.18 riastrad guess *= uimax(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