2 * Copyright (c) 2001 by Thomas Moestl <tmm@FreeBSD.org>.
3 * Copyright (c) 2005 by Marius Strobl <marius@FreeBSD.org>.
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18 * IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
19 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
20 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
21 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
22 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
23 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
24 * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 #include <sys/cdefs.h>
28 __FBSDID("$FreeBSD$");
31 * Some Open Firmware helper functions that are likely machine dependent.
34 #include <sys/param.h>
36 #include <sys/systm.h>
38 #include <net/ethernet.h>
40 #include <dev/ofw/ofw_bus.h>
41 #include <dev/ofw/ofw_pci.h>
42 #include <dev/ofw/openfirm.h>
44 #include <machine/bus.h>
45 #include <machine/idprom.h>
46 #include <machine/ofw_machdep.h>
49 OF_getetheraddr(device_t dev, u_char *addr)
51 char buf[sizeof("true")];
55 if ((node = OF_finddevice("/options")) > 0 &&
56 OF_getprop(node, "local-mac-address?", buf, sizeof(buf)) > 0) {
57 buf[sizeof(buf) - 1] = '\0';
58 if (strcmp(buf, "true") == 0 &&
59 (node = ofw_bus_get_node(dev)) > 0 &&
60 OF_getprop(node, "local-mac-address", addr,
61 ETHER_ADDR_LEN) == ETHER_ADDR_LEN)
66 if (node <= 0 || OF_getprop(node, "idprom", &idp, sizeof(idp)) == -1)
67 panic("Could not determine the machine ethernet address");
68 bcopy(&idp.id_ether, addr, ETHER_ADDR_LEN);
71 static __inline uint32_t
72 phys_hi_mask_space(const char *bus, uint32_t phys_hi)
77 if (strcmp(bus, "ebus") == 0 || strcmp(bus, "isa") == 0)
79 else if (strcmp(bus, "pci") == 0)
80 space &= OFW_PCI_PHYS_HI_SPACEMASK;
81 /* The phys.hi cells of the other busses only contain space bits. */
86 * Return the physical address and the bus space to use for a node
87 * referenced by its package handle and the index of the register bank
88 * to decode. Intended to be used to together with sparc64_fake_bustag()
89 * by console drivers in early boot only.
90 * Works by mapping the address of the node's bank given in the address
91 * space of its parent upward in the device tree at each bridge along the
93 * Currently only really deals with max. 64-bit addresses, i.e. addresses
94 * consisting of max. 2 phys cells (phys.hi and phys.lo). If we encounter
95 * a 3 phys cells address (as with PCI addresses) we assume phys.hi can
96 * be ignored except for the space bits (generally contained in phys.hi)
97 * and treat phys.mid as phys.hi.
100 OF_decode_addr(phandle_t node, int bank, int *space, bus_addr_t *addr)
103 uint64_t cend, cstart, end, phys, sz, start;
104 pcell_t addrc, szc, paddrc;
105 phandle_t bus, lbus, pbus;
106 uint32_t banks[10 * 5]; /* 10 PCI banks */
107 uint32_t cspace, spc;
111 * In general the addresses are contained in the "reg" property
112 * of a node. The first address in the "reg" property of a PCI
113 * node however is the address of its configuration registers in
114 * the configuration space of the host bridge. Additional entries
115 * denote the memory and I/O addresses. For relocatable addresses
116 * the "reg" property contains the BAR, for non-relocatable
117 * addresses it contains the absolute PCI address. The PCI-only
118 * "assigned-addresses" property however always contains the
119 * absolute PCI addresses.
120 * The "assigned-addresses" and "reg" properties are arrays of
121 * address structures consisting of #address-cells 32-bit phys
122 * cells and #size-cells 32-bit size cells. If a parent lacks
123 * the "#address-cells" or "#size-cells" property the default
124 * for #address-cells to use is 2 and for #size-cells 1.
126 bus = OF_parent(node);
129 if (OF_getprop(bus, "name", name, sizeof(name)) == -1)
131 name[sizeof(name) - 1] = '\0';
132 if (OF_getprop(bus, "#address-cells", &addrc, sizeof(addrc)) == -1)
134 if (OF_getprop(bus, "#size-cells", &szc, sizeof(szc)) == -1)
136 if (addrc < 2 || addrc > 3 || szc < 1 || szc > 2)
138 if (strcmp(name, "pci") == 0) {
141 nbank = OF_getprop(node, "assigned-addresses", &banks,
146 nbank = OF_getprop(node, "reg", &banks, sizeof(banks));
150 nbank /= sizeof(banks[0]) * (addrc + szc);
151 if (bank < 0 || bank > nbank - 1)
154 for (i = 0; i < MIN(2, addrc); i++)
155 phys |= (uint64_t)banks[(addrc + szc) * bank + addrc - 2 + i] <<
156 32 * (MIN(2, addrc) - i - 1);
158 for (i = 0; i < szc; i++)
159 sz |= (uint64_t)banks[(addrc + szc) * bank + addrc + i] <<
163 spc = phys_hi_mask_space(name, banks[(addrc + szc) * bank]);
166 * Map upward in the device tree at every bridge we encounter
167 * using their "ranges" properties.
168 * The "ranges" property of a bridge is an array of a structure
169 * consisting of that bridge's #address-cells 32-bit child-phys
170 * cells, its parent bridge #address-cells 32-bit parent-phys
171 * cells and that bridge's #size-cells 32-bit size cells.
172 * If a bridge doesn't have a "ranges" property no mapping is
173 * necessary at that bridge.
177 while ((pbus = OF_parent(bus)) != 0) {
178 if (OF_getprop(pbus, "#address-cells", &paddrc,
179 sizeof(paddrc)) == -1)
181 if (paddrc < 2 || paddrc > 3)
183 nbank = OF_getprop(bus, "ranges", &banks, sizeof(banks));
185 if (OF_getprop(pbus, "name", name, sizeof(name)) == -1)
187 name[sizeof(name) - 1] = '\0';
191 if (OF_getprop(bus, "#size-cells", &szc,
194 if (szc < 1 || szc > 2)
197 nbank /= sizeof(banks[0]) * (addrc + paddrc + szc);
198 for (i = 0; i < nbank; i++) {
199 cspace = phys_hi_mask_space(name,
200 banks[(addrc + paddrc + szc) * i]);
204 for (j = 0; j < MIN(2, addrc); j++)
205 phys |= (uint64_t)banks[
206 (addrc + paddrc + szc) * i +
208 32 * (MIN(2, addrc) - j - 1);
210 for (j = 0; j < szc; j++)
211 sz |= (uint64_t)banks[
212 (addrc + paddrc + szc) * i + addrc +
216 cend = phys + sz - 1;
217 if (start < cstart || start > cend)
219 if (end < cstart || end > cend)
222 for (j = 0; j < MIN(2, paddrc); j++)
223 phys |= (uint64_t)banks[
224 (addrc + paddrc + szc) * i + addrc +
226 32 * (MIN(2, paddrc) - j - 1);
227 start += phys - cstart;
228 end += phys - cstart;
229 if (OF_getprop(pbus, "name", name, sizeof(name)) == -1)
231 name[sizeof(name) - 1] = '\0';
232 spc = phys_hi_mask_space(name,
233 banks[(addrc + paddrc + szc) * i + addrc]);
244 /* Done with mapping. Return the bus space as used by FreeBSD. */
246 if (OF_parent(lbus) == 0) {
247 *space = NEXUS_BUS_SPACE;
250 if (OF_getprop(lbus, "name", name, sizeof(name)) == -1)
252 name[sizeof(name) - 1] = '\0';
253 if (strcmp(name, "central") == 0 || strcmp(name, "upa") == 0) {
254 *space = NEXUS_BUS_SPACE;
256 } else if (strcmp(name, "pci") == 0) {
258 case OFW_PCI_PHYS_HI_SPACE_IO:
259 *space = PCI_IO_BUS_SPACE;
261 case OFW_PCI_PHYS_HI_SPACE_MEM32:
262 *space = PCI_MEMORY_BUS_SPACE;
265 } else if (strcmp(name, "sbus") == 0) {
266 *space = SBUS_BUS_SPACE;