Example #1
0
/*
 * 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);
}
Example #2
0
/*
 * 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);
}
Example #4
0
/*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);
}
Example #5
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);
}
Example #6
0
/*
 * 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);
}
Example #7
0
/*
 * 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);
	}
}
Example #8
0
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);
}
Example #9
0
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);
}
Example #10
0
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);
	}
}
Example #11
0
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);
}