Пример #1
0
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);
}
Пример #3
0
/* 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);
}
Пример #4
0
/*
 * 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, &regbuf);
	}
	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", &regbuf);

#ifdef __sparc
    if ((len <= 0) && di_phdl)
	len = di_prom_prop_lookup_ints(di_phdl, node, "reg", &regbuf);
#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);
}
Пример #6
0
/*
 * 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);
}
Пример #7
0
static int
get_reg_dev(di_node_t node)
{
	int *reg = NULL;
	if (di_prop_lookup_ints(DDI_DEV_T_ANY, node, OBP_REG, &reg) < 0) {
		if (di_prom_prop_lookup_ints(prom_handle, node, OBP_REG,
			&reg) < 0) {
			return (-1);
		}
		return (PCI_REG_DEV_G(reg[0]));
	}
	return (PCI_REG_DEV_G(reg[0]));
}
Пример #8
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);
}
Пример #9
0
/*
 * 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);
}
Пример #10
0
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);
}
Пример #11
0
/*
 * 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);
}
Пример #12
0
/*
 * 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",
				  &regbuf);

#ifdef __sparc
	if ((len <= 0) && di_phdl) {
	    len = di_prom_prop_lookup_ints(di_phdl, args.node,
				"assigned-addresses", &regbuf);
	}
#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 *)&regbuf[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 *)&regbuf[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);
}
Пример #14
0
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);
}
Пример #15
0
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;
}
Пример #17
0
/*
 * 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);
		}
Пример #18
0
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 **)&regbuf);
			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);
}
Пример #19
0
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);

}
Пример #20
0
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);
}
Пример #21
0
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);
}
Пример #22
0
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);
}