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