1 /* $OpenBSD: openpic.c,v 1.58 2009/10/01 20:19:18 kettenis 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_intrmaxlvl[ICU_LEN]; 62 struct intrhand *o_intrhand[ICU_LEN] = { 0 }; 63 int o_hwirq[ICU_LEN], o_virq[ICU_LEN]; 64 int o_virq_max; 65 66 static int fakeintr(void *); 67 static char *intr_typename(int type); 68 void openpic_calc_mask(void); 69 static __inline int cntlzw(int x); 70 static int mapirq(int irq); 71 int openpic_prog_button(void *arg); 72 void openpic_enable_irq_mask(int irq_mask); 73 74 #define HWIRQ_MAX (31 - (SI_NQUEUES + 1)) 75 #define HWIRQ_MASK (0xffffffff >> (SI_NQUEUES + 1)) 76 77 /* IRQ vector used for inter-processor interrupts. */ 78 #define IPI_VECTOR_NOP 64 79 #define IPI_VECTOR_DDB 65 80 #ifdef MULTIPROCESSOR 81 static struct evcount ipi_ddb[PPC_MAXPROCS]; 82 static struct evcount ipi_nop[PPC_MAXPROCS]; 83 static int ipi_nopirq = IPI_VECTOR_NOP; 84 static int ipi_ddbirq = IPI_VECTOR_DDB; 85 #endif 86 87 static __inline u_int openpic_read(int); 88 static __inline void openpic_write(int, u_int); 89 void openpic_set_enable_irq(int, int); 90 void openpic_enable_irq(int); 91 void openpic_disable_irq(int); 92 void openpic_init(void); 93 void openpic_set_priority(int, int); 94 void openpic_ipi_ddb(void); 95 static __inline int openpic_read_irq(int); 96 static __inline void openpic_eoi(int); 97 98 struct openpic_softc { 99 struct device sc_dev; 100 }; 101 102 int openpic_match(struct device *parent, void *cf, void *aux); 103 void openpic_attach(struct device *, struct device *, void *); 104 void openpic_do_pending_int(void); 105 void openpic_collect_preconf_intr(void); 106 void ext_intr_openpic(void); 107 108 struct cfattach openpic_ca = { 109 sizeof(struct openpic_softc), 110 openpic_match, 111 openpic_attach 112 }; 113 114 struct cfdriver openpic_cd = { 115 NULL, "openpic", DV_DULL 116 }; 117 118 int 119 openpic_match(struct device *parent, void *cf, void *aux) 120 { 121 char type[40]; 122 int pirq; 123 struct confargs *ca = aux; 124 125 bzero (type, sizeof(type)); 126 127 if (OF_getprop(ca->ca_node, "interrupt-parent", &pirq, sizeof(pirq)) 128 == sizeof(pirq)) 129 return 0; /* XXX */ 130 131 if (strcmp(ca->ca_name, "interrupt-controller") != 0 && 132 strcmp(ca->ca_name, "mpic") != 0) 133 return 0; 134 135 OF_getprop(ca->ca_node, "device_type", type, sizeof(type)); 136 if (strcmp(type, "open-pic") != 0) 137 return 0; 138 139 if (ca->ca_nreg < 8) 140 return 0; 141 142 return 1; 143 } 144 145 typedef void (void_f) (void); 146 extern void_f *pending_int_f; 147 148 vaddr_t openpic_base; 149 void * openpic_intr_establish( void * lcv, int irq, int type, int level, 150 int (*ih_fun)(void *), void *ih_arg, const char *name); 151 void openpic_intr_disestablish( void *lcp, void *arg); 152 #ifdef MULTIPROCESSOR 153 intr_send_ipi_t openpic_send_ipi; 154 #endif 155 void openpic_collect_preconf_intr(void); 156 int openpic_big_endian; 157 158 void 159 openpic_attach(struct device *parent, struct device *self, void *aux) 160 { 161 struct confargs *ca = aux; 162 u_int32_t reg; 163 164 reg = 0; 165 if (OF_getprop(ca->ca_node, "big-endian", ®, sizeof reg) == 0) 166 openpic_big_endian = 1; 167 168 openpic_base = (vaddr_t) mapiodev (ca->ca_baseaddr + 169 ca->ca_reg[0], 0x40000); 170 171 printf(": version 0x%x %s endian", openpic_read(OPENPIC_VENDOR_ID), 172 openpic_big_endian ? "big" : "little" ); 173 174 openpic_init(); 175 176 pending_int_f = openpic_do_pending_int; 177 intr_establish_func = openpic_intr_establish; 178 intr_disestablish_func = openpic_intr_disestablish; 179 mac_intr_establish_func = openpic_intr_establish; 180 mac_intr_disestablish_func = openpic_intr_disestablish; 181 #ifdef MULTIPROCESSOR 182 intr_send_ipi_func = openpic_send_ipi; 183 #endif 184 install_extint(ext_intr_openpic); 185 186 #if 1 187 openpic_collect_preconf_intr(); 188 #endif 189 190 #if 1 191 mac_intr_establish(parent, 0x37, IST_LEVEL, 192 IPL_HIGH, openpic_prog_button, (void *)0x37, "progbutton"); 193 #endif 194 195 ppc_intr_enable(1); 196 197 printf("\n"); 198 } 199 200 void 201 openpic_collect_preconf_intr() 202 { 203 int i; 204 for (i = 0; i < ppc_configed_intr_cnt; i++) { 205 #ifdef DEBUG 206 printf("\n\t%s irq %d level %d fun %x arg %x", 207 ppc_configed_intr[i].ih_what, ppc_configed_intr[i].ih_irq, 208 ppc_configed_intr[i].ih_level, ppc_configed_intr[i].ih_fun, 209 ppc_configed_intr[i].ih_arg); 210 #endif 211 openpic_intr_establish(NULL, ppc_configed_intr[i].ih_irq, 212 IST_LEVEL, ppc_configed_intr[i].ih_level, 213 ppc_configed_intr[i].ih_fun, ppc_configed_intr[i].ih_arg, 214 ppc_configed_intr[i].ih_what); 215 } 216 } 217 218 static int 219 fakeintr(void *arg) 220 { 221 222 return 0; 223 } 224 225 /* 226 * Register an interrupt handler. 227 */ 228 void * 229 openpic_intr_establish(void *lcv, int irq, int type, int level, 230 int (*ih_fun)(void *), void *ih_arg, const char *name) 231 { 232 struct intrhand **p, *q, *ih; 233 static struct intrhand fakehand; 234 235 fakehand.ih_next = NULL; 236 fakehand.ih_fun = fakeintr; 237 238 #if 0 239 printf("mac_intr_establish, hI %d L %d ", irq, type); 240 #endif 241 242 irq = mapirq(irq); 243 #if 0 244 printf("vI %d ", irq); 245 #endif 246 247 /* no point in sleeping unless someone can free memory. */ 248 ih = malloc(sizeof *ih, M_DEVBUF, cold ? M_NOWAIT : M_WAITOK); 249 if (ih == NULL) 250 panic("intr_establish: can't malloc handler info"); 251 252 if (!LEGAL_IRQ(irq) || type == IST_NONE) 253 panic("intr_establish: bogus irq or type"); 254 255 switch (o_intrtype[irq]) { 256 case IST_NONE: 257 o_intrtype[irq] = type; 258 break; 259 case IST_EDGE: 260 case IST_LEVEL: 261 if (type == o_intrtype[irq]) 262 break; 263 case IST_PULSE: 264 if (type != IST_NONE) 265 panic("intr_establish: can't share %s with %s", 266 intr_typename(o_intrtype[irq]), 267 intr_typename(type)); 268 break; 269 } 270 271 /* 272 * Figure out where to put the handler. 273 * This is O(N^2), but we want to preserve the order, and N is 274 * generally small. 275 */ 276 for (p = &o_intrhand[irq]; (q = *p) != NULL; p = &q->ih_next) 277 ; 278 279 /* 280 * Actually install a fake handler momentarily, since we might be doing 281 * this with interrupts enabled and DON'T WANt the real routine called 282 * until masking is set up. 283 */ 284 fakehand.ih_level = level; 285 *p = &fakehand; 286 287 openpic_calc_mask(); 288 289 /* 290 * Poke the real handler in now. 291 */ 292 ih->ih_fun = ih_fun; 293 ih->ih_arg = ih_arg; 294 ih->ih_next = NULL; 295 ih->ih_level = level; 296 ih->ih_irq = irq; 297 evcount_attach(&ih->ih_count, name, (void *)&o_hwirq[irq], 298 &evcount_intr); 299 *p = ih; 300 301 return (ih); 302 } 303 304 /* 305 * Deregister an interrupt handler. 306 */ 307 void 308 openpic_intr_disestablish(void *lcp, void *arg) 309 { 310 struct intrhand *ih = arg; 311 int irq = ih->ih_irq; 312 struct intrhand **p, *q; 313 314 if (!LEGAL_IRQ(irq)) 315 panic("intr_disestablish: bogus irq"); 316 317 /* 318 * Remove the handler from the chain. 319 * This is O(n^2), too. 320 */ 321 for (p = &o_intrhand[irq]; (q = *p) != NULL && q != ih; p = &q->ih_next) 322 ; 323 if (q) 324 *p = q->ih_next; 325 else 326 panic("intr_disestablish: handler not registered"); 327 328 evcount_detach(&ih->ih_count); 329 free((void *)ih, M_DEVBUF); 330 331 openpic_calc_mask(); 332 333 if (o_intrhand[irq] == NULL) 334 o_intrtype[irq] = IST_NONE; 335 } 336 337 338 static char * 339 intr_typename(int type) 340 { 341 342 switch (type) { 343 case IST_NONE: 344 return ("none"); 345 case IST_PULSE: 346 return ("pulsed"); 347 case IST_EDGE: 348 return ("edge-triggered"); 349 case IST_LEVEL: 350 return ("level-triggered"); 351 default: 352 panic("intr_typename: invalid type %d", type); 353 #if 1 /* XXX */ 354 return ("unknown"); 355 #endif 356 } 357 } 358 359 /* 360 * Recalculate the interrupt masks from scratch. 361 * We could code special registry and deregistry versions of this function that 362 * would be faster, but the code would be nastier, and we don't expect this to 363 * happen very much anyway. 364 */ 365 366 void 367 openpic_calc_mask() 368 { 369 int irq; 370 struct intrhand *ih; 371 int i; 372 373 /* disable all openpic interrupts */ 374 openpic_set_priority(0, 15); 375 376 for (irq = 0; irq < ICU_LEN; irq++) { 377 int max = IPL_NONE; 378 int min = IPL_HIGH; 379 int reg; 380 if (o_virq[irq] != 0) { 381 for (ih = o_intrhand[o_virq[irq]]; ih; 382 ih = ih->ih_next) { 383 if (ih->ih_level > max) 384 max = ih->ih_level; 385 if (ih->ih_level < min) 386 min = ih->ih_level; 387 } 388 } 389 390 o_intrmaxlvl[irq] = max; 391 392 /* adjust priority if it changes */ 393 reg = openpic_read(OPENPIC_SRC_VECTOR(irq)); 394 if (max != ((reg >> OPENPIC_PRIORITY_SHIFT) & 0xf)) { 395 openpic_write(OPENPIC_SRC_VECTOR(irq), 396 (reg & ~(0xf << OPENPIC_PRIORITY_SHIFT)) | 397 (max << OPENPIC_PRIORITY_SHIFT) ); 398 } 399 400 if (max == IPL_NONE) 401 min = IPL_NONE; /* Interrupt not enabled */ 402 403 if (o_virq[irq] != 0) { 404 /* Enable (dont mask) interrupts at lower levels */ 405 for (i = IPL_NONE; i < min; i++) 406 imask[i] &= ~(1 << o_virq[irq]); 407 for (; i <= IPL_HIGH; i++) 408 imask[i] |= (1 << o_virq[irq]); 409 } 410 } 411 412 /* restore interrupts */ 413 openpic_set_priority(0, 0); 414 415 for (i = IPL_NONE; i <= IPL_HIGH; i++) { 416 if (i > IPL_NONE) 417 imask[i] |= SINT_ALLMASK; 418 if (i >= IPL_CLOCK) 419 imask[i] |= SPL_CLOCKMASK; 420 } 421 imask[IPL_HIGH] = 0xffffffff; 422 } 423 424 /* 425 * Map 64 irqs into 32 (bits). 426 */ 427 static int 428 mapirq(int irq) 429 { 430 int v; 431 432 /* irq in table already? */ 433 if (o_virq[irq] != 0) 434 return o_virq[irq]; 435 436 if (irq < 0 || irq >= ICU_LEN) 437 panic("invalid irq %d", irq); 438 439 o_virq_max++; 440 v = o_virq_max; 441 if (v > HWIRQ_MAX) 442 panic("virq overflow"); 443 444 o_hwirq[v] = irq; 445 o_virq[irq] = v; 446 #if 0 447 printf("\nmapirq %x to %x\n", irq, v); 448 #endif 449 450 return v; 451 } 452 453 /* 454 * Count leading zeros. 455 */ 456 static __inline int 457 cntlzw(int x) 458 { 459 int a; 460 461 __asm __volatile ("cntlzw %0,%1" : "=r"(a) : "r"(x)); 462 463 return a; 464 } 465 466 void openpic_do_pending_softint(int pcpl); 467 468 void 469 openpic_do_pending_int() 470 { 471 struct cpu_info *ci = curcpu(); 472 struct intrhand *ih; 473 int irq; 474 int pcpl; 475 int hwpend; 476 int pri, pripending; 477 int s; 478 479 if (ci->ci_iactive & CI_IACTIVE_PROCESSING_HARD) 480 return; 481 482 atomic_setbits_int(&ci->ci_iactive, CI_IACTIVE_PROCESSING_HARD); 483 s = ppc_intr_disable(); 484 pcpl = ci->ci_cpl; 485 486 hwpend = ci->ci_ipending & ~pcpl; /* Do now unmasked pendings */ 487 hwpend &= HWIRQ_MASK; 488 while (hwpend) { 489 /* this still doesn't handle the interrupts in priority order */ 490 for (pri = IPL_HIGH; pri >= IPL_NONE; pri--) { 491 pripending = hwpend & ~imask[pri]; 492 if (pripending == 0) 493 continue; 494 irq = 31 - cntlzw(pripending); 495 ci->ci_ipending &= ~(1 << irq); 496 ci->ci_cpl = imask[o_intrmaxlvl[o_hwirq[irq]]]; 497 openpic_enable_irq_mask(~ci->ci_cpl); 498 ih = o_intrhand[irq]; 499 while(ih) { 500 ppc_intr_enable(1); 501 502 KERNEL_LOCK(); 503 if ((*ih->ih_fun)(ih->ih_arg)) 504 ih->ih_count.ec_count++; 505 KERNEL_UNLOCK(); 506 507 (void)ppc_intr_disable(); 508 509 ih = ih->ih_next; 510 } 511 } 512 hwpend = ci->ci_ipending & ~pcpl;/* Catch new pendings */ 513 hwpend &= HWIRQ_MASK; 514 } 515 ci->ci_cpl = pcpl | SINT_ALLMASK; 516 openpic_enable_irq_mask(~ci->ci_cpl); 517 atomic_clearbits_int(&ci->ci_iactive, CI_IACTIVE_PROCESSING_HARD); 518 519 openpic_do_pending_softint(pcpl); 520 521 ppc_intr_enable(s); 522 } 523 524 void 525 openpic_do_pending_softint(int pcpl) 526 { 527 struct cpu_info *ci = curcpu(); 528 529 if (ci->ci_iactive & CI_IACTIVE_PROCESSING_SOFT) 530 return; 531 532 atomic_setbits_int(&ci->ci_iactive, CI_IACTIVE_PROCESSING_SOFT); 533 534 do { 535 if((ci->ci_ipending & SINT_CLOCK) & ~pcpl) { 536 ci->ci_ipending &= ~SINT_CLOCK; 537 ci->ci_cpl = SINT_CLOCK|SINT_NET|SINT_TTY; 538 ppc_intr_enable(1); 539 KERNEL_LOCK(); 540 softintr_dispatch(SI_SOFTCLOCK); 541 KERNEL_UNLOCK(); 542 ppc_intr_disable(); 543 continue; 544 } 545 if((ci->ci_ipending & SINT_NET) & ~pcpl) { 546 ci->ci_ipending &= ~SINT_NET; 547 ci->ci_cpl = SINT_NET|SINT_TTY; 548 ppc_intr_enable(1); 549 KERNEL_LOCK(); 550 softintr_dispatch(SI_SOFTNET); 551 KERNEL_UNLOCK(); 552 ppc_intr_disable(); 553 continue; 554 } 555 if((ci->ci_ipending & SINT_TTY) & ~pcpl) { 556 ci->ci_ipending &= ~SINT_TTY; 557 ci->ci_cpl = SINT_TTY; 558 ppc_intr_enable(1); 559 KERNEL_LOCK(); 560 softintr_dispatch(SI_SOFTTTY); 561 KERNEL_UNLOCK(); 562 ppc_intr_disable(); 563 continue; 564 } 565 } while ((ci->ci_ipending & SINT_ALLMASK) & ~pcpl); 566 ci->ci_cpl = pcpl; /* Don't use splx... we are here already! */ 567 568 atomic_clearbits_int(&ci->ci_iactive, CI_IACTIVE_PROCESSING_SOFT); 569 } 570 571 u_int 572 openpic_read(int reg) 573 { 574 char *addr = (void *)(openpic_base + reg); 575 576 if (openpic_big_endian) 577 return in32(addr); 578 else 579 return in32rb(addr); 580 } 581 582 void 583 openpic_write(int reg, u_int val) 584 { 585 char *addr = (void *)(openpic_base + reg); 586 587 if (openpic_big_endian) 588 out32(addr, val); 589 else 590 out32rb(addr, val); 591 } 592 593 void 594 openpic_enable_irq_mask(int irq_mask) 595 { 596 int irq; 597 for ( irq = 0; irq <= o_virq_max; irq++) { 598 if (irq_mask & (1 << irq)) 599 openpic_enable_irq(o_hwirq[irq]); 600 else 601 openpic_disable_irq(o_hwirq[irq]); 602 } 603 } 604 605 void 606 openpic_set_enable_irq(int irq, int type) 607 { 608 u_int x; 609 610 x = openpic_read(OPENPIC_SRC_VECTOR(irq)); 611 x &= ~(OPENPIC_IMASK|OPENPIC_SENSE_LEVEL|OPENPIC_SENSE_EDGE); 612 if (type == IST_LEVEL) 613 x |= OPENPIC_SENSE_LEVEL; 614 else 615 x |= OPENPIC_SENSE_EDGE; 616 openpic_write(OPENPIC_SRC_VECTOR(irq), x); 617 } 618 void 619 openpic_enable_irq(int irq) 620 { 621 u_int x; 622 623 x = openpic_read(OPENPIC_SRC_VECTOR(irq)); 624 x &= ~(OPENPIC_IMASK|OPENPIC_SENSE_LEVEL|OPENPIC_SENSE_EDGE); 625 if (o_intrtype[o_virq[irq]] == IST_LEVEL) 626 x |= OPENPIC_SENSE_LEVEL; 627 else 628 x |= OPENPIC_SENSE_EDGE; 629 openpic_write(OPENPIC_SRC_VECTOR(irq), x); 630 } 631 632 void 633 openpic_disable_irq(int irq) 634 { 635 u_int x; 636 637 x = openpic_read(OPENPIC_SRC_VECTOR(irq)); 638 x |= OPENPIC_IMASK; 639 openpic_write(OPENPIC_SRC_VECTOR(irq), x); 640 } 641 642 void 643 openpic_set_priority(int cpu, int pri) 644 { 645 u_int x; 646 647 x = openpic_read(OPENPIC_CPU_PRIORITY(cpu)); 648 x &= ~OPENPIC_CPU_PRIORITY_MASK; 649 x |= pri; 650 openpic_write(OPENPIC_CPU_PRIORITY(cpu), x); 651 } 652 653 int 654 openpic_read_irq(int cpu) 655 { 656 return openpic_read(OPENPIC_IACK(cpu)) & OPENPIC_VECTOR_MASK; 657 } 658 659 void 660 openpic_eoi(int cpu) 661 { 662 openpic_write(OPENPIC_EOI(cpu), 0); 663 openpic_read(OPENPIC_EOI(cpu)); 664 } 665 666 #ifdef MULTIPROCESSOR 667 668 void 669 openpic_send_ipi(struct cpu_info *ci, int id) 670 { 671 switch (id) { 672 case PPC_IPI_NOP: 673 id = 0; 674 break; 675 case PPC_IPI_DDB: 676 id = 1; 677 break; 678 default: 679 panic("invalid ipi send to cpu %d %d\n", ci->ci_cpuid, id); 680 } 681 682 683 openpic_write(OPENPIC_IPI(curcpu()->ci_cpuid, id), 1 << ci->ci_cpuid); 684 } 685 686 #endif 687 688 void 689 ext_intr_openpic() 690 { 691 struct cpu_info *ci = curcpu(); 692 int irq, realirq; 693 int r_imen; 694 int pcpl, ocpl; 695 struct intrhand *ih; 696 697 pcpl = ci->ci_cpl; 698 699 realirq = openpic_read_irq(ci->ci_cpuid); 700 701 while (realirq != 255) { 702 #ifdef MULTIPROCESSOR 703 if (realirq == IPI_VECTOR_NOP) { 704 ipi_nop[ci->ci_cpuid].ec_count++; 705 openpic_eoi(ci->ci_cpuid); 706 realirq = openpic_read_irq(ci->ci_cpuid); 707 continue; 708 } 709 if (realirq == IPI_VECTOR_DDB) { 710 ipi_ddb[ci->ci_cpuid].ec_count++; 711 openpic_eoi(ci->ci_cpuid); 712 openpic_ipi_ddb(); 713 realirq = openpic_read_irq(ci->ci_cpuid); 714 continue; 715 } 716 #endif 717 718 irq = o_virq[realirq]; 719 720 /* XXX check range */ 721 722 r_imen = 1 << irq; 723 724 if ((pcpl & r_imen) != 0) { 725 /* Masked! Mark this as pending. */ 726 ci->ci_ipending |= r_imen; 727 openpic_enable_irq_mask(~imask[o_intrmaxlvl[realirq]]); 728 openpic_eoi(ci->ci_cpuid); 729 } else { 730 openpic_enable_irq_mask(~imask[o_intrmaxlvl[realirq]]); 731 openpic_eoi(ci->ci_cpuid); 732 ocpl = splraise(imask[o_intrmaxlvl[realirq]]); 733 734 ih = o_intrhand[irq]; 735 while (ih) { 736 ppc_intr_enable(1); 737 738 KERNEL_LOCK(); 739 if ((*ih->ih_fun)(ih->ih_arg)) 740 ih->ih_count.ec_count++; 741 KERNEL_UNLOCK(); 742 743 (void)ppc_intr_disable(); 744 ih = ih->ih_next; 745 } 746 747 uvmexp.intrs++; 748 __asm__ volatile("":::"memory"); /* don't reorder.... */ 749 ci->ci_cpl = ocpl; 750 __asm__ volatile("":::"memory"); /* don't reorder.... */ 751 openpic_enable_irq_mask(~pcpl); 752 } 753 754 realirq = openpic_read_irq(ci->ci_cpuid); 755 } 756 ppc_intr_enable(1); 757 758 splx(pcpl); /* Process pendings. */ 759 } 760 761 void 762 openpic_init() 763 { 764 int irq; 765 u_int x; 766 767 /* disable all interrupts */ 768 for (irq = 0; irq < 255; irq++) 769 openpic_write(OPENPIC_SRC_VECTOR(irq), OPENPIC_IMASK); 770 openpic_set_priority(0, 15); 771 772 /* we don't need 8259 pass through mode */ 773 x = openpic_read(OPENPIC_CONFIG); 774 x |= OPENPIC_CONFIG_8259_PASSTHRU_DISABLE; 775 openpic_write(OPENPIC_CONFIG, x); 776 777 /* send all interrupts to cpu 0 */ 778 for (irq = 0; irq < ICU_LEN; irq++) 779 openpic_write(OPENPIC_IDEST(irq), 1 << 0); 780 for (irq = 0; irq < ICU_LEN; irq++) { 781 x = irq; 782 x |= OPENPIC_IMASK; 783 x |= OPENPIC_POLARITY_POSITIVE; 784 x |= OPENPIC_SENSE_LEVEL; 785 x |= 8 << OPENPIC_PRIORITY_SHIFT; 786 openpic_write(OPENPIC_SRC_VECTOR(irq), x); 787 } 788 789 #ifdef MULTIPROCESSOR 790 /* Set up inter-processor interrupts. */ 791 /* IPI0 - NOP */ 792 x = openpic_read(OPENPIC_IPI_VECTOR(0)); 793 x &= ~(OPENPIC_IMASK | OPENPIC_PRIORITY_MASK | OPENPIC_VECTOR_MASK); 794 x |= (15 << OPENPIC_PRIORITY_SHIFT) | IPI_VECTOR_NOP; 795 openpic_write(OPENPIC_IPI_VECTOR(0), x); 796 /* IPI1 - DDB */ 797 x = openpic_read(OPENPIC_IPI_VECTOR(1)); 798 x &= ~(OPENPIC_IMASK | OPENPIC_PRIORITY_MASK | OPENPIC_VECTOR_MASK); 799 x |= (15 << OPENPIC_PRIORITY_SHIFT) | IPI_VECTOR_DDB; 800 openpic_write(OPENPIC_IPI_VECTOR(1), x); 801 802 evcount_attach(&ipi_nop[0], "ipi_nop0", (void *)&ipi_nopirq, 803 &evcount_intr); 804 evcount_attach(&ipi_nop[1], "ipi_nop1", (void *)&ipi_nopirq, 805 &evcount_intr); 806 evcount_attach(&ipi_ddb[0], "ipi_ddb0", (void *)&ipi_ddbirq, 807 &evcount_intr); 808 evcount_attach(&ipi_ddb[1], "ipi_ddb1", (void *)&ipi_ddbirq, 809 &evcount_intr); 810 #endif 811 812 /* XXX set spurious intr vector */ 813 814 openpic_set_priority(0, 0); 815 816 /* clear all pending interrunts */ 817 for (irq = 0; irq < ICU_LEN; irq++) { 818 openpic_read_irq(0); 819 openpic_eoi(0); 820 } 821 822 for (irq = 0; irq < ICU_LEN; irq++) 823 openpic_disable_irq(irq); 824 825 install_extint(ext_intr_openpic); 826 } 827 /* 828 * programmer_button function to fix args to Debugger. 829 * deal with any enables/disables, if necessary. 830 */ 831 int 832 openpic_prog_button (void *arg) 833 { 834 #ifdef DDB 835 if (db_console) 836 Debugger(); 837 #else 838 printf("programmer button pressed, debugger not available\n"); 839 #endif 840 return 1; 841 } 842 843 844 void 845 openpic_ipi_ddb(void) 846 { 847 Debugger(); 848 } 849 850