/*ARGSUSED*/ static int maybe_di_chars_copy(tnode_t *tn, did_t *pd, const char *dpnm, const char *tpgrp, const char *tpnm) { topo_mod_t *mp; uchar_t *typbuf; char *tmpbuf; int sz = -1; int err, e; if (di_bytes_get(did_mod(pd), did_dinode(pd), dpnm, &sz, &typbuf) < 0) return (0); mp = did_mod(pd); if ((tmpbuf = topo_mod_alloc(mp, sz + 1)) == NULL) return (topo_mod_seterrno(mp, EMOD_NOMEM)); bcopy(typbuf, tmpbuf, sz); tmpbuf[sz] = 0; e = topo_prop_set_string(tn, tpgrp, tpnm, TOPO_PROP_IMMUTABLE, tmpbuf, &err); topo_mod_free(mp, tmpbuf, sz + 1); if (e != 0) return (topo_mod_seterrno(mp, err)); return (0); }
static int maybe_di_uint_to_dec_str(tnode_t *tn, did_t *pd, const char *dpnm, const char *tpgrp, const char *tpnm) { uint_t v; if (di_uintprop_get(did_mod(pd), did_dinode(pd), dpnm, &v) < 0) return (0); return (uint_to_dec_strprop(did_mod(pd), v, tn, tpgrp, tpnm)); }
int did_props_set(tnode_t *tn, did_t *pd, txprop_t txarray[], int txnum) { topo_mod_t *mp; int i, r, e; mp = did_mod(pd); for (i = 0; i < txnum; i++) { /* * Ensure the property group has been created. */ if (txarray[i].tx_tpgroup != NULL) { if (topo_pgroup_create(tn, txarray[i].tx_tpgroup, &e) < 0) { if (e != ETOPO_PROP_DEFD) return (topo_mod_seterrno(mp, e)); } } topo_mod_dprintf(mp, "Setting property %s in group %s.\n", txarray[i].tx_tprop, txarray[i].tx_tpgroup->tpi_name); r = txarray[i].tx_xlate(tn, pd, txarray[i].tx_diprop, txarray[i].tx_tpgroup->tpi_name, txarray[i].tx_tprop); if (r != 0) { topo_mod_dprintf(mp, "failed.\n"); topo_mod_dprintf(mp, "Error was %s.\n", topo_strerror(topo_mod_errno(mp))); return (-1); } topo_mod_dprintf(mp, "succeeded.\n"); } return (0); }
/*ARGSUSED*/ static int MODULEprop_set(tnode_t *tn, did_t *pd, const char *dpnm, const char *tpgrp, const char *tpnm) { nvlist_t *mod; topo_mod_t *mp; char *dnm; int err; if ((dnm = di_driver_name(did_dinode(pd))) == NULL) return (0); mp = did_mod(pd); if ((mod = topo_mod_modfmri(mp, FM_MOD_SCHEME_VERSION, dnm)) == NULL) return (0); /* driver maybe detached, return success */ if (topo_prop_set_fmri(tn, tpgrp, tpnm, TOPO_PROP_IMMUTABLE, mod, &err) < 0) { nvlist_free(mod); return (topo_mod_seterrno(mp, err)); } nvlist_free(mod); return (0); }
static int AADDR_set(tnode_t *tn, did_t *pd, const char *dpnm, const char *tpgrp, const char *tpnm) { topo_mod_t *mp; uchar_t *typbuf; int sz = -1; int err, e; if (di_bytes_get(did_mod(pd), did_dinode(pd), dpnm, &sz, &typbuf) < 0) return (0); mp = did_mod(pd); e = topo_prop_set_uint32_array(tn, tpgrp, tpnm, TOPO_PROP_IMMUTABLE, /*LINTED*/ (uint32_t *)typbuf, sz/4, &err); if (e != 0) return (topo_mod_seterrno(mp, err)); return (0); }
/*ARGSUSED*/ static int INSTprop_set(tnode_t *tn, did_t *pd, const char *dpnm, const char *tpgrp, const char *tpnm) { int inst, err; if ((inst = di_instance(did_dinode(pd))) == -1) return (0); if (topo_prop_set_uint32(tn, tpgrp, tpnm, TOPO_PROP_IMMUTABLE, inst, &err) < 0) return (topo_mod_seterrno(did_mod(pd), err)); return (0); }
/*ARGSUSED*/ static int DEVprop_set(tnode_t *tn, did_t *pd, const char *dpnm, const char *tpgrp, const char *tpnm) { topo_mod_t *mp; char *dnpath; char *path, *fpath; int d, f; int err, e; mp = did_mod(pd); if ((dnpath = di_devfs_path(did_dinode(pd))) == NULL) { topo_mod_dprintf(mp, "NULL di_devfs_path.\n"); return (topo_mod_seterrno(mp, ETOPO_PROP_NOENT)); } if ((path = topo_mod_strdup(mp, dnpath)) == NULL) { di_devfs_path_free(dnpath); return (-1); } di_devfs_path_free(dnpath); /* The DEV path is modified for hostbridges */ if (strcmp(topo_node_name(tn), HOSTBRIDGE) == 0) { fpath = dev_for_hostbridge(did_mod(pd), path); } else { did_BDF(pd, NULL, &d, &f); fpath = dev_path_fix(mp, path, d, f); } if (fpath == NULL) return (-1); e = topo_prop_set_string(tn, tpgrp, tpnm, TOPO_PROP_IMMUTABLE, fpath, &err); topo_mod_strfree(mp, fpath); if (e != 0) return (topo_mod_seterrno(mp, err)); return (0); }
/*ARGSUSED*/ static int DRIVERprop_set(tnode_t *tn, did_t *pd, const char *dpnm, const char *tpgrp, const char *tpnm) { char *dnm; int err; if ((dnm = di_driver_name(did_dinode(pd))) == NULL) return (0); if (topo_prop_set_string(tn, tpgrp, tpnm, TOPO_PROP_IMMUTABLE, dnm, &err) < 0) return (topo_mod_seterrno(did_mod(pd), err)); return (0); }
/*ARGSUSED*/ static int BDF_set(tnode_t *tn, did_t *pd, const char *dpnm, const char *tpgrp, const char *tpnm) { int bdf; char str[23]; /* '0x' + sizeof (UINT64_MAX) + '\0' */ int e; if ((bdf = did_bdf(pd)) <= 0) return (0); (void) snprintf(str, 23, "0x%x", bdf); if (topo_prop_set_string(tn, tpgrp, tpnm, TOPO_PROP_IMMUTABLE, str, &e) < 0) return (topo_mod_seterrno(did_mod(pd), e)); return (0); }
/*ARGSUSED*/ static int label_set(tnode_t *tn, did_t *pd, const char *dpnm, const char *tpgrp, const char *tpnm) { topo_mod_t *mp; nvlist_t *in, *out; char *label; int err; mp = did_mod(pd); /* * If this is a PCIEX_BUS and its parent is a PCIEX_ROOT, * check for a CPUBOARD predecessor. If found, inherit its * parent's Label. Otherwise, continue with label set. */ if ((strcmp(topo_node_name(tn), PCIEX_BUS) == 0) && (strcmp(topo_node_name(topo_node_parent(tn)), PCIEX_ROOT) == 0)) { if (use_predecessor_label(mp, tn, CPUBOARD) == 0) return (0); } if (topo_mod_nvalloc(mp, &in, NV_UNIQUE_NAME) != 0) return (topo_mod_seterrno(mp, EMOD_FMRI_NVL)); if (nvlist_add_uint64(in, TOPO_METH_LABEL_ARG_NVL, (uintptr_t)pd) != 0) { nvlist_free(in); return (topo_mod_seterrno(mp, EMOD_NOMEM)); } if (topo_method_invoke(tn, TOPO_METH_LABEL, TOPO_METH_LABEL_VERSION, in, &out, &err) != 0) { nvlist_free(in); return (topo_mod_seterrno(mp, err)); } nvlist_free(in); if (out != NULL && nvlist_lookup_string(out, TOPO_METH_LABEL_RET_STR, &label) == 0) { if (topo_prop_set_string(tn, TOPO_PGROUP_PROTOCOL, TOPO_PROP_LABEL, TOPO_PROP_IMMUTABLE, label, &err) != 0) { nvlist_free(out); return (topo_mod_seterrno(mp, err)); } nvlist_free(out); } return (0); }
/*ARGSUSED*/ static int EXCAP_set(tnode_t *tn, did_t *pd, const char *dpnm, const char *tpgrp, const char *tpnm) { int excap = did_excap(pd); int err; int e = 0; switch (excap & PCIE_PCIECAP_DEV_TYPE_MASK) { case PCIE_PCIECAP_DEV_TYPE_ROOT: e = topo_prop_set_string(tn, TOPO_PGROUP_PCI, TOPO_PCI_EXCAP, TOPO_PROP_IMMUTABLE, PCIEX_ROOT, &err); break; case PCIE_PCIECAP_DEV_TYPE_UP: e = topo_prop_set_string(tn, TOPO_PGROUP_PCI, TOPO_PCI_EXCAP, TOPO_PROP_IMMUTABLE, PCIEX_SWUP, &err); break; case PCIE_PCIECAP_DEV_TYPE_DOWN: e = topo_prop_set_string(tn, TOPO_PGROUP_PCI, TOPO_PCI_EXCAP, TOPO_PROP_IMMUTABLE, PCIEX_SWDWN, &err); break; case PCIE_PCIECAP_DEV_TYPE_PCI2PCIE: e = topo_prop_set_string(tn, TOPO_PGROUP_PCI, TOPO_PCI_EXCAP, TOPO_PROP_IMMUTABLE, PCIEX_BUS, &err); break; case PCIE_PCIECAP_DEV_TYPE_PCIE2PCI: e = topo_prop_set_string(tn, TOPO_PGROUP_PCI, TOPO_PCI_EXCAP, TOPO_PROP_IMMUTABLE, PCI_BUS, &err); break; case PCIE_PCIECAP_DEV_TYPE_PCIE_DEV: e = topo_prop_set_string(tn, TOPO_PGROUP_PCI, TOPO_PCI_EXCAP, TOPO_PROP_IMMUTABLE, PCIEX_DEVICE, &err); break; } if (e != 0) return (topo_mod_seterrno(did_mod(pd), err)); return (0); }
/*ARGSUSED*/ static int FRU_set(tnode_t *tn, did_t *pd, const char *dpnm, const char *tpgrp, const char *tpnm) { topo_mod_t *mp; char *nm; int e = 0, err = 0; nm = topo_node_name(tn); mp = did_mod(pd); /* * If this is a PCIEX_BUS and its parent is a PCIEX_ROOT, * check for a CPUBOARD predecessor. If found, inherit its * parent's FRU. Otherwise, continue with FRU set. */ if ((strcmp(nm, PCIEX_BUS) == 0) && (strcmp(topo_node_name(topo_node_parent(tn)), PCIEX_ROOT) == 0)) { if (use_predecessor_fru(tn, CPUBOARD) == 0) return (0); } /* * If this topology node represents something other than an * ioboard or a device that implements a slot, inherit the * parent's FRU value. If there is no label, inherit our * parent's FRU value. Otherwise, munge up an fmri based on * the label. */ if (strcmp(nm, IOBOARD) != 0 && strcmp(nm, PCI_DEVICE) != 0 && strcmp(nm, PCIEX_DEVICE) != 0 && strcmp(nm, PCIEX_BUS) != 0) { (void) topo_node_fru_set(tn, NULL, 0, &e); return (0); } /* * If ioboard, set fru fmri to hc fmri */ if (strcmp(nm, IOBOARD) == 0) { e = FRU_fmri_set(mp, tn); return (e); } else if (strcmp(nm, PCI_DEVICE) == 0 || strcmp(nm, PCIEX_DEVICE) == 0 || strcmp(nm, PCIEX_BUS) == 0) { nvlist_t *in, *out; mp = did_mod(pd); if (topo_mod_nvalloc(mp, &in, NV_UNIQUE_NAME) != 0) return (topo_mod_seterrno(mp, EMOD_FMRI_NVL)); if (nvlist_add_uint64(in, "nv1", (uintptr_t)pd) != 0) { nvlist_free(in); return (topo_mod_seterrno(mp, EMOD_NOMEM)); } if (topo_method_invoke(tn, TOPO_METH_FRU_COMPUTE, TOPO_METH_FRU_COMPUTE_VERSION, in, &out, &err) != 0) { nvlist_free(in); return (topo_mod_seterrno(mp, err)); } nvlist_free(in); (void) topo_node_fru_set(tn, out, 0, &err); if (out != NULL) nvlist_free(out); } else (void) topo_node_fru_set(tn, NULL, 0, &err); return (0); }
/*ARGSUSED*/ static int ASRU_set(tnode_t *tn, did_t *pd, const char *dpnm, const char *tpgrp, const char *tpnm) { topo_mod_t *mp; nvlist_t *fmri; char *dnpath, *path, *fpath, *nm; int d, e, f; /* * If this topology node represents a function of device, * set the ASRU to a dev scheme FMRI based on the value of * di_devfs_path(). If that path is NULL, set the ASRU to * be the resource describing this topology node. If this * isn't a function, inherit any ASRU from the parent. */ mp = did_mod(pd); nm = topo_node_name(tn); if ((strcmp(nm, PCI_BUS) == 0 && did_gettnode(pd) && strcmp(topo_node_name(did_gettnode(pd)), HOSTBRIDGE) == 0) || strcmp(nm, PCI_FUNCTION) == 0 || strcmp(nm, PCIEX_FUNCTION) == 0 || strcmp(nm, PCIEX_ROOT) == 0) { if ((dnpath = di_devfs_path(did_dinode(pd))) != NULL) { /* * Dup the path, dev_path_fix() may replace it and * dev_path_fix() wouldn't know to use * di_devfs_path_free() */ if ((path = topo_mod_strdup(mp, dnpath)) == NULL) { di_devfs_path_free(dnpath); return (topo_mod_seterrno(mp, EMOD_NOMEM)); } di_devfs_path_free(dnpath); did_BDF(pd, NULL, &d, &f); if ((fpath = dev_path_fix(mp, path, d, f)) == NULL) return (topo_mod_seterrno(mp, EMOD_NOMEM)); fmri = topo_mod_devfmri(mp, FM_DEV_SCHEME_VERSION, fpath, NULL); if (fmri == NULL) { topo_mod_dprintf(mp, "dev:///%s fmri creation failed.\n", fpath); topo_mod_strfree(mp, fpath); return (-1); } topo_mod_strfree(mp, fpath); } else { topo_mod_dprintf(mp, "NULL di_devfs_path.\n"); if (topo_prop_get_fmri(tn, TOPO_PGROUP_PROTOCOL, TOPO_PROP_RESOURCE, &fmri, &e) < 0) return (topo_mod_seterrno(mp, e)); } if (topo_node_asru_set(tn, fmri, 0, &e) < 0) { nvlist_free(fmri); return (topo_mod_seterrno(mp, e)); } nvlist_free(fmri); return (0); } (void) topo_node_asru_set(tn, NULL, 0, &e); return (0); }
/*ARGSUSED*/ static int maybe_pcidb_set(tnode_t *tn, did_t *pd, const char *dpnm, const char *tpgrp, const char *tpnm) { const char *vname, *dname = NULL, *ssname = NULL; uint_t vid, pid, svid, ssid; pcidb_vendor_t *pciv; pcidb_device_t *pcid; pcidb_subvd_t *pcis = NULL; pcidb_hdl_t *pcih; topo_mod_t *mod = did_mod(pd); int err; /* * At a minimum, we need the vid/devid of the device to be able to * lookup anything in the PCI database. So if we fail to look either * of those up, bail out. */ if (di_uintprop_get(did_mod(pd), did_dinode(pd), DI_VENDIDPROP, &vid) < 0 || di_uintprop_get(did_mod(pd), did_dinode(pd), DI_DEVIDPROP, &pid) < 0) { return (0); } /* * If we fail to lookup the vendor, by the vid that's also a * deal-breaker. */ if ((pcih = topo_mod_pcidb(mod)) == NULL || (pciv = pcidb_lookup_vendor(pcih, vid)) == NULL) { return (0); } /* lookup vendor-name and set the topo property, if found */ vname = pcidb_vendor_name(pciv); if (vname != NULL && topo_prop_set_string(tn, tpgrp, TOPO_PCI_VENDNM, TOPO_PROP_IMMUTABLE, vname, &err) != 0) { return (topo_mod_seterrno(mod, err)); } /* lookup device-name and set the topo property, if found */ if ((pcid = pcidb_lookup_device_by_vendor(pciv, pid)) != NULL) { dname = pcidb_device_name(pcid); } if (dname != NULL && topo_prop_set_string(tn, tpgrp, TOPO_PCI_DEVNM, TOPO_PROP_IMMUTABLE, dname, &err) != 0) { return (topo_mod_seterrno(mod, err)); } /* * Not all devices will have a subsystem-name that we can lookup, * but if both subsystem-vendorid and subsystem-id exist in devinfo and * if we were previously able to find the device by devid then we can * at least attempt a lookup. If found, set the topo property. */ if (pcid != NULL && di_uintprop_get(did_mod(pd), did_dinode(pd), DI_SUBVENDIDPROP, &svid) == 0 && di_uintprop_get(did_mod(pd), did_dinode(pd), DI_SUBSYSTEMID, &ssid) == 0) { pcis = pcidb_lookup_subvd_by_device(pcid, svid, ssid); } if (pcis != NULL) { ssname = pcidb_subvd_name(pcis); } if (ssname != NULL && strlen(ssname) > 0 && topo_prop_set_string(tn, tpgrp, TOPO_PCI_SUBSYSNM, TOPO_PROP_IMMUTABLE, ssname, &err) != 0) { return (topo_mod_seterrno(mod, err)); } return (0); }