svn commit: r200925 - head/sys/sparc64/sparc64

Marius Strobl marius at FreeBSD.org
Wed Dec 23 22:25:23 UTC 2009


Author: marius
Date: Wed Dec 23 22:25:23 2009
New Revision: 200925
URL: http://svn.freebsd.org/changeset/base/200925

Log:
  - By re-arranging the code in OF_decode_addr() somewhat and accepting
    a bit of a detour we can just iterate through the banks array instead
    of having to calculate every offset. This change is inspired by the
    powerpc version of this function.
  - Add support for the JBus to EBus bridges which hang off of nexus(4).

Modified:
  head/sys/sparc64/sparc64/ofw_machdep.c

Modified: head/sys/sparc64/sparc64/ofw_machdep.c
==============================================================================
--- head/sys/sparc64/sparc64/ofw_machdep.c	Wed Dec 23 22:11:33 2009	(r200924)
+++ head/sys/sparc64/sparc64/ofw_machdep.c	Wed Dec 23 22:25:23 2009	(r200925)
@@ -1,6 +1,6 @@
 /*-
  * Copyright (c) 2001 by Thomas Moestl <tmm at FreeBSD.org>.
- * Copyright (c) 2005 by Marius Strobl <marius at FreeBSD.org>.
+ * Copyright (c) 2005 - 2009 by Marius Strobl <marius at FreeBSD.org>.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -98,11 +98,11 @@ int
 OF_decode_addr(phandle_t node, int bank, int *space, bus_addr_t *addr)
 {
 	char name[32];
-	uint64_t cend, cstart, end, phys, sz, start;
+	uint64_t cend, cstart, end, phys, pphys, sz, start;
 	pcell_t addrc, szc, paddrc;
 	phandle_t bus, lbus, pbus;
 	uint32_t banks[10 * 5];	/* 10 PCI banks */
-	uint32_t cspace, spc;
+	uint32_t cspc, pspc, spc;
 	int i, j, nbank;
 
 	/*
@@ -148,17 +148,18 @@ OF_decode_addr(phandle_t node, int bank,
 	nbank /= sizeof(banks[0]) * (addrc + szc);
 	if (bank < 0 || bank > nbank - 1)
 		return (ENXIO);
+	bank *= addrc + szc;
+	spc = phys_hi_mask_space(name, banks[bank]);
+	/* Skip the high cell for 3-cell addresses. */
+	bank += addrc - 2;
 	phys = 0;
 	for (i = 0; i < MIN(2, addrc); i++)
-		phys |= (uint64_t)banks[(addrc + szc) * bank + addrc - 2 + i] <<
-		    32 * (MIN(2, addrc) - i - 1);
+		phys = ((uint64_t)phys << 32) | banks[bank++];
 	sz = 0;
 	for (i = 0; i < szc; i++)
-		sz |= (uint64_t)banks[(addrc + szc) * bank + addrc + i] <<
-		    32 * (szc - i - 1);
+		sz = ((uint64_t)sz << 32) | banks[bank++];
 	start = phys;
 	end = phys + sz - 1;
-	spc = phys_hi_mask_space(name, banks[(addrc + szc) * bank]);
 
 	/*
 	 * Map upward in the device tree at every bridge we encounter
@@ -170,7 +171,7 @@ OF_decode_addr(phandle_t node, int bank,
 	 * If a bridge doesn't have a "ranges" property no mapping is
 	 * necessary at that bridge.
 	 */
-	cspace = 0;
+	cspc = 0;
 	lbus = bus;
 	while ((pbus = OF_parent(bus)) != 0) {
 		if (OF_getprop(pbus, "#address-cells", &paddrc,
@@ -193,42 +194,40 @@ OF_decode_addr(phandle_t node, int bank,
 				return (ENXIO);
 		}
 		nbank /= sizeof(banks[0]) * (addrc + paddrc + szc);
+		bank = 0;
 		for (i = 0; i < nbank; i++) {
-			cspace = phys_hi_mask_space(name,
-			    banks[(addrc + paddrc + szc) * i]);
-			if (cspace != spc)
+			cspc = phys_hi_mask_space(name, banks[bank]);
+			if (cspc != spc) {
+				bank += addrc + paddrc + szc;
 				continue;
+			}
+			/* Skip the high cell for 3-cell addresses. */
+			bank += addrc - 2;
 			phys = 0;
 			for (j = 0; j < MIN(2, addrc); j++)
-				phys |= (uint64_t)banks[
-				    (addrc + paddrc + szc) * i +
-				    addrc - 2 + j] <<
-				    32 * (MIN(2, addrc) - j - 1);
+				phys = ((uint64_t)phys << 32) | banks[bank++];
+			pspc = banks[bank];
+			/* Skip the high cell for 3-cell addresses. */
+			bank += paddrc - 2;
+			pphys = 0;
+			for (j = 0; j < MIN(2, paddrc); j++)
+				pphys =
+				    ((uint64_t)pphys << 32) | banks[bank++];
 			sz = 0;
 			for (j = 0; j < szc; j++)
-				sz |= (uint64_t)banks[
-				    (addrc + paddrc + szc) * i + addrc +
-				    paddrc + j] <<
-				    32 * (szc - j - 1);
+				sz = ((uint64_t)sz << 32) | banks[bank++];
 			cstart = phys;
 			cend = phys + sz - 1;
 			if (start < cstart || start > cend)
 				continue;
 			if (end < cstart || end > cend)
 				return (ENXIO);
-			phys = 0;
-			for (j = 0; j < MIN(2, paddrc); j++)
-				phys |= (uint64_t)banks[
-				    (addrc + paddrc + szc) * i + addrc +
-				    paddrc - 2 + j] <<
-				    32 * (MIN(2, paddrc) - j - 1);
-			start += phys - cstart;
-			end += phys - cstart;
 			if (OF_getprop(pbus, "name", name, sizeof(name)) == -1)
 				return (ENXIO);
 			name[sizeof(name) - 1] = '\0';
-			spc = phys_hi_mask_space(name,
-			    banks[(addrc + paddrc + szc) * i + addrc]);
+			spc = phys_hi_mask_space(name, pspc);
+			start += pphys - cstart;
+			end += pphys - cstart;
 			break;
 		}
 		if (i == nbank)
@@ -239,8 +238,8 @@ OF_decode_addr(phandle_t node, int bank,
 		bus = pbus;
 	}
 
-	/* Done with mapping. Return the bus space as used by FreeBSD. */
 	*addr = start;
+	/* Determine the bus space based on the last bus we mapped. */
 	if (OF_parent(lbus) == 0) {
 		*space = NEXUS_BUS_SPACE;
 		return (0);
@@ -248,11 +247,12 @@ OF_decode_addr(phandle_t node, int bank,
 	if (OF_getprop(lbus, "name", name, sizeof(name)) == -1)
 		return (ENXIO);
 	name[sizeof(name) - 1] = '\0';
-	if (strcmp(name, "central") == 0 || strcmp(name, "upa") == 0) {
+	if (strcmp(name, "central") == 0 || strcmp(name, "ebus") == 0 ||
+	    strcmp(name, "upa") == 0) {
 		*space = NEXUS_BUS_SPACE;
 		return (0);
 	} else if (strcmp(name, "pci") == 0) {
-		switch (cspace) {
+		switch (cspc) {
 		case OFW_PCI_PHYS_HI_SPACE_IO:
 			*space = PCI_IO_BUS_SPACE;
 			return (0);


More information about the svn-src-all mailing list