Annotation of sys/arch/aviion/aviion/av400_machdep.c, Revision 1.1
1.1 ! nbrk 1: /* $OpenBSD: av400_machdep.c,v 1.5 2007/05/12 20:02:12 miod Exp $ */
! 2: /*
! 3: * Copyright (c) 2006, Miodrag Vallat.
! 4: *
! 5: * Redistribution and use in source and binary forms, with or without
! 6: * modification, are permitted provided that the following conditions
! 7: * are met:
! 8: * 1. Redistributions of source code must retain the above copyright
! 9: * notice, this list of conditions and the following disclaimer.
! 10: * 2. Redistributions in binary form must reproduce the above copyright
! 11: * notice, this list of conditions and the following disclaimer in the
! 12: * documentation and/or other materials provided with the distribution.
! 13: *
! 14: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
! 15: * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
! 16: * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
! 17: * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
! 18: * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
! 19: * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
! 20: * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
! 21: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
! 22: * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
! 23: * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
! 24: * POSSIBILITY OF SUCH DAMAGE.
! 25: */
! 26: /*
! 27: * Copyright (c) 1998, 1999, 2000, 2001 Steve Murphree, Jr.
! 28: * Copyright (c) 1996 Nivas Madhur
! 29: * All rights reserved.
! 30: *
! 31: * Redistribution and use in source and binary forms, with or without
! 32: * modification, are permitted provided that the following conditions
! 33: * are met:
! 34: * 1. Redistributions of source code must retain the above copyright
! 35: * notice, this list of conditions and the following disclaimer.
! 36: * 2. Redistributions in binary form must reproduce the above copyright
! 37: * notice, this list of conditions and the following disclaimer in the
! 38: * documentation and/or other materials provided with the distribution.
! 39: * 3. All advertising materials mentioning features or use of this software
! 40: * must display the following acknowledgement:
! 41: * This product includes software developed by Nivas Madhur.
! 42: * 4. The name of the author may not be used to endorse or promote products
! 43: * derived from this software without specific prior written permission
! 44: *
! 45: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
! 46: * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
! 47: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
! 48: * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
! 49: * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
! 50: * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
! 51: * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
! 52: * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
! 53: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
! 54: * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
! 55: *
! 56: */
! 57: /*
! 58: * Copyright (c) 1999 Steve Murphree, Jr.
! 59: * Copyright (c) 1995 Theo de Raadt
! 60: *
! 61: * Redistribution and use in source and binary forms, with or without
! 62: * modification, are permitted provided that the following conditions
! 63: * are met:
! 64: * 1. Redistributions of source code must retain the above copyright
! 65: * notice, this list of conditions and the following disclaimer.
! 66: * 2. Redistributions in binary form must reproduce the above copyright
! 67: * notice, this list of conditions and the following disclaimer in the
! 68: * documentation and/or other materials provided with the distribution.
! 69: *
! 70: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
! 71: * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
! 72: * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
! 73: * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
! 74: * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
! 75: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
! 76: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
! 77: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
! 78: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
! 79: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
! 80: * SUCH DAMAGE.
! 81: *
! 82: * Copyright (c) 1992, 1993
! 83: * The Regents of the University of California. All rights reserved.
! 84: * Copyright (c) 1995 Nivas Madhur
! 85: * Copyright (c) 1994 Gordon W. Ross
! 86: * Copyright (c) 1993 Adam Glass
! 87: *
! 88: * This software was developed by the Computer Systems Engineering group
! 89: * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
! 90: * contributed to Berkeley.
! 91: *
! 92: * All advertising materials mentioning features or use of this software
! 93: * must display the following acknowledgement:
! 94: * This product includes software developed by the University of
! 95: * California, Lawrence Berkeley Laboratory.
! 96: *
! 97: * Redistribution and use in source and binary forms, with or without
! 98: * modification, are permitted provided that the following conditions
! 99: * are met:
! 100: * 1. Redistributions of source code must retain the above copyright
! 101: * notice, this list of conditions and the following disclaimer.
! 102: * 2. Redistributions in binary form must reproduce the above copyright
! 103: * notice, this list of conditions and the following disclaimer in the
! 104: * documentation and/or other materials provided with the distribution.
! 105: * 3. Neither the name of the University nor the names of its contributors
! 106: * may be used to endorse or promote products derived from this software
! 107: * without specific prior written permission.
! 108: *
! 109: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
! 110: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
! 111: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
! 112: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
! 113: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
! 114: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
! 115: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
! 116: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
! 117: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
! 118: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
! 119: * SUCH DAMAGE.
! 120: *
! 121: * @(#)clock.c 8.1 (Berkeley) 6/11/93
! 122: */
! 123: /*
! 124: * Mach Operating System
! 125: * Copyright (c) 1993-1991 Carnegie Mellon University
! 126: * Copyright (c) 1991 OMRON Corporation
! 127: * All Rights Reserved.
! 128: *
! 129: * Permission to use, copy, modify and distribute this software and its
! 130: * documentation is hereby granted, provided that both the copyright
! 131: * notice and this permission notice appear in all copies of the
! 132: * software, derivative works or modified versions, and any portions
! 133: * thereof, and that both notices appear in supporting documentation.
! 134: *
! 135: */
! 136:
! 137: #include <sys/param.h>
! 138: #include <sys/systm.h>
! 139: #include <sys/kernel.h>
! 140: #include <sys/errno.h>
! 141:
! 142: #include <uvm/uvm_extern.h>
! 143:
! 144: #include <machine/asm_macro.h>
! 145: #include <machine/board.h>
! 146: #include <machine/cmmu.h>
! 147: #include <machine/cpu.h>
! 148: #include <machine/reg.h>
! 149: #include <machine/trap.h>
! 150:
! 151: #include <machine/m88100.h>
! 152: #include <machine/m8820x.h>
! 153: #include <machine/avcommon.h>
! 154: #include <machine/av400.h>
! 155: #include <machine/prom.h>
! 156:
! 157: #include <aviion/dev/sysconreg.h>
! 158:
! 159: u_int safe_level(u_int mask, u_int curlevel);
! 160:
! 161: const pmap_table_entry
! 162: av400_ptable[] = {
! 163: { AV400_PROM, AV400_PROM, AV400_PROM_SIZE,
! 164: UVM_PROT_RW, CACHE_INH },
! 165: #if 0 /* mapped by the hardcoded BATC entries */
! 166: { AV400_UTILITY,AV400_UTILITY, AV400_UTILITY_SIZE,
! 167: UVM_PROT_RW, CACHE_INHIBIT },
! 168: #endif
! 169: { 0, 0, (vsize_t)-1, 0, 0 }
! 170: };
! 171:
! 172: const struct board board_av400 = {
! 173: "100/200/300/400/3000/4000/4300 series",
! 174: av400_bootstrap,
! 175: av400_memsize,
! 176: av400_startup,
! 177: av400_intr,
! 178: av400_init_clocks,
! 179: av400_getipl,
! 180: av400_setipl,
! 181: av400_raiseipl,
! 182: av400_ptable
! 183: };
! 184:
! 185: /*
! 186: * The MVME188 interrupt arbiter has 25 orthogonal interrupt sources.
! 187: * On the AViiON machines, there are even more interrupt sources in use,
! 188: * but differences are minimal.
! 189: * We fold this model in the 8-level spl model this port uses, enforcing
! 190: * priorities manually with the interrupt masks.
! 191: */
! 192:
! 193: /*
! 194: * Copy of the interrupt enable register for each CPU.
! 195: * Note that, on the AV400 design, the interrupt enable registers are
! 196: * write-only and read back as 0xffffffff.
! 197: */
! 198: unsigned int int_mask_reg[] = { 0, 0, 0, 0 };
! 199:
! 200: u_int av400_curspl[] = { 0, 0, 0, 0 };
! 201:
! 202: /*
! 203: * external interrupt masks per spl.
! 204: */
! 205: const unsigned int int_mask_val[INT_LEVEL] = {
! 206: MASK_LVL_0,
! 207: MASK_LVL_1,
! 208: MASK_LVL_2,
! 209: MASK_LVL_3,
! 210: MASK_LVL_4,
! 211: MASK_LVL_5,
! 212: MASK_LVL_6,
! 213: MASK_LVL_7
! 214: };
! 215:
! 216: /*
! 217: * Figure out how much memory is available, by asking the PROM.
! 218: */
! 219: vaddr_t
! 220: av400_memsize()
! 221: {
! 222: vaddr_t memsize;
! 223:
! 224: memsize = scm_memsize(1);
! 225:
! 226: /*
! 227: * What we got is the ``top of memory'', i.e. the largest addressable
! 228: * word address, ending in 0xffc. Round up to a multiple of a page.
! 229: */
! 230: memsize = round_page(memsize);
! 231:
! 232: return (memsize);
! 233: }
! 234:
! 235: void
! 236: av400_startup()
! 237: {
! 238: }
! 239:
! 240: int32_t cpuid, sysid;
! 241:
! 242: void
! 243: av400_bootstrap()
! 244: {
! 245: extern struct cmmu_p cmmu8820x;
! 246: extern u_char hostaddr[6];
! 247:
! 248: /*
! 249: * These are the fixed assignments on AV400 designs.
! 250: */
! 251: cmmu = &cmmu8820x;
! 252: m8820x_cmmu[0].cmmu_regs = (void *)AV400_CMMU_I0;
! 253: m8820x_cmmu[1].cmmu_regs = (void *)AV400_CMMU_D0;
! 254: m8820x_cmmu[2].cmmu_regs = (void *)AV400_CMMU_I1;
! 255: m8820x_cmmu[3].cmmu_regs = (void *)AV400_CMMU_D1;
! 256: m8820x_cmmu[4].cmmu_regs = (void *)AV400_CMMU_I2;
! 257: m8820x_cmmu[5].cmmu_regs = (void *)AV400_CMMU_D2;
! 258: m8820x_cmmu[6].cmmu_regs = (void *)AV400_CMMU_I3;
! 259: m8820x_cmmu[7].cmmu_regs = (void *)AV400_CMMU_D3;
! 260:
! 261: /* clear and disable all interrupts */
! 262: *(volatile u_int32_t *)AV_IENALL = 0;
! 263:
! 264: /*
! 265: * Get all the information we'll need later from the PROM, while
! 266: * we can still use it.
! 267: */
! 268: scm_getenaddr(hostaddr);
! 269: cpuid = scm_cpuid();
! 270: sysid = scm_sysid();
! 271: }
! 272:
! 273: /*
! 274: * return next safe spl to reenable interrupts.
! 275: */
! 276: u_int
! 277: safe_level(u_int mask, u_int curlevel)
! 278: {
! 279: int i;
! 280:
! 281: for (i = curlevel; i < INT_LEVEL; i++)
! 282: if ((int_mask_val[i] & mask) == 0)
! 283: return i;
! 284:
! 285: return (INT_LEVEL - 1);
! 286: }
! 287:
! 288: u_int
! 289: av400_getipl(void)
! 290: {
! 291: return av400_curspl[cpu_number()];
! 292: }
! 293:
! 294: u_int
! 295: av400_setipl(u_int level)
! 296: {
! 297: u_int32_t mask, curspl;
! 298: u_int cpu = cpu_number();
! 299:
! 300: curspl = av400_curspl[cpu];
! 301:
! 302: mask = int_mask_val[level];
! 303: #ifdef MULTIPROCESSOR
! 304: if (cpu != master_cpu)
! 305: mask &= ~SLAVE_MASK;
! 306: #endif
! 307:
! 308: *(u_int32_t *)AV_IEN(cpu) = int_mask_reg[cpu] = mask;
! 309: av400_curspl[cpu] = level;
! 310:
! 311: return curspl;
! 312: }
! 313:
! 314: u_int
! 315: av400_raiseipl(u_int level)
! 316: {
! 317: u_int32_t mask, curspl;
! 318: u_int cpu = cpu_number();
! 319:
! 320: curspl = av400_curspl[cpu];
! 321: if (curspl < level) {
! 322: mask = int_mask_val[level];
! 323: #ifdef MULTIPROCESSOR
! 324: if (cpu != master_cpu)
! 325: mask &= ~SLAVE_MASK;
! 326: #endif
! 327:
! 328: *(u_int32_t *)AV_IEN(cpu) = int_mask_reg[cpu] = mask;
! 329: av400_curspl[cpu] = level;
! 330: }
! 331: return curspl;
! 332: }
! 333:
! 334: /*
! 335: * Device interrupt handler for AV400
! 336: */
! 337:
! 338: /*
! 339: * Hard coded vector table for onboard devices and hardware failure
! 340: * interrupts.
! 341: */
! 342: const unsigned int obio_vec[32] = {
! 343: 0, /* SWI0 */
! 344: 0, /* SWI1 */
! 345: 0,
! 346: 0,
! 347: 0, /* VME1 */
! 348: SYSCV_SCSI, /* SCI */
! 349: 0, /* VME2 */
! 350: 0,
! 351: 0,
! 352: 0, /* DVB */
! 353: 0, /* VME3 */
! 354: 0, /* DWP */
! 355: 0, /* VME4 */
! 356: 0, /* DTC */
! 357: 0, /* VME5 */
! 358: SYSCV_LE, /* ECI */
! 359: SYSCV_SCC2, /* DI2 */
! 360: SYSCV_SCC, /* DI1 */
! 361: 0, /* PPI */
! 362: 0, /* VME6 */
! 363: SYSCV_SYSF, /* SF */
! 364: SYSCV_TIMER2, /* CIOI */
! 365: 0, /* KBD */
! 366: 0, /* VME7 */
! 367: 0, /* PAR */
! 368: 0, /* VID */
! 369: 0, /* ZBUF */
! 370: 0,
! 371: 0,
! 372: 0, /* ARBTO */ /* no vector, but always masked */
! 373: SYSCV_ACF, /* ACF */
! 374: SYSCV_ABRT /* ABORT */
! 375: };
! 376:
! 377: #define VME_VECTOR_MASK 0x1ff /* mask into VIACK register */
! 378: #define VME_BERR_MASK 0x100 /* timeout during VME IACK cycle */
! 379:
! 380: void
! 381: av400_intr(u_int v, struct trapframe *eframe)
! 382: {
! 383: int cpu = cpu_number();
! 384: unsigned int cur_mask, ign_mask;
! 385: unsigned int level, old_spl;
! 386: struct intrhand *intr;
! 387: intrhand_t *list;
! 388: int ret, intbit;
! 389: vaddr_t ivec;
! 390: u_int vec;
! 391: int unmasked = 0;
! 392: #ifdef DIAGNOSTIC
! 393: static int problems = 0;
! 394: #endif
! 395:
! 396: cur_mask = ISR_GET_CURRENT_MASK(cpu);
! 397: ign_mask = 0;
! 398: old_spl = av400_curspl[cpu];
! 399: eframe->tf_mask = old_spl;
! 400:
! 401: if (cur_mask == 0) {
! 402: /*
! 403: * Spurious interrupts - may be caused by debug output clearing
! 404: * DUART interrupts.
! 405: */
! 406: flush_pipeline();
! 407: goto out;
! 408: }
! 409:
! 410: uvmexp.intrs++;
! 411:
! 412: /*
! 413: * We want to service all interrupts marked in the IST register
! 414: * They are all valid because the mask would have prevented them
! 415: * from being generated otherwise. We will service them in order of
! 416: * priority.
! 417: */
! 418: do {
! 419: level = safe_level(cur_mask, old_spl);
! 420: setipl(level);
! 421:
! 422: /*
! 423: * Do not enable interrupts yet if we know, from cur_mask,
! 424: * that we have not cleared enough conditions yet.
! 425: * For now, only the timer interrupt requires its condition
! 426: * to be cleared before interrupts are enabled.
! 427: */
! 428: if (unmasked == 0 /* && (cur_mask & whatever) == 0 */) {
! 429: set_psr(get_psr() & ~PSR_IND);
! 430: unmasked = 1;
! 431: }
! 432:
! 433: /* find the first bit set in the current mask */
! 434: intbit = ff1(cur_mask);
! 435: if (OBIO_INTERRUPT_MASK & (1 << intbit)) {
! 436: vec = obio_vec[intbit];
! 437: if (vec == 0) {
! 438: panic("unknown onboard interrupt: mask = 0x%b",
! 439: 1 << intbit, IST_STRING);
! 440: }
! 441: vec += SYSCON_VECT;
! 442: } else if (HW_FAILURE_MASK & (1 << intbit)) {
! 443: vec = obio_vec[intbit];
! 444: if (vec == 0) {
! 445: panic("unknown hardware failure: mask = 0x%b",
! 446: 1 << intbit, IST_STRING);
! 447: }
! 448: vec += SYSCON_VECT;
! 449: } else if (VME_INTERRUPT_MASK & (1 << intbit)) {
! 450: ivec = AV400_VIRQLV + (level << 2);
! 451: vec = *(volatile u_int32_t *)ivec & VME_VECTOR_MASK;
! 452: if (vec & VME_BERR_MASK) {
! 453: printf("%s: timeout getting VME "
! 454: "interrupt vector, "
! 455: "level %d, mask 0x%b\n",
! 456: __func__, level,
! 457: cur_mask, IST_STRING);
! 458: ign_mask |= 1 << intbit;
! 459: continue;
! 460: }
! 461: if (vec == 0) {
! 462: panic("%s: invalid VME interrupt vector, "
! 463: "level %d, mask 0x%b",
! 464: __func__, level, cur_mask, IST_STRING);
! 465: }
! 466: } else {
! 467: panic("%s: unexpected interrupt source, "
! 468: "level %d, mask 0x%b",
! 469: __func__, level, cur_mask, IST_STRING);
! 470: }
! 471:
! 472: list = &intr_handlers[vec];
! 473: if (SLIST_EMPTY(list)) {
! 474: printf("%s: spurious interrupt, "
! 475: "level %d, vec 0x%x, mask 0x%b\n",
! 476: __func__, level, vec, cur_mask, IST_STRING);
! 477: ign_mask |= 1 << intbit;
! 478: } else {
! 479: /*
! 480: * Walk through all interrupt handlers in the chain
! 481: * for the given vector, calling each handler in turn,
! 482: * till some handler returns a value != 0.
! 483: */
! 484: ret = 0;
! 485: SLIST_FOREACH(intr, list, ih_link) {
! 486: if (intr->ih_wantframe != 0)
! 487: ret = (*intr->ih_fn)((void *)eframe);
! 488: else
! 489: ret = (*intr->ih_fn)(intr->ih_arg);
! 490: if (ret != 0) {
! 491: intr->ih_count.ec_count++;
! 492: break;
! 493: }
! 494: }
! 495: if (ret == 0) {
! 496: panic("%s: unclaimed interrupt, "
! 497: "level %d, vec %x, mask 0x%b"
! 498: __func__, level, vec, cur_mask, IST_STRING);
! 499: ign_mask |= 1 << intbit;
! 500: break;
! 501: }
! 502: }
! 503: } while (((cur_mask = ISR_GET_CURRENT_MASK(cpu)) & ~ign_mask) != 0);
! 504:
! 505: #ifdef DIAGNOSTIC
! 506: if (ign_mask != 0) {
! 507: if (++problems >= 10)
! 508: panic("%s: broken interrupt behaviour", __func__);
! 509: } else
! 510: problems = 0;
! 511: #endif
! 512:
! 513: out:
! 514: /*
! 515: * process any remaining data access exceptions before
! 516: * returning to assembler
! 517: */
! 518: if (eframe->tf_dmt0 & DMT_VALID)
! 519: m88100_trap(T_DATAFLT, eframe);
! 520:
! 521: /*
! 522: * Disable interrupts before returning to assembler, the spl will
! 523: * be restored later.
! 524: */
! 525: set_psr(get_psr() | PSR_IND);
! 526: }
! 527:
! 528: /*
! 529: * Clock routines
! 530: */
! 531:
! 532: void av400_cio_init(unsigned);
! 533: u_int read_cio(int);
! 534: void write_cio(int, u_int);
! 535:
! 536: struct intrhand clock_ih;
! 537:
! 538: int av400_clockintr(void *);
! 539:
! 540: struct simplelock av400_cio_lock;
! 541:
! 542: #define CIO_LOCK simple_lock(&av400_cio_lock)
! 543: #define CIO_UNLOCK simple_unlock(&av400_cio_lock)
! 544:
! 545: /*
! 546: * Statistics clock interval and variance, in usec. Variance must be a
! 547: * power of two. Since this gives us an even number, not an odd number,
! 548: * we discard one case and compensate. That is, a variance of 4096 would
! 549: * give us offsets in [0..4095]. Instead, we take offsets in [1..4095].
! 550: * This is symmetric about the point 2048, or statvar/2, and thus averages
! 551: * to that value (assuming uniform random numbers).
! 552: */
! 553: int statvar = 8192;
! 554: int statmin; /* statclock interval - 1/2*variance */
! 555:
! 556: /*
! 557: * Notes on the AV400 clock usage:
! 558: *
! 559: * Unlike the MVME188 design, we only have access to three counter/timers
! 560: * in the Zilog Z8536 (since we can not receive the DUART timer interrupts).
! 561: *
! 562: * Clock is run on a Z8536 counter, kept in counter mode and retriggered
! 563: * every interrupt (when using the Z8536 in timer mode, it _seems_ that it
! 564: * resets at 0xffff instead of the initial count value...)
! 565: *
! 566: * It should be possible to run statclock on the Z8536 counter #2, but
! 567: * this would make interrupt handling more tricky, in the case both
! 568: * counters interrupt at the same time...
! 569: */
! 570:
! 571: void
! 572: av400_init_clocks(void)
! 573: {
! 574:
! 575: simple_lock_init(&av400_cio_lock);
! 576:
! 577: #ifdef DIAGNOSTIC
! 578: if (1000000 % hz) {
! 579: printf("cannot get %d Hz clock; using 100 Hz\n", hz);
! 580: hz = 100;
! 581: }
! 582: #endif
! 583: tick = 1000000 / hz;
! 584:
! 585: av400_cio_init(tick);
! 586:
! 587: stathz = 0;
! 588:
! 589: clock_ih.ih_fn = av400_clockintr;
! 590: clock_ih.ih_arg = 0;
! 591: clock_ih.ih_wantframe = 1;
! 592: clock_ih.ih_ipl = IPL_CLOCK;
! 593: sysconintr_establish(SYSCV_TIMER2, &clock_ih, "clock");
! 594: }
! 595:
! 596: int
! 597: av400_clockintr(void *eframe)
! 598: {
! 599: CIO_LOCK;
! 600: write_cio(CIO_CSR1, CIO_GCB | CIO_CIP); /* Ack the interrupt */
! 601:
! 602: hardclock(eframe);
! 603:
! 604: /* restart counter */
! 605: write_cio(CIO_CSR1, CIO_GCB | CIO_TCB | CIO_IE);
! 606: CIO_UNLOCK;
! 607:
! 608: return (1);
! 609: }
! 610:
! 611: /* Write CIO register */
! 612: void
! 613: write_cio(int reg, u_int val)
! 614: {
! 615: int s;
! 616: volatile int i;
! 617: volatile u_int32_t * cio_ctrl = (volatile u_int32_t *)CIO_CTRL;
! 618:
! 619: s = splclock();
! 620: CIO_LOCK;
! 621:
! 622: i = *cio_ctrl; /* goto state 1 */
! 623: *cio_ctrl = 0; /* take CIO out of RESET */
! 624: i = *cio_ctrl; /* reset CIO state machine */
! 625:
! 626: *cio_ctrl = (reg & 0xff); /* select register */
! 627: *cio_ctrl = (val & 0xff); /* write the value */
! 628:
! 629: CIO_UNLOCK;
! 630: splx(s);
! 631: }
! 632:
! 633: /* Read CIO register */
! 634: u_int
! 635: read_cio(int reg)
! 636: {
! 637: int c, s;
! 638: volatile int i;
! 639: volatile u_int32_t * cio_ctrl = (volatile u_int32_t *)CIO_CTRL;
! 640:
! 641: s = splclock();
! 642: CIO_LOCK;
! 643:
! 644: /* select register */
! 645: *cio_ctrl = (reg & 0xff);
! 646: /* delay for a short time to allow 8536 to settle */
! 647: for (i = 0; i < 100; i++)
! 648: ;
! 649: /* read the value */
! 650: c = *cio_ctrl;
! 651: CIO_UNLOCK;
! 652: splx(s);
! 653: return (c & 0xff);
! 654: }
! 655:
! 656: /*
! 657: * Initialize the CTC (8536)
! 658: * Only the counter/timers are used - the IO ports are un-comitted.
! 659: */
! 660: void
! 661: av400_cio_init(unsigned period)
! 662: {
! 663: volatile int i;
! 664:
! 665: CIO_LOCK;
! 666:
! 667: /* Start by forcing chip into known state */
! 668: read_cio(CIO_MICR);
! 669: write_cio(CIO_MICR, CIO_MICR_RESET); /* Reset the CTC */
! 670: for (i = 0; i < 1000; i++) /* Loop to delay */
! 671: ;
! 672:
! 673: /* Clear reset and start init seq. */
! 674: write_cio(CIO_MICR, 0x00);
! 675:
! 676: /* Wait for chip to come ready */
! 677: while ((read_cio(CIO_MICR) & CIO_MICR_RJA) == 0)
! 678: ;
! 679:
! 680: /* Initialize the 8536 for real */
! 681: write_cio(CIO_MICR,
! 682: CIO_MICR_MIE /* | CIO_MICR_NV */ | CIO_MICR_RJA | CIO_MICR_DLC);
! 683: write_cio(CIO_CTMS1, CIO_CTMS_CSC); /* Continuous count */
! 684: write_cio(CIO_PDCB, 0xff); /* set port B to input */
! 685:
! 686: period <<= 1; /* CT#1 runs at PCLK/2, hence 2MHz */
! 687: write_cio(CIO_CT1MSB, period >> 8);
! 688: write_cio(CIO_CT1LSB, period);
! 689: /* enable counter #1 */
! 690: write_cio(CIO_MCCR, CIO_MCCR_CT1E | CIO_MCCR_PBE);
! 691: write_cio(CIO_CSR1, CIO_GCB | CIO_TCB | CIO_IE);
! 692:
! 693: CIO_UNLOCK;
! 694: }
CVSweb