static int disk_callback_wwn(di_minor_t minor, di_node_t node) { char disk[10]; int lun; int targ; int *intp; if (di_prop_lookup_ints(DDI_DEV_T_ANY, node, SCSI_ADDR_PROP_TARGET, &intp) <= 0) { return (DEVFSADM_CONTINUE); } targ = *intp; if (di_prop_lookup_ints(DDI_DEV_T_ANY, node, SCSI_ADDR_PROP_LUN, &intp) <= 0) { lun = 0; } else { lun = *intp; } (void) sprintf(disk, "t%dd%d", targ, lun); disk_common(minor, node, disk, RM_STALE); return (DEVFSADM_CONTINUE); }
/* * Discover an HBA node with matching path. * The di_node_t argument should be the root of the device tree. * This routine assumes the locks have been taken */ static int find_matching_hba(di_node_t node, void *arg) { int *propData, rval; walkarg_t *wa = (walkarg_t *)arg; char *devpath, fulldevpath[MAXPATHLEN]; /* Skip stub(instance -1) nodes */ if (IS_STUB_NODE(node)) { return (DI_WALK_CONTINUE); } rval = di_prop_lookup_ints(DDI_DEV_T_ANY, node, "sm-hba-supported", &propData); if (rval < 0) { return (DI_WALK_CONTINUE); } else { if ((devpath = di_devfs_path(node)) == NULL) { /* still continue to see if there is matching one. */ return (DI_WALK_CONTINUE); } (void) snprintf(fulldevpath, MAXPATHLEN, "%s%s", DEVICES_DIR, devpath); if ((strstr(fulldevpath, wa->devpath)) != NULL) { *wa->flag = B_TRUE; /* Found a node. No need to walk any more. */ di_devfs_path_free(devpath); return (DI_WALK_TERMINATE); } di_devfs_path_free(devpath); } return (DI_WALK_CONTINUE); }
/* 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); }
/* * PCMCIA dialout serial ports * Creates links of the form "/dev/cua/pcN", where N is the PCMCIA * socket number the device is plugged into. */ static int pcmcia_dialout_create(di_minor_t minor, di_node_t node) { char l_path[MAXPATHLEN]; char *devfspath; int socket, *intp; devfspath = di_devfs_path(node); if (devfspath == NULL) { devfsadm_errprint("%s: di_devfs_path() failed\n", modname); return (DEVFSADM_TERMINATE); } if (di_prop_lookup_ints(DDI_DEV_T_ANY, node, "socket", &intp) <= 0) { devfsadm_errprint("%s: failed socket lookup\n\t%s\n", modname, devfspath); di_devfs_path_free(devfspath); return (DEVFSADM_TERMINATE); } socket = PCMCIA_SOCKETNO(*intp); di_devfs_path_free(devfspath); (void) sprintf(l_path, "cua/pc%d", socket); (void) devfsadm_mklink(l_path, node, minor, 0); return (DEVFSADM_TERMINATE); }
static int find_target_node(di_node_t node, void *arg) { int *regbuf = NULL; int len = 0; uint32_t busno, funcno, devno; i_devnode_t *devnode = (i_devnode_t *)arg; /* * Test the property functions, only for testing */ /* void *prop = DI_PROP_NIL; (void) fprintf(stderr, "start of node 0x%x\n", node->nodeid); while ((prop = di_prop_hw_next(node, prop)) != DI_PROP_NIL) { int i; (void) fprintf(stderr, "name=%s: ", di_prop_name(prop)); len = 0; if (!strcmp(di_prop_name(prop), "reg")) { len = di_prop_ints(prop, ®buf); } for (i = 0; i < len; i++) { fprintf(stderr, "0x%0x.", regbuf[i]); } fprintf(stderr, "\n"); } (void) fprintf(stderr, "end of node 0x%x\n", node->nodeid); */ len = di_prop_lookup_ints(DDI_DEV_T_ANY, node, "reg", ®buf); #ifdef __sparc if ((len <= 0) && di_phdl) len = di_prom_prop_lookup_ints(di_phdl, node, "reg", ®buf); #endif if (len <= 0) { #ifdef DEBUG fprintf(stderr, "error = %x\n", errno); fprintf(stderr, "can not find assigned-address\n"); #endif return (DI_WALK_CONTINUE); } busno = PCI_REG_BUS_G(regbuf[0]); devno = PCI_REG_DEV_G(regbuf[0]); funcno = PCI_REG_FUNC_G(regbuf[0]); if ((busno == devnode->bus) && (devno == devnode->dev) && (funcno == devnode->func)) { devnode->node = node; return (DI_WALK_TERMINATE); } return (DI_WALK_CONTINUE); }
/* * Return Bus/Dev/Func from "reg" devinfo property. */ uint16_t x86pi_bdf(topo_mod_t *mod, di_node_t node) { int *val; if (di_prop_lookup_ints(DDI_DEV_T_ANY, node, "reg", &val) < 0) { topo_mod_dprintf(mod, "couldn't get \"reg\" prop: %s.\n", strerror(errno)); return ((uint16_t)-1); } return (uint16_t)((*val & PCI_REG_BDFR_M) >> PCI_REG_FUNC_SHIFT); }
static int get_reg_dev(di_node_t node) { int *reg = NULL; if (di_prop_lookup_ints(DDI_DEV_T_ANY, node, OBP_REG, ®) < 0) { if (di_prom_prop_lookup_ints(prom_handle, node, OBP_REG, ®) < 0) { return (-1); } return (PCI_REG_DEV_G(reg[0])); } return (PCI_REG_DEV_G(reg[0])); }
/* * Return PHY from "sata-phy" devinfo proporty. */ int x86pi_phy(topo_mod_t *mod, di_node_t node) { int *phy; if (di_prop_lookup_ints(DDI_DEV_T_ANY, node, "sata-phy", &phy) < 0) { topo_mod_dprintf(mod, "couldn't get \"sata-phy\" prop: %s.\n", strerror(errno)); return (-1); } return (*phy); }
/* * Given a devinfo node find its reg property. */ static int get_reg_prop(di_node_t dn, int **pdata) { int dret = 0; dret = di_prop_lookup_ints(DDI_DEV_T_ANY, dn, OBP_REG, pdata); if (dret > 0) return (dret); if (!ph) return (0); dret = di_prom_prop_lookup_ints(ph, dn, OBP_REG, pdata); return (dret < 0? 0 : dret); }
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); }
/* * Get one of the positive int or boolean properties. */ static int get_prop(char *prop_name, di_node_t node) { int num; int *ip; if ((num = di_prop_lookup_ints(DDI_DEV_T_ANY, node, prop_name, &ip)) >= 0) { if (num == 0) { /* boolean */ return (1); } else if (num == 1) { /* single int */ return (*ip); } } return (-1); }
/* * Get the NIU/Neptune ethernet function number from the reg property */ static int niufn_instance_get(topo_mod_t *mod, di_node_t node, topo_instance_t *inst) { di_prom_handle_t phan; int rval, *intp; *inst = (topo_instance_t)0; rval = -1; if ((phan = topo_mod_prominfo(mod)) != DI_PROM_HANDLE_NIL) { rval = di_prom_prop_lookup_ints(phan, node, DI_PROP_REG, &intp); } if (rval < 0) { rval = di_prop_lookup_ints(DDI_DEV_T_ANY, node, DI_PROP_REG, &intp); if (rval < 0) return (-1); } *inst = (topo_instance_t)intp[0]; return (0); }
/* * 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); }
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); }
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; }
/* * The fw_identify() function walks the device * tree trying to find devices which this plugin * can work with. * * The parameter "start" gives us the starting index number * to give the device when we add it to the fw_devices list. * * firstdev is allocated by us and we add space as needed * * When we store the desired information, inquiry-serial-no * goes in thisdev->addresses[1], and client-guid goes in * thisdev->addresses[2]. */ int fw_identify(int start) { int idx = start; int fw_sata_disk = 0; int *exists; di_node_t thisnode; struct devicelist *newdev = NULL; char *devpath = NULL; char *driver = NULL; char *sp_temp; char *sp_temp_cut; /* We need to inquiry information manually by sending probe command */ libscsi_hdl_t *handle; libscsi_target_t *target; libscsi_errno_t serr; /* Just in case we've got an FC-attached device on sparc */ if (strcmp(self->drvname, "ssd") == 0) { driver = self->drvname; } else driver = drivername; thisnode = di_drv_first_node(driver, rootnode); if (thisnode == DI_NODE_NIL) { logmsg(MSG_INFO, "No %s nodes in this system\n", driver); return (FWFLASH_FAILURE); } if ((handle = libscsi_init(LIBSCSI_VERSION, &serr)) == NULL) { logmsg(MSG_ERROR, gettext("%s: failed to initialize " "libscsi\n"), newdev->drvname); return (FWFLASH_FAILURE); } /* we've found one, at least */ for (; thisnode != DI_NODE_NIL; thisnode = di_drv_next_node(thisnode)) { /* Need to free by di_devfs_path_free */ if ((devpath = di_devfs_path(thisnode)) == NULL) { logmsg(MSG_INFO, "unable to get device path for " "current node with errno %d\n", errno); continue; } /* * We check if this is removable device, in which case * we really aren't interested, so exit stage left */ if (di_prop_lookup_ints(DDI_DEV_T_ANY, thisnode, "removable-media", &exists) > -1) { logmsg(MSG_INFO, "%s: not interested in removable media device\n" "%s\n", driver, devpath); FW_SD_FREE_DEVPATH(devpath) continue; } if ((newdev = calloc(1, sizeof (struct devicelist))) == NULL) { logmsg(MSG_ERROR, gettext("%s: identification function unable " "to allocate space for device entry\n"), driver); libscsi_fini(handle); FW_SD_FREE_DEVPATH(devpath) return (FWFLASH_FAILURE); }
static int sunos_add_devices(di_devlink_t link, void *arg) { struct devlink_cbarg *largs = (struct devlink_cbarg *)arg; struct node_args *nargs; di_node_t myself, pnode; uint64_t session_id = 0; uint16_t bdf = 0; struct libusb_device *dev; sunos_dev_priv_t *devpriv; const char *path, *newpath; int n, i; int *addr_prop; uint8_t bus_number = 0; nargs = (struct node_args *)largs->nargs; myself = largs->myself; if (nargs->last_ugenpath) { /* the same node's links */ return (DI_WALK_CONTINUE); } /* * Construct session ID. * session ID = ...parent hub addr|hub addr|dev addr. */ pnode = myself; i = 0; while (pnode != DI_NODE_NIL) { if (di_prop_exists(DDI_DEV_T_ANY, pnode, "root-hub") == 1) { /* walk to root */ uint32_t *regbuf = NULL; uint32_t reg; n = di_prop_lookup_ints(DDI_DEV_T_ANY, pnode, "reg", (int **)®buf); reg = regbuf[0]; bdf = (PCI_REG_BUS_G(reg) << 8) | (PCI_REG_DEV_G(reg) << 3) | PCI_REG_FUNC_G(reg); session_id |= (bdf << i * 8); /* same as 'unit-address' property */ bus_number = (PCI_REG_DEV_G(reg) << 3) | PCI_REG_FUNC_G(reg); usbi_dbg("device bus address=%s:%x", di_bus_addr(pnode), bus_number); break; } /* usb_addr */ n = di_prop_lookup_ints(DDI_DEV_T_ANY, pnode, "assigned-address", &addr_prop); if ((n != 1) || (addr_prop[0] == 0)) { usbi_dbg("cannot get valid usb_addr"); return (DI_WALK_CONTINUE); } session_id |= ((addr_prop[0] & 0xff) << i * 8); if (++i > 7) break; pnode = di_parent_node(pnode); } path = di_devlink_path(link); dev = usbi_get_device_by_session_id(nargs->ctx, session_id); if (dev == NULL) { dev = usbi_alloc_device(nargs->ctx, session_id); if (dev == NULL) { usbi_dbg("can't alloc device"); return (DI_WALK_TERMINATE); } devpriv = (sunos_dev_priv_t *)dev->os_priv; if ((newpath = strrchr(path, '/')) == NULL) { libusb_unref_device(dev); return (DI_WALK_TERMINATE); } devpriv->ugenpath = strndup(path, strlen(path) - strlen(newpath)); dev->bus_number = bus_number; if (sunos_fill_in_dev_info(myself, dev) != LIBUSB_SUCCESS) { libusb_unref_device(dev); return (DI_WALK_TERMINATE); } if (usbi_sanitize_device(dev) < 0) { libusb_unref_device(dev); usbi_dbg("sanatize failed: "); return (DI_WALK_TERMINATE); } } else { usbi_dbg("Dev %s exists", path); } devpriv = (sunos_dev_priv_t *)dev->os_priv; if (nargs->last_ugenpath == NULL) { /* first device */ nargs->last_ugenpath = devpriv->ugenpath; if (discovered_devs_append(*(nargs->discdevs), dev) == NULL) { usbi_dbg("cannot append device"); } /* * we alloc and hence ref this dev. We don't need to ref it * hereafter. Front end or app should take care of their ref. */ libusb_unref_device(dev); } usbi_dbg("Device %s %s id=0x%llx, devcount:%d, bdf=%x", devpriv->ugenpath, path, (uint64_t)session_id, (*nargs->discdevs)->len, bdf); 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 int sunos_fill_in_dev_info(di_node_t node, struct libusb_device *dev) { int proplen; int n, *addr, *port_prop; char *phypath; uint8_t *rdata; struct libusb_device_descriptor *descr; sunos_dev_priv_t *dpriv = (sunos_dev_priv_t *)dev->os_priv; /* Device descriptors */ proplen = di_prop_lookup_bytes(DDI_DEV_T_ANY, node, "usb-dev-descriptor", &rdata); if (proplen <= 0) { return (LIBUSB_ERROR_IO); } descr = (struct libusb_device_descriptor *)rdata; bcopy(descr, &dpriv->dev_descr, LIBUSB_DT_DEVICE_SIZE); dpriv->dev_descr.bcdUSB = libusb_cpu_to_le16(descr->bcdUSB); dpriv->dev_descr.idVendor = libusb_cpu_to_le16(descr->idVendor); dpriv->dev_descr.idProduct = libusb_cpu_to_le16(descr->idProduct); dpriv->dev_descr.bcdDevice = libusb_cpu_to_le16(descr->bcdDevice); /* Raw configuration descriptors */ proplen = di_prop_lookup_bytes(DDI_DEV_T_ANY, node, "usb-raw-cfg-descriptors", &rdata); if (proplen <= 0) { usbi_dbg("can't find raw config descriptors"); return (LIBUSB_ERROR_IO); } dpriv->raw_cfgdescr = calloc(1, proplen); if (dpriv->raw_cfgdescr == NULL) { return (LIBUSB_ERROR_NO_MEM); } else { bcopy(rdata, dpriv->raw_cfgdescr, proplen); dpriv->cfgvalue = ((struct libusb_config_descriptor *) rdata)->bConfigurationValue; } n = di_prop_lookup_ints(DDI_DEV_T_ANY, node, "reg", &port_prop); if ((n != 1) || (*port_prop <= 0)) { return (LIBUSB_ERROR_IO); } dev->port_number = *port_prop; /* device physical path */ phypath = di_devfs_path(node); if (phypath) { dpriv->phypath = strdup(phypath); di_devfs_path_free(phypath); } else { free(dpriv->raw_cfgdescr); return (LIBUSB_ERROR_IO); } /* address */ n = di_prop_lookup_ints(DDI_DEV_T_ANY, node, "assigned-address", &addr); if (n != 1 || *addr == 0) { usbi_dbg("can't get address"); } else { dev->device_address = *addr; } /* speed */ if (di_prop_exists(DDI_DEV_T_ANY, node, "low-speed") == 1) { dev->speed = LIBUSB_SPEED_LOW; } else if (di_prop_exists(DDI_DEV_T_ANY, node, "high-speed") == 1) { dev->speed = LIBUSB_SPEED_HIGH; } else if (di_prop_exists(DDI_DEV_T_ANY, node, "full-speed") == 1) { dev->speed = LIBUSB_SPEED_FULL; } else if (di_prop_exists(DDI_DEV_T_ANY, node, "super-speed") == 1) { dev->speed = LIBUSB_SPEED_SUPER; } usbi_dbg("vid=%x pid=%x, path=%s, bus_nmber=0x%x, port_number=%d, " "speed=%d", dpriv->dev_descr.idVendor, dpriv->dev_descr.idProduct, dpriv->phypath, dev->bus_number, dev->port_number, dev->speed); return (LIBUSB_SUCCESS); }
static int probe_device_node(di_node_t node, void *arg) { int *retbuf = NULL; int len = 0, i; struct pci_device *pci_base; probe_info_t *pinfo = ((probe_args_t *)arg)->pinfo; nexus_t *nexus = ((probe_args_t *)arg)->nexus; property_info_t property_list[] = { { "class-code", 0 }, { "device-id", 0 }, { "vendor-id", 0 }, { "revision-id", 0}, { "subsystem-vendor-id", 0}, { "subsystem-id", 0}, }; #define NUM_PROPERTIES sizeof(property_list)/sizeof(property_info_t) len = di_prop_lookup_ints(DDI_DEV_T_ANY, node, "reg", &retbuf); #ifdef __sparc if ((len <= 0) && di_phdl) len = di_prom_prop_lookup_ints(di_phdl, node, "reg", &retbuf); #endif /* Exclude usb devices */ if (len < 5) { return DI_WALK_CONTINUE; } pci_base = &pinfo->devices[pinfo->num_devices].base; pci_base->domain = nexus->domain; pci_base->bus = PCI_REG_BUS_G(retbuf[0]); pci_base->dev = PCI_REG_DEV_G(retbuf[0]); pci_base->func = PCI_REG_FUNC_G(retbuf[0]); /* Get property values */ for (i = 0; i < NUM_PROPERTIES; i++) { len = di_prop_lookup_ints(DDI_DEV_T_ANY, node, property_list[i].name, &retbuf); #ifdef __sparc if ((len <= 0) && di_phdl) len = di_prom_prop_lookup_ints(di_phdl, node, property_list[i].name, &retbuf); #endif if (len > 0) property_list[i].value = retbuf[0]; else { /* a device must have property "class-code", "device-id", "vendor-id" */ if (i < 3) return DI_WALK_CONTINUE; #ifdef DEBUG fprintf(stderr, "cannot get property \"%s\" for nexus = %s :\n", property_list[i].name, nexus->path); fprintf(stderr, " domain = %x, busno = %x, devno = %x, funcno = %x\n", pci_base->domain, pci_base->bus, pci_base->dev, pci_base->func); #endif } } if ((property_list[1].value == 0) && (property_list[2].value == 0)) return DI_WALK_CONTINUE; pci_base->device_class = property_list[0].value; pci_base->device_id = property_list[1].value; pci_base->vendor_id = property_list[2].value; pci_base->revision = property_list[3].value; pci_base->subvendor_id = property_list[4].value; pci_base->subdevice_id = property_list[5].value; #ifdef DEBUG fprintf(stderr, "nexus = %s, domain = %x, busno = %x, devno = %x, funcno = %x\n", nexus->path, pci_base->domain, pci_base->bus, pci_base->dev, pci_base->func); #endif pinfo->num_devices++; if (pinfo->num_devices == pinfo->num_allocated_elems) { struct pci_device_private *new_devs; size_t new_num_elems = pinfo->num_allocated_elems * 2; new_devs = realloc(pinfo->devices, new_num_elems * sizeof (struct pci_device_private)); if (new_devs == NULL) { (void) fprintf(stderr, "Error allocating memory for PCI devices:" " %s\n discarding additional devices\n", strerror(errno)); ((probe_args_t *)arg)->ret = 1; return (DI_WALK_TERMINATE); } (void) memset(&new_devs[pinfo->num_devices], 0, pinfo->num_allocated_elems * sizeof (struct pci_device_private)); pinfo->num_allocated_elems = new_num_elems; pinfo->devices = new_devs; } return (DI_WALK_CONTINUE); }