1 /* $OpenBSD: openpic.c,v 1.52 2008/11/21 17:35:52 deraadt 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 27 75 #define HWIRQ_MASK 0x0fffffff 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, 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, 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_MASK; 418 } 419 imask[IPL_HIGH] = 0xffffffff; 420 } 421 422 /* 423 * Map 64 irqs into 32 (bits). 424 */ 425 static int 426 mapirq(int irq) 427 { 428 int v; 429 430 /* irq in table already? */ 431 if (o_virq[irq] != 0) 432 return o_virq[irq]; 433 434 if (irq < 0 || irq >= ICU_LEN) 435 panic("invalid irq %d", irq); 436 437 o_virq_max++; 438 v = o_virq_max; 439 if (v > HWIRQ_MAX) 440 panic("virq overflow"); 441 442 o_hwirq[v] = irq; 443 o_virq[irq] = v; 444 #if 0 445 printf("\nmapirq %x to %x\n", irq, v); 446 #endif 447 448 return v; 449 } 450 451 /* 452 * Count leading zeros. 453 */ 454 static __inline int 455 cntlzw(int x) 456 { 457 int a; 458 459 __asm __volatile ("cntlzw %0,%1" : "=r"(a) : "r"(x)); 460 461 return a; 462 } 463 464 void openpic_do_pending_softint(int pcpl); 465 466 void 467 openpic_do_pending_int() 468 { 469 struct cpu_info *ci = curcpu(); 470 struct intrhand *ih; 471 int irq; 472 int pcpl; 473 int hwpend; 474 int pri, pripending; 475 int s; 476 477 if (ci->ci_iactive & CI_IACTIVE_PROCESSING_HARD) 478 return; 479 480 atomic_setbits_int(&ci->ci_iactive, CI_IACTIVE_PROCESSING_HARD); 481 s = ppc_intr_disable(); 482 pcpl = ci->ci_cpl; 483 484 hwpend = ci->ci_ipending & ~pcpl; /* Do now unmasked pendings */ 485 hwpend &= HWIRQ_MASK; 486 while (hwpend) { 487 /* this still doesn't handle the interrupts in priority order */ 488 for (pri = IPL_HIGH; pri >= IPL_NONE; pri--) { 489 pripending = hwpend & ~imask[pri]; 490 irq = 31 - cntlzw(pripending); 491 ci->ci_ipending &= ~(1L << irq); 492 ci->ci_cpl = imask[o_intrmaxlvl[o_hwirq[irq]]]; 493 openpic_enable_irq_mask(~ci->ci_cpl); 494 ih = o_intrhand[irq]; 495 while(ih) { 496 ppc_intr_enable(1); 497 498 KERNEL_LOCK(); 499 if ((*ih->ih_fun)(ih->ih_arg)) 500 ih->ih_count.ec_count++; 501 KERNEL_UNLOCK(); 502 503 (void)ppc_intr_disable(); 504 505 ih = ih->ih_next; 506 } 507 } 508 hwpend = ci->ci_ipending & ~pcpl;/* Catch new pendings */ 509 hwpend &= HWIRQ_MASK; 510 } 511 ci->ci_cpl = pcpl | SINT_MASK; 512 openpic_enable_irq_mask(~ci->ci_cpl); 513 atomic_clearbits_int(&ci->ci_iactive, CI_IACTIVE_PROCESSING_HARD); 514 515 openpic_do_pending_softint(pcpl); 516 517 ppc_intr_enable(s); 518 } 519 520 void 521 openpic_do_pending_softint(int pcpl) 522 { 523 struct cpu_info *ci = curcpu(); 524 525 if (ci->ci_iactive & CI_IACTIVE_PROCESSING_SOFT) 526 return; 527 528 atomic_setbits_int(&ci->ci_iactive, CI_IACTIVE_PROCESSING_SOFT); 529 530 do { 531 if((ci->ci_ipending & SINT_CLOCK) & ~pcpl) { 532 ci->ci_ipending &= ~SINT_CLOCK; 533 ci->ci_cpl = SINT_CLOCK|SINT_NET|SINT_TTY; 534 ppc_intr_enable(1); 535 KERNEL_LOCK(); 536 softclock(); 537 KERNEL_UNLOCK(); 538 ppc_intr_disable(); 539 continue; 540 } 541 if((ci->ci_ipending & SINT_NET) & ~pcpl) { 542 extern int netisr; 543 int pisr; 544 545 ci->ci_ipending &= ~SINT_NET; 546 ci->ci_cpl = SINT_NET|SINT_TTY; 547 while ((pisr = netisr) != 0) { 548 atomic_clearbits_int(&netisr, pisr); 549 ppc_intr_enable(1); 550 KERNEL_LOCK(); 551 softnet(pisr); 552 KERNEL_UNLOCK(); 553 ppc_intr_disable(); 554 } 555 continue; 556 } 557 if((ci->ci_ipending & SINT_TTY) & ~pcpl) { 558 ci->ci_ipending &= ~SINT_TTY; 559 ci->ci_cpl = SINT_TTY; 560 ppc_intr_enable(1); 561 KERNEL_LOCK(); 562 softtty(); 563 KERNEL_UNLOCK(); 564 ppc_intr_disable(); 565 continue; 566 } 567 } while ((ci->ci_ipending & SINT_MASK) & ~pcpl); 568 ci->ci_cpl = pcpl; /* Don't use splx... we are here already! */ 569 570 atomic_clearbits_int(&ci->ci_iactive, CI_IACTIVE_PROCESSING_SOFT); 571 } 572 573 u_int 574 openpic_read(int reg) 575 { 576 char *addr = (void *)(openpic_base + reg); 577 578 if (openpic_big_endian) 579 return in32(addr); 580 else 581 return in32rb(addr); 582 } 583 584 void 585 openpic_write(int reg, u_int val) 586 { 587 char *addr = (void *)(openpic_base + reg); 588 589 if (openpic_big_endian) 590 out32(addr, val); 591 else 592 out32rb(addr, val); 593 } 594 595 void 596 openpic_enable_irq_mask(int irq_mask) 597 { 598 int irq; 599 for ( irq = 0; irq <= o_virq_max; irq++) { 600 if (irq_mask & (1 << irq)) 601 openpic_enable_irq(o_hwirq[irq]); 602 else 603 openpic_disable_irq(o_hwirq[irq]); 604 } 605 } 606 607 void 608 openpic_set_enable_irq(int irq, int type) 609 { 610 u_int x; 611 612 x = openpic_read(OPENPIC_SRC_VECTOR(irq)); 613 x &= ~(OPENPIC_IMASK|OPENPIC_SENSE_LEVEL|OPENPIC_SENSE_EDGE); 614 if (type == IST_LEVEL) 615 x |= OPENPIC_SENSE_LEVEL; 616 else 617 x |= OPENPIC_SENSE_EDGE; 618 openpic_write(OPENPIC_SRC_VECTOR(irq), x); 619 } 620 void 621 openpic_enable_irq(int irq) 622 { 623 u_int x; 624 625 x = openpic_read(OPENPIC_SRC_VECTOR(irq)); 626 x &= ~(OPENPIC_IMASK|OPENPIC_SENSE_LEVEL|OPENPIC_SENSE_EDGE); 627 if (o_intrtype[o_virq[irq]] == IST_LEVEL) 628 x |= OPENPIC_SENSE_LEVEL; 629 else 630 x |= OPENPIC_SENSE_EDGE; 631 openpic_write(OPENPIC_SRC_VECTOR(irq), x); 632 } 633 634 void 635 openpic_disable_irq(int irq) 636 { 637 u_int x; 638 639 x = openpic_read(OPENPIC_SRC_VECTOR(irq)); 640 x |= OPENPIC_IMASK; 641 openpic_write(OPENPIC_SRC_VECTOR(irq), x); 642 } 643 644 void 645 openpic_set_priority(int cpu, int pri) 646 { 647 u_int x; 648 649 x = openpic_read(OPENPIC_CPU_PRIORITY(cpu)); 650 x &= ~OPENPIC_CPU_PRIORITY_MASK; 651 x |= pri; 652 openpic_write(OPENPIC_CPU_PRIORITY(cpu), x); 653 } 654 655 int 656 openpic_read_irq(int cpu) 657 { 658 return openpic_read(OPENPIC_IACK(cpu)) & OPENPIC_VECTOR_MASK; 659 } 660 661 void 662 openpic_eoi(int cpu) 663 { 664 openpic_write(OPENPIC_EOI(cpu), 0); 665 openpic_read(OPENPIC_EOI(cpu)); 666 } 667 668 #ifdef MULTIPROCESSOR 669 670 void 671 openpic_send_ipi(struct cpu_info *ci, int id) 672 { 673 switch (id) { 674 case PPC_IPI_NOP: 675 id = 0; 676 break; 677 case PPC_IPI_DDB: 678 id = 1; 679 break; 680 default: 681 panic("invalid ipi send to cpu %d %d\n", ci->ci_cpuid, id); 682 } 683 684 685 openpic_write(OPENPIC_IPI(curcpu()->ci_cpuid, id), 1 << ci->ci_cpuid); 686 } 687 688 #endif 689 690 void 691 ext_intr_openpic() 692 { 693 struct cpu_info *ci = curcpu(); 694 int irq, realirq; 695 int r_imen; 696 int pcpl, ocpl; 697 struct intrhand *ih; 698 699 pcpl = ci->ci_cpl; 700 701 realirq = openpic_read_irq(ci->ci_cpuid); 702 703 while (realirq != 255) { 704 #ifdef MULTIPROCESSOR 705 if (realirq == IPI_VECTOR_NOP) { 706 ipi_nop[ci->ci_cpuid].ec_count++; 707 openpic_eoi(ci->ci_cpuid); 708 realirq = openpic_read_irq(ci->ci_cpuid); 709 continue; 710 } 711 if (realirq == IPI_VECTOR_DDB) { 712 ipi_ddb[ci->ci_cpuid].ec_count++; 713 openpic_eoi(ci->ci_cpuid); 714 openpic_ipi_ddb(); 715 realirq = openpic_read_irq(ci->ci_cpuid); 716 continue; 717 } 718 #endif 719 720 irq = o_virq[realirq]; 721 722 /* XXX check range */ 723 724 r_imen = 1 << irq; 725 726 if ((pcpl & r_imen) != 0) { 727 /* Masked! Mark this as pending. */ 728 ci->ci_ipending |= r_imen; 729 openpic_enable_irq_mask(~imask[o_intrmaxlvl[realirq]]); 730 openpic_eoi(ci->ci_cpuid); 731 } else { 732 openpic_enable_irq_mask(~imask[o_intrmaxlvl[realirq]]); 733 openpic_eoi(ci->ci_cpuid); 734 ocpl = splraise(imask[o_intrmaxlvl[realirq]]); 735 736 ih = o_intrhand[irq]; 737 while (ih) { 738 ppc_intr_enable(1); 739 740 KERNEL_LOCK(); 741 if ((*ih->ih_fun)(ih->ih_arg)) 742 ih->ih_count.ec_count++; 743 KERNEL_UNLOCK(); 744 745 (void)ppc_intr_disable(); 746 ih = ih->ih_next; 747 } 748 749 uvmexp.intrs++; 750 __asm__ volatile("":::"memory"); /* don't reorder.... */ 751 ci->ci_cpl = ocpl; 752 __asm__ volatile("":::"memory"); /* don't reorder.... */ 753 openpic_enable_irq_mask(~pcpl); 754 } 755 756 realirq = openpic_read_irq(ci->ci_cpuid); 757 } 758 ppc_intr_enable(1); 759 760 splx(pcpl); /* Process pendings. */ 761 } 762 763 void 764 openpic_init() 765 { 766 int irq; 767 u_int x; 768 769 /* disable all interrupts */ 770 for (irq = 0; irq < 255; irq++) 771 openpic_write(OPENPIC_SRC_VECTOR(irq), OPENPIC_IMASK); 772 openpic_set_priority(0, 15); 773 774 /* we don't need 8259 pass through mode */ 775 x = openpic_read(OPENPIC_CONFIG); 776 x |= OPENPIC_CONFIG_8259_PASSTHRU_DISABLE; 777 openpic_write(OPENPIC_CONFIG, x); 778 779 /* send all interrupts to cpu 0 */ 780 for (irq = 0; irq < ICU_LEN; irq++) 781 openpic_write(OPENPIC_IDEST(irq), 1 << 0); 782 for (irq = 0; irq < ICU_LEN; irq++) { 783 x = irq; 784 x |= OPENPIC_IMASK; 785 x |= OPENPIC_POLARITY_POSITIVE; 786 x |= OPENPIC_SENSE_LEVEL; 787 x |= 8 << OPENPIC_PRIORITY_SHIFT; 788 openpic_write(OPENPIC_SRC_VECTOR(irq), x); 789 } 790 791 #ifdef MULTIPROCESSOR 792 /* Set up inter-processor interrupts. */ 793 /* IPI0 - NOP */ 794 x = openpic_read(OPENPIC_IPI_VECTOR(0)); 795 x &= ~(OPENPIC_IMASK | OPENPIC_PRIORITY_MASK | OPENPIC_VECTOR_MASK); 796 x |= (15 << OPENPIC_PRIORITY_SHIFT) | IPI_VECTOR_NOP; 797 openpic_write(OPENPIC_IPI_VECTOR(0), x); 798 /* IPI1 - DDB */ 799 x = openpic_read(OPENPIC_IPI_VECTOR(1)); 800 x &= ~(OPENPIC_IMASK | OPENPIC_PRIORITY_MASK | OPENPIC_VECTOR_MASK); 801 x |= (15 << OPENPIC_PRIORITY_SHIFT) | IPI_VECTOR_DDB; 802 openpic_write(OPENPIC_IPI_VECTOR(1), x); 803 804 evcount_attach(&ipi_nop[0], "ipi_nop0", (void *)&ipi_nopirq, 805 &evcount_intr); 806 evcount_attach(&ipi_nop[1], "ipi_nop1", (void *)&ipi_nopirq, 807 &evcount_intr); 808 evcount_attach(&ipi_ddb[0], "ipi_ddb0", (void *)&ipi_ddbirq, 809 &evcount_intr); 810 evcount_attach(&ipi_ddb[1], "ipi_ddb1", (void *)&ipi_ddbirq, 811 &evcount_intr); 812 #endif 813 814 /* XXX set spurious intr vector */ 815 816 openpic_set_priority(0, 0); 817 818 /* clear all pending interrunts */ 819 for (irq = 0; irq < ICU_LEN; irq++) { 820 openpic_read_irq(0); 821 openpic_eoi(0); 822 } 823 824 for (irq = 0; irq < ICU_LEN; irq++) 825 openpic_disable_irq(irq); 826 827 install_extint(ext_intr_openpic); 828 } 829 /* 830 * programmer_button function to fix args to Debugger. 831 * deal with any enables/disables, if necessary. 832 */ 833 int 834 openpic_prog_button (void *arg) 835 { 836 #ifdef DDB 837 if (db_console) 838 Debugger(); 839 #else 840 printf("programmer button pressed, debugger not available\n"); 841 #endif 842 return 1; 843 } 844 845 846 void 847 openpic_ipi_ddb(void) 848 { 849 Debugger(); 850 } 851 852