/* di_walk_node callback for disk_list_gather */ static int dev_walk_di_nodes(di_node_t node, void *arg) { char *devidstr = NULL; char *s; int *val; /* * If it's not a scsi_vhci client and doesn't have a target_port * property and doesn't have a target property then it's not a storage * device and we're not interested. */ if (di_path_client_next_path(node, NULL) == NULL && di_prop_lookup_strings(DDI_DEV_T_ANY, node, SCSI_ADDR_PROP_TARGET_PORT, &s) <= 0 && di_prop_lookup_ints(DDI_DEV_T_ANY, node, SCSI_ADDR_PROP_TARGET, &val) <= 0) { return (DI_WALK_CONTINUE); } (void) di_prop_lookup_strings(DDI_DEV_T_ANY, node, DEVID_PROP_NAME, &devidstr); /* create/find the devid scsi topology node */ (void) dev_di_node_add(node, devidstr, arg); return (DI_WALK_CONTINUE); }
/* * The following boot properties can be used to configure a network * interface in the case of a diskless boot. * host-ip, subnet-mask, server-path, server-name, server-ip. * * XXX non-diskless case requires "network-interface"? */ static boolean_t boot_properties_present() { /* XXX should use sys/bootprops.h, but it's not delivered */ const char *required_properties[] = { "host-ip", "subnet-mask", "server-path", "server-name", "server-ip", NULL, }; const char **prop = required_properties; char *prop_value; di_node_t dn; if ((dn = di_init("/", DINFOPROP)) == DI_NODE_NIL) { (void) fprintf(stderr, "%s: di_init: %s\n", program, strerror(errno)); di_fini(dn); return (B_FALSE); } while (*prop != NULL) { if (di_prop_lookup_strings(DDI_DEV_T_ANY, dn, *prop, &prop_value) != 1) { di_fini(dn); return (B_FALSE); } prop++; } di_fini(dn); return (B_TRUE); }
static int print_bootpath() { char *bootprop = NULL; if (di_prop_lookup_strings(DDI_DEV_T_ANY, devinfo_root, "bootpath", &bootprop) >= 0) { (void) printf("%s\n", bootprop); return (0); } else if (di_prop_lookup_strings(DDI_DEV_T_ANY, devinfo_root, "boot-path", &bootprop) >= 0) { (void) printf("%s\n", bootprop); return (0); } else { (void) printf("ERROR: no bootpath/boot-path property found\n"); return (ENOENT); } }
static char * get_str_prop(char *prop_name, di_node_t node) { char *str; if (di_prop_lookup_strings(DDI_DEV_T_ANY, node, prop_name, &str) == 1) { return (str); } return (NULL); }
static int count_cb(di_node_t node, void *arg) { struct cb_data *cb = (struct cb_data *)arg; char *prop_data; if (di_prop_lookup_strings(DDI_DEV_T_ANY, node, "zfd_zname", &prop_data) != -1) { assert(prop_data != NULL); if (strcmp(prop_data, zone_name) == 0) { cb->found++; return (DI_WALK_CONTINUE); } } return (DI_WALK_CONTINUE); }
static int disk_callback_fabric(di_minor_t minor, di_node_t node) { char disk[DISK_SUBPATH_MAX]; int lun; int count; int *intp; uchar_t *str; uchar_t *wwn; uchar_t ascii_wwn[ASCIIWWNSIZE]; if (di_prop_lookup_strings(DDI_DEV_T_ANY, node, "client-guid", (char **)&wwn) > 0) { if (strlcpy((char *)ascii_wwn, (char *)wwn, sizeof (ascii_wwn)) >= sizeof (ascii_wwn)) { devfsadm_errprint("SUNW_disk_link: GUID too long:%d", strlen((char *)wwn)); return (DEVFSADM_CONTINUE); } lun = 0; } else if (di_prop_lookup_bytes(DDI_DEV_T_ANY, node, "port-wwn", &wwn) > 0) { if (di_prop_lookup_ints(DDI_DEV_T_ANY, node, SCSI_ADDR_PROP_LUN, &intp) > 0) { lun = *intp; } else { lun = 0; } for (count = 0, str = ascii_wwn; count < 8; count++, str += 2) { (void) sprintf((caddr_t)str, "%02x", wwn[count]); } *str = '\0'; } else { return (DEVFSADM_CONTINUE); } for (str = ascii_wwn; *str != '\0'; str++) { *str = DISK_LINK_TO_UPPER(*str); } (void) snprintf(disk, DISK_SUBPATH_MAX, "t%sd%d", ascii_wwn, lun); disk_common(minor, node, disk, RM_STALE); return (DEVFSADM_CONTINUE); }
/* * For the zfs control node: * /dev/zfs -> /devices/pseudo/zfs@0:zfs * For zvols: * /dev/zvol/dsk/<pool>/<dataset> -> /devices/pseudo/zfs@0:1 * /dev/zvol/rdsk/<pool>/<dataset> -> /devices/pseudo/zfs@0:1,raw */ static int zfs(di_minor_t minor, di_node_t node) { dev_t dev; int err; char mn[MAXNAMELEN + 1]; char blkname[MAXNAMELEN + 1]; char rawname[MAXNAMELEN + 1]; char path[PATH_MAX + 1]; char *name; (void) strcpy(mn, di_minor_name(minor)); if (strcmp(mn, ZFS_DRIVER) == 0) { (void) devfsadm_mklink(ZFS_DRIVER, node, minor, 0); } else { dev = di_minor_devt(minor); err = di_prop_lookup_strings(dev, node, ZVOL_PROP_NAME, &name); if (err < 0) { /* property not defined so can't do anything */ return (DEVFSADM_CONTINUE); } (void) snprintf(blkname, sizeof (blkname), "%dc", (int)minor(dev)); (void) snprintf(rawname, sizeof (rawname), "%dc,raw", (int)minor(dev)); /* * This is where the actual public name gets constructed. * Change the snprintf format to change the public * path that gets constructed. */ if (strcmp(mn, blkname) == 0) { (void) snprintf(path, sizeof (path), "%s/%s", ZVOL_DEV_DIR, name); } else if (strcmp(mn, rawname) == 0) { (void) snprintf(path, sizeof (path), "%s/%s", ZVOL_RDEV_DIR, name); } else { return (DEVFSADM_CONTINUE); } (void) devfsadm_mklink(path, node, minor, 0); } return (DEVFSADM_CONTINUE); }
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); }
static int zcons_create(di_minor_t minor, di_node_t node) { char *minor_str; char *zonename; char path[MAXPATHLEN]; minor_str = di_minor_name(minor); if (di_prop_lookup_strings(DDI_DEV_T_ANY, node, "zonename", &zonename) == -1) { return (DEVFSADM_CONTINUE); } (void) snprintf(path, sizeof (path), "zcons/%s/%s", zonename, minor_str); (void) devfsadm_mklink(path, node, minor, 0); return (DEVFSADM_CONTINUE); }
/* * destroy_zfd_devs() and its helper destroy_cb() tears down any zfd instances * associated with this zone. If things went very wrong, we might have an * incorrect number of instances hanging around. This routine hunts down and * tries to remove all of them. Of course, if the fd is open, the instance will * not detach, which is a potential issue. */ static int destroy_cb(di_node_t node, void *arg) { struct cb_data *cb = (struct cb_data *)arg; char *prop_data; char *tmp; char devpath[MAXPATHLEN]; devctl_hdl_t hdl; if (di_prop_lookup_strings(DDI_DEV_T_ANY, node, "zfd_zname", &prop_data) == -1) return (DI_WALK_CONTINUE); assert(prop_data != NULL); if (strcmp(prop_data, zone_name) != 0) { /* this is a zfd for a different zone */ return (DI_WALK_CONTINUE); } cb->found++; tmp = di_devfs_path(node); (void) snprintf(devpath, sizeof (devpath), "/devices/%s", tmp); di_devfs_path_free(tmp); if ((hdl = devctl_device_acquire(devpath, 0)) == NULL) { zerror(cb->zlogp, B_TRUE, "WARNING: zfd %s found, " "but it could not be controlled.", devpath); return (DI_WALK_CONTINUE); } if (devctl_device_remove(hdl) == 0) { cb->killed++; } else { zerror(cb->zlogp, B_TRUE, "WARNING: zfd %s found, " "but it could not be removed.", devpath); } devctl_release(hdl); return (DI_WALK_CONTINUE); }
HalDevice * devinfo_add_node(HalDevice *parent, di_node_t node) { HalDevice *d = NULL; char *devfs_path; char *device_type = NULL; DevinfoDevHandler *handler; int i; devfs_path = di_devfs_path (node); (void) di_prop_lookup_strings (DDI_DEV_T_ANY, node, "device_type", &device_type); for (i = 0; (d == NULL) && (devinfo_handlers[i] != NULL); i++) { handler = devinfo_handlers[i]; d = handler->add (parent, node, devfs_path, device_type); } di_devfs_path_free(devfs_path); HAL_INFO (("add_node: %s", d ? hal_device_get_udi (d) : "none")); return (d); }
/* * 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 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 dev_di_node_add(di_node_t node, char *devid, disk_cbdata_t *cbp) { topo_mod_t *mod = cbp->dcb_mod; dev_di_node_t *dnode; di_path_t pnode; char *path; int mlen; char *minorpath; char *extn = ":a"; char *s; int64_t *nblocksp; uint64_t nblocks; int *dblksizep; uint_t dblksize; char lentry[MAXPATHLEN]; int pathcount; int *inq_dtype, itype; int i; if (devid) { /* * Check for list duplicate using devid search. * Note if there is no devid, then we can end up with duplicates * in the list, but this doesn't do any harm. */ for (dnode = topo_list_next(cbp->dcb_list); dnode != NULL; dnode = topo_list_next(dnode)) { if (dnode->ddn_devid && devid_str_compare(dnode->ddn_devid, devid) == 0) { topo_mod_dprintf(mod, "dev_di_node_add: " "already there %s\n", devid); return (0); } } } if ((dnode = topo_mod_zalloc(mod, sizeof (dev_di_node_t))) == NULL) return (-1); if (devid) { /* Establish the devid. */ dnode->ddn_devid = topo_mod_strdup(mod, devid); if (dnode->ddn_devid == NULL) goto error; } /* Establish the devinfo dpath */ if ((path = di_devfs_path(node)) == NULL) { (void) topo_mod_seterrno(mod, errno); goto error; } dnode->ddn_dpath = topo_mod_strdup(mod, path); di_devfs_path_free(path); if (dnode->ddn_dpath == NULL) goto error; /* * Establish the physical ppath and target ports. If the device is * non-mpxio then dpath and ppath are the same, and the target port is a * property of the device node. * * If dpath is a client node under scsi_vhci, then iterate over all * paths and get their physical paths and target port properrties. * di_path_client_next_path call below will * return non-NULL, and ppath is set to the physical path to the first * pathinfo node. * * NOTE: It is possible to get a generic.vs.non-generic path * for di_devfs_path.vs.di_path_devfs_path like: * xml: /pci@7b,0/pci1022,7458@11/pci1000,3060@2/sd@2,0 * pnode: /pci@7b,0/pci1022,7458@11/pci1000,3060@2/disk@2,0 * To resolve this issue disk_declare_path() needs to use the * special di_devfs_path_match() interface. */ pathcount = 0; pnode = NULL; while ((pnode = di_path_client_next_path(node, pnode)) != NULL) { pathcount++; } if (pathcount == 0) { if ((dnode->ddn_ppath = topo_mod_zalloc(mod, sizeof (char *))) == NULL) goto error; dnode->ddn_ppath_count = 1; if ((dnode->ddn_ppath[0] = topo_mod_strdup(mod, dnode->ddn_dpath)) == NULL) goto error; if ((dnode->ddn_target_port = topo_mod_zalloc(mod, sizeof (char *))) == NULL) goto error; if ((dnode->ddn_attached_port = topo_mod_zalloc(mod, sizeof (char *))) == NULL) goto error; if ((dnode->ddn_bridge_port = topo_mod_zalloc(mod, sizeof (char *))) == NULL) goto error; /* There should be only one target port for a devinfo node. */ if ((di_prop_lookup_strings(DDI_DEV_T_ANY, node, SCSI_ADDR_PROP_TARGET_PORT, &s)) == 1) { if ((dnode->ddn_target_port[0] = topo_mod_strdup(mod, scsi_wwnstr_skip_ua_prefix(s))) == NULL) goto error; } if ((di_prop_lookup_strings(DDI_DEV_T_ANY, node, SCSI_ADDR_PROP_ATTACHED_PORT, &s)) == 1) { /* There should be one attached port if any. */ if ((dnode->ddn_attached_port[0] = topo_mod_strdup(mod, scsi_wwnstr_skip_ua_prefix(s))) == NULL) goto error; } if ((di_prop_lookup_strings(DDI_DEV_T_ANY, node, SCSI_ADDR_PROP_BRIDGE_PORT, &s)) == 1) { /* There should be one bridge port if any. */ if ((dnode->ddn_bridge_port[0] = topo_mod_strdup(mod, scsi_wwnstr_skip_ua_prefix(s))) == NULL) goto error; } } else { /* processing a scsi_vhci device. */ if ((dnode->ddn_ppath = topo_mod_zalloc(mod, pathcount * sizeof (char *))) == NULL) goto error; dnode->ddn_ppath_count = pathcount; if ((dnode->ddn_target_port = topo_mod_zalloc(mod, pathcount * sizeof (char *))) == NULL) goto error; if ((dnode->ddn_attached_port = topo_mod_zalloc(mod, pathcount * sizeof (char *))) == NULL) goto error; if ((dnode->ddn_bridge_port = topo_mod_zalloc(mod, pathcount * sizeof (char *))) == NULL) goto error; pnode = NULL; pathcount = 0; while ((pnode = di_path_client_next_path(node, pnode)) != NULL) { if ((path = di_path_devfs_path(pnode)) == NULL) { (void) topo_mod_seterrno(mod, errno); goto error; } dnode->ddn_ppath[pathcount] = topo_mod_strdup(mod, path); di_devfs_path_free(path); if (dnode->ddn_ppath[pathcount] == NULL) goto error; if ((di_path_prop_lookup_strings(pnode, SCSI_ADDR_PROP_TARGET_PORT, &s)) == 1) { if ((dnode->ddn_target_port[pathcount] = topo_mod_strdup(mod, scsi_wwnstr_skip_ua_prefix(s))) == NULL) goto error; } if ((di_path_prop_lookup_strings(pnode, SCSI_ADDR_PROP_ATTACHED_PORT, &s)) == 1) { if ((dnode->ddn_attached_port[pathcount] = topo_mod_strdup(mod, scsi_wwnstr_skip_ua_prefix(s))) == NULL) goto error; } if ((di_path_prop_lookup_strings(pnode, SCSI_ADDR_PROP_BRIDGE_PORT, &s)) == 1) { if ((dnode->ddn_bridge_port[pathcount] = topo_mod_strdup(mod, scsi_wwnstr_skip_ua_prefix(s))) == NULL) goto error; } pathcount++; } } /* * Find the public /dev name for a disk by adding a minor name and using * di_devlink interface for reverse translation (use devinfo path). */ if (di_prop_lookup_ints(DDI_DEV_T_ANY, node, "inquiry-device-type", &inq_dtype) > 0) { dnode->ddn_dtype = *inq_dtype; itype = (*inq_dtype) & DTYPE_MASK; if (itype == DTYPE_DIRECT) { mlen = strlen(dnode->ddn_dpath) + strlen(extn) + 1; if ((minorpath = topo_mod_alloc(mod, mlen)) == NULL) goto error; (void) snprintf(minorpath, mlen, "%s%s", dnode->ddn_dpath, extn); cbp->dcb_dnode = dnode; (void) di_devlink_walk(cbp->dcb_devhdl, "^dsk/", minorpath, DI_PRIMARY_LINK, cbp, disk_devlink_callback); topo_mod_free(mod, minorpath, mlen); if (dnode->ddn_lpath == NULL) { topo_mod_dprintf(mod, "dev_di_node_add: " "failed to determine logical path"); } } } else { dnode->ddn_dtype = DTYPE_UNKNOWN; } /* cache various bits of optional information about the device. */ if (di_prop_lookup_strings(DDI_DEV_T_ANY, node, INQUIRY_VENDOR_ID, &s) > 0) { if ((dnode->ddn_mfg = disk_trim_whitespace(mod, s)) == NULL) goto error; } if (di_prop_lookup_strings(DDI_DEV_T_ANY, node, INQUIRY_PRODUCT_ID, &s) > 0) { if ((dnode->ddn_model = disk_trim_whitespace(mod, s)) == NULL) goto error; } if (di_prop_lookup_strings(DDI_DEV_T_ANY, node, INQUIRY_REVISION_ID, &s) > 0) { if ((dnode->ddn_firm = disk_trim_whitespace(mod, s)) == NULL) goto error; } if (di_prop_lookup_strings(DDI_DEV_T_ANY, node, INQUIRY_SERIAL_NO, &s) > 0) { if ((dnode->ddn_serial = disk_trim_whitespace(mod, s)) == NULL) goto error; } if (di_prop_lookup_int64(DDI_DEV_T_ANY, node, "device-nblocks", &nblocksp) > 0) { nblocks = (uint64_t)*nblocksp; /* * To save kernel memory, the driver may not define * "device-dblksize" when its value is default DEV_BSIZE. */ if (di_prop_lookup_ints(DDI_DEV_T_ANY, node, "device-dblksize", &dblksizep) > 0) dblksize = (uint_t)*dblksizep; else dblksize = DEV_BSIZE; /* default value */ (void) snprintf(lentry, sizeof (lentry), "%" PRIu64, nblocks * dblksize); if ((dnode->ddn_cap = topo_mod_strdup(mod, lentry)) == NULL) goto error; } topo_mod_dprintf(mod, "dev_di_node_add: " "adding %s\n", devid ? dnode->ddn_devid : "NULL devid"); topo_mod_dprintf(mod, " " " %s\n", dnode->ddn_dpath); for (i = 0; i < dnode->ddn_ppath_count; i++) { topo_mod_dprintf(mod, " " " %s\n", dnode->ddn_ppath[i]); } topo_list_append(cbp->dcb_list, dnode); return (0); error: dev_di_node_free(mod, dnode); return (-1); }
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; }
static int disk_callback_sas(di_minor_t minor, di_node_t node) { char disk[DISK_SUBPATH_MAX]; int lun64_found = 0; scsi_lun64_t lun64, sl; scsi_lun_t lun; int64_t *lun64p; uint64_t wwn; int *intp; char *tgt_port; uchar_t addr_method; /* Get lun property */ if (di_prop_lookup_int64(DDI_DEV_T_ANY, node, SCSI_ADDR_PROP_LUN64, &lun64p) > 0) { if (*lun64p != SCSI_LUN64_ILLEGAL) { lun64_found = 1; lun64 = (uint64_t)*lun64p; } } if ((!lun64_found) && (di_prop_lookup_ints(DDI_DEV_T_ANY, node, SCSI_ADDR_PROP_LUN, &intp) > 0)) { lun64 = (uint64_t)*intp; } lun = scsi_lun64_to_lun(lun64); addr_method = (lun.sl_lun1_msb & SCSI_LUN_AM_MASK); if (di_prop_lookup_strings(DDI_DEV_T_ANY, node, SCSI_ADDR_PROP_TARGET_PORT, &tgt_port) > 0) { (void) scsi_wwnstr_to_wwn(tgt_port, &wwn); if ((addr_method == SCSI_LUN_AM_PDEV) && (lun.sl_lun2_msb == 0) && (lun.sl_lun2_lsb == 0) && (lun.sl_lun3_msb == 0) && (lun.sl_lun3_lsb == 0) && (lun.sl_lun4_msb == 0) && (lun.sl_lun4_lsb == 0)) { (void) snprintf(disk, DISK_SUBPATH_MAX, "t%"PRIX64"d%"PRId64, wwn, lun64); } else if ((addr_method == SCSI_LUN_AM_FLAT) && (lun.sl_lun2_msb == 0) && (lun.sl_lun2_lsb == 0) && (lun.sl_lun3_msb == 0) && (lun.sl_lun3_lsb == 0) && (lun.sl_lun4_msb == 0) && (lun.sl_lun4_lsb == 0)) { sl = (lun.sl_lun1_msb << 8) | lun.sl_lun1_lsb; (void) snprintf(disk, DISK_SUBPATH_MAX, "t%"PRIX64"d%"PRIX16, wwn, sl); } else { (void) snprintf(disk, DISK_SUBPATH_MAX, "t%"PRIX64"d%"PRIX64, wwn, lun64); } } else if (di_prop_lookup_ints(DDI_DEV_T_ANY, node, SCSI_ADDR_PROP_SATA_PHY, &intp) > 0) { /* Use phy format naming, for SATA devices without wwn */ if ((addr_method == SCSI_LUN_AM_PDEV) && (lun.sl_lun2_msb == 0) && (lun.sl_lun2_lsb == 0) && (lun.sl_lun3_msb == 0) && (lun.sl_lun3_lsb == 0) && (lun.sl_lun4_msb == 0) && (lun.sl_lun4_lsb == 0)) { (void) snprintf(disk, DISK_SUBPATH_MAX, "t%dd%"PRId64, *intp, lun64); } else if ((addr_method == SCSI_LUN_AM_FLAT) && (lun.sl_lun2_msb == 0) && (lun.sl_lun2_lsb == 0) && (lun.sl_lun3_msb == 0) && (lun.sl_lun3_lsb == 0) && (lun.sl_lun4_msb == 0) && (lun.sl_lun4_lsb == 0)) { sl = (lun.sl_lun1_msb << 8) | lun.sl_lun1_lsb; (void) snprintf(disk, DISK_SUBPATH_MAX, "t%dd%"PRIX16, *intp, sl); } else { (void) snprintf(disk, DISK_SUBPATH_MAX, "t%dd%"PRIX64, *intp, lun64); } } else { return (DEVFSADM_CONTINUE); } disk_common(minor, node, disk, RM_STALE); return (DEVFSADM_CONTINUE); }