Exemplo n.º 1
0
/*
 * Called by di_walk_node() to walk the list of device nodes and
 * force all nodes of type "network" to be loaded.
 *
 * Returns: DI_WALK_CONTINUE
 */
static int
process_node(di_node_t node, void *arg)
{
	di_prom_handle_t ph = (di_prom_handle_t)arg;
	char *pdevtype;
	int ret;

	/*
	 * Only want to process nodes whose device_type is "network".
	 */
	ret = di_prom_prop_lookup_strings(ph, node, "device_type", &pdevtype);
	if ((ret <= 0) || (strcmp(pdevtype, "network") != 0)) {
		return (DI_WALK_CONTINUE);
	}

	/*
	 * If the instance is '-1', then the driver for the device
	 * has not been loaded - so force it to be loaded. Ignore
	 * errors loading the driver.
	 */
	if (di_instance(node) == -1) {
		node = di_init_driver(di_driver_name(node), 0);
		if (node != DI_NODE_NIL) {
			di_fini(node);
		}
	}
	return (DI_WALK_CONTINUE);
}
Exemplo n.º 2
0
/*
 * Check whether node corresponds to a network device.
 */
static boolean_t
is_network_device(di_node_t node)
{
	char		*type;

	return (di_prom_prop_lookup_strings(phdl, node,
	    "device_type", &type) > 0 && strcmp(type, "network") == 0);
}
Exemplo n.º 3
0
static char *
get_prom_str(char *prop_name, di_node_t node, di_prom_handle_t ph)
{
	char *str;

	if (di_prom_prop_lookup_strings(ph, node, prop_name, &str) == 1) {
		return (str);
	}

	return (NULL);
}
Exemplo n.º 4
0
/*
 * String properties in the prom can contain multiple null-terminated
 * strings which are concatenated together.  We must represent them in
 * an MD as a data property.  This function retrieves such a property
 * and adds it to the MD.  If the 'alt_name' PROM property exists then
 * the MD property is created with the value of the PROM 'alt_name'
 * property, otherwise it is created with the value of the PROM 'name'
 * property.
 */
static int
add_prom_string_prop(di_prom_handle_t ph,
    mmd_t *mdp, md_node_t *np, di_node_t di, char *name, char *alt_name)
{
	int		count;
	char		*pp_data = NULL;
	char		*str;
	int		rv = 0;

	if (alt_name != NULL) {
		count = di_prom_prop_lookup_strings(ph, di, alt_name, &pp_data);
	}
	if (pp_data == NULL) {
		count = di_prom_prop_lookup_strings(ph, di, name, &pp_data);
	}

	if (count > 0 && pp_data != NULL) {
		for (str = pp_data; count > 0; str += strlen(str) + 1)
			count--;
		rv = md_add_data_property(mdp,
		    np, name, str - pp_data, (uint8_t *)pp_data);
	}
	return (rv);
}
Exemplo n.º 5
0
static boolean_t
is_root_complex(di_prom_handle_t ph, di_node_t di)
{
	int	len;
	char	*type;

	len = di_prom_prop_lookup_strings(ph, di, "device_type", &type);
	if ((len == 0) || (type == NULL))
		return (B_FALSE);

	if (strcmp(type, PCIEX) != 0)
		return (B_FALSE);

	/*
	 * A root complex node is directly under the root node.  So, if
	 * 'di' is not the root node, and its parent has no parent,
	 * then 'di' represents a root complex node.
	 */
	return ((di_parent_node(di) != DI_NODE_NIL) &&
	    (di_parent_node(di_parent_node(di)) == DI_NODE_NIL));
}
/*
 * 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;
}