示例#1
0
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);
}
示例#2
0
int
nvme_open(di_minor_t minor)
{
	char *devpath, *path;
	int fd;

	if ((devpath = di_devfs_minor_path(minor)) == NULL)
		err(-1, "nvme_open()");

	if (asprintf(&path, "/devices%s", devpath) < 0) {
		di_devfs_path_free(devpath);
		err(-1, "nvme_open()");
	}

	di_devfs_path_free(devpath);

	fd = open(path, O_RDWR);
	free(path);

	if (fd < 0) {
		if (debug)
			warn("nvme_open(%s)", path);
		return (-1);
	}

	return (fd);
}
示例#3
0
/*
 * 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);
}
示例#4
0
/*
 * 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);
}
示例#5
0
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);
}
示例#6
0
/*
 * This function is called from di_walk_minor() when any PROBE is processed
 */
static int
probe_nexus_node(di_node_t di_node, di_minor_t minor, void *arg)
{
    probe_info_t *pinfo = (probe_info_t *)arg;
    char *nexus_name, *nexus_dev_path;
    nexus_t *nexus;
    int fd;
    char nexus_path[MAXPATHLEN];

    di_prop_t prop;
    char *strings;
    int *ints;
    int numval;
    int pci_node = 0;
    int first_bus = 0, last_bus = PCI_REG_BUS_G(PCI_REG_BUS_M);
    int domain = 0;
    di_node_t rnode =  DI_NODE_NIL;
#ifdef __sparc
    int bus_range_found = 0;
    int device_type_found = 0;
    di_prom_prop_t prom_prop;
#endif


#ifdef DEBUG
    nexus_name = di_devfs_minor_path(minor);
    fprintf(stderr, "-- device name: %s\n", nexus_name);
    di_devfs_path_free(nexus_name);
#endif

    for (prop = di_prop_next(di_node, NULL); prop != NULL;
	 prop = di_prop_next(di_node, prop)) {

	const char *prop_name = di_prop_name(prop);

#ifdef DEBUG
	fprintf(stderr, "   property: %s\n", prop_name);
#endif

	if (strcmp(prop_name, "device_type") == 0) {
	    numval = di_prop_strings(prop, &strings);
	    if (numval == 1) {
		if (strncmp(strings, "pci", 3) != 0)
		    /* not a PCI node, bail */
		    return (DI_WALK_CONTINUE);
		else {
		    pci_node = 1;
#ifdef __sparc
		    device_type_found =  1;
#endif
		}
	    }
	}
	else if (strcmp(prop_name, "class-code") == 0) {
	    /* not a root bus node, bail */
	    return (DI_WALK_CONTINUE);
	}
	else if (strcmp(prop_name, "bus-range") == 0) {
	    numval = di_prop_ints(prop, &ints);
	    if (numval == 2) {
		first_bus = ints[0];
		last_bus = ints[1];
#ifdef __sparc
		bus_range_found = 1;
#endif
	    }
	}
#ifdef __sparc
	domain = nexus_count;
#else
	else if (strcmp(prop_name, "pciseg") == 0) {
	    numval = di_prop_ints(prop, &ints);
	    if (numval == 1) {
		domain = ints[0];
	    }
	}
#endif
    }
示例#7
0
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",
				  &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);
}
/*
 * This function is called from di_walk_minor() when any PROBE is processed
 */
static int
probe_nexus_node(di_node_t di_node, di_minor_t minor, void *arg)
{
    probe_info_t *pinfo = (probe_info_t *)arg;
    char *nexus_name, *nexus_dev_path;
    nexus_t *nexus;
    int fd;
    char nexus_path[MAXPATHLEN];

    di_prop_t prop;
    char *strings;
    int *ints;
    int numval;
    int pci_node = 0;
    int first_bus = 0, last_bus = PCI_REG_BUS_G(PCI_REG_BUS_M);
    int domain = 0;
#ifdef __sparc
    int bus_range_found = 0;
    int device_type_found = 0;
    di_prom_prop_t prom_prop;
#endif


#ifdef DEBUG
    nexus_name = di_devfs_minor_path(minor);
    fprintf(stderr, "-- device name: %s\n", nexus_name);
#endif

    for (prop = di_prop_next(di_node, NULL); prop != NULL;
	 prop = di_prop_next(di_node, prop)) {

	const char *prop_name = di_prop_name(prop);

#ifdef DEBUG
	fprintf(stderr, "   property: %s\n", prop_name);
#endif

	if (strcmp(prop_name, "device_type") == 0) {
	    numval = di_prop_strings(prop, &strings);
	    if (numval == 1) {
		if (strncmp(strings, "pci", 3) != 0)
		    /* not a PCI node, bail */
		    return (DI_WALK_CONTINUE);
		else {
		    pci_node = 1;
#ifdef __sparc
		    device_type_found =  1;
#endif
		}
	    }
	}
	else if (strcmp(prop_name, "class-code") == 0) {
	    /* not a root bus node, bail */
	    return (DI_WALK_CONTINUE);
	}
	else if (strcmp(prop_name, "bus-range") == 0) {
	    numval = di_prop_ints(prop, &ints);
	    if (numval == 2) {
		first_bus = ints[0];
		last_bus = ints[1];
#ifdef __sparc
		bus_range_found = 1;
#endif
	    }
	}
	else if (strcmp(prop_name, "pciseg") == 0) {
	    numval = di_prop_ints(prop, &ints);
	    if (numval == 1) {
		domain = ints[0];
	    }
	}
    }

#ifdef __sparc
    if ((!device_type_found) && di_phdl) {
	numval = di_prom_prop_lookup_strings(di_phdl, di_node,
	    "device_type", &strings);
	if (numval == 1) {
	    if (strncmp(strings, "pci", 3) != 0)
		return (DI_WALK_CONTINUE);
	    else
		pci_node = 1;
	}
    }

    if ((!bus_range_found) && di_phdl) {
	numval = di_prom_prop_lookup_ints(di_phdl, di_node,
	    "bus-range", &ints);
	if (numval == 2) {
	    first_bus = ints[0];
	    last_bus = ints[1];
	}
    }
#endif

    if (pci_node != 1)
	return (DI_WALK_CONTINUE);

    /* we have a PCI root bus node. */
    nexus = calloc(1, sizeof(nexus_t));
    if (nexus == NULL) {
	(void) fprintf(stderr, "Error allocating memory for nexus: %s\n",
		       strerror(errno));
	return (DI_WALK_TERMINATE);
    }
    nexus->first_bus = first_bus;
    nexus->last_bus = last_bus;
    nexus->domain = domain;

#ifdef __sparc
    if ((nexus->devlist = calloc(INITIAL_NUM_DEVICES,
			sizeof (struct pci_device *))) == NULL) {
	(void) fprintf(stderr, "Error allocating memory for nexus devlist: %s\n",
                       strerror(errno));
	free (nexus);
	return (DI_WALK_TERMINATE);
    }
    nexus->num_allocated_elems = INITIAL_NUM_DEVICES;
    nexus->num_devices = 0;
#endif

    nexus_name = di_devfs_minor_path(minor);
    if (nexus_name == NULL) {
	(void) fprintf(stderr, "Error getting nexus path: %s\n",
		       strerror(errno));
	free(nexus);
	return (DI_WALK_CONTINUE);
    }

    snprintf(nexus_path, sizeof(nexus_path), "/devices%s", nexus_name);
    di_devfs_path_free(nexus_name);

#ifdef DEBUG
    fprintf(stderr, "nexus = %s, bus-range = %d - %d\n",
	    nexus_path, first_bus, last_bus);
#endif

    if ((fd = open(nexus_path, O_RDWR | O_CLOEXEC)) >= 0) {
	nexus->fd = fd;
	nexus->path = strdup(nexus_path);
	nexus_dev_path = di_devfs_path(di_node);
	nexus->dev_path = strdup(nexus_dev_path);
	di_devfs_path_free(nexus_dev_path);
	if ((do_probe(nexus, pinfo) != 0) && (errno != ENXIO)) {
	    (void) fprintf(stderr, "Error probing node %s: %s\n",
			   nexus_path, strerror(errno));
	    (void) close(fd);
	    free(nexus->path);
	    free(nexus->dev_path);
	    free(nexus);
	} else {
	    nexus->next = nexus_list;
	    nexus_list = nexus;
	}
    } else {
	(void) fprintf(stderr, "Error opening %s: %s\n",
		       nexus_path, strerror(errno));
	free(nexus);
    }

    return DI_WALK_CONTINUE;
}
示例#10
0
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);
}