1 /* $OpenBSD: openpic.c,v 1.72 2014/07/12 18:44:42 tedu Exp $ */ 2 3 /*- 4 * Copyright (c) 2008 Dale Rahn <drahn@openbsd.org> 5 * Copyright (c) 1995 Per Fogelstrom 6 * Copyright (c) 1993, 1994 Charles M. Hannum. 7 * Copyright (c) 1990 The Regents of the University of California. 8 * All rights reserved. 9 * 10 * This code is derived from software contributed to Berkeley by 11 * William Jolitz and Don Ahn. 12 * 13 * Redistribution and use in source and binary forms, with or without 14 * modification, are permitted provided that the following conditions 15 * are met: 16 * 1. Redistributions of source code must retain the above copyright 17 * notice, this list of conditions and the following disclaimer. 18 * 2. Redistributions in binary form must reproduce the above copyright 19 * notice, this list of conditions and the following disclaimer in the 20 * documentation and/or other materials provided with the distribution. 21 * 3. Neither the name of the University nor the names of its contributors 22 * may be used to endorse or promote products derived from this software 23 * without specific prior written permission. 24 * 25 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 26 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 27 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 28 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 29 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 30 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 31 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 32 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 33 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 34 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 35 * SUCH DAMAGE. 36 * 37 * @(#)isa.c 7.2 (Berkeley) 5/12/91 38 */ 39 40 #include <sys/param.h> 41 #include <sys/device.h> 42 #include <sys/systm.h> 43 #include <sys/malloc.h> 44 45 #include <uvm/uvm_extern.h> 46 #include <ddb/db_var.h> 47 48 #include <machine/atomic.h> 49 #include <machine/autoconf.h> 50 #include <machine/intr.h> 51 #include <machine/psl.h> 52 #include <machine/pio.h> 53 #include <dev/ofw/openfirm.h> 54 55 #include <macppc/dev/openpicreg.h> 56 57 #define ICU_LEN 128 58 int openpic_numirq = ICU_LEN; 59 #define LEGAL_IRQ(x) ((x >= 0) && (x < ICU_LEN)) 60 61 int openpic_pri_share[IPL_NUM]; 62 63 struct intrq openpic_handler[ICU_LEN]; 64 65 void openpic_calc_mask(void); 66 67 ppc_splraise_t openpic_splraise; 68 ppc_spllower_t openpic_spllower; 69 ppc_splx_t openpic_splx; 70 71 /* IRQ vector used for inter-processor interrupts. */ 72 #define IPI_VECTOR_NOP 64 73 #define IPI_VECTOR_DDB 65 74 #ifdef MULTIPROCESSOR 75 static struct evcount ipi_ddb[PPC_MAXPROCS]; 76 static struct evcount ipi_nop[PPC_MAXPROCS]; 77 static int ipi_nopirq = IPI_VECTOR_NOP; 78 static int ipi_ddbirq = IPI_VECTOR_DDB; 79 #endif 80 struct evcount openpic_spurious; 81 int openpic_spurious_irq = 255; 82 83 void openpic_enable_irq(int, int); 84 void openpic_disable_irq(int); 85 void openpic_init(void); 86 void openpic_set_priority(int, int); 87 void openpic_ipi_ddb(void); 88 void *openpic_intr_establish(void *, int, int, int, int (*)(void *), 89 void *, const char *); 90 91 typedef void (void_f) (void); 92 extern void_f *pending_int_f; 93 94 vaddr_t openpic_base; 95 void openpic_intr_disestablish( void *lcp, void *arg); 96 void openpic_collect_preconf_intr(void); 97 int openpic_big_endian; 98 #ifdef MULTIPROCESSOR 99 intr_send_ipi_t openpic_send_ipi; 100 #endif 101 102 u_int openpic_read(int reg); 103 void openpic_write(int reg, u_int val); 104 105 struct openpic_softc { 106 struct device sc_dev; 107 }; 108 109 int openpic_match(struct device *parent, void *cf, void *aux); 110 void openpic_attach(struct device *, struct device *, void *); 111 void openpic_do_pending_int(int pcpl); 112 void openpic_do_pending_int_dis(int pcpl, int s); 113 void openpic_collect_preconf_intr(void); 114 void openpic_ext_intr(void); 115 116 struct cfattach openpic_ca = { 117 sizeof(struct openpic_softc), 118 openpic_match, 119 openpic_attach 120 }; 121 122 struct cfdriver openpic_cd = { 123 NULL, "openpic", DV_DULL 124 }; 125 126 u_int 127 openpic_read(int reg) 128 { 129 char *addr = (void *)(openpic_base + reg); 130 131 asm volatile("eieio"::: "memory"); 132 if (openpic_big_endian) 133 return in32(addr); 134 else 135 return in32rb(addr); 136 } 137 138 void 139 openpic_write(int reg, u_int val) 140 { 141 char *addr = (void *)(openpic_base + reg); 142 143 if (openpic_big_endian) 144 out32(addr, val); 145 else 146 out32rb(addr, val); 147 asm volatile("eieio"::: "memory"); 148 } 149 150 static inline int 151 openpic_read_irq(int cpu) 152 { 153 return openpic_read(OPENPIC_IACK(cpu)) & OPENPIC_VECTOR_MASK; 154 } 155 156 static inline void 157 openpic_eoi(int cpu) 158 { 159 openpic_write(OPENPIC_EOI(cpu), 0); 160 } 161 162 int 163 openpic_match(struct device *parent, void *cf, void *aux) 164 { 165 char type[40]; 166 int pirq; 167 struct confargs *ca = aux; 168 169 bzero (type, sizeof(type)); 170 171 if (OF_getprop(ca->ca_node, "interrupt-parent", &pirq, sizeof(pirq)) 172 == sizeof(pirq)) 173 return 0; /* XXX */ 174 175 if (strcmp(ca->ca_name, "interrupt-controller") != 0 && 176 strcmp(ca->ca_name, "mpic") != 0) 177 return 0; 178 179 OF_getprop(ca->ca_node, "device_type", type, sizeof(type)); 180 if (strcmp(type, "open-pic") != 0) 181 return 0; 182 183 if (ca->ca_nreg < 8) 184 return 0; 185 186 return 1; 187 } 188 189 void 190 openpic_attach(struct device *parent, struct device *self, void *aux) 191 { 192 struct cpu_info *ci = curcpu(); 193 struct confargs *ca = aux; 194 u_int32_t reg; 195 196 reg = 0; 197 if (OF_getprop(ca->ca_node, "big-endian", ®, sizeof reg) == 0) 198 openpic_big_endian = 1; 199 200 openpic_base = (vaddr_t) mapiodev (ca->ca_baseaddr + 201 ca->ca_reg[0], 0x40000); 202 203 /* openpic may support more than 128 interupts but driver doesn't */ 204 openpic_numirq = ((openpic_read(OPENPIC_FEATURE) >> 16) & 0x7f)+1; 205 206 printf(": version 0x%x feature %x %s", 207 openpic_read(OPENPIC_VENDOR_ID), 208 openpic_read(OPENPIC_FEATURE), 209 openpic_big_endian ? "BE" : "LE" ); 210 211 openpic_init(); 212 213 intr_establish_func = openpic_intr_establish; 214 intr_disestablish_func = openpic_intr_disestablish; 215 mac_intr_establish_func = openpic_intr_establish; 216 mac_intr_disestablish_func = openpic_intr_disestablish; 217 #ifdef MULTIPROCESSOR 218 intr_send_ipi_func = openpic_send_ipi; 219 #endif 220 221 ppc_smask_init(); 222 223 openpic_collect_preconf_intr(); 224 225 evcount_attach(&openpic_spurious, "spurious", &openpic_spurious_irq); 226 227 ppc_intr_func.raise = openpic_splraise; 228 ppc_intr_func.lower = openpic_spllower; 229 ppc_intr_func.x = openpic_splx; 230 231 openpic_set_priority(0, ci->ci_cpl); 232 233 ppc_intr_enable(1); 234 235 printf("\n"); 236 } 237 238 static inline void 239 openpic_setipl(int newcpl) 240 { 241 struct cpu_info *ci = curcpu(); 242 int s; 243 /* XXX - try do to this without the disable */ 244 s = ppc_intr_disable(); 245 ci->ci_cpl = newcpl; 246 openpic_set_priority(ci->ci_cpuid, newcpl); 247 ppc_intr_enable(s); 248 } 249 250 int 251 openpic_splraise(int newcpl) 252 { 253 struct cpu_info *ci = curcpu(); 254 newcpl = openpic_pri_share[newcpl]; 255 int ocpl = ci->ci_cpl; 256 if (ocpl > newcpl) 257 newcpl = ocpl; 258 259 openpic_setipl(newcpl); 260 261 return ocpl; 262 } 263 264 int 265 openpic_spllower(int newcpl) 266 { 267 struct cpu_info *ci = curcpu(); 268 int ocpl = ci->ci_cpl; 269 270 openpic_splx(newcpl); 271 272 return ocpl; 273 } 274 275 void 276 openpic_splx(int newcpl) 277 { 278 openpic_do_pending_int(newcpl); 279 } 280 281 void 282 openpic_collect_preconf_intr() 283 { 284 int i; 285 for (i = 0; i < ppc_configed_intr_cnt; i++) { 286 #ifdef DEBUG 287 printf("\n\t%s irq %d level %d fun %x arg %x", 288 ppc_configed_intr[i].ih_what, ppc_configed_intr[i].ih_irq, 289 ppc_configed_intr[i].ih_level, ppc_configed_intr[i].ih_fun, 290 ppc_configed_intr[i].ih_arg); 291 #endif 292 openpic_intr_establish(NULL, ppc_configed_intr[i].ih_irq, 293 IST_LEVEL, ppc_configed_intr[i].ih_level, 294 ppc_configed_intr[i].ih_fun, ppc_configed_intr[i].ih_arg, 295 ppc_configed_intr[i].ih_what); 296 } 297 } 298 299 /* 300 * Register an interrupt handler. 301 */ 302 void * 303 openpic_intr_establish(void *lcv, int irq, int type, int level, 304 int (*ih_fun)(void *), void *ih_arg, const char *name) 305 { 306 struct intrhand *ih; 307 struct intrq *iq; 308 int s; 309 310 /* no point in sleeping unless someone can free memory. */ 311 ih = malloc(sizeof *ih, M_DEVBUF, cold ? M_NOWAIT : M_WAITOK); 312 if (ih == NULL) 313 panic("intr_establish: can't malloc handler info"); 314 iq = &openpic_handler[irq]; 315 316 if (!LEGAL_IRQ(irq) || type == IST_NONE) 317 panic("intr_establish: bogus irq or type"); 318 319 switch (iq->iq_ist) { 320 case IST_NONE: 321 iq->iq_ist = type; 322 break; 323 case IST_EDGE: 324 intr_shared_edge = 1; 325 /* FALLTHROUGH */ 326 case IST_LEVEL: 327 if (type == iq->iq_ist) 328 break; 329 case IST_PULSE: 330 if (type != IST_NONE) 331 panic("intr_establish: can't share %s with %s", 332 ppc_intr_typename(iq->iq_ist), 333 ppc_intr_typename(type)); 334 break; 335 } 336 337 ih->ih_fun = ih_fun; 338 ih->ih_arg = ih_arg; 339 ih->ih_level = level; 340 ih->ih_irq = irq; 341 342 evcount_attach(&ih->ih_count, name, &ih->ih_irq); 343 344 /* 345 * Append handler to end of list 346 */ 347 s = ppc_intr_disable(); 348 349 TAILQ_INSERT_TAIL(&iq->iq_list, ih, ih_list); 350 openpic_calc_mask(); 351 352 ppc_intr_enable(s); 353 354 return (ih); 355 } 356 357 /* 358 * Deregister an interrupt handler. 359 */ 360 void 361 openpic_intr_disestablish(void *lcp, void *arg) 362 { 363 struct intrhand *ih = arg; 364 int irq = ih->ih_irq; 365 struct intrq *iq = &openpic_handler[irq]; 366 int s; 367 368 if (!LEGAL_IRQ(irq)) 369 panic("intr_disestablish: bogus irq"); 370 371 /* 372 * Remove the handler from the chain. 373 */ 374 s = ppc_intr_disable(); 375 376 TAILQ_REMOVE(&iq->iq_list, ih, ih_list); 377 openpic_calc_mask(); 378 379 ppc_intr_enable(s); 380 381 evcount_detach(&ih->ih_count); 382 free((void *)ih, M_DEVBUF, 0); 383 384 if (TAILQ_EMPTY(&iq->iq_list)) 385 iq->iq_ist = IST_NONE; 386 } 387 388 /* 389 * Recalculate the interrupt masks from scratch. 390 * We could code special registry and deregistry versions of this function that 391 * would be faster, but the code would be nastier, and we don't expect this to 392 * happen very much anyway. 393 */ 394 395 void 396 openpic_calc_mask() 397 { 398 struct cpu_info *ci = curcpu(); 399 int irq; 400 struct intrhand *ih; 401 int i; 402 403 /* disable all openpic interrupts */ 404 openpic_set_priority(ci->ci_cpuid, 15); 405 406 for (i = IPL_NONE; i < IPL_NUM; i++) { 407 openpic_pri_share[i] = i; 408 } 409 410 for (irq = 0; irq < openpic_numirq; irq++) { 411 int maxipl = IPL_NONE; 412 int minipl = IPL_HIGH; 413 struct intrq *iq = &openpic_handler[irq]; 414 415 TAILQ_FOREACH(ih, &iq->iq_list, ih_list) { 416 if (ih->ih_level > maxipl) 417 maxipl = ih->ih_level; 418 if (ih->ih_level < minipl) 419 minipl = ih->ih_level; 420 } 421 422 if (maxipl == IPL_NONE) { 423 minipl = IPL_NONE; /* Interrupt not enabled */ 424 425 openpic_disable_irq(irq); 426 } else { 427 for (i = minipl; i <= maxipl; i++) { 428 openpic_pri_share[i] = maxipl; 429 } 430 openpic_enable_irq(irq, maxipl); 431 } 432 433 iq->iq_ipl = maxipl; 434 } 435 436 /* restore interrupts */ 437 openpic_set_priority(ci->ci_cpuid, ci->ci_cpl); 438 } 439 440 void 441 openpic_do_pending_int(int pcpl) 442 { 443 int s; 444 s = ppc_intr_disable(); 445 openpic_do_pending_int_dis(pcpl, s); 446 ppc_intr_enable(s); 447 448 } 449 450 /* 451 * This function expect interrupts disabled on entry and exit, 452 * the s argument indicates if interrupts may be enabled during 453 * the processing of off level interrupts, s 'should' always be 1. 454 */ 455 void 456 openpic_do_pending_int_dis(int pcpl, int s) 457 { 458 struct cpu_info *ci = curcpu(); 459 460 (void)ppc_intr_disable(); 461 if (ci->ci_iactive & CI_IACTIVE_PROCESSING_SOFT) { 462 /* soft interrupts are being processed, just set ipl/return */ 463 openpic_setipl(pcpl); 464 ppc_intr_enable(s); 465 return; 466 } 467 468 atomic_setbits_int(&ci->ci_iactive, CI_IACTIVE_PROCESSING_SOFT); 469 470 do { 471 if ((ci->ci_ipending & SI_TO_IRQBIT(SI_SOFTCLOCK)) && 472 (pcpl < IPL_SOFTCLOCK)) { 473 ci->ci_ipending &= ~SI_TO_IRQBIT(SI_SOFTCLOCK); 474 ppc_intr_enable(1); 475 KERNEL_LOCK(); 476 softintr_dispatch(SI_SOFTCLOCK); 477 KERNEL_UNLOCK(); 478 (void)ppc_intr_disable(); 479 } 480 if ((ci->ci_ipending & SI_TO_IRQBIT(SI_SOFTNET)) && 481 (pcpl < IPL_SOFTNET)) { 482 ci->ci_ipending &= ~SI_TO_IRQBIT(SI_SOFTNET); 483 ppc_intr_enable(1); 484 KERNEL_LOCK(); 485 softintr_dispatch(SI_SOFTNET); 486 KERNEL_UNLOCK(); 487 (void)ppc_intr_disable(); 488 } 489 if ((ci->ci_ipending & SI_TO_IRQBIT(SI_SOFTTTY)) && 490 (pcpl < IPL_SOFTTTY)) { 491 ci->ci_ipending &= ~SI_TO_IRQBIT(SI_SOFTTTY); 492 ppc_intr_enable(1); 493 KERNEL_LOCK(); 494 softintr_dispatch(SI_SOFTTTY); 495 KERNEL_UNLOCK(); 496 (void)ppc_intr_disable(); 497 } 498 } while (ci->ci_ipending & ppc_smask[pcpl]); 499 openpic_setipl(pcpl); /* Don't use splx... we are here already! */ 500 501 atomic_clearbits_int(&ci->ci_iactive, CI_IACTIVE_PROCESSING_SOFT); 502 ppc_intr_enable(s); 503 } 504 505 void 506 openpic_enable_irq(int irq, int pri) 507 { 508 u_int x; 509 struct intrq *iq = &openpic_handler[irq]; 510 511 x = irq; 512 if (iq->iq_ist == IST_LEVEL) 513 x |= OPENPIC_SENSE_LEVEL; 514 else 515 x |= OPENPIC_SENSE_EDGE; 516 x |= OPENPIC_POLARITY_NEGATIVE; 517 x |= pri << OPENPIC_PRIORITY_SHIFT; 518 openpic_write(OPENPIC_SRC_VECTOR(irq), x); 519 } 520 521 void 522 openpic_disable_irq(int irq) 523 { 524 u_int x; 525 526 x = openpic_read(OPENPIC_SRC_VECTOR(irq)); 527 x |= OPENPIC_IMASK; 528 openpic_write(OPENPIC_SRC_VECTOR(irq), x); 529 } 530 531 void 532 openpic_set_priority(int cpu, int pri) 533 { 534 openpic_write(OPENPIC_CPU_PRIORITY(cpu), pri); 535 } 536 537 #ifdef MULTIPROCESSOR 538 void 539 openpic_send_ipi(struct cpu_info *ci, int id) 540 { 541 switch (id) { 542 case PPC_IPI_NOP: 543 id = 0; 544 break; 545 case PPC_IPI_DDB: 546 id = 1; 547 break; 548 default: 549 panic("invalid ipi send to cpu %d %d", ci->ci_cpuid, id); 550 } 551 552 openpic_write(OPENPIC_IPI(curcpu()->ci_cpuid, id), 1 << ci->ci_cpuid); 553 } 554 555 #endif 556 557 int openpic_irqnest[PPC_MAXPROCS]; 558 int openpic_irqloop[PPC_MAXPROCS]; 559 void 560 openpic_ext_intr() 561 { 562 struct cpu_info *ci = curcpu(); 563 int irq, pcpl, ret; 564 int maxipl = IPL_NONE; 565 struct intrhand *ih; 566 struct intrq *iq; 567 int spurious; 568 569 pcpl = ci->ci_cpl; 570 571 openpic_irqloop[ci->ci_cpuid] = 0; 572 irq = openpic_read_irq(ci->ci_cpuid); 573 openpic_irqnest[ci->ci_cpuid]++; 574 575 while (irq != 255) { 576 openpic_irqloop[ci->ci_cpuid]++; 577 #ifdef DEBUG 578 if (openpic_irqloop[ci->ci_cpuid] > 20 || 579 openpic_irqnest[ci->ci_cpuid] > 3) { 580 printf("irqloop %d irqnest %d\n", 581 openpic_irqloop[ci->ci_cpuid], 582 openpic_irqnest[ci->ci_cpuid]); 583 } 584 #endif 585 if (openpic_irqloop[ci->ci_cpuid] > 20) { 586 #ifdef DEBUG 587 printf("irqloop %d irqnest %d: returning\n", 588 openpic_irqloop[ci->ci_cpuid], 589 openpic_irqnest[ci->ci_cpuid]); 590 #endif 591 openpic_irqnest[ci->ci_cpuid]--; 592 return; 593 } 594 #ifdef MULTIPROCESSOR 595 if (irq == IPI_VECTOR_NOP) { 596 ipi_nop[ci->ci_cpuid].ec_count++; 597 openpic_eoi(ci->ci_cpuid); 598 irq = openpic_read_irq(ci->ci_cpuid); 599 continue; 600 } 601 if (irq == IPI_VECTOR_DDB) { 602 ipi_ddb[ci->ci_cpuid].ec_count++; 603 openpic_eoi(ci->ci_cpuid); 604 openpic_ipi_ddb(); 605 irq = openpic_read_irq(ci->ci_cpuid); 606 continue; 607 } 608 #endif 609 iq = &openpic_handler[irq]; 610 611 if (iq->iq_ipl <= ci->ci_cpl) 612 printf("invalid interrupt %d lvl %d at %d hw %d\n", 613 irq, iq->iq_ipl, ci->ci_cpl, 614 openpic_read(OPENPIC_CPU_PRIORITY(ci->ci_cpuid))); 615 if (iq->iq_ipl > maxipl) 616 maxipl = iq->iq_ipl; 617 splraise(iq->iq_ipl); 618 openpic_eoi(ci->ci_cpuid); 619 620 spurious = 1; 621 TAILQ_FOREACH(ih, &iq->iq_list, ih_list) { 622 ppc_intr_enable(1); 623 KERNEL_LOCK(); 624 ret = (*ih->ih_fun)(ih->ih_arg); 625 if (ret) { 626 ih->ih_count.ec_count++; 627 spurious = 0; 628 } 629 KERNEL_UNLOCK(); 630 631 (void)ppc_intr_disable(); 632 if (intr_shared_edge == 00 && ret == 1) 633 break; 634 } 635 if (spurious) { 636 openpic_spurious.ec_count++; 637 #ifdef OPENPIC_NOISY 638 printf("spurious intr %d\n", irq); 639 #endif 640 } 641 642 uvmexp.intrs++; 643 openpic_setipl(pcpl); 644 645 irq = openpic_read_irq(ci->ci_cpuid); 646 } 647 648 /* 649 * sending 0 in to openpic_do_pending_int_dis will leave 650 * external interrupts disabled, but since we are about 651 * to return from interrupt leaving them disabled until then 652 * prevents additional recursion. 653 */ 654 openpic_do_pending_int_dis(pcpl, 0); 655 656 openpic_irqnest[ci->ci_cpuid]--; 657 } 658 659 void 660 openpic_init() 661 { 662 struct cpu_info *ci = curcpu(); 663 struct intrq *iq; 664 int irq; 665 u_int x; 666 int i; 667 668 openpic_set_priority(ci->ci_cpuid, 15); 669 670 /* disable all interrupts */ 671 for (irq = 0; irq < openpic_numirq; irq++) 672 openpic_write(OPENPIC_SRC_VECTOR(irq), OPENPIC_IMASK); 673 674 for (i = 0; i < openpic_numirq; i++) { 675 iq = &openpic_handler[i]; 676 TAILQ_INIT(&iq->iq_list); 677 } 678 679 /* we don't need 8259 pass through mode */ 680 x = openpic_read(OPENPIC_CONFIG); 681 x |= OPENPIC_CONFIG_8259_PASSTHRU_DISABLE; 682 openpic_write(OPENPIC_CONFIG, x); 683 684 /* initialize all vectors to something sane */ 685 for (irq = 0; irq < ICU_LEN; irq++) { 686 x = irq; 687 x |= OPENPIC_IMASK; 688 x |= OPENPIC_POLARITY_NEGATIVE; 689 x |= OPENPIC_SENSE_LEVEL; 690 x |= 8 << OPENPIC_PRIORITY_SHIFT; 691 openpic_write(OPENPIC_SRC_VECTOR(irq), x); 692 } 693 694 /* send all interrupts to cpu 0 */ 695 for (irq = 0; irq < openpic_numirq; irq++) 696 openpic_write(OPENPIC_IDEST(irq), 1 << 0); 697 698 /* clear all pending interrunts */ 699 for (irq = 0; irq < ICU_LEN; irq++) { 700 openpic_read_irq(ci->ci_cpuid); 701 openpic_eoi(ci->ci_cpuid); 702 } 703 704 #ifdef MULTIPROCESSOR 705 /* Set up inter-processor interrupts. */ 706 /* IPI0 - NOP */ 707 x = IPI_VECTOR_NOP; 708 x |= 15 << OPENPIC_PRIORITY_SHIFT; 709 openpic_write(OPENPIC_IPI_VECTOR(0), x); 710 /* IPI1 - DDB */ 711 x = IPI_VECTOR_DDB; 712 x |= 15 << OPENPIC_PRIORITY_SHIFT; 713 openpic_write(OPENPIC_IPI_VECTOR(1), x); 714 715 /* XXX - ncpus */ 716 evcount_attach(&ipi_nop[0], "ipi_nop0", &ipi_nopirq); 717 evcount_attach(&ipi_nop[1], "ipi_nop1", &ipi_nopirq); 718 evcount_attach(&ipi_ddb[0], "ipi_ddb0", &ipi_ddbirq); 719 evcount_attach(&ipi_ddb[1], "ipi_ddb1", &ipi_ddbirq); 720 #endif 721 722 /* clear all pending interrunts */ 723 for (irq = 0; irq < ICU_LEN; irq++) { 724 openpic_read_irq(0); 725 openpic_eoi(0); 726 } 727 728 #if 0 729 openpic_write(OPENPIC_SPURIOUS_VECTOR, 255); 730 #endif 731 732 install_extint(openpic_ext_intr); 733 734 openpic_set_priority(ci->ci_cpuid, 0); 735 } 736 737 void 738 openpic_ipi_ddb() 739 { 740 #ifdef OPENPIC_NOISY 741 printf("ipi_ddb() called\n"); 742 #endif 743 Debugger(); 744 } 745