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*0db3240dSStephen Hanson * Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved. 247aec1d6eScindi */ 257aec1d6eScindi 267aec1d6eScindi /* 277aec1d6eScindi * did.c 287aec1d6eScindi * The acronym did means "Dev-Info-Data". Many properties and 297aec1d6eScindi * characteristics of topology nodes are, with a bit of coaxing 307aec1d6eScindi * derived from devinfo nodes. These routines do some of the 317aec1d6eScindi * derivation and also encapsulate the discoveries in did_t 327aec1d6eScindi * structures that get associated with topology nodes as their 337aec1d6eScindi * "private" data. 347aec1d6eScindi */ 357aec1d6eScindi #include <alloca.h> 367aec1d6eScindi #include <assert.h> 377aec1d6eScindi #include <string.h> 387aec1d6eScindi #include <strings.h> 397aec1d6eScindi #include <sys/types.h> 400eb822a1Scindi #include <fm/topo_mod.h> 417aec1d6eScindi #include <libnvpair.h> 427aec1d6eScindi #include <libdevinfo.h> 437aec1d6eScindi #include <sys/pcie.h> 447aec1d6eScindi 450eb822a1Scindi #include <hostbridge.h> 460eb822a1Scindi #include <pcibus.h> 470eb822a1Scindi #include <did_props.h> 480eb822a1Scindi 497aec1d6eScindi #include "did_impl.h" 507aec1d6eScindi 517aec1d6eScindi static void slotnm_destroy(slotnm_t *); 527aec1d6eScindi 537aec1d6eScindi static slotnm_t * 547aec1d6eScindi slotnm_create(topo_mod_t *mp, int dev, char *str) 557aec1d6eScindi { 567aec1d6eScindi slotnm_t *p; 577aec1d6eScindi 587aec1d6eScindi if ((p = topo_mod_alloc(mp, sizeof (slotnm_t))) == NULL) 597aec1d6eScindi return (NULL); 607aec1d6eScindi p->snm_mod = mp; 617aec1d6eScindi p->snm_next = NULL; 627aec1d6eScindi p->snm_dev = dev; 6360348818STarik Soydan p->snm_name = topo_mod_strdup(mp, str); 6460348818STarik Soydan if (p->snm_name == NULL) { 657aec1d6eScindi slotnm_destroy(p); 667aec1d6eScindi return (NULL); 677aec1d6eScindi } 687aec1d6eScindi return (p); 697aec1d6eScindi } 707aec1d6eScindi 717aec1d6eScindi static void 727aec1d6eScindi slotnm_destroy(slotnm_t *p) 737aec1d6eScindi { 747aec1d6eScindi if (p == NULL) 757aec1d6eScindi return; 767aec1d6eScindi slotnm_destroy(p->snm_next); 7760348818STarik Soydan if (p->snm_name != NULL) 7860348818STarik Soydan topo_mod_strfree(p->snm_mod, p->snm_name); 797aec1d6eScindi topo_mod_free(p->snm_mod, p, sizeof (slotnm_t)); 807aec1d6eScindi } 817aec1d6eScindi 827aec1d6eScindi static int 8349fbdd30SErwin T Tsaur di_devtype_get(topo_mod_t *mp, di_node_t src, char **devtype) 847aec1d6eScindi { 850b6016e6Shueston int sz; 860b6016e6Shueston uchar_t *buf; 877aec1d6eScindi 887aec1d6eScindi /* 8949fbdd30SErwin T Tsaur * For PCI the device type defined the type of device directly below. 9049fbdd30SErwin T Tsaur * For PCIe RP and Switches, the device-type should be "pciex". For 9149fbdd30SErwin T Tsaur * PCIe-PCI and PCI-PCI bridges it should be "pci". NICs = "network", 9249fbdd30SErwin T Tsaur * Graphics = "display", etc.. 937aec1d6eScindi */ 9449fbdd30SErwin T Tsaur if (di_bytes_get(mp, src, DI_DEVTYPPROP, &sz, &buf) == 0) { 9549fbdd30SErwin T Tsaur *devtype = topo_mod_strdup(mp, (char *)buf); 9649fbdd30SErwin T Tsaur } else { 9749fbdd30SErwin T Tsaur *devtype = NULL; 987aec1d6eScindi } 9949fbdd30SErwin T Tsaur 10049fbdd30SErwin T Tsaur if (*devtype != NULL) 10149fbdd30SErwin T Tsaur return (0); 10249fbdd30SErwin T Tsaur return (-1); 10349fbdd30SErwin T Tsaur } 10449fbdd30SErwin T Tsaur 105*0db3240dSStephen Hanson typedef struct smbios_slot_cb { 106*0db3240dSStephen Hanson int cb_slotnum; 107*0db3240dSStephen Hanson const char *cb_label; 108*0db3240dSStephen Hanson } smbios_slot_cb_t; 109*0db3240dSStephen Hanson 110*0db3240dSStephen Hanson static int 111*0db3240dSStephen Hanson di_smbios_find_slot(smbios_hdl_t *shp, const smbios_struct_t *strp, void *data) 112*0db3240dSStephen Hanson { 113*0db3240dSStephen Hanson smbios_slot_cb_t *cbp = data; 114*0db3240dSStephen Hanson smbios_slot_t slot; 115*0db3240dSStephen Hanson 116*0db3240dSStephen Hanson if (strp->smbstr_type != SMB_TYPE_SLOT || 117*0db3240dSStephen Hanson smbios_info_slot(shp, strp->smbstr_id, &slot) != 0) 118*0db3240dSStephen Hanson return (0); 119*0db3240dSStephen Hanson 120*0db3240dSStephen Hanson if (slot.smbl_id == cbp->cb_slotnum) { 121*0db3240dSStephen Hanson cbp->cb_label = slot.smbl_name; 122*0db3240dSStephen Hanson return (1); 123*0db3240dSStephen Hanson } 124*0db3240dSStephen Hanson 125*0db3240dSStephen Hanson return (0); 126*0db3240dSStephen Hanson } 127*0db3240dSStephen Hanson 12849fbdd30SErwin T Tsaur static int 12960348818STarik Soydan di_physlotinfo_get(topo_mod_t *mp, di_node_t src, int *slotnum, char **slotname) 13049fbdd30SErwin T Tsaur { 13149fbdd30SErwin T Tsaur char *slotbuf; 13249fbdd30SErwin T Tsaur int sz; 13349fbdd30SErwin T Tsaur uchar_t *buf; 134*0db3240dSStephen Hanson smbios_hdl_t *shp; 135*0db3240dSStephen Hanson boolean_t got_slotprop = B_FALSE; 13649fbdd30SErwin T Tsaur 13749fbdd30SErwin T Tsaur *slotnum = -1; 13860348818STarik Soydan 139*0db3240dSStephen Hanson (void) di_uintprop_get(mp, src, DI_PHYSPROP, (uint_t *)slotnum); 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) { 148*0db3240dSStephen Hanson /* 149*0db3240dSStephen Hanson * If there is a DI_SLOTPROP of the form SlotX (ie set up from 150*0db3240dSStephen Hanson * the IRQ routing table) then trust that in preference to 151*0db3240dSStephen Hanson * DI_PHYSPROP (which is set up from the PCIe slotcap reg). 152*0db3240dSStephen Hanson */ 153*0db3240dSStephen Hanson got_slotprop = B_TRUE; 154*0db3240dSStephen Hanson (void) sscanf((char *)&buf[4], "Slot%d", slotnum); 155*0db3240dSStephen Hanson } 156*0db3240dSStephen Hanson 157*0db3240dSStephen Hanson if (*slotnum == -1) 158*0db3240dSStephen Hanson return (0); 159*0db3240dSStephen Hanson 160*0db3240dSStephen Hanson /* 161*0db3240dSStephen Hanson * Order of preference 162*0db3240dSStephen Hanson * 1) take slotnum and look up in SMBIOS table 163*0db3240dSStephen Hanson * 2) use slot-names 164*0db3240dSStephen Hanson * 3) fabricate name based on slotnum 165*0db3240dSStephen Hanson */ 166*0db3240dSStephen Hanson if ((shp = topo_mod_smbios(mp)) != NULL) { 167*0db3240dSStephen Hanson /* 168*0db3240dSStephen Hanson * The PCI spec describes slot number 0 as reserved for 169*0db3240dSStephen Hanson * internal PCI devices. Not all platforms respect 170*0db3240dSStephen Hanson * this, so we have to treat slot 0 as a valid device. 171*0db3240dSStephen Hanson * But other platforms use 0 to identify an internal 172*0db3240dSStephen Hanson * device. We deal with this by letting SMBIOS be the 173*0db3240dSStephen Hanson * final decision maker. If SMBIOS is supported, but 174*0db3240dSStephen Hanson * the given slot number is not represented in the 175*0db3240dSStephen Hanson * SMBIOS tables, then ignore the slot entirely. 176*0db3240dSStephen Hanson */ 177*0db3240dSStephen Hanson smbios_slot_cb_t cbdata; 178*0db3240dSStephen Hanson 179*0db3240dSStephen Hanson cbdata.cb_slotnum = *slotnum; 180*0db3240dSStephen Hanson cbdata.cb_label = NULL; 181*0db3240dSStephen Hanson if (smbios_iter(shp, di_smbios_find_slot, &cbdata) <= 0) 182*0db3240dSStephen Hanson return (0); 183*0db3240dSStephen Hanson slotbuf = (char *)cbdata.cb_label; 184*0db3240dSStephen Hanson topo_mod_dprintf(mp, "%s: node=%p: using smbios name\n", 185*0db3240dSStephen Hanson __func__, src); 186*0db3240dSStephen Hanson } else if (got_slotprop == B_TRUE) { 1870b6016e6Shueston slotbuf = (char *)&buf[4]; 188*0db3240dSStephen Hanson topo_mod_dprintf(mp, "%s: node=%p: found %s property\n", 189*0db3240dSStephen Hanson __func__, src, DI_SLOTPROP); 1900b6016e6Shueston } else { 1910b6016e6Shueston /* 1920b6016e6Shueston * Make generic description string "SLOT <num>", allow up to 1930b6016e6Shueston * 10 digits for number 1940b6016e6Shueston */ 1950b6016e6Shueston slotbuf = alloca(16); 1960b6016e6Shueston (void) snprintf(slotbuf, 16, "SLOT %d", *slotnum); 197*0db3240dSStephen Hanson topo_mod_dprintf(mp, "%s: node=%p: using generic slot name\n", 198*0db3240dSStephen Hanson __func__, src); 1990b6016e6Shueston } 20060348818STarik Soydan if ((*slotname = topo_mod_strdup(mp, slotbuf)) == NULL) 2017aec1d6eScindi return (-1); 2027aec1d6eScindi 203*0db3240dSStephen Hanson topo_mod_dprintf(mp, "%s: node=%p: slotname=%s\n", 204*0db3240dSStephen Hanson __func__, src, *slotname); 20560348818STarik Soydan 2067aec1d6eScindi return (0); 2077aec1d6eScindi } 2087aec1d6eScindi 2097aec1d6eScindi static int 21060348818STarik Soydan di_slotinfo_get(topo_mod_t *mp, di_node_t src, int *nslots, 21160348818STarik Soydan slotnm_t **slotnames) 2127aec1d6eScindi { 2137aec1d6eScindi slotnm_t *lastslot = NULL; 2147aec1d6eScindi slotnm_t *newslot; 2157aec1d6eScindi uchar_t *slotbuf; 2167aec1d6eScindi uint_t slotmap = 0; 2177aec1d6eScindi char *slotname; 2187aec1d6eScindi int andbit; 2197aec1d6eScindi int sz = -1; 2207aec1d6eScindi 22160348818STarik Soydan *slotnames = NULL; 2227aec1d6eScindi *nslots = 0; 2230eb822a1Scindi if (di_bytes_get(mp, src, DI_SLOTPROP, &sz, &slotbuf) < 0) 2247aec1d6eScindi return (0); 2257aec1d6eScindi if (sz < sizeof (uint_t)) 2267aec1d6eScindi return (0); 2277aec1d6eScindi bcopy(slotbuf, &slotmap, sizeof (uint_t)); 2287aec1d6eScindi if (slotmap == 0) 2297aec1d6eScindi return (0); 2307aec1d6eScindi 2317aec1d6eScindi slotname = (char *)&slotbuf[4]; 2327aec1d6eScindi for (andbit = 0; andbit < 32; andbit++) { 2337aec1d6eScindi if (slotmap & (1 << andbit)) { 2347aec1d6eScindi char *s = slotname; 2357aec1d6eScindi slotname += strlen(s) + 1; 2367aec1d6eScindi if ((newslot = slotnm_create(mp, andbit, s)) == NULL) { 23760348818STarik Soydan slotnm_destroy(*slotnames); 23860348818STarik Soydan *slotnames = NULL; 2397aec1d6eScindi *nslots = 0; 2407aec1d6eScindi return (-1); 2417aec1d6eScindi } 2427aec1d6eScindi if (lastslot == NULL) 24360348818STarik Soydan *slotnames = lastslot = newslot; 244c863ec5cSstephh else { 2457aec1d6eScindi lastslot->snm_next = newslot; 246c863ec5cSstephh lastslot = newslot; 247c863ec5cSstephh } 2487aec1d6eScindi (*nslots)++; 2497aec1d6eScindi } 2507aec1d6eScindi } 2517aec1d6eScindi return (0); 2527aec1d6eScindi } 2537aec1d6eScindi 2547aec1d6eScindi int 25560348818STarik Soydan did_physlot(did_t *did) 2567aec1d6eScindi { 2577aec1d6eScindi assert(did != NULL); 2587aec1d6eScindi return (did->dp_physlot); 2597aec1d6eScindi } 2607aec1d6eScindi 26160348818STarik Soydan int 26260348818STarik Soydan did_physlot_exists(did_t *did) 26360348818STarik Soydan { 26460348818STarik Soydan assert(did != NULL); 26560348818STarik Soydan return ((did->dp_physlot >= 0) || (did->dp_nslots > 0)); 26660348818STarik Soydan } 26760348818STarik Soydan 2687aec1d6eScindi did_t * 2690eb822a1Scindi did_create(topo_mod_t *mp, di_node_t src, 2700eb822a1Scindi int ibrd, int ibrdge, int irc, int ibus) 2717aec1d6eScindi { 2727aec1d6eScindi did_t *np; 2737aec1d6eScindi did_t *pd; 2747aec1d6eScindi uint_t code; 2757aec1d6eScindi uint_t reg; 2767aec1d6eScindi 2770eb822a1Scindi if ((pd = did_hash_lookup(mp, src)) != NULL) { 2787aec1d6eScindi topo_mod_dprintf(mp, "Attempt to create existing did_t.\n"); 2797aec1d6eScindi assert(ibus == TRUST_BDF || (pd->dp_bus == ibus)); 2807aec1d6eScindi return (pd); 2817aec1d6eScindi } 2827aec1d6eScindi 2837aec1d6eScindi if ((np = topo_mod_zalloc(mp, sizeof (did_t))) == NULL) 2847aec1d6eScindi return (NULL); 2857aec1d6eScindi np->dp_mod = mp; 2867aec1d6eScindi np->dp_src = src; 2870eb822a1Scindi np->dp_hash = (did_hash_t *)topo_mod_getspecific(mp); 28840e5e17bSzx np->dp_tnode = NULL; 2897aec1d6eScindi 2907aec1d6eScindi /* 2917aec1d6eScindi * We must have a reg prop and from it we extract the bus #, 2927aec1d6eScindi * device #, and function #. 2937aec1d6eScindi */ 2940eb822a1Scindi if (di_uintprop_get(mp, src, DI_REGPROP, ®) < 0) { 2957aec1d6eScindi topo_mod_free(mp, np, sizeof (did_t)); 2967aec1d6eScindi return (NULL); 2977aec1d6eScindi } 2987aec1d6eScindi np->dp_board = ibrd; 2997aec1d6eScindi np->dp_bridge = ibrdge; 3007aec1d6eScindi np->dp_rc = irc; 3017aec1d6eScindi if (ibus == TRUST_BDF) 3027aec1d6eScindi np->dp_bus = PCI_REG_BUS_G(reg); 3037aec1d6eScindi else 3047aec1d6eScindi np->dp_bus = ibus; 3057aec1d6eScindi np->dp_dev = PCI_REG_DEV_G(reg); 3067aec1d6eScindi np->dp_fn = PCI_REG_FUNC_G(reg); 30700d0963fSdilpreet np->dp_bdf = (PCI_REG_BUS_G(reg) << 8) | (PCI_REG_DEV_G(reg) << 3) | 30800d0963fSdilpreet PCI_REG_FUNC_G(reg); 3097aec1d6eScindi /* 3107aec1d6eScindi * There *may* be a class code we can capture. If there wasn't 3117aec1d6eScindi * one, capture that fact by setting the class value to -1. 3127aec1d6eScindi */ 3130eb822a1Scindi if (di_uintprop_get(mp, src, DI_CCPROP, &code) == 0) { 3147aec1d6eScindi np->dp_class = GETCLASS(code); 3157aec1d6eScindi np->dp_subclass = GETSUBCLASS(code); 3167aec1d6eScindi } else { 3177aec1d6eScindi np->dp_class = -1; 3187aec1d6eScindi } 3197aec1d6eScindi /* 32049fbdd30SErwin T Tsaur * There *may* be a device type we can capture. 3217aec1d6eScindi */ 32249fbdd30SErwin T Tsaur (void) di_devtype_get(mp, src, &np->dp_devtype); 323*0db3240dSStephen Hanson 324*0db3240dSStephen Hanson if (irc >= 0) { 325*0db3240dSStephen Hanson /* 326*0db3240dSStephen Hanson * This is a pciex node. 327*0db3240dSStephen Hanson */ 328*0db3240dSStephen Hanson if (di_physlotinfo_get(mp, src, &np->dp_physlot, 329*0db3240dSStephen Hanson &np->dp_physlot_name) < 0) { 330*0db3240dSStephen Hanson if (np->dp_devtype != NULL) 331*0db3240dSStephen Hanson topo_mod_strfree(mp, np->dp_devtype); 332*0db3240dSStephen Hanson topo_mod_free(mp, np, sizeof (did_t)); 333*0db3240dSStephen Hanson return (NULL); 334*0db3240dSStephen Hanson } 335*0db3240dSStephen Hanson } else { 336*0db3240dSStephen Hanson /* 337*0db3240dSStephen Hanson * This is a pci node. 338*0db3240dSStephen Hanson */ 339*0db3240dSStephen Hanson if (di_slotinfo_get(mp, src, &np->dp_nslots, 340*0db3240dSStephen Hanson &np->dp_slotnames) < 0) { 341*0db3240dSStephen Hanson if (np->dp_devtype != NULL) 342*0db3240dSStephen Hanson topo_mod_strfree(mp, np->dp_devtype); 343*0db3240dSStephen Hanson topo_mod_free(mp, np, sizeof (did_t)); 344*0db3240dSStephen Hanson return (NULL); 345*0db3240dSStephen Hanson } 3467aec1d6eScindi } 3470eb822a1Scindi did_hash_insert(mp, src, np); 3487aec1d6eScindi did_hold(np); 3497aec1d6eScindi return (np); 3507aec1d6eScindi } 3517aec1d6eScindi 3527aec1d6eScindi did_t * 3537aec1d6eScindi did_link_get(did_t *dp) 3547aec1d6eScindi { 3557aec1d6eScindi assert(dp != NULL); 3567aec1d6eScindi return (dp->dp_link); 3577aec1d6eScindi } 3587aec1d6eScindi 3597aec1d6eScindi did_t * 3607aec1d6eScindi did_chain_get(did_t *dp) 3617aec1d6eScindi { 3627aec1d6eScindi assert(dp != NULL); 3637aec1d6eScindi return (dp->dp_chain); 3647aec1d6eScindi } 3657aec1d6eScindi 3667aec1d6eScindi void 3670eb822a1Scindi did_link_set(topo_mod_t *mod, tnode_t *head, did_t *tail) 3687aec1d6eScindi { 3697aec1d6eScindi did_t *hd, *pd; 3707aec1d6eScindi 3717aec1d6eScindi assert(head != NULL); 3720eb822a1Scindi pd = hd = did_find(mod, topo_node_getspecific(head)); 3737aec1d6eScindi assert(hd != NULL); 3747aec1d6eScindi while ((hd = did_link_get(hd)) != NULL) 3757aec1d6eScindi pd = hd; 3767aec1d6eScindi pd->dp_link = tail; 3777aec1d6eScindi tail->dp_link = NULL; 3787aec1d6eScindi } 3797aec1d6eScindi 3807aec1d6eScindi void 3817aec1d6eScindi did_did_link_set(did_t *from, did_t *to) 3827aec1d6eScindi { 3837aec1d6eScindi assert(from != NULL && to != NULL); 3847aec1d6eScindi from->dp_link = to; 3857aec1d6eScindi } 3867aec1d6eScindi 3877aec1d6eScindi void 3887aec1d6eScindi did_did_chain_set(did_t *from, did_t *to) 3897aec1d6eScindi { 3907aec1d6eScindi assert(from != NULL && to != NULL); 3917aec1d6eScindi from->dp_chain = to; 3927aec1d6eScindi } 3937aec1d6eScindi 3947aec1d6eScindi void 3957aec1d6eScindi did_destroy(did_t *dp) 3967aec1d6eScindi { 3977aec1d6eScindi assert(dp != NULL); 3987aec1d6eScindi 3997aec1d6eScindi /* 4007aec1d6eScindi * did_destroy() is called only from did_hash_destroy() when 4017aec1d6eScindi * all references to the did_t have been released. We can 4027aec1d6eScindi * safely destroy the did_t. If at some later time, more 4037aec1d6eScindi * fine-grained reference count control is desired, this 4047aec1d6eScindi * code will need to change 4057aec1d6eScindi */ 4067aec1d6eScindi 40749fbdd30SErwin T Tsaur if (dp->dp_devtype != NULL) 40849fbdd30SErwin T Tsaur topo_mod_strfree(dp->dp_mod, dp->dp_devtype); 40960348818STarik Soydan if (dp->dp_physlot_name != NULL) 41060348818STarik Soydan topo_mod_strfree(dp->dp_mod, dp->dp_physlot_name); 41160348818STarik Soydan if (dp->dp_slot_label != NULL) 41260348818STarik Soydan topo_mod_strfree(dp->dp_mod, dp->dp_slot_label); 4137aec1d6eScindi slotnm_destroy(dp->dp_slotnames); 4147aec1d6eScindi topo_mod_free(dp->dp_mod, dp, sizeof (did_t)); 4157aec1d6eScindi } 4167aec1d6eScindi 4177aec1d6eScindi void 4187aec1d6eScindi did_hold(did_t *dp) 4197aec1d6eScindi { 4207aec1d6eScindi assert(dp != NULL); 4217aec1d6eScindi dp->dp_refcnt++; 4227aec1d6eScindi } 4237aec1d6eScindi 4247aec1d6eScindi void 4257aec1d6eScindi did_rele(did_t *dp) 4267aec1d6eScindi { 4277aec1d6eScindi assert(dp != NULL); 4287aec1d6eScindi assert(dp->dp_refcnt > 0); 4297aec1d6eScindi dp->dp_refcnt--; 4307aec1d6eScindi } 4317aec1d6eScindi 4327aec1d6eScindi di_node_t 4337aec1d6eScindi did_dinode(did_t *dp) 4347aec1d6eScindi { 4357aec1d6eScindi assert(dp != NULL); 4367aec1d6eScindi assert(dp->dp_src != NULL); 4377aec1d6eScindi return (dp->dp_src); 4387aec1d6eScindi } 4397aec1d6eScindi 4407aec1d6eScindi topo_mod_t * 4417aec1d6eScindi did_mod(did_t *dp) 4427aec1d6eScindi { 4437aec1d6eScindi assert(dp != NULL); 4447aec1d6eScindi return (dp->dp_mod); 4457aec1d6eScindi } 4467aec1d6eScindi 4477aec1d6eScindi void 4487aec1d6eScindi did_markrc(did_t *dp) 4497aec1d6eScindi { 4507aec1d6eScindi assert(dp != NULL); 4517aec1d6eScindi dp->dp_excap |= PCIE_PCIECAP_DEV_TYPE_ROOT; 4527aec1d6eScindi } 4537aec1d6eScindi 4547aec1d6eScindi void 4557aec1d6eScindi did_BDF(did_t *dp, int *bus, int *dev, int *fn) 4567aec1d6eScindi { 4577aec1d6eScindi assert(dp != NULL); 4587aec1d6eScindi if (bus != NULL) 4597aec1d6eScindi *bus = dp->dp_bus; 4607aec1d6eScindi if (dev != NULL) 4617aec1d6eScindi *dev = dp->dp_dev; 4627aec1d6eScindi if (fn != NULL) 4637aec1d6eScindi *fn = dp->dp_fn; 4647aec1d6eScindi } 4657aec1d6eScindi 4667aec1d6eScindi int 4677aec1d6eScindi did_board(did_t *did) 4687aec1d6eScindi { 4697aec1d6eScindi assert(did != NULL); 4707aec1d6eScindi return (did->dp_board); 4717aec1d6eScindi } 4727aec1d6eScindi 4737aec1d6eScindi int 4747aec1d6eScindi did_bridge(did_t *did) 4757aec1d6eScindi { 4767aec1d6eScindi assert(did != NULL); 4777aec1d6eScindi return (did->dp_bridge); 4787aec1d6eScindi } 4797aec1d6eScindi 4807aec1d6eScindi int 4817aec1d6eScindi did_rc(did_t *did) 4827aec1d6eScindi { 4837aec1d6eScindi assert(did != NULL); 4847aec1d6eScindi return (did->dp_rc); 4857aec1d6eScindi } 4867aec1d6eScindi 4877aec1d6eScindi int 4887aec1d6eScindi did_excap(did_t *dp) 4897aec1d6eScindi { 4907aec1d6eScindi assert(dp != NULL); 4917aec1d6eScindi return ((int)dp->dp_excap); 4927aec1d6eScindi } 4937aec1d6eScindi 49449fbdd30SErwin T Tsaur void 49549fbdd30SErwin T Tsaur did_excap_set(did_t *dp, int type) 49649fbdd30SErwin T Tsaur { 49749fbdd30SErwin T Tsaur dp->dp_excap = type; 49849fbdd30SErwin T Tsaur } 49949fbdd30SErwin T Tsaur 50000d0963fSdilpreet int 50100d0963fSdilpreet did_bdf(did_t *dp) 50200d0963fSdilpreet { 50300d0963fSdilpreet assert(dp != NULL); 50400d0963fSdilpreet return ((int)dp->dp_bdf); 50500d0963fSdilpreet } 50600d0963fSdilpreet 5077aec1d6eScindi const char * 50860348818STarik Soydan did_physlot_name(did_t *dp, int dev) 5097aec1d6eScindi { 5107aec1d6eScindi slotnm_t *slot; 5117aec1d6eScindi 5127aec1d6eScindi assert(dp != NULL); 513*0db3240dSStephen Hanson 514*0db3240dSStephen Hanson /* 515*0db3240dSStephen Hanson * For pciex, name will be in dp_physlot_name 516*0db3240dSStephen Hanson */ 51760348818STarik Soydan if (dp->dp_physlot_name != NULL) 51860348818STarik Soydan return (dp->dp_physlot_name); 519*0db3240dSStephen Hanson 520*0db3240dSStephen Hanson /* 521*0db3240dSStephen Hanson * For pci, name will be in dp_slotnames 522*0db3240dSStephen Hanson */ 5237aec1d6eScindi for (slot = dp->dp_slotnames; slot != NULL; slot = slot->snm_next) 5247aec1d6eScindi if (slot->snm_dev == dev) 5257aec1d6eScindi break; 5267aec1d6eScindi if (slot != NULL) 52760348818STarik Soydan return (slot->snm_name); 5287aec1d6eScindi return (NULL); 5297aec1d6eScindi } 5307aec1d6eScindi 53160348818STarik Soydan char * 53260348818STarik Soydan did_slot_label_get(did_t *did) 53360348818STarik Soydan { 53460348818STarik Soydan assert(did != NULL); 53560348818STarik Soydan return (did->dp_slot_label); 53660348818STarik Soydan } 53760348818STarik Soydan 53860348818STarik Soydan void 53960348818STarik Soydan did_slot_label_set(did_t *did, char *l) 54060348818STarik Soydan { 54160348818STarik Soydan assert(did != NULL); 54260348818STarik Soydan did->dp_slot_label = l; 54360348818STarik Soydan } 54460348818STarik Soydan 5457aec1d6eScindi did_t * 5460eb822a1Scindi did_find(topo_mod_t *mp, di_node_t dn) 5477aec1d6eScindi { 5480eb822a1Scindi return (did_hash_lookup(mp, dn)); 5497aec1d6eScindi } 5507aec1d6eScindi 5517aec1d6eScindi int 5520eb822a1Scindi pci_BDF_get(topo_mod_t *mp, di_node_t dn, int *bus, int *dev, int *fn) 5537aec1d6eScindi { 5547aec1d6eScindi did_t *dp; 5557aec1d6eScindi 5560eb822a1Scindi if ((dp = did_find(mp, dn)) == NULL) 5577aec1d6eScindi return (-1); 5587aec1d6eScindi *bus = dp->dp_bus; 5597aec1d6eScindi *dev = dp->dp_dev; 5607aec1d6eScindi *fn = dp->dp_fn; 5617aec1d6eScindi did_rele(dp); 5627aec1d6eScindi return (0); 5637aec1d6eScindi } 5647aec1d6eScindi 5657aec1d6eScindi int 5660eb822a1Scindi pci_classcode_get(topo_mod_t *mp, di_node_t dn, uint_t *class, uint_t *sub) 5677aec1d6eScindi { 5687aec1d6eScindi did_t *dp; 5697aec1d6eScindi 5700eb822a1Scindi if ((dp = did_find(mp, dn)) == NULL) 5717aec1d6eScindi return (-1); 5727aec1d6eScindi if (dp->dp_class < 0) { 5737aec1d6eScindi did_rele(dp); 5747aec1d6eScindi return (-1); 5757aec1d6eScindi } 5767aec1d6eScindi *class = dp->dp_class; 5777aec1d6eScindi *sub = dp->dp_subclass; 5787aec1d6eScindi did_rele(dp); 5797aec1d6eScindi return (0); 5807aec1d6eScindi } 5817aec1d6eScindi 58249fbdd30SErwin T Tsaur char * 58349fbdd30SErwin T Tsaur pci_devtype_get(topo_mod_t *mp, di_node_t dn) 58449fbdd30SErwin T Tsaur { 58549fbdd30SErwin T Tsaur did_t *dp; 58649fbdd30SErwin T Tsaur 58749fbdd30SErwin T Tsaur if ((dp = did_find(mp, dn)) == NULL) 58849fbdd30SErwin T Tsaur return (NULL); 58949fbdd30SErwin T Tsaur did_rele(dp); 59049fbdd30SErwin T Tsaur return (dp->dp_devtype); 59149fbdd30SErwin T Tsaur } 59249fbdd30SErwin T Tsaur 5937aec1d6eScindi int 5940eb822a1Scindi pciex_cap_get(topo_mod_t *mp, di_node_t dn) 5957aec1d6eScindi { 5967aec1d6eScindi did_t *dp; 5977aec1d6eScindi 5980eb822a1Scindi if ((dp = did_find(mp, dn)) == NULL) 5997aec1d6eScindi return (-1); 6007aec1d6eScindi did_rele(dp); 6017aec1d6eScindi return (dp->dp_excap); 6027aec1d6eScindi } 6037aec1d6eScindi 6040eb822a1Scindi void 6050eb822a1Scindi did_setspecific(topo_mod_t *mp, void *data) 6060eb822a1Scindi { 6070eb822a1Scindi did_t *hbdid; 6080eb822a1Scindi 6090eb822a1Scindi hbdid = (did_t *)data; 6100eb822a1Scindi topo_mod_setspecific(mp, hbdid->dp_hash); 6110eb822a1Scindi } 61240e5e17bSzx 61340e5e17bSzx void 61440e5e17bSzx did_settnode(did_t *pd, tnode_t *tn) 61540e5e17bSzx { 61640e5e17bSzx assert(tn != NULL); 61740e5e17bSzx pd->dp_tnode = tn; 61840e5e17bSzx } 61940e5e17bSzx 62040e5e17bSzx tnode_t * 62140e5e17bSzx did_gettnode(did_t *pd) 62240e5e17bSzx { 62340e5e17bSzx return (pd->dp_tnode); 62440e5e17bSzx } 625