Annotation of sys/arch/macppc/dev/openpic.c, Revision 1.1
1.1 ! nbrk 1: /* $OpenBSD: openpic.c,v 1.40 2007/05/29 18:10:43 miod Exp $ */
! 2:
! 3: /*-
! 4: * Copyright (c) 1995 Per Fogelstrom
! 5: * Copyright (c) 1993, 1994 Charles M. Hannum.
! 6: * Copyright (c) 1990 The Regents of the University of California.
! 7: * All rights reserved.
! 8: *
! 9: * This code is derived from software contributed to Berkeley by
! 10: * William Jolitz and Don Ahn.
! 11: *
! 12: * Redistribution and use in source and binary forms, with or without
! 13: * modification, are permitted provided that the following conditions
! 14: * are met:
! 15: * 1. Redistributions of source code must retain the above copyright
! 16: * notice, this list of conditions and the following disclaimer.
! 17: * 2. Redistributions in binary form must reproduce the above copyright
! 18: * notice, this list of conditions and the following disclaimer in the
! 19: * documentation and/or other materials provided with the distribution.
! 20: * 3. Neither the name of the University nor the names of its contributors
! 21: * may be used to endorse or promote products derived from this software
! 22: * without specific prior written permission.
! 23: *
! 24: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
! 25: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
! 26: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
! 27: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
! 28: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
! 29: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
! 30: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
! 31: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
! 32: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
! 33: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
! 34: * SUCH DAMAGE.
! 35: *
! 36: * @(#)isa.c 7.2 (Berkeley) 5/12/91
! 37: */
! 38:
! 39: #include <sys/param.h>
! 40: #include <sys/device.h>
! 41: #include <sys/ioctl.h>
! 42: #include <sys/mbuf.h>
! 43: #include <sys/socket.h>
! 44: #include <sys/systm.h>
! 45:
! 46: #include <uvm/uvm.h>
! 47: #include <ddb/db_var.h>
! 48:
! 49: #include <machine/atomic.h>
! 50: #include <machine/autoconf.h>
! 51: #include <machine/intr.h>
! 52: #include <machine/psl.h>
! 53: #include <machine/pio.h>
! 54: #include <machine/powerpc.h>
! 55: #include <macppc/dev/openpicreg.h>
! 56: #include <dev/ofw/openfirm.h>
! 57:
! 58: #define ICU_LEN 128
! 59: #define LEGAL_IRQ(x) ((x >= 0) && (x < ICU_LEN))
! 60:
! 61: int o_intrtype[ICU_LEN], o_intrmask[ICU_LEN], o_intrlevel[ICU_LEN];
! 62: struct intrhand *o_intrhand[ICU_LEN] = { 0 };
! 63: int o_hwirq[ICU_LEN], o_virq[ICU_LEN];
! 64: unsigned int imen_o = 0xffffffff;
! 65: int o_virq_max;
! 66:
! 67: static int fakeintr(void *);
! 68: static char *intr_typename(int type);
! 69: static void intr_calculatemasks(void);
! 70: static __inline int cntlzw(int x);
! 71: static int mapirq(int irq);
! 72: int openpic_prog_button(void *arg);
! 73: void openpic_enable_irq_mask(int irq_mask);
! 74:
! 75: #define HWIRQ_MAX 27
! 76: #define HWIRQ_MASK 0x0fffffff
! 77:
! 78: static __inline u_int openpic_read(int);
! 79: static __inline void openpic_write(int, u_int);
! 80: void openpic_set_enable_irq(int, int);
! 81: void openpic_enable_irq(int);
! 82: void openpic_disable_irq(int);
! 83: void openpic_init(void);
! 84: void openpic_set_priority(int, int);
! 85: static __inline int openpic_read_irq(int);
! 86: static __inline void openpic_eoi(int);
! 87:
! 88: struct openpic_softc {
! 89: struct device sc_dev;
! 90: };
! 91:
! 92: int openpic_match(struct device *parent, void *cf, void *aux);
! 93: void openpic_attach(struct device *, struct device *, void *);
! 94: void openpic_do_pending_int(void);
! 95: void openpic_collect_preconf_intr(void);
! 96: void ext_intr_openpic(void);
! 97:
! 98: struct cfattach openpic_ca = {
! 99: sizeof(struct openpic_softc),
! 100: openpic_match,
! 101: openpic_attach
! 102: };
! 103:
! 104: struct cfdriver openpic_cd = {
! 105: NULL, "openpic", DV_DULL
! 106: };
! 107:
! 108: int
! 109: openpic_match(struct device *parent, void *cf, void *aux)
! 110: {
! 111: char type[40];
! 112: int pirq;
! 113: struct confargs *ca = aux;
! 114:
! 115: bzero (type, sizeof(type));
! 116:
! 117: if (OF_getprop(ca->ca_node, "interrupt-parent", &pirq, sizeof(pirq))
! 118: == sizeof(pirq))
! 119: return 0; /* XXX */
! 120:
! 121: if (strcmp(ca->ca_name, "interrupt-controller") != 0 &&
! 122: strcmp(ca->ca_name, "mpic") != 0)
! 123: return 0;
! 124:
! 125: OF_getprop(ca->ca_node, "device_type", type, sizeof(type));
! 126: if (strcmp(type, "open-pic") != 0)
! 127: return 0;
! 128:
! 129: if (ca->ca_nreg < 8)
! 130: return 0;
! 131:
! 132: return 1;
! 133: }
! 134:
! 135: typedef void (void_f) (void);
! 136: extern void_f *pending_int_f;
! 137:
! 138: vaddr_t openpic_base;
! 139: void * openpic_intr_establish( void * lcv, int irq, int type, int level,
! 140: int (*ih_fun)(void *), void *ih_arg, char *name);
! 141: void openpic_intr_disestablish( void *lcp, void *arg);
! 142: void openpic_collect_preconf_intr(void);
! 143: int openpic_big_endian;
! 144:
! 145: void
! 146: openpic_attach(struct device *parent, struct device *self, void *aux)
! 147: {
! 148: struct confargs *ca = aux;
! 149: extern intr_establish_t *intr_establish_func;
! 150: extern intr_disestablish_t *intr_disestablish_func;
! 151: extern intr_establish_t *mac_intr_establish_func;
! 152: extern intr_disestablish_t *mac_intr_disestablish_func;
! 153: u_int32_t reg;
! 154:
! 155: reg = 0;
! 156: if (OF_getprop(ca->ca_node, "big-endian", ®, sizeof reg) == 0)
! 157: openpic_big_endian = 1;
! 158:
! 159: openpic_base = (vaddr_t) mapiodev (ca->ca_baseaddr +
! 160: ca->ca_reg[0], 0x40000);
! 161:
! 162: printf(": version 0x%x %s endian", openpic_read(OPENPIC_VENDOR_ID),
! 163: openpic_big_endian ? "big" : "little" );
! 164:
! 165: openpic_init();
! 166:
! 167: pending_int_f = openpic_do_pending_int;
! 168: intr_establish_func = openpic_intr_establish;
! 169: intr_disestablish_func = openpic_intr_disestablish;
! 170: mac_intr_establish_func = openpic_intr_establish;
! 171: mac_intr_disestablish_func = openpic_intr_disestablish;
! 172: install_extint(ext_intr_openpic);
! 173:
! 174: #if 1
! 175: openpic_collect_preconf_intr();
! 176: #endif
! 177:
! 178: #if 1
! 179: mac_intr_establish(parent, 0x37, IST_LEVEL,
! 180: IPL_HIGH, openpic_prog_button, (void *)0x37, "progbutton");
! 181: #endif
! 182: ppc_intr_enable(1);
! 183:
! 184: printf("\n");
! 185: }
! 186:
! 187: void
! 188: openpic_collect_preconf_intr()
! 189: {
! 190: int i;
! 191: for (i = 0; i < ppc_configed_intr_cnt; i++) {
! 192: #ifdef DEBUG
! 193: printf("\n\t%s irq %d level %d fun %x arg %x",
! 194: ppc_configed_intr[i].ih_what, ppc_configed_intr[i].ih_irq,
! 195: ppc_configed_intr[i].ih_level, ppc_configed_intr[i].ih_fun,
! 196: ppc_configed_intr[i].ih_arg);
! 197: #endif
! 198: openpic_intr_establish(NULL, ppc_configed_intr[i].ih_irq,
! 199: IST_LEVEL, ppc_configed_intr[i].ih_level,
! 200: ppc_configed_intr[i].ih_fun, ppc_configed_intr[i].ih_arg,
! 201: ppc_configed_intr[i].ih_what);
! 202: }
! 203: }
! 204:
! 205: static int
! 206: fakeintr(void *arg)
! 207: {
! 208:
! 209: return 0;
! 210: }
! 211:
! 212: /*
! 213: * Register an interrupt handler.
! 214: */
! 215: void *
! 216: openpic_intr_establish(void *lcv, int irq, int type, int level,
! 217: int (*ih_fun)(void *), void *ih_arg, char *name)
! 218: {
! 219: struct intrhand **p, *q, *ih;
! 220: static struct intrhand fakehand;
! 221:
! 222: fakehand.ih_next = NULL;
! 223: fakehand.ih_fun = fakeintr;
! 224:
! 225: #if 0
! 226: printf("mac_intr_establish, hI %d L %d ", irq, type);
! 227: #endif
! 228:
! 229: irq = mapirq(irq);
! 230: #if 0
! 231: printf("vI %d ", irq);
! 232: #endif
! 233:
! 234: /* no point in sleeping unless someone can free memory. */
! 235: ih = malloc(sizeof *ih, M_DEVBUF, cold ? M_NOWAIT : M_WAITOK);
! 236: if (ih == NULL)
! 237: panic("intr_establish: can't malloc handler info");
! 238:
! 239: if (!LEGAL_IRQ(irq) || type == IST_NONE)
! 240: panic("intr_establish: bogus irq or type");
! 241:
! 242: switch (o_intrtype[irq]) {
! 243: case IST_NONE:
! 244: o_intrtype[irq] = type;
! 245: break;
! 246: case IST_EDGE:
! 247: case IST_LEVEL:
! 248: if (type == o_intrtype[irq])
! 249: break;
! 250: case IST_PULSE:
! 251: if (type != IST_NONE)
! 252: panic("intr_establish: can't share %s with %s",
! 253: intr_typename(o_intrtype[irq]),
! 254: intr_typename(type));
! 255: break;
! 256: }
! 257:
! 258: /*
! 259: * Figure out where to put the handler.
! 260: * This is O(N^2), but we want to preserve the order, and N is
! 261: * generally small.
! 262: */
! 263: for (p = &o_intrhand[irq]; (q = *p) != NULL; p = &q->ih_next)
! 264: ;
! 265:
! 266: /*
! 267: * Actually install a fake handler momentarily, since we might be doing
! 268: * this with interrupts enabled and DON'T WANt the real routine called
! 269: * until masking is set up.
! 270: */
! 271: fakehand.ih_level = level;
! 272: *p = &fakehand;
! 273:
! 274: intr_calculatemasks();
! 275:
! 276: /*
! 277: * Poke the real handler in now.
! 278: */
! 279: ih->ih_fun = ih_fun;
! 280: ih->ih_arg = ih_arg;
! 281: ih->ih_next = NULL;
! 282: ih->ih_level = level;
! 283: ih->ih_irq = irq;
! 284: evcount_attach(&ih->ih_count, name, (void *)&o_hwirq[irq],
! 285: &evcount_intr);
! 286: *p = ih;
! 287:
! 288: return (ih);
! 289: }
! 290:
! 291: /*
! 292: * Deregister an interrupt handler.
! 293: */
! 294: void
! 295: openpic_intr_disestablish(void *lcp, void *arg)
! 296: {
! 297: struct intrhand *ih = arg;
! 298: int irq = ih->ih_irq;
! 299: struct intrhand **p, *q;
! 300:
! 301: if (!LEGAL_IRQ(irq))
! 302: panic("intr_disestablish: bogus irq");
! 303:
! 304: /*
! 305: * Remove the handler from the chain.
! 306: * This is O(n^2), too.
! 307: */
! 308: for (p = &o_intrhand[irq]; (q = *p) != NULL && q != ih; p = &q->ih_next)
! 309: ;
! 310: if (q)
! 311: *p = q->ih_next;
! 312: else
! 313: panic("intr_disestablish: handler not registered");
! 314:
! 315: evcount_detach(&ih->ih_count);
! 316: free((void *)ih, M_DEVBUF);
! 317:
! 318: intr_calculatemasks();
! 319:
! 320: if (o_intrhand[irq] == NULL)
! 321: o_intrtype[irq] = IST_NONE;
! 322: }
! 323:
! 324:
! 325: static char *
! 326: intr_typename(int type)
! 327: {
! 328:
! 329: switch (type) {
! 330: case IST_NONE:
! 331: return ("none");
! 332: case IST_PULSE:
! 333: return ("pulsed");
! 334: case IST_EDGE:
! 335: return ("edge-triggered");
! 336: case IST_LEVEL:
! 337: return ("level-triggered");
! 338: default:
! 339: panic("intr_typename: invalid type %d", type);
! 340: #if 1 /* XXX */
! 341: return ("unknown");
! 342: #endif
! 343: }
! 344: }
! 345:
! 346: /*
! 347: * Recalculate the interrupt masks from scratch.
! 348: * We could code special registry and deregistry versions of this function that
! 349: * would be faster, but the code would be nastier, and we don't expect this to
! 350: * happen very much anyway.
! 351: */
! 352: static void
! 353: intr_calculatemasks()
! 354: {
! 355: int irq, level;
! 356: struct intrhand *q;
! 357:
! 358: /* First, figure out which levels each IRQ uses. */
! 359: for (irq = 0; irq < ICU_LEN; irq++) {
! 360: register int levels = 0;
! 361: for (q = o_intrhand[irq]; q; q = q->ih_next)
! 362: levels |= 1 << q->ih_level;
! 363: o_intrlevel[irq] = levels;
! 364: }
! 365:
! 366: /* Then figure out which IRQs use each level. */
! 367: for (level = IPL_NONE; level < IPL_NUM; level++) {
! 368: register int irqs = 0;
! 369: for (irq = 0; irq < ICU_LEN; irq++)
! 370: if (o_intrlevel[irq] & (1 << level))
! 371: irqs |= 1 << irq;
! 372: imask[level] = irqs | SINT_MASK;
! 373: }
! 374:
! 375: /*
! 376: * There are tty, network and disk drivers that use free() at interrupt
! 377: * time, so vm > (tty | net | bio).
! 378: *
! 379: * Enforce a hierarchy that gives slow devices a better chance at not
! 380: * dropping data.
! 381: */
! 382: imask[IPL_NET] |= imask[IPL_BIO];
! 383: imask[IPL_TTY] |= imask[IPL_NET];
! 384: imask[IPL_VM] |= imask[IPL_TTY];
! 385: imask[IPL_CLOCK] |= imask[IPL_VM] | SPL_CLOCK;
! 386:
! 387: /*
! 388: * These are pseudo-levels.
! 389: */
! 390: imask[IPL_NONE] = 0x00000000;
! 391: imask[IPL_HIGH] = 0xffffffff;
! 392:
! 393: /* And eventually calculate the complete masks. */
! 394: for (irq = 0; irq < ICU_LEN; irq++) {
! 395: register int irqs = 1 << irq;
! 396: for (q = o_intrhand[irq]; q; q = q->ih_next)
! 397: irqs |= imask[q->ih_level];
! 398: o_intrmask[irq] = irqs | SINT_MASK;
! 399: }
! 400:
! 401: /* Lastly, determine which IRQs are actually in use. */
! 402: {
! 403: register int irqs = 0;
! 404: for (irq = 0; irq < ICU_LEN; irq++) {
! 405: if (o_intrhand[irq]) {
! 406: irqs |= 1 << irq;
! 407: openpic_enable_irq(o_hwirq[irq]);
! 408: } else {
! 409: openpic_disable_irq(o_hwirq[irq]);
! 410: }
! 411: }
! 412: imen_o = ~irqs;
! 413: }
! 414: }
! 415:
! 416: /*
! 417: * Map 64 irqs into 32 (bits).
! 418: */
! 419: static int
! 420: mapirq(int irq)
! 421: {
! 422: int v;
! 423:
! 424: /* irq in table already? */
! 425: if (o_virq[irq] != 0)
! 426: return o_virq[irq];
! 427:
! 428: if (irq < 0 || irq >= ICU_LEN)
! 429: panic("invalid irq %d", irq);
! 430:
! 431: o_virq_max++;
! 432: v = o_virq_max;
! 433: if (v > HWIRQ_MAX)
! 434: panic("virq overflow");
! 435:
! 436: o_hwirq[v] = irq;
! 437: o_virq[irq] = v;
! 438: #if 0
! 439: printf("\nmapirq %x to %x\n", irq, v);
! 440: #endif
! 441:
! 442: return v;
! 443: }
! 444:
! 445: /*
! 446: * Count leading zeros.
! 447: */
! 448: static __inline int
! 449: cntlzw(int x)
! 450: {
! 451: int a;
! 452:
! 453: __asm __volatile ("cntlzw %0,%1" : "=r"(a) : "r"(x));
! 454:
! 455: return a;
! 456: }
! 457:
! 458:
! 459: void
! 460: openpic_do_pending_int()
! 461: {
! 462: struct cpu_info *ci = curcpu();
! 463: struct intrhand *ih;
! 464: int irq;
! 465: int pcpl;
! 466: int hwpend;
! 467: int s;
! 468:
! 469: if (ci->ci_iactive)
! 470: return;
! 471:
! 472: ci->ci_iactive = 1;
! 473: pcpl = splhigh(); /* Turn off all */
! 474: s = ppc_intr_disable();
! 475:
! 476: hwpend = ci->ci_ipending & ~pcpl; /* Do now unmasked pendings */
! 477: imen_o &= ~hwpend;
! 478: openpic_enable_irq_mask(~imen_o);
! 479: hwpend &= HWIRQ_MASK;
! 480: while (hwpend) {
! 481: irq = 31 - cntlzw(hwpend);
! 482: hwpend &= ~(1L << irq);
! 483: ih = o_intrhand[irq];
! 484: while(ih) {
! 485: ppc_intr_enable(1);
! 486:
! 487: if ((*ih->ih_fun)(ih->ih_arg))
! 488: ih->ih_count.ec_count++;
! 489:
! 490: (void)ppc_intr_disable();
! 491:
! 492: ih = ih->ih_next;
! 493: }
! 494: }
! 495:
! 496: /*out32rb(INT_ENABLE_REG, ~imen_o);*/
! 497:
! 498: do {
! 499: if((ci->ci_ipending & SINT_CLOCK) & ~pcpl) {
! 500: ci->ci_ipending &= ~SINT_CLOCK;
! 501: softclock();
! 502: }
! 503: if((ci->ci_ipending & SINT_NET) & ~pcpl) {
! 504: extern int netisr;
! 505: int pisr;
! 506:
! 507: ci->ci_ipending &= ~SINT_NET;
! 508: while ((pisr = netisr) != 0) {
! 509: atomic_clearbits_int(&netisr, pisr);
! 510: softnet(pisr);
! 511: }
! 512: }
! 513: if((ci->ci_ipending & SINT_TTY) & ~pcpl) {
! 514: ci->ci_ipending &= ~SINT_TTY;
! 515: softtty();
! 516: }
! 517: } while ((ci->ci_ipending & SINT_MASK) & ~pcpl);
! 518: ci->ci_ipending &= pcpl;
! 519: ci->ci_cpl = pcpl; /* Don't use splx... we are here already! */
! 520: ppc_intr_enable(s);
! 521: ci->ci_iactive = 0;
! 522: }
! 523:
! 524: u_int
! 525: openpic_read(int reg)
! 526: {
! 527: char *addr = (void *)(openpic_base + reg);
! 528:
! 529: if (openpic_big_endian)
! 530: return in32(addr);
! 531: else
! 532: return in32rb(addr);
! 533: }
! 534:
! 535: void
! 536: openpic_write(int reg, u_int val)
! 537: {
! 538: char *addr = (void *)(openpic_base + reg);
! 539:
! 540: if (openpic_big_endian)
! 541: out32(addr, val);
! 542: else
! 543: out32rb(addr, val);
! 544: }
! 545:
! 546: void
! 547: openpic_enable_irq_mask(int irq_mask)
! 548: {
! 549: int irq;
! 550: for ( irq = 0; irq <= o_virq_max; irq++) {
! 551: if (irq_mask & (1 << irq))
! 552: openpic_enable_irq(o_hwirq[irq]);
! 553: else
! 554: openpic_disable_irq(o_hwirq[irq]);
! 555: }
! 556: }
! 557:
! 558: void
! 559: openpic_set_enable_irq(int irq, int type)
! 560: {
! 561: u_int x;
! 562:
! 563: x = openpic_read(OPENPIC_SRC_VECTOR(irq));
! 564: x &= ~(OPENPIC_IMASK|OPENPIC_SENSE_LEVEL|OPENPIC_SENSE_EDGE);
! 565: if (type == IST_LEVEL)
! 566: x |= OPENPIC_SENSE_LEVEL;
! 567: else
! 568: x |= OPENPIC_SENSE_EDGE;
! 569: openpic_write(OPENPIC_SRC_VECTOR(irq), x);
! 570: }
! 571: void
! 572: openpic_enable_irq(int irq)
! 573: {
! 574: u_int x;
! 575:
! 576: x = openpic_read(OPENPIC_SRC_VECTOR(irq));
! 577: x &= ~(OPENPIC_IMASK|OPENPIC_SENSE_LEVEL|OPENPIC_SENSE_EDGE);
! 578: if (o_intrtype[o_virq[irq]] == IST_LEVEL)
! 579: x |= OPENPIC_SENSE_LEVEL;
! 580: else
! 581: x |= OPENPIC_SENSE_EDGE;
! 582: openpic_write(OPENPIC_SRC_VECTOR(irq), x);
! 583: }
! 584:
! 585: void
! 586: openpic_disable_irq(int irq)
! 587: {
! 588: u_int x;
! 589:
! 590: x = openpic_read(OPENPIC_SRC_VECTOR(irq));
! 591: x |= OPENPIC_IMASK;
! 592: openpic_write(OPENPIC_SRC_VECTOR(irq), x);
! 593: }
! 594:
! 595: void
! 596: openpic_set_priority(int cpu, int pri)
! 597: {
! 598: u_int x;
! 599:
! 600: x = openpic_read(OPENPIC_CPU_PRIORITY(cpu));
! 601: x &= ~OPENPIC_CPU_PRIORITY_MASK;
! 602: x |= pri;
! 603: openpic_write(OPENPIC_CPU_PRIORITY(cpu), x);
! 604: }
! 605:
! 606: int
! 607: openpic_read_irq(int cpu)
! 608: {
! 609: return openpic_read(OPENPIC_IACK(cpu)) & OPENPIC_VECTOR_MASK;
! 610: }
! 611:
! 612: void
! 613: openpic_eoi(int cpu)
! 614: {
! 615: openpic_write(OPENPIC_EOI(cpu), 0);
! 616: openpic_read(OPENPIC_EOI(cpu));
! 617: }
! 618:
! 619: void
! 620: ext_intr_openpic()
! 621: {
! 622: struct cpu_info *ci = curcpu();
! 623: int irq, realirq;
! 624: int r_imen;
! 625: int pcpl, ocpl;
! 626: struct intrhand *ih;
! 627:
! 628: pcpl = ci->ci_cpl;
! 629:
! 630: realirq = openpic_read_irq(0);
! 631:
! 632: while (realirq != 255) {
! 633: irq = o_virq[realirq];
! 634:
! 635: /* XXX check range */
! 636:
! 637: r_imen = 1 << irq;
! 638:
! 639: if ((pcpl & r_imen) != 0) {
! 640: /* Masked! Mark this as pending. */
! 641: ci->ci_ipending |= r_imen;
! 642: openpic_disable_irq(realirq);
! 643: openpic_eoi(0);
! 644: } else {
! 645: openpic_disable_irq(realirq);
! 646: openpic_eoi(0);
! 647: ocpl = splraise(o_intrmask[irq]);
! 648:
! 649: ih = o_intrhand[irq];
! 650: while (ih) {
! 651: ppc_intr_enable(1);
! 652:
! 653: if ((*ih->ih_fun)(ih->ih_arg))
! 654: ih->ih_count.ec_count++;
! 655:
! 656: (void)ppc_intr_disable();
! 657: ih = ih->ih_next;
! 658: }
! 659:
! 660: uvmexp.intrs++;
! 661: __asm__ volatile("":::"memory"); /* don't reorder.... */
! 662: ci->ci_cpl = ocpl;
! 663: __asm__ volatile("":::"memory"); /* don't reorder.... */
! 664: openpic_enable_irq(realirq);
! 665: }
! 666:
! 667: realirq = openpic_read_irq(0);
! 668: }
! 669: ppc_intr_enable(1);
! 670:
! 671: splx(pcpl); /* Process pendings. */
! 672: }
! 673:
! 674: void
! 675: openpic_init()
! 676: {
! 677: int irq;
! 678: u_int x;
! 679:
! 680: /* disable all interrupts */
! 681: for (irq = 0; irq < 255; irq++)
! 682: openpic_write(OPENPIC_SRC_VECTOR(irq), OPENPIC_IMASK);
! 683: openpic_set_priority(0, 15);
! 684:
! 685: /* we don't need 8259 pass through mode */
! 686: x = openpic_read(OPENPIC_CONFIG);
! 687: x |= OPENPIC_CONFIG_8259_PASSTHRU_DISABLE;
! 688: openpic_write(OPENPIC_CONFIG, x);
! 689:
! 690: /* send all interrupts to cpu 0 */
! 691: for (irq = 0; irq < ICU_LEN; irq++)
! 692: openpic_write(OPENPIC_IDEST(irq), 1 << 0);
! 693: for (irq = 0; irq < ICU_LEN; irq++) {
! 694: x = irq;
! 695: x |= OPENPIC_IMASK;
! 696: x |= OPENPIC_POLARITY_POSITIVE;
! 697: x |= OPENPIC_SENSE_LEVEL;
! 698: x |= 8 << OPENPIC_PRIORITY_SHIFT;
! 699: openpic_write(OPENPIC_SRC_VECTOR(irq), x);
! 700: }
! 701:
! 702: /* XXX set spurious intr vector */
! 703:
! 704: openpic_set_priority(0, 0);
! 705:
! 706: /* clear all pending interrunts */
! 707: for (irq = 0; irq < ICU_LEN; irq++) {
! 708: openpic_read_irq(0);
! 709: openpic_eoi(0);
! 710: }
! 711:
! 712: for (irq = 0; irq < ICU_LEN; irq++)
! 713: openpic_disable_irq(irq);
! 714:
! 715: install_extint(ext_intr_openpic);
! 716: }
! 717:
! 718: /*
! 719: * programmer_button function to fix args to Debugger.
! 720: * deal with any enables/disables, if necessary.
! 721: */
! 722: int
! 723: openpic_prog_button (void *arg)
! 724: {
! 725: #ifdef DDB
! 726: if (db_console)
! 727: Debugger();
! 728: #else
! 729: printf("programmer button pressed, debugger not available\n");
! 730: #endif
! 731: return 1;
! 732: }
CVSweb