Annotation of sys/arch/mac68k/mac68k/psc.c, Revision 1.1
1.1 ! nbrk 1: /* $OpenBSD: psc.c,v 1.6 2004/12/14 14:50:55 martin Exp $ */
! 2: /* $NetBSD: psc.c,v 1.8 2004/03/26 12:15:46 wiz Exp $ */
! 3:
! 4:
! 5: /*-
! 6: * Copyright (c) 1997 David Huang <khym@azeotrope.org>
! 7: * All rights reserved.
! 8: *
! 9: * Redistribution and use in source and binary forms, with or without
! 10: * modification, are permitted provided that the following conditions
! 11: * are met:
! 12: * 1. Redistributions of source code must retain the above copyright
! 13: * notice, this list of conditions and the following disclaimer.
! 14: * 2. The name of the author may not be used to endorse or promote products
! 15: * derived from this software without specific prior written permission
! 16: *
! 17: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
! 18: * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
! 19: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
! 20: * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
! 21: * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
! 22: * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
! 23: * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
! 24: * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
! 25: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
! 26: * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
! 27: *
! 28: */
! 29:
! 30: /*
! 31: * This handles registration/unregistration of PSC (Peripheral
! 32: * Subsystem Controller) interrupts. The PSC is used only on the
! 33: * Centris/Quadra 660av and the Quadra 840av.
! 34: */
! 35:
! 36: #include <sys/param.h>
! 37: #include <sys/systm.h>
! 38:
! 39: #include <machine/bus.h>
! 40: #include <machine/cpu.h>
! 41: #include <machine/psc.h>
! 42:
! 43: static void psc_kill_dma(void);
! 44: int psc_lev3_intr(void *);
! 45: static void psc_lev3_noint(void *);
! 46: int psc_lev4_intr(void *);
! 47: static int psc_lev4_noint(void *);
! 48: int psc_lev5_intr(void *);
! 49: static void psc_lev5_noint(void *);
! 50: int psc_lev6_intr(void *);
! 51: static void psc_lev6_noint(void *);
! 52:
! 53: void (*psc3_ihandler)(void *) = psc_lev3_noint;
! 54: void *psc3_iarg;
! 55:
! 56: int (*psc4_itab[4])(void *) = {
! 57: psc_lev4_noint, /* 0 */
! 58: psc_lev4_noint, /* 1 */
! 59: psc_lev4_noint, /* 2 */
! 60: psc_lev4_noint /* 3 */
! 61: };
! 62:
! 63: void *psc4_iarg[4] = {
! 64: (void *)0, (void *)1, (void *)2, (void *)3
! 65: };
! 66:
! 67: void (*psc5_itab[2])(void *) = {
! 68: psc_lev5_noint, /* 0 */
! 69: psc_lev5_noint /* 1 */
! 70: };
! 71:
! 72: void *psc5_iarg[2] = {
! 73: (void *)0, (void *)1
! 74: };
! 75:
! 76: void (*psc6_itab[3])(void *) = {
! 77: psc_lev6_noint, /* 0 */
! 78: psc_lev6_noint, /* 1 */
! 79: psc_lev6_noint /* 2 */
! 80: };
! 81:
! 82: void *psc6_iarg[3] = {
! 83: (void *)0, (void *)1, (void *)2
! 84: };
! 85:
! 86: /*
! 87: * Make excessively sure that all PSC DMA is shut down.
! 88: */
! 89: void
! 90: psc_kill_dma()
! 91: {
! 92: int i;
! 93:
! 94: for (i = 0; i < 9; i++) {
! 95: psc_reg2(PSC_CTLBASE + (i << 4)) = 0x8800;
! 96: psc_reg2(PSC_CTLBASE + (i << 4)) = 0x1000;
! 97: psc_reg2(PSC_CMDBASE + (i << 5)) = 0x1100;
! 98: psc_reg2(PSC_CMDBASE + (i << 5) + PSC_SET1) = 0x1100;
! 99: }
! 100: }
! 101:
! 102: /*
! 103: * Setup the interrupt vectors and disable most of the PSC interrupts
! 104: */
! 105: void
! 106: psc_init()
! 107: {
! 108: int s, i;
! 109:
! 110: /*
! 111: * Only Quadra AVs have a PSC.
! 112: */
! 113: if (current_mac_model->class == MACH_CLASSAV) {
! 114: s = splhigh();
! 115: psc_kill_dma();
! 116: intr_establish(psc_lev3_intr, NULL, 3, "psc");
! 117: intr_establish(psc_lev4_intr, NULL, 4, "psc");
! 118: intr_establish(psc_lev5_intr, NULL, 5, "psc");
! 119: intr_establish(psc_lev6_intr, NULL, 6, "psc");
! 120: for (i = 3; i < 7; i++) {
! 121: /* Clear any flags */
! 122: psc_reg1(PSC_ISR_BASE + 0x10 * i) = 0x0F;
! 123: /* Clear any interrupt enable */
! 124: psc_reg1(PSC_IER_BASE + 0x10 * i) = 0x0F;
! 125: }
! 126: psc_reg1(PSC_LEV4_IER) = 0x86; /* enable SCC */
! 127: splx(s);
! 128: }
! 129: }
! 130:
! 131: int
! 132: add_psc_lev3_intr(handler, arg)
! 133: void (*handler)(void *);
! 134: void *arg;
! 135: {
! 136: int s;
! 137:
! 138: s = splhigh();
! 139:
! 140: psc3_ihandler = handler;
! 141: psc3_iarg = arg;
! 142:
! 143: splx(s);
! 144:
! 145: return 1;
! 146: }
! 147:
! 148: int
! 149: remove_psc_lev3_intr()
! 150: {
! 151: return add_psc_lev3_intr(psc_lev3_noint, (void *)0);
! 152: }
! 153:
! 154: int
! 155: psc_lev3_intr(arg)
! 156: void *arg;
! 157: {
! 158: u_int8_t intbits;
! 159:
! 160: while ((intbits = psc_reg1(PSC_LEV3_ISR)) != psc_reg1(PSC_LEV3_ISR))
! 161: ;
! 162: intbits &= 0x1 & psc_reg1(PSC_LEV3_IER);
! 163:
! 164: if (intbits)
! 165: psc3_ihandler(psc3_iarg);
! 166:
! 167: return 0;
! 168: }
! 169:
! 170: static void
! 171: psc_lev3_noint(arg)
! 172: void *arg;
! 173: {
! 174: #ifdef DEBUG
! 175: printf("psc_lev3_noint\n");
! 176: #endif
! 177: }
! 178:
! 179: int
! 180: psc_lev4_intr(arg)
! 181: void * arg;
! 182: {
! 183: u_int8_t intbits, bitnum;
! 184: u_int mask;
! 185:
! 186: while ((intbits = psc_reg1(PSC_LEV4_ISR)) != psc_reg1(PSC_LEV4_ISR))
! 187: ;
! 188: intbits &= 0xf & psc_reg1(PSC_LEV4_IER);
! 189:
! 190: mask = 1;
! 191: bitnum = 0;
! 192: do {
! 193: if (intbits & mask)
! 194: psc4_itab[bitnum](psc4_iarg[bitnum]);
! 195: mask <<= 1;
! 196: } while (intbits >= mask && ++bitnum);
! 197:
! 198: return 0;
! 199: }
! 200:
! 201: int
! 202: add_psc_lev4_intr(dev, handler, arg)
! 203: int dev;
! 204: int (*handler)(void *);
! 205: void *arg;
! 206: {
! 207: int s;
! 208:
! 209: if ((dev < 0) || (dev > 3))
! 210: return 0;
! 211:
! 212: s = splhigh();
! 213:
! 214: psc4_itab[dev] = handler;
! 215: psc4_iarg[dev] = arg;
! 216:
! 217: splx(s);
! 218:
! 219: return 1;
! 220: }
! 221:
! 222: int
! 223: remove_psc_lev4_intr(dev)
! 224: int dev;
! 225: {
! 226: return add_psc_lev4_intr(dev, psc_lev4_noint, (void *)dev);
! 227: }
! 228:
! 229: int
! 230: psc_lev4_noint(arg)
! 231: void *arg;
! 232: {
! 233: #ifdef DEBUG
! 234: printf("psc_lev4_noint: device %d\n", (int)arg);
! 235: #endif
! 236: return 0;
! 237: }
! 238:
! 239: int
! 240: psc_lev5_intr(arg)
! 241: void *arg;
! 242: {
! 243: u_int8_t intbits, bitnum;
! 244: u_int mask;
! 245:
! 246: while ((intbits = psc_reg1(PSC_LEV5_ISR)) != psc_reg1(PSC_LEV5_ISR))
! 247: ;
! 248: intbits &= 0x3 & psc_reg1(PSC_LEV5_IER);
! 249:
! 250: mask = 1;
! 251: bitnum = 0;
! 252: do {
! 253: if (intbits & mask)
! 254: psc5_itab[bitnum](psc5_iarg[bitnum]);
! 255: mask <<= 1;
! 256: } while (intbits >= mask && ++bitnum);
! 257:
! 258: return 0;
! 259: }
! 260:
! 261: int
! 262: add_psc_lev5_intr(dev, handler, arg)
! 263: int dev;
! 264: void (*handler)(void *);
! 265: void *arg;
! 266: {
! 267: int s;
! 268:
! 269: if ((dev < 0) || (dev > 1))
! 270: return 0;
! 271:
! 272: s = splhigh();
! 273:
! 274: psc5_itab[dev] = handler;
! 275: psc5_iarg[dev] = arg;
! 276:
! 277: splx(s);
! 278:
! 279: return 1;
! 280: }
! 281:
! 282: int
! 283: remove_psc_lev5_intr(dev)
! 284: int dev;
! 285: {
! 286: return add_psc_lev5_intr(dev, psc_lev5_noint, (void *)dev);
! 287: }
! 288:
! 289: void
! 290: psc_lev5_noint(arg)
! 291: void *arg;
! 292: {
! 293: #ifdef DEBUG
! 294: printf("psc_lev5_noint: device %d\n", (int)arg);
! 295: #endif
! 296: }
! 297:
! 298: int
! 299: psc_lev6_intr(arg)
! 300: void *arg;
! 301: {
! 302: u_int8_t intbits, bitnum;
! 303: u_int mask;
! 304:
! 305: while ((intbits = psc_reg1(PSC_LEV6_ISR)) != psc_reg1(PSC_LEV6_ISR))
! 306: ;
! 307: intbits &= 0x7 & psc_reg1(PSC_LEV6_IER);
! 308:
! 309: mask = 1;
! 310: bitnum = 0;
! 311: do {
! 312: if (intbits & mask)
! 313: psc6_itab[bitnum](psc6_iarg[bitnum]);
! 314: mask <<= 1;
! 315: } while (intbits >= mask && ++bitnum);
! 316:
! 317: return 0;
! 318: }
! 319:
! 320: int
! 321: add_psc_lev6_intr(dev, handler, arg)
! 322: int dev;
! 323: void (*handler)(void *);
! 324: void *arg;
! 325: {
! 326: int s;
! 327:
! 328: if ((dev < 0) || (dev > 2))
! 329: return 0;
! 330:
! 331: s = splhigh();
! 332:
! 333: psc6_itab[dev] = handler;
! 334: psc6_iarg[dev] = arg;
! 335:
! 336: splx(s);
! 337:
! 338: return 1;
! 339: }
! 340:
! 341: int
! 342: remove_psc_lev6_intr(dev)
! 343: int dev;
! 344: {
! 345: return add_psc_lev6_intr(dev, psc_lev6_noint, (void *)dev);
! 346: }
! 347:
! 348: void
! 349: psc_lev6_noint(arg)
! 350: void *arg;
! 351: {
! 352: #ifdef DEBUG
! 353: printf("psc_lev6_noint: device %d\n", (int)arg);
! 354: #endif
! 355: }
CVSweb