Req review: OF_decode_addr()

Marcel Moolenaar marcel at xcllnt.net
Mon Sep 1 19:18:15 PDT 2003


Gang,

Attached a patch to add function OF_decode_addr(). The function
takes a package handle (phandle_t) and returns the physical
(decoded) address at which it resides as well as it space.
This function is needed by uart(4) to for low-level console
access.

There's one thing I'm not happy about and that's the call to
ofw_isa_map_iorange(). It makes it impossible to create a kernel
without isa. It makes sense to move the bulk of the code in
OF_decode_addr() to the respective bus drivers and have some
linker set to tie bus name to function pointer. I'm not sure
it's important to have that right away or if we can commit this
and deal with that later?

-- 
 Marcel Moolenaar	  USPA: A-39004		 marcel at xcllnt.net
-------------- next part --------------
Index: dev/gem/if_gem_pci.c
===================================================================
RCS file: /home/ncvs/src/sys/dev/gem/if_gem_pci.c,v
retrieving revision 1.11
diff -u -r1.11 if_gem_pci.c
--- dev/gem/if_gem_pci.c	24 Aug 2003 17:46:07 -0000	1.11
+++ dev/gem/if_gem_pci.c	2 Sep 2003 02:01:34 -0000
@@ -53,6 +53,7 @@
 
 #include <machine/bus.h>
 #include <machine/resource.h>
+#include <dev/ofw/openfirm.h>
 #include <machine/ofw_machdep.h>
 
 #include <sys/rman.h>
Index: dev/hme/if_hme_pci.c
===================================================================
RCS file: /home/ncvs/src/sys/dev/hme/if_hme_pci.c,v
retrieving revision 1.10
diff -u -r1.10 if_hme_pci.c
--- dev/hme/if_hme_pci.c	24 Aug 2003 17:46:09 -0000	1.10
+++ dev/hme/if_hme_pci.c	2 Sep 2003 02:03:45 -0000
@@ -43,6 +43,7 @@
 #include <sys/socket.h>
 
 #include <machine/bus.h>
+#include <dev/ofw/openfirm.h>
 #include <machine/ofw_machdep.h>
 #include <machine/resource.h>
 
Index: dev/hme/if_hme_sbus.c
===================================================================
RCS file: /home/ncvs/src/sys/dev/hme/if_hme_sbus.c,v
retrieving revision 1.7
diff -u -r1.7 if_hme_sbus.c
--- dev/hme/if_hme_sbus.c	24 Aug 2003 17:46:09 -0000	1.7
+++ dev/hme/if_hme_sbus.c	2 Sep 2003 02:03:55 -0000
@@ -51,6 +51,7 @@
 #include <sys/socket.h>
 
 #include <machine/bus.h>
+#include <dev/ofw/openfirm.h>
 #include <machine/ofw_machdep.h>
 #include <machine/resource.h>
 
Index: dev/isp/isp_sbus.c
===================================================================
RCS file: /home/ncvs/src/sys/dev/isp/isp_sbus.c,v
retrieving revision 1.10
diff -u -r1.10 isp_sbus.c
--- dev/isp/isp_sbus.c	24 Aug 2003 17:49:14 -0000	1.10
+++ dev/isp/isp_sbus.c	2 Sep 2003 00:47:52 -0000
@@ -35,10 +35,10 @@
 #include <sys/kernel.h>
 #include <sys/resource.h>
 #include <machine/bus.h>
-#include <machine/ofw_machdep.h>
 #include <machine/resource.h>
 #include <sys/rman.h>
 #include <dev/ofw/openfirm.h>
+#include <machine/ofw_machdep.h>
 #include <sparc64/sbus/sbusvar.h>
 
 #include <dev/isp/isp_freebsd.h>
Index: sparc64/include/ofw_machdep.h
===================================================================
RCS file: /home/ncvs/src/sys/sparc64/include/ofw_machdep.h,v
retrieving revision 1.2
diff -u -r1.2 ofw_machdep.h
--- sparc64/include/ofw_machdep.h	13 Mar 2002 04:59:01 -0000	1.2
+++ sparc64/include/ofw_machdep.h	2 Sep 2003 00:20:14 -0000
@@ -30,7 +30,8 @@
 
 #include <sys/bus.h>
 
-void OF_getetheraddr(device_t dev, u_char *addr);
+int  OF_decode_addr(phandle_t, int *, bus_addr_t *);
+void OF_getetheraddr(device_t, u_char *);
 void cpu_shutdown(void *);
 void openfirmware_exit(void *);
 
Index: sparc64/sparc64/machdep.c
===================================================================
RCS file: /home/ncvs/src/sys/sparc64/sparc64/machdep.c,v
retrieving revision 1.100
diff -u -r1.100 machdep.c
--- sparc64/sparc64/machdep.c	11 Aug 2003 07:05:55 -0000	1.100
+++ sparc64/sparc64/machdep.c	2 Sep 2003 01:26:18 -0000
@@ -89,6 +89,7 @@
 
 #include <ddb/ddb.h>
 
+#include <machine/bus.h>
 #include <machine/cache.h>
 #include <machine/clock.h>
 #include <machine/cpu.h>
Index: sparc64/sparc64/mp_machdep.c
===================================================================
RCS file: /home/ncvs/src/sys/sparc64/sparc64/mp_machdep.c,v
retrieving revision 1.22
diff -u -r1.22 mp_machdep.c
--- sparc64/sparc64/mp_machdep.c	22 Aug 2003 07:38:08 -0000	1.22
+++ sparc64/sparc64/mp_machdep.c	2 Sep 2003 01:27:06 -0000
@@ -80,6 +80,7 @@
 
 #include <machine/asi.h>
 #include <machine/atomic.h>
+#include <machine/bus.h>
 #include <machine/md_var.h>
 #include <machine/metadata.h>
 #include <machine/ofw_machdep.h>
Index: sparc64/sparc64/ofw_machdep.c
===================================================================
RCS file: /home/ncvs/src/sys/sparc64/sparc64/ofw_machdep.c,v
retrieving revision 1.3
diff -u -r1.3 ofw_machdep.c
--- sparc64/sparc64/ofw_machdep.c	23 Aug 2003 00:11:15 -0000	1.3
+++ sparc64/sparc64/ofw_machdep.c	2 Sep 2003 00:24:55 -0000
@@ -36,8 +36,15 @@
 
 #include <dev/ofw/openfirm.h>
 
+#include <machine/bus.h>
 #include <machine/idprom.h>
 #include <machine/ofw_machdep.h>
+#include <machine/ofw_upa.h>
+#include <machine/resource.h>
+
+#include <sparc64/pci/ofw_pci.h>
+#include <sparc64/isa/ofw_isa.h>
+#include <sparc64/sbus/ofw_sbus.h>
 
 void
 OF_getetheraddr(device_t dev, u_char *addr)
@@ -49,4 +56,107 @@
 	if (node <= 0 || OF_getprop(node, "idprom", &idp, sizeof(idp)) == -1)
 		panic("Could not determine the machine ethernet address");
 	bcopy(&idp.id_ether, addr, ETHER_ADDR_LEN);
+}
+
+int
+OF_decode_addr(phandle_t node, int *space, bus_addr_t *addr)
+{
+	char name[32];
+	union {
+		struct isa_ranges isa[4];
+		struct sbus_ranges sbus[8];
+		struct upa_ranges upa[4];
+	} range;
+	union {
+		struct isa_regs isa;
+		struct sbus_regs sbus;
+	} reg;
+	phandle_t bus, pbus;
+	u_long child, dummy, phys;
+	int cs, i, rsz, type;
+
+	bus = OF_parent(node);
+	if (bus == NULL)
+		return (ENXIO);
+	if (OF_getprop(bus, "name", name, sizeof(name)) == -1)
+		return (ENXIO);
+	name[sizeof(name) - 1] = '\0';
+	if (strcmp(name, "ebus") == 0) {
+		if (OF_getprop(node, "reg", &reg.isa, sizeof(reg.isa)) == -1)
+			return (ENXIO);
+		rsz = OF_getprop(bus, "ranges", range.isa, sizeof(range.isa));
+		if (rsz == -1)
+			return (ENXIO);
+		phys = ISA_REG_PHYS(&reg.isa);
+		dummy = phys + 1;
+		type = ofw_isa_map_iorange(range.isa, rsz / sizeof(*range.isa),
+		    &phys, &dummy);
+		if (type == SYS_RES_MEMORY) {
+			cs = PCI_CS_MEM32;
+			*space = PCI_MEMORY_BUS_SPACE;
+		} else {
+			cs = PCI_CS_IO;
+			*space = PCI_IO_BUS_SPACE;
+		}
+
+		/* Find the topmost PCI node (the host bridge) */
+		while (1) {
+			pbus = OF_parent(bus);
+			if (pbus == NULL)
+				return (ENXIO);
+			if (OF_getprop(pbus, "name", name, sizeof(name)) == -1)
+				return (ENXIO);
+			name[sizeof(name) - 1] = '\0';
+			if (strcmp(name, "pci") != 0)
+				break;
+			bus = pbus;
+		}
+
+		/* There wasn't a PCI bridge. */
+		if (bus == OF_parent(node))
+			return (ENXIO);
+
+		/* Make sure we reached the UPA/PCI node. */
+		if (OF_getprop(pbus, "device_type", name, sizeof(name)) == -1)
+			return (ENXIO);
+		name[sizeof(name) - 1] = '\0';
+		if (strcmp(name, "upa") != 0)
+			return (ENXIO);
+
+		rsz = OF_getprop(bus, "ranges", range.upa, sizeof(range.upa));
+		if (rsz == -1)
+			return (ENXIO);
+		for (i = 0; i < (rsz / sizeof(range.upa[0])); i++) {
+			child = UPA_RANGE_CHILD(&range.upa[i]);
+			if (UPA_RANGE_CS(&range.upa[i]) == cs &&
+			    phys >= child &&
+			    phys - child < UPA_RANGE_SIZE(&range.upa[i])) {
+				*addr = UPA_RANGE_PHYS(&range.upa[i]) + phys;
+				return (0);
+			}
+		}
+	} else if (strcmp(name, "sbus") == 0) {
+		if (OF_getprop(node, "reg", &reg.sbus, sizeof(reg.sbus)) == -1)
+			return (ENXIO);
+		rsz = OF_getprop(bus, "ranges", range.sbus,
+		    sizeof(range.sbus));
+		if (rsz == -1)
+			return (ENXIO);
+		for (i = 0; i < (rsz / sizeof(range.sbus[0])); i++) {
+			if (reg.sbus.sbr_slot != range.sbus[i].cspace)
+				continue;
+			if (reg.sbus.sbr_offset < range.sbus[i].coffset ||
+			    reg.sbus.sbr_offset >= range.sbus[i].coffset +
+			    range.sbus[i].size)
+				continue;
+			/* Found it... */
+			phys = range.sbus[i].poffset |
+			    ((bus_addr_t)range.sbus[i].pspace << 32);
+			phys += reg.sbus.sbr_offset - range.sbus[i].coffset;
+			*addr = phys;
+			*space = SBUS_BUS_SPACE;
+			return (0);
+		}
+	}
+	return (ENXIO);
 }
Index: sparc64/sparc64/vm_machdep.c
===================================================================
RCS file: /home/ncvs/src/sys/sparc64/sparc64/vm_machdep.c,v
retrieving revision 1.51
diff -u -r1.51 vm_machdep.c
--- sparc64/sparc64/vm_machdep.c	29 Aug 2003 20:04:10 -0000	1.51
+++ sparc64/sparc64/vm_machdep.c	2 Sep 2003 01:28:46 -0000
@@ -76,6 +76,7 @@
 #include <vm/uma_int.h>
 
 #include <machine/cache.h>
+#include <machine/bus.h>
 #include <machine/cpu.h>
 #include <machine/fp.h>
 #include <machine/fsr.h>


More information about the freebsd-sparc64 mailing list