PERFORCE change 37148 for review
Marcel Moolenaar
marcel at FreeBSD.org
Thu Aug 28 20:54:50 PDT 2003
http://perforce.freebsd.org/chv.cgi?CH=37148
Change 37148 by marcel at marcel_nfs on 2003/08/28 20:54:18
Teach OF_decode_addr() about the sbus. This hasn't been tested
properly. The ebus decoding still works though :-)
Affected files ...
.. //depot/projects/uart/sparc64/sparc64/ofw_machdep.c#4 edit
Differences ...
==== //depot/projects/uart/sparc64/sparc64/ofw_machdep.c#4 (text+ko) ====
@@ -44,6 +44,7 @@
#include <sparc64/pci/ofw_pci.h>
#include <sparc64/isa/ofw_isa.h>
+#include <sparc64/sbus/ofw_sbus.h>
int OF_decode_addr(phandle_t node, int *space, bus_addr_t *addr);
@@ -63,55 +64,99 @@
OF_decode_addr(phandle_t node, int *space, bus_addr_t *addr)
{
char name[32];
- struct isa_ranges ir[4];
- struct isa_regs reg;
- struct upa_ranges ur[4];
- phandle_t bus, parent, pbus;
+ 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;
- parent = OF_parent(node);
- if (parent == NULL)
+ bus = OF_parent(node);
+ if (bus == NULL)
return (ENXIO);
- rsz = OF_getprop(parent, "ranges", ir, sizeof(ir));
- if (rsz == -1 || OF_getprop(node, "reg", ®, sizeof(reg)) == -1)
- return (ENXIO);
- phys = ISA_REG_PHYS(®);
- dummy = phys + 1;
- type = ofw_isa_map_iorange(ir, rsz / sizeof(*ir), &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;
- }
- bus = OF_parent(parent);
if (OF_getprop(bus, "name", name, sizeof(name)) == -1)
return (ENXIO);
name[sizeof(name) - 1] = '\0';
- if (strcmp(name, "pci") != 0)
- return (ENXIO);
+ if (strcmp(name, "ebus") == 0) {
+ if (OF_getprop(node, "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(®.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 ((pbus = OF_parent(bus)) != 0) {
- if (OF_getprop(pbus, "name", name, sizeof(name)) != -1) {
+ /* 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);
+ }
}
- bus = pbus;
- }
- if (pbus == 0)
- return (ENXIO);
- if ((rsz = OF_getprop(bus, "ranges", ur, sizeof(ur))) == -1)
- return (ENXIO);
- for (i = 0; i < (rsz / sizeof(ur[0])); i++) {
- child = UPA_RANGE_CHILD(&ur[i]);
- if (UPA_RANGE_CS(&ur[i]) == cs && phys >= child &&
- phys - child < UPA_RANGE_SIZE(&ur[i])) {
- *addr = UPA_RANGE_PHYS(&ur[i]) + phys;
- return (0);
+ } else if (strcmp(name, "sbus") == 0) {
+ if (OF_getprop(node, "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 (ENXIO);
More information about the p4-projects
mailing list