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); }
/* * 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 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); }
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); }
/*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); }
/* * 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); }
/* * probe for port nodes */ static int probe_tree(di_node_t node, void *arg) { char *nodetype = NULL; char *devfs_path = NULL; char *bus_addr = NULL; char *drv_name = NULL; plist_t *listptr = NULL; port_info_t *port_info = NULL; frutree_port_type_t port_type = UNKNOWN_PORT; di_minor_t minor = DI_MINOR_NIL; if (arg == NULL) { return (DI_WALK_TERMINATE); } listptr = (plist_t *)arg; while ((minor = di_minor_next(node, minor)) != DI_MINOR_NIL) { nodetype = di_minor_nodetype(minor); if (nodetype == NULL) { continue; } if (strcmp(nodetype, DDI_NT_NET) == 0) { port_type = NETWORK_PORT; } else if (strcmp(nodetype, DDI_NT_PARALLEL) == 0) { port_type = PARALLEL_PORT; } else if ((strcmp(nodetype, DDI_NT_SERIAL) == 0) || (strcmp(nodetype, DDI_NT_SERIAL_MB) == 0) || (strcmp(nodetype, DDI_NT_SERIAL_DO) == 0) || (strcmp(nodetype, DDI_NT_SERIAL_MB_DO) == 0)) { port_type = SERIAL_PORT; } else { continue; } /* found port node */ devfs_path = di_devfs_path(node); if (devfs_path == NULL) { continue; } bus_addr = di_bus_addr(node); drv_name = di_driver_name(node); if ((bus_addr == NULL) || (drv_name == NULL)) { di_devfs_path_free(devfs_path); continue; } port_info = malloc(sizeof (port_info_t)); if (port_info == NULL) { di_devfs_path_free(devfs_path); return (PICL_NOSPACE); } (void) strncpy(port_info->devfs_path, devfs_path, sizeof (port_info->devfs_path)); (void) strncpy(port_info->bus_addr, bus_addr, sizeof (port_info->bus_addr)); (void) strncpy(port_info->drv_name, drv_name, sizeof (port_info->drv_name)); port_info->type = port_type; port_info->instance = di_instance(node); port_info->geo_addr = -1; port_info->next = NULL; switch (port_type) { case NETWORK_PORT: listptr->n_network++; break; case SERIAL_PORT: listptr->n_serial++; break; case PARALLEL_PORT: listptr->n_parallel++; break; } /* add to the list */ if (listptr->first == NULL) { /* 1st node */ listptr->first = port_info; listptr->last = NULL; } else if (listptr->last != NULL) { /* last node */ listptr->last->next = port_info; listptr->last = port_info; } else { /* 2nd node */ listptr->first->next = port_info; listptr->last = port_info; } di_devfs_path_free(devfs_path); return (DI_WALK_CONTINUE); } return (DI_WALK_CONTINUE); }
static disk_t * create_disk(char *deviceid, char *kernel_name, struct search_args *args) { disk_t *diskp; char *type; char *prod_id; char *vendor_id; if (dm_debug) { (void) fprintf(stderr, "INFO: create_disk %s\n", kernel_name); } diskp = calloc(1, sizeof (disk_t)); if (diskp == NULL) { return (NULL); } diskp->controllers = (controller_t **) calloc(1, sizeof (controller_t *)); if (diskp->controllers == NULL) { cache_free_disk(diskp); return (NULL); } diskp->controllers[0] = NULL; diskp->devid = NULL; if (deviceid != NULL) { if ((diskp->device_id = strdup(deviceid)) == NULL) { cache_free_disk(diskp); return (NULL); } (void) devid_str_decode(deviceid, &(diskp->devid), NULL); } if (kernel_name != NULL) { diskp->kernel_name = strdup(kernel_name); if (diskp->kernel_name == NULL) { cache_free_disk(diskp); return (NULL); } } diskp->paths = NULL; diskp->aliases = NULL; diskp->cd_rom = 0; diskp->rpm = 0; diskp->solid_state = -1; type = di_minor_nodetype(args->minor); prod_id = get_str_prop(PROD_ID_PROP, args->node); if (prod_id != NULL) { if ((diskp->product_id = strdup(prod_id)) == NULL) { cache_free_disk(diskp); return (NULL); } } else { prod_id = get_str_prop(PROD_ID_USB_PROP, args->node); if (prod_id != NULL) { if ((diskp->product_id = strdup(prod_id)) == NULL) { cache_free_disk(diskp); return (NULL); } } } vendor_id = get_str_prop(VENDOR_ID_PROP, args->node); if (vendor_id != NULL) { if ((diskp->vendor_id = strdup(vendor_id)) == NULL) { cache_free_disk(diskp); return (NULL); } } else { vendor_id = get_str_prop(VENDOR_ID_USB_PROP, args->node); if (vendor_id != NULL) { if ((diskp->vendor_id = strdup(vendor_id)) == NULL) { cache_free_disk(diskp); return (NULL); } } } /* * DVD, CD-ROM, CD-RW, MO, etc. are all reported as CD-ROMS. * We try to use uscsi later to determine the real type. * The cd_rom flag tells us that the kernel categorized the drive * as a CD-ROM. We leave the drv_type as UNKNOWN for now. * The combination of the cd_rom flag being set with the drv_type of * unknown is what triggers the uscsi probe in drive.c. */ if (disk_is_cdrom(type)) { diskp->drv_type = DM_DT_UNKNOWN; diskp->cd_rom = 1; diskp->removable = 1; } else if (libdiskmgt_str_eq(type, DDI_NT_FD)) { diskp->drv_type = DM_DT_FLOPPY; diskp->removable = 1; } else { /* not a CD-ROM or Floppy */ diskp->removable = get_prop(REMOVABLE_PROP, args->node); if (diskp->removable == -1) { diskp->removable = 0; diskp->drv_type = DM_DT_FIXED; } } diskp->next = args->disk_listp; args->disk_listp = diskp; return (diskp); }
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 is_drive(di_minor_t minor) { return (strncmp(di_minor_nodetype(minor), DDI_NT_BLOCK, strlen(DDI_NT_BLOCK)) == 0); }