1 /*- 2 * Copyright (C) 1996 Wolfgang Solfrank. 3 * Copyright (C) 1996 TooLs GmbH. 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 3. All advertising materials mentioning features or use of this software 15 * must display the following acknowledgement: 16 * This product includes software developed by TooLs GmbH. 17 * 4. The name of TooLs GmbH may not be used to endorse or promote products 18 * derived from this software without specific prior written permission. 19 * 20 * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR 21 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 22 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 23 * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 24 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 25 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 26 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 27 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 28 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 29 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 * 31 * $NetBSD: ofw_machdep.c,v 1.5 2000/05/23 13:25:43 tsubai Exp $ 32 */ 33 34 #include <sys/cdefs.h> 35 __FBSDID("$FreeBSD$"); 36 37 #include <sys/param.h> 38 #include <sys/bus.h> 39 #include <sys/systm.h> 40 #include <sys/conf.h> 41 #include <sys/disk.h> 42 #include <sys/fcntl.h> 43 #include <sys/malloc.h> 44 #include <sys/smp.h> 45 #include <sys/stat.h> 46 47 #include <net/ethernet.h> 48 49 #include <dev/ofw/openfirm.h> 50 #include <dev/ofw/ofw_pci.h> 51 #include <dev/ofw/ofw_bus.h> 52 53 #include <vm/vm.h> 54 #include <vm/vm_param.h> 55 #include <vm/vm_page.h> 56 57 #include <machine/bus.h> 58 #include <machine/cpu.h> 59 #include <machine/md_var.h> 60 #include <machine/platform.h> 61 #include <machine/ofw_machdep.h> 62 63 static struct mem_region OFmem[PHYS_AVAIL_SZ], OFavail[PHYS_AVAIL_SZ]; 64 static struct mem_region OFfree[PHYS_AVAIL_SZ]; 65 66 static int apple_hacks; 67 68 #ifdef AIM 69 extern register_t ofmsr[5]; 70 extern void *openfirmware_entry; 71 static void *fdt; 72 int ofw_real_mode; 73 74 int ofwcall(void *); 75 static int openfirmware(void *args); 76 77 /* 78 * Saved SPRG0-3 from OpenFirmware. Will be restored prior to the callback. 79 */ 80 register_t ofw_sprg0_save; 81 82 static __inline void 83 ofw_sprg_prepare(void) 84 { 85 if (!apple_hacks) 86 return; 87 88 /* 89 * Assume that interrupt are disabled at this point, or 90 * SPRG1-3 could be trashed 91 */ 92 __asm __volatile("mfsprg0 %0\n\t" 93 "mtsprg0 %1\n\t" 94 "mtsprg1 %2\n\t" 95 "mtsprg2 %3\n\t" 96 "mtsprg3 %4\n\t" 97 : "=&r"(ofw_sprg0_save) 98 : "r"(ofmsr[1]), 99 "r"(ofmsr[2]), 100 "r"(ofmsr[3]), 101 "r"(ofmsr[4])); 102 } 103 104 static __inline void 105 ofw_sprg_restore(void) 106 { 107 if (!apple_hacks) 108 return; 109 110 /* 111 * Note that SPRG1-3 contents are irrelevant. They are scratch 112 * registers used in the early portion of trap handling when 113 * interrupts are disabled. 114 * 115 * PCPU data cannot be used until this routine is called ! 116 */ 117 __asm __volatile("mtsprg0 %0" :: "r"(ofw_sprg0_save)); 118 } 119 #endif 120 121 /* 122 * Memory region utilities: determine if two regions overlap, 123 * and merge two overlapping regions into one 124 */ 125 static int 126 memr_overlap(struct mem_region *r1, struct mem_region *r2) 127 { 128 if ((r1->mr_start + r1->mr_size) < r2->mr_start || 129 (r2->mr_start + r2->mr_size) < r1->mr_start) 130 return (FALSE); 131 132 return (TRUE); 133 } 134 135 static void 136 memr_merge(struct mem_region *from, struct mem_region *to) 137 { 138 vm_offset_t end; 139 end = ulmax(to->mr_start + to->mr_size, from->mr_start + from->mr_size); 140 to->mr_start = ulmin(from->mr_start, to->mr_start); 141 to->mr_size = end - to->mr_start; 142 } 143 144 /* 145 * Quick sort callout for comparing memory regions. 146 */ 147 static int mr_cmp(const void *a, const void *b); 148 149 static int 150 mr_cmp(const void *a, const void *b) 151 { 152 const struct mem_region *regiona; 153 const struct mem_region *regionb; 154 155 regiona = a; 156 regionb = b; 157 if (regiona->mr_start < regionb->mr_start) 158 return (-1); 159 else if (regiona->mr_start > regionb->mr_start) 160 return (1); 161 else 162 return (0); 163 } 164 165 static int 166 parse_ofw_memory(phandle_t node, const char *prop, struct mem_region *output) 167 { 168 cell_t address_cells, size_cells; 169 cell_t OFmem[4 * PHYS_AVAIL_SZ]; 170 int sz, i, j; 171 int apple_hack_mode; 172 phandle_t phandle; 173 174 sz = 0; 175 apple_hack_mode = 0; 176 177 /* 178 * Get #address-cells from root node, defaulting to 1 if it cannot 179 * be found. 180 */ 181 phandle = OF_finddevice("/"); 182 if (OF_getprop(phandle, "#address-cells", &address_cells, 183 sizeof(address_cells)) < (ssize_t)sizeof(address_cells)) 184 address_cells = 1; 185 if (OF_getprop(phandle, "#size-cells", &size_cells, 186 sizeof(size_cells)) < (ssize_t)sizeof(size_cells)) 187 size_cells = 1; 188 189 /* 190 * On Apple hardware, address_cells is always 1 for "available", 191 * even when it is explicitly set to 2. All memory above 4 GB 192 * also needs to be added by hand to the available list. 193 */ 194 if (strcmp(prop, "available") == 0 && apple_hacks) 195 address_cells = 1; 196 197 /* 198 * Get memory. 199 */ 200 if (node == -1 || (sz = OF_getprop(node, prop, 201 OFmem, sizeof(OFmem))) <= 0) 202 panic("Physical memory map not found"); 203 204 i = 0; 205 j = 0; 206 while (i < sz/sizeof(cell_t)) { 207 #ifndef __powerpc64__ 208 /* On 32-bit PPC, ignore regions starting above 4 GB */ 209 if (address_cells > 1 && OFmem[i] > 0) { 210 i += address_cells + size_cells; 211 continue; 212 } 213 #endif 214 215 output[j].mr_start = OFmem[i++]; 216 if (address_cells == 2) { 217 #ifdef __powerpc64__ 218 output[j].mr_start <<= 32; 219 #endif 220 output[j].mr_start += OFmem[i++]; 221 } 222 223 output[j].mr_size = OFmem[i++]; 224 if (size_cells == 2) { 225 #ifdef __powerpc64__ 226 output[j].mr_size <<= 32; 227 #endif 228 output[j].mr_size += OFmem[i++]; 229 } 230 231 #ifndef __powerpc64__ 232 /* 233 * Check for memory regions extending above 32-bit 234 * memory space, and restrict them to stay there. 235 */ 236 if (((uint64_t)output[j].mr_start + 237 (uint64_t)output[j].mr_size) > 238 BUS_SPACE_MAXADDR_32BIT) { 239 output[j].mr_size = BUS_SPACE_MAXADDR_32BIT - 240 output[j].mr_start; 241 } 242 #endif 243 244 j++; 245 } 246 sz = j*sizeof(output[0]); 247 248 #ifdef __powerpc64__ 249 if (strcmp(prop, "available") == 0 && apple_hacks) { 250 /* Add in regions above 4 GB to the available list */ 251 struct mem_region himem[16]; 252 int hisz; 253 254 hisz = parse_ofw_memory(node, "reg", himem); 255 for (i = 0; i < hisz/sizeof(himem[0]); i++) { 256 if (himem[i].mr_start > BUS_SPACE_MAXADDR_32BIT) { 257 output[j].mr_start = himem[i].mr_start; 258 output[j].mr_size = himem[i].mr_size; 259 j++; 260 } 261 } 262 sz = j*sizeof(output[0]); 263 } 264 #endif 265 266 return (sz); 267 } 268 269 static int 270 parse_drconf_memory(int *msz, int *asz, struct mem_region *ofmem, 271 struct mem_region *ofavail) 272 { 273 phandle_t phandle; 274 vm_offset_t base; 275 int i, idx, len, lasz, lmsz, res; 276 uint32_t lmb_size[2]; 277 unsigned long *dmem, flags; 278 279 lmsz = *msz; 280 lasz = *asz; 281 282 phandle = OF_finddevice("/ibm,dynamic-reconfiguration-memory"); 283 if (phandle == -1) 284 /* No drconf node, return. */ 285 return (0); 286 287 res = OF_getprop(phandle, "ibm,lmb-size", lmb_size, sizeof(lmb_size)); 288 if (res == -1) 289 return (0); 290 291 /* Parse the /ibm,dynamic-memory. 292 The first position gives the # of entries. The next two words 293 reflect the address of the memory block. The next four words are 294 the DRC index, reserved, list index and flags. 295 (see PAPR C.6.6.2 ibm,dynamic-reconfiguration-memory) 296 297 #el Addr DRC-idx res list-idx flags 298 ------------------------------------------------- 299 | 4 | 8 | 4 | 4 | 4 | 4 |.... 300 ------------------------------------------------- 301 */ 302 303 len = OF_getproplen(phandle, "ibm,dynamic-memory"); 304 if (len > 0) { 305 306 /* We have to use a variable length array on the stack 307 since we have very limited stack space. 308 */ 309 cell_t arr[len/sizeof(cell_t)]; 310 311 res = OF_getprop(phandle, "ibm,dynamic-memory", &arr, 312 sizeof(arr)); 313 if (res == -1) 314 return (0); 315 316 /* Number of elements */ 317 idx = arr[0]; 318 319 /* First address. */ 320 dmem = (void*)&arr[1]; 321 322 for (i = 0; i < idx; i++) { 323 base = *dmem; 324 dmem += 2; 325 flags = *dmem; 326 /* Use region only if available and not reserved. */ 327 if ((flags & 0x8) && !(flags & 0x80)) { 328 ofmem[lmsz].mr_start = base; 329 ofmem[lmsz].mr_size = (vm_size_t)lmb_size[1]; 330 ofavail[lasz].mr_start = base; 331 ofavail[lasz].mr_size = (vm_size_t)lmb_size[1]; 332 lmsz++; 333 lasz++; 334 } 335 dmem++; 336 } 337 } 338 339 *msz = lmsz; 340 *asz = lasz; 341 342 return (1); 343 } 344 /* 345 * This is called during powerpc_init, before the system is really initialized. 346 * It shall provide the total and the available regions of RAM. 347 * Both lists must have a zero-size entry as terminator. 348 * The available regions need not take the kernel into account, but needs 349 * to provide space for two additional entry beyond the terminating one. 350 */ 351 void 352 ofw_mem_regions(struct mem_region **memp, int *memsz, 353 struct mem_region **availp, int *availsz) 354 { 355 phandle_t phandle; 356 vm_offset_t maxphysaddr; 357 int asz, msz, fsz; 358 int i, j, res; 359 int still_merging; 360 char name[31]; 361 362 asz = msz = 0; 363 364 /* 365 * Get memory from all the /memory nodes. 366 */ 367 for (phandle = OF_child(OF_peer(0)); phandle != 0; 368 phandle = OF_peer(phandle)) { 369 if (OF_getprop(phandle, "name", name, sizeof(name)) <= 0) 370 continue; 371 if (strncmp(name, "memory", sizeof(name)) != 0) 372 continue; 373 374 res = parse_ofw_memory(phandle, "reg", &OFmem[msz]); 375 msz += res/sizeof(struct mem_region); 376 if (OF_getproplen(phandle, "available") >= 0) 377 res = parse_ofw_memory(phandle, "available", 378 &OFavail[asz]); 379 else 380 res = parse_ofw_memory(phandle, "reg", &OFavail[asz]); 381 asz += res/sizeof(struct mem_region); 382 } 383 384 /* Check for memory in ibm,dynamic-reconfiguration-memory */ 385 parse_drconf_memory(&msz, &asz, OFmem, OFavail); 386 387 qsort(OFmem, msz, sizeof(*OFmem), mr_cmp); 388 qsort(OFavail, asz, sizeof(*OFavail), mr_cmp); 389 390 *memp = OFmem; 391 *memsz = msz; 392 393 /* 394 * On some firmwares (SLOF), some memory may be marked available that 395 * doesn't actually exist. This manifests as an extension of the last 396 * available segment past the end of physical memory, so truncate that 397 * one. 398 */ 399 maxphysaddr = 0; 400 for (i = 0; i < msz; i++) 401 if (OFmem[i].mr_start + OFmem[i].mr_size > maxphysaddr) 402 maxphysaddr = OFmem[i].mr_start + OFmem[i].mr_size; 403 404 if (OFavail[asz - 1].mr_start + OFavail[asz - 1].mr_size > maxphysaddr) 405 OFavail[asz - 1].mr_size = maxphysaddr - 406 OFavail[asz - 1].mr_start; 407 408 /* 409 * OFavail may have overlapping regions - collapse these 410 * and copy out remaining regions to OFfree 411 */ 412 do { 413 still_merging = FALSE; 414 for (i = 0; i < asz; i++) { 415 if (OFavail[i].mr_size == 0) 416 continue; 417 for (j = i+1; j < asz; j++) { 418 if (OFavail[j].mr_size == 0) 419 continue; 420 if (memr_overlap(&OFavail[j], &OFavail[i])) { 421 memr_merge(&OFavail[j], &OFavail[i]); 422 /* mark inactive */ 423 OFavail[j].mr_size = 0; 424 still_merging = TRUE; 425 } 426 } 427 } 428 } while (still_merging == TRUE); 429 430 /* evict inactive ranges */ 431 for (i = 0, fsz = 0; i < asz; i++) { 432 if (OFavail[i].mr_size != 0) { 433 OFfree[fsz] = OFavail[i]; 434 fsz++; 435 } 436 } 437 438 *availp = OFfree; 439 *availsz = fsz; 440 } 441 442 #ifdef AIM 443 void 444 OF_initial_setup(void *fdt_ptr, void *junk, int (*openfirm)(void *)) 445 { 446 if (ofmsr[0] & PSL_DR) 447 ofw_real_mode = 0; 448 else 449 ofw_real_mode = 1; 450 451 fdt = fdt_ptr; 452 453 #ifdef FDT_DTB_STATIC 454 /* Check for a statically included blob */ 455 if (fdt == NULL) 456 fdt = &fdt_static_dtb; 457 #endif 458 } 459 460 boolean_t 461 OF_bootstrap() 462 { 463 boolean_t status = FALSE; 464 465 if (openfirmware_entry != NULL) { 466 if (ofw_real_mode) { 467 status = OF_install(OFW_STD_REAL, 0); 468 } else { 469 #ifdef __powerpc64__ 470 status = OF_install(OFW_STD_32BIT, 0); 471 #else 472 status = OF_install(OFW_STD_DIRECT, 0); 473 #endif 474 } 475 476 if (status != TRUE) 477 return status; 478 479 OF_init(openfirmware); 480 } else if (fdt != NULL) { 481 status = OF_install(OFW_FDT, 0); 482 483 if (status != TRUE) 484 return status; 485 486 OF_init(fdt); 487 } 488 489 /* Apple firmware has some bugs. Check for a "mac-io" alias. */ 490 apple_hacks = (OF_finddevice("mac-io") != -1) ? 1 : 0; 491 492 return (status); 493 } 494 495 void 496 ofw_quiesce(void) 497 { 498 struct { 499 cell_t name; 500 cell_t nargs; 501 cell_t nreturns; 502 } args; 503 504 KASSERT(!pmap_bootstrapped, ("Cannot call ofw_quiesce after VM is up")); 505 506 args.name = (cell_t)(uintptr_t)"quiesce"; 507 args.nargs = 0; 508 args.nreturns = 0; 509 openfirmware(&args); 510 } 511 512 static int 513 openfirmware_core(void *args) 514 { 515 int result; 516 register_t oldmsr; 517 518 /* 519 * Turn off exceptions - we really don't want to end up 520 * anywhere unexpected with PCPU set to something strange 521 * or the stack pointer wrong. 522 */ 523 oldmsr = intr_disable(); 524 525 ofw_sprg_prepare(); 526 527 #if defined(AIM) && !defined(__powerpc64__) 528 /* 529 * Clear battable[] translations 530 */ 531 if (!(cpu_features & PPC_FEATURE_64)) 532 __asm __volatile("mtdbatu 2, %0\n" 533 "mtdbatu 3, %0" : : "r" (0)); 534 isync(); 535 #endif 536 537 result = ofwcall(args); 538 ofw_sprg_restore(); 539 540 intr_restore(oldmsr); 541 542 return (result); 543 } 544 545 #ifdef SMP 546 struct ofw_rv_args { 547 void *args; 548 int retval; 549 volatile int in_progress; 550 }; 551 552 static void 553 ofw_rendezvous_dispatch(void *xargs) 554 { 555 struct ofw_rv_args *rv_args = xargs; 556 557 /* NOTE: Interrupts are disabled here */ 558 559 if (PCPU_GET(cpuid) == 0) { 560 /* 561 * Execute all OF calls on CPU 0 562 */ 563 rv_args->retval = openfirmware_core(rv_args->args); 564 rv_args->in_progress = 0; 565 } else { 566 /* 567 * Spin with interrupts off on other CPUs while OF has 568 * control of the machine. 569 */ 570 while (rv_args->in_progress) 571 cpu_spinwait(); 572 } 573 } 574 #endif 575 576 static int 577 openfirmware(void *args) 578 { 579 int result; 580 #ifdef SMP 581 struct ofw_rv_args rv_args; 582 583 rv_args.args = args; 584 rv_args.in_progress = 1; 585 smp_rendezvous(smp_no_rendevous_barrier, ofw_rendezvous_dispatch, 586 smp_no_rendevous_barrier, &rv_args); 587 result = rv_args.retval; 588 #else 589 result = openfirmware_core(args); 590 #endif 591 592 return (result); 593 } 594 595 void 596 OF_reboot() 597 { 598 struct { 599 cell_t name; 600 cell_t nargs; 601 cell_t nreturns; 602 cell_t arg; 603 } args; 604 605 args.name = (cell_t)(uintptr_t)"interpret"; 606 args.nargs = 1; 607 args.nreturns = 0; 608 args.arg = (cell_t)(uintptr_t)"reset-all"; 609 openfirmware_core(&args); /* Don't do rendezvous! */ 610 611 for (;;); /* just in case */ 612 } 613 614 #endif /* AIM */ 615 616 void 617 OF_getetheraddr(device_t dev, u_char *addr) 618 { 619 phandle_t node; 620 621 node = ofw_bus_get_node(dev); 622 OF_getprop(node, "local-mac-address", addr, ETHER_ADDR_LEN); 623 } 624 625 /* 626 * Return a bus handle and bus tag that corresponds to the register 627 * numbered regno for the device referenced by the package handle 628 * dev. This function is intended to be used by console drivers in 629 * early boot only. It works by mapping the address of the device's 630 * register in the address space of its parent and recursively walk 631 * the device tree upward this way. 632 */ 633 static void 634 OF_get_addr_props(phandle_t node, uint32_t *addrp, uint32_t *sizep, int *pcip) 635 { 636 char type[64]; 637 uint32_t addr, size; 638 int pci, res; 639 640 res = OF_getprop(node, "#address-cells", &addr, sizeof(addr)); 641 if (res == -1) 642 addr = 2; 643 res = OF_getprop(node, "#size-cells", &size, sizeof(size)); 644 if (res == -1) 645 size = 1; 646 pci = 0; 647 if (addr == 3 && size == 2) { 648 res = OF_getprop(node, "device_type", type, sizeof(type)); 649 if (res != -1) { 650 type[sizeof(type) - 1] = '\0'; 651 pci = (strcmp(type, "pci") == 0) ? 1 : 0; 652 } 653 } 654 if (addrp != NULL) 655 *addrp = addr; 656 if (sizep != NULL) 657 *sizep = size; 658 if (pcip != NULL) 659 *pcip = pci; 660 } 661 662 int 663 OF_decode_addr(phandle_t dev, int regno, bus_space_tag_t *tag, 664 bus_space_handle_t *handle) 665 { 666 uint32_t cell[32]; 667 bus_addr_t addr, raddr, baddr; 668 bus_size_t size, rsize; 669 uint32_t c, nbridge, naddr, nsize; 670 phandle_t bridge, parent; 671 u_int spc, rspc, prefetch; 672 int pci, pcib, res; 673 674 /* Sanity checking. */ 675 if (dev == 0) 676 return (EINVAL); 677 bridge = OF_parent(dev); 678 if (bridge == 0) 679 return (EINVAL); 680 if (regno < 0) 681 return (EINVAL); 682 if (tag == NULL || handle == NULL) 683 return (EINVAL); 684 685 /* Assume big-endian unless we find a PCI device */ 686 *tag = &bs_be_tag; 687 688 /* Get the requested register. */ 689 OF_get_addr_props(bridge, &naddr, &nsize, &pci); 690 if (pci) 691 *tag = &bs_le_tag; 692 res = OF_getprop(dev, (pci) ? "assigned-addresses" : "reg", 693 cell, sizeof(cell)); 694 if (res == -1) 695 return (ENXIO); 696 if (res % sizeof(cell[0])) 697 return (ENXIO); 698 res /= sizeof(cell[0]); 699 regno *= naddr + nsize; 700 if (regno + naddr + nsize > res) 701 return (EINVAL); 702 spc = (pci) ? cell[regno] & OFW_PCI_PHYS_HI_SPACEMASK : ~0; 703 prefetch = (pci) ? cell[regno] & OFW_PCI_PHYS_HI_PREFETCHABLE : 0; 704 addr = 0; 705 for (c = 0; c < naddr; c++) 706 addr = ((uint64_t)addr << 32) | cell[regno++]; 707 size = 0; 708 for (c = 0; c < nsize; c++) 709 size = ((uint64_t)size << 32) | cell[regno++]; 710 711 /* 712 * Map the address range in the bridge's decoding window as given 713 * by the "ranges" property. If a node doesn't have such property 714 * then no mapping is done. 715 */ 716 parent = OF_parent(bridge); 717 while (parent != 0) { 718 OF_get_addr_props(parent, &nbridge, NULL, &pcib); 719 if (pcib) 720 *tag = &bs_le_tag; 721 res = OF_getprop(bridge, "ranges", cell, sizeof(cell)); 722 if (res == -1) 723 goto next; 724 if (res % sizeof(cell[0])) 725 return (ENXIO); 726 res /= sizeof(cell[0]); 727 regno = 0; 728 while (regno < res) { 729 rspc = (pci) 730 ? cell[regno] & OFW_PCI_PHYS_HI_SPACEMASK 731 : ~0; 732 if (rspc != spc) { 733 regno += naddr + nbridge + nsize; 734 continue; 735 } 736 raddr = 0; 737 for (c = 0; c < naddr; c++) 738 raddr = ((uint64_t)raddr << 32) | cell[regno++]; 739 rspc = (pcib) 740 ? cell[regno] & OFW_PCI_PHYS_HI_SPACEMASK 741 : ~0; 742 baddr = 0; 743 for (c = 0; c < nbridge; c++) 744 baddr = ((uint64_t)baddr << 32) | cell[regno++]; 745 rsize = 0; 746 for (c = 0; c < nsize; c++) 747 rsize = ((uint64_t)rsize << 32) | cell[regno++]; 748 if (addr < raddr || addr >= raddr + rsize) 749 continue; 750 addr = addr - raddr + baddr; 751 if (rspc != ~0) 752 spc = rspc; 753 } 754 755 next: 756 bridge = parent; 757 parent = OF_parent(bridge); 758 OF_get_addr_props(bridge, &naddr, &nsize, &pci); 759 } 760 761 return (bus_space_map(*tag, addr, size, 762 prefetch ? BUS_SPACE_MAP_PREFETCHABLE : 0, handle)); 763 } 764 765