1 /* $NetBSD: ofw_machdep.c,v 1.16 2001/07/20 00:07:14 eeh Exp $ */ 2 3 /* 4 * Copyright (C) 1996 Wolfgang Solfrank. 5 * Copyright (C) 1996 TooLs GmbH. 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 3. All advertising materials mentioning features or use of this software 17 * must display the following acknowledgement: 18 * This product includes software developed by TooLs GmbH. 19 * 4. The name of TooLs GmbH may not be used to endorse or promote products 20 * derived from this software without specific prior written permission. 21 * 22 * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR 23 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 24 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 25 * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 26 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 27 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 28 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 29 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 30 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 31 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 */ 33 #include <sys/param.h> 34 #include <sys/buf.h> 35 #include <sys/conf.h> 36 #include <sys/device.h> 37 #include <sys/disk.h> 38 #include <sys/disklabel.h> 39 #include <sys/fcntl.h> 40 #include <sys/ioctl.h> 41 #include <sys/malloc.h> 42 #include <sys/stat.h> 43 #include <sys/systm.h> 44 45 #include <machine/openfirm.h> 46 47 #if defined(FFS) && defined(CD9660) 48 #include <ufs/ffs/fs.h> 49 #endif 50 51 /* 52 * Note that stdarg.h and the ANSI style va_start macro is used for both 53 * ANSI and traditional C compilers. 54 */ 55 #include <machine/stdarg.h> 56 57 #include <machine/sparc64.h> 58 59 int vsprintf __P((char *, const char *, va_list)); 60 61 void dk_cleanup __P((void)); 62 #if defined(FFS) && defined(CD9660) 63 static int dk_match_ffs __P((void)); 64 #endif 65 66 static u_int mmuh = -1, memh = -1; 67 68 static u_int get_mmu_handle __P((void)); 69 static u_int get_memory_handle __P((void)); 70 71 static u_int 72 get_mmu_handle() 73 { 74 u_int chosen; 75 76 if ((chosen = OF_finddevice("/chosen")) == -1) { 77 prom_printf("get_mmu_handle: cannot get /chosen\r\n"); 78 return -1; 79 } 80 if (OF_getprop(chosen, "mmu", &mmuh, sizeof(mmuh)) == -1) { 81 prom_printf("get_mmu_handle: cannot get mmuh\r\n"); 82 return -1; 83 } 84 return mmuh; 85 } 86 87 static u_int 88 get_memory_handle() 89 { 90 u_int chosen; 91 92 if ((chosen = OF_finddevice("/chosen")) == -1) { 93 prom_printf("get_mmu_handle: cannot get /chosen\r\n"); 94 return -1; 95 } 96 if (OF_getprop(chosen, "memory", &memh, sizeof(memh)) == -1) { 97 prom_printf("get_memory_handle: cannot get memh\r\n"); 98 return -1; 99 } 100 return memh; 101 } 102 103 104 /* 105 * Point prom to our trap table. This stops the prom from mapping us. 106 */ 107 int 108 prom_set_trap_table(tba) 109 vaddr_t tba; 110 { 111 struct { 112 cell_t name; 113 cell_t nargs; 114 cell_t nreturns; 115 cell_t tba; 116 } args; 117 118 args.name = ADR2CELL(&"SUNW,set-trap-table"); 119 args.nargs = 1; 120 args.nreturns = 0; 121 args.tba = ADR2CELL(tba); 122 return openfirmware(&args); 123 } 124 125 /* 126 * Have the prom convert from virtual to physical addresses. 127 * 128 * Only works while the prom is actively mapping us. 129 */ 130 paddr_t 131 prom_vtop(vaddr) 132 vaddr_t vaddr; 133 { 134 struct { 135 cell_t name; 136 cell_t nargs; 137 cell_t nreturns; 138 cell_t method; 139 cell_t ihandle; 140 cell_t vaddr; 141 cell_t status; 142 cell_t retaddr; 143 cell_t mode; 144 cell_t phys_hi; 145 cell_t phys_lo; 146 } args; 147 148 if (mmuh == -1 && ((mmuh = get_mmu_handle()) == -1)) { 149 prom_printf("prom_vtop: cannot get mmuh\r\n"); 150 return 0; 151 } 152 args.name = ADR2CELL(&"call-method"); 153 args.nargs = 3; 154 args.nreturns = 5; 155 args.method = ADR2CELL(&"translate"); 156 args.ihandle = HDL2CELL(mmuh); 157 args.vaddr = ADR2CELL(vaddr); 158 if(openfirmware(&args) == -1) 159 return -1; 160 #if 0 161 prom_printf("Called \"translate\", mmuh=%x, vaddr=%x, status=%x %x,\r\n retaddr=%x %x, mode=%x %x, phys_hi=%x %x, phys_lo=%x %x\r\n", 162 mmuh, vaddr, (int)(args.status>>32), (int)args.status, (int)(args.retaddr>>32), (int)args.retaddr, 163 (int)(args.mode>>32), (int)args.mode, (int)(args.phys_hi>>32), (int)args.phys_hi, 164 (int)(args.phys_lo>>32), (int)args.phys_lo); 165 #endif 166 return (paddr_t)((((paddr_t)args.phys_hi)<<32)|(u_int32_t)args.phys_lo); 167 } 168 169 /* 170 * Grab some address space from the prom 171 * 172 * Only works while the prom is actively mapping us. 173 */ 174 vaddr_t 175 prom_claim_virt(vaddr, len) 176 vaddr_t vaddr; 177 int len; 178 { 179 struct { 180 cell_t name; 181 cell_t nargs; 182 cell_t nreturns; 183 cell_t method; 184 cell_t ihandle; 185 cell_t align; 186 cell_t len; 187 cell_t vaddr; 188 cell_t status; 189 cell_t retaddr; 190 } args; 191 192 if (mmuh == -1 && ((mmuh = get_mmu_handle()) == -1)) { 193 prom_printf("prom_claim_virt: cannot get mmuh\r\n"); 194 return 0; 195 } 196 args.name = ADR2CELL(&"call-method"); 197 args.nargs = 5; 198 args.nreturns = 2; 199 args.method = ADR2CELL(&"claim"); 200 args.ihandle = HDL2CELL(mmuh); 201 args.align = 0; 202 args.len = len; 203 args.vaddr = ADR2CELL(vaddr); 204 if (openfirmware(&args) == -1) 205 return -1; 206 return (paddr_t)args.retaddr; 207 } 208 209 /* 210 * Request some address space from the prom 211 * 212 * Only works while the prom is actively mapping us. 213 */ 214 vaddr_t 215 prom_alloc_virt(len, align) 216 int len; 217 int align; 218 { 219 static int retaddr; 220 struct { 221 cell_t name; 222 cell_t nargs; 223 cell_t nreturns; 224 cell_t method; 225 cell_t ihandle; 226 cell_t align; 227 cell_t len; 228 cell_t status; 229 cell_t retaddr; 230 } args; 231 232 if (mmuh == -1 && ((mmuh = get_mmu_handle()) == -1)) { 233 prom_printf("prom_alloc_virt: cannot get mmuh\r\n"); 234 return -1LL; 235 } 236 args.name = ADR2CELL(&"call-method"); 237 args.nargs = 4; 238 args.nreturns = 2; 239 args.method = ADR2CELL(&"claim"); 240 args.ihandle = HDL2CELL(mmuh); 241 args.align = align; 242 args.len = len; 243 args.retaddr = ADR2CELL(&retaddr); 244 if (openfirmware(&args) != 0) 245 return -1; 246 return retaddr; /* Kluge till we go 64-bit */ 247 } 248 249 /* 250 * Release some address space to the prom 251 * 252 * Only works while the prom is actively mapping us. 253 */ 254 int 255 prom_free_virt(vaddr, len) 256 vaddr_t vaddr; 257 int len; 258 { 259 struct { 260 cell_t name; 261 cell_t nargs; 262 cell_t nreturns; 263 cell_t method; 264 cell_t ihandle; 265 cell_t len; 266 cell_t vaddr; 267 } args; 268 269 if (mmuh == -1 && ((mmuh = get_mmu_handle()) == -1)) { 270 prom_printf("prom_claim_virt: cannot get mmuh\r\n"); 271 return -1; 272 } 273 args.name = ADR2CELL(&"call-method"); 274 args.nargs = 4; 275 args.nreturns = 0; 276 args.method = ADR2CELL(&"release"); 277 args.ihandle = HDL2CELL(mmuh); 278 args.vaddr = ADR2CELL(vaddr); 279 args.len = len; 280 return openfirmware(&args); 281 } 282 283 284 /* 285 * Unmap some address space 286 * 287 * Only works while the prom is actively mapping us. 288 */ 289 int 290 prom_unmap_virt(vaddr, len) 291 vaddr_t vaddr; 292 int len; 293 { 294 struct { 295 cell_t name; 296 cell_t nargs; 297 cell_t nreturns; 298 cell_t method; 299 cell_t ihandle; 300 cell_t len; 301 cell_t vaddr; 302 } args; 303 304 if (mmuh == -1 && ((mmuh = get_mmu_handle()) == -1)) { 305 prom_printf("prom_claim_virt: cannot get mmuh\r\n"); 306 return -1; 307 } 308 args.name = ADR2CELL(&"call-method"); 309 args.nargs = 4; 310 args.nreturns = 0; 311 args.method = ADR2CELL(&"unmap"); 312 args.ihandle = HDL2CELL(mmuh); 313 args.vaddr = ADR2CELL(vaddr); 314 args.len = len; 315 return openfirmware(&args); 316 } 317 318 /* 319 * Have prom map in some memory 320 * 321 * Only works while the prom is actively mapping us. 322 */ 323 int 324 prom_map_phys(paddr, size, vaddr, mode) 325 paddr_t paddr; 326 off_t size; 327 vaddr_t vaddr; 328 int mode; 329 { 330 struct { 331 cell_t name; 332 cell_t nargs; 333 cell_t nreturns; 334 cell_t method; 335 cell_t ihandle; 336 cell_t mode; 337 cell_t size; 338 cell_t vaddr; 339 cell_t phys_hi; 340 cell_t phys_lo; 341 cell_t status; 342 cell_t retaddr; 343 } args; 344 345 if (mmuh == -1 && ((mmuh = get_mmu_handle()) == -1)) { 346 prom_printf("prom_map_phys: cannot get mmuh\r\n"); 347 return 0; 348 } 349 args.name = ADR2CELL(&"call-method"); 350 args.nargs = 7; 351 args.nreturns = 1; 352 args.method = ADR2CELL(&"map"); 353 args.ihandle = HDL2CELL(mmuh); 354 args.mode = mode; 355 args.size = size; 356 args.vaddr = ADR2CELL(vaddr); 357 args.phys_hi = HDL2CELL(paddr>>32); 358 args.phys_lo = HDL2CELL(paddr); 359 360 if (openfirmware(&args) == -1) 361 return -1; 362 if (args.status) 363 return -1; 364 return args.retaddr; 365 } 366 367 368 /* 369 * Request some RAM from the prom 370 * 371 * Only works while the prom is actively mapping us. 372 */ 373 paddr_t 374 prom_alloc_phys(len, align) 375 int len; 376 int align; 377 { 378 struct { 379 cell_t name; 380 cell_t nargs; 381 cell_t nreturns; 382 cell_t method; 383 cell_t ihandle; 384 cell_t align; 385 cell_t len; 386 cell_t status; 387 cell_t phys_hi; 388 cell_t phys_lo; 389 } args; 390 391 if (memh == -1 && ((memh = get_memory_handle()) == -1)) { 392 prom_printf("prom_alloc_phys: cannot get memh\r\n"); 393 return -1; 394 } 395 args.name = ADR2CELL(&"call-method"); 396 args.nargs = 4; 397 args.nreturns = 3; 398 args.method = ADR2CELL(&"claim"); 399 args.ihandle = HDL2CELL(memh); 400 args.align = align; 401 args.len = len; 402 if (openfirmware(&args) != 0) 403 return -1; 404 return (paddr_t)((((paddr_t)args.phys_hi)<<32)|(u_int32_t)args.phys_lo); 405 } 406 407 /* 408 * Request some specific RAM from the prom 409 * 410 * Only works while the prom is actively mapping us. 411 */ 412 paddr_t 413 prom_claim_phys(phys, len) 414 paddr_t phys; 415 int len; 416 { 417 struct { 418 cell_t name; 419 cell_t nargs; 420 cell_t nreturns; 421 cell_t method; 422 cell_t ihandle; 423 cell_t align; 424 cell_t len; 425 cell_t phys_hi; 426 cell_t phys_lo; 427 cell_t status; 428 cell_t rphys_hi; 429 cell_t rphys_lo; 430 } args; 431 432 if (memh == -1 && ((memh = get_memory_handle()) == -1)) { 433 prom_printf("prom_alloc_phys: cannot get memh\r\n"); 434 return -1; 435 } 436 args.name = ADR2CELL(&"call-method"); 437 args.nargs = 6; 438 args.nreturns = 3; 439 args.method = ADR2CELL(&"claim"); 440 args.ihandle = HDL2CELL(memh); 441 args.align = 0; 442 args.len = len; 443 args.phys_hi = HDL2CELL(phys>>32); 444 args.phys_lo = HDL2CELL(phys); 445 if (openfirmware(&args) != 0) 446 return -1; 447 return (paddr_t)((((paddr_t)args.rphys_hi)<<32)|(u_int32_t)args.rphys_lo); 448 } 449 450 /* 451 * Free some RAM to prom 452 * 453 * Only works while the prom is actively mapping us. 454 */ 455 int 456 prom_free_phys(phys, len) 457 paddr_t phys; 458 int len; 459 { 460 struct { 461 cell_t name; 462 cell_t nargs; 463 cell_t nreturns; 464 cell_t method; 465 cell_t ihandle; 466 cell_t len; 467 cell_t phys_hi; 468 cell_t phys_lo; 469 } args; 470 471 if (memh == -1 && ((memh = get_memory_handle()) == -1)) { 472 prom_printf("prom_free_phys: cannot get memh\r\n"); 473 return -1; 474 } 475 args.name = ADR2CELL(&"call-method"); 476 args.nargs = 5; 477 args.nreturns = 0; 478 args.method = ADR2CELL(&"release"); 479 args.ihandle = HDL2CELL(memh); 480 args.len = len; 481 args.phys_hi = HDL2CELL(phys>>32); 482 args.phys_lo = HDL2CELL(phys); 483 return openfirmware(&args); 484 } 485 486 /* 487 * Get the msgbuf from the prom. Only works once. 488 * 489 * Only works while the prom is actively mapping us. 490 */ 491 paddr_t 492 prom_get_msgbuf(len, align) 493 int len; 494 int align; 495 { 496 struct { 497 cell_t name; 498 cell_t nargs; 499 cell_t nreturns; 500 cell_t method; 501 cell_t ihandle; 502 cell_t align; 503 cell_t len; 504 cell_t id; 505 cell_t status; 506 cell_t phys_hi; 507 cell_t phys_lo; 508 } args; 509 paddr_t addr; 510 int rooth; 511 int is_e250 = 1; 512 513 /* E250s tend to have buggy PROMs that break on test-method */ 514 if ((rooth = OF_finddevice("/")) != -1) { 515 char name[80]; 516 517 if ((OF_getprop(rooth, "name", &name, sizeof(name))) != -1) { 518 if (strcmp(name, "SUNW,Ultra-250")) 519 is_e250 = 0; 520 } else prom_printf("prom_get_msgbuf: cannot get \"name\"\r\n"); 521 } else prom_printf("prom_get_msgbuf: cannot open root device \r\n"); 522 523 if (memh == -1 && ((memh = get_memory_handle()) == -1)) { 524 prom_printf("prom_get_msgbuf: cannot get memh\r\n"); 525 return -1; 526 } 527 if (is_e250) { 528 prom_printf("prom_get_msgbuf: Cannot recover msgbuf on E250\r\n"); 529 } else if (OF_test("test-method") == 0) { 530 if (OF_test_method(memh, "SUNW,retain") != 0) { 531 args.name = ADR2CELL(&"call-method"); 532 args.nargs = 5; 533 args.nreturns = 3; 534 args.method = ADR2CELL(&"SUNW,retain"); 535 args.id = ADR2CELL(&"msgbuf"); 536 args.ihandle = HDL2CELL(memh); 537 args.len = len; 538 args.align = align; 539 args.status = -1; 540 if (openfirmware(&args) == 0 && args.status == 0) { 541 return (((paddr_t)args.phys_hi<<32)| 542 (u_int32_t)args.phys_lo); 543 } else prom_printf("prom_get_msgbuf: SUNW,retain failed\r\n"); 544 } else prom_printf("prom_get_msgbuf: test-method failed\r\n"); 545 } else prom_printf("prom_get_msgbuf: test failed\r\n"); 546 /* Allocate random memory -- page zero avail?*/ 547 addr = prom_claim_phys(0x000, len); 548 prom_printf("prom_get_msgbuf: allocated new buf at %08x\r\n", (int)addr); 549 if (addr == -1) { 550 prom_printf("prom_get_msgbuf: cannot get allocate physmem\r\n"); 551 return -1; 552 } 553 prom_printf("prom_get_msgbuf: claiming new buf at %08x\r\n", (int)addr); 554 { int i; for (i=0; i<200000000; i++); } 555 return addr; /* Kluge till we go 64-bit */ 556 } 557 558 /* 559 * Low-level prom I/O routines. 560 */ 561 562 static u_int stdin = NULL; 563 static u_int stdout = NULL; 564 565 int 566 OF_stdin() 567 { 568 u_int chosen; 569 570 if (stdin != NULL) 571 return stdin; 572 573 chosen = OF_finddevice("/chosen"); 574 OF_getprop(chosen, "stdin", &stdin, sizeof(stdin)); 575 return stdin; 576 } 577 578 int 579 OF_stdout() 580 { 581 u_int chosen; 582 583 if (stdout != NULL) 584 return stdout; 585 586 chosen = OF_finddevice("/chosen"); 587 OF_getprop(chosen, "stdout", &stdout, sizeof(stdout)); 588 return stdout; 589 } 590 591 592 /* 593 * print debug info to prom. 594 * This is not safe, but then what do you expect? 595 */ 596 void 597 #ifdef __STDC__ 598 prom_printf(const char *fmt, ...) 599 #else 600 prom_printf(fmt, va_alist) 601 char *fmt; 602 va_dcl 603 #endif 604 { 605 int len; 606 static char buf[256]; 607 va_list ap; 608 609 va_start(ap, fmt); 610 len = vsprintf(buf, fmt, ap); 611 va_end(ap); 612 613 OF_write(OF_stdout(), buf, len); 614 } 615 616 #ifdef DEBUG 617 int ofmapintrdebug = 0; 618 #define DPRINTF(x) if (ofmapintrdebug) printf x 619 #else 620 #define DPRINTF(x) 621 #endif 622 623 624 /* 625 * Recursively hunt for a property. 626 */ 627 int 628 OF_searchprop(int node, char *prop, void *buf, int buflen) 629 { 630 int len; 631 632 for( ; node; node = OF_parent(node)) { 633 len = OF_getprop(node, prop, buf, buflen); 634 if (len >= 0) 635 return (len); 636 } 637 /* Error -- not found */ 638 return (-1); 639 } 640 641 642 /* 643 * Compare a sequence of cells with a mask, 644 * return 1 if they match and 0 if they don't. 645 */ 646 static int compare_cells (int *cell1, int *cell2, int *mask, int ncells); 647 static int 648 compare_cells(int *cell1, int *cell2, int *mask, int ncells) 649 { 650 int i; 651 652 for (i=0; i<ncells; i++) { 653 DPRINTF(("src %x ^ dest %x -> %x & mask %x -> %x\n", 654 cell1[i], cell2[i], (cell1[i] ^ cell2[i]), 655 mask[i], ((cell1[i] ^ cell2[i]) & mask[i]))); 656 if (((cell1[i] ^ cell2[i]) & mask[i]) != 0) 657 return (0); 658 } 659 return (1); 660 } 661 662 /* 663 * Follow the OFW algorithm and return an interrupt specifier. 664 * 665 * Pass in the interrupt specifier you want mapped and the node 666 * you want it mapped from. validlen is the number of cells in 667 * the interrupt specifier, and buflen is the number of cells in 668 * the buffer. 669 */ 670 int 671 OF_mapintr(int node, int *interrupt, int validlen, int buflen) 672 { 673 int i, len; 674 int address_cells, size_cells, interrupt_cells, interrupt_map_len; 675 int interrupt_map[100]; 676 int interrupt_map_mask[10]; 677 int reg[10]; 678 679 /* 680 * If there is no interrupt map in the bus node, we 681 * need to convert the slot address to its parent 682 * bus format, and hunt up the parent bus to see if 683 * we need to remap. 684 * 685 * The specification for interrupt mapping is borken. 686 * You are supposed to query the interrupt parent in 687 * the interrupt-map specification to determine the 688 * number of address and interrupt cells, but we need 689 * to know how many address and interrupt cells to skip 690 * to find the phandle... 691 * 692 */ 693 if ((len = OF_getprop(node, "reg", ®, sizeof(reg))) <= 0) { 694 printf("OF_mapintr: no reg property?\n"); 695 return (-1); 696 } 697 698 for (; node; node = OF_parent(node)) { 699 #ifdef DEBUG 700 char name[40]; 701 702 if (ofmapintrdebug) { 703 OF_getprop(node, "name", &name, sizeof(name)); 704 printf("Node %s\n", name); 705 } 706 #endif 707 708 if ((interrupt_map_len = OF_getprop(node, 709 "interrupt-map", &interrupt_map, 710 sizeof(interrupt_map))) <= 0) { 711 /* Get reg for next level compare. */ 712 OF_getprop(node, "reg", ®, sizeof(reg)); 713 continue; 714 } 715 /* Convert from bytes to cells. */ 716 interrupt_map_len = interrupt_map_len/sizeof(int); 717 if ((len = (OF_searchprop(node, "#address-cells", &address_cells, 718 sizeof(address_cells)))) <= 0) { 719 /* How should I know. */ 720 address_cells = 2; 721 } 722 DPRINTF(("#address-cells = %d len %d", address_cells, len)); 723 if ((len = OF_searchprop(node, "#size-cells", &size_cells, 724 sizeof(size_cells))) <= 0) { 725 /* How should I know. */ 726 size_cells = 2; 727 } 728 DPRINTF(("#size-cells = %d len %d", size_cells, len)); 729 if ((len = OF_getprop(node, "#interrupt-cells", &interrupt_cells, 730 sizeof(interrupt_cells))) <= 0) { 731 /* How should I know. */ 732 interrupt_cells = 1; 733 } 734 DPRINTF(("#interrupt-cells = %d, len %d\n", interrupt_cells, 735 len)); 736 if ((len = OF_getprop(node, "interrupt-map-mask", &interrupt_map_mask, 737 sizeof(interrupt_map_mask))) <= 0) { 738 /* Create a mask that masks nothing. */ 739 for (i = 0; i<(address_cells + interrupt_cells); i++) 740 interrupt_map_mask[i] = -1; 741 } 742 #ifdef DEBUG 743 DPRINTF(("interrupt-map-mask len %d = ", len)); 744 for (i=0; i<(address_cells + interrupt_cells); i++) 745 DPRINTF(("%x.", interrupt_map_mask[i])); 746 DPRINTF(("reg = ")); 747 for (i=0; i<(address_cells); i++) 748 DPRINTF(("%x.", reg[i])); 749 DPRINTF(("interrupts = ")); 750 for (i=0; i<(interrupt_cells); i++) 751 DPRINTF(("%x.", interrupt[i])); 752 753 #endif 754 755 /* finally we can attempt the compare */ 756 i=0; 757 while ( i < interrupt_map_len ) { 758 int pintr_cells; 759 int *imap = &interrupt_map[i]; 760 int *parent = &imap[address_cells + interrupt_cells]; 761 762 #ifdef DEBUG 763 DPRINTF(("\ninterrupt-map addr ")); 764 for (len=0; len<address_cells; len++) 765 DPRINTF(("%x.", imap[len])); 766 DPRINTF((" intr ")); 767 for (; len<(address_cells+interrupt_cells); len++) 768 DPRINTF(("%x.", imap[len])); 769 DPRINTF(("\nnode %x vs parent %x\n", 770 imap[len], *parent)); 771 #endif 772 773 /* Find out how many cells we'll need to skip. */ 774 if ((len = OF_searchprop(*parent, "#interrupt-cells", 775 &pintr_cells, sizeof(pintr_cells))) < 0) { 776 pintr_cells = interrupt_cells; 777 } 778 DPRINTF(("pintr_cells = %d len %d\n", pintr_cells, len)); 779 780 if (compare_cells(imap, reg, 781 interrupt_map_mask, address_cells) && 782 compare_cells(&imap[address_cells], 783 interrupt, 784 &interrupt_map_mask[address_cells], 785 interrupt_cells)) 786 { 787 /* Bingo! */ 788 if (buflen < pintr_cells) { 789 /* Error -- ran out of storage. */ 790 return (-1); 791 } 792 parent ++; 793 #ifdef DEBUG 794 DPRINTF(("Match! using ")); 795 for (len=0; len<pintr_cells; len++) 796 DPRINTF(("%x.", parent[len])); 797 #endif 798 for (i=0; i<pintr_cells; i++) 799 interrupt[i] = parent[i]; 800 validlen = pintr_cells; 801 break; 802 } 803 /* Move on to the next interrupt_map entry. */ 804 #ifdef DEBUG 805 DPRINTF(("skip %d cells:", 806 address_cells + interrupt_cells + 807 pintr_cells + 1)); 808 for (len=0; len<(address_cells + 809 interrupt_cells + pintr_cells + 1); len++) 810 DPRINTF(("%x.", imap[len])); 811 #endif 812 i += address_cells + interrupt_cells + pintr_cells + 1; 813 } 814 815 /* Get reg for the next level search. */ 816 if ((len = OF_getprop(node, "reg", ®, sizeof(reg))) <= 0) { 817 DPRINTF(("OF_mapintr: no reg property?\n")); 818 continue; 819 } 820 DPRINTF(("reg len %d\n", len)); 821 822 } 823 return (validlen); 824 } 825