示例#1
0
static int
is_ctrl(di_node_t node, di_minor_t minor)
{
	char	*type;
	char	*name;
	int	type_index;

	type = di_minor_nodetype(minor);
	type_index = 0;

	while (ctrltypes[type_index] != NULL) {
		if (libdiskmgt_str_eq(type, ctrltypes[type_index])) {
			return (1);
		}
		type_index++;
	}

	name = di_node_name(node);
	if (libdiskmgt_str_eq(type, DDI_PSEUDO) &&
	    (libdiskmgt_str_eq(name, "ide") ||
	    libdiskmgt_str_eq(name, "xpvd")))
		return (1);

	return (0);
}
示例#2
0
/*
 * Given the root node of the device tree.
 * compare it to the picl tree and add to it cpus
 * that are new.
 */
static void
add_cpus(di_node_t di_node)
{
	int		err;
	di_node_t	cnode;
	picl_nodehdl_t	plath;
	cpu_lookup_t	cpu_arg;
	char		*nodename;

	err = ptree_get_node_by_path(PLATFORM_PATH, &plath);
	if (err != PICL_SUCCESS)
		return;

	for (cnode = di_child_node(di_node); cnode != DI_NODE_NIL;
	    cnode = di_sibling_node(cnode)) {
		nodename = di_node_name(cnode);
		if (nodename == NULL)
			continue;
		if (strcmp(nodename, OBP_CPU) == 0) {
			cpu_arg.di_node = cnode;

			if (ptree_walk_tree_by_class(plath,
			    PICL_CLASS_CPU, &cpu_arg, cpu_exists)
			    != PICL_SUCCESS)
				return;

			if (cpu_arg.result == 0)
				/*
				 * Didn't find a matching cpu, add it.
				 */
				(void) construct_cpu_node(plath,
				    cnode);
		}
	}
}
/*
 * Handles minor node type "ddi_parallel".
 * type=ddi_parallel;name=mcpp     mcpp\N0
 */
static int
parallel(di_minor_t minor, di_node_t node)
{
	char path[PATH_MAX + 1], *buf;
	devfsadm_enumerate_t rules[1] = {"mcpp([0-9]+)$", 1, MATCH_ALL};


	if (strcmp(di_node_name(node), "mcpp") != 0) {
		return (DEVFSADM_CONTINUE);
	}

	if (NULL == (buf = di_devfs_path(node))) {
		return (DEVFSADM_CONTINUE);
	}

	(void) snprintf(path, sizeof (path), "%s:%s",
	    buf, di_minor_name(minor));

	di_devfs_path_free(buf);

	if (devfsadm_enumerate_int(path, 0, &buf, rules, 1)) {
		return (DEVFSADM_CONTINUE);
	}
	(void) snprintf(path, sizeof (path), "mcpp%s", buf);
	free(buf);

	(void) devfsadm_mklink(path, node, minor, 0);
	return (DEVFSADM_CONTINUE);
}
示例#4
0
/*
 * This function is called for every ramdisk minor node.
 * Calls enumerate to assign a logical ramdisk id, and then
 * devfsadm_mklink to make the link.
 *
 * For pseudo ramdisk devices:
 *
 *	/dev/ramdiskctl      -> /devices/pseudo/ramdisk@0:ctl
 *	/dev/ramdisk/<name>  -> /devices/pseudo/ramdisk@0:<name>
 *	/dev/rramdisk/<name> -> /devices/pseudo/ramdisk@0:<name>,raw
 *
 * For OBP-created ramdisk devices:
 *
 *	/dev/ramdisk/<name>  -> /devices/ramdisk-<name>:a
 *	/dev/rramdisk/<name> -> /devices/ramdisk-<name>:a,raw
 */
static int
ramdisk(di_minor_t di_minor, di_node_t node)
{
	char	*name;
	char	devnm[MAXNAMELEN + 1];
	char	path[PATH_MAX];

	/*
	 * If this is an OBP-created ramdisk use the node name, having first
	 * stripped the "ramdisk-" prefix.  For pseudo ramdisks use the minor
	 * name, having first stripped any ",raw" suffix.
	 */
	if (di_nodeid(node) == DI_PROM_NODEID) {
		RD_STRIP_PREFIX(name, di_node_name(node));
		(void) strlcpy(devnm, name, sizeof (devnm));
	} else {
		(void) strlcpy(devnm, di_minor_name(di_minor), sizeof (devnm));
		RD_STRIP_SUFFIX(devnm);
	}

	if (strcmp(devnm, RD_CTL_NODE) == 0) {
		(void) devfsadm_mklink(RD_CTL_NAME, node, di_minor, 0);
	} else {
		/*
		 * Make the link in /dev/ramdisk or /dev/rramdisk.
		 */
		(void) snprintf(path, sizeof (path), "%s/%s",
		    di_minor_spectype(di_minor) == S_IFBLK ?
		    RD_BLOCK_NAME : RD_CHAR_NAME, devnm);
		(void) devfsadm_mklink(path, node, di_minor, 0);
	}

	return (DEVFSADM_CONTINUE);
}
示例#5
0
static int
is_zvol(di_node_t node, di_minor_t minor)
{
	if ((strncmp(di_node_name(node), ZFS_DRIVER, 3) == 0) &&
	    minor(di_minor_devt(minor)))
		return (1);
	return (0);
}
示例#6
0
int prt_node(di_node_t node, void *arg)
{
    di_prop_t prop = DI_PROP_NIL;

    if (strcmp(di_node_name(node), "i86pc") == 0) {
        while ((prop = di_prop_next(node, prop)) != DI_PROP_NIL) {
            prt_prop(prop);
        }
        return (DI_WALK_TERMINATE);
    }
    return (DI_WALK_CONTINUE);
}
static int
node_slash_minor(di_minor_t minor, di_node_t node)
{

	char path[PATH_MAX + 1];

	(void) strcpy(path, di_node_name(node));
	(void) strcat(path, "/");
	(void) strcat(path, di_minor_name(minor));
	(void) devfsadm_mklink(path, node, minor, 0);
	return (DEVFSADM_CONTINUE);
}
示例#8
0
int
wrsm(di_minor_t minor, di_node_t node)
{
	const char *node_name = di_node_name(node);
	const char *minor_name = di_minor_name(minor);
	char path[PATH_MAX + 1];

	if (minor_name == NULL || node_name == NULL) {
		return (DEVFSADM_CONTINUE);
	}
	if (strcmp(minor_name, "admin") == 0) {
		/* admin pseudo device */
		(void) snprintf(path, sizeof (path), "%s%s", node_name,
		    minor_name);
	} else if (strcmp(minor_name, "ctrl") == 0) {
		/* controller pseudo device */
		dev_t dev = di_minor_devt(minor);
		minor_t dev_minor = minor(dev);
		(void) snprintf(path, sizeof (path), "%s%u", node_name,
		    (uint_t)dev_minor);
	} else {
		/*
		 * For hardware devices, the devlink must be
		 * /dev/<node_name><portid>. devpath is of the format
		 * ".../<node_name>@<portid>,0". Need to extract the
		 * <portid> for use in bulding devlink.
		 */
		char devpath[PATH_MAX + 1];
		char *devfs_path;
		int i;

		devfs_path = di_devfs_path(node);
		if (devfs_path == NULL) {
			return (DEVFSADM_CONTINUE);
		}
		(void) strcpy(devpath, devfs_path);
		di_devfs_path_free(devfs_path);

		for (i = strlen(devpath); devpath[i] != '@' && i > 0; i--) {
			if (devpath[i] == ',') {
				devpath[i] = 0;
			}
		}
		if (i == 0) {
			return (DEVFSADM_CONTINUE);
		}
		(void) snprintf(path, sizeof (path), "wci%s", &devpath[i+1]);
	}
	(void) devfsadm_mklink(path, node, minor, 0);

	return (DEVFSADM_CONTINUE);
}
示例#9
0
/*
 * Walk all "service" device nodes to find the one with the
 * matching glvc minor name
 */
static char *
svc_name_to_glvc_dev_path(char *service)
{
	di_node_t root_node, service_node;
	char *glvc_path;
	char *minor_name;
	di_minor_t minor;
	char *dev_path = NULL;

	if (service == NULL)
		return (NULL);

	/* Get device node */
	root_node = di_init("/", DINFOCPYALL);
	if (root_node == DI_NODE_NIL) {
		return (dev_path);
	}

	service_node = di_drv_first_node("glvc", root_node);

	while (service_node != DI_NODE_NIL) {
		/* Make sure node name matches service name */
		if (strcmp(service, di_node_name(service_node)) == 0) {
			/* Walk minor nodes */
			minor = di_minor_next(service_node, DI_NODE_NIL);

			while (minor != DI_NODE_NIL) {
				glvc_path = di_devfs_minor_path(minor);
				minor_name = di_minor_name(minor);

				if (strcmp(minor_name, "glvc") == 0) {
					dev_path = malloc(strlen(glvc_path) +
					    strlen(DEVICES_DIR) + 1);
					(void) strcpy(dev_path, DEVICES_DIR);
					(void) strcat(dev_path, glvc_path);
					di_devfs_path_free(glvc_path);
					break;
				}

				di_devfs_path_free(glvc_path);
				minor = di_minor_next(service_node, minor);
			}
		}
		if (dev_path != NULL)
			break;

		service_node = di_drv_next_node(service_node);
	}

	di_fini(root_node);
	return (dev_path);
}
/*
 * Creates /dev/lom and /dev/tsalarm:ctl for tsalarm node
 */
static int
tsalarm_create(di_minor_t minor, di_node_t node)
{
	char buf[PATH_MAX + 1];
	char *mn = di_minor_name(minor);

	(void) snprintf(buf, sizeof (buf), "%s%s", di_node_name(node), ":ctl");

	(void) devfsadm_mklink(mn, node, minor, 0);
	(void) devfsadm_mklink(buf, node, minor, 0);

	return (DEVFSADM_CONTINUE);
}
/*
 * For device
 *      /dev/spfma -> /devices/virtual-devices/fma@5:glvc
 */
static int
glvc(di_minor_t minor, di_node_t node)
{
	char node_name[MAXNAMELEN + 1];

	(void) strcpy(node_name, di_node_name(node));

	if (strncmp(node_name, "fma", 3) == 0) {
		/* Only one fma channel */
		(void) devfsadm_mklink("spfma", node, minor, 0);
	}
	return (DEVFSADM_CONTINUE);
}
示例#12
0
/*
 * Handles minor node type "ddi_other"
 * type=ddi_other;name=SUNW,pmc    pmc
 * type=ddi_other;name=SUNW,mic    mic\M0
 */
static int
ddi_other(di_minor_t minor, di_node_t node)
{
	char path[PATH_MAX + 1];
	char *nn = di_node_name(node);
	char *mn = di_minor_name(minor);

	if (strcmp(nn, "SUNW,pmc") == 0) {
		(void) devfsadm_mklink("pcm", node, minor, 0);
	} else if (strcmp(nn, "SUNW,mic") == 0) {
		(void) strcpy(path, "mic");
		(void) strcat(path, mn);
		(void) devfsadm_mklink(path, node, minor, 0);
	}

	return (DEVFSADM_CONTINUE);
}
示例#13
0
/*
 * Get the value of the named property on the named node in root.
 */
static char *
get_prop(const char *nodename, const char *propname, size_t *lenp)
{
	di_node_t		node;
	di_prom_prop_t		pp;
	char			*val = NULL;
	int			len;

	/*
	 * Locate nodename within '/'.
	 */
	for (node = di_child_node(root_node);
	    node != DI_NODE_NIL;
	    node = di_sibling_node(node)) {
		if (strcmp(di_node_name(node), nodename) == 0) {
			break;
		}
	}
	if (node == DI_NODE_NIL) {
		return (NULL);
	}

	/*
	 * Scan all properties of /nodename for the 'propname' property.
	 */
	for (pp = di_prom_prop_next(phdl, node, DI_PROM_PROP_NIL);
	    pp != DI_PROM_PROP_NIL;
	    pp = di_prom_prop_next(phdl, node, pp)) {
		if (strcmp(propname, di_prom_prop_name(pp)) == 0) {
			break;
		}
	}
	if (pp == DI_PROM_PROP_NIL) {
		return (NULL);
	}

	/*
	 * Found the property; copy out its length and return its value.
	 */
	len = di_prom_prop_data(pp, (uchar_t **)&val);
	if (lenp != NULL) {
		*lenp = len;
	}
	return (val);
}
示例#14
0
static char *
ctype(di_node_t node, di_minor_t minor)
{
	char	*type;
	char	*name;

	type = di_minor_nodetype(minor);
	name = di_node_name(node);

	/* IDE disks use SCSI nexus as the type, so handle this special case */
	if ((libdiskmgt_str_eq(type, DDI_NT_SCSI_NEXUS) ||
	    libdiskmgt_str_eq(type, DDI_PSEUDO)) &&
	    libdiskmgt_str_eq(name, "ide"))
		return (DM_CTYPE_ATA);

	if (libdiskmgt_str_eq(type, DDI_NT_FC_ATTACHMENT_POINT) ||
	    (libdiskmgt_str_eq(type, DDI_NT_NEXUS) &&
	    libdiskmgt_str_eq(name, "fp")))
		return (DM_CTYPE_FIBRE);

	if (libdiskmgt_str_eq(type, DDI_NT_NVME_ATTACHMENT_POINT))
		return (DM_CTYPE_NVME);

	if (libdiskmgt_str_eq(type, DDI_NT_SATA_NEXUS) ||
	    libdiskmgt_str_eq(type, DDI_NT_SATA_ATTACHMENT_POINT))
		return (DM_CTYPE_SATA);

	if (libdiskmgt_str_eq(type, DDI_NT_SCSI_NEXUS) ||
	    libdiskmgt_str_eq(type, DDI_NT_SCSI_ATTACHMENT_POINT))
		return (DM_CTYPE_SCSI);

	if (libdiskmgt_str_eq(di_minor_name(minor), "scsa2usb"))
		return (DM_CTYPE_USB);

	if (libdiskmgt_str_eq(type, DDI_PSEUDO) &&
	    libdiskmgt_str_eq(name, "xpvd"))
		return (DM_CTYPE_XEN);

	if (dm_debug) {
		(void) fprintf(stderr,
		    "INFO: unknown controller type=%s name=%s\n", type, name);
	}

	return (DM_CTYPE_UNKNOWN);
}
示例#15
0
void
devinfo_set_default_properties (HalDevice *d, HalDevice *parent, di_node_t node, char *devfs_path)
{
	char	*driver_name, *s;
	const char *s1;
	char	udi[HAL_PATH_MAX];

	if (parent != NULL) {
		hal_device_property_set_string (d, "info.parent", hal_device_get_udi (parent));
	} else {
		hal_device_property_set_string (d, "info.parent", "/org/freedesktop/Hal/devices/local");
	}

	hal_util_compute_udi (hald_get_gdl (), udi, sizeof (udi),
				"/org/freedesktop/Hal/devices%s_%d",
				devfs_path,
				di_instance (node));
	hal_device_set_udi (d, udi);
	hal_device_property_set_string (d, "info.udi", udi);

	if (di_prop_lookup_strings (DDI_DEV_T_ANY, node, "model", &s) > 0) {
		hal_device_property_set_string (d, "info.product", s);
	} else {
		hal_device_property_set_string (d, "info.product", di_node_name (node));
	}

	hal_device_property_set_string (d, "solaris.devfs_path", devfs_path);

	if ((driver_name = di_driver_name (node)) != NULL) {
		hal_device_property_set_string (d, "info.solaris.driver",
						driver_name);
	}


	/* inherit parent's claim attributes */
	if (hal_device_property_get_bool (parent, "info.claimed")) {
		s1 = hal_device_property_get_string (parent, "info.claimed.service");
		if (s1 != NULL) {
			hal_device_property_set_bool (d, "info.claimed", TRUE);
			hal_device_property_set_string (d, "info.claimed.service", s1);
		}
	}
}
示例#16
0
static void
print_mpx_capable(di_node_t curnode)
{
	char *prop;
	char *path;
	char *aliases = NULL;

	if (cap_N_option) {
		aliases = calloc(1, MAXPATHLEN + 1);
		if (aliases == NULL) {
			logmsg(MSG_ERROR,
			    gettext("Unable to allocate memory for a device "
			    "alias list\n"));
			return;
		}
	}

	for (; curnode != DI_NODE_NIL; curnode = di_drv_next_node(curnode)) {
		if (di_prop_lookup_strings(DDI_DEV_T_ANY, curnode,
		    "initiator-port", &prop) >= 0) {
			if ((path = di_devfs_path(curnode)) == NULL) {
				logmsg(MSG_INFO,
				    "Unable to find devfs path for device "
				    "%s: %s\n", &curnode, strerror(errno));
				continue;
			}
			if (cap_N_option) {
				char *nodename = di_node_name(curnode);
				/* nodename is never going to be null */
				if (strstr(aliases, nodename) == NULL)
					/* haven't seen this nodename before */
					(void) snprintf(aliases,
					    MAXPATHLEN + 1, "%s|%s",
					    ((aliases != NULL) ? aliases : ""),
					    nodename);
			} else
				(void) printf("%s\n", path);
		}
	}
	if (cap_N_option)
		(void) printf("%s\n", aliases);
}
示例#17
0
/*
 * Create a  picl node of type cpu and fill it.
 * properties are filled from both the device tree and the
 * Machine description.
 */
static int
construct_cpu_node(picl_nodehdl_t plath, di_node_t dn)
{
	int		err;
	char		*nodename;
	picl_nodehdl_t	anodeh;

	nodename = di_node_name(dn);	/* PICL_PROP_NAME */

	err = ptree_create_and_add_node(plath, nodename, PICL_CLASS_CPU,
	    &anodeh);
	if (err != PICL_SUCCESS)
		return (err);

	add_devinfo_props(anodeh, dn);
	add_reg_prop(anodeh, dn);
	(void) add_cpu_prop(anodeh, NULL);

	return (err);
}
示例#18
0
int
find_cpu(di_node_t node, int cpuid)
{
	int	dcpuid;
	di_node_t cnode;
	char	*nodename;

	for (cnode = di_child_node(node); cnode != DI_NODE_NIL;
	    cnode = di_sibling_node(cnode)) {
		nodename = di_node_name(cnode);
		if (nodename == NULL)
			continue;
		if (strcmp(nodename, OBP_CPU) == 0) {
			dcpuid = get_cpuid(cnode);
			if (dcpuid == cpuid) {
				return (1);
			}
		}
	}
	return (0);
}
示例#19
0
void
devinfo_add_subtree(HalDevice *parent, di_node_t node, gboolean is_root)
{
	HalDevice *d;
	di_node_t root_node, child_node;

	HAL_INFO (("add_subtree: %s", di_node_name (node)));

	root_node = node;
	do {
		d = devinfo_add_node (parent, node);

		if ((d != NULL) &&
		    (child_node = di_child_node (node)) != DI_NODE_NIL) {
			devinfo_add_subtree (d, child_node, FALSE);
		}

		node = di_sibling_node (node);
	} while ((node != DI_NODE_NIL) &&
		(!is_root || di_parent_node (node) == root_node));
}
示例#20
0
static struct priv_data *
match_priv_data(di_node_t node)
{
	int i;
	size_t len;
	char *drv_name, *tmp;
	di_node_t parent;
	struct priv_data *pdp;

	if ((parent = di_parent_node(node)) == DI_NODE_NIL)
		return (NULL);

	if ((drv_name = di_driver_name(parent)) == NULL)
		return (NULL);

	pdp = prt_priv_data;
	len = strlen(drv_name);
	for (i = 0; i < nprt_priv_data; ++i, ++pdp) {
		tmp = pdp->drv_name;
		while (tmp && (*tmp != '\0')) {
			if (strncmp(tmp, drv_name, len) == 0) {
#ifdef	DEBUG
				dprintf("matched parent private data"
				    " at Node <%s> parent driver <%s>\n",
				    di_node_name(node), drv_name);
#endif	/* DEBUG */
				return (pdp);
			}
			/*
			 * skip a white space
			 */
			if (tmp = strchr(tmp, ' '))
				tmp++;
		}
	}

	return (NULL);
}
示例#21
0
static char *
bus_type(di_node_t node, di_minor_t minor, di_prom_handle_t ph)
{
	char	*type;
	int	i;

	type = get_prom_str("device_type", node, ph);
	if (type == NULL) {
		type = di_node_name(node);
	}

	for (i = 0; bustypes[i]; i++) {
		if (libdiskmgt_str_eq(type, bustypes[i])) {
			return (type);
		}
	}

	if (minor != NULL && strcmp(di_minor_nodetype(minor),
	    DDI_NT_USB_ATTACHMENT_POINT) == 0) {
		return ("usb");
	}

	return (NULL);
}
示例#22
0
/*
 * This function is called for Smartcard card reader nodes
 * Handles minor node type "ddi_smartcard_reader"
 * type=ddi_smartcard_reader;name=card-reader   scmi2c\N0
 * Calls enumerate to assign logical card-reader id and then
 * devfsadm_mklink to make the link.
 */
static int
ddi_cardreader(di_minor_t minor, di_node_t node)
{
	char p_path[PATH_MAX +1], l_path[PATH_MAX +1];
	char *buf;
	char *ptr;
	char *nn, *mn;

	devfsadm_enumerate_t rules[1] = {"^scmi2c([0-9]+)$", 1, MATCH_ALL};

	nn = di_node_name(node);
	if (strcmp(nn, "card-reader")) {
		return (DEVFSADM_CONTINUE);
	}

	if (NULL == (ptr = di_devfs_path(node))) {
		return (DEVFSADM_CONTINUE);
	}

	(void) strcpy(p_path, ptr);
	(void) strcat(p_path, ":");

	mn = di_minor_name(minor);

	(void) strcat(p_path, mn);
	di_devfs_path_free(ptr);

	if (devfsadm_enumerate_int(p_path, 0, &buf, rules, 1)) {
		return (DEVFSADM_CONTINUE);
	}
	(void) snprintf(l_path, sizeof (l_path), "scmi2c%s", buf);
	free(buf);
	(void) devfsadm_mklink(l_path, node, minor, 0);

	return (DEVFSADM_CONTINUE);
}
示例#23
0
static bus_t *
add_bus(struct search_args *args, di_node_t node, di_minor_t minor,
    controller_t *cp)
{
	char		*btype;
	char		*devpath;
	bus_t		*bp;
	char		kstat_name[MAXPATHLEN];
	di_node_t	pnode;

	if (node == DI_NODE_NIL) {
		return (NULL);
	}

	if ((btype = bus_type(node, minor, args->ph)) == NULL) {
		return (add_bus(args, di_parent_node(node),
		    di_minor_next(di_parent_node(node), NULL), cp));
	}

	devpath = di_devfs_path(node);

	if ((bp = find_bus(args, devpath)) != NULL) {
		di_devfs_path_free((void *) devpath);

		if (cp != NULL) {
			if (add_ptr2array(cp,
			    (void ***)&bp->controllers) != 0) {
				args->dev_walk_status = ENOMEM;
				return (NULL);
			}
		}
		return (bp);
	}

	/* Special handling for root node. */
	if (strcmp(devpath, "/") == 0) {
		di_devfs_path_free((void *) devpath);
		return (NULL);
	}

	if (dm_debug) {
		(void) fprintf(stderr, "INFO: add_bus %s\n", devpath);
	}

	bp = (bus_t *)calloc(1, sizeof (bus_t));
	if (bp == NULL) {
		return (NULL);
	}

	bp->name = strdup(devpath);
	di_devfs_path_free((void *) devpath);
	if (bp->name == NULL) {
		args->dev_walk_status = ENOMEM;
		cache_free_bus(bp);
		return (NULL);
	}

	bp->btype = strdup(btype);
	if (bp->btype == NULL) {
		args->dev_walk_status = ENOMEM;
		cache_free_bus(bp);
		return (NULL);
	}

	(void) snprintf(kstat_name, sizeof (kstat_name), "%s%d",
	    di_node_name(node), di_instance(node));

	if ((bp->kstat_name = strdup(kstat_name)) == NULL) {
		args->dev_walk_status = ENOMEM;
		cache_free_bus(bp);
		return (NULL);
	}

	/* if parent node is a bus, get its name */
	if ((pnode = get_parent_bus(node, args)) != NULL) {
		devpath = di_devfs_path(pnode);
		bp->pname = strdup(devpath);
		di_devfs_path_free((void *) devpath);
		if (bp->pname == NULL) {
			args->dev_walk_status = ENOMEM;
			cache_free_bus(bp);
			return (NULL);
		}

	} else {
		bp->pname = NULL;
	}

	bp->freq = get_prom_int("clock-frequency", node, args->ph);

	bp->controllers = (controller_t **)calloc(1, sizeof (controller_t *));
	if (bp->controllers == NULL) {
		args->dev_walk_status = ENOMEM;
		cache_free_bus(bp);
		return (NULL);
	}
	bp->controllers[0] = NULL;

	if (cp != NULL) {
		if (add_ptr2array(cp, (void ***)&bp->controllers) != 0) {
			args->dev_walk_status = ENOMEM;
			return (NULL);
		}
	}

	bp->next = args->bus_listp;
	args->bus_listp = bp;

	return (bp);
}
示例#24
0
static controller_t *
add_controller(struct search_args *args, di_node_t node, di_minor_t minor)
{
	char		*devpath;
	controller_t	*cp;
	char		kstat_name[MAXPATHLEN];
	char		*c_type = DM_CTYPE_UNKNOWN;

	devpath = di_devfs_path(node);

	if ((cp = find_controller(args, devpath)) != NULL) {
		di_devfs_path_free((void *) devpath);
		return (cp);
	}

	/* Special handling for fp attachment node. */
	if (strcmp(di_node_name(node), "fp") == 0) {
		di_node_t pnode;

		pnode = di_parent_node(node);
		if (pnode != DI_NODE_NIL) {
			di_devfs_path_free((void *) devpath);
			devpath = di_devfs_path(pnode);

			if ((cp = find_controller(args, devpath)) != NULL) {
				di_devfs_path_free((void *) devpath);
				return (cp);
			}

			/* not in the list, create it */
			node = pnode;
			c_type = DM_CTYPE_FIBRE;
		}
	}

	if (dm_debug) {
		(void) fprintf(stderr, "INFO: add_controller %s\n", devpath);
	}

	cp = (controller_t *)calloc(1, sizeof (controller_t));
	if (cp == NULL) {
		return (NULL);
	}

	cp->name = strdup(devpath);
	di_devfs_path_free((void *) devpath);
	if (cp->name == NULL) {
		cache_free_controller(cp);
		return (NULL);
	}

	if (strcmp(c_type, DM_CTYPE_UNKNOWN) == 0) {
		c_type = ctype(node, minor);
	}
	cp->ctype = c_type;

	(void) snprintf(kstat_name, sizeof (kstat_name), "%s%d",
	    di_node_name(node), di_instance(node));

	if ((cp->kstat_name = strdup(kstat_name)) == NULL) {
		cache_free_controller(cp);
		return (NULL);
	}

	if (libdiskmgt_str_eq(cp->ctype, "scsi")) {
		cp->scsi_options = get_prop(SCSI_OPTIONS_PROP, node);
	}

	if (libdiskmgt_str_eq(di_node_name(node), "scsi_vhci")) {
		cp->multiplex = 1;
	} else {
		cp->multiplex = 0;
	}

	cp->freq = get_prom_int("clock-frequency", node, args->ph);

	cp->disks = (disk_t **)calloc(1, sizeof (disk_t *));
	if (cp->disks == NULL) {
		cache_free_controller(cp);
		return (NULL);
	}
	cp->disks[0] = NULL;

	cp->next = args->controller_listp;
	args->controller_listp = cp;

	cp->bus = add_bus(args, di_parent_node(node),
	    di_minor_next(di_parent_node(node), NULL), cp);

	return (cp);
}
示例#25
0
static int
add_devpath(di_devlink_t devlink, void *arg)
{
	struct search_args *args;
	char		*devidstr;
	disk_t		*diskp;
	char		kernel_name[MAXPATHLEN];

	args =	(struct search_args *)arg;

	/*
	 * Get the diskp value from calling have_disk. Can either be found
	 * by kernel name or devid.
	 */

	diskp = NULL;
	devidstr = get_str_prop(DEVICE_ID_PROP, args->node);
	(void) snprintf(kernel_name, sizeof (kernel_name), "%s%d",
	    di_node_name(args->node), di_instance(args->node));

	(void) have_disk(args, devidstr, kernel_name, &diskp);

	/*
	 * The devlink_path is usually of the form /dev/rdsk/c0t0d0s0.
	 * For diskettes it is /dev/rdiskette*.
	 * On Intel we would also get each fdisk partition as well
	 * (e.g. /dev/rdsk/c0t0d0p0).
	 */
	if (diskp != NULL) {
		alias_t	*ap;
		char	*devlink_path;

		if (diskp->drv_type != DM_DT_FLOPPY) {
			/*
			 * Add other controllers for multipath disks.
			 * This will have no effect if the controller
			 * relationship is already set up.
			 */
			if (add_disk2controller(diskp, args) != 0) {
				args->dev_walk_status = ENOMEM;
			}
		}

		(void) snprintf(kernel_name, sizeof (kernel_name), "%s%d",
		    di_node_name(args->node), di_instance(args->node));
		devlink_path = (char *)di_devlink_path(devlink);

		if (dm_debug > 1) {
			(void) fprintf(stderr,
			    "INFO:     devpath %s\n", devlink_path);
		}

		if ((ap = find_alias(diskp, kernel_name)) == NULL) {
			if (new_alias(diskp, kernel_name, devlink_path,
			    args) != 0) {
				args->dev_walk_status = ENOMEM;
			}
		} else {
			/*
			 * It is possible that we have already added this
			 * devpath.  Do not add it again. new_devpath will
			 * return a 0 if found, and not add the path.
			 */
			if (new_devpath(ap, devlink_path) != 0) {
				args->dev_walk_status = ENOMEM;
			}
		}
	}

	return (DI_WALK_CONTINUE);
}
/*
 * Handles links of the form:
 * type=ddi_pseudo;name=xyz  \D
 */
static int
node_name(di_minor_t minor, di_node_t node)
{
	(void) devfsadm_mklink(di_node_name(node), node, minor, 0);
	return (DEVFSADM_CONTINUE);
}
示例#27
0
static int
add_devs(di_node_t node, di_minor_t minor, void *arg)
{
	struct search_args	*args;
	int result = DI_WALK_CONTINUE;

	args = (struct search_args *)arg;

	if (dm_debug > 1) {
		/* This is all just debugging code */
		char	*devpath;
		char	dev_name[MAXPATHLEN];

		devpath = di_devfs_path(node);
		(void) snprintf(dev_name, sizeof (dev_name), "%s:%s", devpath,
		    di_minor_name(minor));
		di_devfs_path_free((void *) devpath);

		(void) fprintf(stderr,
		    "INFO: dev: %s, node: %s%d, minor: 0x%x, type: %s\n",
		    dev_name, di_node_name(node), di_instance(node),
		    di_minor_spectype(minor),
		    (di_minor_nodetype(minor) != NULL ?
		    di_minor_nodetype(minor) : "NULL"));
	}

	if (bus_type(node, minor, args->ph) != NULL) {
		if (add_bus(args, node, minor, NULL) == NULL) {
			args->dev_walk_status = ENOMEM;
			result = DI_WALK_TERMINATE;
		}

	} else if (is_ctrl(node, minor)) {
		if (add_controller(args, node, minor) == NULL) {
			args->dev_walk_status = ENOMEM;
			result = DI_WALK_TERMINATE;
		}

	} else if (di_minor_spectype(minor) == S_IFCHR &&
	    (is_drive(minor) || is_zvol(node, minor))) {
		char	*devidstr;
		char	kernel_name[MAXPATHLEN];
		disk_t	*diskp;

		(void) snprintf(kernel_name, sizeof (kernel_name), "%s%d",
		    di_node_name(node), di_instance(node));
		devidstr = get_str_prop(DEVICE_ID_PROP, node);

		args->node = node;
		args->minor = minor;
		/*
		 * Check if we already got this disk and
		 * this is another slice.
		 */
		if (!have_disk(args, devidstr, kernel_name, &diskp)) {
			args->dev_walk_status = 0;
			/*
			 * This is a newly found disk, create the
			 * disk structure.
			 */
			diskp = create_disk(devidstr, kernel_name, args);
			if (diskp == NULL) {
				args->dev_walk_status = ENOMEM;
			}

			if (diskp->drv_type != DM_DT_FLOPPY) {
				/* add the controller relationship */
				if (args->dev_walk_status == 0) {
					if (add_disk2controller(diskp,
					    args) != 0) {
						args->dev_walk_status = ENOMEM;
					}
				}
			}
		}
		if (is_zvol(node, minor)) {
			char zvdsk[MAXNAMELEN];
			char *str;
			alias_t *ap;

			if (di_prop_lookup_strings(di_minor_devt(minor),
			    node, "name", &str) == -1)
				return (DI_WALK_CONTINUE);
			(void) snprintf(zvdsk, MAXNAMELEN, "/dev/zvol/rdsk/%s",
			    str);
			if ((ap = find_alias(diskp, kernel_name)) == NULL) {
				if (new_alias(diskp, kernel_name,
				    zvdsk, args) != 0) {
					args->dev_walk_status = ENOMEM;
				}
			} else {
				/*
				 * It is possible that we have already added
				 * this devpath.
				 * Do not add it again. new_devpath will
				 * return a 0 if found, and not add the path.
				 */
				if (new_devpath(ap, zvdsk) != 0) {
					args->dev_walk_status = ENOMEM;
				}
			}
		}

		/* Add the devpaths for the drive. */
		if (args->dev_walk_status == 0) {
			char	*devpath;
			char	slice_path[MAXPATHLEN];
			char	*pattern;

			/*
			 * We will come through here once for each of
			 * the raw slice device names.
			 */
			devpath = di_devfs_path(node);
			(void) snprintf(slice_path,
			    sizeof (slice_path), "%s:%s",
			    devpath, di_minor_name(minor));
			di_devfs_path_free((void *) devpath);

			if (libdiskmgt_str_eq(di_minor_nodetype(minor),
			    DDI_NT_FD)) {
				pattern = DEVLINK_FLOPPY_REGEX;
			} else {
				pattern = DEVLINK_REGEX;
			}

			/* Walk the /dev tree to get the devlinks. */
			(void) di_devlink_walk(args->handle, pattern,
			    slice_path, DI_PRIMARY_LINK, arg, add_devpath);
		}

		if (args->dev_walk_status != 0) {
			result = DI_WALK_TERMINATE;
		}
	}

	return (result);
}
示例#28
0
static int
add_disk2controller(disk_t *diskp, struct search_args *args)
{
	di_node_t	pnode;
	controller_t	*cp;
	di_minor_t	minor;
	di_node_t	node;
	int		i;

	node = args->node;

	pnode = di_parent_node(node);
	if (pnode == DI_NODE_NIL) {
		return (0);
	}

	minor = di_minor_next(pnode, NULL);
	if (minor == NULL) {
		return (0);
	}

	if ((cp = add_controller(args, pnode, minor)) == NULL) {
		return (ENOMEM);
	}

	/* check if the disk <-> ctrl assoc is already there */
	for (i = 0; diskp->controllers[i]; i++) {
		if (cp == diskp->controllers[i]) {
			return (0);
		}
	}

	/* this is a new controller for this disk */

	/* add the disk to the controller */
	if (add_ptr2array(diskp, (void ***)&cp->disks) != 0) {
		return (ENOMEM);
	}

	/* add the controller to the disk */
	if (add_ptr2array(cp, (void ***)&diskp->controllers) != 0) {
		return (ENOMEM);
	}

	/*
	 * Set up paths for mpxio controlled drives.
	 */
	if (libdiskmgt_str_eq(di_node_name(pnode), "scsi_vhci")) {
		/* note: mpxio di_path stuff is all consolidation private */
		di_path_t   pi = DI_PATH_NIL;

		while (
		    (pi = di_path_client_next_path(node, pi)) != DI_PATH_NIL) {
			int	cnt;
			uchar_t	*bytes;
			char	str[MAXPATHLEN];
			char	*wwn;

			di_node_t phci_node = di_path_phci_node(pi);

			/* get the node wwn */
			cnt = di_path_prop_lookup_bytes(pi, WWN_PROP, &bytes);
			wwn = NULL;
			if (cnt > 0) {
				int	i;
				str[0] = 0;

				for (i = 0; i < cnt; i++) {
					/*
					 * A byte is only 2 hex chars + null.
					 */
					char bstr[8];

					(void) snprintf(bstr,
					    sizeof (bstr), "%.2x", bytes[i]);
					(void) strlcat(str, bstr, sizeof (str));
				}
				wwn = str;
			}

			if (new_path(cp, diskp, phci_node,
			    di_path_state(pi), wwn) == NULL) {
				return (ENOMEM);
			}
		}
	}

	return (0);
}
示例#29
0
/*
 * This function is called for every usb minor node.
 * Calls enumerate to assign a logical usb id, and then
 * devfsadm_mklink to make the link.
 */
static int
usb_process(di_minor_t minor, di_node_t node)
{
	devfsadm_enumerate_t rules[1];
	char *l_path, *p_path, *buf, *devfspath;
	char *minor_nm, *drvr_nm, *name = (char *)NULL;
	int i, index;
	int flags = 0;
	int create_secondary_link = 0;

	minor_nm = di_minor_name(minor);
	drvr_nm = di_driver_name(node);
	if ((minor_nm == NULL) || (drvr_nm == NULL)) {
		return (DEVFSADM_CONTINUE);
	}

	devfsadm_print(debug_mid, "usb_process: minor=%s node=%s type=%s\n",
	    minor_nm, di_node_name(node), di_minor_nodetype(minor));

	devfspath = di_devfs_path(node);
	if (devfspath == NULL) {
		devfsadm_print(debug_mid,
		    "USB_process: devfspath is	NULL\n");
		return (DEVFSADM_CONTINUE);
	}

	l_path = (char *)malloc(PATH_MAX);
	if (l_path == NULL) {
		di_devfs_path_free(devfspath);
		devfsadm_print(debug_mid, "usb_process: malloc() failed\n");
		return (DEVFSADM_CONTINUE);
	}

	p_path = (char *)malloc(PATH_MAX);
	if (p_path == NULL) {
		devfsadm_print(debug_mid, "usb_process: malloc() failed\n");
		di_devfs_path_free(devfspath);
		free(l_path);
		return (DEVFSADM_CONTINUE);
	}

	(void) strcpy(p_path, devfspath);
	(void) strcat(p_path, ":");
	(void) strcat(p_path, minor_nm);
	di_devfs_path_free(devfspath);

	devfsadm_print(debug_mid, "usb_process: path %s\n", p_path);

	for (i = 0; ; i++) {
		if ((driver_name_table[i].driver_name == NULL) ||
		    (strcmp(drvr_nm, driver_name_table[i].driver_name) == 0)) {
			index = driver_name_table[i].index;
			break;
		}
	}

	if (strcmp(di_minor_nodetype(minor), DDI_NT_UGEN) == 0) {
		ugen_create_link(p_path, minor_nm, node, minor);
		free(l_path);
		free(p_path);
		return (DEVFSADM_CONTINUE);
	}

	/* Figure out which rules to apply */
	switch (index) {
	case DRIVER_HUBD:
	case DRIVER_OHCI:
	case DRIVER_EHCI:
	case DRIVER_UHCI:
		rules[0] = hub_rules[0];	/* For HUBs */
		name = "hub";

		break;
	case DRIVER_USB_AC:
		if (strcmp(minor_nm, "sound,audio") == 0) {
			rules[0] = audio_rules[0];
			name = "audio";		/* For audio */
			create_secondary_link = 1;
		} else if (strcmp(minor_nm, "sound,audioctl") == 0) {
			rules[0] = audio_control_rules[0];
			name = "audio-control";		/* For audio */
			create_secondary_link = 1;
		} else if (strcmp(minor_nm, "mux") == 0) {
			rules[0] = audio_mux_rules[0];
			name = "audio-mux";		/* For audio */
		} else {
			free(l_path);
			free(p_path);
			return (DEVFSADM_CONTINUE);
		}
		break;
	case DRIVER_USB_AS:
		rules[0] = audio_stream_rules[0];
		name = "audio-stream";		/* For audio */
		break;
	case DRIVER_VIDEO:
		rules[0] = video_rules[0];
		name = "video";			/* For video */
		create_secondary_link = 1;
		break;
	case DRIVER_HID:
		rules[0] = hid_rules[0];
		name = "hid";			/* For HIDs */
		break;
	case DRIVER_USB_MID:
		rules[0] = device_rules[0];
		name = "device";		/* For other USB devices */
		break;
	case DRIVER_DDIVS_USBC:
		rules[0] = ddivs_usbc_rules[0];
		name = "device";		/* For other USB devices */
		break;
	case DRIVER_SCSA2USB:
		rules[0] = mass_storage_rules[0];
		name = "mass-storage";		/* For mass-storage devices */
		break;
	case DRIVER_USBPRN:
		rules[0] = usbprn_rules[0];
		name = "printer";
		break;
	case DRIVER_HWAHC:
		if (strcmp(minor_nm, "hwahc") == 0) {
			rules[0] = whost_rules[0];
			name = "whost";		/* For HWA HC */
		} else if (strcmp(minor_nm, "hubd") == 0) {
			rules[0] = hub_rules[0];
			name = "hub";		/* For HWA HC */
		} else {
			free(l_path);
			free(p_path);
			return (DEVFSADM_CONTINUE);
		}
		break;
	case DRIVER_HWARC:
		rules[0] = hwarc_rules[0];
		name = "hwarc";		/* For UWB HWA Radio Controllers */
		break;
	case DRIVER_WUSB_CA:
		rules[0] = wusb_ca_rules[0];
		name = "wusb_ca";	/* for wusb cable association */
		break;
	default:
		devfsadm_print(debug_mid, "usb_process: unknown driver=%s\n",
		    drvr_nm);
		free(l_path);
		free(p_path);
		return (DEVFSADM_CONTINUE);
	}

	/*
	 *  build the physical path from the components.
	 *  find the logical usb id, and stuff it in buf
	 */
	if (devfsadm_enumerate_int(p_path, 0, &buf, rules, 1)) {
		devfsadm_print(debug_mid, "usb_process: exit/continue\n");
		free(l_path);
		free(p_path);
		return (DEVFSADM_CONTINUE);
	}

	(void) snprintf(l_path, PATH_MAX, "usb/%s%s", name, buf);

	devfsadm_print(debug_mid, "usb_process: p_path=%s buf=%s\n",
	    p_path, buf);

	free(buf);

	devfsadm_print(debug_mid, "mklink %s -> %s\n", l_path, p_path);

	(void) devfsadm_mklink(l_path, node, minor, flags);

	if (create_secondary_link) {
		/*
		 * Create secondary links to make newly hotplugged
		 * usb audio device the primary device.
		 */
		if (strcmp(name, "audio") == 0) {
			(void) devfsadm_secondary_link("audio", l_path, 0);
		} else if (strcmp(name, "audio-control") == 0) {
			(void) devfsadm_secondary_link("audioctl", l_path, 0);
		} else if (strcmp(name, "video") == 0) {
			(void) devfsadm_secondary_link(l_path + 4, l_path, 0);
		}
	}

	free(p_path);
	free(l_path);

	return (DEVFSADM_CONTINUE);
}
示例#30
0
static int
walk_tree(di_node_t node, void *arg)
{
	char	*path = NULL;
	char	*bus_addr = NULL;
	char	*char_di_bus_addr = NULL;
	int	busaddr = 0;
	int	di_busaddr = 0;
	char 	*node_name = NULL;
	frutree_devinfo_t *devinfo;
	frutree_frunode_t *frup = NULL;

	devinfo = *(frutree_devinfo_t **)arg;
	frup = (frutree_frunode_t *)devinfo->arg;
	if (frup == NULL) {
		return (DI_WALK_TERMINATE);
	}

	if (devinfo->rnode == node) {	/* skip the root node */
		return (DI_WALK_CONTINUE);
	}
	bus_addr = devinfo->bus_addr;

	char_di_bus_addr = di_bus_addr(node);
	if (char_di_bus_addr == NULL) {
		/*
		 * look for reg property
		 * This applies to only cPCI devices
		 */
		if (strstr(bus_addr, ",") != NULL) {
			/* bus addr is of type 1,0 */
			/* we dont handle this case yet */
			return (DI_WALK_PRUNECHILD);
		}
		di_busaddr = get_reg_dev(node);
		if (di_busaddr == -1) {
			/* reg prop not found */
			return (DI_WALK_PRUNECHILD);
		}

		/* check if the bus addresses are same */
		errno = 0;
		busaddr = strtol(bus_addr, (char **)NULL, 16);
		if (errno != 0) {
			return (DI_WALK_TERMINATE);
		}
		if (di_busaddr != busaddr) {
			return (DI_WALK_PRUNECHILD);
		}

		/* build the fru path name */
		/* parent_path/nodename@bus_addr */
		node_name = di_node_name(node);
		if (node_name == NULL) {
			return (DI_WALK_TERMINATE);
		}
		(void) snprintf(devinfo->path, sizeof (devinfo->path),
			"%s/%s@%s", frup->fru_path, node_name, bus_addr);
		return (DI_WALK_TERMINATE);
	}

	if (strstr(bus_addr, ",") != NULL) { /* bus addr is of type 1,0 */
		if (strcmp(bus_addr, char_di_bus_addr) != 0) {
			return (DI_WALK_PRUNECHILD);
		}
	} else { /* bus addr is of type 0x */

		/* check if the values are same */
		errno = 0;
		busaddr = strtol(bus_addr, (char **)NULL, 16);
		if (errno != 0) {
			return (DI_WALK_TERMINATE);
		}

		errno = 0;
		di_busaddr = strtol(char_di_bus_addr, (char **)NULL, 16);
		if (errno != 0) {
			return (DI_WALK_TERMINATE);
		}

		if (di_busaddr != busaddr) {
			return (DI_WALK_PRUNECHILD);
		}
	}

	/* node found */
	path = di_devfs_path(node);
	(void) strncpy(devinfo->path, path, sizeof (devinfo->path));
	di_devfs_path_free(path);
	return (DI_WALK_TERMINATE);
}