Annotation of sys/arch/mvme68k/dev/clock.c, Revision 1.1
1.1 ! nbrk 1: /* $OpenBSD: clock.c,v 1.13 2004/07/30 22:29:44 miod Exp $ */
! 2:
! 3: /*
! 4: * Copyright (c) 1995 Theo de Raadt
! 5: *
! 6: * Redistribution and use in source and binary forms, with or without
! 7: * modification, are permitted provided that the following conditions
! 8: * are met:
! 9: * 1. Redistributions of source code must retain the above copyright
! 10: * notice, this list of conditions and the following disclaimer.
! 11: * 2. Redistributions in binary form must reproduce the above copyright
! 12: * notice, this list of conditions and the following disclaimer in the
! 13: * documentation and/or other materials provided with the distribution.
! 14: *
! 15: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
! 16: * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
! 17: * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
! 18: * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
! 19: * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
! 20: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
! 21: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
! 22: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
! 23: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
! 24: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
! 25: * SUCH DAMAGE.
! 26: *
! 27: * Copyright (c) 1992, 1993
! 28: * The Regents of the University of California. All rights reserved.
! 29: *
! 30: * This software was developed by the Computer Systems Engineering group
! 31: * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
! 32: * contributed to Berkeley.
! 33: *
! 34: * All advertising materials mentioning features or use of this software
! 35: * must display the following acknowledgement:
! 36: * This product includes software developed by the University of
! 37: * California, Lawrence Berkeley Laboratory.
! 38: *
! 39: * Redistribution and use in source and binary forms, with or without
! 40: * modification, are permitted provided that the following conditions
! 41: * are met:
! 42: * 1. Redistributions of source code must retain the above copyright
! 43: * notice, this list of conditions and the following disclaimer.
! 44: * 2. Redistributions in binary form must reproduce the above copyright
! 45: * notice, this list of conditions and the following disclaimer in the
! 46: * documentation and/or other materials provided with the distribution.
! 47: * 3. Neither the name of the University nor the names of its contributors
! 48: * may be used to endorse or promote products derived from this software
! 49: * without specific prior written permission.
! 50: *
! 51: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
! 52: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
! 53: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
! 54: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
! 55: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
! 56: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
! 57: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
! 58: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
! 59: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
! 60: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
! 61: * SUCH DAMAGE.
! 62: *
! 63: * @(#)clock.c 8.1 (Berkeley) 6/11/93
! 64: */
! 65:
! 66: #include <sys/param.h>
! 67: #include <sys/device.h>
! 68: #include <sys/kernel.h>
! 69: #include <sys/systm.h>
! 70:
! 71: #include <machine/psl.h>
! 72: #include <machine/autoconf.h>
! 73: #include <machine/cpu.h>
! 74:
! 75: #include "pcc.h"
! 76: #include "mc.h"
! 77: #include "pcctwo.h"
! 78:
! 79: #if NPCC > 0
! 80: #include <mvme68k/dev/pccreg.h>
! 81: #endif
! 82: #if NPCCTWO > 0
! 83: #include <mvme68k/dev/pcctworeg.h>
! 84: #include <mvme68k/dev/vme.h>
! 85: extern struct vme2reg *sys_vme2;
! 86: #endif
! 87: #if NMC > 0
! 88: #include <mvme68k/dev/mcreg.h>
! 89: #endif
! 90:
! 91: /*
! 92: * Statistics clock interval and variance, in usec. Variance must be a
! 93: * power of two. Since this gives us an even number, not an odd number,
! 94: * we discard one case and compensate. That is, a variance of 8192 would
! 95: * give us offsets in [0..8191]. Instead, we take offsets in [1..8191].
! 96: * This is symmetric about the point 2048, or statvar/2, and thus averages
! 97: * to that value (assuming uniform random numbers).
! 98: */
! 99: int statvar = 8192;
! 100: int statmin; /* statclock interval - 1/2*variance */
! 101:
! 102: struct clocksoftc {
! 103: struct device sc_dev;
! 104: struct intrhand sc_profih;
! 105: struct intrhand sc_statih;
! 106: };
! 107:
! 108: void clockattach(struct device *, struct device *, void *);
! 109: int clockmatch(struct device *, void *, void *);
! 110:
! 111: struct cfattach clock_ca = {
! 112: sizeof(struct clocksoftc), clockmatch, clockattach
! 113: };
! 114:
! 115: struct cfdriver clock_cd = {
! 116: NULL, "clock", DV_DULL
! 117: };
! 118:
! 119: int clockintr(void *);
! 120: int statintr(void *);
! 121:
! 122: int clockbus;
! 123: u_char stat_reset, prof_reset;
! 124:
! 125: /*
! 126: * Every machine must have a clock tick device of some sort; for this
! 127: * platform this file manages it, no matter what form it takes.
! 128: */
! 129: int
! 130: clockmatch(parent, vcf, args)
! 131: struct device *parent;
! 132: void *vcf, *args;
! 133: {
! 134: return (1);
! 135: }
! 136:
! 137: void
! 138: clockattach(parent, self, args)
! 139: struct device *parent, *self;
! 140: void *args;
! 141: {
! 142: struct confargs *ca = args;
! 143: struct clocksoftc *sc = (struct clocksoftc *)self;
! 144:
! 145: sc->sc_profih.ih_fn = clockintr;
! 146: sc->sc_profih.ih_arg = 0;
! 147: sc->sc_profih.ih_wantframe = 1;
! 148: sc->sc_profih.ih_ipl = ca->ca_ipl;
! 149:
! 150: sc->sc_statih.ih_fn = statintr;
! 151: sc->sc_statih.ih_arg = 0;
! 152: sc->sc_statih.ih_wantframe = 1;
! 153: sc->sc_statih.ih_ipl = ca->ca_ipl;
! 154:
! 155: clockbus = ca->ca_bustype;
! 156: switch (ca->ca_bustype) {
! 157: #if NPCC > 0
! 158: case BUS_PCC:
! 159: prof_reset = ca->ca_ipl | PCC_IRQ_IEN | PCC_TIMERACK;
! 160: stat_reset = ca->ca_ipl | PCC_IRQ_IEN | PCC_TIMERACK;
! 161: pccintr_establish(PCCV_TIMER1, &sc->sc_profih, "clock");
! 162: pccintr_establish(PCCV_TIMER2, &sc->sc_statih, "stat");
! 163: break;
! 164: #endif
! 165: #if NMC > 0
! 166: case BUS_MC:
! 167: prof_reset = ca->ca_ipl | MC_IRQ_IEN | MC_IRQ_ICLR;
! 168: stat_reset = ca->ca_ipl | MC_IRQ_IEN | MC_IRQ_ICLR;
! 169: mcintr_establish(MCV_TIMER1, &sc->sc_profih, "clock");
! 170: mcintr_establish(MCV_TIMER2, &sc->sc_statih, "stat");
! 171: break;
! 172: #endif
! 173: #if NPCCTWO > 0
! 174: case BUS_PCCTWO:
! 175: prof_reset = ca->ca_ipl | PCC2_IRQ_IEN | PCC2_IRQ_ICLR;
! 176: stat_reset = ca->ca_ipl | PCC2_IRQ_IEN | PCC2_IRQ_ICLR;
! 177: pcctwointr_establish(PCC2V_TIMER1, &sc->sc_profih, "clock");
! 178: pcctwointr_establish(PCC2V_TIMER2, &sc->sc_statih, "stat");
! 179: break;
! 180: #endif
! 181: }
! 182:
! 183: printf("\n");
! 184: }
! 185:
! 186: /*
! 187: * clockintr: ack intr and call hardclock
! 188: */
! 189: int
! 190: clockintr(arg)
! 191: void *arg;
! 192: {
! 193: switch (clockbus) {
! 194: #if NPCC > 0
! 195: case BUS_PCC:
! 196: sys_pcc->pcc_t1irq = prof_reset;
! 197: break;
! 198: #endif
! 199: #if NMC > 0
! 200: case BUS_MC:
! 201: sys_mc->mc_t1irq = prof_reset;
! 202: break;
! 203: #endif
! 204: #if NPCCTWO > 0
! 205: case BUS_PCCTWO:
! 206: sys_pcc2->pcc2_t1irq = prof_reset;
! 207: break;
! 208: #endif
! 209: }
! 210:
! 211: hardclock(arg);
! 212: return (1);
! 213: }
! 214:
! 215: /*
! 216: * Set up real-time clock; we don't have a statistics clock at
! 217: * present.
! 218: */
! 219: void
! 220: cpu_initclocks()
! 221: {
! 222: register int statint, minint;
! 223:
! 224: if (1000000 % hz) {
! 225: printf("cannot get %d Hz clock; using 100 Hz\n", hz);
! 226: hz = 100;
! 227: tick = 1000000 / hz;
! 228: }
! 229: if (stathz == 0)
! 230: stathz = hz;
! 231: if (1000000 % stathz) {
! 232: printf("cannot get %d Hz statclock; using 100 Hz\n", stathz);
! 233: stathz = 100;
! 234: }
! 235: profhz = stathz; /* always */
! 236:
! 237: statint = 1000000 / stathz;
! 238: minint = statint / 2 + 100;
! 239: while (statvar > minint)
! 240: statvar >>= 1;
! 241: switch (clockbus) {
! 242: #if NPCC > 0
! 243: case BUS_PCC:
! 244: sys_pcc->pcc_t1pload = pcc_timer_us2lim(tick);
! 245: sys_pcc->pcc_t1ctl = PCC_TIMERCLEAR;
! 246: sys_pcc->pcc_t1ctl = PCC_TIMERSTART;
! 247: sys_pcc->pcc_t1irq = prof_reset;
! 248:
! 249: sys_pcc->pcc_t2pload = pcc_timer_us2lim(statint);
! 250: sys_pcc->pcc_t2ctl = PCC_TIMERCLEAR;
! 251: sys_pcc->pcc_t2ctl = PCC_TIMERSTART;
! 252: sys_pcc->pcc_t2irq = stat_reset;
! 253: break;
! 254: #endif
! 255: #if NMC > 0
! 256: case BUS_MC:
! 257: /* profclock */
! 258: sys_mc->mc_t1ctl = 0;
! 259: sys_mc->mc_t1cmp = mc_timer_us2lim(tick);
! 260: sys_mc->mc_t1count = 0;
! 261: sys_mc->mc_t1ctl = MC_TCTL_CEN | MC_TCTL_COC | MC_TCTL_COVF;
! 262: sys_mc->mc_t1irq = prof_reset;
! 263:
! 264: /* statclock */
! 265: sys_mc->mc_t2ctl = 0;
! 266: sys_mc->mc_t2cmp = mc_timer_us2lim(statint);
! 267: sys_mc->mc_t2count = 0;
! 268: sys_mc->mc_t2ctl = MC_TCTL_CEN | MC_TCTL_COC | MC_TCTL_COVF;
! 269: sys_mc->mc_t2irq = stat_reset;
! 270: break;
! 271: #endif
! 272: #if NPCCTWO > 0
! 273: case BUS_PCCTWO:
! 274: /* profclock */
! 275: sys_pcc2->pcc2_t1ctl = 0;
! 276: sys_pcc2->pcc2_t1cmp = pcc2_timer_us2lim(tick);
! 277: sys_pcc2->pcc2_t1count = 0;
! 278: sys_pcc2->pcc2_t1ctl = PCC2_TCTL_CEN | PCC2_TCTL_COC |
! 279: PCC2_TCTL_COVF;
! 280: sys_pcc2->pcc2_t1irq = prof_reset;
! 281:
! 282: /* statclock */
! 283: sys_pcc2->pcc2_t2ctl = 0;
! 284: sys_pcc2->pcc2_t2cmp = pcc2_timer_us2lim(statint);
! 285: sys_pcc2->pcc2_t2count = 0;
! 286: sys_pcc2->pcc2_t2ctl = PCC2_TCTL_CEN | PCC2_TCTL_COC |
! 287: PCC2_TCTL_COVF;
! 288: sys_pcc2->pcc2_t2irq = stat_reset;
! 289: break;
! 290: #endif
! 291: }
! 292: statmin = statint - (statvar >> 1);
! 293: }
! 294:
! 295: void
! 296: setstatclockrate(newhz)
! 297: int newhz;
! 298: {
! 299: }
! 300:
! 301: int
! 302: statintr(cap)
! 303: void *cap;
! 304: {
! 305: register u_long newint, r, var;
! 306:
! 307: switch (clockbus) {
! 308: #if NPCC > 0
! 309: case BUS_PCC:
! 310: sys_pcc->pcc_t2irq = stat_reset;
! 311: break;
! 312: #endif
! 313: #if NMC > 0
! 314: case BUS_MC:
! 315: sys_mc->mc_t2irq = stat_reset;
! 316: break;
! 317: #endif
! 318: #if NPCCTWO > 0
! 319: case BUS_PCCTWO:
! 320: sys_pcc2->pcc2_t2irq = stat_reset;
! 321: break;
! 322: #endif
! 323: }
! 324:
! 325: statclock((struct clockframe *)cap);
! 326:
! 327: /*
! 328: * Compute new randomized interval. The intervals are uniformly
! 329: * distributed on [statint - statvar / 2, statint + statvar / 2],
! 330: * and therefore have mean statint, giving a stathz frequency clock.
! 331: */
! 332: var = statvar;
! 333: do {
! 334: r = random() & (var - 1);
! 335: } while (r == 0);
! 336: newint = statmin + r;
! 337:
! 338: switch (clockbus) {
! 339: #if NPCC > 0
! 340: case BUS_PCC:
! 341: sys_pcc->pcc_t2pload = pcc_timer_us2lim(newint);
! 342: sys_pcc->pcc_t2ctl = PCC_TIMERCLEAR;
! 343: sys_pcc->pcc_t2ctl = PCC_TIMERSTART;
! 344: sys_pcc->pcc_t2irq = stat_reset;
! 345: break;
! 346: #endif
! 347: #if NMC > 0
! 348: case BUS_MC:
! 349: sys_mc->mc_t2ctl = 0;
! 350: sys_mc->mc_t2cmp = mc_timer_us2lim(newint);
! 351: sys_mc->mc_t2count = 0; /* should I? */
! 352: sys_mc->mc_t2irq = stat_reset;
! 353: sys_mc->mc_t2ctl = MC_TCTL_CEN | MC_TCTL_COC;
! 354: break;
! 355: #endif
! 356: #if NPCCTWO > 0
! 357: case BUS_PCCTWO:
! 358: sys_pcc2->pcc2_t2ctl = 0;
! 359: sys_pcc2->pcc2_t2cmp = pcc2_timer_us2lim(newint);
! 360: sys_pcc2->pcc2_t2count = 0; /* should I? */
! 361: sys_pcc2->pcc2_t2irq = stat_reset;
! 362: sys_pcc2->pcc2_t2ctl = PCC2_TCTL_CEN | PCC2_TCTL_COC;
! 363: break;
! 364: #endif
! 365: }
! 366: return (1);
! 367: }
! 368:
! 369: void
! 370: delay(us)
! 371: int us;
! 372: {
! 373: #if (NPCC > 0) || (NPCCTWO > 0)
! 374: volatile register int c;
! 375: #endif
! 376:
! 377: switch (clockbus) {
! 378: #if NPCC > 0
! 379: case BUS_PCC:
! 380: /*
! 381: * XXX MVME147 doesn't have a 3rd free-running timer,
! 382: * so we use a stupid loop. Fix the code to watch t1:
! 383: * the profiling timer.
! 384: */
! 385: c = 2 * us;
! 386: while (--c > 0)
! 387: ;
! 388: break;
! 389: #endif
! 390: #if NMC > 0
! 391: case BUS_MC:
! 392: /*
! 393: * Reset and restart a free-running timer 1MHz, watch
! 394: * for it to reach the required count.
! 395: */
! 396: sys_mc->mc_t3irq = 0;
! 397: sys_mc->mc_t3ctl = 0;
! 398: sys_mc->mc_t3count = 0;
! 399: sys_mc->mc_t3ctl = MC_TCTL_CEN | MC_TCTL_COVF;
! 400:
! 401: while (sys_mc->mc_t3count < us)
! 402: ;
! 403: break;
! 404: #endif
! 405: #if NPCCTWO > 0
! 406: case BUS_PCCTWO:
! 407: /*
! 408: * Use the first VMEChip2 timer in polling mode whenever
! 409: * possible. However, since clock attaches before vme,
! 410: * use a tight loop if necessary.
! 411: */
! 412: {
! 413: struct vme2reg *vme2;
! 414:
! 415: if (sys_vme2 != NULL)
! 416: vme2 = sys_vme2;
! 417: else
! 418: vme2 = (struct vme2reg *)IIOV(0xfff40000);
! 419:
! 420: vme2->vme2_t1cmp = 0xffffffff;
! 421: vme2->vme2_t1count = 0;
! 422: vme2->vme2_tctl |= VME2_TCTL_CEN;
! 423:
! 424: while (vme2->vme2_t1count < us)
! 425: ;
! 426:
! 427: vme2->vme2_tctl &= ~VME2_TCTL_CEN;
! 428: }
! 429: break;
! 430: #endif
! 431: }
! 432: }
CVSweb