1 /* $OpenBSD: openpic.c,v 1.87 2021/03/11 11:16:58 jsg 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 "hpb.h" 41 42 #include <sys/param.h> 43 #include <sys/device.h> 44 #include <sys/systm.h> 45 #include <sys/malloc.h> 46 #include <sys/atomic.h> 47 48 #include <uvm/uvm_extern.h> 49 50 #include <machine/autoconf.h> 51 #include <machine/intr.h> 52 #include <machine/psl.h> 53 #include <machine/pio.h> 54 #include <dev/ofw/openfirm.h> 55 56 #include <macppc/dev/openpicreg.h> 57 58 #ifdef OPENPIC_DEBUG 59 #define DPRINTF(x...) do { printf(x); } while(0) 60 #else 61 #define DPRINTF(x...) 62 #endif 63 64 #define ICU_LEN 128 65 int openpic_numirq = ICU_LEN; 66 #define LEGAL_IRQ(x) ((x >= 0) && (x < ICU_LEN)) 67 68 int openpic_pri_share[IPL_NUM]; 69 70 struct intrq openpic_handler[ICU_LEN]; 71 72 struct openpic_softc { 73 struct device sc_dev; 74 }; 75 76 vaddr_t openpic_base; 77 int openpic_big_endian; 78 struct evcount openpic_spurious; 79 int openpic_spurious_irq = 255; 80 81 int openpic_match(struct device *parent, void *cf, void *aux); 82 void openpic_attach(struct device *, struct device *, void *); 83 84 int openpic_splraise(int); 85 int openpic_spllower(int); 86 void openpic_splx(int); 87 88 u_int openpic_read(int reg); 89 void openpic_write(int reg, u_int val); 90 91 void openpic_acknowledge_irq(int, int); 92 void openpic_enable_irq(int, int, int); 93 void openpic_disable_irq(int, int); 94 95 void openpic_calc_mask(void); 96 void openpic_set_priority(int, int); 97 void *openpic_intr_establish(void *, int, int, int, int (*)(void *), void *, 98 const char *); 99 void openpic_intr_disestablish(void *, void *); 100 void openpic_collect_preconf_intr(void); 101 void openpic_ext_intr(void); 102 int openpic_ext_intr_handler(struct intrhand *, int *); 103 104 /* Generic IRQ management routines. */ 105 void openpic_gen_acknowledge_irq(int, int); 106 void openpic_gen_enable_irq(int, int, int); 107 void openpic_gen_disable_irq(int, int); 108 109 #if NHPB > 0 110 /* CPC945 IRQ management routines. */ 111 void openpic_cpc945_acknowledge_irq(int, int); 112 void openpic_cpc945_enable_irq(int, int, int); 113 void openpic_cpc945_disable_irq(int, int); 114 #endif /* NHPB */ 115 116 struct openpic_ops { 117 void (*acknowledge_irq)(int, int); 118 void (*enable_irq)(int, int, int); 119 void (*disable_irq)(int, int); 120 } openpic_ops = { 121 openpic_gen_acknowledge_irq, 122 openpic_gen_enable_irq, 123 openpic_gen_disable_irq 124 }; 125 126 #ifdef MULTIPROCESSOR 127 void openpic_ipi_ddb(void); 128 129 /* IRQ vector used for inter-processor interrupts. */ 130 #define IPI_VECTOR_NOP 64 131 #define IPI_VECTOR_DDB 65 132 133 static struct evcount ipi_count; 134 135 static int ipi_irq = IPI_VECTOR_NOP; 136 137 intr_send_ipi_t openpic_send_ipi; 138 #endif /* MULTIPROCESSOR */ 139 140 const struct cfattach openpic_ca = { 141 sizeof(struct openpic_softc), openpic_match, openpic_attach 142 }; 143 144 struct cfdriver openpic_cd = { 145 NULL, "openpic", DV_DULL 146 }; 147 148 u_int 149 openpic_read(int reg) 150 { 151 char *addr = (void *)(openpic_base + reg); 152 153 membar_sync(); 154 if (openpic_big_endian) 155 return in32(addr); 156 else 157 return in32rb(addr); 158 } 159 160 void 161 openpic_write(int reg, u_int val) 162 { 163 char *addr = (void *)(openpic_base + reg); 164 165 if (openpic_big_endian) 166 out32(addr, val); 167 else 168 out32rb(addr, val); 169 membar_sync(); 170 } 171 172 static inline int 173 openpic_read_irq(int cpu) 174 { 175 return openpic_read(OPENPIC_IACK(cpu)) & OPENPIC_VECTOR_MASK; 176 } 177 178 static inline void 179 openpic_eoi(int cpu) 180 { 181 openpic_write(OPENPIC_EOI(cpu), 0); 182 } 183 184 int 185 openpic_match(struct device *parent, void *cf, void *aux) 186 { 187 char type[40]; 188 int pirq; 189 struct confargs *ca = aux; 190 191 bzero (type, sizeof(type)); 192 193 if (OF_getprop(ca->ca_node, "interrupt-parent", &pirq, sizeof(pirq)) 194 == sizeof(pirq)) 195 return 0; /* XXX */ 196 197 if (strcmp(ca->ca_name, "interrupt-controller") != 0 && 198 strcmp(ca->ca_name, "mpic") != 0) 199 return 0; 200 201 OF_getprop(ca->ca_node, "device_type", type, sizeof(type)); 202 if (strcmp(type, "open-pic") != 0) 203 return 0; 204 205 if (ca->ca_nreg < 8) 206 return 0; 207 208 return 1; 209 } 210 211 void 212 openpic_attach(struct device *parent, struct device *self, void *aux) 213 { 214 struct cpu_info *ci = curcpu(); 215 struct confargs *ca = aux; 216 struct intrq *iq; 217 uint32_t reg = 0; 218 int i, irq; 219 u_int x; 220 221 if (OF_getprop(ca->ca_node, "big-endian", ®, sizeof reg) == 0) 222 openpic_big_endian = 1; 223 224 openpic_base = (vaddr_t) mapiodev (ca->ca_baseaddr + 225 ca->ca_reg[0], 0x40000); 226 227 /* Reset the PIC */ 228 x = openpic_read(OPENPIC_CONFIG) | OPENPIC_CONFIG_RESET; 229 openpic_write(OPENPIC_CONFIG, x); 230 231 while (openpic_read(OPENPIC_CONFIG) & OPENPIC_CONFIG_RESET) 232 delay(100); 233 234 /* openpic may support more than 128 interrupts but driver doesn't */ 235 openpic_numirq = ((openpic_read(OPENPIC_FEATURE) >> 16) & 0x7f)+1; 236 237 printf(": version 0x%x feature %x %s", 238 openpic_read(OPENPIC_VENDOR_ID), 239 openpic_read(OPENPIC_FEATURE), 240 openpic_big_endian ? "BE" : "LE" ); 241 242 openpic_set_priority(ci->ci_cpuid, 15); 243 244 /* disable all interrupts */ 245 for (irq = 0; irq < openpic_numirq; irq++) 246 openpic_write(OPENPIC_SRC_VECTOR(irq), OPENPIC_IMASK); 247 248 for (i = 0; i < openpic_numirq; i++) { 249 iq = &openpic_handler[i]; 250 TAILQ_INIT(&iq->iq_list); 251 } 252 253 /* we don't need 8259 pass through mode */ 254 x = openpic_read(OPENPIC_CONFIG); 255 x |= OPENPIC_CONFIG_8259_PASSTHRU_DISABLE; 256 openpic_write(OPENPIC_CONFIG, x); 257 258 /* initialize all vectors to something sane */ 259 for (irq = 0; irq < ICU_LEN; irq++) { 260 x = irq; 261 x |= OPENPIC_IMASK; 262 x |= OPENPIC_POLARITY_NEGATIVE; 263 x |= OPENPIC_SENSE_LEVEL; 264 x |= 8 << OPENPIC_PRIORITY_SHIFT; 265 openpic_write(OPENPIC_SRC_VECTOR(irq), x); 266 } 267 268 /* send all interrupts to cpu 0 */ 269 for (irq = 0; irq < openpic_numirq; irq++) 270 openpic_write(OPENPIC_IDEST(irq), 1 << 0); 271 272 /* clear all pending interrunts */ 273 for (irq = 0; irq < ICU_LEN; irq++) { 274 openpic_read_irq(ci->ci_cpuid); 275 openpic_eoi(ci->ci_cpuid); 276 } 277 278 #ifdef MULTIPROCESSOR 279 /* Set up inter-processor interrupts. */ 280 /* IPI0 - NOP */ 281 x = IPI_VECTOR_NOP; 282 x |= 15 << OPENPIC_PRIORITY_SHIFT; 283 openpic_write(OPENPIC_IPI_VECTOR(0), x); 284 /* IPI1 - DDB */ 285 x = IPI_VECTOR_DDB; 286 x |= 15 << OPENPIC_PRIORITY_SHIFT; 287 openpic_write(OPENPIC_IPI_VECTOR(1), x); 288 289 evcount_attach(&ipi_count, "ipi", &ipi_irq); 290 #endif 291 292 /* clear all pending interrunts */ 293 for (irq = 0; irq < ICU_LEN; irq++) { 294 openpic_read_irq(0); 295 openpic_eoi(0); 296 } 297 298 #if 0 299 openpic_write(OPENPIC_SPURIOUS_VECTOR, 255); 300 #endif 301 302 #if NHPB > 0 303 /* Only U4 systems have a big-endian MPIC. */ 304 if (openpic_big_endian) { 305 openpic_ops.acknowledge_irq = openpic_cpc945_acknowledge_irq; 306 openpic_ops.enable_irq = openpic_cpc945_enable_irq; 307 openpic_ops.disable_irq = openpic_cpc945_disable_irq; 308 } 309 #endif 310 311 install_extint(openpic_ext_intr); 312 313 openpic_set_priority(ci->ci_cpuid, 0); 314 315 intr_establish_func = openpic_intr_establish; 316 intr_disestablish_func = openpic_intr_disestablish; 317 #ifdef MULTIPROCESSOR 318 intr_send_ipi_func = openpic_send_ipi; 319 #endif 320 321 ppc_smask_init(); 322 323 openpic_collect_preconf_intr(); 324 325 evcount_attach(&openpic_spurious, "spurious", &openpic_spurious_irq); 326 327 ppc_intr_func.raise = openpic_splraise; 328 ppc_intr_func.lower = openpic_spllower; 329 ppc_intr_func.x = openpic_splx; 330 331 openpic_set_priority(0, ci->ci_cpl); 332 333 ppc_intr_enable(1); 334 335 printf("\n"); 336 } 337 338 /* Must be called with interrupt disable. */ 339 static inline void 340 openpic_setipl(int newcpl) 341 { 342 struct cpu_info *ci = curcpu(); 343 344 ci->ci_cpl = newcpl; 345 openpic_set_priority(ci->ci_cpuid, newcpl); 346 } 347 348 int 349 openpic_splraise(int newcpl) 350 { 351 struct cpu_info *ci = curcpu(); 352 int ocpl = ci->ci_cpl; 353 int s; 354 355 newcpl = openpic_pri_share[newcpl]; 356 if (ocpl > newcpl) 357 newcpl = ocpl; 358 359 s = ppc_intr_disable(); 360 openpic_setipl(newcpl); 361 ppc_intr_enable(s); 362 363 return ocpl; 364 } 365 366 int 367 openpic_spllower(int newcpl) 368 { 369 struct cpu_info *ci = curcpu(); 370 int ocpl = ci->ci_cpl; 371 372 openpic_splx(newcpl); 373 374 return ocpl; 375 } 376 377 void 378 openpic_splx(int newcpl) 379 { 380 struct cpu_info *ci = curcpu(); 381 int intr, s; 382 383 intr = ppc_intr_disable(); 384 openpic_setipl(newcpl); 385 if (newcpl < IPL_SOFTTTY && (ci->ci_ipending & ppc_smask[newcpl])) { 386 s = splsofttty(); 387 dosoftint(newcpl); 388 openpic_setipl(s); /* no-overhead splx */ 389 } 390 ppc_intr_enable(intr); 391 } 392 393 void 394 openpic_collect_preconf_intr(void) 395 { 396 int i; 397 for (i = 0; i < ppc_configed_intr_cnt; i++) { 398 DPRINTF("\n\t%s irq %d level %d fun %p arg %p", 399 ppc_configed_intr[i].ih_what, ppc_configed_intr[i].ih_irq, 400 ppc_configed_intr[i].ih_level, ppc_configed_intr[i].ih_fun, 401 ppc_configed_intr[i].ih_arg); 402 openpic_intr_establish(NULL, ppc_configed_intr[i].ih_irq, 403 IST_LEVEL, ppc_configed_intr[i].ih_level, 404 ppc_configed_intr[i].ih_fun, ppc_configed_intr[i].ih_arg, 405 ppc_configed_intr[i].ih_what); 406 } 407 } 408 409 /* 410 * Register an interrupt handler. 411 */ 412 void * 413 openpic_intr_establish(void *lcv, int irq, int type, int level, 414 int (*ih_fun)(void *), void *ih_arg, const char *name) 415 { 416 struct intrhand *ih; 417 struct intrq *iq; 418 int s, flags; 419 420 if (!LEGAL_IRQ(irq) || type == IST_NONE) { 421 printf("%s: bogus irq %d or type %d", __func__, irq, type); 422 return (NULL); 423 } 424 425 /* no point in sleeping unless someone can free memory. */ 426 ih = malloc(sizeof *ih, M_DEVBUF, cold ? M_NOWAIT : M_WAITOK); 427 if (ih == NULL) 428 panic("%s: can't malloc handler info", __func__); 429 430 iq = &openpic_handler[irq]; 431 switch (iq->iq_ist) { 432 case IST_NONE: 433 iq->iq_ist = type; 434 break; 435 case IST_EDGE: 436 intr_shared_edge = 1; 437 /* FALLTHROUGH */ 438 case IST_LEVEL: 439 if (type == iq->iq_ist) 440 break; 441 case IST_PULSE: 442 if (type != IST_NONE) 443 panic("intr_establish: can't share %s with %s", 444 ppc_intr_typename(iq->iq_ist), 445 ppc_intr_typename(type)); 446 break; 447 } 448 449 flags = level & IPL_MPSAFE; 450 level &= ~IPL_MPSAFE; 451 452 KASSERT(level <= IPL_TTY || level >= IPL_CLOCK || flags & IPL_MPSAFE); 453 454 ih->ih_fun = ih_fun; 455 ih->ih_arg = ih_arg; 456 ih->ih_level = level; 457 ih->ih_flags = flags; 458 ih->ih_irq = irq; 459 460 evcount_attach(&ih->ih_count, name, &ih->ih_irq); 461 462 /* 463 * Append handler to end of list 464 */ 465 s = ppc_intr_disable(); 466 467 TAILQ_INSERT_TAIL(&iq->iq_list, ih, ih_list); 468 openpic_calc_mask(); 469 470 ppc_intr_enable(s); 471 472 return (ih); 473 } 474 475 /* 476 * Deregister an interrupt handler. 477 */ 478 void 479 openpic_intr_disestablish(void *lcp, void *arg) 480 { 481 struct intrhand *ih = arg; 482 int irq = ih->ih_irq; 483 struct intrq *iq = &openpic_handler[irq]; 484 int s; 485 486 if (!LEGAL_IRQ(irq)) { 487 printf("%s: bogus irq %d", __func__, irq); 488 return; 489 } 490 491 /* 492 * Remove the handler from the chain. 493 */ 494 s = ppc_intr_disable(); 495 496 TAILQ_REMOVE(&iq->iq_list, ih, ih_list); 497 openpic_calc_mask(); 498 499 ppc_intr_enable(s); 500 501 evcount_detach(&ih->ih_count); 502 free(ih, M_DEVBUF, sizeof *ih); 503 504 if (TAILQ_EMPTY(&iq->iq_list)) 505 iq->iq_ist = IST_NONE; 506 } 507 508 /* 509 * Recalculate the interrupt masks from scratch. 510 * We could code special registry and deregistry versions of this function that 511 * would be faster, but the code would be nastier, and we don't expect this to 512 * happen very much anyway. 513 */ 514 515 void 516 openpic_calc_mask(void) 517 { 518 struct cpu_info *ci = curcpu(); 519 int irq; 520 struct intrhand *ih; 521 int i; 522 523 /* disable all openpic interrupts */ 524 openpic_set_priority(ci->ci_cpuid, 15); 525 526 for (i = IPL_NONE; i < IPL_NUM; i++) { 527 openpic_pri_share[i] = i; 528 } 529 530 for (irq = 0; irq < openpic_numirq; irq++) { 531 int maxipl = IPL_NONE; 532 int minipl = IPL_HIGH; 533 struct intrq *iq = &openpic_handler[irq]; 534 535 TAILQ_FOREACH(ih, &iq->iq_list, ih_list) { 536 if (ih->ih_level > maxipl) 537 maxipl = ih->ih_level; 538 if (ih->ih_level < minipl) 539 minipl = ih->ih_level; 540 } 541 542 if (maxipl == IPL_NONE) { 543 minipl = IPL_NONE; /* Interrupt not enabled */ 544 545 openpic_disable_irq(irq, iq->iq_ist); 546 } else { 547 for (i = minipl; i <= maxipl; i++) { 548 openpic_pri_share[i] = maxipl; 549 } 550 openpic_enable_irq(irq, iq->iq_ist, maxipl); 551 } 552 553 iq->iq_ipl = maxipl; 554 } 555 556 /* restore interrupts */ 557 openpic_set_priority(ci->ci_cpuid, ci->ci_cpl); 558 } 559 560 void 561 openpic_gen_acknowledge_irq(int irq, int cpuid) 562 { 563 openpic_eoi(cpuid); 564 } 565 566 void 567 openpic_gen_enable_irq(int irq, int ist, int pri) 568 { 569 u_int x; 570 571 x = irq; 572 573 if (ist == IST_LEVEL) 574 x |= OPENPIC_SENSE_LEVEL; 575 else 576 x |= OPENPIC_SENSE_EDGE; 577 x |= OPENPIC_POLARITY_NEGATIVE; 578 x |= pri << OPENPIC_PRIORITY_SHIFT; 579 openpic_write(OPENPIC_SRC_VECTOR(irq), x); 580 } 581 582 void 583 openpic_gen_disable_irq(int irq, int ist) 584 { 585 u_int x; 586 587 x = openpic_read(OPENPIC_SRC_VECTOR(irq)); 588 x |= OPENPIC_IMASK; 589 openpic_write(OPENPIC_SRC_VECTOR(irq), x); 590 } 591 592 void 593 openpic_set_priority(int cpu, int pri) 594 { 595 openpic_write(OPENPIC_CPU_PRIORITY(cpu), pri); 596 } 597 598 int openpic_irqnest[PPC_MAXPROCS]; 599 int openpic_irqloop[PPC_MAXPROCS]; 600 601 void 602 openpic_ext_intr(void) 603 { 604 struct cpu_info *ci = curcpu(); 605 int irq, pcpl, ret; 606 int maxipl = IPL_NONE; 607 struct intrhand *ih; 608 struct intrq *iq; 609 int spurious; 610 611 pcpl = ci->ci_cpl; 612 613 openpic_irqloop[ci->ci_cpuid] = 0; 614 irq = openpic_read_irq(ci->ci_cpuid); 615 openpic_irqnest[ci->ci_cpuid]++; 616 617 while (irq != 255) { 618 openpic_irqloop[ci->ci_cpuid]++; 619 #ifdef OPENPIC_DEBUG 620 if (openpic_irqloop[ci->ci_cpuid] > 20 || 621 openpic_irqnest[ci->ci_cpuid] > 3) { 622 printf("irqloop %d irqnest %d\n", 623 openpic_irqloop[ci->ci_cpuid], 624 openpic_irqnest[ci->ci_cpuid]); 625 } 626 #endif 627 if (openpic_irqloop[ci->ci_cpuid] > 20) { 628 DPRINTF("irqloop %d irqnest %d: returning\n", 629 openpic_irqloop[ci->ci_cpuid], 630 openpic_irqnest[ci->ci_cpuid]); 631 openpic_irqnest[ci->ci_cpuid]--; 632 return; 633 } 634 #ifdef MULTIPROCESSOR 635 if (irq == IPI_VECTOR_NOP || irq == IPI_VECTOR_DDB) { 636 ipi_count.ec_count++; 637 openpic_eoi(ci->ci_cpuid); 638 if (irq == IPI_VECTOR_DDB) 639 openpic_ipi_ddb(); 640 irq = openpic_read_irq(ci->ci_cpuid); 641 continue; 642 } 643 #endif 644 iq = &openpic_handler[irq]; 645 646 #ifdef OPENPIC_DEBUG 647 if (iq->iq_ipl <= pcpl) 648 printf("invalid interrupt %d lvl %d at %d hw %d\n", 649 irq, iq->iq_ipl, pcpl, 650 openpic_read(OPENPIC_CPU_PRIORITY(ci->ci_cpuid))); 651 #endif 652 653 if (iq->iq_ipl > maxipl) 654 maxipl = iq->iq_ipl; 655 openpic_splraise(iq->iq_ipl); 656 openpic_acknowledge_irq(irq, ci->ci_cpuid); 657 658 spurious = 1; 659 TAILQ_FOREACH(ih, &iq->iq_list, ih_list) { 660 ppc_intr_enable(1); 661 ret = openpic_ext_intr_handler(ih, &spurious); 662 (void)ppc_intr_disable(); 663 if (intr_shared_edge == 00 && ret == 1) 664 break; 665 } 666 if (spurious) { 667 openpic_spurious.ec_count++; 668 DPRINTF("spurious intr %d\n", irq); 669 } 670 671 uvmexp.intrs++; 672 openpic_setipl(pcpl); 673 674 irq = openpic_read_irq(ci->ci_cpuid); 675 } 676 677 openpic_splx(pcpl); /* Process pendings. */ 678 openpic_irqnest[ci->ci_cpuid]--; 679 } 680 681 int 682 openpic_ext_intr_handler(struct intrhand *ih, int *spurious) 683 { 684 int ret; 685 #ifdef MULTIPROCESSOR 686 int need_lock; 687 688 if (ih->ih_flags & IPL_MPSAFE) 689 need_lock = 0; 690 else 691 need_lock = 1; 692 693 if (need_lock) 694 KERNEL_LOCK(); 695 #endif 696 ret = (*ih->ih_fun)(ih->ih_arg); 697 if (ret) { 698 ih->ih_count.ec_count++; 699 *spurious = 0; 700 } 701 702 #ifdef MULTIPROCESSOR 703 if (need_lock) 704 KERNEL_UNLOCK(); 705 #endif 706 707 return (ret); 708 } 709 710 void 711 openpic_acknowledge_irq(int irq, int cpuid) 712 { 713 (openpic_ops.acknowledge_irq)(irq, cpuid); 714 } 715 716 void 717 openpic_enable_irq(int irq, int ist, int pri) 718 { 719 (openpic_ops.enable_irq)(irq, ist, pri); 720 } 721 722 void 723 openpic_disable_irq(int irq, int ist) 724 { 725 (openpic_ops.disable_irq)(irq, ist); 726 } 727 728 #ifdef MULTIPROCESSOR 729 void 730 openpic_send_ipi(struct cpu_info *ci, int id) 731 { 732 switch (id) { 733 case PPC_IPI_NOP: 734 id = 0; 735 break; 736 case PPC_IPI_DDB: 737 id = 1; 738 break; 739 default: 740 panic("invalid ipi send to cpu %d %d", ci->ci_cpuid, id); 741 } 742 743 openpic_write(OPENPIC_IPI(curcpu()->ci_cpuid, id), 1 << ci->ci_cpuid); 744 } 745 746 void 747 openpic_ipi_ddb(void) 748 { 749 #ifdef DDB 750 db_enter(); 751 #endif 752 } 753 #endif /* MULTIPROCESSOR */ 754 755 #if NHPB > 0 756 extern int hpb_enable_irq(int, int); 757 extern int hpb_disable_irq(int, int); 758 extern void hpb_eoi(int); 759 760 void 761 openpic_cpc945_acknowledge_irq(int irq, int cpuid) 762 { 763 hpb_eoi(irq); 764 openpic_gen_acknowledge_irq(irq, cpuid); 765 } 766 767 void 768 openpic_cpc945_enable_irq(int irq, int ist, int pri) 769 { 770 if (hpb_enable_irq(irq, ist)) { 771 u_int x = irq; 772 773 x |= OPENPIC_SENSE_EDGE; 774 x |= OPENPIC_POLARITY_POSITIVE; 775 x |= pri << OPENPIC_PRIORITY_SHIFT; 776 openpic_write(OPENPIC_SRC_VECTOR(irq), x); 777 778 hpb_eoi(irq); 779 } else 780 openpic_gen_enable_irq(irq, ist, pri); 781 } 782 783 void 784 openpic_cpc945_disable_irq(int irq, int ist) 785 { 786 hpb_disable_irq(irq, ist); 787 openpic_gen_disable_irq(irq, ist); 788 } 789 #endif /* NHPB */ 790 791