int topo_method_register(topo_mod_t *mod, tnode_t *node, const topo_method_t *mp) { topo_imethod_t *imp; const topo_method_t *meth; /* * Initialize module methods */ for (meth = &mp[0]; meth->tm_name != NULL; meth++) { topo_node_lock(node); if (topo_method_lookup(node, meth->tm_name) != NULL) { topo_node_unlock(node); continue; } if (meth->tm_stability < TOPO_STABILITY_INTERNAL || meth->tm_stability > TOPO_STABILITY_MAX || meth->tm_func == NULL) return (set_methregister_error(mod, node, NULL, ETOPO_METHOD_INVAL)); imp = topo_mod_zalloc(mod, sizeof (topo_imethod_t)); if (imp == NULL) return (set_methregister_error(mod, node, imp, ETOPO_METHOD_NOMEM)); if ((imp->tim_name = topo_mod_strdup(mod, meth->tm_name)) == NULL) return (set_methregister_error(mod, node, imp, ETOPO_METHOD_NOMEM)); if ((imp->tim_desc = topo_mod_strdup(mod, meth->tm_desc)) == NULL) return (set_methregister_error(mod, node, imp, ETOPO_METHOD_NOMEM)); imp->tim_stability = meth->tm_stability; imp->tim_version = meth->tm_version; imp->tim_func = meth->tm_func; imp->tim_mod = mod; topo_list_append(&node->tn_methods, imp); topo_node_unlock(node); topo_dprintf(mod->tm_hdl, TOPO_DBG_MODSVC, "registered module %s method " "%s for %s=%d\n", mod->tm_name, imp->tim_name, topo_node_name(node), topo_node_instance(node)); } return (0); }
/* * dev_for_hostbridge() -- For hostbridges we truncate the devfs path * after the first element in the bus address. */ static char * dev_for_hostbridge(topo_mod_t *mp, char *path) { char *lastslash; char *newpath; char *comma; int plen; plen = strlen(path) + 1; /* * We only care about the last component of the dev path. If * we don't find a slash, something is weird. */ lastslash = strrchr(path, '/'); assert(lastslash != NULL); /* * Find the comma in the last component component@x,y, and * truncate the comma and any following number. */ comma = strchr(lastslash, ','); assert(comma != NULL); *comma = '\0'; if ((newpath = topo_mod_strdup(mp, path)) == NULL) { topo_mod_free(mp, path, plen); return (NULL); } *comma = ','; topo_mod_free(mp, path, plen); return (newpath); }
/* di_devlink callback for dev_di_node_add */ static int disk_devlink_callback(di_devlink_t dl, void *arg) { disk_cbdata_t *cbp = (disk_cbdata_t *)arg; topo_mod_t *mod = cbp->dcb_mod; dev_di_node_t *dnode = cbp->dcb_dnode; const char *devpath; char *ctds, *slice; devpath = di_devlink_path(dl); if ((dnode == NULL) || (devpath == NULL)) return (DI_WALK_TERMINATE); /* trim the slice off the public name */ if (((ctds = strrchr(devpath, '/')) != NULL) && ((slice = strchr(ctds, 's')) != NULL)) *slice = '\0'; /* Establish the public /dev name (no slice) */ dnode->ddn_lpath = topo_mod_strdup(mod, ctds ? ctds + 1 : devpath); if (ctds && slice) *slice = 's'; return (DI_WALK_TERMINATE); }
did_t * split_bus_address(did_hash_t *dhash, di_node_t dp, uint_t baseaddr, uint_t bussep, int minbrd, int maxbrd, int *brd, int *br, int *bus, di_prom_handle_t promtree, topo_mod_t *mod) { uint_t bc, ac; char *comma; char *bac; char *ba; int e; if ((ba = di_bus_addr(dp)) == NULL || (bac = topo_mod_strdup(mod, ba)) == NULL) return (NULL); topo_mod_dprintf(mod, "Transcribing %s into board, bus, etc.\n", bac); if ((comma = strchr(bac, ',')) == NULL) { topo_mod_strfree(mod, bac); return (NULL); } *comma = '\0'; bc = strtonum(mod, bac, &e); *comma = ','; if (e < 0) { topo_mod_dprintf(mod, "Trouble interpreting %s before comma.\n", bac); topo_mod_strfree(mod, bac); return (NULL); } ac = strtonum(mod, comma + 1, &e); if (e < 0) { topo_mod_dprintf(mod, "Trouble interpreting %s after comma.\n", bac); topo_mod_strfree(mod, bac); return (NULL); } topo_mod_strfree(mod, bac); *brd = ((bc - baseaddr) / bussep) + minbrd; *br = (bc - baseaddr) % bussep; *bus = ((ac == IOB_BUSADDR1) ? 0 : 1); if (*brd < minbrd || *brd > maxbrd || (*br != 0 && *br != 1) || (ac != IOB_BUSADDR1 && ac != IOB_BUSADDR2)) { topo_mod_dprintf(mod, "Trouble with transcription\n"); topo_mod_dprintf(mod, "brd=%d br=%d bus=%d bc=%x ac=%x\n", *brd, *br, *bus, bc, ac); return (NULL); } return (did_create(dhash, dp, *brd, *br, NO_RC, *bus, promtree)); }
int topo_node_range_create(topo_mod_t *mod, tnode_t *pnode, const char *name, topo_instance_t min, topo_instance_t max) { topo_nodehash_t *nhp; topo_node_lock(pnode); assert((pnode->tn_state & TOPO_NODE_BOUND) || (pnode->tn_state & TOPO_NODE_ROOT)); for (nhp = topo_list_next(&pnode->tn_children); nhp != NULL; nhp = topo_list_next(nhp)) { if (strcmp(nhp->th_name, name) == 0) return (node_create_seterror(mod, pnode, NULL, ETOPO_NODE_DUP)); } if (min < 0 || max < min) return (node_create_seterror(mod, pnode, NULL, ETOPO_NODE_INVAL)); if ((nhp = topo_mod_zalloc(mod, sizeof (topo_nodehash_t))) == NULL) return (node_create_seterror(mod, pnode, nhp, ETOPO_NOMEM)); if ((nhp->th_name = topo_mod_strdup(mod, name)) == NULL) return (node_create_seterror(mod, pnode, nhp, ETOPO_NOMEM)); nhp->th_arrlen = max - min + 1; if ((nhp->th_nodearr = topo_mod_zalloc(mod, nhp->th_arrlen * sizeof (tnode_t *))) == NULL) return (node_create_seterror(mod, pnode, nhp, ETOPO_NOMEM)); nhp->th_range.tr_min = min; nhp->th_range.tr_max = max; nhp->th_enum = mod; topo_mod_hold(mod); /* * Add these nodes to parent child list */ topo_list_append(&pnode->tn_children, nhp); topo_node_unlock(pnode); topo_dprintf(TOPO_DBG_MOD, "created node range %s[%d-%d]\n", name, min, max); return (0); }
tf_info_t * tf_info_new(topo_mod_t *mp, xmlDocPtr doc, xmlChar *scheme) { tf_info_t *r; if ((r = topo_mod_zalloc(mp, sizeof (tf_info_t))) == NULL) return (NULL); r->tf_flags = TF_LIVE; if ((r->tf_scheme = topo_mod_strdup(mp, (char *)scheme)) == NULL) { tf_info_free(mp, r); return (NULL); } r->tf_xdoc = doc; return (r); }
/* * Manufacturing strings can contain characters that are invalid for use in hc * authority names. This trims leading and trailing whitespace, and * substitutes any characters known to be bad. */ char * disk_auth_clean(topo_mod_t *mod, const char *str) { char *buf, *p; if (str == NULL) return (NULL); if ((buf = topo_mod_strdup(mod, str)) == NULL) return (NULL); while ((p = strpbrk(buf, " :=")) != NULL) *p = '-'; return (buf); }
const char * x86pi_cleanup_smbios_str(topo_mod_t *mod, const char *begin, int str_type) { char buf[MAXNAMELEN]; const char *end, *cp; char *pp; char c; int i; end = begin + strlen(begin); while (begin < end && isspace(*begin)) begin++; while (begin < end && isspace(*(end - 1))) end--; if (begin >= end) return (NULL); cp = begin; for (i = 0; i < MAXNAMELEN - 1; i++) { if (cp >= end) break; c = *cp; if (str_type == LABEL) { if (!isprint(c)) buf[i] = '-'; else buf[i] = c; } else { if (c == ':' || c == '=' || c == '/' || isspace(c) || !isprint(c)) buf[i] = '-'; else buf[i] = c; } cp++; } buf[i] = 0; pp = topo_mod_strdup(mod, buf); if (str_type == LABEL) topo_mod_strfree(mod, (char *)begin); return (pp); }
tf_rdata_t * tf_rdata_new(topo_mod_t *mp, tf_info_t *xinfo, xmlNodePtr n, tnode_t *troot) { tf_rdata_t *r; uint64_t ui; xmlChar *name = NULL; topo_dprintf(mp->tm_hdl, TOPO_DBG_XML, "new rdata\n"); if ((r = topo_mod_zalloc(mp, sizeof (tf_rdata_t))) == NULL) { (void) topo_mod_seterrno(mp, ETOPO_NOMEM); return (NULL); } r->rd_pn = troot; if ((name = xmlGetProp(n, (xmlChar *)Name)) == NULL) { (void) topo_mod_seterrno(mp, ETOPO_PRSR_NOATTR); goto rdata_nogood; } if ((r->rd_name = topo_mod_strdup(mp, (char *)name)) == NULL) { (void) topo_mod_seterrno(mp, ETOPO_NOMEM); goto rdata_nogood; } if (xmlattr_to_int(mp, n, Min, &ui) < 0) goto rdata_nogood; r->rd_min = (int)ui; if (xmlattr_to_int(mp, n, Max, &ui) < 0) goto rdata_nogood; r->rd_max = (int)ui; if (r->rd_min < 0 || r->rd_max < 0 || r->rd_max < r->rd_min) { (void) topo_mod_seterrno(mp, ETOPO_PRSR_BADRNG); goto rdata_nogood; } r->rd_finfo = xinfo; r->rd_mod = mp; if (topo_xml_range_process(mp, n, r) < 0) goto rdata_nogood; xmlFree(name); return (r); rdata_nogood: if (name != NULL) xmlFree(name); tf_rdata_free(mp, r); return (NULL); }
/* * Get the server hostname (the ID as far as the topo authority is * concerned) from sysinfo and return a copy to the caller. * * The string must be freed with topo_mod_strfree() */ char * x86pi_get_serverid(topo_mod_t *mod) { int result; char hostname[MAXNAMELEN]; topo_mod_dprintf(mod, "x86pi_get_serverid\n"); result = sysinfo(SI_HOSTNAME, hostname, sizeof (hostname)); /* Everything is freed up and it's time to return the platform-id */ if (result == -1) { return (NULL); } topo_mod_dprintf(mod, "x86pi_get_serverid: hostname = %s\n", hostname); return (topo_mod_strdup(mod, hostname)); }
ttree_t * topo_tree_create(topo_hdl_t *thp, topo_mod_t *mod, const char *scheme) { ttree_t *tp; tnode_t *rp; if ((tp = topo_mod_zalloc(mod, sizeof (ttree_t))) == NULL) return (set_create_error(thp, NULL, ETOPO_NOMEM)); tp->tt_mod = mod; if ((tp->tt_scheme = topo_mod_strdup(mod, scheme)) == NULL) return (set_create_error(thp, tp, ETOPO_NOMEM)); /* * Initialize a private walker for internal use */ if ((tp->tt_walk = topo_mod_zalloc(mod, sizeof (topo_walk_t))) == NULL) return (set_create_error(thp, tp, ETOPO_NOMEM)); /* * Create the root of this tree: LINKED but never BOUND */ if ((rp = topo_mod_zalloc(mod, sizeof (tnode_t))) == NULL) return (set_create_error(thp, tp, 0)); /* th_errno set */ rp->tn_state = TOPO_NODE_ROOT | TOPO_NODE_INIT; rp->tn_name = tp->tt_scheme; rp->tn_instance = 0; rp->tn_enum = mod; rp->tn_hdl = thp; topo_node_hold(rp); tp->tt_walk->tw_root = rp; tp->tt_walk->tw_thp = thp; topo_mod_hold(mod); /* released when root node destroyed */ tp->tt_root = rp; return (tp); }
/* * Remove the 3 character device name (pci/niu) from devfs path. */ static char * xaui_trans_str(topo_mod_t *mod, char *dn, char *p, size_t buf_len) { int i = 0; int j = 0; char buf[MAXPATHLEN]; topo_mod_dprintf(mod, "xaui_trans_str: dev path(%s) dev name(%s)\n", dn, p); do { /* strip out either "pci" or "niu" */ if (dn[i] == p[0] && dn[i + 1] == p[1] && dn[i + 2] == p[2]) i += 3; else buf[j++] = dn[i++]; } while (i < buf_len); topo_mod_dprintf(mod, "xaui_trans_str: return(%s)\n", buf); return (topo_mod_strdup(mod, (char *)buf)); }
/*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); }
static int create_core(topo_mod_t *mod, tnode_t *pnode, nvlist_t *cpu, nvlist_t *auth, uint16_t chip_smbiosid) { tnode_t *core; int32_t coreid, cpuid; int err, perr, nerr = 0; nvlist_t *fmri; char *serial = NULL; char *part = NULL; char *rev = NULL; if ((err = nvlist_lookup_int32(cpu, FM_PHYSCPU_INFO_CORE_ID, &coreid)) != 0) { whinge(mod, NULL, "create_core: lookup core_id failed: %s\n", strerror(err)); return (-1); } if ((core = topo_node_lookup(pnode, CORE_NODE_NAME, coreid)) == NULL) { if ((core = create_node(mod, pnode, auth, CORE_NODE_NAME, coreid, chip_smbiosid)) == NULL) return (-1); /* * Inherit FRU from the chip node, for native, we use hc * scheme ASRU for the core node. */ (void) topo_node_fru_set(core, NULL, 0, &perr); /* * From the inherited FRU, extract the Serial * number if SMBIOS donates and set it in the ASRU */ if (FM_AWARE_SMBIOS(mod)) { char *val = NULL; if (topo_node_resource(core, &fmri, &err) != 0) whinge(mod, NULL, "create_core: topo_prop_get_fmri failed\n"); if (nvlist_lookup_string(fmri, FM_FMRI_HC_SERIAL_ID, &val) != 0) whinge(mod, NULL, "create_core:" "nvlist_lookup_string failed\n"); else serial = topo_mod_strdup(mod, val); nvlist_free(fmri); } if (is_xpv()) { if (topo_node_resource(core, &fmri, &err) == -1) { whinge(mod, &nerr, "create_core: " "topo_node_resource failed\n"); } else { if (FM_AWARE_SMBIOS(mod)) (void) nvlist_add_string(fmri, FM_FMRI_HC_SERIAL_ID, serial); (void) topo_node_asru_set(core, fmri, 0, &err); nvlist_free(fmri); } } if (topo_method_register(mod, core, strands_retire_methods) < 0) whinge(mod, &nerr, "create_core: " "topo_method_register failed\n"); (void) topo_pgroup_create(core, &core_pgroup, &err); nerr -= add_nvlist_longprops(mod, core, cpu, PGNAME(CORE), NULL, CORE_CHIP_ID, CORE_PROCNODE_ID, NULL); if (topo_node_range_create(mod, core, STRAND_NODE_NAME, 0, 255) != 0) return (-1); } if (!is_xpv()) { /* * In native mode, we're in favor of cpu scheme ASRU for * printing reason. More work needs to be done to support * multi-strand cpu: the ASRU will be a list of cpuid then. */ if (nvlist_lookup_int32(cpu, STRAND_CPU_ID, &cpuid) != 0) { whinge(mod, &nerr, "create_core: lookup cpuid " "failed\n"); } else { if ((fmri = cpu_fmri_create(mod, cpuid, serial, 0)) != NULL) { (void) topo_node_asru_set(core, fmri, 0, &err); nvlist_free(fmri); } else { whinge(mod, &nerr, "create_core: " "cpu_fmri_create() failed\n"); } } } if (FM_AWARE_SMBIOS(mod)) { (void) topo_node_label_set(core, NULL, &perr); if (topo_node_resource(core, &fmri, &perr) != 0) { whinge(mod, &nerr, "create_core: " "topo_node_resource failed\n"); perr = 0; } perr += nvlist_lookup_string(fmri, FM_FMRI_HC_PART, &part); perr += nvlist_lookup_string(fmri, FM_FMRI_HC_REVISION, &rev); if (perr != 0) { whinge(mod, NULL, "create_core: nvlist_lookup_string failed\n"); perr = 0; } perr += topo_prop_set_string(core, PGNAME(CORE), FM_FMRI_HC_SERIAL_ID, TOPO_PROP_IMMUTABLE, serial, &perr); perr += topo_prop_set_string(core, PGNAME(CORE), FM_FMRI_HC_PART, TOPO_PROP_IMMUTABLE, part, &perr); perr += topo_prop_set_string(core, PGNAME(CORE), FM_FMRI_HC_REVISION, TOPO_PROP_IMMUTABLE, rev, &perr); if (perr != 0) whinge(mod, NULL, "create_core: topo_prop_set_string" "failed\n"); nvlist_free(fmri); topo_mod_strfree(mod, serial); } err = create_strand(mod, core, cpu, auth, chip_smbiosid); return (err == 0 && nerr == 0 ? 0 : -1); }
static int create_strand(topo_mod_t *mod, tnode_t *pnode, nvlist_t *cpu, nvlist_t *auth, uint16_t chip_smbiosid) { tnode_t *strand; int32_t strandid, cpuid; int err, perr, nerr = 0; nvlist_t *fmri; char *serial = NULL; char *part = NULL; char *rev = NULL; if ((err = nvlist_lookup_int32(cpu, FM_PHYSCPU_INFO_STRAND_ID, &strandid)) != 0) { whinge(mod, NULL, "create_strand: lookup strand_id failed: " "%s\n", strerror(err)); return (-1); } if ((strand = topo_node_lookup(pnode, STRAND_NODE_NAME, strandid)) != NULL) { whinge(mod, NULL, "create_strand: duplicate tuple found\n"); return (-1); } if ((strand = create_node(mod, pnode, auth, STRAND_NODE_NAME, strandid, chip_smbiosid)) == NULL) return (-1); /* * Inherit FRU from core node, in native use cpu scheme ASRU, * in xpv, use hc scheme ASRU. */ (void) topo_node_fru_set(strand, NULL, 0, &perr); /* * From the inherited FRU, extract the Serial * number(if SMBIOS donates) and set it in the ASRU */ if (FM_AWARE_SMBIOS(mod)) { char *val = NULL; if (topo_prop_get_fmri(strand, TOPO_PGROUP_PROTOCOL, TOPO_PROP_RESOURCE, &fmri, &err) != 0) whinge(mod, NULL, "create_strand: topo_prop_get_fmri failed\n"); if (nvlist_lookup_string(fmri, FM_FMRI_HC_SERIAL_ID, &val) != 0) whinge(mod, NULL, "create_strand: nvlist_lookup_string failed: \n"); else serial = topo_mod_strdup(mod, val); nvlist_free(fmri); } if (is_xpv()) { if (topo_node_resource(strand, &fmri, &err) == -1) { whinge(mod, &nerr, "create_strand: " "topo_node_resource failed\n"); } else { if (FM_AWARE_SMBIOS(mod)) (void) nvlist_add_string(fmri, FM_FMRI_HC_SERIAL_ID, serial); (void) topo_node_asru_set(strand, fmri, 0, &err); nvlist_free(fmri); } } else { if (nvlist_lookup_int32(cpu, STRAND_CPU_ID, &cpuid) != 0) { whinge(mod, &nerr, "create_strand: lookup cpuid " "failed\n"); } else { if ((fmri = cpu_fmri_create(mod, cpuid, serial, 0)) != NULL) { (void) topo_node_asru_set(strand, fmri, 0, &err); nvlist_free(fmri); } else { whinge(mod, &nerr, "create_strand: " "cpu_fmri_create() failed\n"); } } } if (topo_method_register(mod, strand, strands_retire_methods) < 0) whinge(mod, &nerr, "create_strand: " "topo_method_register failed\n"); (void) topo_pgroup_create(strand, &strand_pgroup, &err); nerr -= add_nvlist_longprops(mod, strand, cpu, PGNAME(STRAND), NULL, STRAND_CHIP_ID, STRAND_PROCNODE_ID, STRAND_CORE_ID, STRAND_CPU_ID, NULL); if (FM_AWARE_SMBIOS(mod)) { (void) topo_node_label_set(strand, NULL, &perr); if (topo_node_resource(strand, &fmri, &perr) != 0) { whinge(mod, &nerr, "create_strand: " "topo_node_resource failed\n"); perr = 0; } perr += nvlist_lookup_string(fmri, FM_FMRI_HC_PART, &part); perr += nvlist_lookup_string(fmri, FM_FMRI_HC_REVISION, &rev); if (perr != 0) { whinge(mod, NULL, "create_strand: nvlist_lookup_string failed\n"); perr = 0; } perr += topo_prop_set_string(strand, PGNAME(STRAND), FM_FMRI_HC_SERIAL_ID, TOPO_PROP_IMMUTABLE, serial, &perr); perr += topo_prop_set_string(strand, PGNAME(STRAND), FM_FMRI_HC_PART, TOPO_PROP_IMMUTABLE, part, &perr); perr += topo_prop_set_string(strand, PGNAME(STRAND), FM_FMRI_HC_REVISION, TOPO_PROP_IMMUTABLE, rev, &perr); if (perr != 0) whinge(mod, NULL, "create_strand: topo_prop_set_string" "failed\n"); nvlist_free(fmri); topo_mod_strfree(mod, serial); } return (err == 0 && nerr == 0 ? 0 : -1); }
/*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); }
tnode_t * x86pi_gen_chassis(topo_mod_t *mod, tnode_t *t_parent, int smb_id, int instance) { int rv; smbios_info_t ip; smbios_chassis_t ch; x86pi_hcfmri_t ch_hcfmri; tnode_t *ch_node; char *f = "x86pi_gen_chassis"; smbios_hdl_t *shp; shp = topo_mod_smbios(mod); if (shp == NULL) { topo_mod_dprintf(mod, "%s: failed to load SMBIOS\n", f); return (NULL); } /* init fmri struct */ bzero(&ch_hcfmri, sizeof (x86pi_hcfmri_t)); /* grab SMBIOS strings */ rv = smbios_info_common(shp, smb_id, &ip); if (rv != 0) { return (NULL); } /* grab SMBIOS type 3 struct */ rv = smbios_info_chassis(shp, smb_id, &ch); if (rv != 0) { return (NULL); } /* populate string entries */ ch_hcfmri.serial_number = x86pi_cleanup_smbios_str(mod, ip.smbi_serial, 0); ch_hcfmri.version = x86pi_cleanup_smbios_str(mod, ip.smbi_version, 0); ch_hcfmri.manufacturer = x86pi_cleanup_smbios_str(mod, ip.smbi_manufacturer, 0); /* set hc_name and instance */ ch_hcfmri.hc_name = topo_mod_strdup(mod, "chassis"); ch_hcfmri.instance = instance; topo_mod_dprintf(mod, "%s: instance (%d)\n", f, ch_hcfmri.instance); topo_mod_dprintf(mod, "%s: hc name (%s)\n", f, ch_hcfmri.hc_name); topo_mod_dprintf(mod, "%s: Serial Number (%s)\n", f, ch_hcfmri.serial_number); topo_mod_dprintf(mod, "%s: Version (%s)\n", f, ch_hcfmri.version); topo_mod_dprintf(mod, "%s: Manufacturer (%s)\n", f, ch_hcfmri.manufacturer); /* create topo node */ if (!instance) { /* First Chassis SMBIOS Record is Chassis topo instance 0 */ rv = x86pi_enum_generic(mod, &ch_hcfmri, t_parent, NULL, &ch_node, 0); } else { rv = x86pi_enum_generic(mod, &ch_hcfmri, t_parent, t_parent, &ch_node, 0); } if (rv != 0) { topo_mod_dprintf(mod, "%s: failed to create %d tnode\n", f, instance); return (NULL); } /* free up strings */ if (ch_hcfmri.serial_number != NULL) { topo_mod_strfree(mod, (char *)ch_hcfmri.serial_number); } if (ch_hcfmri.version != NULL) { topo_mod_strfree(mod, (char *)ch_hcfmri.version); } if (ch_hcfmri.manufacturer != NULL) { topo_mod_strfree(mod, (char *)ch_hcfmri.manufacturer); } if (ch_hcfmri.hc_name != NULL) { topo_mod_strfree(mod, (char *)ch_hcfmri.hc_name); } return (ch_node); }
static int cpu_n2_mdesc_init(topo_mod_t *mod, md_t *mdp, md_info_t *chip) { mde_cookie_t *list1p, *list2p; md_cpumap_t *mcmp; md_proc_t *procp; md_fru_t *frup; int i, j, cnt; int procid_flag = 0; int nnode, ncomp, nproc, ncpu; char *str = NULL; uint64_t x, sn; char *strserial, *end; nnode = md_node_count(mdp); list1p = topo_mod_zalloc(mod, sizeof (mde_cookie_t) * nnode); /* Count the number of processors and strands */ ncomp = md_scan_dag(mdp, MDE_INVAL_ELEM_COOKIE, md_find_name(mdp, MD_STR_COMPONENT), md_find_name(mdp, "fwd"), list1p); if (ncomp <= 0) { topo_mod_dprintf(mod, "Component nodes not found\n"); topo_mod_free(mod, list1p, sizeof (mde_cookie_t) * nnode); return (-1); } for (i = 0, nproc = 0, ncpu = 0; i < ncomp; i++) { if (md_get_prop_str(mdp, list1p[i], MD_STR_TYPE, &str) == 0 && str != NULL && strcmp(str, MD_STR_PROCESSOR) == 0) { nproc++; /* check if the physical id exists */ if (md_get_prop_val(mdp, list1p[i], MD_STR_ID, &x) == 0) { procid_flag = 1; } } if (md_get_prop_str(mdp, list1p[i], MD_STR_TYPE, &str) == 0 && str && strcmp(str, MD_STR_STRAND) == 0) { ncpu++; } } topo_mod_dprintf(mod, "Found %d procs and %d strands\n", nproc, ncpu); if (nproc == 0 || ncpu == 0) { topo_mod_free(mod, list1p, sizeof (mde_cookie_t) * nnode); return (-1); } /* Alloc processors and strand entries */ list2p = topo_mod_zalloc(mod, sizeof (mde_cookie_t) * 2 * ncpu); chip->nprocs = nproc; chip->procs = topo_mod_zalloc(mod, nproc * sizeof (md_proc_t)); chip->ncpus = ncpu; chip->cpus = topo_mod_zalloc(mod, ncpu * sizeof (md_cpumap_t)); /* Visit each processor node */ procp = chip->procs; mcmp = chip->cpus; for (i = 0, nproc = 0, ncpu = 0; i < ncomp; i++) { if (md_get_prop_str(mdp, list1p[i], MD_STR_TYPE, &str) < 0 || str == NULL || strcmp(str, MD_STR_PROCESSOR)) continue; if (md_get_prop_val(mdp, list1p[i], MD_STR_SERIAL, &sn) < 0) { if (md_get_prop_str(mdp, list1p[i], MD_STR_SERIAL, &strserial) < 0) { topo_mod_dprintf(mod, "Failed to get the serial number of" "proc[%d]\n", nproc); continue; } else { sn = (uint64_t)strtoull(strserial, &end, 16); if (strserial == end) { topo_mod_dprintf(mod, "Failed to convert the serial " "string to serial int of " "proc[%d]\n", nproc); continue; } } } procp->serialno = sn; /* Assign physical proc id */ procp->id = -1; if (procid_flag) { if (md_get_prop_val(mdp, list1p[i], MD_STR_ID, &x) == 0) { procp->id = x; } } else { procp->id = nproc; } topo_mod_dprintf(mod, "proc %d: sn=%llx, id=%d\n", nproc, procp->serialno, procp->id); /* Get all the strands below this proc */ cnt = md_scan_dag(mdp, list1p[i], md_find_name(mdp, MD_STR_COMPONENT), md_find_name(mdp, "fwd"), list2p); topo_mod_dprintf(mod, "proc[%llx]: Found %d fwd components\n", sn, cnt); if (cnt <= 0) { nproc++; procp++; continue; } for (j = 0; j < cnt; j++) { /* Consider only the strand nodes */ if (md_get_prop_str(mdp, list2p[j], MD_STR_TYPE, &str) < 0 || str == NULL || strcmp(str, MD_STR_STRAND)) continue; if (md_get_prop_val(mdp, list2p[j], MD_STR_ID, &x) < 0) x = (uint64_t)-1; /* invalid value */ mcmp->cpumap_id = x; if (md_get_prop_val(mdp, list2p[j], MD_STR_PID, &x) < 0) x = mcmp->cpumap_id; mcmp->cpumap_pid = x; mcmp->cpumap_serialno = sn; mcmp->cpumap_chipidx = nproc; ncpu++; mcmp++; } /* * To get the fru of this proc, follow the back arc up to * find the first node whose fru field is set */ cnt = md_scan_dag(mdp, list1p[i], md_find_name(mdp, MD_STR_COMPONENT), md_find_name(mdp, "back"), list2p); topo_mod_dprintf(mod, "proc[%d]: Found %d back components\n", nproc, cnt); if (cnt <= 0) { nproc++; procp++; continue; } for (j = 0; j < cnt; j++) { /* test the fru field which must be positive number */ if ((md_get_prop_val(mdp, list2p[j], MD_STR_FRU, &x) == 0) && x > 0) break; } if (j < cnt) { /* Found the FRU node, get the fru identity */ topo_mod_dprintf(mod, "proc[%d] sn=%llx has a fru %d\n", nproc, procp->serialno, j); frup = topo_mod_zalloc(mod, sizeof (md_fru_t)); procp->fru = frup; if (!md_get_prop_str(mdp, list2p[j], MD_STR_NAC, &str)) frup->nac = topo_mod_strdup(mod, str); else frup->nac = topo_mod_strdup(mod, MD_FRU_DEF); if (!md_get_prop_str(mdp, list2p[j], MD_STR_PART, &str)) frup->part = topo_mod_strdup(mod, str); if (!md_get_prop_str(mdp, list2p[j], MD_STR_SERIAL, &str)) frup->serial = topo_mod_strdup(mod, str); if (!md_get_prop_str(mdp, list2p[j], MD_STR_DASH, &str)) frup->dash = topo_mod_strdup(mod, str); } else { topo_mod_dprintf(mod, "proc[%d] sn=%llx has no fru\n", i, procp->serialno); } nproc++; procp++; } /* for i */ topo_mod_free(mod, list1p, sizeof (mde_cookie_t) * nnode); topo_mod_free(mod, list2p, sizeof (mde_cookie_t) * 2*chip->ncpus); return (0); }
/* * Request the SAS address of the disk (if any) attached to this mpt_sas * instance at (Enclosure Number, Slot Number). The function returns * -1 on error and sets errno to ENOENT _only_ if the /devices node * (*devctl) does not exist. */ static int get_sas_address(topo_mod_t *mod, char *devctl, uint32_t enclosure, uint32_t slot, char **sas_address) { int ret = -1, en = ENXIO; int fd, i; mptsas_get_disk_info_t gdi; mptsas_disk_info_t *di; size_t disz; bzero(&gdi, sizeof (gdi)); if ((fd = open(devctl, O_RDWR)) == -1) { en = errno; topo_mod_dprintf(mod, "could not open '%s' for ioctl: %s\n", devctl, strerror(errno)); errno = en; return (-1); } if (ioctl(fd, MPTIOCTL_GET_DISK_INFO, &gdi) == -1) { if (errno != ENOENT) en = errno; topo_mod_dprintf(mod, "ioctl 1 on '%s' failed: %s\n", devctl, strerror(errno)); goto out; } gdi.DiskInfoArraySize = disz = sizeof (mptsas_disk_info_t) * gdi.DiskCount; gdi.PtrDiskInfoArray = di = topo_mod_alloc(mod, disz); if (di == NULL) { topo_mod_dprintf(mod, "memory allocation failed\n"); en = ENOMEM; goto out; } if (ioctl(fd, MPTIOCTL_GET_DISK_INFO, &gdi) == -1) { if (errno != ENOENT) en = errno; topo_mod_dprintf(mod, "ioctl 2 on '%s' failed: %s\n", devctl, strerror(errno)); topo_mod_free(mod, di, disz); goto out; } for (i = 0; i < gdi.DiskCount; i++) { if (di[i].Enclosure == enclosure && di[i].Slot == slot) { char sas[17]; /* 16 hex digits and NUL */ (void) snprintf(sas, 17, "%llx", di[i].SasAddress); topo_mod_dprintf(mod, "found mpt_sas disk (%d/%d) " "with adddress %s\n", enclosure, slot, sas); *sas_address = topo_mod_strdup(mod, sas); en = ret = 0; break; } } topo_mod_free(mod, di, disz); out: (void) close(fd); errno = en; return (ret); }
static int mb_get_pri_info(topo_mod_t *mod, char **serialp, char **partp, char **csnp, char **psnp) { char isa[MAXNAMELEN]; md_t *mdp; mde_cookie_t *listp; uint64_t *bufp; ssize_t bufsize = 0; int nfrus, num_nodes, i; char *pstr = NULL; char *sn, *pn, *dn, *csn, *psn; uint32_t type = 0; ldom_hdl_t *lhp; lhp = ldom_init(mb_topo_alloc, mb_topo_free); if (lhp == NULL) { topo_mod_dprintf(mod, "ldom_init failed\n"); return (-1); } (void) sysinfo(SI_MACHINE, isa, MAXNAMELEN); if (strcmp(isa, "sun4v") != 0) { topo_mod_dprintf(mod, "not sun4v architecture%s\n", isa); ldom_fini(lhp); return (-1); } (void) ldom_get_type(lhp, &type); if ((type & LDOM_TYPE_CONTROL) != 0) { bufsize = ldom_get_core_md(lhp, &bufp); } else { bufsize = ldom_get_local_md(lhp, &bufp); } if (bufsize < 1) { topo_mod_dprintf(mod, "Failed to get the pri/md (bufsize=%d)\n", bufsize); ldom_fini(lhp); return (-1); } topo_mod_dprintf(mod, "pri/md bufsize=%d\n", bufsize); if ((mdp = md_init_intern(bufp, mb_topo_alloc, mb_topo_free)) == NULL || (num_nodes = md_node_count(mdp)) < 1) { topo_mod_dprintf(mod, "md_init_intern error\n"); mb_topo_free(bufp, (size_t)bufsize); ldom_fini(lhp); return (-1); } topo_mod_dprintf(mod, "num_nodes=%d\n", num_nodes); if ((listp = (mde_cookie_t *)mb_topo_alloc( sizeof (mde_cookie_t) * num_nodes)) == NULL) { topo_mod_dprintf(mod, "alloc listp error\n"); mb_topo_free(bufp, (size_t)bufsize); (void) md_fini(mdp); ldom_fini(lhp); return (-1); } nfrus = md_scan_dag(mdp, MDE_INVAL_ELEM_COOKIE, md_find_name(mdp, "component"), md_find_name(mdp, "fwd"), listp); if (nfrus <= 0) { topo_mod_dprintf(mod, "error: nfrus=%d\n", nfrus); mb_topo_free(listp, sizeof (mde_cookie_t) * num_nodes); mb_topo_free(bufp, (size_t)bufsize); (void) md_fini(mdp); ldom_fini(lhp); return (-1); } topo_mod_dprintf(mod, "nfrus=%d\n", nfrus); sn = pn = dn = psn = csn = NULL; for (i = 0; i < nfrus; i++) { if (md_get_prop_str(mdp, listp[i], "type", &pstr) == 0) { /* systemboard/motherboard component */ if (strcmp("systemboard", pstr) == 0) { if (md_get_prop_str(mdp, listp[i], "serial_number", &sn) < 0) sn = NULL; if (md_get_prop_str(mdp, listp[i], "part_number", &pn) < 0) pn = NULL; if (md_get_prop_str(mdp, listp[i], "dash_number", &dn) < 0) dn = NULL; } else if (strcmp("product", pstr) == 0) { if (md_get_prop_str(mdp, listp[i], "serial_number", &psn) < 0) psn = NULL; } } /* redefined access method for chassis serial number */ if (md_get_prop_str(mdp, listp[i], "nac", &pstr) == 0) { if (strcmp("SYS", pstr) == 0) { if (md_get_prop_str(mdp, listp[i], "serial_number", &csn) < 0) csn = NULL; } } } *serialp = topo_mod_strdup(mod, sn); i = (pn ? strlen(pn) : 0) + (dn ? strlen(dn) : 0) + 1; pstr = mb_topo_alloc(i); (void) snprintf(pstr, i, "%s%s", pn ? pn : "", dn ? dn : ""); *partp = topo_mod_strdup(mod, pstr); mb_topo_free(pstr, i); *csnp = topo_mod_strdup(mod, csn); *psnp = topo_mod_strdup(mod, psn); mb_topo_free(listp, sizeof (mde_cookie_t) * num_nodes); mb_topo_free(bufp, (size_t)bufsize); (void) md_fini(mdp); ldom_fini(lhp); return (0); }
/* * Calculate the authority information for a node. Inherit the data if * possible, but always create an appropriate property group. */ int x86pi_set_auth(topo_mod_t *mod, x86pi_hcfmri_t *hcfmri, tnode_t *t_parent, tnode_t *t_node) { int result; int err; int is_chassis = 0; int chassis_instance = 0; nvlist_t *auth; char *val = NULL; char *prod = NULL; char *psn = NULL; char *csn = NULL; char *server = NULL; char *f = "x86pi_set_auth"; if (mod == NULL || t_parent == NULL || t_node == NULL) { return (-1); } result = topo_pgroup_create(t_node, &auth_pgroup, &err); if (result != 0 && err != ETOPO_PROP_DEFD) { /* * We failed to create the property group and it was not * already defined. Set the err code and return failure. */ (void) topo_mod_seterrno(mod, err); return (-1); } /* Get the authority information already available from the parent */ auth = topo_mod_auth(mod, t_parent); /* Determnine if this is a chassis node and set it's instance */ if ((strlen(hcfmri->hc_name) == strlen(CHASSIS)) && strncmp(hcfmri->hc_name, CHASSIS, strlen(CHASSIS)) == 0) { is_chassis = 1; chassis_instance = hcfmri->instance; } /* * Set the authority data, inheriting it if possible, but creating it * if necessary. */ /* product-id */ result = topo_prop_inherit(t_node, FM_FMRI_AUTHORITY, FM_FMRI_AUTH_PRODUCT, &err); if (result != 0 && err != ETOPO_PROP_DEFD) { result = nvlist_lookup_string(auth, FM_FMRI_AUTH_PRODUCT, &prod); if (result != 0 || prod == NULL) { /* * No product information in the parent node or auth * list. Use the product information in the hcfrmi * struct. */ prod = (char *)hcfmri->product; if (prod == NULL) { topo_mod_dprintf(mod, "%s: product name not " "found for %s node\n", f, hcfmri->hc_name); } } /* * We continue even if the product information is not available * to enumerate as much as possible. */ if (prod != NULL) { result = topo_prop_set_string(t_node, FM_FMRI_AUTHORITY, FM_FMRI_AUTH_PRODUCT, TOPO_PROP_IMMUTABLE, prod, &err); if (result != 0) { /* Preserve the error and continue */ (void) topo_mod_seterrno(mod, err); topo_mod_dprintf(mod, "%s: failed to set " "property %s (%d) : %s\n", f, FM_FMRI_AUTH_PRODUCT, err, topo_strerror(err)); } } } /* product-sn */ result = topo_prop_inherit(t_node, FM_FMRI_AUTHORITY, FM_FMRI_AUTH_PRODUCT_SN, &err); if (result != 0 && err != ETOPO_PROP_DEFD) { result = nvlist_lookup_string(auth, FM_FMRI_AUTH_PRODUCT_SN, &psn); if (result != 0 || psn == NULL) { /* * No product-sn information in the parent node or auth * list. */ topo_mod_dprintf(mod, "%s: psn not found\n", f); } else { /* * We continue even if the product-sn information is * not available to enumerate as much as possible. */ result = topo_prop_set_string(t_node, FM_FMRI_AUTHORITY, FM_FMRI_AUTH_PRODUCT_SN, TOPO_PROP_IMMUTABLE, psn, &err); if (result != 0) { /* Preserve the error and continue */ (void) topo_mod_seterrno(mod, err); topo_mod_dprintf(mod, "%s: failed to " "set property %s (%d) : %s\n", f, FM_FMRI_AUTH_PRODUCT_SN, err, topo_strerror(err)); } } } /* chassis-id */ if (is_chassis == 0 || (is_chassis == 1 && chassis_instance == 0)) { /* either not a chassis node, or chassis #0 */ result = topo_prop_inherit(t_node, FM_FMRI_AUTHORITY, FM_FMRI_AUTH_CHASSIS, &err); } else { /* chassis 'n' in a >1 chassis system */ result = err = -1; } if (result != 0 && err != ETOPO_PROP_DEFD) { if (is_chassis == 0) { result = nvlist_lookup_string(auth, FM_FMRI_AUTH_CHASSIS, &csn); if (result != 0 || csn == NULL) { /* * No chassis information in the parent * node or auth list. */ topo_mod_dprintf(mod, "%s: csn name not found\n", f); } } else { /* * So as not to blindly set the chassis-id to * chassis #0's serial number. */ csn = val = topo_mod_strdup(mod, hcfmri->serial_number); } /* * We continue even if the chassis information is not available * to enumerate as much as possible. */ if (csn != NULL) { if (is_chassis == 1) result = topo_prop_set_string(t_node, FM_FMRI_AUTHORITY, FM_FMRI_AUTH_CHASSIS, TOPO_PROP_MUTABLE, csn, &err); else result = topo_prop_set_string(t_node, FM_FMRI_AUTHORITY, FM_FMRI_AUTH_CHASSIS, TOPO_PROP_IMMUTABLE, csn, &err); if (result != 0) { /* Preserve the error and continue */ (void) topo_mod_seterrno(mod, err); topo_mod_dprintf(mod, "%s: failed to " "set property %s (%d) : %s\n", f, FM_FMRI_AUTH_CHASSIS, err, topo_strerror(err)); } } if (val != NULL) { topo_mod_strfree(mod, val); val = NULL; } } /* server-id */ result = topo_prop_inherit(t_node, FM_FMRI_AUTHORITY, FM_FMRI_AUTH_SERVER, &err); if (result != 0 && err != ETOPO_PROP_DEFD) { result = nvlist_lookup_string(auth, FM_FMRI_AUTH_SERVER, &server); if (result != 0 || server == NULL) { /* * No server information in the parent node or auth * list. Find the server information in hostname. */ server = val = x86pi_get_serverid(mod); if (server == NULL) { topo_mod_dprintf(mod, "%s: server " "name not found for %s node\n", f, hcfmri->hc_name); } } /* * We continue even if the server information is not available * to enumerate as much as possible. */ if (server != NULL) { result = topo_prop_set_string(t_node, FM_FMRI_AUTHORITY, FM_FMRI_AUTH_SERVER, TOPO_PROP_IMMUTABLE, server, &err); if (result != 0) { /* Preserve the error and continue */ (void) topo_mod_seterrno(mod, err); topo_mod_dprintf(mod, "%s: failed to " "set property %s (%d) : %s\n", f, FM_FMRI_AUTH_SERVER, err, topo_strerror(err)); } } if (val != NULL) topo_mod_strfree(mod, val); } nvlist_free(auth); return (0); }
static int dev_di_node_add(di_node_t node, char *devid, disk_cbdata_t *cbp) { topo_mod_t *mod = cbp->dcb_mod; dev_di_node_t *dnode; di_path_t pnode; char *path; int mlen; char *minorpath; char *extn = ":a"; char *s; int64_t *nblocksp; uint64_t nblocks; int *dblksizep; uint_t dblksize; char lentry[MAXPATHLEN]; int pathcount; int *inq_dtype, itype; int i; if (devid) { /* * Check for list duplicate using devid search. * Note if there is no devid, then we can end up with duplicates * in the list, but this doesn't do any harm. */ for (dnode = topo_list_next(cbp->dcb_list); dnode != NULL; dnode = topo_list_next(dnode)) { if (dnode->ddn_devid && devid_str_compare(dnode->ddn_devid, devid) == 0) { topo_mod_dprintf(mod, "dev_di_node_add: " "already there %s\n", devid); return (0); } } } if ((dnode = topo_mod_zalloc(mod, sizeof (dev_di_node_t))) == NULL) return (-1); if (devid) { /* Establish the devid. */ dnode->ddn_devid = topo_mod_strdup(mod, devid); if (dnode->ddn_devid == NULL) goto error; } /* Establish the devinfo dpath */ if ((path = di_devfs_path(node)) == NULL) { (void) topo_mod_seterrno(mod, errno); goto error; } dnode->ddn_dpath = topo_mod_strdup(mod, path); di_devfs_path_free(path); if (dnode->ddn_dpath == NULL) goto error; /* * Establish the physical ppath and target ports. If the device is * non-mpxio then dpath and ppath are the same, and the target port is a * property of the device node. * * If dpath is a client node under scsi_vhci, then iterate over all * paths and get their physical paths and target port properrties. * di_path_client_next_path call below will * return non-NULL, and ppath is set to the physical path to the first * pathinfo node. * * NOTE: It is possible to get a generic.vs.non-generic path * for di_devfs_path.vs.di_path_devfs_path like: * xml: /pci@7b,0/pci1022,7458@11/pci1000,3060@2/sd@2,0 * pnode: /pci@7b,0/pci1022,7458@11/pci1000,3060@2/disk@2,0 * To resolve this issue disk_declare_path() needs to use the * special di_devfs_path_match() interface. */ pathcount = 0; pnode = NULL; while ((pnode = di_path_client_next_path(node, pnode)) != NULL) { pathcount++; } if (pathcount == 0) { if ((dnode->ddn_ppath = topo_mod_zalloc(mod, sizeof (char *))) == NULL) goto error; dnode->ddn_ppath_count = 1; if ((dnode->ddn_ppath[0] = topo_mod_strdup(mod, dnode->ddn_dpath)) == NULL) goto error; if ((dnode->ddn_target_port = topo_mod_zalloc(mod, sizeof (char *))) == NULL) goto error; if ((dnode->ddn_attached_port = topo_mod_zalloc(mod, sizeof (char *))) == NULL) goto error; if ((dnode->ddn_bridge_port = topo_mod_zalloc(mod, sizeof (char *))) == NULL) goto error; /* There should be only one target port for a devinfo node. */ if ((di_prop_lookup_strings(DDI_DEV_T_ANY, node, SCSI_ADDR_PROP_TARGET_PORT, &s)) == 1) { if ((dnode->ddn_target_port[0] = topo_mod_strdup(mod, scsi_wwnstr_skip_ua_prefix(s))) == NULL) goto error; } if ((di_prop_lookup_strings(DDI_DEV_T_ANY, node, SCSI_ADDR_PROP_ATTACHED_PORT, &s)) == 1) { /* There should be one attached port if any. */ if ((dnode->ddn_attached_port[0] = topo_mod_strdup(mod, scsi_wwnstr_skip_ua_prefix(s))) == NULL) goto error; } if ((di_prop_lookup_strings(DDI_DEV_T_ANY, node, SCSI_ADDR_PROP_BRIDGE_PORT, &s)) == 1) { /* There should be one bridge port if any. */ if ((dnode->ddn_bridge_port[0] = topo_mod_strdup(mod, scsi_wwnstr_skip_ua_prefix(s))) == NULL) goto error; } } else { /* processing a scsi_vhci device. */ if ((dnode->ddn_ppath = topo_mod_zalloc(mod, pathcount * sizeof (char *))) == NULL) goto error; dnode->ddn_ppath_count = pathcount; if ((dnode->ddn_target_port = topo_mod_zalloc(mod, pathcount * sizeof (char *))) == NULL) goto error; if ((dnode->ddn_attached_port = topo_mod_zalloc(mod, pathcount * sizeof (char *))) == NULL) goto error; if ((dnode->ddn_bridge_port = topo_mod_zalloc(mod, pathcount * sizeof (char *))) == NULL) goto error; pnode = NULL; pathcount = 0; while ((pnode = di_path_client_next_path(node, pnode)) != NULL) { if ((path = di_path_devfs_path(pnode)) == NULL) { (void) topo_mod_seterrno(mod, errno); goto error; } dnode->ddn_ppath[pathcount] = topo_mod_strdup(mod, path); di_devfs_path_free(path); if (dnode->ddn_ppath[pathcount] == NULL) goto error; if ((di_path_prop_lookup_strings(pnode, SCSI_ADDR_PROP_TARGET_PORT, &s)) == 1) { if ((dnode->ddn_target_port[pathcount] = topo_mod_strdup(mod, scsi_wwnstr_skip_ua_prefix(s))) == NULL) goto error; } if ((di_path_prop_lookup_strings(pnode, SCSI_ADDR_PROP_ATTACHED_PORT, &s)) == 1) { if ((dnode->ddn_attached_port[pathcount] = topo_mod_strdup(mod, scsi_wwnstr_skip_ua_prefix(s))) == NULL) goto error; } if ((di_path_prop_lookup_strings(pnode, SCSI_ADDR_PROP_BRIDGE_PORT, &s)) == 1) { if ((dnode->ddn_bridge_port[pathcount] = topo_mod_strdup(mod, scsi_wwnstr_skip_ua_prefix(s))) == NULL) goto error; } pathcount++; } } /* * Find the public /dev name for a disk by adding a minor name and using * di_devlink interface for reverse translation (use devinfo path). */ if (di_prop_lookup_ints(DDI_DEV_T_ANY, node, "inquiry-device-type", &inq_dtype) > 0) { dnode->ddn_dtype = *inq_dtype; itype = (*inq_dtype) & DTYPE_MASK; if (itype == DTYPE_DIRECT) { mlen = strlen(dnode->ddn_dpath) + strlen(extn) + 1; if ((minorpath = topo_mod_alloc(mod, mlen)) == NULL) goto error; (void) snprintf(minorpath, mlen, "%s%s", dnode->ddn_dpath, extn); cbp->dcb_dnode = dnode; (void) di_devlink_walk(cbp->dcb_devhdl, "^dsk/", minorpath, DI_PRIMARY_LINK, cbp, disk_devlink_callback); topo_mod_free(mod, minorpath, mlen); if (dnode->ddn_lpath == NULL) { topo_mod_dprintf(mod, "dev_di_node_add: " "failed to determine logical path"); } } } else { dnode->ddn_dtype = DTYPE_UNKNOWN; } /* cache various bits of optional information about the device. */ if (di_prop_lookup_strings(DDI_DEV_T_ANY, node, INQUIRY_VENDOR_ID, &s) > 0) { if ((dnode->ddn_mfg = disk_trim_whitespace(mod, s)) == NULL) goto error; } if (di_prop_lookup_strings(DDI_DEV_T_ANY, node, INQUIRY_PRODUCT_ID, &s) > 0) { if ((dnode->ddn_model = disk_trim_whitespace(mod, s)) == NULL) goto error; } if (di_prop_lookup_strings(DDI_DEV_T_ANY, node, INQUIRY_REVISION_ID, &s) > 0) { if ((dnode->ddn_firm = disk_trim_whitespace(mod, s)) == NULL) goto error; } if (di_prop_lookup_strings(DDI_DEV_T_ANY, node, INQUIRY_SERIAL_NO, &s) > 0) { if ((dnode->ddn_serial = disk_trim_whitespace(mod, s)) == NULL) goto error; } if (di_prop_lookup_int64(DDI_DEV_T_ANY, node, "device-nblocks", &nblocksp) > 0) { nblocks = (uint64_t)*nblocksp; /* * To save kernel memory, the driver may not define * "device-dblksize" when its value is default DEV_BSIZE. */ if (di_prop_lookup_ints(DDI_DEV_T_ANY, node, "device-dblksize", &dblksizep) > 0) dblksize = (uint_t)*dblksizep; else dblksize = DEV_BSIZE; /* default value */ (void) snprintf(lentry, sizeof (lentry), "%" PRIu64, nblocks * dblksize); if ((dnode->ddn_cap = topo_mod_strdup(mod, lentry)) == NULL) goto error; } topo_mod_dprintf(mod, "dev_di_node_add: " "adding %s\n", devid ? dnode->ddn_devid : "NULL devid"); topo_mod_dprintf(mod, " " " %s\n", dnode->ddn_dpath); for (i = 0; i < dnode->ddn_ppath_count; i++) { topo_mod_dprintf(mod, " " " %s\n", dnode->ddn_ppath[i]); } topo_list_append(cbp->dcb_list, dnode); return (0); error: dev_di_node_free(mod, dnode); return (-1); }
static int xaui_get_pri_label(topo_mod_t *mod, topo_instance_t n, void *priv, char **labelp) { ldom_hdl_t *hdlp; uint32_t type = 0; ssize_t bufsize = 0; uint64_t *bufp; md_t *mdp; int num_nodes, ncomp; mde_cookie_t *listp; char *pstr = NULL; int i; char *path; /* Get device path minus the device names */ path = xaui_get_path(mod, priv, n); if (path == NULL) { topo_mod_dprintf(mod, "can't get path\n"); return (-1); } hdlp = ldom_init(xaui_topo_alloc, xaui_topo_free); if (hdlp == NULL) { topo_mod_dprintf(mod, "ldom_init failed\n"); return (-1); } (void) ldom_get_type(hdlp, &type); if ((type & LDOM_TYPE_CONTROL) != 0) { bufsize = ldom_get_core_md(hdlp, &bufp); } else { bufsize = ldom_get_local_md(hdlp, &bufp); } if (bufsize < 1) { topo_mod_dprintf(mod, "failed to get pri/md (%d)\n", bufsize); ldom_fini(hdlp); return (-1); } if ((mdp = md_init_intern(bufp, xaui_topo_alloc, xaui_topo_free)) == NULL || (num_nodes = md_node_count(mdp)) < 1) { topo_mod_dprintf(mod, "md_init_intern failed\n"); xaui_topo_free(bufp, (size_t)bufsize); ldom_fini(hdlp); return (-1); } if ((listp = (mde_cookie_t *)xaui_topo_alloc( sizeof (mde_cookie_t) * num_nodes)) == NULL) { topo_mod_dprintf(mod, "can't alloc listp\n"); xaui_topo_free(bufp, (size_t)bufsize); (void) md_fini(mdp); ldom_fini(hdlp); return (-1); } ncomp = md_scan_dag(mdp, MDE_INVAL_ELEM_COOKIE, md_find_name(mdp, "component"), md_find_name(mdp, "fwd"), listp); if (ncomp <= 0) { topo_mod_dprintf(mod, "no component nodes found\n"); xaui_topo_free(listp, sizeof (mde_cookie_t) * num_nodes); xaui_topo_free(bufp, (size_t)bufsize); (void) md_fini(mdp); ldom_fini(hdlp); return (-1); } topo_mod_dprintf(mod, "number of comps (%d)\n", ncomp); for (i = 0; i < ncomp; i++) { /* * Look for type == "io", topo-hc-name == "xaui"; * match "path" md property. */ if ((md_get_prop_str(mdp, listp[i], "type", &pstr) == 0) && (pstr != NULL) && (strncmp(pstr, "io", strlen(pstr)) == 0) && (md_get_prop_str(mdp, listp[i], "topo-hc-name", &pstr) == 0) && (pstr != NULL) && (strncmp(pstr, "xaui", strlen(pstr)) == 0) && (md_get_prop_str(mdp, listp[i], "path", &pstr) == 0) && (pstr != NULL)) { /* check node path */ if (strncmp(pstr, path, sizeof (path)) == 0) { /* this is the node, grab the label */ if (md_get_prop_str(mdp, listp[i], "nac", &pstr) == 0) { *labelp = topo_mod_strdup(mod, pstr); /* need to free this later */ freeprilabel = 1; break; } } } } xaui_topo_free(listp, sizeof (mde_cookie_t) * num_nodes); xaui_topo_free(bufp, (size_t)bufsize); (void) md_fini(mdp); ldom_fini(hdlp); if (path != NULL) { xaui_topo_free(path, strlen(path) + 1); } return (0); }