/* * The functions in this file do a dev tree walk to build up a model of the * disks, controllers and paths on the system. This model is returned in the * args->disk_listp and args->controller_listp members of the args param. * There is no global data for this file so it is thread safe. It is up to * the caller to merge the resulting model with any existing model that is * cached. The caller must also free the memory for this model when it is * no longer needed. */ void findevs(struct search_args *args) { di_node_t di_root; args->bus_listp = NULL; args->controller_listp = NULL; args->disk_listp = NULL; args->dev_walk_status = 0; args->handle = di_devlink_init(NULL, 0); /* * Have to make several passes at this with the new devfs caching. * First, we find non-mpxio devices. Then we find mpxio/multipath * devices. */ di_root = di_init("/", DINFOCACHE); args->ph = di_prom_init(); (void) di_walk_minor(di_root, NULL, 0, args, add_devs); di_fini(di_root); di_root = di_init("/", DINFOCPYALL|DINFOPATH); (void) di_walk_minor(di_root, NULL, 0, args, add_devs); di_fini(di_root); (void) di_devlink_fini(&(args->handle)); clean_paths(args); }
/* * Handle DR events. Only supports cpu add and remove. */ int update_devices(char *dev, int op) { di_node_t di_root; if ((di_root = di_init("/", DINFOCPYALL)) == DI_NODE_NIL) return (PICL_FAILURE); if ((ph = di_prom_init()) == NULL) return (PICL_FAILURE); if (op == DEV_ADD) { if (strcmp(dev, OBP_CPU) == 0) add_cpus(di_root); } if (op == DEV_REMOVE) { if (strcmp(dev, OBP_CPU) == 0) remove_cpus(di_root); } di_fini(di_root); di_prom_fini(ph); return (PICL_SUCCESS); }
/* * Attempt to access PCI subsystem using Solaris's devfs interface. * Solaris version */ _pci_hidden int pci_system_solx_devfs_create( void ) { int err = 0; di_node_t di_node; probe_info_t pinfo; struct pci_device_private *devices; if (nexus_list != NULL) { return 0; } if ((di_node = di_init("/", DINFOCPYALL)) == DI_NODE_NIL) { err = errno; (void) fprintf(stderr, "di_init() failed: %s\n", strerror(errno)); return (err); } if ((devices = calloc(INITIAL_NUM_DEVICES, sizeof (struct pci_device_private))) == NULL) { err = errno; di_fini(di_node); return (err); } #ifdef __sparc if ((di_phdl = di_prom_init()) == DI_PROM_HANDLE_NIL) (void) fprintf(stderr, "di_prom_init failed: %s\n", strerror(errno)); #endif pinfo.num_allocated_elems = INITIAL_NUM_DEVICES; pinfo.num_devices = 0; pinfo.devices = devices; (void) di_walk_minor(di_node, DDI_NT_REGACC, 0, &pinfo, probe_nexus_node); di_fini(di_node); if ((pci_sys = calloc(1, sizeof (struct pci_system))) == NULL) { err = errno; free(devices); return (err); } pci_sys->methods = &solx_devfs_methods; pci_sys->devices = pinfo.devices; pci_sys->num_devices = pinfo.num_devices; return (err); }
/*ARGSUSED*/ static int iob_enum(topo_mod_t *mp, tnode_t *pn, const char *name, topo_instance_t imin, topo_instance_t imax, void *notused) { topo_mod_t *hbmod; int rv; did_hash_t *didhash; di_prom_handle_t promtree; if (strcmp(name, IOBOARD) != 0) { topo_mod_dprintf(mp, "Currently only know how to enumerate %s components.\n", IOBOARD); return (0); } if ((promtree = di_prom_init()) == DI_PROM_HANDLE_NIL) { topo_mod_dprintf(mp, "Ioboard enumerator: di_prom_handle_init failed.\n"); return (-1); } /* * Load the hostbridge enumerator, we'll soon need it! */ if ((hbmod = hb_enumr_load(mp, pn)) == NULL) { di_prom_fini(promtree); return (-1); } if ((didhash = did_hash_init(mp)) == NULL) { topo_mod_dprintf(mp, "Hash initialization for ioboard enumerator failed.\n"); di_prom_fini(promtree); topo_mod_unload(hbmod); return (-1); } rv = platform_iob_enum(pn, imin, imax, didhash, promtree, mp); did_hash_fini(didhash); di_prom_fini(promtree); topo_mod_unload(hbmod); if (rv < 0) return (topo_mod_seterrno(mp, EMOD_PARTIAL_ENUM)); else return (0); }
/* * Take a snapshot of the device tree, i.e. get a devinfo handle and * a PROM handle. */ static boolean_t snapshot_devtree(void) { /* * Deallocate any existing devinfo stuff first. */ destroy_snapshot(); if ((root_node = di_init("/", DINFOCPYALL)) == DI_NODE_NIL || (phdl = di_prom_init()) == DI_PROM_HANDLE_NIL) { destroy_snapshot(); return (B_FALSE); } return (B_TRUE); }
/* * Force all "network" drivers to be loaded. * * Returns: ICFG_SUCCESS or ICFG_FAILURE. In the case of * ICFG_FAILURE, syserr will contain the errno. */ static int nic_load_drivers(int *syserr) { di_node_t root_node; di_prom_handle_t ph; int ret; root_node = di_init(NIC_DEVTREE_ROOT, DINFOCPYALL); if (root_node == DI_NODE_NIL) { *syserr = errno; return (ICFG_FAILURE); } /* * Create handle to PROM */ if ((ph = di_prom_init()) == DI_PROM_HANDLE_NIL) { *syserr = errno; di_fini(root_node); return (ICFG_FAILURE); } /* * Walk nodes and make sure all network devices have * drivers loaded so that devinfo has accurate data. */ ret = di_walk_node(root_node, DI_WALK_CLDFIRST, ph, process_node); if (ret != 0) { *syserr = errno; di_prom_fini(ph); di_fini(root_node); return (ICFG_FAILURE); } /* * Clean up handles */ di_prom_fini(ph); di_fini(root_node); return (ICFG_SUCCESS); }
/* * Retrieve the version from the card. * uses PROM properties */ static int emulex_fcodeversion(di_node_t node, uchar_t *ver) { di_prom_prop_t promprop; di_prom_handle_t ph; char *promname; uchar_t *ver_data = NULL; int size, found = 0; /* check to make sure ver is not NULL */ if (ver == NULL) { return (1); } if ((ph = di_prom_init()) == DI_PROM_HANDLE_NIL) { return (1); } for (promprop = di_prom_prop_next(ph, node, DI_PROM_PROP_NIL); promprop != DI_PROM_PROP_NIL; promprop = di_prom_prop_next(ph, node, promprop)) { if (((promname = di_prom_prop_name( promprop)) != NULL) && (strcmp(promname, "fcode-version") == 0)) { size = di_prom_prop_data(promprop, &ver_data); (void) memset(ver, NULL, size); (void) memcpy(ver, ver_data, size); found = 1; } } if (found) { return (0); } else { return (1); } }
static int device_tree_to_md(mmd_t *mdp, md_node_t *top) { di_node_t node; di_node_t root; di_prom_handle_t ph; int rv = 0; root = di_init("/", DINFOSUBTREE | DINFOPROP); if (root == DI_NODE_NIL) { LDMA_ERR("di_init cannot find device tree root node."); return (errno); } ph = di_prom_init(); if (ph == DI_PROM_HANDLE_NIL) { LDMA_ERR("di_prom_init failed."); di_fini(root); return (errno); } node = di_child_node(root); while (node != NULL) { if (is_root_complex(ph, node)) { rv = create_children(mdp, ph, top, node); if (rv != 0) break; } node = di_sibling_node(node); } di_prom_fini(ph); di_fini(root); return (rv); }
void fmd_create(fmd_t *dp, const char *arg0, const char *root, const char *conf) { fmd_conf_path_t *pap; char file[PATH_MAX]; const char *name; fmd_stat_t *sp; int i; smbios_hdl_t *shp; smbios_system_t s1; smbios_info_t s2; id_t id; di_prom_handle_t promh = DI_PROM_HANDLE_NIL; di_node_t rooth = DI_NODE_NIL; char *bufp; (void) sysinfo(SI_PLATFORM, _fmd_plat, sizeof (_fmd_plat)); (void) sysinfo(SI_ARCHITECTURE, _fmd_isa, sizeof (_fmd_isa)); (void) uname(&_fmd_uts); if ((shp = smbios_open(NULL, SMB_VERSION, 0, NULL)) != NULL) { if ((id = smbios_info_system(shp, &s1)) != SMB_ERR && smbios_info_common(shp, id, &s2) != SMB_ERR) { (void) strlcpy(_fmd_prod, s2.smbi_product, MAXNAMELEN); (void) strlcpy(_fmd_csn, s2.smbi_serial, MAXNAMELEN); } smbios_close(shp); } else if ((rooth = di_init("/", DINFOPROP)) != DI_NODE_NIL && (promh = di_prom_init()) != DI_PROM_HANDLE_NIL) { if (di_prom_prop_lookup_bytes(promh, rooth, "chassis-sn", (unsigned char **)&bufp) != -1) { (void) strlcpy(_fmd_csn, bufp, MAXNAMELEN); } } if (promh != DI_PROM_HANDLE_NIL) di_prom_fini(promh); if (rooth != DI_NODE_NIL) di_fini(rooth); bzero(dp, sizeof (fmd_t)); dp->d_version = _fmd_version; dp->d_pname = fmd_strbasename(arg0); dp->d_pid = getpid(); if (pthread_key_create(&dp->d_key, NULL) != 0) fmd_error(EFMD_EXIT, "failed to create pthread key"); (void) pthread_mutex_init(&dp->d_xprt_lock, NULL); (void) pthread_mutex_init(&dp->d_err_lock, NULL); (void) pthread_mutex_init(&dp->d_thr_lock, NULL); (void) pthread_mutex_init(&dp->d_mod_lock, NULL); (void) pthread_mutex_init(&dp->d_stats_lock, NULL); (void) pthread_rwlock_init(&dp->d_log_lock, NULL); /* * A small number of properties must be set manually before we open * the root configuration file. These include any settings for our * memory allocator and path expansion token values, because these * values are needed by the routines in fmd_conf.c itself. After * the root configuration file is processed, we reset these properties * based upon the latest values from the configuration file. */ dp->d_alloc_msecs = 10; dp->d_alloc_tries = 3; dp->d_str_buckets = 211; dp->d_rootdir = root ? root : ""; dp->d_platform = _fmd_plat; dp->d_machine = _fmd_uts.machine; dp->d_isaname = _fmd_isa; dp->d_conf = fmd_conf_open(conf, sizeof (_fmd_conf) / sizeof (_fmd_conf[0]), _fmd_conf, FMD_CONF_DEFER); if (dp->d_conf == NULL) { fmd_error(EFMD_EXIT, "failed to load required configuration properties\n"); } (void) fmd_conf_getprop(dp->d_conf, "alloc.msecs", &dp->d_alloc_msecs); (void) fmd_conf_getprop(dp->d_conf, "alloc.tries", &dp->d_alloc_tries); (void) fmd_conf_getprop(dp->d_conf, "strbuckets", &dp->d_str_buckets); (void) fmd_conf_getprop(dp->d_conf, "platform", &dp->d_platform); (void) fmd_conf_getprop(dp->d_conf, "machine", &dp->d_machine); (void) fmd_conf_getprop(dp->d_conf, "isaname", &dp->d_isaname); /* * Manually specified rootdirs override config files, so only update * d_rootdir based on the config files we parsed if no 'root' was set. */ if (root == NULL) (void) fmd_conf_getprop(dp->d_conf, "rootdir", &dp->d_rootdir); else (void) fmd_conf_setprop(dp->d_conf, "rootdir", dp->d_rootdir); /* * Once the base conf file properties are loaded, lookup the values * of $conf_path and $conf_file and merge in any other conf files. */ (void) fmd_conf_getprop(dp->d_conf, "conf_path", &pap); (void) fmd_conf_getprop(dp->d_conf, "conf_file", &name); for (i = 0; i < pap->cpa_argc; i++) { (void) snprintf(file, sizeof (file), "%s/%s", pap->cpa_argv[i], name); if (access(file, F_OK) == 0) fmd_conf_merge(dp->d_conf, file); } /* * Update the value of fmd.d_fg based on "fg". We cache this property * because it must be accessed deep within fmd at fmd_verror() time. * Update any other properties that must be cached for performance. */ (void) fmd_conf_getprop(fmd.d_conf, "fg", &fmd.d_fg); (void) fmd_conf_getprop(fmd.d_conf, "xprt.ttl", &fmd.d_xprt_ttl); /* * Initialize our custom libnvpair allocator and create an nvlist for * authority elements corresponding to this instance of the daemon. */ (void) nv_alloc_init(&dp->d_nva, &fmd_nv_alloc_ops); dp->d_auth = fmd_protocol_authority(); /* * The fmd_module_t for the root module must be created manually. Most * of it remains unused and zero, except for the few things we fill in. */ dp->d_rmod = fmd_zalloc(sizeof (fmd_module_t), FMD_SLEEP); dp->d_rmod->mod_name = fmd_strdup(dp->d_pname, FMD_SLEEP); dp->d_rmod->mod_fmri = fmd_protocol_fmri_module(dp->d_rmod); fmd_list_append(&dp->d_mod_list, dp->d_rmod); fmd_module_hold(dp->d_rmod); (void) pthread_mutex_init(&dp->d_rmod->mod_lock, NULL); (void) pthread_cond_init(&dp->d_rmod->mod_cv, NULL); (void) pthread_mutex_init(&dp->d_rmod->mod_stats_lock, NULL); dp->d_rmod->mod_thread = fmd_thread_xcreate(dp->d_rmod, pthread_self()); dp->d_rmod->mod_stats = fmd_zalloc(sizeof (fmd_modstat_t), FMD_SLEEP); dp->d_rmod->mod_ustat = fmd_ustat_create(); if (pthread_setspecific(dp->d_key, dp->d_rmod->mod_thread) != 0) fmd_error(EFMD_EXIT, "failed to attach main thread key"); if ((dp->d_stats = (fmd_statistics_t *)fmd_ustat_insert( dp->d_rmod->mod_ustat, FMD_USTAT_NOALLOC, sizeof (_fmd_stats) / sizeof (fmd_stat_t), (fmd_stat_t *)&_fmd_stats, NULL)) == NULL) fmd_error(EFMD_EXIT, "failed to initialize statistics"); (void) pthread_mutex_lock(&dp->d_rmod->mod_lock); dp->d_rmod->mod_flags |= FMD_MOD_INIT; (void) pthread_mutex_unlock(&dp->d_rmod->mod_lock); /* * In addition to inserting the _fmd_stats collection of program-wide * statistics, we also insert a statistic named after each of our * errors and update these counts in fmd_verror() (see fmd_subr.c). */ dp->d_errstats = sp = fmd_zalloc(sizeof (fmd_stat_t) * (EFMD_END - EFMD_UNKNOWN), FMD_SLEEP); for (i = 0; i < EFMD_END - EFMD_UNKNOWN; i++, sp++) { (void) snprintf(sp->fmds_name, sizeof (sp->fmds_name), "err.%s", strrchr(fmd_errclass(EFMD_UNKNOWN + i), '.') + 1); sp->fmds_type = FMD_TYPE_UINT64; } (void) fmd_ustat_insert(dp->d_rmod->mod_ustat, FMD_USTAT_NOALLOC, EFMD_END - EFMD_UNKNOWN, dp->d_errstats, NULL); }
picl_errno_t get_fru_path(char *parent_path, frutree_frunode_t *frup) { picl_errno_t rc = 0; picl_nodehdl_t loch; di_node_t rnode; frutree_devinfo_t *devinfo = NULL; char slot_type[PICL_PROPNAMELEN_MAX]; char probe_path[PICL_PROPNAMELEN_MAX]; char bus_addr[PICL_PROPNAMELEN_MAX]; if ((rc = ptree_get_propval_by_name(frup->frunodeh, PICL_PROP_PARENT, &loch, sizeof (loch))) != PICL_SUCCESS) { return (rc); } if ((rc = ptree_get_propval_by_name(loch, PICL_PROP_SLOT_TYPE, slot_type, sizeof (slot_type))) != PICL_SUCCESS) { return (rc); } if (strcmp(slot_type, SANIBEL_SCSI_SLOT) == 0 || strcmp(slot_type, SANIBEL_IDE_SLOT) == 0) { if (ptree_get_propval_by_name(loch, PICL_PROP_PROBE_PATH, probe_path, sizeof (probe_path)) != PICL_SUCCESS) { return (rc); } (void) strncpy(frup->fru_path, probe_path, sizeof (frup->fru_path)); return (PICL_SUCCESS); } prom_handle = di_prom_init(); rnode = di_init(parent_path, DINFOSUBTREE|DINFOMINOR); if (rnode == DI_NODE_NIL) { di_prom_fini(prom_handle); return (PICL_FAILURE); } devinfo = (frutree_devinfo_t *)malloc(sizeof (frutree_devinfo_t)); if (devinfo == NULL) { di_fini(rnode); di_prom_fini(prom_handle); return (PICL_NOSPACE); } if (ptree_get_propval_by_name(loch, PICL_PROP_BUS_ADDR, bus_addr, sizeof (bus_addr)) != PICL_SUCCESS) { free(devinfo); di_fini(rnode); di_prom_fini(prom_handle); return (rc); } devinfo->rnode = rnode; (void) strncpy(devinfo->bus_addr, bus_addr, sizeof (devinfo->bus_addr)); devinfo->path[0] = '\0'; devinfo->arg = frup; if (di_walk_node(rnode, DI_WALK_SIBFIRST, &devinfo, walk_tree) != 0) { di_fini(rnode); di_prom_fini(prom_handle); free(devinfo); return (PICL_FAILURE); } di_fini(rnode); di_prom_fini(prom_handle); if (devinfo->path[0]) { (void) strncpy(frup->fru_path, devinfo->path, sizeof (frup->fru_path)); free(devinfo); return (PICL_SUCCESS); } else { free(devinfo); return (PICL_NODENOTFOUND); } }
static char * topo_snap_create(topo_hdl_t *thp, int *errp, boolean_t need_force) { uuid_t uuid; char *ustr = NULL; topo_hdl_lock(thp); if (thp->th_uuid != NULL) { *errp = ETOPO_HDL_UUID; topo_hdl_unlock(thp); return (NULL); } if ((thp->th_uuid = topo_hdl_zalloc(thp, TOPO_UUID_SIZE)) == NULL) { *errp = ETOPO_NOMEM; topo_dprintf(thp, TOPO_DBG_ERR, "unable to allocate uuid: %s\n", topo_strerror(*errp)); topo_hdl_unlock(thp); return (NULL); } uuid_generate(uuid); uuid_unparse(uuid, thp->th_uuid); if ((ustr = topo_hdl_strdup(thp, thp->th_uuid)) == NULL) { *errp = ETOPO_NOMEM; topo_hdl_unlock(thp); return (NULL); } if (need_force) { topo_dprintf(thp, TOPO_DBG_FORCE, "taking a DINFOFORCE snapshot\n"); thp->th_di = di_init("/", DINFOFORCE | DINFOSUBTREE | DINFOMINOR | DINFOPROP | DINFOPATH); } else { thp->th_di = di_init("/", DINFOCACHE); } thp->th_pi = di_prom_init(); if (topo_tree_enum_all(thp) < 0) { topo_dprintf(thp, TOPO_DBG_ERR, "enumeration failure: %s\n", topo_hdl_errmsg(thp)); if (topo_hdl_errno(thp) == ETOPO_ENUM_FATAL) { *errp = thp->th_errno; if (thp->th_di != DI_NODE_NIL) { di_fini(thp->th_di); thp->th_di = DI_NODE_NIL; } if (thp->th_pi != DI_PROM_HANDLE_NIL) { di_prom_fini(thp->th_pi); thp->th_pi = DI_PROM_HANDLE_NIL; } topo_hdl_strfree(thp, ustr); topo_hdl_unlock(thp); return (NULL); } } if (thp->th_ipmi != NULL && ipmi_sdr_changed(thp->th_ipmi) && ipmi_sdr_refresh(thp->th_ipmi) != 0) { topo_dprintf(thp, TOPO_DBG_ERR, "failed to refresh IPMI sdr repository: %s\n", ipmi_errmsg(thp->th_ipmi)); } topo_hdl_unlock(thp); return (ustr); }