17aec1d6eScindi /*
27aec1d6eScindi  * CDDL HEADER START
37aec1d6eScindi  *
47aec1d6eScindi  * The contents of this file are subject to the terms of the
57aec1d6eScindi  * Common Development and Distribution License (the "License").
67aec1d6eScindi  * You may not use this file except in compliance with the License.
77aec1d6eScindi  *
87aec1d6eScindi  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97aec1d6eScindi  * or http://www.opensolaris.org/os/licensing.
107aec1d6eScindi  * See the License for the specific language governing permissions
117aec1d6eScindi  * and limitations under the License.
127aec1d6eScindi  *
137aec1d6eScindi  * When distributing Covered Code, include this CDDL HEADER in each
147aec1d6eScindi  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157aec1d6eScindi  * If applicable, add the following below this CDDL HEADER, with the
167aec1d6eScindi  * fields enclosed by brackets "[]" replaced with your own identifying
177aec1d6eScindi  * information: Portions Copyright [yyyy] [name of copyright owner]
187aec1d6eScindi  *
197aec1d6eScindi  * CDDL HEADER END
207aec1d6eScindi  */
217aec1d6eScindi 
227aec1d6eScindi /*
237aec1d6eScindi  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
247aec1d6eScindi  * Use is subject to license terms.
257aec1d6eScindi  */
267aec1d6eScindi 
277aec1d6eScindi #pragma ident	"%Z%%M%	%I%	%E% SMI"
287aec1d6eScindi 
297aec1d6eScindi /*
307aec1d6eScindi  * did.c
317aec1d6eScindi  *	The acronym did means "Dev-Info-Data".  Many properties and
327aec1d6eScindi  *	characteristics of topology nodes are, with a bit of coaxing
337aec1d6eScindi  *	derived from devinfo nodes.  These routines do some of the
347aec1d6eScindi  *	derivation and also encapsulate the discoveries in did_t
357aec1d6eScindi  *	structures that get associated with topology nodes as their
367aec1d6eScindi  *	"private" data.
377aec1d6eScindi  */
387aec1d6eScindi #include <alloca.h>
397aec1d6eScindi #include <assert.h>
407aec1d6eScindi #include <string.h>
417aec1d6eScindi #include <strings.h>
427aec1d6eScindi #include <sys/types.h>
43*0eb822a1Scindi #include <fm/topo_mod.h>
447aec1d6eScindi #include <libnvpair.h>
457aec1d6eScindi #include <libdevinfo.h>
467aec1d6eScindi #include <sys/pcie.h>
477aec1d6eScindi 
48*0eb822a1Scindi #include <hostbridge.h>
49*0eb822a1Scindi #include <pcibus.h>
50*0eb822a1Scindi #include <did_props.h>
51*0eb822a1Scindi 
527aec1d6eScindi #include "did_impl.h"
537aec1d6eScindi 
547aec1d6eScindi static void slotnm_destroy(slotnm_t *);
557aec1d6eScindi 
567aec1d6eScindi static slotnm_t *
577aec1d6eScindi slotnm_create(topo_mod_t *mp, int dev, char *str)
587aec1d6eScindi {
597aec1d6eScindi 	slotnm_t *p;
607aec1d6eScindi 
617aec1d6eScindi 	if ((p = topo_mod_alloc(mp, sizeof (slotnm_t))) == NULL)
627aec1d6eScindi 		return (NULL);
637aec1d6eScindi 	p->snm_mod = mp;
647aec1d6eScindi 	p->snm_next = NULL;
657aec1d6eScindi 	p->snm_dev = dev;
667aec1d6eScindi 	p->snm_label = topo_mod_strdup(mp, str);
677aec1d6eScindi 	if (p->snm_label == NULL) {
687aec1d6eScindi 		slotnm_destroy(p);
697aec1d6eScindi 		return (NULL);
707aec1d6eScindi 	}
717aec1d6eScindi 	return (p);
727aec1d6eScindi }
737aec1d6eScindi 
747aec1d6eScindi static void
757aec1d6eScindi slotnm_destroy(slotnm_t *p)
767aec1d6eScindi {
777aec1d6eScindi 	if (p == NULL)
787aec1d6eScindi 		return;
797aec1d6eScindi 	slotnm_destroy(p->snm_next);
807aec1d6eScindi 	if (p->snm_label != NULL)
817aec1d6eScindi 		topo_mod_strfree(p->snm_mod, p->snm_label);
827aec1d6eScindi 	topo_mod_free(p->snm_mod, p, sizeof (slotnm_t));
837aec1d6eScindi }
847aec1d6eScindi 
857aec1d6eScindi static int
867aec1d6eScindi slotnm_cp(did_t *from, did_t *to, int *nslots)
877aec1d6eScindi {
887aec1d6eScindi 	slotnm_t *nxt, *new;
897aec1d6eScindi 	slotnm_t *last = NULL;
907aec1d6eScindi 
917aec1d6eScindi 	*nslots = 0;
927aec1d6eScindi 	for (nxt = from->dp_slotnames; nxt != NULL; nxt = nxt->snm_next) {
937aec1d6eScindi 		new = slotnm_create(to->dp_mod, nxt->snm_dev, nxt->snm_label);
947aec1d6eScindi 		if (new == NULL) {
957aec1d6eScindi 			if (to->dp_slotnames != NULL)
967aec1d6eScindi 				slotnm_destroy(to->dp_slotnames);
977aec1d6eScindi 			to->dp_slotnames = NULL;
987aec1d6eScindi 			*nslots = 0;
997aec1d6eScindi 			return (-1);
1007aec1d6eScindi 		}
1017aec1d6eScindi 		if (last == NULL) {
1027aec1d6eScindi 			to->dp_slotnames = last = new;
1037aec1d6eScindi 		} else {
1047aec1d6eScindi 			last->snm_next = new;
1057aec1d6eScindi 			last = new;
1067aec1d6eScindi 		}
1077aec1d6eScindi 		(*nslots)++;
1087aec1d6eScindi 	}
1097aec1d6eScindi 	if (*nslots > 0)
1107aec1d6eScindi 		topo_mod_dprintf(to->dp_mod,
1117aec1d6eScindi 		    "%p inherits %d slot label(s) from %p.\n",
1127aec1d6eScindi 		    to, *nslots, from);
1137aec1d6eScindi 	return (0);
1147aec1d6eScindi }
1157aec1d6eScindi 
1167aec1d6eScindi static int
1177aec1d6eScindi di_physlotinfo_get(topo_mod_t *mp, di_node_t src, uint_t excap,
118*0eb822a1Scindi     int *slotnum, char **slotnm)
1197aec1d6eScindi {
1207aec1d6eScindi 	char *slotbuf;
1210b6016e6Shueston 	int sz;
1220b6016e6Shueston 	uchar_t *buf;
1237aec1d6eScindi 
1247aec1d6eScindi 	*slotnum = -1;
125*0eb822a1Scindi 	(void) di_uintprop_get(mp, src, DI_PHYSPROP, (uint_t *)slotnum);
1267aec1d6eScindi 	/*
1277aec1d6eScindi 	 * If no physical slot number property was found, then the
1287aec1d6eScindi 	 * capabilities register may indicate the pci-express device
1297aec1d6eScindi 	 * implements a slot, and we should record which slot.
1307aec1d6eScindi 	 */
1317aec1d6eScindi 	if (*slotnum == -1 && (excap & PCIE_PCIECAP_SLOT_IMPL) != 0) {
1327aec1d6eScindi 		uint_t slotcap;
1337aec1d6eScindi 		int e;
134*0eb822a1Scindi 		e = di_uintprop_get(mp, src, "pcie-slotcap-reg", &slotcap);
1357aec1d6eScindi 		if (e == 0)
1367aec1d6eScindi 			*slotnum = slotcap >> PCIE_SLOTCAP_PHY_SLOT_NUM_SHIFT;
1377aec1d6eScindi 	}
1387aec1d6eScindi 	if (*slotnum == -1)
1397aec1d6eScindi 		return (0);
1407aec1d6eScindi 
1417aec1d6eScindi 	/*
1420b6016e6Shueston 	 * For PCI-Express, there is only one downstream device, so check for
1430b6016e6Shueston 	 * a slot-names property, and if it exists, ignore the slotmask value
1440b6016e6Shueston 	 * and use the string as the label.
1457aec1d6eScindi 	 */
146*0eb822a1Scindi 	if (di_bytes_get(mp, src, DI_SLOTPROP, &sz, &buf) == 0 &&
147724365f7Ssethg 	    sz > 4) {
1480b6016e6Shueston 		slotbuf = (char *)&buf[4];
1490b6016e6Shueston 	} else {
1500b6016e6Shueston 		/*
1510b6016e6Shueston 		 * Make generic description string "SLOT <num>", allow up to
1520b6016e6Shueston 		 * 10 digits for number
1530b6016e6Shueston 		 */
1540b6016e6Shueston 		slotbuf = alloca(16);
1550b6016e6Shueston 		(void) snprintf(slotbuf, 16, "SLOT %d", *slotnum);
1560b6016e6Shueston 	}
1577aec1d6eScindi 	if ((*slotnm = topo_mod_strdup(mp, slotbuf)) == NULL)
1587aec1d6eScindi 		return (-1);
1597aec1d6eScindi 
1607aec1d6eScindi 	return (0);
1617aec1d6eScindi }
1627aec1d6eScindi 
1637aec1d6eScindi static int
164*0eb822a1Scindi di_slotinfo_get(topo_mod_t *mp, di_node_t src, int *nslots, slotnm_t **slots)
1657aec1d6eScindi {
1667aec1d6eScindi 	slotnm_t *lastslot = NULL;
1677aec1d6eScindi 	slotnm_t *newslot;
1687aec1d6eScindi 	uchar_t *slotbuf;
1697aec1d6eScindi 	uint_t slotmap = 0;
1707aec1d6eScindi 	char *slotname;
1717aec1d6eScindi 	int andbit;
1727aec1d6eScindi 	int sz = -1;
1737aec1d6eScindi 
1747aec1d6eScindi 	*slots = NULL;
1757aec1d6eScindi 	*nslots = 0;
176*0eb822a1Scindi 	if (di_bytes_get(mp, src, DI_SLOTPROP, &sz, &slotbuf) < 0)
1777aec1d6eScindi 		return (0);
1787aec1d6eScindi 	if (sz < sizeof (uint_t))
1797aec1d6eScindi 		return (0);
1807aec1d6eScindi 	bcopy(slotbuf, &slotmap, sizeof (uint_t));
1817aec1d6eScindi 	if (slotmap == 0)
1827aec1d6eScindi 		return (0);
1837aec1d6eScindi 
1847aec1d6eScindi 	slotname = (char *)&slotbuf[4];
1857aec1d6eScindi 	for (andbit = 0; andbit < 32; andbit++) {
1867aec1d6eScindi 		if (slotmap & (1 << andbit)) {
1877aec1d6eScindi 			char *s = slotname;
1887aec1d6eScindi 			slotname += strlen(s) + 1;
1897aec1d6eScindi 			if ((newslot = slotnm_create(mp, andbit, s)) == NULL) {
1907aec1d6eScindi 				slotnm_destroy(*slots);
1917aec1d6eScindi 				*slots = NULL;
1927aec1d6eScindi 				*nslots = 0;
1937aec1d6eScindi 				return (-1);
1947aec1d6eScindi 			}
1957aec1d6eScindi 			if (lastslot == NULL)
1967aec1d6eScindi 				*slots = lastslot = newslot;
197c863ec5cSstephh 			else {
1987aec1d6eScindi 				lastslot->snm_next = newslot;
199c863ec5cSstephh 				lastslot = newslot;
200c863ec5cSstephh 			}
2017aec1d6eScindi 			(*nslots)++;
2027aec1d6eScindi 		}
2037aec1d6eScindi 	}
2047aec1d6eScindi 	return (0);
2057aec1d6eScindi }
2067aec1d6eScindi 
2077aec1d6eScindi int
2087aec1d6eScindi did_physslot(did_t *did)
2097aec1d6eScindi {
2107aec1d6eScindi 	assert(did != NULL);
2117aec1d6eScindi 	return (did->dp_physlot);
2127aec1d6eScindi }
2137aec1d6eScindi 
2147aec1d6eScindi did_t *
215*0eb822a1Scindi did_create(topo_mod_t *mp, di_node_t src,
216*0eb822a1Scindi     int ibrd, int ibrdge, int irc, int ibus)
2177aec1d6eScindi {
2187aec1d6eScindi 	did_t *np;
2197aec1d6eScindi 	did_t *pd;
2207aec1d6eScindi 	uint_t code;
2217aec1d6eScindi 	uint_t reg;
2227aec1d6eScindi 
223*0eb822a1Scindi 	if ((pd = did_hash_lookup(mp, src)) != NULL) {
2247aec1d6eScindi 		topo_mod_dprintf(mp, "Attempt to create existing did_t.\n");
2257aec1d6eScindi 		assert(ibus == TRUST_BDF || (pd->dp_bus == ibus));
2267aec1d6eScindi 		return (pd);
2277aec1d6eScindi 	}
2287aec1d6eScindi 
2297aec1d6eScindi 	if ((np = topo_mod_zalloc(mp, sizeof (did_t))) == NULL)
2307aec1d6eScindi 		return (NULL);
2317aec1d6eScindi 	np->dp_mod = mp;
2327aec1d6eScindi 	np->dp_src = src;
233*0eb822a1Scindi 	np->dp_hash = (did_hash_t *)topo_mod_getspecific(mp);
2347aec1d6eScindi 
2357aec1d6eScindi 	/*
2367aec1d6eScindi 	 * We must have a reg prop and from it we extract the bus #,
2377aec1d6eScindi 	 * device #, and function #.
2387aec1d6eScindi 	 */
239*0eb822a1Scindi 	if (di_uintprop_get(mp, src, DI_REGPROP, &reg) < 0) {
2407aec1d6eScindi 		topo_mod_free(mp, np, sizeof (did_t));
2417aec1d6eScindi 		return (NULL);
2427aec1d6eScindi 	}
2437aec1d6eScindi 	np->dp_board = ibrd;
2447aec1d6eScindi 	np->dp_bridge = ibrdge;
2457aec1d6eScindi 	np->dp_rc = irc;
2467aec1d6eScindi 	if (ibus == TRUST_BDF)
2477aec1d6eScindi 		np->dp_bus = PCI_REG_BUS_G(reg);
2487aec1d6eScindi 	else
2497aec1d6eScindi 		np->dp_bus = ibus;
2507aec1d6eScindi 	np->dp_dev = PCI_REG_DEV_G(reg);
2517aec1d6eScindi 	np->dp_fn = PCI_REG_FUNC_G(reg);
25200d0963fSdilpreet 	np->dp_bdf = (PCI_REG_BUS_G(reg) << 8) | (PCI_REG_DEV_G(reg) << 3) |
25300d0963fSdilpreet 	    PCI_REG_FUNC_G(reg);
2547aec1d6eScindi 	/*
2557aec1d6eScindi 	 * There *may* be a class code we can capture.  If there wasn't
2567aec1d6eScindi 	 * one, capture that fact by setting the class value to -1.
2577aec1d6eScindi 	 */
258*0eb822a1Scindi 	if (di_uintprop_get(mp, src, DI_CCPROP, &code) == 0) {
2597aec1d6eScindi 		np->dp_class = GETCLASS(code);
2607aec1d6eScindi 		np->dp_subclass = GETSUBCLASS(code);
2617aec1d6eScindi 	} else {
2627aec1d6eScindi 		np->dp_class = -1;
2637aec1d6eScindi 	}
2647aec1d6eScindi 	/*
2657aec1d6eScindi 	 * There *may* be a PCI-express capabilities register we can capture.
2667aec1d6eScindi 	 * If there wasn't one, the capabilities will be the out-of-bounds
2677aec1d6eScindi 	 * value of zero.
2687aec1d6eScindi 	 */
269*0eb822a1Scindi 	(void) di_uintprop_get(mp, src, "pcie-capid-reg", &np->dp_excap);
2707aec1d6eScindi 	/*
2717aec1d6eScindi 	 * There *may* be a physical slot number property we can capture.
2727aec1d6eScindi 	 */
2737aec1d6eScindi 	if (di_physlotinfo_get(mp,
274*0eb822a1Scindi 	    src, np->dp_excap, &np->dp_physlot, &np->dp_physlot_label) < 0) {
2757aec1d6eScindi 		topo_mod_free(mp, np, sizeof (did_t));
2767aec1d6eScindi 		return (NULL);
2777aec1d6eScindi 	}
2787aec1d6eScindi 	/*
2797aec1d6eScindi 	 * There *may* be PCI slot info we can capture
2807aec1d6eScindi 	 */
281*0eb822a1Scindi 	if (di_slotinfo_get(mp, src, &np->dp_nslots, &np->dp_slotnames) < 0) {
2827aec1d6eScindi 		if (np->dp_physlot_label != NULL)
2837aec1d6eScindi 			topo_mod_strfree(mp, np->dp_physlot_label);
2847aec1d6eScindi 		topo_mod_free(mp, np, sizeof (did_t));
2857aec1d6eScindi 		return (NULL);
2867aec1d6eScindi 	}
287*0eb822a1Scindi 	did_hash_insert(mp, src, np);
2887aec1d6eScindi 	did_hold(np);
2897aec1d6eScindi 	return (np);
2907aec1d6eScindi }
2917aec1d6eScindi 
2927aec1d6eScindi did_t *
2937aec1d6eScindi did_link_get(did_t *dp)
2947aec1d6eScindi {
2957aec1d6eScindi 	assert(dp != NULL);
2967aec1d6eScindi 	return (dp->dp_link);
2977aec1d6eScindi }
2987aec1d6eScindi 
2997aec1d6eScindi did_t *
3007aec1d6eScindi did_chain_get(did_t *dp)
3017aec1d6eScindi {
3027aec1d6eScindi 	assert(dp != NULL);
3037aec1d6eScindi 	return (dp->dp_chain);
3047aec1d6eScindi }
3057aec1d6eScindi 
3067aec1d6eScindi void
307*0eb822a1Scindi did_link_set(topo_mod_t *mod, tnode_t *head, did_t *tail)
3087aec1d6eScindi {
3097aec1d6eScindi 	did_t *hd, *pd;
3107aec1d6eScindi 
3117aec1d6eScindi 	assert(head != NULL);
312*0eb822a1Scindi 	pd = hd = did_find(mod, topo_node_getspecific(head));
3137aec1d6eScindi 	assert(hd != NULL);
3147aec1d6eScindi 	while ((hd = did_link_get(hd)) != NULL)
3157aec1d6eScindi 		pd = hd;
3167aec1d6eScindi 	pd->dp_link = tail;
3177aec1d6eScindi 	tail->dp_link = NULL;
3187aec1d6eScindi }
3197aec1d6eScindi 
3207aec1d6eScindi void
3217aec1d6eScindi did_did_link_set(did_t *from, did_t *to)
3227aec1d6eScindi {
3237aec1d6eScindi 	assert(from != NULL && to != NULL);
3247aec1d6eScindi 	from->dp_link = to;
3257aec1d6eScindi }
3267aec1d6eScindi 
3277aec1d6eScindi void
3287aec1d6eScindi did_did_chain_set(did_t *from, did_t *to)
3297aec1d6eScindi {
3307aec1d6eScindi 	assert(from != NULL && to != NULL);
3317aec1d6eScindi 	from->dp_chain = to;
3327aec1d6eScindi }
3337aec1d6eScindi 
3347aec1d6eScindi void
3357aec1d6eScindi did_destroy(did_t *dp)
3367aec1d6eScindi {
3377aec1d6eScindi 	assert(dp != NULL);
3387aec1d6eScindi 
3397aec1d6eScindi 	/*
3407aec1d6eScindi 	 * did_destroy() is called only from did_hash_destroy() when
3417aec1d6eScindi 	 * all references to the did_t have been released.  We can
3427aec1d6eScindi 	 * safely destroy the did_t.  If at some later time, more
3437aec1d6eScindi 	 * fine-grained reference count control is desired, this
3447aec1d6eScindi 	 * code will need to change
3457aec1d6eScindi 	 */
3467aec1d6eScindi 
3477aec1d6eScindi 	if (dp->dp_physlot_label != NULL)
3487aec1d6eScindi 		topo_mod_strfree(dp->dp_mod, dp->dp_physlot_label);
3497aec1d6eScindi 	slotnm_destroy(dp->dp_slotnames);
3507aec1d6eScindi 	topo_mod_free(dp->dp_mod, dp, sizeof (did_t));
3517aec1d6eScindi }
3527aec1d6eScindi 
3537aec1d6eScindi void
3547aec1d6eScindi did_hold(did_t *dp)
3557aec1d6eScindi {
3567aec1d6eScindi 	assert(dp != NULL);
3577aec1d6eScindi 	dp->dp_refcnt++;
3587aec1d6eScindi }
3597aec1d6eScindi 
3607aec1d6eScindi void
3617aec1d6eScindi did_rele(did_t *dp)
3627aec1d6eScindi {
3637aec1d6eScindi 	assert(dp != NULL);
3647aec1d6eScindi 	assert(dp->dp_refcnt > 0);
3657aec1d6eScindi 	dp->dp_refcnt--;
3667aec1d6eScindi }
3677aec1d6eScindi 
3687aec1d6eScindi di_node_t
3697aec1d6eScindi did_dinode(did_t *dp)
3707aec1d6eScindi {
3717aec1d6eScindi 	assert(dp != NULL);
3727aec1d6eScindi 	assert(dp->dp_src != NULL);
3737aec1d6eScindi 	return (dp->dp_src);
3747aec1d6eScindi }
3757aec1d6eScindi 
3767aec1d6eScindi topo_mod_t *
3777aec1d6eScindi did_mod(did_t *dp)
3787aec1d6eScindi {
3797aec1d6eScindi 	assert(dp != NULL);
3807aec1d6eScindi 	return (dp->dp_mod);
3817aec1d6eScindi }
3827aec1d6eScindi 
3837aec1d6eScindi void
3847aec1d6eScindi did_markrc(did_t *dp)
3857aec1d6eScindi {
3867aec1d6eScindi 	assert(dp != NULL);
3877aec1d6eScindi 	dp->dp_excap |= PCIE_PCIECAP_DEV_TYPE_ROOT;
3887aec1d6eScindi }
3897aec1d6eScindi 
3907aec1d6eScindi void
3917aec1d6eScindi did_BDF(did_t *dp, int *bus, int *dev, int *fn)
3927aec1d6eScindi {
3937aec1d6eScindi 	assert(dp != NULL);
3947aec1d6eScindi 	if (bus != NULL)
3957aec1d6eScindi 		*bus = dp->dp_bus;
3967aec1d6eScindi 	if (dev != NULL)
3977aec1d6eScindi 		*dev = dp->dp_dev;
3987aec1d6eScindi 	if (fn != NULL)
3997aec1d6eScindi 		*fn = dp->dp_fn;
4007aec1d6eScindi }
4017aec1d6eScindi 
4027aec1d6eScindi int
4037aec1d6eScindi did_board(did_t *did)
4047aec1d6eScindi {
4057aec1d6eScindi 	assert(did != NULL);
4067aec1d6eScindi 	return (did->dp_board);
4077aec1d6eScindi }
4087aec1d6eScindi 
4097aec1d6eScindi int
4107aec1d6eScindi did_bridge(did_t *did)
4117aec1d6eScindi {
4127aec1d6eScindi 	assert(did != NULL);
4137aec1d6eScindi 	return (did->dp_bridge);
4147aec1d6eScindi }
4157aec1d6eScindi 
4167aec1d6eScindi int
4177aec1d6eScindi did_rc(did_t *did)
4187aec1d6eScindi {
4197aec1d6eScindi 	assert(did != NULL);
4207aec1d6eScindi 	return (did->dp_rc);
4217aec1d6eScindi }
4227aec1d6eScindi 
4237aec1d6eScindi static int
4247aec1d6eScindi did_numlabels(did_t *dp)
4257aec1d6eScindi {
4267aec1d6eScindi 	assert(dp != NULL);
4277aec1d6eScindi 	return (dp->dp_nslots);
4287aec1d6eScindi }
4297aec1d6eScindi 
4307aec1d6eScindi int
4317aec1d6eScindi did_excap(did_t *dp)
4327aec1d6eScindi {
4337aec1d6eScindi 	assert(dp != NULL);
4347aec1d6eScindi 	return ((int)dp->dp_excap);
4357aec1d6eScindi }
4367aec1d6eScindi 
43700d0963fSdilpreet int
43800d0963fSdilpreet did_bdf(did_t *dp)
43900d0963fSdilpreet {
44000d0963fSdilpreet 	assert(dp != NULL);
44100d0963fSdilpreet 	return ((int)dp->dp_bdf);
44200d0963fSdilpreet }
44300d0963fSdilpreet 
4447aec1d6eScindi const char *
4457aec1d6eScindi did_label(did_t *dp, int dev)
4467aec1d6eScindi {
4477aec1d6eScindi 	slotnm_t *slot;
4487aec1d6eScindi 
4497aec1d6eScindi 	assert(dp != NULL);
4507aec1d6eScindi 	if (dp->dp_physlot_label != NULL)
4517aec1d6eScindi 		return (dp->dp_physlot_label);
4527aec1d6eScindi 	for (slot = dp->dp_slotnames; slot != NULL; slot = slot->snm_next)
4537aec1d6eScindi 		if (slot->snm_dev == dev)
4547aec1d6eScindi 			break;
4557aec1d6eScindi 	if (slot != NULL)
4567aec1d6eScindi 		return (slot->snm_label);
4577aec1d6eScindi 	return (NULL);
4587aec1d6eScindi }
4597aec1d6eScindi 
4607aec1d6eScindi did_t *
461*0eb822a1Scindi did_find(topo_mod_t *mp, di_node_t dn)
4627aec1d6eScindi {
463*0eb822a1Scindi 	return (did_hash_lookup(mp, dn));
4647aec1d6eScindi }
4657aec1d6eScindi 
4667aec1d6eScindi int
467*0eb822a1Scindi pci_BDF_get(topo_mod_t *mp, di_node_t dn, int *bus, int *dev, int *fn)
4687aec1d6eScindi {
4697aec1d6eScindi 	did_t *dp;
4707aec1d6eScindi 
471*0eb822a1Scindi 	if ((dp = did_find(mp, dn)) == NULL)
4727aec1d6eScindi 		return (-1);
4737aec1d6eScindi 	*bus = dp->dp_bus;
4747aec1d6eScindi 	*dev = dp->dp_dev;
4757aec1d6eScindi 	*fn = dp->dp_fn;
4767aec1d6eScindi 	did_rele(dp);
4777aec1d6eScindi 	return (0);
4787aec1d6eScindi }
4797aec1d6eScindi 
4807aec1d6eScindi int
481*0eb822a1Scindi pci_classcode_get(topo_mod_t *mp, di_node_t dn, uint_t *class, uint_t *sub)
4827aec1d6eScindi {
4837aec1d6eScindi 	did_t *dp;
4847aec1d6eScindi 
485*0eb822a1Scindi 	if ((dp = did_find(mp, dn)) == NULL)
4867aec1d6eScindi 		return (-1);
4877aec1d6eScindi 	if (dp->dp_class < 0) {
4887aec1d6eScindi 		did_rele(dp);
4897aec1d6eScindi 		return (-1);
4907aec1d6eScindi 	}
4917aec1d6eScindi 	*class = dp->dp_class;
4927aec1d6eScindi 	*sub = dp->dp_subclass;
4937aec1d6eScindi 	did_rele(dp);
4947aec1d6eScindi 	return (0);
4957aec1d6eScindi }
4967aec1d6eScindi 
4977aec1d6eScindi int
498*0eb822a1Scindi pciex_cap_get(topo_mod_t *mp, di_node_t dn)
4997aec1d6eScindi {
5007aec1d6eScindi 	did_t *dp;
5017aec1d6eScindi 
502*0eb822a1Scindi 	if ((dp = did_find(mp, dn)) == NULL)
5037aec1d6eScindi 		return (-1);
5047aec1d6eScindi 	did_rele(dp);
5057aec1d6eScindi 	return (dp->dp_excap);
5067aec1d6eScindi }
5077aec1d6eScindi 
5087aec1d6eScindi int
5090b6016e6Shueston did_inherit(did_t *pdp, did_t *dp)
5107aec1d6eScindi {
5117aec1d6eScindi 	/*
5127aec1d6eScindi 	 * If the child already has a label, we're done.
5137aec1d6eScindi 	 */
5147aec1d6eScindi 	assert(dp != NULL);
5157aec1d6eScindi 	if (did_numlabels(dp) > 0)
5167aec1d6eScindi 		return (0);
5177aec1d6eScindi 
5187aec1d6eScindi 	assert(pdp != NULL);
5197aec1d6eScindi 
5207aec1d6eScindi 	/*
5217aec1d6eScindi 	 * If the child and parent are the same, we're done.
5227aec1d6eScindi 	 */
5237aec1d6eScindi 	if (dp == pdp)
5247aec1d6eScindi 		return (0);
5257aec1d6eScindi 
5267aec1d6eScindi 	if (pdp->dp_physlot_label != NULL) {
5277aec1d6eScindi 		topo_mod_dprintf(dp->dp_mod,
5287aec1d6eScindi 		    "%p inherits physlot label from %p.\n", dp, pdp);
5297aec1d6eScindi 		dp->dp_physlot_label =
5307aec1d6eScindi 		    topo_mod_strdup(dp->dp_mod, pdp->dp_physlot_label);
5317aec1d6eScindi 		if (dp->dp_physlot_label == NULL)
5327aec1d6eScindi 			return (-1);
5337aec1d6eScindi 	}
5347aec1d6eScindi 	if (slotnm_cp(pdp, dp, &dp->dp_nslots) < 0)
5357aec1d6eScindi 		return (-1);
5367aec1d6eScindi 	return (0);
5377aec1d6eScindi }
538*0eb822a1Scindi 
539*0eb822a1Scindi void
540*0eb822a1Scindi did_setspecific(topo_mod_t *mp, void *data)
541*0eb822a1Scindi {
542*0eb822a1Scindi 	did_t *hbdid;
543*0eb822a1Scindi 
544*0eb822a1Scindi 	hbdid = (did_t *)data;
545*0eb822a1Scindi 	topo_mod_setspecific(mp, hbdid->dp_hash);
546*0eb822a1Scindi }
547