xref: /freebsd/sys/dev/bhnd/bhnd_subr.c (revision 1d386b48)
1 /*-
2  * SPDX-License-Identifier: BSD-2-Clause
3  *
4  * Copyright (c) 2015-2016 Landon Fuller <landon@landonf.org>
5  * Copyright (c) 2017 The FreeBSD Foundation
6  * All rights reserved.
7  *
8  * Portions of this software were developed by Landon Fuller
9  * under sponsorship from the FreeBSD Foundation.
10  *
11  * Redistribution and use in source and binary forms, with or without
12  * modification, are permitted provided that the following conditions
13  * are met:
14  * 1. Redistributions of source code must retain the above copyright
15  *    notice, this list of conditions and the following disclaimer,
16  *    without modification.
17  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18  *    similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any
19  *    redistribution must be conditioned upon including a substantially
20  *    similar Disclaimer requirement for further binary redistribution.
21  *
22  * NO WARRANTY
23  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
24  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
25  * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY
26  * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
27  * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY,
28  * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
29  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
30  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
31  * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
32  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
33  * THE POSSIBILITY OF SUCH DAMAGES.
34  */
35 
36 #include <sys/cdefs.h>
37 #include <sys/param.h>
38 #include <sys/bus.h>
39 #include <sys/refcount.h>
40 #include <sys/systm.h>
41 
42 #include <machine/bus.h>
43 #include <sys/rman.h>
44 #include <machine/resource.h>
45 
46 #include <dev/bhnd/siba/sibareg.h>
47 
48 #include <dev/bhnd/cores/chipc/chipcreg.h>
49 
50 #include "nvram/bhnd_nvram.h"
51 
52 #include "bhnd_chipc_if.h"
53 
54 #include "bhnd_nvram_if.h"
55 #include "bhnd_nvram_map.h"
56 
57 #include "bhndreg.h"
58 #include "bhndvar.h"
59 #include "bhnd_private.h"
60 
61 static void	bhnd_service_registry_free_entry(
62 		    struct bhnd_service_entry *entry);
63 
64 static int	compare_ascending_probe_order(const void *lhs, const void *rhs);
65 static int	compare_descending_probe_order(const void *lhs,
66 		    const void *rhs);
67 
68 /* BHND core device description table. */
69 static const struct bhnd_core_desc {
70 	uint16_t	 vendor;
71 	uint16_t	 device;
72 	bhnd_devclass_t	 class;
73 	const char	*desc;
74 } bhnd_core_descs[] = {
75 	#define	BHND_CDESC(_mfg, _cid, _cls, _desc)		\
76 	    { BHND_MFGID_ ## _mfg, BHND_COREID_ ## _cid,	\
77 		BHND_DEVCLASS_ ## _cls, _desc }
78 
79 	BHND_CDESC(BCM, CC,		CC,		"ChipCommon I/O Controller"),
80 	BHND_CDESC(BCM, ILINE20,	OTHER,		"iLine20 HPNA"),
81 	BHND_CDESC(BCM, SRAM,		RAM,		"SRAM"),
82 	BHND_CDESC(BCM, SDRAM,		RAM,		"SDRAM"),
83 	BHND_CDESC(BCM, PCI,		PCI,		"PCI Bridge"),
84 	BHND_CDESC(BCM, MIPS,		CPU,		"BMIPS CPU"),
85 	BHND_CDESC(BCM, ENET,		ENET_MAC,	"Fast Ethernet MAC"),
86 	BHND_CDESC(BCM, V90_CODEC,	SOFTMODEM,	"V.90 SoftModem Codec"),
87 	BHND_CDESC(BCM, USB,		USB_DUAL,	"USB 1.1 Device/Host Controller"),
88 	BHND_CDESC(BCM, ADSL,		OTHER,		"ADSL Core"),
89 	BHND_CDESC(BCM, ILINE100,	OTHER,		"iLine100 HPNA"),
90 	BHND_CDESC(BCM, IPSEC,		OTHER,		"IPsec Accelerator"),
91 	BHND_CDESC(BCM, UTOPIA,		OTHER,		"UTOPIA ATM Core"),
92 	BHND_CDESC(BCM, PCMCIA,		PCCARD,		"PCMCIA Bridge"),
93 	BHND_CDESC(BCM, SOCRAM,		RAM,		"Internal Memory"),
94 	BHND_CDESC(BCM, MEMC,		MEMC,		"MEMC SDRAM Controller"),
95 	BHND_CDESC(BCM, OFDM,		OTHER,		"OFDM PHY"),
96 	BHND_CDESC(BCM, EXTIF,		OTHER,		"External Interface"),
97 	BHND_CDESC(BCM, D11,		WLAN,		"802.11 MAC/PHY/Radio"),
98 	BHND_CDESC(BCM, APHY,		WLAN_PHY,	"802.11a PHY"),
99 	BHND_CDESC(BCM, BPHY,		WLAN_PHY,	"802.11b PHY"),
100 	BHND_CDESC(BCM, GPHY,		WLAN_PHY,	"802.11g PHY"),
101 	BHND_CDESC(BCM, MIPS33,		CPU,		"BMIPS33 CPU"),
102 	BHND_CDESC(BCM, USB11H,		USB_HOST,	"USB 1.1 Host Controller"),
103 	BHND_CDESC(BCM, USB11D,		USB_DEV,	"USB 1.1 Device Controller"),
104 	BHND_CDESC(BCM, USB20H,		USB_HOST,	"USB 2.0 Host Controller"),
105 	BHND_CDESC(BCM, USB20D,		USB_DEV,	"USB 2.0 Device Controller"),
106 	BHND_CDESC(BCM, SDIOH,		OTHER,		"SDIO Host Controller"),
107 	BHND_CDESC(BCM, ROBO,		OTHER,		"RoboSwitch"),
108 	BHND_CDESC(BCM, ATA100,		OTHER,		"Parallel ATA Controller"),
109 	BHND_CDESC(BCM, SATAXOR,	OTHER,		"SATA DMA/XOR Controller"),
110 	BHND_CDESC(BCM, GIGETH,		ENET_MAC,	"Gigabit Ethernet MAC"),
111 	BHND_CDESC(BCM, PCIE,		PCIE,		"PCIe Bridge"),
112 	BHND_CDESC(BCM, NPHY,		WLAN_PHY,	"802.11n 2x2 PHY"),
113 	BHND_CDESC(BCM, SRAMC,		MEMC,		"SRAM Controller"),
114 	BHND_CDESC(BCM, MINIMAC,	OTHER,		"MINI MAC/PHY"),
115 	BHND_CDESC(BCM, ARM11,		CPU,		"ARM1176 CPU"),
116 	BHND_CDESC(BCM, ARM7S,		CPU,		"ARM7TDMI-S CPU"),
117 	BHND_CDESC(BCM, LPPHY,		WLAN_PHY,	"802.11a/b/g PHY"),
118 	BHND_CDESC(BCM, PMU,		PMU,		"PMU"),
119 	BHND_CDESC(BCM, SSNPHY,		WLAN_PHY,	"802.11n Single-Stream PHY"),
120 	BHND_CDESC(BCM, SDIOD,		OTHER,		"SDIO Device Core"),
121 	BHND_CDESC(BCM, ARMCM3,		CPU,		"ARM Cortex-M3 CPU"),
122 	BHND_CDESC(BCM, HTPHY,		WLAN_PHY,	"802.11n 4x4 PHY"),
123 	BHND_CDESC(MIPS,MIPS74K,	CPU,		"MIPS74k CPU"),
124 	BHND_CDESC(BCM, GMAC,		ENET_MAC,	"Gigabit MAC core"),
125 	BHND_CDESC(BCM, DMEMC,		MEMC,		"DDR1/DDR2 Memory Controller"),
126 	BHND_CDESC(BCM, PCIERC,		OTHER,		"PCIe Root Complex"),
127 	BHND_CDESC(BCM, OCP,		SOC_BRIDGE,	"OCP to OCP Bridge"),
128 	BHND_CDESC(BCM, SC,		OTHER,		"Shared Common Core"),
129 	BHND_CDESC(BCM, AHB,		SOC_BRIDGE,	"OCP to AHB Bridge"),
130 	BHND_CDESC(BCM, SPIH,		OTHER,		"SPI Host Controller"),
131 	BHND_CDESC(BCM, I2S,		OTHER,		"I2S Digital Audio Interface"),
132 	BHND_CDESC(BCM, DMEMS,		MEMC,		"SDR/DDR1 Memory Controller"),
133 	BHND_CDESC(BCM, UBUS_SHIM,	OTHER,		"BCM6362/UBUS WLAN SHIM"),
134 	BHND_CDESC(BCM, PCIE2,		PCIE,		"PCIe Bridge (Gen2)"),
135 
136 	BHND_CDESC(ARM, APB_BRIDGE,	SOC_BRIDGE,	"BP135 AMBA3 AXI to APB Bridge"),
137 	BHND_CDESC(ARM, PL301,		SOC_ROUTER,	"PL301 AMBA3 Interconnect"),
138 	BHND_CDESC(ARM, EROM,		EROM,		"PL366 Device Enumeration ROM"),
139 	BHND_CDESC(ARM, OOB_ROUTER,	OTHER,		"PL367 OOB Interrupt Router"),
140 	BHND_CDESC(ARM, AXI_UNMAPPED,	OTHER,		"Unmapped Address Ranges"),
141 
142 	BHND_CDESC(BCM, 4706_CC,	CC,		"ChipCommon I/O Controller"),
143 	BHND_CDESC(BCM, NS_PCIE2,	PCIE,		"PCIe Bridge (Gen2)"),
144 	BHND_CDESC(BCM, NS_DMA,		OTHER,		"DMA engine"),
145 	BHND_CDESC(BCM, NS_SDIO,	OTHER,		"SDIO 3.0 Host Controller"),
146 	BHND_CDESC(BCM, NS_USB20H,	USB_HOST,	"USB 2.0 Host Controller"),
147 	BHND_CDESC(BCM, NS_USB30H,	USB_HOST,	"USB 3.0 Host Controller"),
148 	BHND_CDESC(BCM, NS_A9JTAG,	OTHER,		"ARM Cortex A9 JTAG Interface"),
149 	BHND_CDESC(BCM, NS_DDR23_MEMC,	MEMC,		"Denali DDR2/DD3 Memory Controller"),
150 	BHND_CDESC(BCM, NS_ROM,		NVRAM,		"System ROM"),
151 	BHND_CDESC(BCM, NS_NAND,	NVRAM,		"NAND Flash Controller"),
152 	BHND_CDESC(BCM, NS_QSPI,	NVRAM,		"QSPI Flash Controller"),
153 	BHND_CDESC(BCM, NS_CC_B,	CC_B,		"ChipCommon B Auxiliary I/O Controller"),
154 	BHND_CDESC(BCM, 4706_SOCRAM,	RAM,		"Internal Memory"),
155 	BHND_CDESC(BCM, IHOST_ARMCA9,	CPU,		"ARM Cortex A9 CPU"),
156 	BHND_CDESC(BCM, 4706_GMAC_CMN,	ENET,		"Gigabit MAC (Common)"),
157 	BHND_CDESC(BCM, 4706_GMAC,	ENET_MAC,	"Gigabit MAC"),
158 	BHND_CDESC(BCM, AMEMC,		MEMC,		"Denali DDR1/DDR2 Memory Controller"),
159 #undef	BHND_CDESC
160 
161 	/* Derived from inspection of the BCM4331 cores that provide PrimeCell
162 	 * IDs. Due to lack of documentation, the surmised device name/purpose
163 	 * provided here may be incorrect. */
164 	{ BHND_MFGID_ARM,	BHND_PRIMEID_EROM,	BHND_DEVCLASS_OTHER,
165 	    "PL364 Device Enumeration ROM" },
166 	{ BHND_MFGID_ARM,	BHND_PRIMEID_SWRAP,	BHND_DEVCLASS_OTHER,
167 	    "PL368 Device Management Interface" },
168 	{ BHND_MFGID_ARM,	BHND_PRIMEID_MWRAP,	BHND_DEVCLASS_OTHER,
169 	    "PL369 Device Management Interface" },
170 	{ 0, 0, 0, NULL }
171 };
172 
173 static const struct bhnd_device_quirk bhnd_chipc_clkctl_quirks[];
174 static const struct bhnd_device_quirk bhnd_pcmcia_clkctl_quirks[];
175 
176 /**
177  * Device table entries for core-specific CLKCTL quirk lookup.
178  */
179 static const struct bhnd_device bhnd_clkctl_devices[] = {
180 	BHND_DEVICE(BCM, CC,		NULL,	bhnd_chipc_clkctl_quirks),
181 	BHND_DEVICE(BCM, PCMCIA,	NULL,	bhnd_pcmcia_clkctl_quirks),
182 	BHND_DEVICE_END,
183 };
184 
185 /** ChipCommon CLKCTL quirks */
186 static const struct bhnd_device_quirk bhnd_chipc_clkctl_quirks[] = {
187 	/* HTAVAIL/ALPAVAIL are bitswapped in chipc's CLKCTL */
188 	BHND_CHIP_QUIRK(4328,	HWREV_ANY,	BHND_CLKCTL_QUIRK_CCS0),
189 	BHND_CHIP_QUIRK(5354,	HWREV_ANY,	BHND_CLKCTL_QUIRK_CCS0),
190 	BHND_DEVICE_QUIRK_END
191 };
192 
193 /** PCMCIA CLKCTL quirks */
194 static const struct bhnd_device_quirk bhnd_pcmcia_clkctl_quirks[] = {
195 	/* HTAVAIL/ALPAVAIL are bitswapped in pcmcia's CLKCTL */
196 	BHND_CHIP_QUIRK(4328,	HWREV_ANY,	BHND_CLKCTL_QUIRK_CCS0),
197 	BHND_CHIP_QUIRK(5354,	HWREV_ANY,	BHND_CLKCTL_QUIRK_CCS0),
198 	BHND_DEVICE_QUIRK_END
199 };
200 
201 /**
202  * Return the name for a given JEP106 manufacturer ID.
203  *
204  * @param vendor A JEP106 Manufacturer ID, including the non-standard ARM 4-bit
205  * JEP106 continuation code.
206  */
207 const char *
208 bhnd_vendor_name(uint16_t vendor)
209 {
210 	switch (vendor) {
211 	case BHND_MFGID_ARM:
212 		return "ARM";
213 	case BHND_MFGID_BCM:
214 		return "Broadcom";
215 	case BHND_MFGID_MIPS:
216 		return "MIPS";
217 	default:
218 		return "unknown";
219 	}
220 }
221 
222 /**
223  * Return the name of a port type.
224  *
225  * @param port_type The port type to look up.
226  */
227 const char *
228 bhnd_port_type_name(bhnd_port_type port_type)
229 {
230 	switch (port_type) {
231 	case BHND_PORT_DEVICE:
232 		return ("device");
233 	case BHND_PORT_BRIDGE:
234 		return ("bridge");
235 	case BHND_PORT_AGENT:
236 		return ("agent");
237 	default:
238 		return "unknown";
239 	}
240 }
241 
242 /**
243  * Return the name of an NVRAM source.
244  *
245  * @param nvram_src The NVRAM source type to look up.
246  */
247 const char *
248 bhnd_nvram_src_name(bhnd_nvram_src nvram_src)
249 {
250 	switch (nvram_src) {
251 	case BHND_NVRAM_SRC_FLASH:
252 		return ("flash");
253 	case BHND_NVRAM_SRC_OTP:
254 		return ("OTP");
255 	case BHND_NVRAM_SRC_SPROM:
256 		return ("SPROM");
257 	case BHND_NVRAM_SRC_UNKNOWN:
258 		return ("none");
259 	default:
260 		return ("unknown");
261 	}
262 }
263 
264 static const struct bhnd_core_desc *
265 bhnd_find_core_desc(uint16_t vendor, uint16_t device)
266 {
267 	for (u_int i = 0; bhnd_core_descs[i].desc != NULL; i++) {
268 		if (bhnd_core_descs[i].vendor != vendor)
269 			continue;
270 
271 		if (bhnd_core_descs[i].device != device)
272 			continue;
273 
274 		return (&bhnd_core_descs[i]);
275 	}
276 
277 	return (NULL);
278 }
279 
280 /**
281  * Return a human-readable name for a BHND core.
282  *
283  * @param vendor The core designer's JEDEC-106 Manufacturer ID.
284  * @param device The core identifier.
285  */
286 const char *
287 bhnd_find_core_name(uint16_t vendor, uint16_t device)
288 {
289 	const struct bhnd_core_desc *desc;
290 
291 	if ((desc = bhnd_find_core_desc(vendor, device)) == NULL)
292 		return ("unknown");
293 
294 	return desc->desc;
295 }
296 
297 /**
298  * Return the device class for a BHND core.
299  *
300  * @param vendor The core designer's JEDEC-106 Manufacturer ID.
301  * @param device The core identifier.
302  */
303 bhnd_devclass_t
304 bhnd_find_core_class(uint16_t vendor, uint16_t device)
305 {
306 	const struct bhnd_core_desc *desc;
307 
308 	if ((desc = bhnd_find_core_desc(vendor, device)) == NULL)
309 		return (BHND_DEVCLASS_OTHER);
310 
311 	return desc->class;
312 }
313 
314 /**
315  * Return a human-readable name for a BHND core.
316  *
317  * @param ci The core's info record.
318  */
319 const char *
320 bhnd_core_name(const struct bhnd_core_info *ci)
321 {
322 	return bhnd_find_core_name(ci->vendor, ci->device);
323 }
324 
325 /**
326  * Return the device class for a BHND core.
327  *
328  * @param ci The core's info record.
329  */
330 bhnd_devclass_t
331 bhnd_core_class(const struct bhnd_core_info *ci)
332 {
333 	return bhnd_find_core_class(ci->vendor, ci->device);
334 }
335 
336 /**
337  * Write a human readable name representation of the given
338  * BHND_CHIPID_* constant to @p buffer.
339  *
340  * @param buffer Output buffer, or NULL to compute the required size.
341  * @param size Capacity of @p buffer, in bytes.
342  * @param chip_id Chip ID to be formatted.
343  *
344  * @return The required number of bytes on success, or a negative integer on
345  * failure. No more than @p size-1 characters be written, with the @p size'th
346  * set to '\0'.
347  *
348  * @sa BHND_CHIPID_MAX_NAMELEN
349  */
350 int
351 bhnd_format_chip_id(char *buffer, size_t size, uint16_t chip_id)
352 {
353 	/* All hex formatted IDs are within the range of 0x4000-0x9C3F (40000-1) */
354 	if (chip_id >= 0x4000 && chip_id <= 0x9C3F)
355 		return (snprintf(buffer, size, "BCM%hX", chip_id));
356 	else
357 		return (snprintf(buffer, size, "BCM%hu", chip_id));
358 }
359 
360 /**
361  * Return a core info record populated from a bhnd-attached @p dev.
362  *
363  * @param dev A bhnd device.
364  *
365  * @return A core info record for @p dev.
366  */
367 struct bhnd_core_info
368 bhnd_get_core_info(device_t dev) {
369 	return (struct bhnd_core_info) {
370 		.vendor		= bhnd_get_vendor(dev),
371 		.device		= bhnd_get_device(dev),
372 		.hwrev		= bhnd_get_hwrev(dev),
373 		.core_idx	= bhnd_get_core_index(dev),
374 		.unit		= bhnd_get_core_unit(dev)
375 	};
376 }
377 
378 /**
379  * Find a @p class child device with @p unit on @p bus.
380  *
381  * @param bus The bhnd-compatible bus to be searched.
382  * @param class The device class to match on.
383  * @param unit The core unit number; specify -1 to return the first match
384  * regardless of unit number.
385  *
386  * @retval device_t if a matching child device is found.
387  * @retval NULL if no matching child device is found.
388  */
389 device_t
390 bhnd_bus_find_child(device_t bus, bhnd_devclass_t class, int unit)
391 {
392 	struct bhnd_core_match md = {
393 		BHND_MATCH_CORE_CLASS(class),
394 		BHND_MATCH_CORE_UNIT(unit)
395 	};
396 
397 	if (unit == -1)
398 		md.m.match.core_unit = 0;
399 
400 	return bhnd_bus_match_child(bus, &md);
401 }
402 
403 /**
404  * Find the first child device on @p bus that matches @p desc.
405  *
406  * @param bus The bhnd-compatible bus to be searched.
407  * @param desc A match descriptor.
408  *
409  * @retval device_t if a matching child device is found.
410  * @retval NULL if no matching child device is found.
411  */
412 device_t
413 bhnd_bus_match_child(device_t bus, const struct bhnd_core_match *desc)
414 {
415 	device_t	*devlistp;
416 	device_t	 match;
417 	int		 devcnt;
418 	int		 error;
419 
420 	error = device_get_children(bus, &devlistp, &devcnt);
421 	if (error != 0)
422 		return (NULL);
423 
424 	match = NULL;
425 	for (int i = 0; i < devcnt; i++) {
426 		struct bhnd_core_info ci = bhnd_get_core_info(devlistp[i]);
427 
428 		if (bhnd_core_matches(&ci, desc)) {
429 			match = devlistp[i];
430 			goto done;
431 		}
432 	}
433 
434 done:
435 	free(devlistp, M_TEMP);
436 	return match;
437 }
438 
439 /**
440  * Retrieve an ordered list of all device instances currently connected to
441  * @p bus, returning a pointer to the array in @p devlistp and the count
442  * in @p ndevs.
443  *
444  * The memory allocated for the table must be freed via
445  * bhnd_bus_free_children().
446  *
447  * @param	bus		The bhnd-compatible bus to be queried.
448  * @param[out]	devlist		The array of devices.
449  * @param[out]	devcount	The number of devices in @p devlistp
450  * @param	order		The order in which devices will be returned
451  *				in @p devlist.
452  *
453  * @retval 0		success
454  * @retval non-zero	if an error occurs, a regular unix error code will
455  *			be returned.
456  */
457 int
458 bhnd_bus_get_children(device_t bus, device_t **devlist, int *devcount,
459     bhnd_device_order order)
460 {
461 	int error;
462 
463 	/* Fetch device array */
464 	if ((error = device_get_children(bus, devlist, devcount)))
465 		return (error);
466 
467 	/* Perform requested sorting */
468 	if ((error = bhnd_sort_devices(*devlist, *devcount, order))) {
469 		bhnd_bus_free_children(*devlist);
470 		return (error);
471 	}
472 
473 	return (0);
474 }
475 
476 /**
477  * Free any memory allocated in a previous call to bhnd_bus_get_children().
478  *
479  * @param devlist The device array returned by bhnd_bus_get_children().
480  */
481 void
482 bhnd_bus_free_children(device_t *devlist)
483 {
484 	free(devlist, M_TEMP);
485 }
486 
487 /**
488  * Perform in-place sorting of an array of bhnd device instances.
489  *
490  * @param devlist	An array of bhnd devices.
491  * @param devcount	The number of devices in @p devs.
492  * @param order		The sort order to be used.
493  *
494  * @retval 0		success
495  * @retval EINVAL	if the sort order is unknown.
496  */
497 int
498 bhnd_sort_devices(device_t *devlist, size_t devcount, bhnd_device_order order)
499 {
500 	int (*compare)(const void *, const void *);
501 
502 	switch (order) {
503 	case BHND_DEVICE_ORDER_ATTACH:
504 		compare = compare_ascending_probe_order;
505 		break;
506 	case BHND_DEVICE_ORDER_DETACH:
507 		compare = compare_descending_probe_order;
508 		break;
509 	default:
510 		printf("unknown sort order: %d\n", order);
511 		return (EINVAL);
512 	}
513 
514 	qsort(devlist, devcount, sizeof(*devlist), compare);
515 	return (0);
516 }
517 
518 /*
519  * Ascending comparison of bhnd device's probe order.
520  */
521 static int
522 compare_ascending_probe_order(const void *lhs, const void *rhs)
523 {
524 	device_t	ldev, rdev;
525 	int		lorder, rorder;
526 
527 	ldev = (*(const device_t *) lhs);
528 	rdev = (*(const device_t *) rhs);
529 
530 	lorder = BHND_BUS_GET_PROBE_ORDER(device_get_parent(ldev), ldev);
531 	rorder = BHND_BUS_GET_PROBE_ORDER(device_get_parent(rdev), rdev);
532 
533 	if (lorder < rorder) {
534 		return (-1);
535 	} else if (lorder > rorder) {
536 		return (1);
537 	} else {
538 		return (0);
539 	}
540 }
541 
542 /*
543  * Descending comparison of bhnd device's probe order.
544  */
545 static int
546 compare_descending_probe_order(const void *lhs, const void *rhs)
547 {
548 	return (compare_ascending_probe_order(rhs, lhs));
549 }
550 
551 /**
552  * Call device_probe_and_attach() for each of the bhnd bus device's
553  * children, in bhnd attach order.
554  *
555  * @param bus The bhnd-compatible bus for which all children should be probed
556  * and attached.
557  */
558 int
559 bhnd_bus_probe_children(device_t bus)
560 {
561 	device_t	*devs;
562 	int		 ndevs;
563 	int		 error;
564 
565 	/* Fetch children in attach order */
566 	error = bhnd_bus_get_children(bus, &devs, &ndevs,
567 	    BHND_DEVICE_ORDER_ATTACH);
568 	if (error)
569 		return (error);
570 
571 	/* Probe and attach all children */
572 	for (int i = 0; i < ndevs; i++) {
573 		device_t child = devs[i];
574 		device_probe_and_attach(child);
575 	}
576 
577 	bhnd_bus_free_children(devs);
578 
579 	return (0);
580 }
581 
582 /**
583  * Walk up the bhnd device hierarchy to locate the root device
584  * to which the bhndb bridge is attached.
585  *
586  * This can be used from within bhnd host bridge drivers to locate the
587  * actual upstream host device.
588  *
589  * @param dev A bhnd device.
590  * @param bus_class The expected bus (e.g. "pci") to which the bridge root
591  * should be attached.
592  *
593  * @retval device_t if a matching parent device is found.
594  * @retval NULL if @p dev is not attached via a bhndb bus.
595  * @retval NULL if no parent device is attached via @p bus_class.
596  */
597 device_t
598 bhnd_find_bridge_root(device_t dev, devclass_t bus_class)
599 {
600 	devclass_t	bhndb_class;
601 	device_t	parent;
602 
603 	KASSERT(device_get_devclass(device_get_parent(dev)) ==
604 	    devclass_find("bhnd"),
605 	   ("%s not a bhnd device", device_get_nameunit(dev)));
606 
607 	bhndb_class = devclass_find("bhndb");
608 
609 	/* Walk the device tree until we hit a bridge */
610 	parent = dev;
611 	while ((parent = device_get_parent(parent)) != NULL) {
612 		if (device_get_devclass(parent) == bhndb_class)
613 			break;
614 	}
615 
616 	/* No bridge? */
617 	if (parent == NULL)
618 		return (NULL);
619 
620 	/* Search for a parent attached to the expected bus class */
621 	while ((parent = device_get_parent(parent)) != NULL) {
622 		device_t bus;
623 
624 		bus = device_get_parent(parent);
625 		if (bus != NULL && device_get_devclass(bus) == bus_class)
626 			return (parent);
627 	}
628 
629 	/* Not found */
630 	return (NULL);
631 }
632 
633 /**
634  * Find the first core in @p cores that matches @p desc.
635  *
636  * @param cores The table to search.
637  * @param num_cores The length of @p cores.
638  * @param desc A match descriptor.
639  *
640  * @retval bhnd_core_info if a matching core is found.
641  * @retval NULL if no matching core is found.
642  */
643 const struct bhnd_core_info *
644 bhnd_match_core(const struct bhnd_core_info *cores, u_int num_cores,
645     const struct bhnd_core_match *desc)
646 {
647 	for (u_int i = 0; i < num_cores; i++) {
648 		if (bhnd_core_matches(&cores[i], desc))
649 			return &cores[i];
650 	}
651 
652 	return (NULL);
653 }
654 
655 /**
656  * Find the first core in @p cores with the given @p class.
657  *
658  * @param cores The table to search.
659  * @param num_cores The length of @p cores.
660  * @param class The device class to match on.
661  *
662  * @retval non-NULL if a matching core is found.
663  * @retval NULL if no matching core is found.
664  */
665 const struct bhnd_core_info *
666 bhnd_find_core(const struct bhnd_core_info *cores, u_int num_cores,
667     bhnd_devclass_t class)
668 {
669 	struct bhnd_core_match md = {
670 		BHND_MATCH_CORE_CLASS(class)
671 	};
672 
673 	return bhnd_match_core(cores, num_cores, &md);
674 }
675 
676 /**
677  * Create an equality match descriptor for @p core.
678  *
679  * @param core The core info to be matched on.
680  *
681  * @return an equality match descriptor for @p core.
682  */
683 struct bhnd_core_match
684 bhnd_core_get_match_desc(const struct bhnd_core_info *core)
685 {
686 	return ((struct bhnd_core_match) {
687 		BHND_MATCH_CORE_VENDOR(core->vendor),
688 		BHND_MATCH_CORE_ID(core->device),
689 		BHND_MATCH_CORE_REV(HWREV_EQ(core->hwrev)),
690 		BHND_MATCH_CORE_CLASS(bhnd_core_class(core)),
691 		BHND_MATCH_CORE_IDX(core->core_idx),
692 		BHND_MATCH_CORE_UNIT(core->unit)
693 	});
694 }
695 
696 /**
697  * Return true if the @p lhs is equal to @p rhs.
698  *
699  * @param lhs The first bhnd core descriptor to compare.
700  * @param rhs The second bhnd core descriptor to compare.
701  *
702  * @retval true if @p lhs is equal to @p rhs
703  * @retval false if @p lhs is not equal to @p rhs
704  */
705 bool
706 bhnd_cores_equal(const struct bhnd_core_info *lhs,
707     const struct bhnd_core_info *rhs)
708 {
709 	struct bhnd_core_match md;
710 
711 	/* Use an equality match descriptor to perform the comparison */
712 	md = bhnd_core_get_match_desc(rhs);
713 	return (bhnd_core_matches(lhs, &md));
714 }
715 
716 /**
717  * Return true if the @p core matches @p desc.
718  *
719  * @param core A bhnd core descriptor.
720  * @param desc A match descriptor to compare against @p core.
721  *
722  * @retval true if @p core matches @p match.
723  * @retval false if @p core does not match @p match.
724  */
725 bool
726 bhnd_core_matches(const struct bhnd_core_info *core,
727     const struct bhnd_core_match *desc)
728 {
729 	if (desc->m.match.core_vendor && desc->core_vendor != core->vendor)
730 		return (false);
731 
732 	if (desc->m.match.core_id && desc->core_id != core->device)
733 		return (false);
734 
735 	if (desc->m.match.core_unit && desc->core_unit != core->unit)
736 		return (false);
737 
738 	if (desc->m.match.core_rev &&
739 	    !bhnd_hwrev_matches(core->hwrev, &desc->core_rev))
740 		return (false);
741 
742 	if (desc->m.match.core_idx && desc->core_idx != core->core_idx)
743 		return (false);
744 
745 	if (desc->m.match.core_class &&
746 	    desc->core_class != bhnd_core_class(core))
747 		return (false);
748 
749 	return true;
750 }
751 
752 /**
753  * Return true if the @p chip matches @p desc.
754  *
755  * @param chip A bhnd chip identifier.
756  * @param desc A match descriptor to compare against @p chip.
757  *
758  * @retval true if @p chip matches @p match.
759  * @retval false if @p chip does not match @p match.
760  */
761 bool
762 bhnd_chip_matches(const struct bhnd_chipid *chip,
763     const struct bhnd_chip_match *desc)
764 {
765 	if (desc->m.match.chip_id && chip->chip_id != desc->chip_id)
766 		return (false);
767 
768 	if (desc->m.match.chip_pkg && chip->chip_pkg != desc->chip_pkg)
769 		return (false);
770 
771 	if (desc->m.match.chip_rev &&
772 	    !bhnd_hwrev_matches(chip->chip_rev, &desc->chip_rev))
773 		return (false);
774 
775 	if (desc->m.match.chip_type && chip->chip_type != desc->chip_type)
776 		return (false);
777 
778 	return (true);
779 }
780 
781 /**
782  * Return true if the @p board matches @p desc.
783  *
784  * @param board The bhnd board info.
785  * @param desc A match descriptor to compare against @p board.
786  *
787  * @retval true if @p chip matches @p match.
788  * @retval false if @p chip does not match @p match.
789  */
790 bool
791 bhnd_board_matches(const struct bhnd_board_info *board,
792     const struct bhnd_board_match *desc)
793 {
794 	if (desc->m.match.board_srom_rev &&
795 	    !bhnd_hwrev_matches(board->board_srom_rev, &desc->board_srom_rev))
796 		return (false);
797 
798 	if (desc->m.match.board_vendor &&
799 	    board->board_vendor != desc->board_vendor)
800 		return (false);
801 
802 	if (desc->m.match.board_type && board->board_type != desc->board_type)
803 		return (false);
804 
805 	if (desc->m.match.board_devid &&
806 	    board->board_devid != desc->board_devid)
807 		return (false);
808 
809 	if (desc->m.match.board_rev &&
810 	    !bhnd_hwrev_matches(board->board_rev, &desc->board_rev))
811 		return (false);
812 
813 	return (true);
814 }
815 
816 /**
817  * Return true if the @p hwrev matches @p desc.
818  *
819  * @param hwrev A bhnd hardware revision.
820  * @param desc A match descriptor to compare against @p core.
821  *
822  * @retval true if @p hwrev matches @p match.
823  * @retval false if @p hwrev does not match @p match.
824  */
825 bool
826 bhnd_hwrev_matches(uint16_t hwrev, const struct bhnd_hwrev_match *desc)
827 {
828 	if (desc->start != BHND_HWREV_INVALID &&
829 	    desc->start > hwrev)
830 		return false;
831 
832 	if (desc->end != BHND_HWREV_INVALID &&
833 	    desc->end < hwrev)
834 		return false;
835 
836 	return true;
837 }
838 
839 /**
840  * Return true if the @p dev matches @p desc.
841  *
842  * @param dev A bhnd device.
843  * @param desc A match descriptor to compare against @p dev.
844  *
845  * @retval true if @p dev matches @p match.
846  * @retval false if @p dev does not match @p match.
847  */
848 bool
849 bhnd_device_matches(device_t dev, const struct bhnd_device_match *desc)
850 {
851 	struct bhnd_core_info		 core;
852 	const struct bhnd_chipid	*chip;
853 	struct bhnd_board_info		 board;
854 	device_t			 parent;
855 	int				 error;
856 
857 	/* Construct individual match descriptors */
858 	struct bhnd_core_match	m_core	= { _BHND_CORE_MATCH_COPY(desc) };
859 	struct bhnd_chip_match	m_chip	= { _BHND_CHIP_MATCH_COPY(desc) };
860 	struct bhnd_board_match	m_board	= { _BHND_BOARD_MATCH_COPY(desc) };
861 
862 	/* Fetch and match core info */
863 	if (m_core.m.match_flags) {
864 		/* Only applicable to bhnd-attached cores */
865 		parent = device_get_parent(dev);
866 		if (device_get_devclass(parent) != devclass_find("bhnd")) {
867 			device_printf(dev, "attempting to match core "
868 			    "attributes against non-core device\n");
869 			return (false);
870 		}
871 
872 		core = bhnd_get_core_info(dev);
873 		if (!bhnd_core_matches(&core, &m_core))
874 			return (false);
875 	}
876 
877 	/* Fetch and match chip info */
878 	if (m_chip.m.match_flags) {
879 		chip = bhnd_get_chipid(dev);
880 
881 		if (!bhnd_chip_matches(chip, &m_chip))
882 			return (false);
883 	}
884 
885 	/* Fetch and match board info.
886 	 *
887 	 * This is not available until  after NVRAM is up; earlier device
888 	 * matches should not include board requirements */
889 	if (m_board.m.match_flags) {
890 		if ((error = bhnd_read_board_info(dev, &board))) {
891 			device_printf(dev, "failed to read required board info "
892 			    "during device matching: %d\n", error);
893 			return (false);
894 		}
895 
896 		if (!bhnd_board_matches(&board, &m_board))
897 			return (false);
898 	}
899 
900 	/* All matched */
901 	return (true);
902 }
903 
904 /**
905  * Search @p table for an entry matching @p dev.
906  *
907  * @param dev A bhnd device to match against @p table.
908  * @param table The device table to search.
909  * @param entry_size The @p table entry size, in bytes.
910  *
911  * @retval non-NULL the first matching device, if any.
912  * @retval NULL if no matching device is found in @p table.
913  */
914 const struct bhnd_device *
915 bhnd_device_lookup(device_t dev, const struct bhnd_device *table,
916     size_t entry_size)
917 {
918 	const struct bhnd_device	*entry;
919 	device_t			 hostb, parent;
920 	bhnd_attach_type		 attach_type;
921 	uint32_t			 dflags;
922 
923 	parent = device_get_parent(dev);
924 	hostb = bhnd_bus_find_hostb_device(parent);
925 	attach_type = bhnd_get_attach_type(dev);
926 
927 	for (entry = table; !BHND_DEVICE_IS_END(entry); entry =
928 	    (const struct bhnd_device *) ((const char *) entry + entry_size))
929 	{
930 		/* match core info */
931 		if (!bhnd_device_matches(dev, &entry->core))
932 			continue;
933 
934 		/* match device flags */
935 		dflags = entry->device_flags;
936 
937 		/* hostb implies BHND_ATTACH_ADAPTER requirement */
938 		if (dflags & BHND_DF_HOSTB)
939 			dflags |= BHND_DF_ADAPTER;
940 
941 		if (dflags & BHND_DF_ADAPTER)
942 			if (attach_type != BHND_ATTACH_ADAPTER)
943 				continue;
944 
945 		if (dflags & BHND_DF_HOSTB)
946 			if (dev != hostb)
947 				continue;
948 
949 		if (dflags & BHND_DF_SOC)
950 			if (attach_type != BHND_ATTACH_NATIVE)
951 				continue;
952 
953 		/* device found */
954 		return (entry);
955 	}
956 
957 	/* not found */
958 	return (NULL);
959 }
960 
961 /**
962  * Scan the device @p table for all quirk flags applicable to @p dev.
963  *
964  * @param dev A bhnd device to match against @p table.
965  * @param table The device table to search.
966  * @param entry_size The @p table entry size, in bytes.
967  *
968  * @return all matching quirk flags.
969  */
970 uint32_t
971 bhnd_device_quirks(device_t dev, const struct bhnd_device *table,
972     size_t entry_size)
973 {
974 	const struct bhnd_device	*dent;
975 	const struct bhnd_device_quirk	*qent, *qtable;
976 	uint32_t			 quirks;
977 
978 	/* Locate the device entry */
979 	if ((dent = bhnd_device_lookup(dev, table, entry_size)) == NULL)
980 		return (0);
981 
982 	/* Quirks table is optional */
983 	qtable = dent->quirks_table;
984 	if (qtable == NULL)
985 		return (0);
986 
987 	/* Collect matching device quirk entries */
988 	quirks = 0;
989 	for (qent = qtable; !BHND_DEVICE_QUIRK_IS_END(qent); qent++) {
990 		if (bhnd_device_matches(dev, &qent->desc))
991 			quirks |= qent->quirks;
992 	}
993 
994 	return (quirks);
995 }
996 
997 /**
998  * Allocate bhnd(4) resources defined in @p rs from a parent bus.
999  *
1000  * @param dev The device requesting ownership of the resources.
1001  * @param rs A standard bus resource specification. This will be updated
1002  * with the allocated resource's RIDs.
1003  * @param res On success, the allocated bhnd resources.
1004  *
1005  * @retval 0 success
1006  * @retval non-zero if allocation of any non-RF_OPTIONAL resource fails,
1007  * 		    all allocated resources will be released and a regular
1008  * 		    unix error code will be returned.
1009  */
1010 int
1011 bhnd_alloc_resources(device_t dev, struct resource_spec *rs,
1012     struct bhnd_resource **res)
1013 {
1014 	/* Initialize output array */
1015 	for (u_int i = 0; rs[i].type != -1; i++)
1016 		res[i] = NULL;
1017 
1018 	for (u_int i = 0; rs[i].type != -1; i++) {
1019 		res[i] = bhnd_alloc_resource_any(dev, rs[i].type, &rs[i].rid,
1020 		    rs[i].flags);
1021 
1022 		/* Clean up all allocations on failure */
1023 		if (res[i] == NULL && !(rs[i].flags & RF_OPTIONAL)) {
1024 			bhnd_release_resources(dev, rs, res);
1025 			return (ENXIO);
1026 		}
1027 	}
1028 
1029 	return (0);
1030 }
1031 
1032 /**
1033  * Release bhnd(4) resources defined in @p rs from a parent bus.
1034  *
1035  * @param dev The device that owns the resources.
1036  * @param rs A standard bus resource specification previously initialized
1037  * by @p bhnd_alloc_resources.
1038  * @param res The bhnd resources to be released.
1039  */
1040 void
1041 bhnd_release_resources(device_t dev, const struct resource_spec *rs,
1042     struct bhnd_resource **res)
1043 {
1044 	for (u_int i = 0; rs[i].type != -1; i++) {
1045 		if (res[i] == NULL)
1046 			continue;
1047 
1048 		bhnd_release_resource(dev, rs[i].type, rs[i].rid, res[i]);
1049 		res[i] = NULL;
1050 	}
1051 }
1052 
1053 /**
1054  * Allocate and return a new per-core PMU clock control/status (clkctl)
1055  * instance for @p dev.
1056  *
1057  * @param dev		The bhnd(4) core device mapped by @p r.
1058  * @param pmu_dev	The bhnd(4) PMU device, implmenting the bhnd_pmu_if
1059  *			interface. The caller is responsible for ensuring that
1060  *			this reference remains valid for the lifetime of the
1061  *			returned clkctl instance.
1062  * @param r		A resource mapping the core's clock control register
1063  * 			(see BHND_CLK_CTL_ST). The caller is responsible for
1064  *			ensuring that this resource remains valid for the
1065  *			lifetime of the returned clkctl instance.
1066  * @param offset	The offset to the clock control register within @p r.
1067  * @param max_latency	The PMU's maximum state transition latency in
1068  *			microseconds; this upper bound will be used to busy-wait
1069  *			on PMU state transitions.
1070  *
1071  * @retval non-NULL	success
1072  * @retval NULL		if allocation fails.
1073  *
1074  */
1075 struct bhnd_core_clkctl *
1076 bhnd_alloc_core_clkctl(device_t dev, device_t pmu_dev, struct bhnd_resource *r,
1077     bus_size_t offset, u_int max_latency)
1078 {
1079 	struct bhnd_core_clkctl	*clkctl;
1080 
1081 	clkctl = malloc(sizeof(*clkctl), M_BHND, M_ZERO | M_NOWAIT);
1082 	if (clkctl == NULL)
1083 		return (NULL);
1084 
1085 	clkctl->cc_dev = dev;
1086 	clkctl->cc_pmu_dev = pmu_dev;
1087 	clkctl->cc_res = r;
1088 	clkctl->cc_res_offset = offset;
1089 	clkctl->cc_max_latency = max_latency;
1090 	clkctl->cc_quirks = bhnd_device_quirks(dev, bhnd_clkctl_devices,
1091 	    sizeof(bhnd_clkctl_devices[0]));
1092 
1093 	BHND_CLKCTL_LOCK_INIT(clkctl);
1094 
1095 	return (clkctl);
1096 }
1097 
1098 /**
1099  * Free a clkctl instance previously allocated via bhnd_alloc_core_clkctl().
1100  *
1101  * @param clkctl	The clkctl instance to be freed.
1102  */
1103 void
1104 bhnd_free_core_clkctl(struct bhnd_core_clkctl *clkctl)
1105 {
1106 	BHND_CLKCTL_LOCK_DESTROY(clkctl);
1107 
1108 	free(clkctl, M_BHND);
1109 }
1110 
1111 /**
1112  * Wait for the per-core clock status to be equal to @p value after
1113  * applying @p mask, timing out after the maximum transition latency is reached.
1114  *
1115  * @param clkctl	Per-core clkctl state to be queryied.
1116  * @param value		Value to wait for.
1117  * @param mask		Mask to apply prior to value comparison.
1118  *
1119  * @retval 0		success
1120  * @retval ETIMEDOUT	if the PMU's maximum transition delay is reached before
1121  *			the clock status matches @p value and @p mask.
1122  */
1123 int
1124 bhnd_core_clkctl_wait(struct bhnd_core_clkctl *clkctl, uint32_t value,
1125     uint32_t mask)
1126 {
1127 	uint32_t	clkst;
1128 
1129 	BHND_CLKCTL_LOCK_ASSERT(clkctl, MA_OWNED);
1130 
1131 	/* Bitswapped HTAVAIL/ALPAVAIL work-around */
1132 	if (clkctl->cc_quirks & BHND_CLKCTL_QUIRK_CCS0) {
1133 		uint32_t fmask, fval;
1134 
1135 		fmask = mask & ~(BHND_CCS_HTAVAIL | BHND_CCS_ALPAVAIL);
1136 		fval = value & ~(BHND_CCS_HTAVAIL | BHND_CCS_ALPAVAIL);
1137 
1138 		if (mask & BHND_CCS_HTAVAIL)
1139 			fmask |= BHND_CCS0_HTAVAIL;
1140 		if (value & BHND_CCS_HTAVAIL)
1141 			fval |= BHND_CCS0_HTAVAIL;
1142 
1143 		if (mask & BHND_CCS_ALPAVAIL)
1144 			fmask |= BHND_CCS0_ALPAVAIL;
1145 		if (value & BHND_CCS_ALPAVAIL)
1146 			fval |= BHND_CCS0_ALPAVAIL;
1147 
1148 		mask = fmask;
1149 		value = fval;
1150 	}
1151 
1152 	for (u_int i = 0; i < clkctl->cc_max_latency; i += 10) {
1153 		clkst = bhnd_bus_read_4(clkctl->cc_res, clkctl->cc_res_offset);
1154 		if ((clkst & mask) == (value & mask))
1155 			return (0);
1156 
1157 		DELAY(10);
1158 	}
1159 
1160 	device_printf(clkctl->cc_dev, "clkst wait timeout (value=%#x, "
1161 	    "mask=%#x)\n", value, mask);
1162 
1163 	return (ETIMEDOUT);
1164 }
1165 
1166 /**
1167  * Read an NVRAM variable's NUL-terminated string value.
1168  *
1169  * @param 	dev	A bhnd bus child device.
1170  * @param	name	The NVRAM variable name.
1171  * @param[out]	buf	A buffer large enough to hold @p len bytes. On
1172  *			success, the NUL-terminated string value will be
1173  *			written to this buffer. This argment may be NULL if
1174  *			the value is not desired.
1175  * @param	len	The maximum capacity of @p buf.
1176  * @param[out]	rlen	On success, will be set to the actual size of
1177  *			the requested value (including NUL termination). This
1178  *			argment may be NULL if the size is not desired.
1179  *
1180  * @retval 0		success
1181  * @retval ENOENT	The requested variable was not found.
1182  * @retval ENODEV	No valid NVRAM source could be found.
1183  * @retval ENOMEM	If @p buf is non-NULL and a buffer of @p len is too
1184  *			small to hold the requested value.
1185  * @retval EFTYPE	If the variable data cannot be coerced to a valid
1186  *			string representation.
1187  * @retval ERANGE	If value coercion would overflow @p type.
1188  * @retval non-zero	If reading @p name otherwise fails, a regular unix
1189  *			error code will be returned.
1190  */
1191 int
1192 bhnd_nvram_getvar_str(device_t dev, const char *name, char *buf, size_t len,
1193     size_t *rlen)
1194 {
1195 	size_t	larg;
1196 	int	error;
1197 
1198 	larg = len;
1199 	error = bhnd_nvram_getvar(dev, name, buf, &larg,
1200 	    BHND_NVRAM_TYPE_STRING);
1201 	if (rlen != NULL)
1202 		*rlen = larg;
1203 
1204 	return (error);
1205 }
1206 
1207 /**
1208  * Read an NVRAM variable's unsigned integer value.
1209  *
1210  * @param 		dev	A bhnd bus child device.
1211  * @param		name	The NVRAM variable name.
1212  * @param[out]		value	On success, the requested value will be written
1213  *				to this pointer.
1214  * @param		width	The output integer type width (1, 2, or
1215  *				4 bytes).
1216  *
1217  * @retval 0		success
1218  * @retval ENOENT	The requested variable was not found.
1219  * @retval ENODEV	No valid NVRAM source could be found.
1220  * @retval EFTYPE	If the variable data cannot be coerced to a
1221  *			a valid unsigned integer representation.
1222  * @retval ERANGE	If value coercion would overflow (or underflow) an
1223  *			unsigned representation of the given @p width.
1224  * @retval non-zero	If reading @p name otherwise fails, a regular unix
1225  *			error code will be returned.
1226  */
1227 int
1228 bhnd_nvram_getvar_uint(device_t dev, const char *name, void *value, int width)
1229 {
1230 	bhnd_nvram_type	type;
1231 	size_t		len;
1232 
1233 	switch (width) {
1234 	case 1:
1235 		type = BHND_NVRAM_TYPE_UINT8;
1236 		break;
1237 	case 2:
1238 		type = BHND_NVRAM_TYPE_UINT16;
1239 		break;
1240 	case 4:
1241 		type = BHND_NVRAM_TYPE_UINT32;
1242 		break;
1243 	default:
1244 		device_printf(dev, "unsupported NVRAM integer width: %d\n",
1245 		    width);
1246 		return (EINVAL);
1247 	}
1248 
1249 	len = width;
1250 	return (bhnd_nvram_getvar(dev, name, value, &len, type));
1251 }
1252 
1253 /**
1254  * Read an NVRAM variable's unsigned 8-bit integer value.
1255  *
1256  * @param 		dev	A bhnd bus child device.
1257  * @param		name	The NVRAM variable name.
1258  * @param[out]		value	On success, the requested value will be written
1259  *				to this pointer.
1260  *
1261  * @retval 0		success
1262  * @retval ENOENT	The requested variable was not found.
1263  * @retval ENODEV	No valid NVRAM source could be found.
1264  * @retval EFTYPE	If the variable data cannot be coerced to a
1265  *			a valid unsigned integer representation.
1266  * @retval ERANGE	If value coercion would overflow (or underflow) uint8_t.
1267  * @retval non-zero	If reading @p name otherwise fails, a regular unix
1268  *			error code will be returned.
1269  */
1270 int
1271 bhnd_nvram_getvar_uint8(device_t dev, const char *name, uint8_t *value)
1272 {
1273 	return (bhnd_nvram_getvar_uint(dev, name, value, sizeof(*value)));
1274 }
1275 
1276 /**
1277  * Read an NVRAM variable's unsigned 16-bit integer value.
1278  *
1279  * @param 		dev	A bhnd bus child device.
1280  * @param		name	The NVRAM variable name.
1281  * @param[out]		value	On success, the requested value will be written
1282  *				to this pointer.
1283  *
1284  * @retval 0		success
1285  * @retval ENOENT	The requested variable was not found.
1286  * @retval ENODEV	No valid NVRAM source could be found.
1287  * @retval EFTYPE	If the variable data cannot be coerced to a
1288  *			a valid unsigned integer representation.
1289  * @retval ERANGE	If value coercion would overflow (or underflow)
1290  *			uint16_t.
1291  * @retval non-zero	If reading @p name otherwise fails, a regular unix
1292  *			error code will be returned.
1293  */
1294 int
1295 bhnd_nvram_getvar_uint16(device_t dev, const char *name, uint16_t *value)
1296 {
1297 	return (bhnd_nvram_getvar_uint(dev, name, value, sizeof(*value)));
1298 }
1299 
1300 /**
1301  * Read an NVRAM variable's unsigned 32-bit integer value.
1302  *
1303  * @param 		dev	A bhnd bus child device.
1304  * @param		name	The NVRAM variable name.
1305  * @param[out]		value	On success, the requested value will be written
1306  *				to this pointer.
1307  *
1308  * @retval 0		success
1309  * @retval ENOENT	The requested variable was not found.
1310  * @retval ENODEV	No valid NVRAM source could be found.
1311  * @retval EFTYPE	If the variable data cannot be coerced to a
1312  *			a valid unsigned integer representation.
1313  * @retval ERANGE	If value coercion would overflow (or underflow)
1314  *			uint32_t.
1315  * @retval non-zero	If reading @p name otherwise fails, a regular unix
1316  *			error code will be returned.
1317  */
1318 int
1319 bhnd_nvram_getvar_uint32(device_t dev, const char *name, uint32_t *value)
1320 {
1321 	return (bhnd_nvram_getvar_uint(dev, name, value, sizeof(*value)));
1322 }
1323 
1324 /**
1325  * Read an NVRAM variable's signed integer value.
1326  *
1327  * @param 		dev	A bhnd bus child device.
1328  * @param		name	The NVRAM variable name.
1329  * @param[out]		value	On success, the requested value will be written
1330  *				to this pointer.
1331  * @param		width	The output integer type width (1, 2, or
1332  *				4 bytes).
1333  *
1334  * @retval 0		success
1335  * @retval ENOENT	The requested variable was not found.
1336  * @retval ENODEV	No valid NVRAM source could be found.
1337  * @retval EFTYPE	If the variable data cannot be coerced to a
1338  *			a valid integer representation.
1339  * @retval ERANGE	If value coercion would overflow (or underflow) an
1340  *			signed representation of the given @p width.
1341  * @retval non-zero	If reading @p name otherwise fails, a regular unix
1342  *			error code will be returned.
1343  */
1344 int
1345 bhnd_nvram_getvar_int(device_t dev, const char *name, void *value, int width)
1346 {
1347 	bhnd_nvram_type	type;
1348 	size_t		len;
1349 
1350 	switch (width) {
1351 	case 1:
1352 		type = BHND_NVRAM_TYPE_INT8;
1353 		break;
1354 	case 2:
1355 		type = BHND_NVRAM_TYPE_INT16;
1356 		break;
1357 	case 4:
1358 		type = BHND_NVRAM_TYPE_INT32;
1359 		break;
1360 	default:
1361 		device_printf(dev, "unsupported NVRAM integer width: %d\n",
1362 		    width);
1363 		return (EINVAL);
1364 	}
1365 
1366 	len = width;
1367 	return (bhnd_nvram_getvar(dev, name, value, &len, type));
1368 }
1369 
1370 /**
1371  * Read an NVRAM variable's signed 8-bit integer value.
1372  *
1373  * @param 		dev	A bhnd bus child device.
1374  * @param		name	The NVRAM variable name.
1375  * @param[out]		value	On success, the requested value will be written
1376  *				to this pointer.
1377  *
1378  * @retval 0		success
1379  * @retval ENOENT	The requested variable was not found.
1380  * @retval ENODEV	No valid NVRAM source could be found.
1381  * @retval EFTYPE	If the variable data cannot be coerced to a
1382  *			a valid integer representation.
1383  * @retval ERANGE	If value coercion would overflow (or underflow) int8_t.
1384  * @retval non-zero	If reading @p name otherwise fails, a regular unix
1385  *			error code will be returned.
1386  */
1387 int
1388 bhnd_nvram_getvar_int8(device_t dev, const char *name, int8_t *value)
1389 {
1390 	return (bhnd_nvram_getvar_int(dev, name, value, sizeof(*value)));
1391 }
1392 
1393 /**
1394  * Read an NVRAM variable's signed 16-bit integer value.
1395  *
1396  * @param 		dev	A bhnd bus child device.
1397  * @param		name	The NVRAM variable name.
1398  * @param[out]		value	On success, the requested value will be written
1399  *				to this pointer.
1400  *
1401  * @retval 0		success
1402  * @retval ENOENT	The requested variable was not found.
1403  * @retval ENODEV	No valid NVRAM source could be found.
1404  * @retval EFTYPE	If the variable data cannot be coerced to a
1405  *			a valid integer representation.
1406  * @retval ERANGE	If value coercion would overflow (or underflow)
1407  *			int16_t.
1408  * @retval non-zero	If reading @p name otherwise fails, a regular unix
1409  *			error code will be returned.
1410  */
1411 int
1412 bhnd_nvram_getvar_int16(device_t dev, const char *name, int16_t *value)
1413 {
1414 	return (bhnd_nvram_getvar_int(dev, name, value, sizeof(*value)));
1415 }
1416 
1417 /**
1418  * Read an NVRAM variable's signed 32-bit integer value.
1419  *
1420  * @param 		dev	A bhnd bus child device.
1421  * @param		name	The NVRAM variable name.
1422  * @param[out]		value	On success, the requested value will be written
1423  *				to this pointer.
1424  *
1425  * @retval 0		success
1426  * @retval ENOENT	The requested variable was not found.
1427  * @retval ENODEV	No valid NVRAM source could be found.
1428  * @retval EFTYPE	If the variable data cannot be coerced to a
1429  *			a valid integer representation.
1430  * @retval ERANGE	If value coercion would overflow (or underflow)
1431  *			int32_t.
1432  * @retval non-zero	If reading @p name otherwise fails, a regular unix
1433  *			error code will be returned.
1434  */
1435 int
1436 bhnd_nvram_getvar_int32(device_t dev, const char *name, int32_t *value)
1437 {
1438 	return (bhnd_nvram_getvar_int(dev, name, value, sizeof(*value)));
1439 }
1440 
1441 /**
1442  * Read an NVRAM variable's array value.
1443  *
1444  * @param 		dev	A bhnd bus child device.
1445  * @param		name	The NVRAM variable name.
1446  * @param[out]		buf	A buffer large enough to hold @p size bytes.
1447  *				On success, the requested value will be written
1448  *				to this buffer.
1449  * @param[in,out]	size	The required number of bytes to write to
1450  *				@p buf.
1451  * @param		type	The desired array element data representation.
1452  *
1453  * @retval 0		success
1454  * @retval ENOENT	The requested variable was not found.
1455  * @retval ENODEV	No valid NVRAM source could be found.
1456  * @retval ENXIO	If less than @p size bytes are available.
1457  * @retval ENOMEM	If a buffer of @p size is too small to hold the
1458  *			requested value.
1459  * @retval EFTYPE	If the variable data cannot be coerced to a
1460  *			a valid instance of @p type.
1461  * @retval ERANGE	If value coercion would overflow (or underflow) a
1462  *			representation of @p type.
1463  * @retval non-zero	If reading @p name otherwise fails, a regular unix
1464  *			error code will be returned.
1465  */
1466 int
1467 bhnd_nvram_getvar_array(device_t dev, const char *name, void *buf, size_t size,
1468     bhnd_nvram_type type)
1469 {
1470 	size_t	nbytes;
1471 	int	error;
1472 
1473 	/* Attempt read */
1474 	nbytes = size;
1475 	if ((error = bhnd_nvram_getvar(dev, name, buf, &nbytes, type)))
1476 		return (error);
1477 
1478 	/* Verify that the expected number of bytes were fetched */
1479 	if (nbytes < size)
1480 		return (ENXIO);
1481 
1482 	return (0);
1483 }
1484 
1485 /**
1486  * Initialize a service provider registry.
1487  *
1488  * @param bsr		The service registry to initialize.
1489  *
1490  * @retval 0            success
1491  * @retval non-zero     if an error occurs initializing the service registry,
1492  *                      a regular unix error code will be returned.
1493 
1494  */
1495 int
1496 bhnd_service_registry_init(struct bhnd_service_registry *bsr)
1497 {
1498 	STAILQ_INIT(&bsr->entries);
1499 	mtx_init(&bsr->lock, "bhnd_service_registry lock", NULL, MTX_DEF);
1500 
1501 	return (0);
1502 }
1503 
1504 /**
1505  * Release all resources held by @p bsr.
1506  *
1507  * @param bsr		A service registry instance previously successfully
1508  *			initialized via bhnd_service_registry_init().
1509  *
1510  * @retval 0		success
1511  * @retval EBUSY	if active references to service providers registered
1512  *			with @p bsr exist.
1513  */
1514 int
1515 bhnd_service_registry_fini(struct bhnd_service_registry *bsr)
1516 {
1517 	struct bhnd_service_entry *entry, *enext;
1518 
1519 	/* Remove everthing we can */
1520 	mtx_lock(&bsr->lock);
1521 	STAILQ_FOREACH_SAFE(entry, &bsr->entries, link, enext) {
1522 		if (entry->refs > 0)
1523 			continue;
1524 
1525 		STAILQ_REMOVE(&bsr->entries, entry, bhnd_service_entry, link);
1526 		free(entry, M_BHND);
1527 	}
1528 
1529 	if (!STAILQ_EMPTY(&bsr->entries)) {
1530 		mtx_unlock(&bsr->lock);
1531 		return (EBUSY);
1532 	}
1533 	mtx_unlock(&bsr->lock);
1534 
1535 	mtx_destroy(&bsr->lock);
1536 	return (0);
1537 }
1538 
1539 /**
1540  * Register a @p provider for the given @p service.
1541  *
1542  * @param bsr		Service registry to be modified.
1543  * @param provider	Service provider to register.
1544  * @param service	Service for which @p provider will be registered.
1545  * @param flags		Service provider flags (see BHND_SPF_*).
1546  *
1547  * @retval 0		success
1548  * @retval EEXIST	if an entry for @p service already exists.
1549  * @retval EINVAL	if @p service is BHND_SERVICE_ANY.
1550  * @retval non-zero	if registering @p provider otherwise fails, a regular
1551  *			unix error code will be returned.
1552  */
1553 int
1554 bhnd_service_registry_add(struct bhnd_service_registry *bsr, device_t provider,
1555     bhnd_service_t service, uint32_t flags)
1556 {
1557 	struct bhnd_service_entry *entry;
1558 
1559 	if (service == BHND_SERVICE_ANY)
1560 		return (EINVAL);
1561 
1562 	mtx_lock(&bsr->lock);
1563 
1564 	/* Is a service provider already registered? */
1565 	STAILQ_FOREACH(entry, &bsr->entries, link) {
1566 		if (entry->service == service) {
1567 			mtx_unlock(&bsr->lock);
1568 			return (EEXIST);
1569 		}
1570 	}
1571 
1572 	/* Initialize and insert our new entry */
1573 	entry = malloc(sizeof(*entry), M_BHND, M_NOWAIT);
1574 	if (entry == NULL) {
1575 		mtx_unlock(&bsr->lock);
1576 		return (ENOMEM);
1577 	}
1578 
1579 	entry->provider = provider;
1580 	entry->service = service;
1581 	entry->flags = flags;
1582 	refcount_init(&entry->refs, 0);
1583 
1584 	STAILQ_INSERT_HEAD(&bsr->entries, entry, link);
1585 
1586 	mtx_unlock(&bsr->lock);
1587 	return (0);
1588 }
1589 
1590 /**
1591  * Free an unreferenced registry entry.
1592  *
1593  * @param entry	The entry to be deallocated.
1594  */
1595 static void
1596 bhnd_service_registry_free_entry(struct bhnd_service_entry *entry)
1597 {
1598 	KASSERT(entry->refs == 0, ("provider has active references"));
1599 	free(entry, M_BHND);
1600 }
1601 
1602 /**
1603  * Attempt to remove the @p service provider registration for @p provider.
1604  *
1605  * @param bsr		The service registry to be modified.
1606  * @param provider	The service provider to be deregistered.
1607  * @param service	The service for which @p provider will be deregistered,
1608  *			or BHND_SERVICE_ANY to remove all service
1609  *			registrations for @p provider.
1610  *
1611  * @retval 0		success
1612  * @retval EBUSY	if active references to @p provider exist; see
1613  *			bhnd_service_registry_retain() and
1614  *			bhnd_service_registry_release().
1615  */
1616 int
1617 bhnd_service_registry_remove(struct bhnd_service_registry *bsr,
1618     device_t provider, bhnd_service_t service)
1619 {
1620 	struct bhnd_service_entry *entry, *enext;
1621 
1622 	mtx_lock(&bsr->lock);
1623 
1624 #define	BHND_PROV_MATCH(_e)	\
1625 	((_e)->provider == provider &&	\
1626 	 (service == BHND_SERVICE_ANY || (_e)->service == service))
1627 
1628 	/* Validate matching provider entries before making any
1629 	 * modifications */
1630 	STAILQ_FOREACH(entry, &bsr->entries, link) {
1631 		/* Skip non-matching entries */
1632 		if (!BHND_PROV_MATCH(entry))
1633 			continue;
1634 
1635 		/* Entry is in use? */
1636 		if (entry->refs > 0) {
1637 			mtx_unlock(&bsr->lock);
1638 			return (EBUSY);
1639 		}
1640 	}
1641 
1642 	/* We can now safely remove matching entries */
1643 	STAILQ_FOREACH_SAFE(entry, &bsr->entries, link, enext) {
1644 		/* Skip non-matching entries */
1645 		if (!BHND_PROV_MATCH(entry))
1646 			continue;
1647 
1648 		/* Remove from list */
1649 		STAILQ_REMOVE(&bsr->entries, entry, bhnd_service_entry, link);
1650 
1651 		/* Free provider entry */
1652 		bhnd_service_registry_free_entry(entry);
1653 	}
1654 #undef	BHND_PROV_MATCH
1655 
1656 	mtx_unlock(&bsr->lock);
1657 	return (0);
1658 }
1659 
1660 /**
1661  * Retain and return a reference to a registered @p service provider, if any.
1662  *
1663  * @param bsr		The service registry to be queried.
1664  * @param service	The service for which a provider should be returned.
1665  *
1666  * On success, the caller assumes ownership the returned provider, and
1667  * is responsible for releasing this reference via
1668  * bhnd_service_registry_release().
1669  *
1670  * @retval device_t	success
1671  * @retval NULL		if no provider is registered for @p service.
1672  */
1673 device_t
1674 bhnd_service_registry_retain(struct bhnd_service_registry *bsr,
1675     bhnd_service_t service)
1676 {
1677 	struct bhnd_service_entry *entry;
1678 
1679 	mtx_lock(&bsr->lock);
1680 	STAILQ_FOREACH(entry, &bsr->entries, link) {
1681 		if (entry->service != service)
1682 			continue;
1683 
1684 		/* With a live refcount, entry is gauranteed to remain alive
1685 		 * after we release our lock */
1686 		refcount_acquire(&entry->refs);
1687 
1688 		mtx_unlock(&bsr->lock);
1689 		return (entry->provider);
1690 	}
1691 	mtx_unlock(&bsr->lock);
1692 
1693 	/* Not found */
1694 	return (NULL);
1695 }
1696 
1697 /**
1698  * Release a reference to a service provider previously returned by
1699  * bhnd_service_registry_retain().
1700  *
1701  * If this is the last reference to an inherited service provider registration
1702  * (see BHND_SPF_INHERITED), the registration will also be removed, and
1703  * true will be returned.
1704  *
1705  * @param bsr		The service registry from which @p provider
1706  *			was returned.
1707  * @param provider	The provider to be released.
1708  * @param service	The service for which @p provider was previously
1709  *			retained.
1710  * @retval true		The inherited service provider registration was removed;
1711  *			the caller should release its own reference to the
1712  *			provider.
1713  * @retval false	The service provider was not inherited, or active
1714  *			references to the provider remain.
1715  *
1716  * @see BHND_SPF_INHERITED
1717  */
1718 bool
1719 bhnd_service_registry_release(struct bhnd_service_registry *bsr,
1720     device_t provider, bhnd_service_t service)
1721 {
1722 	struct bhnd_service_entry *entry;
1723 
1724 	/* Exclusive lock, as we need to prevent any new references to the
1725 	 * entry from being taken if it's to be removed */
1726 	mtx_lock(&bsr->lock);
1727 	STAILQ_FOREACH(entry, &bsr->entries, link) {
1728 		bool removed;
1729 
1730 		if (entry->provider != provider)
1731 			continue;
1732 
1733 		if (entry->service != service)
1734 			continue;
1735 
1736 		if (refcount_release(&entry->refs) &&
1737 		    (entry->flags & BHND_SPF_INHERITED))
1738 		{
1739 			/* If an inherited entry is no longer actively
1740 			 * referenced, remove the local registration and inform
1741 			 * the caller. */
1742 			STAILQ_REMOVE(&bsr->entries, entry, bhnd_service_entry,
1743 			    link);
1744 			bhnd_service_registry_free_entry(entry);
1745 			removed = true;
1746 		} else {
1747 			removed = false;
1748 		}
1749 
1750 		mtx_unlock(&bsr->lock);
1751 		return (removed);
1752 	}
1753 
1754 	/* Caller owns a reference, but no such provider is registered? */
1755 	panic("invalid service provider reference");
1756 }
1757 
1758 /**
1759  * Using the bhnd(4) bus-level core information and a custom core name,
1760  * populate @p dev's device description.
1761  *
1762  * @param dev A bhnd-bus attached device.
1763  * @param dev_name The core's name (e.g. "SDIO Device Core").
1764  */
1765 void
1766 bhnd_set_custom_core_desc(device_t dev, const char *dev_name)
1767 {
1768 	const char *vendor_name;
1769 	char *desc;
1770 
1771 	vendor_name = bhnd_get_vendor_name(dev);
1772 	asprintf(&desc, M_BHND, "%s %s, rev %hhu", vendor_name, dev_name,
1773 	    bhnd_get_hwrev(dev));
1774 
1775 	if (desc != NULL) {
1776 		device_set_desc_copy(dev, desc);
1777 		free(desc, M_BHND);
1778 	} else {
1779 		device_set_desc(dev, dev_name);
1780 	}
1781 }
1782 
1783 /**
1784  * Using the bhnd(4) bus-level core information, populate @p dev's device
1785  * description.
1786  *
1787  * @param dev A bhnd-bus attached device.
1788  */
1789 void
1790 bhnd_set_default_core_desc(device_t dev)
1791 {
1792 	bhnd_set_custom_core_desc(dev, bhnd_get_device_name(dev));
1793 }
1794 
1795 /**
1796  * Using the bhnd @p chip_id, populate the bhnd(4) bus @p dev's device
1797  * description.
1798  *
1799  * @param dev A bhnd-bus attached device.
1800  * @param chip_id The chip identification.
1801  */
1802 void
1803 bhnd_set_default_bus_desc(device_t dev, const struct bhnd_chipid *chip_id)
1804 {
1805 	const char	*bus_name;
1806 	char		*desc;
1807 	char		 chip_name[BHND_CHIPID_MAX_NAMELEN];
1808 
1809 	/* Determine chip type's bus name */
1810 	switch (chip_id->chip_type) {
1811 	case BHND_CHIPTYPE_SIBA:
1812 		bus_name = "SIBA bus";
1813 		break;
1814 	case BHND_CHIPTYPE_BCMA:
1815 	case BHND_CHIPTYPE_BCMA_ALT:
1816 		bus_name = "BCMA bus";
1817 		break;
1818 	case BHND_CHIPTYPE_UBUS:
1819 		bus_name = "UBUS bus";
1820 		break;
1821 	default:
1822 		bus_name = "Unknown Type";
1823 		break;
1824 	}
1825 
1826 	/* Format chip name */
1827 	bhnd_format_chip_id(chip_name, sizeof(chip_name),
1828 	     chip_id->chip_id);
1829 
1830 	/* Format and set device description */
1831 	asprintf(&desc, M_BHND, "%s %s", chip_name, bus_name);
1832 	if (desc != NULL) {
1833 		device_set_desc_copy(dev, desc);
1834 		free(desc, M_BHND);
1835 	} else {
1836 		device_set_desc(dev, bus_name);
1837 	}
1838 
1839 }
1840 
1841 /**
1842  * Helper function for implementing BHND_BUS_REGISTER_PROVIDER().
1843  *
1844  * This implementation delegates the request to the BHND_BUS_REGISTER_PROVIDER()
1845  * method on the parent of @p dev. If no parent exists, the implementation
1846  * will return an error.
1847  */
1848 int
1849 bhnd_bus_generic_register_provider(device_t dev, device_t child,
1850     device_t provider, bhnd_service_t service)
1851 {
1852 	device_t parent = device_get_parent(dev);
1853 
1854 	if (parent != NULL) {
1855 		return (BHND_BUS_REGISTER_PROVIDER(parent, child,
1856 		    provider, service));
1857 	}
1858 
1859 	return (ENXIO);
1860 }
1861 
1862 /**
1863  * Helper function for implementing BHND_BUS_DEREGISTER_PROVIDER().
1864  *
1865  * This implementation delegates the request to the
1866  * BHND_BUS_DEREGISTER_PROVIDER() method on the parent of @p dev. If no parent
1867  * exists, the implementation will panic.
1868  */
1869 int
1870 bhnd_bus_generic_deregister_provider(device_t dev, device_t child,
1871     device_t provider, bhnd_service_t service)
1872 {
1873 	device_t parent = device_get_parent(dev);
1874 
1875 	if (parent != NULL) {
1876 		return (BHND_BUS_DEREGISTER_PROVIDER(parent, child,
1877 		    provider, service));
1878 	}
1879 
1880 	panic("missing BHND_BUS_DEREGISTER_PROVIDER()");
1881 }
1882 
1883 /**
1884  * Helper function for implementing BHND_BUS_RETAIN_PROVIDER().
1885  *
1886  * This implementation delegates the request to the
1887  * BHND_BUS_DEREGISTER_PROVIDER() method on the parent of @p dev. If no parent
1888  * exists, the implementation will return NULL.
1889  */
1890 device_t
1891 bhnd_bus_generic_retain_provider(device_t dev, device_t child,
1892     bhnd_service_t service)
1893 {
1894 	device_t parent = device_get_parent(dev);
1895 
1896 	if (parent != NULL) {
1897 		return (BHND_BUS_RETAIN_PROVIDER(parent, child,
1898 		    service));
1899 	}
1900 
1901 	return (NULL);
1902 }
1903 
1904 /**
1905  * Helper function for implementing BHND_BUS_RELEASE_PROVIDER().
1906  *
1907  * This implementation delegates the request to the
1908  * BHND_BUS_DEREGISTER_PROVIDER() method on the parent of @p dev. If no parent
1909  * exists, the implementation will panic.
1910  */
1911 void
1912 bhnd_bus_generic_release_provider(device_t dev, device_t child,
1913     device_t provider, bhnd_service_t service)
1914 {
1915 	device_t parent = device_get_parent(dev);
1916 
1917 	if (parent != NULL) {
1918 		return (BHND_BUS_RELEASE_PROVIDER(parent, child,
1919 		    provider, service));
1920 	}
1921 
1922 	panic("missing BHND_BUS_RELEASE_PROVIDER()");
1923 }
1924 
1925 /**
1926  * Helper function for implementing BHND_BUS_REGISTER_PROVIDER().
1927  *
1928  * This implementation uses the bhnd_service_registry_add() function to
1929  * do most of the work. It calls BHND_BUS_GET_SERVICE_REGISTRY() to find
1930  * a suitable service registry to edit.
1931  */
1932 int
1933 bhnd_bus_generic_sr_register_provider(device_t dev, device_t child,
1934     device_t provider, bhnd_service_t service)
1935 {
1936 	struct bhnd_service_registry *bsr;
1937 
1938 	bsr = BHND_BUS_GET_SERVICE_REGISTRY(dev, child);
1939 
1940 	KASSERT(bsr != NULL, ("NULL service registry"));
1941 
1942 	return (bhnd_service_registry_add(bsr, provider, service, 0));
1943 }
1944 
1945 /**
1946  * Helper function for implementing BHND_BUS_DEREGISTER_PROVIDER().
1947  *
1948  * This implementation uses the bhnd_service_registry_remove() function to
1949  * do most of the work. It calls BHND_BUS_GET_SERVICE_REGISTRY() to find
1950  * a suitable service registry to edit.
1951  */
1952 int
1953 bhnd_bus_generic_sr_deregister_provider(device_t dev, device_t child,
1954     device_t provider, bhnd_service_t service)
1955 {
1956 	struct bhnd_service_registry *bsr;
1957 
1958 	bsr = BHND_BUS_GET_SERVICE_REGISTRY(dev, child);
1959 
1960 	KASSERT(bsr != NULL, ("NULL service registry"));
1961 
1962 	return (bhnd_service_registry_remove(bsr, provider, service));
1963 }
1964 
1965 /**
1966  * Helper function for implementing BHND_BUS_RETAIN_PROVIDER().
1967  *
1968  * This implementation uses the bhnd_service_registry_retain() function to
1969  * do most of the work. It calls BHND_BUS_GET_SERVICE_REGISTRY() to find
1970  * a suitable service registry.
1971  *
1972  * If a local provider for the service is not available, and a parent device is
1973  * available, this implementation will attempt to fetch and locally register
1974  * a service provider reference from the parent of @p dev.
1975  */
1976 device_t
1977 bhnd_bus_generic_sr_retain_provider(device_t dev, device_t child,
1978     bhnd_service_t service)
1979 {
1980 	struct bhnd_service_registry	*bsr;
1981 	device_t			 parent, provider;
1982 	int				 error;
1983 
1984 	bsr = BHND_BUS_GET_SERVICE_REGISTRY(dev, child);
1985 	KASSERT(bsr != NULL, ("NULL service registry"));
1986 
1987 	/*
1988 	 * Attempt to fetch a service provider reference from either the local
1989 	 * service registry, or if not found, from our parent.
1990 	 *
1991 	 * If we fetch a provider from our parent, we register the provider
1992 	 * with the local service registry to prevent conflicting local
1993 	 * registrations from being added.
1994 	 */
1995 	while (1) {
1996 		/* Check the local service registry first */
1997 		provider = bhnd_service_registry_retain(bsr, service);
1998 		if (provider != NULL)
1999 			return (provider);
2000 
2001 		/* Otherwise, try to delegate to our parent (if any) */
2002 		if ((parent = device_get_parent(dev)) == NULL)
2003 			return (NULL);
2004 
2005 		provider = BHND_BUS_RETAIN_PROVIDER(parent, dev, service);
2006 		if (provider == NULL)
2007 			return (NULL);
2008 
2009 		/* Register the inherited service registration with the local
2010 		 * registry */
2011 		error = bhnd_service_registry_add(bsr, provider, service,
2012 		    BHND_SPF_INHERITED);
2013 		if (error) {
2014 			BHND_BUS_RELEASE_PROVIDER(parent, dev, provider,
2015 			    service);
2016 			if (error == EEXIST) {
2017 				/* A valid service provider was registered
2018 				 * concurrently; retry fetching from the local
2019 				 * registry */
2020 				continue;
2021 			}
2022 
2023 			device_printf(dev, "failed to register service "
2024 			    "provider: %d\n", error);
2025 			return (NULL);
2026 		}
2027 	}
2028 }
2029 
2030 /**
2031  * Helper function for implementing BHND_BUS_RELEASE_PROVIDER().
2032  *
2033  * This implementation uses the bhnd_service_registry_release() function to
2034  * do most of the work. It calls BHND_BUS_GET_SERVICE_REGISTRY() to find
2035  * a suitable service registry.
2036  */
2037 void
2038 bhnd_bus_generic_sr_release_provider(device_t dev, device_t child,
2039     device_t provider, bhnd_service_t service)
2040 {
2041 	struct bhnd_service_registry	*bsr;
2042 
2043 	bsr = BHND_BUS_GET_SERVICE_REGISTRY(dev, child);
2044 	KASSERT(bsr != NULL, ("NULL service registry"));
2045 
2046 	/* Release the provider reference; if the refcount hits zero on an
2047 	 * inherited reference, true will be returned, and we need to drop
2048 	 * our own bus reference to the provider */
2049 	if (!bhnd_service_registry_release(bsr, provider, service))
2050 		return;
2051 
2052 	/* Drop our reference to the borrowed provider */
2053 	BHND_BUS_RELEASE_PROVIDER(device_get_parent(dev), dev, provider,
2054 	    service);
2055 }
2056 
2057 /**
2058  * Helper function for implementing BHND_BUS_IS_HW_DISABLED().
2059  *
2060  * If a parent device is available, this implementation delegates the
2061  * request to the BHND_BUS_IS_HW_DISABLED() method on the parent of @p dev.
2062  *
2063  * If no parent device is available (i.e. on a the bus root), the hardware
2064  * is assumed to be usable and false is returned.
2065  */
2066 bool
2067 bhnd_bus_generic_is_hw_disabled(device_t dev, device_t child)
2068 {
2069 	if (device_get_parent(dev) != NULL)
2070 		return (BHND_BUS_IS_HW_DISABLED(device_get_parent(dev), child));
2071 
2072 	return (false);
2073 }
2074 
2075 /**
2076  * Helper function for implementing BHND_BUS_GET_CHIPID().
2077  *
2078  * This implementation delegates the request to the BHND_BUS_GET_CHIPID()
2079  * method on the parent of @p dev. If no parent exists, the implementation
2080  * will panic.
2081  */
2082 const struct bhnd_chipid *
2083 bhnd_bus_generic_get_chipid(device_t dev, device_t child)
2084 {
2085 	if (device_get_parent(dev) != NULL)
2086 		return (BHND_BUS_GET_CHIPID(device_get_parent(dev), child));
2087 
2088 	panic("missing BHND_BUS_GET_CHIPID()");
2089 }
2090 
2091 /**
2092  * Helper function for implementing BHND_BUS_GET_DMA_TRANSLATION().
2093  *
2094  * If a parent device is available, this implementation delegates the
2095  * request to the BHND_BUS_GET_DMA_TRANSLATION() method on the parent of @p dev.
2096  *
2097  * If no parent device is available, this implementation will panic.
2098  */
2099 int
2100 bhnd_bus_generic_get_dma_translation(device_t dev, device_t child, u_int width,
2101     uint32_t flags, bus_dma_tag_t *dmat,
2102     struct bhnd_dma_translation *translation)
2103 {
2104 	if (device_get_parent(dev) != NULL) {
2105 		return (BHND_BUS_GET_DMA_TRANSLATION(device_get_parent(dev),
2106 		    child, width, flags, dmat, translation));
2107 	}
2108 
2109 	panic("missing BHND_BUS_GET_DMA_TRANSLATION()");
2110 }
2111 
2112 /* nvram board_info population macros for bhnd_bus_generic_read_board_info() */
2113 #define	BHND_GV(_dest, _name)	\
2114 	bhnd_nvram_getvar_uint(child, BHND_NVAR_ ## _name, &_dest,	\
2115 	    sizeof(_dest))
2116 
2117 #define	REQ_BHND_GV(_dest, _name)		do {			\
2118 	if ((error = BHND_GV(_dest, _name))) {				\
2119 		device_printf(dev,					\
2120 		    "error reading " __STRING(_name) ": %d\n", error);	\
2121 		return (error);						\
2122 	}								\
2123 } while(0)
2124 
2125 #define	OPT_BHND_GV(_dest, _name, _default)	do {			\
2126 	if ((error = BHND_GV(_dest, _name))) {				\
2127 		if (error != ENOENT) {					\
2128 			device_printf(dev,				\
2129 			    "error reading "				\
2130 			       __STRING(_name) ": %d\n", error);	\
2131 			return (error);					\
2132 		}							\
2133 		_dest = _default;					\
2134 	}								\
2135 } while(0)
2136 
2137 /**
2138  * Helper function for implementing BHND_BUS_READ_BOARDINFO().
2139  *
2140  * This implementation populates @p info with information from NVRAM,
2141  * defaulting board_vendor and board_type fields to 0 if the
2142  * requested variables cannot be found.
2143  *
2144  * This behavior is correct for most SoCs, but must be overridden on
2145  * bridged (PCI, PCMCIA, etc) devices to produce a complete bhnd_board_info
2146  * result.
2147  */
2148 int
2149 bhnd_bus_generic_read_board_info(device_t dev, device_t child,
2150     struct bhnd_board_info *info)
2151 {
2152 	int	error;
2153 
2154 	OPT_BHND_GV(info->board_vendor,	BOARDVENDOR,	0);
2155 	OPT_BHND_GV(info->board_type,	BOARDTYPE,	0);	/* srom >= 2 */
2156 	OPT_BHND_GV(info->board_devid,	DEVID,		0);	/* srom >= 8 */
2157 	REQ_BHND_GV(info->board_rev,	BOARDREV);
2158 	OPT_BHND_GV(info->board_srom_rev,SROMREV,	0);	/* missing in
2159 								   some SoC
2160 								   NVRAM */
2161 	REQ_BHND_GV(info->board_flags,	BOARDFLAGS);
2162 	OPT_BHND_GV(info->board_flags2,	BOARDFLAGS2,	0);	/* srom >= 4 */
2163 	OPT_BHND_GV(info->board_flags3,	BOARDFLAGS3,	0);	/* srom >= 11 */
2164 
2165 	return (0);
2166 }
2167 
2168 #undef	BHND_GV
2169 #undef	BHND_GV_REQ
2170 #undef	BHND_GV_OPT
2171 
2172 /**
2173  * Helper function for implementing BHND_BUS_GET_NVRAM_VAR().
2174  *
2175  * This implementation searches @p dev for a usable NVRAM child device.
2176  *
2177  * If no usable child device is found on @p dev, the request is delegated to
2178  * the BHND_BUS_GET_NVRAM_VAR() method on the parent of @p dev.
2179  */
2180 int
2181 bhnd_bus_generic_get_nvram_var(device_t dev, device_t child, const char *name,
2182     void *buf, size_t *size, bhnd_nvram_type type)
2183 {
2184 	device_t	nvram;
2185 	device_t	parent;
2186 
2187 	bus_topo_assert();
2188 
2189 	/* Look for a directly-attached NVRAM child */
2190 	if ((nvram = device_find_child(dev, "bhnd_nvram", -1)) != NULL)
2191 		return BHND_NVRAM_GETVAR(nvram, name, buf, size, type);
2192 
2193 	/* Try to delegate to parent */
2194 	if ((parent = device_get_parent(dev)) == NULL)
2195 		return (ENODEV);
2196 
2197 	return (BHND_BUS_GET_NVRAM_VAR(device_get_parent(dev), child,
2198 	    name, buf, size, type));
2199 }
2200 
2201 /**
2202  * Helper function for implementing BHND_BUS_ALLOC_RESOURCE().
2203  *
2204  * This implementation of BHND_BUS_ALLOC_RESOURCE() delegates allocation
2205  * of the underlying resource to BUS_ALLOC_RESOURCE(), and activation
2206  * to @p dev's BHND_BUS_ACTIVATE_RESOURCE().
2207  */
2208 struct bhnd_resource *
2209 bhnd_bus_generic_alloc_resource(device_t dev, device_t child, int type,
2210 	int *rid, rman_res_t start, rman_res_t end, rman_res_t count,
2211 	u_int flags)
2212 {
2213 	struct bhnd_resource	*br;
2214 	struct resource		*res;
2215 	int			 error;
2216 
2217 	br = NULL;
2218 	res = NULL;
2219 
2220 	/* Allocate the real bus resource (without activating it) */
2221 	res = BUS_ALLOC_RESOURCE(dev, child, type, rid, start, end, count,
2222 	    (flags & ~RF_ACTIVE));
2223 	if (res == NULL)
2224 		return (NULL);
2225 
2226 	/* Allocate our bhnd resource wrapper. */
2227 	br = malloc(sizeof(struct bhnd_resource), M_BHND, M_NOWAIT);
2228 	if (br == NULL)
2229 		goto failed;
2230 
2231 	br->direct = false;
2232 	br->res = res;
2233 
2234 	/* Attempt activation */
2235 	if (flags & RF_ACTIVE) {
2236 		error = BHND_BUS_ACTIVATE_RESOURCE(dev, child, type, *rid, br);
2237 		if (error)
2238 			goto failed;
2239 	}
2240 
2241 	return (br);
2242 
2243 failed:
2244 	if (res != NULL)
2245 		BUS_RELEASE_RESOURCE(dev, child, type, *rid, res);
2246 
2247 	free(br, M_BHND);
2248 	return (NULL);
2249 }
2250 
2251 /**
2252  * Helper function for implementing BHND_BUS_RELEASE_RESOURCE().
2253  *
2254  * This implementation of BHND_BUS_RELEASE_RESOURCE() delegates release of
2255  * the backing resource to BUS_RELEASE_RESOURCE().
2256  */
2257 int
2258 bhnd_bus_generic_release_resource(device_t dev, device_t child, int type,
2259     int rid, struct bhnd_resource *r)
2260 {
2261 	int error;
2262 
2263 	if ((error = BUS_RELEASE_RESOURCE(dev, child, type, rid, r->res)))
2264 		return (error);
2265 
2266 	free(r, M_BHND);
2267 	return (0);
2268 }
2269 
2270 /**
2271  * Helper function for implementing BHND_BUS_ACTIVATE_RESOURCE().
2272  *
2273  * This implementation of BHND_BUS_ACTIVATE_RESOURCE() first calls the
2274  * BHND_BUS_ACTIVATE_RESOURCE() method of the parent of @p dev.
2275  *
2276  * If this fails, and if @p dev is the direct parent of @p child, standard
2277  * resource activation is attempted via bus_activate_resource(). This enables
2278  * direct use of the bhnd(4) resource APIs on devices that may not be attached
2279  * to a parent bhnd bus or bridge.
2280  */
2281 int
2282 bhnd_bus_generic_activate_resource(device_t dev, device_t child, int type,
2283     int rid, struct bhnd_resource *r)
2284 {
2285 	int	error;
2286 	bool	passthrough;
2287 
2288 	passthrough = (device_get_parent(child) != dev);
2289 
2290 	/* Try to delegate to the parent */
2291 	if (device_get_parent(dev) != NULL) {
2292 		error = BHND_BUS_ACTIVATE_RESOURCE(device_get_parent(dev),
2293 		    child, type, rid, r);
2294 	} else {
2295 		error = ENODEV;
2296 	}
2297 
2298 	/* If bhnd(4) activation has failed and we're the child's direct
2299 	 * parent, try falling back on standard resource activation.
2300 	 */
2301 	if (error && !passthrough) {
2302 		error = bus_activate_resource(child, type, rid, r->res);
2303 		if (!error)
2304 			r->direct = true;
2305 	}
2306 
2307 	return (error);
2308 }
2309 
2310 /**
2311  * Helper function for implementing BHND_BUS_DEACTIVATE_RESOURCE().
2312  *
2313  * This implementation of BHND_BUS_ACTIVATE_RESOURCE() simply calls the
2314  * BHND_BUS_ACTIVATE_RESOURCE() method of the parent of @p dev.
2315  */
2316 int
2317 bhnd_bus_generic_deactivate_resource(device_t dev, device_t child,
2318     int type, int rid, struct bhnd_resource *r)
2319 {
2320 	if (device_get_parent(dev) != NULL)
2321 		return (BHND_BUS_DEACTIVATE_RESOURCE(device_get_parent(dev),
2322 		    child, type, rid, r));
2323 
2324 	return (EINVAL);
2325 }
2326 
2327 /**
2328  * Helper function for implementing BHND_BUS_GET_INTR_DOMAIN().
2329  *
2330  * This implementation simply returns the address of nearest bhnd(4) bus,
2331  * which may be @p dev; this behavior may be incompatible with FDT/OFW targets.
2332  */
2333 uintptr_t
2334 bhnd_bus_generic_get_intr_domain(device_t dev, device_t child, bool self)
2335 {
2336 	return ((uintptr_t)dev);
2337 }
2338