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 /* 23*40e5e17bSzx * Copyright 2007 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> 430eb822a1Scindi #include <fm/topo_mod.h> 447aec1d6eScindi #include <libnvpair.h> 457aec1d6eScindi #include <libdevinfo.h> 467aec1d6eScindi #include <sys/pcie.h> 477aec1d6eScindi 480eb822a1Scindi #include <hostbridge.h> 490eb822a1Scindi #include <pcibus.h> 500eb822a1Scindi #include <did_props.h> 510eb822a1Scindi 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, 1180eb822a1Scindi int *slotnum, char **slotnm) 1197aec1d6eScindi { 1207aec1d6eScindi char *slotbuf; 1210b6016e6Shueston int sz; 1220b6016e6Shueston uchar_t *buf; 1237aec1d6eScindi 1247aec1d6eScindi *slotnum = -1; 1250eb822a1Scindi (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; 1340eb822a1Scindi 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 */ 1460eb822a1Scindi 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 1640eb822a1Scindi 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; 1760eb822a1Scindi 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 * 2150eb822a1Scindi did_create(topo_mod_t *mp, di_node_t src, 2160eb822a1Scindi 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 2230eb822a1Scindi 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; 2330eb822a1Scindi np->dp_hash = (did_hash_t *)topo_mod_getspecific(mp); 234*40e5e17bSzx np->dp_tnode = NULL; 2357aec1d6eScindi 2367aec1d6eScindi /* 2377aec1d6eScindi * We must have a reg prop and from it we extract the bus #, 2387aec1d6eScindi * device #, and function #. 2397aec1d6eScindi */ 2400eb822a1Scindi if (di_uintprop_get(mp, src, DI_REGPROP, ®) < 0) { 2417aec1d6eScindi topo_mod_free(mp, np, sizeof (did_t)); 2427aec1d6eScindi return (NULL); 2437aec1d6eScindi } 2447aec1d6eScindi np->dp_board = ibrd; 2457aec1d6eScindi np->dp_bridge = ibrdge; 2467aec1d6eScindi np->dp_rc = irc; 2477aec1d6eScindi if (ibus == TRUST_BDF) 2487aec1d6eScindi np->dp_bus = PCI_REG_BUS_G(reg); 2497aec1d6eScindi else 2507aec1d6eScindi np->dp_bus = ibus; 2517aec1d6eScindi np->dp_dev = PCI_REG_DEV_G(reg); 2527aec1d6eScindi np->dp_fn = PCI_REG_FUNC_G(reg); 25300d0963fSdilpreet np->dp_bdf = (PCI_REG_BUS_G(reg) << 8) | (PCI_REG_DEV_G(reg) << 3) | 25400d0963fSdilpreet PCI_REG_FUNC_G(reg); 2557aec1d6eScindi /* 2567aec1d6eScindi * There *may* be a class code we can capture. If there wasn't 2577aec1d6eScindi * one, capture that fact by setting the class value to -1. 2587aec1d6eScindi */ 2590eb822a1Scindi if (di_uintprop_get(mp, src, DI_CCPROP, &code) == 0) { 2607aec1d6eScindi np->dp_class = GETCLASS(code); 2617aec1d6eScindi np->dp_subclass = GETSUBCLASS(code); 2627aec1d6eScindi } else { 2637aec1d6eScindi np->dp_class = -1; 2647aec1d6eScindi } 2657aec1d6eScindi /* 2667aec1d6eScindi * There *may* be a PCI-express capabilities register we can capture. 2677aec1d6eScindi * If there wasn't one, the capabilities will be the out-of-bounds 2687aec1d6eScindi * value of zero. 2697aec1d6eScindi */ 2700eb822a1Scindi (void) di_uintprop_get(mp, src, "pcie-capid-reg", &np->dp_excap); 2717aec1d6eScindi /* 2727aec1d6eScindi * There *may* be a physical slot number property we can capture. 2737aec1d6eScindi */ 2747aec1d6eScindi if (di_physlotinfo_get(mp, 2750eb822a1Scindi src, np->dp_excap, &np->dp_physlot, &np->dp_physlot_label) < 0) { 2767aec1d6eScindi topo_mod_free(mp, np, sizeof (did_t)); 2777aec1d6eScindi return (NULL); 2787aec1d6eScindi } 2797aec1d6eScindi /* 2807aec1d6eScindi * There *may* be PCI slot info we can capture 2817aec1d6eScindi */ 2820eb822a1Scindi if (di_slotinfo_get(mp, src, &np->dp_nslots, &np->dp_slotnames) < 0) { 2837aec1d6eScindi if (np->dp_physlot_label != NULL) 2847aec1d6eScindi topo_mod_strfree(mp, np->dp_physlot_label); 2857aec1d6eScindi topo_mod_free(mp, np, sizeof (did_t)); 2867aec1d6eScindi return (NULL); 2877aec1d6eScindi } 2880eb822a1Scindi did_hash_insert(mp, src, np); 2897aec1d6eScindi did_hold(np); 2907aec1d6eScindi return (np); 2917aec1d6eScindi } 2927aec1d6eScindi 2937aec1d6eScindi did_t * 2947aec1d6eScindi did_link_get(did_t *dp) 2957aec1d6eScindi { 2967aec1d6eScindi assert(dp != NULL); 2977aec1d6eScindi return (dp->dp_link); 2987aec1d6eScindi } 2997aec1d6eScindi 3007aec1d6eScindi did_t * 3017aec1d6eScindi did_chain_get(did_t *dp) 3027aec1d6eScindi { 3037aec1d6eScindi assert(dp != NULL); 3047aec1d6eScindi return (dp->dp_chain); 3057aec1d6eScindi } 3067aec1d6eScindi 3077aec1d6eScindi void 3080eb822a1Scindi did_link_set(topo_mod_t *mod, tnode_t *head, did_t *tail) 3097aec1d6eScindi { 3107aec1d6eScindi did_t *hd, *pd; 3117aec1d6eScindi 3127aec1d6eScindi assert(head != NULL); 3130eb822a1Scindi pd = hd = did_find(mod, topo_node_getspecific(head)); 3147aec1d6eScindi assert(hd != NULL); 3157aec1d6eScindi while ((hd = did_link_get(hd)) != NULL) 3167aec1d6eScindi pd = hd; 3177aec1d6eScindi pd->dp_link = tail; 3187aec1d6eScindi tail->dp_link = NULL; 3197aec1d6eScindi } 3207aec1d6eScindi 3217aec1d6eScindi void 3227aec1d6eScindi did_did_link_set(did_t *from, did_t *to) 3237aec1d6eScindi { 3247aec1d6eScindi assert(from != NULL && to != NULL); 3257aec1d6eScindi from->dp_link = to; 3267aec1d6eScindi } 3277aec1d6eScindi 3287aec1d6eScindi void 3297aec1d6eScindi did_did_chain_set(did_t *from, did_t *to) 3307aec1d6eScindi { 3317aec1d6eScindi assert(from != NULL && to != NULL); 3327aec1d6eScindi from->dp_chain = to; 3337aec1d6eScindi } 3347aec1d6eScindi 3357aec1d6eScindi void 3367aec1d6eScindi did_destroy(did_t *dp) 3377aec1d6eScindi { 3387aec1d6eScindi assert(dp != NULL); 3397aec1d6eScindi 3407aec1d6eScindi /* 3417aec1d6eScindi * did_destroy() is called only from did_hash_destroy() when 3427aec1d6eScindi * all references to the did_t have been released. We can 3437aec1d6eScindi * safely destroy the did_t. If at some later time, more 3447aec1d6eScindi * fine-grained reference count control is desired, this 3457aec1d6eScindi * code will need to change 3467aec1d6eScindi */ 3477aec1d6eScindi 3487aec1d6eScindi if (dp->dp_physlot_label != NULL) 3497aec1d6eScindi topo_mod_strfree(dp->dp_mod, dp->dp_physlot_label); 3507aec1d6eScindi slotnm_destroy(dp->dp_slotnames); 3517aec1d6eScindi topo_mod_free(dp->dp_mod, dp, sizeof (did_t)); 3527aec1d6eScindi } 3537aec1d6eScindi 3547aec1d6eScindi void 3557aec1d6eScindi did_hold(did_t *dp) 3567aec1d6eScindi { 3577aec1d6eScindi assert(dp != NULL); 3587aec1d6eScindi dp->dp_refcnt++; 3597aec1d6eScindi } 3607aec1d6eScindi 3617aec1d6eScindi void 3627aec1d6eScindi did_rele(did_t *dp) 3637aec1d6eScindi { 3647aec1d6eScindi assert(dp != NULL); 3657aec1d6eScindi assert(dp->dp_refcnt > 0); 3667aec1d6eScindi dp->dp_refcnt--; 3677aec1d6eScindi } 3687aec1d6eScindi 3697aec1d6eScindi di_node_t 3707aec1d6eScindi did_dinode(did_t *dp) 3717aec1d6eScindi { 3727aec1d6eScindi assert(dp != NULL); 3737aec1d6eScindi assert(dp->dp_src != NULL); 3747aec1d6eScindi return (dp->dp_src); 3757aec1d6eScindi } 3767aec1d6eScindi 3777aec1d6eScindi topo_mod_t * 3787aec1d6eScindi did_mod(did_t *dp) 3797aec1d6eScindi { 3807aec1d6eScindi assert(dp != NULL); 3817aec1d6eScindi return (dp->dp_mod); 3827aec1d6eScindi } 3837aec1d6eScindi 3847aec1d6eScindi void 3857aec1d6eScindi did_markrc(did_t *dp) 3867aec1d6eScindi { 3877aec1d6eScindi assert(dp != NULL); 3887aec1d6eScindi dp->dp_excap |= PCIE_PCIECAP_DEV_TYPE_ROOT; 3897aec1d6eScindi } 3907aec1d6eScindi 3917aec1d6eScindi void 3927aec1d6eScindi did_BDF(did_t *dp, int *bus, int *dev, int *fn) 3937aec1d6eScindi { 3947aec1d6eScindi assert(dp != NULL); 3957aec1d6eScindi if (bus != NULL) 3967aec1d6eScindi *bus = dp->dp_bus; 3977aec1d6eScindi if (dev != NULL) 3987aec1d6eScindi *dev = dp->dp_dev; 3997aec1d6eScindi if (fn != NULL) 4007aec1d6eScindi *fn = dp->dp_fn; 4017aec1d6eScindi } 4027aec1d6eScindi 4037aec1d6eScindi int 4047aec1d6eScindi did_board(did_t *did) 4057aec1d6eScindi { 4067aec1d6eScindi assert(did != NULL); 4077aec1d6eScindi return (did->dp_board); 4087aec1d6eScindi } 4097aec1d6eScindi 4107aec1d6eScindi int 4117aec1d6eScindi did_bridge(did_t *did) 4127aec1d6eScindi { 4137aec1d6eScindi assert(did != NULL); 4147aec1d6eScindi return (did->dp_bridge); 4157aec1d6eScindi } 4167aec1d6eScindi 4177aec1d6eScindi int 4187aec1d6eScindi did_rc(did_t *did) 4197aec1d6eScindi { 4207aec1d6eScindi assert(did != NULL); 4217aec1d6eScindi return (did->dp_rc); 4227aec1d6eScindi } 4237aec1d6eScindi 4247aec1d6eScindi static int 4257aec1d6eScindi did_numlabels(did_t *dp) 4267aec1d6eScindi { 4277aec1d6eScindi assert(dp != NULL); 4287aec1d6eScindi return (dp->dp_nslots); 4297aec1d6eScindi } 4307aec1d6eScindi 4317aec1d6eScindi int 4327aec1d6eScindi did_excap(did_t *dp) 4337aec1d6eScindi { 4347aec1d6eScindi assert(dp != NULL); 4357aec1d6eScindi return ((int)dp->dp_excap); 4367aec1d6eScindi } 4377aec1d6eScindi 43800d0963fSdilpreet int 43900d0963fSdilpreet did_bdf(did_t *dp) 44000d0963fSdilpreet { 44100d0963fSdilpreet assert(dp != NULL); 44200d0963fSdilpreet return ((int)dp->dp_bdf); 44300d0963fSdilpreet } 44400d0963fSdilpreet 4457aec1d6eScindi const char * 4467aec1d6eScindi did_label(did_t *dp, int dev) 4477aec1d6eScindi { 4487aec1d6eScindi slotnm_t *slot; 4497aec1d6eScindi 4507aec1d6eScindi assert(dp != NULL); 4517aec1d6eScindi if (dp->dp_physlot_label != NULL) 4527aec1d6eScindi return (dp->dp_physlot_label); 4537aec1d6eScindi for (slot = dp->dp_slotnames; slot != NULL; slot = slot->snm_next) 4547aec1d6eScindi if (slot->snm_dev == dev) 4557aec1d6eScindi break; 4567aec1d6eScindi if (slot != NULL) 4577aec1d6eScindi return (slot->snm_label); 4587aec1d6eScindi return (NULL); 4597aec1d6eScindi } 4607aec1d6eScindi 4617aec1d6eScindi did_t * 4620eb822a1Scindi did_find(topo_mod_t *mp, di_node_t dn) 4637aec1d6eScindi { 4640eb822a1Scindi return (did_hash_lookup(mp, dn)); 4657aec1d6eScindi } 4667aec1d6eScindi 4677aec1d6eScindi int 4680eb822a1Scindi pci_BDF_get(topo_mod_t *mp, di_node_t dn, int *bus, int *dev, int *fn) 4697aec1d6eScindi { 4707aec1d6eScindi did_t *dp; 4717aec1d6eScindi 4720eb822a1Scindi if ((dp = did_find(mp, dn)) == NULL) 4737aec1d6eScindi return (-1); 4747aec1d6eScindi *bus = dp->dp_bus; 4757aec1d6eScindi *dev = dp->dp_dev; 4767aec1d6eScindi *fn = dp->dp_fn; 4777aec1d6eScindi did_rele(dp); 4787aec1d6eScindi return (0); 4797aec1d6eScindi } 4807aec1d6eScindi 4817aec1d6eScindi int 4820eb822a1Scindi pci_classcode_get(topo_mod_t *mp, di_node_t dn, uint_t *class, uint_t *sub) 4837aec1d6eScindi { 4847aec1d6eScindi did_t *dp; 4857aec1d6eScindi 4860eb822a1Scindi if ((dp = did_find(mp, dn)) == NULL) 4877aec1d6eScindi return (-1); 4887aec1d6eScindi if (dp->dp_class < 0) { 4897aec1d6eScindi did_rele(dp); 4907aec1d6eScindi return (-1); 4917aec1d6eScindi } 4927aec1d6eScindi *class = dp->dp_class; 4937aec1d6eScindi *sub = dp->dp_subclass; 4947aec1d6eScindi did_rele(dp); 4957aec1d6eScindi return (0); 4967aec1d6eScindi } 4977aec1d6eScindi 4987aec1d6eScindi int 4990eb822a1Scindi pciex_cap_get(topo_mod_t *mp, di_node_t dn) 5007aec1d6eScindi { 5017aec1d6eScindi did_t *dp; 5027aec1d6eScindi 5030eb822a1Scindi if ((dp = did_find(mp, dn)) == NULL) 5047aec1d6eScindi return (-1); 5057aec1d6eScindi did_rele(dp); 5067aec1d6eScindi return (dp->dp_excap); 5077aec1d6eScindi } 5087aec1d6eScindi 5097aec1d6eScindi int 5100b6016e6Shueston did_inherit(did_t *pdp, did_t *dp) 5117aec1d6eScindi { 5127aec1d6eScindi /* 5137aec1d6eScindi * If the child already has a label, we're done. 5147aec1d6eScindi */ 5157aec1d6eScindi assert(dp != NULL); 5167aec1d6eScindi if (did_numlabels(dp) > 0) 5177aec1d6eScindi return (0); 5187aec1d6eScindi 5197aec1d6eScindi assert(pdp != NULL); 5207aec1d6eScindi 5217aec1d6eScindi /* 5227aec1d6eScindi * If the child and parent are the same, we're done. 5237aec1d6eScindi */ 5247aec1d6eScindi if (dp == pdp) 5257aec1d6eScindi return (0); 5267aec1d6eScindi 5277aec1d6eScindi if (pdp->dp_physlot_label != NULL) { 5287aec1d6eScindi topo_mod_dprintf(dp->dp_mod, 5297aec1d6eScindi "%p inherits physlot label from %p.\n", dp, pdp); 5307aec1d6eScindi dp->dp_physlot_label = 5317aec1d6eScindi topo_mod_strdup(dp->dp_mod, pdp->dp_physlot_label); 5327aec1d6eScindi if (dp->dp_physlot_label == NULL) 5337aec1d6eScindi return (-1); 5347aec1d6eScindi } 5357aec1d6eScindi if (slotnm_cp(pdp, dp, &dp->dp_nslots) < 0) 5367aec1d6eScindi return (-1); 5377aec1d6eScindi return (0); 5387aec1d6eScindi } 5390eb822a1Scindi 5400eb822a1Scindi void 5410eb822a1Scindi did_setspecific(topo_mod_t *mp, void *data) 5420eb822a1Scindi { 5430eb822a1Scindi did_t *hbdid; 5440eb822a1Scindi 5450eb822a1Scindi hbdid = (did_t *)data; 5460eb822a1Scindi topo_mod_setspecific(mp, hbdid->dp_hash); 5470eb822a1Scindi } 548*40e5e17bSzx 549*40e5e17bSzx void 550*40e5e17bSzx did_settnode(did_t *pd, tnode_t *tn) 551*40e5e17bSzx { 552*40e5e17bSzx assert(tn != NULL); 553*40e5e17bSzx pd->dp_tnode = tn; 554*40e5e17bSzx } 555*40e5e17bSzx 556*40e5e17bSzx tnode_t * 557*40e5e17bSzx did_gettnode(did_t *pd) 558*40e5e17bSzx { 559*40e5e17bSzx return (pd->dp_tnode); 560*40e5e17bSzx } 561