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