1 /*-
2  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
3  *
4  * Copyright (c) 2001 by Thomas Moestl <[email protected]>.
5  * Copyright (c) 2005 - 2010 by Marius Strobl <[email protected]>.
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20  * IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
21  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
23  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
24  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
25  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
26  * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27  */
28 
29 #include <sys/cdefs.h>
30 __FBSDID("$FreeBSD$");
31 
32 /*
33  * Some Open Firmware helper functions that are likely machine dependent.
34  */
35 
36 #include <sys/param.h>
37 #include <sys/bus.h>
38 #include <sys/systm.h>
39 
40 #include <net/ethernet.h>
41 
42 #include <dev/ofw/ofw_bus.h>
43 #include <dev/ofw/ofw_pci.h>
44 #include <dev/ofw/openfirm.h>
45 
46 #include <machine/bus.h>
47 #include <machine/idprom.h>
48 #include <machine/ofw_machdep.h>
49 #include <machine/stdarg.h>
50 
51 void
OF_getetheraddr(device_t dev,u_char * addr)52 OF_getetheraddr(device_t dev, u_char *addr)
53 {
54 	char buf[sizeof("true")];
55 	phandle_t node;
56 	struct idprom idp;
57 
58 	if ((node = OF_finddevice("/options")) != -1 &&
59 	    OF_getprop(node, "local-mac-address?", buf, sizeof(buf)) > 0) {
60 		buf[sizeof(buf) - 1] = '\0';
61 		if (strcmp(buf, "true") == 0 &&
62 		    (node = ofw_bus_get_node(dev)) > 0 &&
63 		    OF_getprop(node, "local-mac-address", addr,
64 		    ETHER_ADDR_LEN) == ETHER_ADDR_LEN)
65 			return;
66 	}
67 
68 	node = OF_peer(0);
69 	if (node <= 0 || OF_getprop(node, "idprom", &idp, sizeof(idp)) == -1)
70 		panic("Could not determine the machine Ethernet address");
71 	bcopy(&idp.id_ether, addr, ETHER_ADDR_LEN);
72 }
73 
74 u_int
OF_getscsinitid(device_t dev)75 OF_getscsinitid(device_t dev)
76 {
77 	phandle_t node;
78 	uint32_t id;
79 
80 	for (node = ofw_bus_get_node(dev); node != 0; node = OF_parent(node))
81 		if (OF_getprop(node, "scsi-initiator-id", &id,
82 		    sizeof(id)) > 0)
83 			return (id);
84 	return (7);
85 }
86 
87 void
OF_panic(const char * fmt,...)88 OF_panic(const char *fmt, ...)
89 {
90 	char buf[256];
91 	va_list ap;
92 
93 	va_start(ap, fmt);
94 	(void)vsnprintf(buf, sizeof(buf), fmt, ap);
95 	OF_printf("OF_panic: %s\n", buf);
96 	va_end(ap);
97 	OF_exit();
98 }
99 
100 static __inline uint32_t
phys_hi_mask_space(const char * bus,uint32_t phys_hi)101 phys_hi_mask_space(const char *bus, uint32_t phys_hi)
102 {
103 
104 	if (strcmp(bus, "ebus") == 0 || strcmp(bus, "isa") == 0)
105 		phys_hi &= 0x1;
106 	else if (strcmp(bus, "pci") == 0)
107 		phys_hi &= OFW_PCI_PHYS_HI_SPACEMASK;
108 	/* The phys.hi cells of the other busses only contain space bits. */
109 	return (phys_hi);
110 }
111 
112 /*
113  * Return the physical address and the bus space to use for a node
114  * referenced by its package handle and the index of the register bank
115  * to decode.  Intended to be used to together with sparc64_fake_bustag()
116  * by console drivers in early boot only.
117  * Works by mapping the address of the node's bank given in the address
118  * space of its parent upward in the device tree at each bridge along the
119  * path.
120  * Currently only really deals with max. 64-bit addresses, i.e. addresses
121  * consisting of max. 2 phys cells (phys.hi and phys.lo).  If we encounter
122  * a 3 phys cells address (as with PCI addresses) we assume phys.hi can
123  * be ignored except for the space bits (generally contained in phys.hi)
124  * and treat phys.mid as phys.hi.
125  */
126 int
OF_decode_addr(phandle_t node,int bank,int * space,bus_addr_t * addr)127 OF_decode_addr(phandle_t node, int bank, int *space, bus_addr_t *addr)
128 {
129 	char name[32];
130 	uint64_t cend, cstart, end, phys, pphys, sz, start;
131 	pcell_t addrc, szc, paddrc;
132 	phandle_t bus, lbus, pbus;
133 	uint32_t banks[10 * 5];	/* 10 PCI banks */
134 	uint32_t cspc, pspc, spc;
135 	int i, j, nbank;
136 
137 	/*
138 	 * In general the addresses are contained in the "reg" property
139 	 * of a node.  The first address in the "reg" property of a PCI
140 	 * node however is the address of its configuration registers in
141 	 * the configuration space of the host bridge.  Additional entries
142 	 * denote the memory and I/O addresses.  For relocatable addresses
143 	 * the "reg" property contains the BAR, for non-relocatable
144 	 * addresses it contains the absolute PCI address.  The PCI-only
145 	 * "assigned-addresses" property however always contains the
146 	 * absolute PCI addresses.
147 	 * The "assigned-addresses" and "reg" properties are arrays of
148 	 * address structures consisting of #address-cells 32-bit phys
149 	 * cells and #size-cells 32-bit size cells.  If a parent lacks
150 	 * the "#address-cells" or "#size-cells" property the default
151 	 * for #address-cells to use is 2 and for #size-cells 1.
152 	 */
153 	bus = OF_parent(node);
154 	if (bus == 0)
155 		return (ENXIO);
156 	if (OF_getprop(bus, "name", name, sizeof(name)) == -1)
157 		return (ENXIO);
158 	name[sizeof(name) - 1] = '\0';
159 	if (OF_getprop(bus, "#address-cells", &addrc, sizeof(addrc)) == -1)
160 		addrc = 2;
161 	if (OF_getprop(bus, "#size-cells", &szc, sizeof(szc)) == -1)
162 		szc = 1;
163 	if (addrc < 2 || addrc > 3 || szc < 1 || szc > 2)
164 		return (ENXIO);
165 	if (strcmp(name, "pci") == 0) {
166 		if (addrc > 3)
167 			return (ENXIO);
168 		nbank = OF_getprop(node, "assigned-addresses", &banks,
169 		    sizeof(banks));
170 	} else {
171 		if (addrc > 2)
172 			return (ENXIO);
173 		nbank = OF_getprop(node, "reg", &banks, sizeof(banks));
174 	}
175 	if (nbank == -1)
176 		return (ENXIO);
177 	nbank /= sizeof(banks[0]) * (addrc + szc);
178 	if (bank < 0 || bank > nbank - 1)
179 		return (ENXIO);
180 	bank *= addrc + szc;
181 	spc = phys_hi_mask_space(name, banks[bank]);
182 	/* Skip the high cell for 3-cell addresses. */
183 	bank += addrc - 2;
184 	phys = 0;
185 	for (i = 0; i < MIN(2, addrc); i++)
186 		phys = ((uint64_t)phys << 32) | banks[bank++];
187 	sz = 0;
188 	for (i = 0; i < szc; i++)
189 		sz = ((uint64_t)sz << 32) | banks[bank++];
190 	start = phys;
191 	end = phys + sz - 1;
192 
193 	/*
194 	 * Map upward in the device tree at every bridge we encounter
195 	 * using their "ranges" properties.
196 	 * The "ranges" property of a bridge is an array of a structure
197 	 * consisting of that bridge's #address-cells 32-bit child-phys
198 	 * cells, its parent bridge #address-cells 32-bit parent-phys
199 	 * cells and that bridge's #size-cells 32-bit size cells.
200 	 * If a bridge doesn't have a "ranges" property no mapping is
201 	 * necessary at that bridge.
202 	 */
203 	cspc = 0;
204 	lbus = bus;
205 	while ((pbus = OF_parent(bus)) != 0) {
206 		if (OF_getprop(pbus, "#address-cells", &paddrc,
207 		    sizeof(paddrc)) == -1)
208 			paddrc = 2;
209 		if (paddrc < 2 || paddrc > 3)
210 			return (ENXIO);
211 		nbank = OF_getprop(bus, "ranges", &banks, sizeof(banks));
212 		if (nbank == -1) {
213 			if (OF_getprop(pbus, "name", name, sizeof(name)) == -1)
214 				return (ENXIO);
215 			name[sizeof(name) - 1] = '\0';
216 			goto skip;
217 		}
218 		if (OF_getprop(bus, "#size-cells", &szc, sizeof(szc)) == -1)
219 			szc = 1;
220 		if (szc < 1 || szc > 2)
221 			return (ENXIO);
222 		nbank /= sizeof(banks[0]) * (addrc + paddrc + szc);
223 		bank = 0;
224 		for (i = 0; i < nbank; i++) {
225 			cspc = phys_hi_mask_space(name, banks[bank]);
226 			if (cspc != spc) {
227 				bank += addrc + paddrc + szc;
228 				continue;
229 			}
230 			/* Skip the high cell for 3-cell addresses. */
231 			bank += addrc - 2;
232 			phys = 0;
233 			for (j = 0; j < MIN(2, addrc); j++)
234 				phys = ((uint64_t)phys << 32) | banks[bank++];
235 			pspc = banks[bank];
236 			/* Skip the high cell for 3-cell addresses. */
237 			bank += paddrc - 2;
238 			pphys = 0;
239 			for (j = 0; j < MIN(2, paddrc); j++)
240 				pphys =
241 				    ((uint64_t)pphys << 32) | banks[bank++];
242 			sz = 0;
243 			for (j = 0; j < szc; j++)
244 				sz = ((uint64_t)sz << 32) | banks[bank++];
245 			cstart = phys;
246 			cend = phys + sz - 1;
247 			if (start < cstart || start > cend)
248 				continue;
249 			if (end < cstart || end > cend)
250 				return (ENXIO);
251 			if (OF_getprop(pbus, "name", name, sizeof(name)) == -1)
252 				return (ENXIO);
253 			name[sizeof(name) - 1] = '\0';
254 			spc = phys_hi_mask_space(name, pspc);
255 			start += pphys - cstart;
256 			end += pphys - cstart;
257 			break;
258 		}
259 		if (i == nbank)
260 			return (ENXIO);
261 		lbus = bus;
262  skip:
263 		addrc = paddrc;
264 		bus = pbus;
265 	}
266 
267 	*addr = start;
268 	/* Determine the bus space based on the last bus we mapped. */
269 	if (OF_parent(lbus) == 0) {
270 		*space = NEXUS_BUS_SPACE;
271 		return (0);
272 	}
273 	if (OF_getprop(lbus, "name", name, sizeof(name)) == -1)
274 		return (ENXIO);
275 	name[sizeof(name) - 1] = '\0';
276 	if (strcmp(name, "central") == 0 || strcmp(name, "ebus") == 0 ||
277 	    strcmp(name, "upa") == 0) {
278 		*space = NEXUS_BUS_SPACE;
279 		return (0);
280 	} else if (strcmp(name, "pci") == 0) {
281 		switch (cspc) {
282 		case OFW_PCI_PHYS_HI_SPACE_IO:
283 			*space = PCI_IO_BUS_SPACE;
284 			return (0);
285 		case OFW_PCI_PHYS_HI_SPACE_MEM32:
286 			*space = PCI_MEMORY_BUS_SPACE;
287 			return (0);
288 		}
289 	} else if (strcmp(name, "sbus") == 0) {
290 		*space = SBUS_BUS_SPACE;
291 		return (0);
292 	}
293 	return (ENXIO);
294 }
295