ofw_machdep.c revision 259231
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: stable/10/sys/powerpc/ofw/ofw_machdep.c 259231 2013-12-11 21:41:21Z andreast $");
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
63static struct mem_region OFmem[PHYS_AVAIL_SZ], OFavail[PHYS_AVAIL_SZ];
64static struct mem_region OFfree[PHYS_AVAIL_SZ];
65
66extern register_t ofmsr[5];
67extern void	*openfirmware_entry;
68static void	*fdt;
69int		ofw_real_mode;
70
71int		ofwcall(void *);
72static int	openfirmware(void *args);
73
74/*
75 * Saved SPRG0-3 from OpenFirmware. Will be restored prior to the callback.
76 */
77register_t	ofw_sprg0_save;
78
79static __inline void
80ofw_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
98static __inline void
99ofw_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 */
115static int
116memr_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
125static void
126memr_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 */
137static int	mr_cmp(const void *a, const void *b);
138
139static int
140mr_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
155static int
156parse_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
264static int
265parse_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	printf("Logical Memory Block size: %d MB\n", lmb_size[1] >> 20);
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 */
347void
348ofw_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
438void
439OF_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
455boolean_t
456OF_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	} else if (fdt != NULL) {
476		status = OF_install(OFW_FDT, 0);
477
478		if (status != TRUE)
479			return status;
480
481		OF_init(fdt);
482	}
483
484	return (status);
485}
486
487void
488ofw_quiesce(void)
489{
490	struct {
491		cell_t name;
492		cell_t nargs;
493		cell_t nreturns;
494	} args;
495
496	KASSERT(!pmap_bootstrapped, ("Cannot call ofw_quiesce after VM is up"));
497
498	args.name = (cell_t)(uintptr_t)"quiesce";
499	args.nargs = 0;
500	args.nreturns = 0;
501	openfirmware(&args);
502}
503
504static int
505openfirmware_core(void *args)
506{
507	int		result;
508	register_t	oldmsr;
509
510	/*
511	 * Turn off exceptions - we really don't want to end up
512	 * anywhere unexpected with PCPU set to something strange
513	 * or the stack pointer wrong.
514	 */
515	oldmsr = intr_disable();
516
517	ofw_sprg_prepare();
518
519#if defined(AIM) && !defined(__powerpc64__)
520	/*
521	 * Clear battable[] translations
522	 */
523	if (!(cpu_features & PPC_FEATURE_64))
524		__asm __volatile("mtdbatu 2, %0\n"
525				 "mtdbatu 3, %0" : : "r" (0));
526	isync();
527#endif
528
529	result = ofwcall(args);
530	ofw_sprg_restore();
531
532	intr_restore(oldmsr);
533
534	return (result);
535}
536
537#ifdef SMP
538struct ofw_rv_args {
539	void *args;
540	int retval;
541	volatile int in_progress;
542};
543
544static void
545ofw_rendezvous_dispatch(void *xargs)
546{
547	struct ofw_rv_args *rv_args = xargs;
548
549	/* NOTE: Interrupts are disabled here */
550
551	if (PCPU_GET(cpuid) == 0) {
552		/*
553		 * Execute all OF calls on CPU 0
554		 */
555		rv_args->retval = openfirmware_core(rv_args->args);
556		rv_args->in_progress = 0;
557	} else {
558		/*
559		 * Spin with interrupts off on other CPUs while OF has
560		 * control of the machine.
561		 */
562		while (rv_args->in_progress)
563			cpu_spinwait();
564	}
565}
566#endif
567
568static int
569openfirmware(void *args)
570{
571	int result;
572	#ifdef SMP
573	struct ofw_rv_args rv_args;
574
575	rv_args.args = args;
576	rv_args.in_progress = 1;
577	smp_rendezvous(smp_no_rendevous_barrier, ofw_rendezvous_dispatch,
578	    smp_no_rendevous_barrier, &rv_args);
579	result = rv_args.retval;
580	#else
581	result = openfirmware_core(args);
582	#endif
583
584	return (result);
585}
586
587void
588OF_reboot()
589{
590	struct {
591		cell_t name;
592		cell_t nargs;
593		cell_t nreturns;
594		cell_t arg;
595	} args;
596
597	args.name = (cell_t)(uintptr_t)"interpret";
598	args.nargs = 1;
599	args.nreturns = 0;
600	args.arg = (cell_t)(uintptr_t)"reset-all";
601	openfirmware_core(&args); /* Don't do rendezvous! */
602
603	for (;;);	/* just in case */
604}
605
606void
607OF_getetheraddr(device_t dev, u_char *addr)
608{
609	phandle_t	node;
610
611	node = ofw_bus_get_node(dev);
612	OF_getprop(node, "local-mac-address", addr, ETHER_ADDR_LEN);
613}
614
615/*
616 * Return a bus handle and bus tag that corresponds to the register
617 * numbered regno for the device referenced by the package handle
618 * dev. This function is intended to be used by console drivers in
619 * early boot only. It works by mapping the address of the device's
620 * register in the address space of its parent and recursively walk
621 * the device tree upward this way.
622 */
623static void
624OF_get_addr_props(phandle_t node, uint32_t *addrp, uint32_t *sizep, int *pcip)
625{
626	char name[16];
627	uint32_t addr, size;
628	int pci, res;
629
630	res = OF_getprop(node, "#address-cells", &addr, sizeof(addr));
631	if (res == -1)
632		addr = 2;
633	res = OF_getprop(node, "#size-cells", &size, sizeof(size));
634	if (res == -1)
635		size = 1;
636	pci = 0;
637	if (addr == 3 && size == 2) {
638		res = OF_getprop(node, "name", name, sizeof(name));
639		if (res != -1) {
640			name[sizeof(name) - 1] = '\0';
641			pci = (strcmp(name, "pci") == 0) ? 1 : 0;
642		}
643	}
644	if (addrp != NULL)
645		*addrp = addr;
646	if (sizep != NULL)
647		*sizep = size;
648	if (pcip != NULL)
649		*pcip = pci;
650}
651
652int
653OF_decode_addr(phandle_t dev, int regno, bus_space_tag_t *tag,
654    bus_space_handle_t *handle)
655{
656	uint32_t cell[32];
657	bus_addr_t addr, raddr, baddr;
658	bus_size_t size, rsize;
659	uint32_t c, nbridge, naddr, nsize;
660	phandle_t bridge, parent;
661	u_int spc, rspc, prefetch;
662	int pci, pcib, res;
663
664	/* Sanity checking. */
665	if (dev == 0)
666		return (EINVAL);
667	bridge = OF_parent(dev);
668	if (bridge == 0)
669		return (EINVAL);
670	if (regno < 0)
671		return (EINVAL);
672	if (tag == NULL || handle == NULL)
673		return (EINVAL);
674
675	/* Get the requested register. */
676	OF_get_addr_props(bridge, &naddr, &nsize, &pci);
677	res = OF_getprop(dev, (pci) ? "assigned-addresses" : "reg",
678	    cell, sizeof(cell));
679	if (res == -1)
680		return (ENXIO);
681	if (res % sizeof(cell[0]))
682		return (ENXIO);
683	res /= sizeof(cell[0]);
684	regno *= naddr + nsize;
685	if (regno + naddr + nsize > res)
686		return (EINVAL);
687	spc = (pci) ? cell[regno] & OFW_PCI_PHYS_HI_SPACEMASK : ~0;
688	prefetch = (pci) ? cell[regno] & OFW_PCI_PHYS_HI_PREFETCHABLE : 0;
689	addr = 0;
690	for (c = 0; c < naddr; c++)
691		addr = ((uint64_t)addr << 32) | cell[regno++];
692	size = 0;
693	for (c = 0; c < nsize; c++)
694		size = ((uint64_t)size << 32) | cell[regno++];
695
696	/*
697	 * Map the address range in the bridge's decoding window as given
698	 * by the "ranges" property. If a node doesn't have such property
699	 * then no mapping is done.
700	 */
701	parent = OF_parent(bridge);
702	while (parent != 0) {
703		OF_get_addr_props(parent, &nbridge, NULL, &pcib);
704		res = OF_getprop(bridge, "ranges", cell, sizeof(cell));
705		if (res == -1)
706			goto next;
707		if (res % sizeof(cell[0]))
708			return (ENXIO);
709		res /= sizeof(cell[0]);
710		regno = 0;
711		while (regno < res) {
712			rspc = (pci)
713			    ? cell[regno] & OFW_PCI_PHYS_HI_SPACEMASK
714			    : ~0;
715			if (rspc != spc) {
716				regno += naddr + nbridge + nsize;
717				continue;
718			}
719			raddr = 0;
720			for (c = 0; c < naddr; c++)
721				raddr = ((uint64_t)raddr << 32) | cell[regno++];
722			rspc = (pcib)
723			    ? cell[regno] & OFW_PCI_PHYS_HI_SPACEMASK
724			    : ~0;
725			baddr = 0;
726			for (c = 0; c < nbridge; c++)
727				baddr = ((uint64_t)baddr << 32) | cell[regno++];
728			rsize = 0;
729			for (c = 0; c < nsize; c++)
730				rsize = ((uint64_t)rsize << 32) | cell[regno++];
731			if (addr < raddr || addr >= raddr + rsize)
732				continue;
733			addr = addr - raddr + baddr;
734			if (rspc != ~0)
735				spc = rspc;
736		}
737
738	next:
739		bridge = parent;
740		parent = OF_parent(bridge);
741		OF_get_addr_props(bridge, &naddr, &nsize, &pci);
742	}
743
744	*tag = &bs_le_tag;
745	return (bus_space_map(*tag, addr, size,
746	    prefetch ? BUS_SPACE_MAP_PREFETCHABLE : 0, handle));
747}
748
749