static int sunos_walk_minor_node_link(di_node_t node, void *args) { di_minor_t minor = DI_MINOR_NIL; char *minor_path; struct devlink_cbarg arg; struct node_args *nargs = (struct node_args *)args; di_devlink_handle_t devlink_hdl = nargs->dlink_hdl; /* walk each minor to find ugen devices */ while ((minor = di_minor_next(node, minor)) != DI_MINOR_NIL) { minor_path = di_devfs_minor_path(minor); arg.nargs = args; arg.myself = node; arg.minor = minor; (void) di_devlink_walk(devlink_hdl, "^usb/[0-9a-f]+[.][0-9a-f]+", minor_path, DI_PRIMARY_LINK, (void *)&arg, sunos_add_devices); di_devfs_path_free(minor_path); } /* switch to a different node */ nargs->last_ugenpath = NULL; return (DI_WALK_CONTINUE); }
int nvme_open(di_minor_t minor) { char *devpath, *path; int fd; if ((devpath = di_devfs_minor_path(minor)) == NULL) err(-1, "nvme_open()"); if (asprintf(&path, "/devices%s", devpath) < 0) { di_devfs_path_free(devpath); err(-1, "nvme_open()"); } di_devfs_path_free(devpath); fd = open(path, O_RDWR); free(path); if (fd < 0) { if (debug) warn("nvme_open(%s)", path); return (-1); } return (fd); }
/* * 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); }
/* * Walk all vldc device nodes to find the one with the * matching minor name */ static char * svc_name_to_vldc_dev_path(char *service) { di_node_t root_node, vldc_node; char *vldc_path; char *minor_name; di_minor_t minor; char *dev_path = NULL; /* Get device node */ root_node = di_init("/", DINFOCPYALL); if (root_node == DI_NODE_NIL) { return (dev_path); } vldc_node = di_drv_first_node("vldc", root_node); while (vldc_node != DI_NODE_NIL) { /* Walk minor nodes */ minor = di_minor_next(vldc_node, DI_NODE_NIL); while (minor != DI_NODE_NIL) { vldc_path = di_devfs_minor_path(minor); minor_name = di_minor_name(minor); if (strcmp(minor_name, service) == 0) { dev_path = malloc(strlen(vldc_path) + strlen(DEVICES_DIR) + 1); (void) strcpy(dev_path, DEVICES_DIR); (void) strcat(dev_path, vldc_path); di_devfs_path_free(vldc_path); break; } di_devfs_path_free(vldc_path); minor = di_minor_next(vldc_node, minor); } if (dev_path != NULL) break; vldc_node = di_drv_next_node(vldc_node); } di_fini(root_node); return (dev_path); }
int sata_check_target_node(di_node_t node, void *arg) { char *minorpath; char *cp; minorpath = di_devfs_minor_path(di_minor_next(node, DI_MINOR_NIL)); if (minorpath != NULL) { if (strstr(minorpath, arg) != NULL) { cp = strrchr(minorpath, (int)*MINOR_SEP); if (cp != NULL) { (void) strcpy(arg, cp); } free(minorpath); return (DI_WALK_TERMINATE); } free(minorpath); } return (DI_WALK_CONTINUE); }
/* * This function is called from di_walk_minor() when any PROBE is processed */ static int probe_nexus_node(di_node_t di_node, di_minor_t minor, void *arg) { probe_info_t *pinfo = (probe_info_t *)arg; char *nexus_name, *nexus_dev_path; nexus_t *nexus; int fd; char nexus_path[MAXPATHLEN]; di_prop_t prop; char *strings; int *ints; int numval; int pci_node = 0; int first_bus = 0, last_bus = PCI_REG_BUS_G(PCI_REG_BUS_M); int domain = 0; di_node_t rnode = DI_NODE_NIL; #ifdef __sparc int bus_range_found = 0; int device_type_found = 0; di_prom_prop_t prom_prop; #endif #ifdef DEBUG nexus_name = di_devfs_minor_path(minor); fprintf(stderr, "-- device name: %s\n", nexus_name); di_devfs_path_free(nexus_name); #endif for (prop = di_prop_next(di_node, NULL); prop != NULL; prop = di_prop_next(di_node, prop)) { const char *prop_name = di_prop_name(prop); #ifdef DEBUG fprintf(stderr, " property: %s\n", prop_name); #endif if (strcmp(prop_name, "device_type") == 0) { numval = di_prop_strings(prop, &strings); if (numval == 1) { if (strncmp(strings, "pci", 3) != 0) /* not a PCI node, bail */ return (DI_WALK_CONTINUE); else { pci_node = 1; #ifdef __sparc device_type_found = 1; #endif } } } else if (strcmp(prop_name, "class-code") == 0) { /* not a root bus node, bail */ return (DI_WALK_CONTINUE); } else if (strcmp(prop_name, "bus-range") == 0) { numval = di_prop_ints(prop, &ints); if (numval == 2) { first_bus = ints[0]; last_bus = ints[1]; #ifdef __sparc bus_range_found = 1; #endif } } #ifdef __sparc domain = nexus_count; #else else if (strcmp(prop_name, "pciseg") == 0) { numval = di_prop_ints(prop, &ints); if (numval == 1) { domain = ints[0]; } } #endif }
static char * find_link(di_node_t cnode) { di_minor_t devminor = DI_MINOR_NIL; di_devlink_handle_t hdl; char *devfspath = NULL; char *minorpath = NULL; char *linkname = NULL; char *cbresult = NULL; devfspath = di_devfs_path(cnode); if (cnode == DI_NODE_NIL) { logmsg(MSG_ERROR, gettext("find_ctrl must be called with non-null " "di_node_t\n")); return (NULL); } logmsg(MSG_INFO, "find_link: devfspath %s\n", devfspath); if (((cbresult = calloc(1, MAXPATHLEN)) == NULL) || ((minorpath = calloc(1, MAXPATHLEN)) == NULL) || ((linkname = calloc(1, MAXPATHLEN)) == NULL)) { logmsg(MSG_ERROR, "unable to allocate space for dev link\n"); return (NULL); } devminor = di_minor_next(cnode, devminor); hdl = di_devlink_init(di_devfs_minor_path(devminor), DI_MAKE_LINK); if (hdl == NULL) { logmsg((readonlyroot ? MSG_INFO : MSG_ERROR), gettext("unable to take devlink snapshot: %s\n"), strerror(errno)); return (NULL); } linkname = "^dsk/"; (void) snprintf(minorpath, MAXPATHLEN, "%s:c", devfspath); errno = 0; if (di_devlink_walk(hdl, linkname, minorpath, DI_PRIMARY_LINK, (void *)cbresult, link_cb) < 0) { logmsg(MSG_ERROR, gettext("Unable to walk devlink snapshot for %s: %s\n"), minorpath, strerror(errno)); return (NULL); } if (di_devlink_fini(&hdl) < 0) { logmsg(MSG_ERROR, gettext("Unable to close devlink snapshot: %s\n"), strerror(errno)); } if (strstr(cbresult, "dsk/") == NULL) return (devfspath); bzero(minorpath, MAXPATHLEN); /* strip off the trailing "s2" */ bcopy(cbresult, minorpath, strlen(cbresult) - 1); /* Now strip off the /dev/dsk/ prefix for output flexibility */ linkname = strrchr(minorpath, '/'); return (++linkname); }
/* * Solaris version */ static int pci_device_solx_devfs_probe( struct pci_device * dev ) { int err = 0; di_node_t rnode = DI_NODE_NIL; i_devnode_t args = { 0, 0, 0, DI_NODE_NIL }; int *regbuf; pci_regspec_t *reg; int i; int len = 0; uint ent = 0; nexus_t *nexus; #ifdef __sparc if ( (nexus = find_nexus_for_dev(dev)) == NULL ) #else if ( (nexus = find_nexus_for_bus(dev->domain, dev->bus)) == NULL ) #endif return ENODEV; /* * starting to find if it is MEM/MEM64/IO * using libdevinfo */ if ((rnode = di_init(nexus->dev_path, DINFOCPYALL)) == DI_NODE_NIL) { err = errno; (void) fprintf(stderr, "di_init failed: %s\n", strerror(errno)); } else { args.bus = dev->bus; args.dev = dev->dev; args.func = dev->func; (void) di_walk_node(rnode, DI_WALK_CLDFIRST, (void *)&args, find_target_node); } if (args.node != DI_NODE_NIL) { #ifdef __sparc di_minor_t minor; #endif #ifdef __sparc if (minor = di_minor_next(args.node, DI_MINOR_NIL)) MAPPING_DEV_PATH(dev) = di_devfs_minor_path (minor); else MAPPING_DEV_PATH(dev) = NULL; #endif /* * It will succeed for sure, because it was * successfully called in find_target_node */ len = di_prop_lookup_ints(DDI_DEV_T_ANY, args.node, "assigned-addresses", ®buf); #ifdef __sparc if ((len <= 0) && di_phdl) { len = di_prom_prop_lookup_ints(di_phdl, args.node, "assigned-addresses", ®buf); } #endif } if (len <= 0) goto cleanup; /* * how to find the size of rom??? * if the device has expansion rom, * it must be listed in the last * cells because solaris find probe * the base address from offset 0x10 * to 0x30h. So only check the last * item. */ reg = (pci_regspec_t *)®buf[len - CELL_NUMS_1275]; if (PCI_REG_REG_G(reg->pci_phys_hi) == PCI_CONF_ROM) { /* * rom can only be 32 bits */ dev->rom_size = reg->pci_size_low; len = len - CELL_NUMS_1275; } else { /* * size default to 64K and base address * default to 0xC0000 */ dev->rom_size = 0x10000; } /* * Solaris has its own BAR index. * Linux give two region slot for 64 bit address. */ for (i = 0; i < len; i = i + CELL_NUMS_1275) { reg = (pci_regspec_t *)®buf[i]; ent = reg->pci_phys_hi & 0xff; /* * G35 broken in BAR0 */ ent = (ent - PCI_CONF_BASE0) >> 2; if (ent >= 6) { fprintf(stderr, "error ent = %d\n", ent); break; } /* * non relocatable resource is excluded * such like 0xa0000, 0x3b0. If it is met, * the loop is broken; */ if (!PCI_REG_REG_G(reg->pci_phys_hi)) break; if (reg->pci_phys_hi & PCI_PREFETCH_B) { dev->regions[ent].is_prefetchable = 1; } /* * We split the shift count 32 into two 16 to * avoid the complaining of the compiler */ dev->regions[ent].base_addr = reg->pci_phys_low + ((reg->pci_phys_mid << 16) << 16); dev->regions[ent].size = reg->pci_size_low + ((reg->pci_size_hi << 16) << 16); switch (reg->pci_phys_hi & PCI_REG_ADDR_M) { case PCI_ADDR_IO: dev->regions[ent].is_IO = 1; break; case PCI_ADDR_MEM32: break; case PCI_ADDR_MEM64: dev->regions[ent].is_64 = 1; /* * Skip one slot for 64 bit address */ break; } } cleanup: if (rnode != DI_NODE_NIL) { di_fini(rnode); } return (err); }
/* * This function is called from di_walk_minor() when any PROBE is processed */ static int probe_nexus_node(di_node_t di_node, di_minor_t minor, void *arg) { probe_info_t *pinfo = (probe_info_t *)arg; char *nexus_name, *nexus_dev_path; nexus_t *nexus; int fd; char nexus_path[MAXPATHLEN]; di_prop_t prop; char *strings; int *ints; int numval; int pci_node = 0; int first_bus = 0, last_bus = PCI_REG_BUS_G(PCI_REG_BUS_M); int domain = 0; #ifdef __sparc int bus_range_found = 0; int device_type_found = 0; di_prom_prop_t prom_prop; #endif #ifdef DEBUG nexus_name = di_devfs_minor_path(minor); fprintf(stderr, "-- device name: %s\n", nexus_name); #endif for (prop = di_prop_next(di_node, NULL); prop != NULL; prop = di_prop_next(di_node, prop)) { const char *prop_name = di_prop_name(prop); #ifdef DEBUG fprintf(stderr, " property: %s\n", prop_name); #endif if (strcmp(prop_name, "device_type") == 0) { numval = di_prop_strings(prop, &strings); if (numval == 1) { if (strncmp(strings, "pci", 3) != 0) /* not a PCI node, bail */ return (DI_WALK_CONTINUE); else { pci_node = 1; #ifdef __sparc device_type_found = 1; #endif } } } else if (strcmp(prop_name, "class-code") == 0) { /* not a root bus node, bail */ return (DI_WALK_CONTINUE); } else if (strcmp(prop_name, "bus-range") == 0) { numval = di_prop_ints(prop, &ints); if (numval == 2) { first_bus = ints[0]; last_bus = ints[1]; #ifdef __sparc bus_range_found = 1; #endif } } else if (strcmp(prop_name, "pciseg") == 0) { numval = di_prop_ints(prop, &ints); if (numval == 1) { domain = ints[0]; } } } #ifdef __sparc if ((!device_type_found) && di_phdl) { numval = di_prom_prop_lookup_strings(di_phdl, di_node, "device_type", &strings); if (numval == 1) { if (strncmp(strings, "pci", 3) != 0) return (DI_WALK_CONTINUE); else pci_node = 1; } } if ((!bus_range_found) && di_phdl) { numval = di_prom_prop_lookup_ints(di_phdl, di_node, "bus-range", &ints); if (numval == 2) { first_bus = ints[0]; last_bus = ints[1]; } } #endif if (pci_node != 1) return (DI_WALK_CONTINUE); /* we have a PCI root bus node. */ nexus = calloc(1, sizeof(nexus_t)); if (nexus == NULL) { (void) fprintf(stderr, "Error allocating memory for nexus: %s\n", strerror(errno)); return (DI_WALK_TERMINATE); } nexus->first_bus = first_bus; nexus->last_bus = last_bus; nexus->domain = domain; #ifdef __sparc if ((nexus->devlist = calloc(INITIAL_NUM_DEVICES, sizeof (struct pci_device *))) == NULL) { (void) fprintf(stderr, "Error allocating memory for nexus devlist: %s\n", strerror(errno)); free (nexus); return (DI_WALK_TERMINATE); } nexus->num_allocated_elems = INITIAL_NUM_DEVICES; nexus->num_devices = 0; #endif nexus_name = di_devfs_minor_path(minor); if (nexus_name == NULL) { (void) fprintf(stderr, "Error getting nexus path: %s\n", strerror(errno)); free(nexus); return (DI_WALK_CONTINUE); } snprintf(nexus_path, sizeof(nexus_path), "/devices%s", nexus_name); di_devfs_path_free(nexus_name); #ifdef DEBUG fprintf(stderr, "nexus = %s, bus-range = %d - %d\n", nexus_path, first_bus, last_bus); #endif if ((fd = open(nexus_path, O_RDWR | O_CLOEXEC)) >= 0) { nexus->fd = fd; nexus->path = strdup(nexus_path); nexus_dev_path = di_devfs_path(di_node); nexus->dev_path = strdup(nexus_dev_path); di_devfs_path_free(nexus_dev_path); if ((do_probe(nexus, pinfo) != 0) && (errno != ENXIO)) { (void) fprintf(stderr, "Error probing node %s: %s\n", nexus_path, strerror(errno)); (void) close(fd); free(nexus->path); free(nexus->dev_path); free(nexus); } else { nexus->next = nexus_list; nexus_list = nexus; } } else { (void) fprintf(stderr, "Error opening %s: %s\n", nexus_path, strerror(errno)); free(nexus); } return DI_WALK_CONTINUE; }
static int ahciem_devinfo(di_node_t node, void *arg) { char *driver, *mpath, *fullpath; const char *sup; int inst, fd; uint_t i; ahciem_t *ahci = arg; di_minor_t m; ahci_ioc_em_get_t get; if ((driver = di_driver_name(node)) == NULL) return (DI_WALK_CONTINUE); if (strcmp(driver, "ahci") != 0) return (DI_WALK_CONTINUE); inst = di_instance(node); m = DI_MINOR_NIL; while ((m = di_minor_next(node, m)) != DI_MINOR_NIL) { char *mname = di_minor_name(m); if (mname != NULL && strcmp("devctl", mname) == 0) break; } if (m == DI_MINOR_NIL) { warnx("encountered ahci%d without devctl node", inst); return (DI_WALK_PRUNECHILD); } if ((mpath = di_devfs_minor_path(m)) == NULL) { warnx("failed to get path for ahci%d devctl minor", inst); return (DI_WALK_PRUNECHILD); } if (asprintf(&fullpath, "/devices/%s", mpath) == -1) { warn("failed to construct /devices path from %s", mpath); return (DI_WALK_PRUNECHILD); } if ((fd = open(fullpath, O_RDWR)) < 0) { warn("failed to open ahci%d devctl path %s", inst, fullpath); goto out; } bzero(&get, sizeof (get)); if (ioctl(fd, AHCI_EM_IOC_GET, &get) != 0) { warn("failed to get AHCI enclosure information for ahci%d", inst); ahci->ahci_err = 1; goto out; } if ((get.aiemg_flags & AHCI_EM_FLAG_CONTROL_ACTIVITY) != 0) { sup = ahciem_led_to_string(AHCI_EM_LED_IDENT_ENABLE | AHCI_EM_LED_FAULT_ENABLE | AHCI_EM_LED_ACTIVITY_DISABLE); } else { sup = ahciem_led_to_string(AHCI_EM_LED_IDENT_ENABLE | AHCI_EM_LED_FAULT_ENABLE); } for (i = 0; i < AHCI_EM_IOC_MAX_PORTS; i++) { char port[64]; const char *state; if (((1 << i) & get.aiemg_nports) == 0) continue; (void) snprintf(port, sizeof (port), "ahci%d/%u", inst, i); if (!ahciem_match(ahci, port)) continue; if (ahci->ahci_set) { ahciem_set(ahci, port, fd, i); continue; } state = ahciem_led_to_string(get.aiemg_status[i]); (void) printf("%-20s %-12s %s,default\n", port, state, sup); } out: free(fullpath); return (DI_WALK_PRUNECHILD); }