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: releng/9.0/sys/powerpc/ofw/ofw_machdep.c 222667 2011-06-04 04:00:40Z nwhitehorn $");
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)) < sizeof(address_cells))
175 address_cells = 1;
176 if (OF_getprop(phandle, "#size-cells", &size_cells,
177 sizeof(size_cells)) < 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
Cache object: e1fc2eefb4235a9b5177f1c8537bd4c7
|