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