/* * 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); }
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); }
/* * 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); }
scfga_ret_t make_dyncomp( di_node_t node, const char *physpath, char **dyncompp, int *l_errnop) { char *devlink = NULL; scfga_ret_t ret; di_minor_t minor; char *path; char pathbuf[MAXPATHLEN]; int match_minor; if (*dyncompp != NULL) { return (SCFGA_LIB_ERR); } /* tag on minor name */ minor = di_minor_next(node, DI_MINOR_NIL); if (minor == DI_MINOR_NIL) { match_minor = 0; path = (char *)physpath; } else { match_minor = 1; (void) snprintf(pathbuf, MAXPATHLEN, "%s:%s", physpath, di_minor_name(minor)); path = pathbuf; } /* Get the corresponding devlink from the physical path */ ret = physpath_to_devlink(path, &devlink, l_errnop, match_minor); if (ret == SCFGA_OK) { assert(devlink != NULL); /* Create dynamic component. */ ret = devlink_to_dyncomp(devlink, dyncompp, l_errnop); S_FREE(devlink); if (ret == SCFGA_OK) { assert(*dyncompp != NULL); return (SCFGA_OK); } /* * Failed to get devlink based dynamic component. * Try driver and instance */ } ret = drv_to_dyncomp(node, physpath, dyncompp, l_errnop); assert(ret != SCFGA_OK || *dyncompp != NULL); return (ret); }
static di_node_t get_parent_bus(di_node_t node, struct search_args *args) { di_node_t pnode; pnode = di_parent_node(node); if (pnode == DI_NODE_NIL) { return (NULL); } if (bus_type(pnode, di_minor_next(pnode, NULL), args->ph) != NULL) { return (pnode); } return (get_parent_bus(pnode, args)); }
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); }
int emulex_update(char *file) { int fd, retval = 0; int devcnt = 0; uint_t state = 0, fflag = 0; static uchar_t bootpath[PATH_MAX]; int fcode_fd = -1; static struct utmpx *utmpp = NULL; di_node_t root; di_node_t node, sib_node, count_node; di_minor_t minor_node; char phys_path[PATH_MAX], *path; int errnum = 0, fcio_errno = 0; static uchar_t prom_ver_data[MAXNAMELEN]; static char ver_file[EMULEX_FCODE_VERSION_LENGTH]; void (*sigint)(); int prop_entries = -1; int *port_data = NULL; if (file) { /* set the fcode download flag */ fflag++; /* check for a valid file */ if ((fcode_fd = open(file, O_RDONLY)) < 0) { (void) fprintf(stderr, MSGSTR(21118, "Error: Could not open %s, failed " "with errno %d\n"), file, errno); return (1); } /* check for single user mode */ while ((utmpp = getutxent()) != NULL) { if (strstr(utmpp->ut_line, "run-level") && (strcmp(utmpp->ut_line, "run-level S") && strcmp(utmpp->ut_line, "run-level 1"))) { if (q_warn(1)) { (void) endutxent(); (void) close(fcode_fd); return (1); } break; } } (void) endutxent(); /* get bootpath */ if (!q_getbootdev((uchar_t *)&bootpath[0]) && getenv("_LUX_D_DEBUG") != NULL) { (void) fprintf(stdout, " Bootpath: %s\n", bootpath); } } /* * Download the Fcode to all the emulex cards found */ /* Create a snapshot of the kernel device tree */ if ((root = di_init("/", DINFOCPYALL)) == DI_NODE_NIL) { (void) fprintf(stderr, MSGSTR(21114, "Error: Could not get /devices path to " "Emulex Devices.\n")); retval++; } /* point to first node which matches emulex driver */ node = di_drv_first_node("emlxs", root); if (node == DI_NODE_NIL) { /* * Could not find any emulex cards */ (void) di_fini(root); (void) fprintf(stderr, MSGSTR(21115, "\n Found Path to %d Emulex Devices.\n"), devcnt); retval++; } else { count_node = node; while (count_node != DI_NODE_NIL) { state = di_state(count_node); if ((state & DI_DRIVER_DETACHED) != DI_DRIVER_DETACHED) { sib_node = di_child_node(count_node); while (sib_node != DI_NODE_NIL) { state = di_state(sib_node); if ((state & DI_DRIVER_DETACHED) != DI_DRIVER_DETACHED) { /* Found an attached node */ prop_entries = di_prop_lookup_ints( DDI_DEV_T_ANY, sib_node, "port", &port_data); if (prop_entries != -1) { devcnt++; break; } } sib_node = di_sibling_node(sib_node); } } count_node = di_drv_next_node(count_node); } (void) fprintf(stdout, MSGSTR(21116, "\n Found Path to %d Emulex Devices.\n"), devcnt); } /* * Traverse device tree to find all emulex cards */ while (node != DI_NODE_NIL) { state = di_state(node); if ((state & DI_DRIVER_DETACHED) == DI_DRIVER_DETACHED) { node = di_drv_next_node(node); continue; } sib_node = di_child_node(node); while (sib_node != DI_NODE_NIL) { state = di_state(sib_node); if ((state & DI_DRIVER_DETACHED) != DI_DRIVER_DETACHED) { /* Found an attached node */ prop_entries = di_prop_lookup_ints( DDI_DEV_T_ANY, sib_node, "port", &port_data); if (prop_entries != -1) { /* Found a node with "port" property */ minor_node = di_minor_next(sib_node, DI_MINOR_NIL); break; } } sib_node = di_sibling_node(sib_node); } if (sib_node == DI_NODE_NIL) { goto try_next; } path = di_devfs_path(sib_node); (void) strcpy(phys_path, "/devices"); (void) strncat(phys_path, path, strlen(path)); di_devfs_path_free(path); if (fflag && (strstr((char *)bootpath, (char *)phys_path) != NULL)) { (void) fprintf(stderr, MSGSTR(21117, "Ignoring %s (bootpath)\n"), phys_path); node = di_drv_next_node(node); continue; } if (minor_node) { (void) strncat(phys_path, ":", 1); (void) strncat(phys_path, di_minor_name(minor_node), strlen(di_minor_name(minor_node))); } (void) fprintf(stdout, MSGSTR(21107, "\n Opening Device: %s\n"), phys_path); /* Check if the device is valid */ if ((fd = open(phys_path, O_RDWR)) < 0) { (void) fprintf(stderr, MSGSTR(21121, "Error: Could not open %s, failed " "with errno %d\n"), phys_path, errno); retval++; node = di_drv_next_node(node); continue; } (void) close(fd); /* * Check FCode version present on the adapter * (at last boot) */ memset(prom_ver_data, 0, sizeof (prom_ver_data)); if (emulex_fcodeversion(node, (uchar_t *)&prom_ver_data[0]) == 0) { errnum = 0; if (strlen((char *)prom_ver_data) == 0) { (void) fprintf(stdout, MSGSTR(21108, " Detected FCode Version:\tNo version available for this FCode\n")); } else { (void) fprintf(stdout, MSGSTR(21109, " Detected FCode Version:\t%s\n"), prom_ver_data); } } else { errnum = 2; /* can't get prom properties */ retval++; } if (fflag) { memset(ver_file, 0, sizeof (ver_file)); if (emulex_fcode_reader(fcode_fd, "fcode-version", ver_file, sizeof (ver_file)) == 0) { (void) fprintf(stdout, MSGSTR(21110, " New FCode Version:\t\t%s\n"), ver_file); } else { di_fini(root); (void) close(fcode_fd); return (1); } /* * Load the New FCode * Give warning if file doesn't appear to be correct */ if (!q_warn(errnum)) { /* Disable user-interrupt Control-C */ sigint = (void (*)(int)) signal(SIGINT, SIG_IGN); /* Load FCode */ (void) fprintf(stdout, MSGSTR(21111, " Loading FCode: %s\n"), file); if (fcode_load_file(fcode_fd, phys_path, &fcio_errno) == FCODE_SUCCESS) { (void) fprintf(stdout, MSGSTR(21112, " Successful FCode download: %s\n"), phys_path); } else { handle_emulex_error(fcio_errno, phys_path); retval++; } /* Restore SIGINT (user interrupt) setting */ (void) signal(SIGINT, sigint); } } try_next: node = di_drv_next_node(node); } di_fini(root); (void) fprintf(stdout, " "); (void) fprintf(stdout, MSGSTR(125, "Complete\n")); if (fcode_fd != -1) (void) close(fcode_fd); return (retval); }
static int get_drv_info(di_node_t node, led_dtls_t *dtls) { int *target_data; uchar_t *port_data = NULL; di_minor_t min_node; int i, r; int t = -1; int *newStatus = malloc(dtls->n_disks * sizeof (int)); if (newStatus == NULL) return (0); for (i = 0; i < dtls->n_disks; i++) { newStatus[i] = MINORS_UNKNOWN; } r = di_prop_lookup_ints(DDI_DEV_T_ANY, node, HW_PROP_TARGET, &target_data); for (i = 0; i < r; i++) { t = target_data[i]; if ((t >= 0) && (t < dtls->n_disks)) { /* set no minors until we know */ newStatus[t] = NO_MINORS; break; /* go with this node */ } } if ((t >= 0) && (t < dtls->n_disks)) { r = di_prop_lookup_bytes( DDI_DEV_T_ANY, node, HW_PROP_PORT, &port_data); /* * The first byte of the array dtls->disk_port[t] contains * the length of the residue. So 255 is the maximum length * which can be handled. Limit the property data to this. */ if (r > 255) { r = 0; } if ((r > 0) && (port_data != NULL)) { if ((dtls->disk_port[t] != NULL) && (*(dtls->disk_port[t]) != r)) { /* * existing data is of different length, * free it and malloc a fresh array. */ free(dtls->disk_port[t]); dtls->disk_port[t] = NULL; } if (dtls->disk_port[t] == NULL) { dtls->disk_port[t] = malloc(r + 1); } if (dtls->disk_port[t] != NULL) { *(dtls->disk_port[t]) = (uchar_t)r; (void) memcpy(dtls->disk_port[t] + 1, port_data, r); } } min_node = di_minor_next(node, DI_MINOR_NIL); if (min_node != DI_MINOR_NIL) { /* * device has minor device node(s) */ newStatus[t] = HAS_MINORS; /* got minor(s) */ } } /* * propagate attachment status and note changes * don't propagate to absent disks, otherwise we may not detect a * status change when they're replugged. */ r = 0; for (i = 0; i < dtls->n_disks; i++) { if ((newStatus[i] != MINORS_UNKNOWN) && dtls->disk_detected[i] && (dtls->disk_ready[i] != newStatus[i])) { dtls->disk_ready[i] = newStatus[i]; r = 1; } } free(newStatus); return (r); }
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); }
/* * 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 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); }
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 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 path_t * new_path(controller_t *cp, disk_t *dp, di_node_t node, di_path_state_t st, char *wwn) { char *devpath; path_t *pp; di_minor_t minor; /* 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) { node = pnode; } } devpath = di_devfs_path(node); /* check if the path is already there */ pp = NULL; if (cp->paths != NULL) { int i; for (i = 0; cp->paths[i]; i++) { if (libdiskmgt_str_eq(devpath, cp->paths[i]->name)) { pp = cp->paths[i]; break; } } } if (pp != NULL) { /* the path exists, add this disk to it */ di_devfs_path_free((void *) devpath); if (!add_disk2path(dp, pp, st, wwn)) { return (NULL); } return (pp); } /* create a new path */ pp = calloc(1, sizeof (path_t)); if (pp == NULL) { di_devfs_path_free((void *) devpath); return (NULL); } pp->name = strdup(devpath); di_devfs_path_free((void *) devpath); if (pp->name == NULL) { cache_free_path(pp); return (NULL); } /* add the disk to the path */ if (!add_disk2path(dp, pp, st, wwn)) { return (NULL); } /* add the path to the controller */ if (add_ptr2array(pp, (void ***)&cp->paths) != 0) { cache_free_path(pp); return (NULL); } /* add the controller to the path */ pp->controller = cp; minor = di_minor_next(node, NULL); if (minor != NULL) { pp->ctype = ctype(node, minor); } else { pp->ctype = DM_CTYPE_UNKNOWN; } return (pp); }
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); }