static int gpio(di_minor_t minor, di_node_t node) { char l_path[PATH_MAX], p_path[PATH_MAX], *buf, *devfspath; char *minor_nm, *drvr_nm; minor_nm = di_minor_name(minor); drvr_nm = di_driver_name(node); if ((minor_nm == NULL) || (drvr_nm == NULL)) { return (DEVFSADM_CONTINUE); } devfspath = di_devfs_path(node); (void) strcpy(p_path, devfspath); (void) strcat(p_path, ":"); (void) strcat(p_path, minor_nm); di_devfs_path_free(devfspath); /* build the physical path from the components */ if (devfsadm_enumerate_int(p_path, 0, &buf, gpio_rules, 1)) { return (DEVFSADM_CONTINUE); } (void) snprintf(l_path, sizeof (l_path), "%s%s", "gpio", buf); free(buf); (void) devfsadm_mklink(l_path, node, minor, 0); return (DEVFSADM_CONTINUE); }
/*ARGSUSED*/ static scfga_ret_t drv_to_dyncomp(di_node_t node, const char *phys, char **dyncompp, int *l_errnop) { char *drv; int inst; const int dynlen = MAXPATHLEN; scfga_ret_t ret; *l_errnop = 0; if ((*dyncompp = calloc(1, dynlen)) == NULL) { *l_errnop = errno; return (SCFGA_LIB_ERR); } drv = di_driver_name(node); inst = di_instance(node); if (drv != NULL && inst != -1) { if (snprintf(*dyncompp, dynlen, "%s%d", drv, inst) < dynlen) { return (SCFGA_OK); } else { ret = SCFGA_LIB_ERR; } } else { ret = SCFGA_APID_NOEXIST; } S_FREE(*dyncompp); return (ret); }
/* * Handles: * minor node type "ddi_printer". * rules of the form: type=ddi_printer;name=bpp \M0 */ static int printer_create(di_minor_t minor, di_node_t node) { char *mn; char path[PATH_MAX + 1], *buf; devfsadm_enumerate_t rules[1] = {"^printers$/^([0-9]+)$", 1, MATCH_ALL}; mn = di_minor_name(minor); if (strcmp(di_driver_name(node), "bpp") == 0) { (void) devfsadm_mklink(mn, node, minor, 0); } if (NULL == (buf = di_devfs_path(node))) { return (DEVFSADM_CONTINUE); } (void) snprintf(path, sizeof (path), "%s:%s", buf, mn); di_devfs_path_free(buf); if (devfsadm_enumerate_int(path, 0, &buf, rules, 1)) { return (DEVFSADM_CONTINUE); } (void) snprintf(path, sizeof (path), "printers/%s", buf); free(buf); (void) devfsadm_mklink(path, node, minor, 0); return (DEVFSADM_CONTINUE); }
/* * Called by di_walk_node() to walk the list of device nodes and * force all nodes of type "network" to be loaded. * * Returns: DI_WALK_CONTINUE */ static int process_node(di_node_t node, void *arg) { di_prom_handle_t ph = (di_prom_handle_t)arg; char *pdevtype; int ret; /* * Only want to process nodes whose device_type is "network". */ ret = di_prom_prop_lookup_strings(ph, node, "device_type", &pdevtype); if ((ret <= 0) || (strcmp(pdevtype, "network") != 0)) { return (DI_WALK_CONTINUE); } /* * If the instance is '-1', then the driver for the device * has not been loaded - so force it to be loaded. Ignore * errors loading the driver. */ if (di_instance(node) == -1) { node = di_init_driver(di_driver_name(node), 0); if (node != DI_NODE_NIL) { di_fini(node); } } return (DI_WALK_CONTINUE); }
/* * This function is called for every dcam1394 minor node. * Calls enumerate to assign a logical dcam1394 id, and then * devfsadm_mklink to make the link. */ static int dcam1394_process(di_minor_t minor, di_node_t node) { char m_name[PATH_MAX], restring0[DCAM_RE_STRING_LEN]; char l_path[PATH_MAX], p_path[PATH_MAX], *buf, *devfspath; devfsadm_enumerate_t re[1]; (void) strcpy(m_name, di_minor_name(minor)); if (strcmp(di_driver_name(node), "dcam1394") != 0) { return (DEVFSADM_CONTINUE); } if (strncmp(m_name, "dcamctl", 7) == 0) { (void) snprintf(restring0, DCAM_RE_STRING_LEN, DCAM_CTL_LINK_RE); } else if (strncmp(m_name, "dcam", 4) == 0) { (void) snprintf(restring0, DCAM_RE_STRING_LEN, DCAM_STR_LINK_RE); } else { return (DEVFSADM_CONTINUE); } re[0].re = restring0; re[0].subexp = 1; re[0].flags = MATCH_ALL; devfsadm_print(debug_mid, "dcam1394_process: path %s\n", di_devfs_path(node)); (void) strcpy(p_path, devfspath = di_devfs_path(node)); (void) strcat(p_path, ":"); (void) strcat(p_path, di_minor_name(minor)); di_devfs_path_free(devfspath); /* * Build the physical path from the components, omitting * minor name field. Find the logical dcam1394 id, and * stuff it in buf. */ if (devfsadm_enumerate_int(p_path, 0, &buf, re, 1)) { devfsadm_print(debug_mid, "dcam1394_process: exit/continue\n"); return (DEVFSADM_CONTINUE); } devfsadm_print(debug_mid, "dcam1394_process: p_path=%s buf=%s\n", p_path, buf); if (strncmp(di_minor_name(minor), "dcamctl", 7) == 0) (void) snprintf(l_path, PATH_MAX, "dcamctl%s", buf); else (void) snprintf(l_path, PATH_MAX, "dcam%s", buf); (void) devfsadm_mklink(l_path, node, minor, 0); free(buf); return (DEVFSADM_CONTINUE); }
/*ARGSUSED*/ static int MODULEprop_set(tnode_t *tn, did_t *pd, const char *dpnm, const char *tpgrp, const char *tpnm) { nvlist_t *mod; topo_mod_t *mp; char *dnm; int err; if ((dnm = di_driver_name(did_dinode(pd))) == NULL) return (0); mp = did_mod(pd); if ((mod = topo_mod_modfmri(mp, FM_MOD_SCHEME_VERSION, dnm)) == NULL) return (0); /* driver maybe detached, return success */ if (topo_prop_set_fmri(tn, tpgrp, tpnm, TOPO_PROP_IMMUTABLE, mod, &err) < 0) { nvlist_free(mod); return (topo_mod_seterrno(mp, err)); } nvlist_free(mod); return (0); }
/* Make logical name for HBA based on driver and instance */ static int drv_to_hba_logid(di_node_t node, di_minor_t minor, void *arg) { int inst; char *drv, *mn, *log; pathm_t *ptp; const size_t loglen = MAXPATHLEN; ptp = (pathm_t *)arg; errno = 0; mn = di_minor_name(minor); drv = di_driver_name(node); inst = di_instance(node); log = calloc(1, loglen); if (mn != NULL && drv != NULL && inst != -1 && log != NULL) { /* Count does not include terminating NULL */ if (snprintf(log, loglen, "%s%d:%s", drv, inst, mn) < loglen) { ptp->ret = SCFGA_OK; ptp->log = log; return (DI_WALK_TERMINATE); } } S_FREE(log); return (DI_WALK_CONTINUE); }
/* * Handles links of the form: * type=ddi_printer;name=ecpp ecpp\N0 */ static int ecpp_create(di_minor_t minor, di_node_t node) { char *buf; char path[PATH_MAX + 1]; devfsadm_enumerate_t rules[1] = {"^ecpp([0-9]+)$", 1, MATCH_ALL}; if (strcmp(di_driver_name(node), "ecpp") != 0) { return (DEVFSADM_CONTINUE); } if ((buf = di_devfs_path(node)) == NULL) { 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), "ecpp%s", buf); free(buf); (void) devfsadm_mklink(path, node, minor, 0); return (DEVFSADM_CONTINUE); }
/* * handle case where device has been probed but its target driver is not * attached so enumeration has not quite finished. Opening the /devices * pathname will force the kernel to finish the enumeration process and * let us get the data we need. */ static void get_devid(di_node_t node, ddi_devid_t *thisdevid) { int fd; char realpath[MAXPATHLEN]; char *openpath = di_devfs_path(node); errno = 0; bzero(realpath, MAXPATHLEN); if (strstr(openpath, "/devices") == NULL) { (void) snprintf(realpath, MAXPATHLEN, "/devices%s:c,raw", openpath); fd = open(realpath, O_RDONLY|O_NDELAY); } else { fd = open(openpath, O_RDONLY|O_NDELAY); } if (fd < 0) { logmsg(MSG_INFO, "Unable to open path %s: %s\n", openpath, strerror(errno)); return; } if (devid_get(fd, thisdevid) != 0) { logmsg(MSG_INFO, "'%s' node (%s) without a devid registered\n", di_driver_name(node), di_devfs_path(node)); } (void) close(fd); }
/* * Called by di_walk_minor() to walk the list * of ddi_network minor device nodes and add * the interface to the niclist. * * Returns: DI_WALK_CONTINUE or DI_WALK_TERMINATE. */ static int nic_process_minor_nodes(di_node_t node, di_minor_t minor, void *arg) { wlkreq_t *request = (wlkreq_t *)arg; niclist_t **niclist = request->wr_niclist; char *name; char *nodetype; int instance; int ret; /* * Look for network devices only. Unfortunately, our walk will * include nodes with nodetypes of NULL. */ nodetype = di_minor_nodetype(minor); if ((nodetype == NULL) || (strcmp(nodetype, DDI_NT_NET) != 0)) { return (DI_WALK_CONTINUE); } /* * In the case of DDM_MINOR minor nodes, the minor * name is the name of the driver. However, if the name * doesn't include the instance, then it's not one * one we're interested in. In the case of other * minor nodes, we should be able to get the driver name * and its instance from the node properties. If they are * not valid, then we're not interested in them. */ if (di_minor_type(minor) == DDM_MINOR) { name = di_minor_name(minor); if ((name == NULL) || (strlen(name) == 0) || (!isdigit(name[strlen(name) - 1]))) { return (DI_WALK_CONTINUE); } instance = -1; } else { name = di_driver_name(node); instance = di_instance(node); if ((name == NULL) || (strlen(name) == 0) || (instance == -1)) { return (DI_WALK_CONTINUE); } } /* * Add this one to the niclist. */ ret = nic_add(niclist, name, instance, request->wr_syserr); if (ret != ICFG_SUCCESS) { (*request->wr_err) = ret; return (DI_WALK_TERMINATE); } (*request->wr_numif)++; return (DI_WALK_CONTINUE); }
static int vboxSolarisAddPhysHostIface(di_node_t Node, di_minor_t Minor, void *pvHostNetworkInterfaceList) { NOREF(Minor); /* * Skip aggregations. */ if (!strcmp(di_driver_name(Node), "aggr")) return DI_WALK_CONTINUE; /* * Skip softmacs. */ if (!strcmp(di_driver_name(Node), "softmac")) return DI_WALK_CONTINUE; vboxSolarisAddHostIface(di_driver_name(Node), di_instance(Node), pvHostNetworkInterfaceList); return DI_WALK_CONTINUE; }
static int driver_minor(di_minor_t minor, di_node_t node) { char path[PATH_MAX + 1]; (void) strcpy(path, di_driver_name(node)); (void) strcat(path, di_minor_name(minor)); (void) devfsadm_mklink(path, node, minor, 0); return (DEVFSADM_CONTINUE); }
static USBDEVICESTATE solarisDetermineUSBDeviceState(PUSBDEVICE pDevice, di_node_t Node) { char *pszDriverName = di_driver_name(Node); /* Not possible unless a user explicitly unbinds the default driver. */ if (!pszDriverName) return USBDEVICESTATE_UNUSED; if (!strncmp(pszDriverName, VBOXUSB_DRIVER_NAME, sizeof(VBOXUSB_DRIVER_NAME) - 1)) return USBDEVICESTATE_HELD_BY_PROXY; NOREF(pDevice); return USBDEVICESTATE_USED_BY_HOST_CAPTURABLE; }
/*ARGSUSED*/ static int driverprop_set(tnode_t *tn, di_node_t dn, const char *tpgrp, const char *tpnm, topo_mod_t *mod) { char *dnm; int err; if ((dnm = di_driver_name(dn)) == NULL) return (0); if (topo_prop_set_string(tn, tpgrp, tpnm, TOPO_PROP_IMMUTABLE, dnm, &err) < 0) return (topo_mod_seterrno(mod, err)); return (0); }
/*ARGSUSED*/ static int DRIVERprop_set(tnode_t *tn, did_t *pd, const char *dpnm, const char *tpgrp, const char *tpnm) { char *dnm; int err; if ((dnm = di_driver_name(did_dinode(pd))) == NULL) return (0); if (topo_prop_set_string(tn, tpgrp, tpnm, TOPO_PROP_IMMUTABLE, dnm, &err) < 0) return (topo_mod_seterrno(did_mod(pd), err)); return (0); }
static int getnameinst(char *path, int *instance, char *name, int namelen) { di_node_t node; char *driver_name; if ((node = di_init(&path[8], DINFOSUBTREE)) == DI_NODE_NIL) return (-1); if ((driver_name = di_driver_name(node)) == NULL) { di_fini(node); return (-1); } *instance = di_instance(node); (void) strncpy(name, driver_name, namelen); di_fini(node); return (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); } } }
/*ARGSUSED*/ static int load_driver(di_node_t node, void *arg) { char *drv_name = NULL; char cmd[MAXPATHLEN]; if (di_node_state(node) >= DS_ATTACHED) { return (DI_WALK_CONTINUE); } drv_name = di_driver_name(node); if (drv_name == NULL) { return (DI_WALK_CONTINUE); } (void) snprintf(cmd, sizeof (cmd), "%s %s", DEVFSADM_CMD, drv_name); (void) pclose(popen(cmd, "r")); return (DI_WALK_CONTINUE); }
static void get_phci_driver_name(char *phci_path, char **driver_name) { di_node_t phci_node = DI_NODE_NIL; char *tmp = NULL; phci_node = di_init(phci_path, DINFOCPYONE); if (phci_node == DI_NODE_NIL) { logmsg(MSG_ERROR, gettext("Unable to take phci snapshot " "(%s: %d)\n"), strerror(errno), errno); return; } tmp = di_driver_name(phci_node); if (tmp != NULL) { (void) strncpy(*driver_name, tmp, 10); } di_fini(phci_node); }
static int walk_callback(di_node_t node, void *arg) { struct walk_arg *warg = (struct walk_arg *)arg; char *driver_name; char *path; driver_name = di_driver_name(node); if (driver_name != NULL) { if (strcmp(driver_name, warg->name) == 0 && di_instance(node) == warg->instance) { path = di_devfs_path(node); if (path != NULL) { warg->found = 1; (void) strncpy(warg->path, path, warg->pathlen); } return (DI_WALK_TERMINATE); } } return (DI_WALK_CONTINUE); }
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); }
/*ARGSUSED*/ static int moduleprop_set(tnode_t *tn, di_node_t dn, const char *tpgrp, const char *tpnm, topo_mod_t *mod) { nvlist_t *module; char *dnm; int err; if ((dnm = di_driver_name(dn)) == NULL) return (0); if ((module = topo_mod_modfmri(mod, FM_MOD_SCHEME_VERSION, dnm)) == NULL) return (0); /* driver maybe detached, return success */ if (topo_prop_set_fmri(tn, tpgrp, tpnm, TOPO_PROP_IMMUTABLE, module, &err) < 0) { nvlist_free(module); return (topo_mod_seterrno(mod, err)); } nvlist_free(module); return (0); }
static int getOidList(di_node_t root_node, MP_OID_LIST *pOidList) { int numNodes = 0; int instNum = 0; int majorNum = 0; di_node_t vh_node = DI_NODE_NIL; di_node_t ph_node = DI_NODE_NIL; MP_UINT64 osn = 0; int haveList = (NULL != pOidList); log(LOG_INFO, "getOidList()", " - enter"); vh_node = di_vhci_first_node(root_node); while (DI_NODE_NIL != vh_node) { if ((di_driver_name(vh_node) != NULL) && (strncmp(di_driver_name(vh_node), "scsi_vhci", 9) == 0)) { ph_node = di_phci_first_node(vh_node); while (DI_NODE_NIL != ph_node) { if (haveList) { instNum = di_instance(ph_node); majorNum = di_driver_major(ph_node); log(LOG_INFO, "getOidList()", "instNum = %d", instNum); log(LOG_INFO, "getOidList()", "majorNum = %d", majorNum); if (numNodes < pOidList->oidCount) { osn = 0; osn = MP_STORE_INST_TO_ID(instNum, osn); osn = MP_STORE_MAJOR_TO_ID(majorNum, osn); pOidList->oids[numNodes] .objectSequenceNumber = osn; pOidList->oids[numNodes]. objectType = MP_OBJECT_TYPE_INITIATOR_PORT; pOidList->oids[numNodes]. ownerId = g_pluginOwnerID; } } ++numNodes; ph_node = di_phci_next_node(ph_node); } } vh_node = di_vhci_next_node(vh_node); } log(LOG_INFO, "getOidList()", " - numNodes: %d", numNodes); log(LOG_INFO, "getOidList()", " - exit"); return (numNodes); }
/* * Determine whether the interface was configured manually. */ static boolean_t manual_if_init(void) { boolean_t ret = B_FALSE; char *ncs; char *devpath; di_node_t node; int instance; char *drvname; char ifname[IFNAMSIZ + 1]; /* * If net-config-strategy isn't "manual", don't go any further. */ if ((ncs = get_prop("chosen", BI_NET_CONFIG_STRATEGY, NULL)) == NULL || strcmp(ncs, "manual") != 0) { return (B_FALSE); } /* * First check the 'bootpath' property of /chosen to see whether * it specifies the path of a network device; if so, use this. */ if ((devpath = get_bootpath()) == NULL || (node = path2node(devpath)) == DI_NODE_NIL || !is_network_device(node)) { /* * Must have been booted from CD-ROM or disk; attempt to * use the path defined by the 'net' property of /aliases. */ free(devpath); if ((devpath = get_netalias()) == NULL || (node = path2node(devpath)) == DI_NODE_NIL || !is_network_device(node)) { goto cleanup; } } /* * Get the driver name and instance number of this node. * We may have to load the driver. */ if ((drvname = di_driver_name(node)) == NULL) { goto cleanup; } if ((instance = di_instance(node)) == -1) { di_node_t tmp; /* * Attempt to load the driver, create a new snapshot of the * (possibly changed) device tree and re-compute our node. */ if ((tmp = di_init_driver(drvname, 0)) != DI_NODE_NIL) { di_fini(tmp); if (!snapshot_devtree() || (node = path2node(devpath)) == DI_NODE_NIL) { goto cleanup; } } instance = di_instance(node); } /* * Construct the interface name. */ if (instance == -1) { (void) snprintf(ifname, sizeof (ifname), "%s", di_driver_name(node)); } else { (void) snprintf(ifname, sizeof (ifname), "%s%d", di_driver_name(node), instance); } ret = netif_init(ifname, "manual"); cleanup: free(devpath); return (ret); }
/* * Operates on a single di_node_t, collecting all the device properties * that we need. devnvl is allocated by the caller, and we add our nvpairs * to it if they don't already exist. * * We are _only_ interested in devices which have a devid. We pull in * devices even when they're excluded via stmsboot -D (driver), because * we don't want to miss out on any devid data that might be handy later. */ static int popcheck_devnvl(di_node_t thisnode, nvlist_t *devnvl, char *strdevid) { char *path = NULL; char *curpath = NULL; char *devfspath = NULL; char *prop = NULL; int scsivhciparent = 0; int rv = 0; boolean_t mpxenp = B_FALSE; errno = 0; devfspath = di_devfs_path(thisnode); if (devfspath == NULL) { logmsg(MSG_ERROR, gettext("Unable to determine devfs path for node: %s\n"), strerror(errno)); return (-1); } /* Add a convenient devfspath to devid inverse map */ if (nvlist_add_string(mapnvl, devfspath, strdevid) != 0) { logmsg(MSG_ERROR, gettext("Unable to add device path %s with devid " "%s to mapnvl\n"), devfspath, strdevid); return (-1); } if (di_prop_lookup_strings(DDI_DEV_T_ANY, di_parent_node(thisnode), "mpxio-disable", &prop) >= 0) { if (strncmp(prop, "yes", 3) == 0) { if (!mpxprop) mpxprop++; } } if (strncmp(di_driver_name(di_parent_node(thisnode)), "scsi_vhci", 9) == 0) { scsivhciparent = 1; if (!mpxenabled) mpxenabled++; rv = nvlist_lookup_boolean_value(devnvl, NVL_MPXEN, &mpxenp); if (rv || (mpxenp == B_FALSE)) { rv = nvlist_add_boolean_value(devnvl, NVL_MPXEN, B_TRUE); if (rv) { logmsg(MSG_ERROR, gettext("Unable to add property %s " "(set to B_TRUE) for device %s: " "%s (%d)\n"), NVL_MPXEN, devfspath, strerror(rv), rv); return (-1); } logmsg(MSG_INFO, "NVL_MPXEN :: (B_FALSE->B_TRUE)\n"); } } else { /* turn _off_ the flag if it was enabled */ rv = nvlist_add_boolean_value(devnvl, NVL_MPXEN, B_FALSE); if (rv) { logmsg(MSG_ERROR, gettext("Unable to add property %s " "(set to B_FALSE) for device %s: %s (%d)\n"), NVL_MPXEN, devfspath, strerror(rv), rv); return (-1); } logmsg(MSG_INFO, "NVL_MPXEN :: (B_TRUE-> B_FALSE)\n"); } rv = nvlist_add_string(devnvl, NVL_PHYSPATH, devfspath); if (rv) { logmsg(MSG_ERROR, gettext("Unable to add physical device path (%s) " "property to nvl\n")); return (-1); } if ((curpath = calloc(1, MAXPATHLEN)) == NULL) { logmsg(MSG_ERROR, gettext("Unable to allocate space for current path\n")); return (-1); } curpath = find_link(thisnode); if (curpath == NULL) { if (readonlyroot) { return (0); } logmsg(MSG_ERROR, gettext("Unable to determine device path for node %s\n"), devfspath); return (-1); } rv = nvlist_lookup_string(devnvl, NVL_MPXPATH, &path); if (scsivhciparent) { (void) nvlist_add_string(devnvl, NVL_MPXPATH, curpath); } else { (void) nvlist_add_string(devnvl, NVL_PATH, curpath); path = curpath; } /* * This next block provides the path to devid inverse mapping * that other functions require */ if (path != NULL) { if (nvlist_add_string(mapnvl, path, strdevid) != 0) { logmsg(MSG_ERROR, gettext("Unable to add device %s with devid " "%s to mapnvl\n"), path, strdevid); return (-1); } logmsg(MSG_INFO, "popcheck_devnvl: added path %s :: %s\n", path, strdevid); } if (nvlist_add_string(mapnvl, curpath, strdevid) != 0) { logmsg(MSG_ERROR, gettext("Unable to add device %s with devid " "%s to mapnvl: %s\n"), curpath, strdevid, strerror(errno)); return (-1); } logmsg(MSG_INFO, "popcheck_devnvl: added curpath %s :: %s\n", curpath, strdevid); return (0); }
static int solarisWalkDeviceNode(di_node_t Node, void *pvArg) { PUSBDEVICELIST pList = (PUSBDEVICELIST)pvArg; AssertPtrReturn(pList, DI_WALK_TERMINATE); /* * Check if it's a USB device in the first place. */ bool fUSBDevice = false; char *pszCompatNames = NULL; int cCompatNames = di_compatible_names(Node, &pszCompatNames); for (int i = 0; i < cCompatNames; i++, pszCompatNames += strlen(pszCompatNames) + 1) if (!strncmp(pszCompatNames, "usb", 3)) { fUSBDevice = true; break; } if (!fUSBDevice) return DI_WALK_CONTINUE; /* * Check if it's a device node or interface. */ int *pInt = NULL; char *pStr = NULL; int rc = DI_WALK_CONTINUE; if (di_prop_lookup_ints(DDI_DEV_T_ANY, Node, "interface", &pInt) < 0) { /* It's a device node. */ char *pszDevicePath = di_devfs_path(Node); PUSBDEVICE pCur = (PUSBDEVICE)RTMemAllocZ(sizeof(*pCur)); if (!pCur) { LogRel(("USBService: failed to allocate %d bytes for PUSBDEVICE.\n", sizeof(*pCur))); return DI_WALK_TERMINATE; } bool fValidDevice = false; do { AssertBreak(pszDevicePath); char *pszDriverName = di_driver_name(Node); /* * Skip hubs */ if ( pszDriverName && !strcmp(pszDriverName, "hubd")) { break; } /* * Mandatory. * snv_85 and above have usb-dev-descriptor node properties, but older one's do not. * So if we cannot obtain the entire device descriptor, we try falling back to the * individual properties (those must not fail, if it does we drop the device). */ uchar_t *pDevData = NULL; int cbProp = di_prop_lookup_bytes(DDI_DEV_T_ANY, Node, "usb-dev-descriptor", &pDevData); if ( cbProp > 0 && pDevData) { usb_dev_descr_t *pDeviceDescriptor = (usb_dev_descr_t *)pDevData; pCur->bDeviceClass = pDeviceDescriptor->bDeviceClass; pCur->bDeviceSubClass = pDeviceDescriptor->bDeviceSubClass; pCur->bDeviceProtocol = pDeviceDescriptor->bDeviceProtocol; pCur->idVendor = pDeviceDescriptor->idVendor; pCur->idProduct = pDeviceDescriptor->idProduct; pCur->bcdDevice = pDeviceDescriptor->bcdDevice; pCur->bcdUSB = pDeviceDescriptor->bcdUSB; pCur->bNumConfigurations = pDeviceDescriptor->bNumConfigurations; pCur->fPartialDescriptor = false; } else { AssertBreak(di_prop_lookup_ints(DDI_DEV_T_ANY, Node, "usb-vendor-id", &pInt) > 0); pCur->idVendor = (uint16_t)*pInt; AssertBreak(di_prop_lookup_ints(DDI_DEV_T_ANY, Node, "usb-product-id", &pInt) > 0); pCur->idProduct = (uint16_t)*pInt; AssertBreak(di_prop_lookup_ints(DDI_DEV_T_ANY, Node, "usb-revision-id", &pInt) > 0); pCur->bcdDevice = (uint16_t)*pInt; AssertBreak(di_prop_lookup_ints(DDI_DEV_T_ANY, Node, "usb-release", &pInt) > 0); pCur->bcdUSB = (uint16_t)*pInt; pCur->fPartialDescriptor = true; } char *pszPortAddr = di_bus_addr(Node); if (pszPortAddr) pCur->bPort = RTStrToUInt8(pszPortAddr); /* Bus & Port are mixed up (kernel driver/userland) */ else pCur->bPort = 0; char pathBuf[PATH_MAX]; RTStrPrintf(pathBuf, sizeof(pathBuf), "%s", pszDevicePath); RTPathStripFilename(pathBuf); char szBuf[PATH_MAX + 48]; RTStrPrintf(szBuf, sizeof(szBuf), "%#x:%#x:%d:%s", pCur->idVendor, pCur->idProduct, pCur->bcdDevice, pathBuf); pCur->pszAddress = RTStrDup(szBuf); pCur->pszDevicePath = RTStrDup(pszDevicePath); AssertBreak(pCur->pszDevicePath); /* * Optional (some devices don't have all these) */ if (di_prop_lookup_strings(DDI_DEV_T_ANY, Node, "usb-product-name", &pStr) > 0) pCur->pszProduct = RTStrDup(pStr); if (di_prop_lookup_strings(DDI_DEV_T_ANY, Node, "usb-vendor-name", &pStr) > 0) pCur->pszManufacturer = RTStrDup(pStr); if (di_prop_lookup_strings(DDI_DEV_T_ANY, Node, "usb-serialno", &pStr) > 0) pCur->pszSerialNumber = RTStrDup(pStr); if (di_prop_lookup_ints(DDI_DEV_T_ANY, Node, "low-speed", &pInt) >= 0) pCur->enmSpeed = USBDEVICESPEED_LOW; else if (di_prop_lookup_ints(DDI_DEV_T_ANY, Node, "high-speed", &pInt) >= 0) pCur->enmSpeed = USBDEVICESPEED_HIGH; else pCur->enmSpeed = USBDEVICESPEED_FULL; /* Determine state of the USB device. */ pCur->enmState = solarisDetermineUSBDeviceState(pCur, Node); /* * Valid device, add it to the list. */ fValidDevice = true; pCur->pPrev = pList->pTail; if (pList->pTail) pList->pTail = pList->pTail->pNext = pCur; else pList->pTail = pList->pHead = pCur; rc = DI_WALK_CONTINUE; } while(0); di_devfs_path_free(pszDevicePath); if (!fValidDevice) solarisFreeUSBDevice(pCur); } return rc; }
/* * Retrieves the statistics for a specified port.phy on an adapter */ HBA_STATUS Sun_sasGetPhyStatistics(HBA_HANDLE handle, HBA_UINT32 port, HBA_UINT32 phy, SMHBA_PHYSTATISTICS *pStatistics) { const char ROUTINE[] = "Sun_sasGetPhyStatistics"; HBA_STATUS status = HBA_STATUS_OK; struct sun_sas_hba *hba_ptr; struct sun_sas_port *hba_port_ptr; struct phy_info *phy_ptr; PSMHBA_SASPHYSTATISTICS psas; kstat_ctl_t *kc; kstat_t *ksp; kstat_named_t *kname; char *charptr, path[MAXPATHLEN + 1]; char *driver_name, kstat_name[256]; di_node_t node; int instance = 0; int i; uint64_t iport_wwn; /* Validate the arguments */ if (pStatistics == NULL) { log(LOG_DEBUG, ROUTINE, "NULL Phy Statistics buffer of phyIndex: %08lx", phy); return (HBA_STATUS_ERROR_ARG); } psas = pStatistics->SASPhyStatistics; if (psas == NULL) { log(LOG_DEBUG, ROUTINE, "NULL SAS Phy Statistics buffer of phyIndex: %08lx", phy); return (HBA_STATUS_ERROR_ARG); } lock(&all_hbas_lock); if ((hba_ptr = Retrieve_Sun_sasHandle(handle)) == NULL) { log(LOG_DEBUG, ROUTINE, "Invalid HBA handler %08lx of phyIndex: %08lx", handle, phy); unlock(&all_hbas_lock); return (HBA_STATUS_ERROR_INVALID_HANDLE); } /* Check for stale data */ status = verifyAdapter(hba_ptr); if (status != HBA_STATUS_OK) { log(LOG_DEBUG, ROUTINE, "Verify Adapter failed for phyIndex: %08lx", phy); unlock(&all_hbas_lock); return (status); } for (hba_port_ptr = hba_ptr->first_port; hba_port_ptr != NULL; hba_port_ptr = hba_port_ptr->next) { if (hba_port_ptr->index == port) { break; } } if (hba_port_ptr == NULL) { log(LOG_DEBUG, ROUTINE, "Invalid port index of phyIndex: %08lx", phy); unlock(&all_hbas_lock); return (HBA_STATUS_ERROR_ILLEGAL_INDEX); } if (phy >= hba_port_ptr->port_attributes.PortSpecificAttribute. SASPort->NumberofPhys) { log(LOG_DEBUG, ROUTINE, "Invalid phy index %08lx", phy); unlock(&all_hbas_lock); return (HBA_STATUS_ERROR_ILLEGAL_INDEX); } /* We need to find out the phy identifier. */ for (phy_ptr = hba_port_ptr->first_phy; phy_ptr != NULL; phy_ptr = phy_ptr->next) { if (phy == phy_ptr->index) break; } if (phy_ptr == NULL) { log(LOG_DEBUG, ROUTINE, "Invalid phy index %08lx", phy); unlock(&all_hbas_lock); return (HBA_STATUS_ERROR_ILLEGAL_INDEX); } /* * for statistics that are not supported, its bits should all be * set to -1 */ (void) memset(pStatistics->SASPhyStatistics, 0xff, sizeof (SMHBA_SASPHYSTATISTICS)); /* First, we need the deivce path to locate the devinfo node. */ (void *) strlcpy(path, hba_port_ptr->device_path, sizeof (path)); charptr = strrchr(path, ':'); if (charptr) { *charptr = '\0'; } errno = 0; (void *) memset(kstat_name, 0, sizeof (kstat_name)); node = di_init(path, DINFOCPYONE); if (node == DI_NODE_NIL) { di_fini(node); log(LOG_DEBUG, ROUTINE, "Unable to take devinfo snapshot on HBA \"%s\" " "for phyIndex: %08lx due to %s", path, phy, strerror(errno)); unlock(&all_hbas_lock); return (HBA_STATUS_ERROR); } /* * Then we could fetch the instance number and driver name of this * device. */ instance = di_instance(node); if (instance == -1) { di_fini(node); log(LOG_DEBUG, ROUTINE, "An instance number has not been assigned to the " "device \"%s\" when get phyIndex: %08lx", path, phy); unlock(&all_hbas_lock); return (HBA_STATUS_ERROR); } driver_name = di_driver_name(node); if (driver_name == NULL) { di_fini(node); log(LOG_DEBUG, ROUTINE, "No driver bound to this device \"%s\" " "when get phyIndex: %08lx", path, phy); unlock(&all_hbas_lock); return (HBA_STATUS_ERROR); } di_fini(node); iport_wwn = wwnConversion(hba_port_ptr->port_attributes.\ PortSpecificAttribute.SASPort->LocalSASAddress.wwn); /* * Construct the kstat name here. */ (void) snprintf(kstat_name, sizeof (kstat_name), "%s.%016llx.%u.%u", driver_name, iport_wwn, instance, phy_ptr->phy.PhyIdentifier); /* retrieve all the statistics from kstat. */ kc = kstat_open(); if (kc == NULL) { log(LOG_DEBUG, ROUTINE, "kstat_open failed due to \"%s\" of phyIndex: %08lx", strerror(errno), phy); unlock(&all_hbas_lock); return (HBA_STATUS_ERROR); } ksp = kstat_lookup(kc, NULL, -1, kstat_name); if (ksp == NULL) { log(LOG_DEBUG, ROUTINE, "No matching kstat name found for \"%s\" " "of phyIndex: %08lx", kstat_name, phy); unlock(&all_hbas_lock); (void) kstat_close(kc); return (HBA_STATUS_ERROR); } /* Found the phy we're looking for. */ if (kstat_read(kc, ksp, NULL) == -1) { log(LOG_DEBUG, ROUTINE, "error reading kstat data due to \"%s\" " "of phyIndex: %08lx", strerror(errno), phy); unlock(&all_hbas_lock); (void) kstat_close(kc); return (HBA_STATUS_ERROR); } kname = (kstat_named_t *)ksp->ks_data; for (i = 0; i < ksp->ks_ndata; i++, kname++) { if (strcmp(kname->name, "SecondsSinceLastReset") == 0) { psas->SecondsSinceLastReset = kname->value.ull; continue; } if (strcmp(kname->name, "TxFrames") == 0) { psas->TxFrames = kname->value.ull; continue; } if (strcmp(kname->name, "RxFrames") == 0) { psas->RxFrames = kname->value.ull; continue; } if (strcmp(kname->name, "TxWords") == 0) { psas->TxWords = kname->value.ull; continue; } if (strcmp(kname->name, "RxWords") == 0) { psas->RxWords = kname->value.ull; continue; } if (strcmp(kname->name, "InvalidDwordCount") == 0) { psas->InvalidDwordCount = kname->value.ull; continue; } if (strcmp(kname->name, "RunningDisparityErrorCount") == 0) { psas->RunningDisparityErrorCount = kname->value.ull; continue; } if (strcmp(kname->name, "LossofDwordSyncCount") == 0) { psas->LossofDwordSyncCount = kname->value.ull; continue; } if (strcmp(kname->name, "PhyResetProblemCount") == 0) { psas->PhyResetProblemCount = kname->value.ull; } } unlock(&all_hbas_lock); (void) kstat_close(kc); return (HBA_STATUS_OK); }
/* Converts a driver and instance number based logid into a physical path */ static int do_drv_dyn_to_devpath(di_node_t node, void *arg) { int inst, rv, match_minor; devpath_t *dptp; char *physpath, *drv; char *drvinst, *devpath; const size_t drvlen = MAXPATHLEN; size_t devlen; dptp = (devpath_t *)arg; assert(dptp->hba_phys != NULL && dptp->dyncomp != NULL); assert(dptp->path == NULL); /* * Skip stub nodes */ if (IS_STUB_NODE(node)) { return (DI_WALK_CONTINUE); } errno = 0; drv = di_driver_name(node); inst = di_instance(node); physpath = di_devfs_path(node); if (drv == NULL || inst == -1 || physpath == NULL) { rv = DI_WALK_CONTINUE; goto out; } devlen = strlen(DEVICES_DIR) + strlen(physpath) + 1; devpath = calloc(1, devlen); drvinst = calloc(1, drvlen); if (devpath == NULL || drvinst == NULL) { dptp->l_errno = errno; dptp->ret = SCFGA_LIB_ERR; rv = DI_WALK_TERMINATE; goto out; } (void) snprintf(drvinst, drvlen, "%s%d", drv, inst); /* Create the physical path */ (void) snprintf(devpath, devlen, "%s%s", DEVICES_DIR, physpath); /* Skip node if it is the HBA */ match_minor = 0; if (!dev_cmp(dptp->hba_phys, devpath, match_minor)) { rv = DI_WALK_CONTINUE; goto out; } /* Compare the base and dynamic components */ if (!hba_dev_cmp(dptp->hba_phys, devpath) && strcmp(dptp->dyncomp, drvinst) == 0) { dptp->ret = SCFGA_OK; dptp->path = devpath; rv = DI_WALK_TERMINATE; } else { rv = DI_WALK_CONTINUE; } /*FALLTHRU*/ out: S_FREE(drvinst); if (physpath != NULL) di_devfs_path_free(physpath); if (dptp->ret != SCFGA_OK) S_FREE(devpath); return (rv); }
/* * 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); }
/*ARGSUSED*/ static int devfs_entry(di_node_t node, di_minor_t minor, void *arg) { char *devfspath; char resource[MAXPATHLEN]; char dev[MAXNAMELEN]; datalink_id_t linkid; char *drv; char *cp; net_cache_t *probe; cp = di_minor_nodetype(minor); if ((cp == NULL) || (strcmp(cp, DDI_NT_NET))) { /* doesn't look like a network device */ return (DI_WALK_CONTINUE); } drv = di_driver_name(node); if (drv == NULL) { /* what else can we do? */ return (DI_WALK_CONTINUE); } devfspath = di_devfs_path(node); if (!devfspath) { /* no devfs path?!? */ rcm_log_message(RCM_DEBUG, _("NET: missing devfs path\n")); return (DI_WALK_CONTINUE); } if (strncmp("/pseudo", devfspath, strlen("/pseudo")) == 0) { /* ignore pseudo devices, probably not really NICs */ rcm_log_message(RCM_DEBUG, _("NET: ignoring pseudo device %s\n"), devfspath); di_devfs_path_free(devfspath); return (DI_WALK_CONTINUE); } (void) snprintf(resource, sizeof (resource), "/devices%s", devfspath); di_devfs_path_free(devfspath); (void) snprintf(dev, sizeof (dev), "%s%d", drv, di_instance(node)); if (dladm_dev2linkid(dld_handle, dev, &linkid) != DLADM_STATUS_OK) { rcm_log_message(RCM_DEBUG, _("NET: failed to find the linkid for %s\n"), dev); return (DI_WALK_CONTINUE); } probe = cache_lookup(resource); if (probe != NULL) { rcm_log_message(RCM_DEBUG, _("NET: %s already registered (linkid %u)\n"), resource, linkid); probe->linkid = linkid; probe->flags &= ~(CACHE_STALE); } else { rcm_log_message(RCM_DEBUG, _("NET: %s is new resource (linkid %u)\n"), resource, linkid); probe = calloc(1, sizeof (net_cache_t)); if (!probe) { rcm_log_message(RCM_ERROR, _("NET: malloc failure")); return (DI_WALK_CONTINUE); } probe->resource = strdup(resource); probe->linkid = linkid; if (!probe->resource) { free_node(probe); return (DI_WALK_CONTINUE); } probe->flags |= CACHE_NEW; cache_insert(probe); } return (DI_WALK_CONTINUE); }