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); }
/* * 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); }
/* * 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); }
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); }
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); }
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); }
/* * 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); }
/* * 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); }
/* * 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); }
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); }
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); } } }
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); }
/* * 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); }
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); }
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)); }
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); }
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); }
/* * 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); }
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); }
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); }
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); }
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); }
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); }
/* * 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); }
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); }