1 /* $NetBSD: ofw_machdep.c,v 1.18 2008/03/27 18:01:08 phx Exp $ */ 2 3 /* 4 * Copyright (C) 1996 Wolfgang Solfrank. 5 * Copyright (C) 1996 TooLs GmbH. 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 3. All advertising materials mentioning features or use of this software 17 * must display the following acknowledgement: 18 * This product includes software developed by TooLs GmbH. 19 * 4. The name of TooLs GmbH may not be used to endorse or promote products 20 * derived from this software without specific prior written permission. 21 * 22 * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR 23 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 24 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 25 * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 26 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 27 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 28 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 29 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 30 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 31 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 */ 33 34 #include <sys/cdefs.h> 35 __KERNEL_RCSID(0, "$NetBSD: ofw_machdep.c,v 1.18 2008/03/27 18:01:08 phx Exp $"); 36 37 #include <sys/param.h> 38 #include <sys/buf.h> 39 #include <sys/conf.h> 40 #include <sys/device.h> 41 #include <sys/disk.h> 42 #include <sys/disklabel.h> 43 #include <sys/fcntl.h> 44 #include <sys/ioctl.h> 45 #include <sys/malloc.h> 46 #include <sys/stat.h> 47 #include <sys/systm.h> 48 49 #include <dev/ofw/openfirm.h> 50 51 #include <machine/powerpc.h> 52 #include <machine/autoconf.h> 53 54 #define OFMEM_REGIONS 32 55 static struct mem_region OFmem[OFMEM_REGIONS + 1], OFavail[OFMEM_REGIONS + 3]; 56 57 /* 58 * This is called during initppc, before the system is really initialized. 59 * It shall provide the total and the available regions of RAM. 60 * Both lists must have a zero-size entry as terminator. 61 * The available regions need not take the kernel into account, but needs 62 * to provide space for two additional entry beyond the terminating one. 63 */ 64 void 65 mem_regions(struct mem_region **memp, struct mem_region **availp) 66 { 67 int phandle, i, cnt, regcnt; 68 struct mem_region_avail { 69 paddr_t start; 70 paddr_t size; 71 } OFavail_G5[OFMEM_REGIONS + 3] __attribute((unused)); 72 73 /* 74 * Get memory. 75 */ 76 if ((phandle = OF_finddevice("/memory")) == -1) 77 goto error; 78 79 memset(OFmem, 0, sizeof OFmem); 80 regcnt = OF_getprop(phandle, "reg", 81 OFmem, sizeof OFmem[0] * OFMEM_REGIONS); 82 if (regcnt <= 0) 83 goto error; 84 85 /* Remove zero sized entry in the returned data. */ 86 regcnt /= sizeof OFmem[0]; 87 for (i = 0; i < regcnt; ) 88 if (OFmem[i].size == 0) { 89 memmove(&OFmem[i], &OFmem[i + 1], 90 (regcnt - i) * sizeof OFmem[0]); 91 regcnt--; 92 } else 93 i++; 94 95 #if defined (PMAC_G5) 96 /* XXXSL: the G5 implementation of OFW is defines the /memory reg/available 97 * properties differently. Try to fix it up here with minimal damage to the 98 * rest of the code 99 */ 100 { 101 int count; 102 memset(OFavail_G5, 0, sizeof OFavail_G5); 103 count = OF_getprop(phandle, "available", 104 OFavail_G5, sizeof OFavail_G5[0] * OFMEM_REGIONS); 105 106 if (count <= 0) 107 goto error; 108 109 count /= sizeof OFavail_G5[0]; 110 cnt = count * sizeof(OFavail[0]); 111 112 for (i = 0; i < count; i++ ) 113 { 114 OFavail[i].start_hi = 0; 115 OFavail[i].start = OFavail_G5[i].start; 116 OFavail[i].size = OFavail_G5[i].size; 117 } 118 } 119 #else 120 memset(OFavail, 0, sizeof OFavail); 121 cnt = OF_getprop(phandle, "available", 122 OFavail, sizeof OFavail[0] * OFMEM_REGIONS); 123 #endif 124 if (cnt <= 0) 125 goto error; 126 127 cnt /= sizeof OFavail[0]; 128 for (i = 0; i < cnt; ) { 129 if (OFavail[i].size == 0) { 130 memmove(&OFavail[i], &OFavail[i + 1], 131 (cnt - i) * sizeof OFavail[0]); 132 cnt--; 133 } else 134 i++; 135 } 136 137 if (strncmp(model_name, "Pegasos", 7) == 0) { 138 /* 139 * Some versions of SmartFirmware, only recognize the first 140 * 256MB segment as available. Work around it and add an 141 * extra entry to OFavail[] to account for this. 142 */ 143 #define AVAIL_THRESH (0x10000000-1) 144 if (((OFavail[cnt-1].start + OFavail[cnt-1].size + 145 AVAIL_THRESH) & ~AVAIL_THRESH) < 146 (OFmem[regcnt-1].start + OFmem[regcnt-1].size)) { 147 148 OFavail[cnt].start = 149 (OFavail[cnt-1].start + OFavail[cnt-1].size + 150 AVAIL_THRESH) & ~AVAIL_THRESH; 151 OFavail[cnt].size = 152 OFmem[regcnt-1].size - OFavail[cnt].start; 153 aprint_normal("WARNING: add memory segment %lx - %lx," 154 "\nWARNING: which was not recognized by " 155 "the Firmware.\n", 156 (unsigned long)OFavail[cnt].start, 157 (unsigned long)OFavail[cnt].start + 158 OFavail[cnt].size); 159 cnt++; 160 } 161 } 162 163 *memp = OFmem; 164 *availp = OFavail; 165 return; 166 167 error: 168 #if defined (MAMBO) 169 printf("no memory, assuming 512MB\n"); 170 171 OFmem[0].start = 0x0; 172 OFmem[0].size = 0x20000000; 173 174 OFavail[0].start = 0x3000; 175 OFavail[0].size = 0x20000000 - 0x3000; 176 177 *memp = OFmem; 178 *availp = OFavail; 179 #else 180 panic("no memory?"); 181 #endif 182 return; 183 } 184 185 void 186 ppc_exit(void) 187 { 188 OF_exit(); 189 } 190 191 void 192 ppc_boot(char *str) 193 { 194 OF_boot(str); 195 } 196