Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys/arch/powerpc/powerpc deal with /memory "reg" property wh...
details: https://anonhg.NetBSD.org/src/rev/659414fb29ea
branches: trunk
changeset: 785838:659414fb29ea
user: macallan <macallan%NetBSD.org@localhost>
date: Mon Apr 01 20:14:42 2013 +0000
description:
deal with /memory "reg" property which may contain 64bit addresses on G5
diffstat:
sys/arch/powerpc/powerpc/ofw_machdep.c | 184 ++++++++++++++++++++++----------
1 files changed, 126 insertions(+), 58 deletions(-)
diffs (224 lines):
diff -r 6fa5934ba16e -r 659414fb29ea sys/arch/powerpc/powerpc/ofw_machdep.c
--- a/sys/arch/powerpc/powerpc/ofw_machdep.c Mon Apr 01 16:37:22 2013 +0000
+++ b/sys/arch/powerpc/powerpc/ofw_machdep.c Mon Apr 01 20:14:42 2013 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: ofw_machdep.c,v 1.19 2012/02/01 09:54:03 matt Exp $ */
+/* $NetBSD: ofw_machdep.c,v 1.20 2013/04/01 20:14:42 macallan Exp $ */
/*
* Copyright (C) 1996 Wolfgang Solfrank.
@@ -32,7 +32,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ofw_machdep.c,v 1.19 2012/02/01 09:54:03 matt Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ofw_machdep.c,v 1.20 2013/04/01 20:14:42 macallan Exp $");
#include <sys/param.h>
#include <sys/buf.h>
@@ -50,6 +50,12 @@
#include <machine/powerpc.h>
#include <machine/autoconf.h>
+#ifdef DEBUG
+#define DPRINTF aprint_error
+#else
+#define DPRINTF while(0) printf
+#endif
+
#define OFMEM_REGIONS 32
static struct mem_region OFmem[OFMEM_REGIONS + 1], OFavail[OFMEM_REGIONS + 3];
@@ -63,74 +69,136 @@
void
mem_regions(struct mem_region **memp, struct mem_region **availp)
{
- int phandle, i, cnt, regcnt;
- struct mem_region_avail {
- paddr_t start;
- paddr_t size;
- } OFavail_G5[OFMEM_REGIONS + 3] __attribute((unused));
+ int phandle, i, cnt, regcnt, acells, scells;
+ int numregs;
+ uint32_t regs[OFMEM_REGIONS * 4]; /* 2 values + 2 for 64bit */
- /*
- * Get memory.
- */
+ DPRINTF("calling mem_regions\n");
+ /* determine acell size */
+ if ((phandle = OF_finddevice("/")) == -1)
+ goto error;
+ cnt = OF_getprop(phandle, "#address-cells", &acells, sizeof(int));
+ if (cnt <= 0)
+ acells = 1;
+
+ /* determine scell size */
+ if ((phandle = OF_finddevice("/")) == -1)
+ goto error;
+ cnt = OF_getprop(phandle, "#size-cells", &scells, sizeof(int));
+ if (cnt <= 0)
+ scells = 1;
+
+ /* Get memory */
if ((phandle = OF_finddevice("/memory")) == -1)
goto error;
- memset(OFmem, 0, sizeof OFmem);
- regcnt = OF_getprop(phandle, "reg",
- OFmem, sizeof OFmem[0] * OFMEM_REGIONS);
+ memset(regs, 0, sizeof(regs));
+ regcnt = OF_getprop(phandle, "reg", regs,
+ sizeof(regs[0]) * OFMEM_REGIONS * 4);
if (regcnt <= 0)
goto error;
- /* Remove zero sized entry in the returned data. */
- regcnt /= sizeof OFmem[0];
- for (i = 0; i < regcnt; )
- if (OFmem[i].size == 0) {
- memmove(&OFmem[i], &OFmem[i + 1],
- (regcnt - i) * sizeof OFmem[0]);
- regcnt--;
- } else
- i++;
+ /* how many mem regions did we get? */
+ numregs = regcnt / (sizeof(uint32_t)*(acells+scells));
+ DPRINTF("regcnt=%d num=%d acell=%d scell=%d\n",
+ regcnt, numregs, acells, scells);
+
+ /* move the data into OFmem */
+ memset(OFmem, 0, sizeof(OFmem));
+ for (i=0, cnt=0; i <= numregs; i++) {
+ uint64_t addr, size;
+
+ if (acells > 1)
+ memcpy(&addr, ®s[i * (acells + scells)],
+ sizeof(int32_t) * acells);
+ else
+ addr = regs[i * (acells + scells)];
+
+ if (scells > 1)
+ memcpy(&size, ®s[i * (acells + scells) + acells],
+ sizeof(int32_t) * scells);
+ else
+ size = regs[i * (acells + scells) + acells];
-#if defined (PMAC_G5)
- /* XXXSL: the G5 implementation of OFW is defines the /memory reg/available
- * properties differently. Try to fix it up here with minimal damage to the
- * rest of the code
- */
- {
- int count;
- memset(OFavail_G5, 0, sizeof OFavail_G5);
- count = OF_getprop(phandle, "available",
- OFavail_G5, sizeof OFavail_G5[0] * OFMEM_REGIONS);
-
- if (count <= 0)
- goto error;
+ /* skip entry of 0 size */
+ if (size == 0)
+ continue;
+#ifndef _LP64
+ if (addr > 0xFFFFFFFF || size > 0xFFFFFFFF ||
+ (addr + size) > 0xFFFFFFFF) {
+ aprint_error("Base addr of %llx or size of %llx too"
+ " large for 32 bit OS. Skipping.", addr, size);
+ continue;
+ }
+#endif
+ OFmem[cnt].start = addr;
+ OFmem[cnt].size = size;
+ aprint_normal("mem region %d start=%llx size=%llx\n",
+ cnt, addr, size);
+ cnt++;
+ }
- count /= sizeof OFavail_G5[0];
- cnt = count * sizeof(OFavail[0]);
+ DPRINTF("available\n");
- for (i = 0; i < count; i++ )
- {
- OFavail[i].start_hi = 0;
- OFavail[i].start = OFavail_G5[i].start;
- OFavail[i].size = OFavail_G5[i].size;
- }
- }
-#else
- memset(OFavail, 0, sizeof OFavail);
- cnt = OF_getprop(phandle, "available",
- OFavail, sizeof OFavail[0] * OFMEM_REGIONS);
-#endif
- if (cnt <= 0)
+ /* now do the same thing again, for the available counts */
+ memset(regs, 0, sizeof(regs));
+ regcnt = OF_getprop(phandle, "available", regs,
+ sizeof(regs[0]) * OFMEM_REGIONS * 4);
+ if (regcnt <= 0)
goto error;
- cnt /= sizeof OFavail[0];
- for (i = 0; i < cnt; ) {
- if (OFavail[i].size == 0) {
- memmove(&OFavail[i], &OFavail[i + 1],
- (cnt - i) * sizeof OFavail[0]);
- cnt--;
- } else
- i++;
+ DPRINTF("%08x %08x %08x %08x\n", regs[0], regs[1], regs[2], regs[3]);
+
+ /*
+ * some(?) G5s have messed up 'available' properties which don't obey
+ * #address-cells. Try to detect this here.
+ * XXX this needs a better test
+ */
+ if (((regcnt >> 2) % (acells + scells)) != 0) {
+ aprint_normal("messed up 'available' property detected\n");
+ acells = 1;
+ }
+
+ /* how many mem regions did we get? */
+ numregs = regcnt / (sizeof(uint32_t) * (acells + scells));
+ DPRINTF("regcnt=%d num=%d acell=%d scell=%d\n",
+ regcnt, numregs, acells, scells);
+
+ DPRINTF("to OF_avail\n");
+
+ /* move the data into OFavail */
+ memset(OFavail, 0, sizeof(OFavail));
+ for (i=0, cnt=0; i <= numregs; i++) {
+ uint64_t addr, size;
+
+ DPRINTF("%d\n", i);
+ if (acells > 1)
+ memcpy(&addr, ®s[i * (acells + scells)],
+ sizeof(int32_t) * acells);
+ else
+ addr = regs[i * (acells + scells)];
+
+ if (scells > 1)
+ memcpy(&size, ®s[i * (acells + scells) + acells],
+ sizeof(int32_t) * scells);
+ else
+ size = regs[i * (acells + scells) + acells];
+ /* skip entry of 0 size */
+ if (size == 0)
+ continue;
+#ifndef _LP64
+ if (addr > 0xFFFFFFFF || size > 0xFFFFFFFF ||
+ (addr+size) > 0xFFFFFFFF) {
+ aprint_error("Base addr of %llx or size of %llx too"
+ " large for 32 bit OS. Skipping.", addr, size);
+ continue;
+ }
+#endif
+ OFavail[cnt].start = addr;
+ OFavail[cnt].size = size;
+ aprint_normal("avail region %d start=%llx size=%llx\n",
+ cnt, addr, size);
+ cnt++;
}
if (strncmp(model_name, "Pegasos", 7) == 0) {
Home |
Main Index |
Thread Index |
Old Index