/* * 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); }
/* * 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); }
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); }
/* * 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); }
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; }