1 /* $OpenBSD: intr.c,v 1.23 2024/08/05 13:55:34 kettenis Exp $ */ 2 /* 3 * Copyright (c) 2011 Dale Rahn <drahn@openbsd.org> 4 * 5 * Permission to use, copy, modify, and distribute this software for any 6 * purpose with or without fee is hereby granted, provided that the above 7 * copyright notice and this permission notice appear in all copies. 8 * 9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 */ 17 18 #include <sys/param.h> 19 #include <sys/systm.h> 20 #include <sys/malloc.h> 21 22 #include <arm/cpufunc.h> 23 #include <machine/cpu.h> 24 #include <machine/intr.h> 25 26 #include <dev/ofw/openfirm.h> 27 28 int arm_intr_get_parent(int); 29 uint32_t arm_intr_map_msi(int, uint64_t *); 30 31 void *arm_intr_prereg_establish_fdt(void *, int *, int, struct cpu_info *, 32 int (*)(void *), void *, char *); 33 void arm_intr_prereg_disestablish_fdt(void *); 34 35 int arm_dflt_splraise(int); 36 int arm_dflt_spllower(int); 37 void arm_dflt_splx(int); 38 void arm_dflt_setipl(int); 39 void *arm_dflt_intr_establish(int irqno, int level, struct cpu_info *, 40 int (*func)(void *), void *cookie, char *name); 41 void arm_dflt_intr_disestablish(void *cookie); 42 const char *arm_dflt_intr_string(void *cookie); 43 44 void arm_dflt_intr(void *); 45 void arm_intr(void *); 46 47 #define SI_TO_IRQBIT(x) (1 << (x)) 48 uint32_t arm_smask[NIPL]; 49 50 struct arm_intr_func arm_intr_func = { 51 arm_dflt_splraise, 52 arm_dflt_spllower, 53 arm_dflt_splx, 54 arm_dflt_setipl, 55 arm_dflt_intr_establish, 56 arm_dflt_intr_disestablish, 57 arm_dflt_intr_string 58 }; 59 60 void (*arm_intr_dispatch)(void *) = arm_dflt_intr; 61 62 void 63 arm_intr(void *frame) 64 { 65 /* XXX - change this to have irq_dispatch use function pointer */ 66 (*arm_intr_dispatch)(frame); 67 } 68 void 69 arm_dflt_intr(void *frame) 70 { 71 panic("arm_dflt_intr() called"); 72 } 73 74 75 void * 76 arm_intr_establish(int irqno, int level, int (*func)(void *), 77 void *cookie, char *name) 78 { 79 return arm_intr_func.intr_establish(irqno, level, NULL, func, cookie, name); 80 } 81 82 void 83 arm_intr_disestablish(void *cookie) 84 { 85 arm_intr_func.intr_disestablish(cookie); 86 } 87 88 const char * 89 arm_intr_string(void *cookie) 90 { 91 return arm_intr_func.intr_string(cookie); 92 } 93 94 /* 95 * Find the interrupt parent by walking up the tree. 96 */ 97 int 98 arm_intr_get_parent(int node) 99 { 100 uint32_t phandle; 101 102 while (node) { 103 phandle = OF_getpropint(node, "interrupt-parent", 0); 104 if (phandle) 105 return OF_getnodebyphandle(phandle); 106 node = OF_parent(node); 107 if (OF_getpropbool(node, "interrupt-controller")) 108 return node; 109 } 110 111 return 0; 112 } 113 114 uint32_t 115 arm_intr_map_msi(int node, uint64_t *data) 116 { 117 uint64_t msi_base; 118 uint32_t phandle = 0; 119 uint32_t *cell; 120 uint32_t *map; 121 uint32_t mask, rid_base, rid; 122 int i, len, length, mcells, ncells; 123 124 len = OF_getproplen(node, "msi-map"); 125 if (len <= 0) { 126 while (node && !phandle) { 127 phandle = OF_getpropint(node, "msi-parent", 0); 128 node = OF_parent(node); 129 } 130 131 return phandle; 132 } 133 134 map = malloc(len, M_TEMP, M_WAITOK); 135 OF_getpropintarray(node, "msi-map", map, len); 136 137 mask = OF_getpropint(node, "msi-map-mask", 0xffff); 138 rid = *data & mask; 139 140 cell = map; 141 ncells = len / sizeof(uint32_t); 142 while (ncells > 1) { 143 node = OF_getnodebyphandle(cell[1]); 144 if (node == 0) 145 goto out; 146 147 /* 148 * Some device trees (e.g. those for the Rockchip 149 * RK3399 boards) are missing a #msi-cells property. 150 * Assume the msi-specifier uses a single cell in that 151 * case. 152 */ 153 mcells = OF_getpropint(node, "#msi-cells", 1); 154 if (ncells < mcells + 3) 155 goto out; 156 157 rid_base = cell[0]; 158 length = cell[2 + mcells]; 159 msi_base = cell[2]; 160 for (i = 1; i < mcells; i++) { 161 msi_base <<= 32; 162 msi_base |= cell[2 + i]; 163 } 164 if (rid >= rid_base && rid < rid_base + length) { 165 *data = msi_base + (rid - rid_base); 166 phandle = cell[1]; 167 break; 168 } 169 170 cell += (3 + mcells); 171 ncells -= (3 + mcells); 172 } 173 174 out: 175 free(map, M_TEMP, len); 176 return phandle; 177 } 178 179 /* 180 * Interrupt pre-registration. 181 * 182 * To allow device drivers to establish interrupt handlers before all 183 * relevant interrupt controllers have been attached, we support 184 * pre-registration of interrupt handlers. For each node in the 185 * device tree that has an "interrupt-controller" property, we 186 * register a dummy interrupt controller that simply stashes away all 187 * relevant details of the interrupt handler being established. 188 * Later, when the real interrupt controller registers itself, we 189 * establish those interrupt handlers based on that information. 190 */ 191 192 #define MAX_INTERRUPT_CELLS 4 193 194 struct intr_prereg { 195 LIST_ENTRY(intr_prereg) ip_list; 196 uint32_t ip_phandle; 197 uint32_t ip_cell[MAX_INTERRUPT_CELLS]; 198 199 int ip_level; 200 struct cpu_info *ip_ci; 201 int (*ip_func)(void *); 202 void *ip_arg; 203 char *ip_name; 204 205 struct interrupt_controller *ip_ic; 206 void *ip_ih; 207 }; 208 209 LIST_HEAD(, intr_prereg) prereg_interrupts = 210 LIST_HEAD_INITIALIZER(prereg_interrupts); 211 212 void * 213 arm_intr_prereg_establish_fdt(void *cookie, int *cell, int level, 214 struct cpu_info *ci, int (*func)(void *), void *arg, char *name) 215 { 216 struct interrupt_controller *ic = cookie; 217 struct intr_prereg *ip; 218 int i; 219 220 ip = malloc(sizeof(struct intr_prereg), M_DEVBUF, M_ZERO | M_WAITOK); 221 ip->ip_phandle = ic->ic_phandle; 222 for (i = 0; i < ic->ic_cells; i++) 223 ip->ip_cell[i] = cell[i]; 224 ip->ip_level = level; 225 ip->ip_ci = ci; 226 ip->ip_func = func; 227 ip->ip_arg = arg; 228 ip->ip_name = name; 229 LIST_INSERT_HEAD(&prereg_interrupts, ip, ip_list); 230 231 return ip; 232 } 233 234 void 235 arm_intr_prereg_disestablish_fdt(void *cookie) 236 { 237 struct intr_prereg *ip = cookie; 238 struct interrupt_controller *ic = ip->ip_ic; 239 240 if (ip->ip_ic != NULL && ip->ip_ih != NULL) 241 ic->ic_disestablish(ip->ip_ih); 242 243 if (ip->ip_ic != NULL) 244 LIST_REMOVE(ip, ip_list); 245 246 free(ip, M_DEVBUF, sizeof(*ip)); 247 } 248 249 void 250 arm_intr_init_fdt_recurse(int node) 251 { 252 struct interrupt_controller *ic; 253 254 if (OF_getproplen(node, "interrupt-controller") >= 0) { 255 ic = malloc(sizeof(struct interrupt_controller), 256 M_DEVBUF, M_ZERO | M_WAITOK); 257 ic->ic_node = node; 258 ic->ic_cookie = ic; 259 ic->ic_establish = arm_intr_prereg_establish_fdt; 260 ic->ic_disestablish = arm_intr_prereg_disestablish_fdt; 261 arm_intr_register_fdt(ic); 262 } 263 264 for (node = OF_child(node); node; node = OF_peer(node)) 265 arm_intr_init_fdt_recurse(node); 266 } 267 268 void 269 arm_intr_init_fdt(void) 270 { 271 int node = OF_peer(0); 272 273 if (node) 274 arm_intr_init_fdt_recurse(node); 275 } 276 277 LIST_HEAD(, interrupt_controller) interrupt_controllers = 278 LIST_HEAD_INITIALIZER(interrupt_controllers); 279 280 void 281 arm_intr_register_fdt(struct interrupt_controller *ic) 282 { 283 struct intr_prereg *ip, *tip; 284 285 ic->ic_cells = OF_getpropint(ic->ic_node, "#interrupt-cells", 0); 286 ic->ic_phandle = OF_getpropint(ic->ic_node, "phandle", 0); 287 KASSERT(ic->ic_cells <= MAX_INTERRUPT_CELLS); 288 289 LIST_INSERT_HEAD(&interrupt_controllers, ic, ic_list); 290 291 /* Establish pre-registered interrupt handlers. */ 292 LIST_FOREACH_SAFE(ip, &prereg_interrupts, ip_list, tip) { 293 if (ip->ip_phandle != ic->ic_phandle) 294 continue; 295 296 ip->ip_ic = ic; 297 ip->ip_ih = ic->ic_establish(ic->ic_cookie, ip->ip_cell, 298 ip->ip_level, ip->ip_ci, ip->ip_func, ip->ip_arg, 299 ip->ip_name); 300 if (ip->ip_ih == NULL) 301 printf("can't establish interrupt %s\n", ip->ip_name); 302 303 LIST_REMOVE(ip, ip_list); 304 } 305 } 306 307 struct arm_intr_handle { 308 struct interrupt_controller *ih_ic; 309 void *ih_ih; 310 }; 311 312 void * 313 arm_intr_establish_fdt(int node, int level, int (*func)(void *), 314 void *cookie, char *name) 315 { 316 return arm_intr_establish_fdt_idx(node, 0, level, func, cookie, name); 317 } 318 319 void * 320 arm_intr_establish_fdt_cpu(int node, int level, struct cpu_info *ci, 321 int (*func)(void *), void *cookie, char *name) 322 { 323 return arm_intr_establish_fdt_idx_cpu(node, 0, level, ci, func, 324 cookie, name); 325 } 326 327 void * 328 arm_intr_establish_fdt_idx(int node, int idx, int level, int (*func)(void *), 329 void *cookie, char *name) 330 { 331 return arm_intr_establish_fdt_idx_cpu(node, idx, level, NULL, func, 332 cookie, name); 333 } 334 335 void * 336 arm_intr_establish_fdt_idx_cpu(int node, int idx, int level, struct cpu_info *ci, 337 int (*func)(void *), void *cookie, char *name) 338 { 339 struct interrupt_controller *ic; 340 int i, len, ncells, parent; 341 int extended = 1; 342 uint32_t *cell, *cells, phandle; 343 struct arm_intr_handle *ih; 344 void *val = NULL; 345 346 len = OF_getproplen(node, "interrupts-extended"); 347 if (len <= 0) { 348 len = OF_getproplen(node, "interrupts"); 349 extended = 0; 350 } 351 if (len <= 0 || (len % sizeof(uint32_t) != 0)) 352 return NULL; 353 354 /* Old style. */ 355 if (!extended) { 356 parent = arm_intr_get_parent(node); 357 LIST_FOREACH(ic, &interrupt_controllers, ic_list) { 358 if (ic->ic_node == parent) 359 break; 360 } 361 362 if (ic == NULL) 363 return NULL; 364 } 365 366 cell = cells = malloc(len, M_TEMP, M_WAITOK); 367 if (extended) 368 OF_getpropintarray(node, "interrupts-extended", cells, len); 369 else 370 OF_getpropintarray(node, "interrupts", cells, len); 371 ncells = len / sizeof(uint32_t); 372 373 for (i = 0; i <= idx && ncells > 0; i++) { 374 if (extended) { 375 phandle = cell[0]; 376 377 /* Handle "empty" phandle reference. */ 378 if (phandle == 0) { 379 cell++; 380 ncells--; 381 continue; 382 } 383 384 LIST_FOREACH(ic, &interrupt_controllers, ic_list) { 385 if (ic->ic_phandle == phandle) 386 break; 387 } 388 389 if (ic == NULL) 390 break; 391 392 cell++; 393 ncells--; 394 } 395 396 if (i == idx && ncells >= ic->ic_cells && ic->ic_establish) { 397 val = ic->ic_establish(ic->ic_cookie, cell, level, 398 ci, func, cookie, name); 399 break; 400 } 401 402 cell += ic->ic_cells; 403 ncells -= ic->ic_cells; 404 } 405 406 free(cells, M_TEMP, len); 407 408 if (val == NULL) 409 return NULL; 410 411 ih = malloc(sizeof(*ih), M_DEVBUF, M_WAITOK); 412 ih->ih_ic = ic; 413 ih->ih_ih = val; 414 415 return ih; 416 } 417 418 void * 419 arm_intr_establish_fdt_imap(int node, int *reg, int nreg, int level, 420 int (*func)(void *), void *cookie, char *name) 421 { 422 return arm_intr_establish_fdt_imap_cpu(node, reg, nreg, level, NULL, 423 func, cookie, name); 424 } 425 426 void * 427 arm_intr_establish_fdt_imap_cpu(int node, int *reg, int nreg, int level, 428 struct cpu_info *ci, int (*func)(void *), void *cookie, char *name) 429 { 430 struct interrupt_controller *ic; 431 struct arm_intr_handle *ih; 432 uint32_t *cell; 433 uint32_t map_mask[4], *map; 434 int len, acells, ncells; 435 void *val = NULL; 436 437 if (nreg != sizeof(map_mask)) 438 return NULL; 439 440 if (OF_getpropintarray(node, "interrupt-map-mask", map_mask, 441 sizeof(map_mask)) != sizeof(map_mask)) 442 return NULL; 443 444 len = OF_getproplen(node, "interrupt-map"); 445 if (len <= 0) 446 return NULL; 447 448 map = malloc(len, M_DEVBUF, M_WAITOK); 449 OF_getpropintarray(node, "interrupt-map", map, len); 450 451 cell = map; 452 ncells = len / sizeof(uint32_t); 453 while (ncells > 5) { 454 LIST_FOREACH(ic, &interrupt_controllers, ic_list) { 455 if (ic->ic_phandle == cell[4]) 456 break; 457 } 458 459 if (ic == NULL) 460 break; 461 462 acells = OF_getpropint(ic->ic_node, "#address-cells", 0); 463 if (ncells >= (5 + acells + ic->ic_cells) && 464 (reg[0] & map_mask[0]) == cell[0] && 465 (reg[1] & map_mask[1]) == cell[1] && 466 (reg[2] & map_mask[2]) == cell[2] && 467 (reg[3] & map_mask[3]) == cell[3] && 468 ic->ic_establish) { 469 val = ic->ic_establish(ic->ic_cookie, &cell[5 + acells], 470 level, ci, func, cookie, name); 471 break; 472 } 473 474 cell += (5 + acells + ic->ic_cells); 475 ncells -= (5 + acells + ic->ic_cells); 476 } 477 478 if (val == NULL) { 479 free(map, M_DEVBUF, len); 480 return NULL; 481 } 482 483 ih = malloc(sizeof(*ih), M_DEVBUF, M_WAITOK); 484 ih->ih_ic = ic; 485 ih->ih_ih = val; 486 487 free(map, M_DEVBUF, len); 488 return ih; 489 } 490 491 void * 492 arm_intr_establish_fdt_msi(int node, uint64_t *addr, uint64_t *data, 493 int level, int (*func)(void *), void *cookie, char *name) 494 { 495 return arm_intr_establish_fdt_msi_cpu(node, addr, data, level, NULL, 496 func, cookie, name); 497 } 498 499 void * 500 arm_intr_establish_fdt_msi_cpu(int node, uint64_t *addr, uint64_t *data, 501 int level, struct cpu_info *ci, int (*func)(void *), void *cookie, 502 char *name) 503 { 504 struct interrupt_controller *ic; 505 struct arm_intr_handle *ih; 506 uint32_t phandle; 507 void *val = NULL; 508 509 phandle = arm_intr_map_msi(node, data); 510 LIST_FOREACH(ic, &interrupt_controllers, ic_list) { 511 if (ic->ic_phandle == phandle) 512 break; 513 } 514 515 if (ic == NULL || ic->ic_establish_msi == NULL) 516 return NULL; 517 518 val = ic->ic_establish_msi(ic->ic_cookie, addr, data, 519 level, ci, func, cookie, name); 520 521 ih = malloc(sizeof(*ih), M_DEVBUF, M_WAITOK); 522 ih->ih_ic = ic; 523 ih->ih_ih = val; 524 525 return ih; 526 } 527 528 void 529 arm_intr_disestablish_fdt(void *cookie) 530 { 531 struct arm_intr_handle *ih = cookie; 532 struct interrupt_controller *ic = ih->ih_ic; 533 534 ic->ic_disestablish(ih->ih_ih); 535 free(ih, M_DEVBUF, sizeof(*ih)); 536 } 537 538 void 539 arm_intr_enable(void *cookie) 540 { 541 struct arm_intr_handle *ih = cookie; 542 struct interrupt_controller *ic = ih->ih_ic; 543 544 KASSERT(ic->ic_enable != NULL); 545 ic->ic_enable(ih->ih_ih); 546 } 547 548 void 549 arm_intr_disable(void *cookie) 550 { 551 struct arm_intr_handle *ih = cookie; 552 struct interrupt_controller *ic = ih->ih_ic; 553 554 KASSERT(ic->ic_disable != NULL); 555 ic->ic_disable(ih->ih_ih); 556 } 557 558 /* 559 * Some interrupt controllers transparently forward interrupts to 560 * their parent. Such interrupt controllers can use this function to 561 * delegate the interrupt handler to their parent. 562 */ 563 void * 564 arm_intr_parent_establish_fdt(void *cookie, int *cell, int level, 565 struct cpu_info *ci, int (*func)(void *), void *arg, char *name) 566 { 567 struct interrupt_controller *ic = cookie; 568 struct arm_intr_handle *ih; 569 int parent; 570 void *val; 571 572 parent = arm_intr_get_parent(ic->ic_node); 573 LIST_FOREACH(ic, &interrupt_controllers, ic_list) { 574 if (ic->ic_node == parent) 575 break; 576 } 577 if (ic == NULL) 578 return NULL; 579 580 val = ic->ic_establish(ic->ic_cookie, cell, level, ci, func, arg, name); 581 if (val == NULL) 582 return NULL; 583 584 ih = malloc(sizeof(*ih), M_DEVBUF, M_WAITOK); 585 ih->ih_ic = ic; 586 ih->ih_ih = val; 587 588 return ih; 589 } 590 591 void 592 arm_intr_parent_disestablish_fdt(void *cookie) 593 { 594 struct arm_intr_handle *ih = cookie; 595 struct interrupt_controller *ic = ih->ih_ic; 596 597 ic->ic_disestablish(ih->ih_ih); 598 free(ih, M_DEVBUF, sizeof(*ih)); 599 } 600 601 void 602 arm_intr_route(void *cookie, int enable, struct cpu_info *ci) 603 { 604 struct arm_intr_handle *ih = cookie; 605 struct interrupt_controller *ic = ih->ih_ic; 606 607 if (ic->ic_route) 608 ic->ic_route(ih->ih_ih, enable, ci); 609 } 610 611 void 612 arm_intr_cpu_enable(void) 613 { 614 struct interrupt_controller *ic; 615 616 LIST_FOREACH(ic, &interrupt_controllers, ic_list) 617 if (ic->ic_cpu_enable) 618 ic->ic_cpu_enable(); 619 } 620 621 int 622 arm_dflt_splraise(int newcpl) 623 { 624 struct cpu_info *ci = curcpu(); 625 int oldcpl; 626 627 oldcpl = ci->ci_cpl; 628 629 if (newcpl < oldcpl) 630 newcpl = oldcpl; 631 632 ci->ci_cpl = newcpl; 633 634 return oldcpl; 635 } 636 637 int 638 arm_dflt_spllower(int newcpl) 639 { 640 struct cpu_info *ci = curcpu(); 641 int oldcpl; 642 643 oldcpl = ci->ci_cpl; 644 645 splx(newcpl); 646 647 return oldcpl; 648 } 649 650 void 651 arm_dflt_splx(int newcpl) 652 { 653 struct cpu_info *ci = curcpu(); 654 655 if (ci->ci_ipending & arm_smask[newcpl]) 656 arm_do_pending_intr(newcpl); 657 ci->ci_cpl = newcpl; 658 } 659 660 void 661 arm_dflt_setipl(int newcpl) 662 { 663 struct cpu_info *ci = curcpu(); 664 665 ci->ci_cpl = newcpl; 666 } 667 668 void * 669 arm_dflt_intr_establish(int irqno, int level, struct cpu_info *ci, 670 int (*func)(void *), void *cookie, char *name) 671 { 672 panic("arm_dflt_intr_establish called"); 673 } 674 675 void 676 arm_dflt_intr_disestablish(void *cookie) 677 { 678 panic("arm_dflt_intr_disestablish called"); 679 } 680 681 const char * 682 arm_dflt_intr_string(void *cookie) 683 { 684 panic("arm_dflt_intr_string called"); 685 } 686 687 void 688 arm_setsoftintr(int si) 689 { 690 struct cpu_info *ci = curcpu(); 691 int oldirqstate; 692 693 /* XXX atomic? */ 694 oldirqstate = disable_interrupts(PSR_I); 695 ci->ci_ipending |= SI_TO_IRQBIT(si); 696 697 restore_interrupts(oldirqstate); 698 699 /* Process unmasked pending soft interrupts. */ 700 if (ci->ci_ipending & arm_smask[ci->ci_cpl]) 701 arm_do_pending_intr(ci->ci_cpl); 702 } 703 704 void 705 arm_do_pending_intr(int pcpl) 706 { 707 struct cpu_info *ci = curcpu(); 708 int oldirqstate; 709 710 oldirqstate = disable_interrupts(PSR_I); 711 712 #define DO_SOFTINT(si, ipl) \ 713 if ((ci->ci_ipending & arm_smask[pcpl]) & \ 714 SI_TO_IRQBIT(si)) { \ 715 ci->ci_ipending &= ~SI_TO_IRQBIT(si); \ 716 arm_intr_func.setipl(ipl); \ 717 restore_interrupts(oldirqstate); \ 718 softintr_dispatch(si); \ 719 oldirqstate = disable_interrupts(PSR_I); \ 720 } 721 722 do { 723 DO_SOFTINT(SI_SOFTTTY, IPL_SOFTTTY); 724 DO_SOFTINT(SI_SOFTNET, IPL_SOFTNET); 725 DO_SOFTINT(SI_SOFTCLOCK, IPL_SOFTCLOCK); 726 DO_SOFTINT(SI_SOFT, IPL_SOFT); 727 } while (ci->ci_ipending & arm_smask[pcpl]); 728 729 /* Don't use splx... we are here already! */ 730 arm_intr_func.setipl(pcpl); 731 restore_interrupts(oldirqstate); 732 } 733 734 void 735 arm_set_intr_handler(int (*raise)(int), int (*lower)(int), 736 void (*x)(int), void (*setipl)(int), 737 void *(*intr_establish)(int irqno, int level, struct cpu_info *ci, 738 int (*func)(void *), void *cookie, char *name), 739 void (*intr_disestablish)(void *cookie), 740 const char *(intr_string)(void *cookie), 741 void (*intr_handle)(void *)) 742 { 743 arm_intr_func.raise = raise; 744 arm_intr_func.lower = lower; 745 arm_intr_func.x = x; 746 arm_intr_func.setipl = setipl; 747 arm_intr_func.intr_establish = intr_establish; 748 arm_intr_func.intr_disestablish = intr_disestablish; 749 arm_intr_func.intr_string = intr_string; 750 arm_intr_dispatch = intr_handle; 751 } 752 753 void 754 arm_init_smask(void) 755 { 756 static int inited = 0; 757 int i; 758 759 if (inited) 760 return; 761 inited = 1; 762 763 for (i = IPL_NONE; i <= IPL_HIGH; i++) { 764 arm_smask[i] = 0; 765 if (i < IPL_SOFT) 766 arm_smask[i] |= SI_TO_IRQBIT(SI_SOFT); 767 if (i < IPL_SOFTCLOCK) 768 arm_smask[i] |= SI_TO_IRQBIT(SI_SOFTCLOCK); 769 if (i < IPL_SOFTNET) 770 arm_smask[i] |= SI_TO_IRQBIT(SI_SOFTNET); 771 if (i < IPL_SOFTTTY) 772 arm_smask[i] |= SI_TO_IRQBIT(SI_SOFTTTY); 773 } 774 } 775 776 /* provide functions for asm */ 777 #undef splraise 778 #undef spllower 779 #undef splx 780 781 int 782 splraise(int ipl) 783 { 784 return arm_intr_func.raise(ipl); 785 } 786 787 int _spllower(int ipl); /* XXX - called from asm? */ 788 int 789 _spllower(int ipl) 790 { 791 return arm_intr_func.lower(ipl); 792 } 793 int 794 spllower(int ipl) 795 { 796 return arm_intr_func.lower(ipl); 797 } 798 799 void 800 splx(int ipl) 801 { 802 arm_intr_func.x(ipl); 803 } 804 805 806 #ifdef DIAGNOSTIC 807 void 808 arm_splassert_check(int wantipl, const char *func) 809 { 810 int oldipl = curcpu()->ci_cpl; 811 812 if (oldipl < wantipl) { 813 splassert_fail(wantipl, oldipl, func); 814 /* 815 * If the splassert_ctl is set to not panic, raise the ipl 816 * in a feeble attempt to reduce damage. 817 */ 818 arm_intr_func.setipl(wantipl); 819 } 820 821 if (wantipl == IPL_NONE && curcpu()->ci_idepth != 0) { 822 splassert_fail(-1, curcpu()->ci_idepth, func); 823 } 824 } 825 #endif 826 827 void arm_dflt_delay(u_int usecs); 828 829 struct { 830 void (*delay)(u_int); 831 void (*initclocks)(void); 832 void (*setstatclockrate)(int); 833 void (*mpstartclock)(void); 834 } arm_clock_func = { 835 arm_dflt_delay, 836 NULL, 837 NULL, 838 NULL 839 }; 840 841 void 842 arm_clock_register(void (*initclock)(void), void (*delay)(u_int), 843 void (*statclock)(int), void(*mpstartclock)(void)) 844 { 845 if (arm_clock_func.initclocks) 846 return; 847 848 arm_clock_func.initclocks = initclock; 849 arm_clock_func.delay = delay; 850 arm_clock_func.setstatclockrate = statclock; 851 arm_clock_func.mpstartclock = mpstartclock; 852 } 853 854 855 void 856 delay(u_int usec) 857 { 858 arm_clock_func.delay(usec); 859 } 860 861 void 862 cpu_initclocks(void) 863 { 864 if (arm_clock_func.initclocks == NULL) 865 panic("initclocks function not initialized yet"); 866 867 arm_clock_func.initclocks(); 868 } 869 870 void 871 cpu_startclock(void) 872 { 873 if (arm_clock_func.mpstartclock == NULL) 874 panic("startclock function not initialized yet"); 875 876 arm_clock_func.mpstartclock(); 877 } 878 879 void 880 arm_dflt_delay(u_int usecs) 881 { 882 int j; 883 /* BAH - there is no good way to make this close */ 884 /* but this isn't supposed to be used after the real clock attaches */ 885 for (; usecs > 0; usecs--) 886 for (j = 100; j > 0; j--) 887 ; 888 889 } 890 891 void 892 setstatclockrate(int new) 893 { 894 if (arm_clock_func.setstatclockrate == NULL) { 895 panic("arm_clock_func.setstatclockrate not initialized"); 896 } 897 arm_clock_func.setstatclockrate(new); 898 } 899 900 void 901 intr_barrier(void *ih) 902 { 903 sched_barrier(NULL); 904 } 905 906 /* 907 * IPI implementation 908 */ 909 910 void arm_no_send_ipi(struct cpu_info *ci, int id); 911 void (*intr_send_ipi_func)(struct cpu_info *, int) = arm_no_send_ipi; 912 913 void 914 arm_send_ipi(struct cpu_info *ci, int id) 915 { 916 (*intr_send_ipi_func)(ci, id); 917 } 918 919 void 920 arm_no_send_ipi(struct cpu_info *ci, int id) 921 { 922 panic("arm_send_ipi() called: no ipi function"); 923 } 924