/* Make logical name for HBA based on driver and instance */ static int drv_to_hba_logid(di_node_t node, di_minor_t minor, void *arg) { int inst; char *drv, *mn, *log; pathm_t *ptp; const size_t loglen = MAXPATHLEN; ptp = (pathm_t *)arg; errno = 0; mn = di_minor_name(minor); drv = di_driver_name(node); inst = di_instance(node); log = calloc(1, loglen); if (mn != NULL && drv != NULL && inst != -1 && log != NULL) { /* Count does not include terminating NULL */ if (snprintf(log, loglen, "%s%d:%s", drv, inst, mn) < loglen) { ptp->ret = SCFGA_OK; ptp->log = log; return (DI_WALK_TERMINATE); } } S_FREE(log); return (DI_WALK_CONTINUE); }
/*ARGSUSED*/ static scfga_ret_t drv_to_dyncomp(di_node_t node, const char *phys, char **dyncompp, int *l_errnop) { char *drv; int inst; const int dynlen = MAXPATHLEN; scfga_ret_t ret; *l_errnop = 0; if ((*dyncompp = calloc(1, dynlen)) == NULL) { *l_errnop = errno; return (SCFGA_LIB_ERR); } drv = di_driver_name(node); inst = di_instance(node); if (drv != NULL && inst != -1) { if (snprintf(*dyncompp, dynlen, "%s%d", drv, inst) < dynlen) { return (SCFGA_OK); } else { ret = SCFGA_LIB_ERR; } } else { ret = SCFGA_APID_NOEXIST; } S_FREE(*dyncompp); return (ret); }
/* * 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); }
/* * Called by di_walk_minor() to walk the list * of ddi_network minor device nodes and add * the interface to the niclist. * * Returns: DI_WALK_CONTINUE or DI_WALK_TERMINATE. */ static int nic_process_minor_nodes(di_node_t node, di_minor_t minor, void *arg) { wlkreq_t *request = (wlkreq_t *)arg; niclist_t **niclist = request->wr_niclist; char *name; char *nodetype; int instance; int ret; /* * Look for network devices only. Unfortunately, our walk will * include nodes with nodetypes of NULL. */ nodetype = di_minor_nodetype(minor); if ((nodetype == NULL) || (strcmp(nodetype, DDI_NT_NET) != 0)) { return (DI_WALK_CONTINUE); } /* * In the case of DDM_MINOR minor nodes, the minor * name is the name of the driver. However, if the name * doesn't include the instance, then it's not one * one we're interested in. In the case of other * minor nodes, we should be able to get the driver name * and its instance from the node properties. If they are * not valid, then we're not interested in them. */ if (di_minor_type(minor) == DDM_MINOR) { name = di_minor_name(minor); if ((name == NULL) || (strlen(name) == 0) || (!isdigit(name[strlen(name) - 1]))) { return (DI_WALK_CONTINUE); } instance = -1; } else { name = di_driver_name(node); instance = di_instance(node); if ((name == NULL) || (strlen(name) == 0) || (instance == -1)) { return (DI_WALK_CONTINUE); } } /* * Add this one to the niclist. */ ret = nic_add(niclist, name, instance, request->wr_syserr); if (ret != ICFG_SUCCESS) { (*request->wr_err) = ret; return (DI_WALK_TERMINATE); } (*request->wr_numif)++; return (DI_WALK_CONTINUE); }
/* * Starcat sbbc node. We only really care about generating a /dev * link for the lone sbbc on the SC (as opposed to the potentially * numerous sbbcs on the domain), so only operate on instance 0. */ static int starcat_sbbc_node(di_minor_t minor, di_node_t node) { char *mn; if (di_instance(node) == 0) { mn = di_minor_name(minor); (void) devfsadm_mklink(mn, node, minor, 0); } return (DEVFSADM_CONTINUE); }
/*ARGSUSED*/ static int INSTprop_set(tnode_t *tn, did_t *pd, const char *dpnm, const char *tpgrp, const char *tpnm) { int inst, err; if ((inst = di_instance(did_dinode(pd))) == -1) return (0); if (topo_prop_set_uint32(tn, tpgrp, tpnm, TOPO_PROP_IMMUTABLE, inst, &err) < 0) return (topo_mod_seterrno(did_mod(pd), err)); return (0); }
static int getnameinst(char *path, int *instance, char *name, int namelen) { di_node_t node; char *driver_name; if ((node = di_init(&path[8], DINFOSUBTREE)) == DI_NODE_NIL) return (-1); if ((driver_name = di_driver_name(node)) == NULL) { di_fini(node); return (-1); } *instance = di_instance(node); (void) strncpy(name, driver_name, namelen); di_fini(node); return (0); }
static int vboxSolarisAddPhysHostIface(di_node_t Node, di_minor_t Minor, void *pvHostNetworkInterfaceList) { NOREF(Minor); /* * Skip aggregations. */ if (!strcmp(di_driver_name(Node), "aggr")) return DI_WALK_CONTINUE; /* * Skip softmacs. */ if (!strcmp(di_driver_name(Node), "softmac")) return DI_WALK_CONTINUE; vboxSolarisAddHostIface(di_driver_name(Node), di_instance(Node), pvHostNetworkInterfaceList); return DI_WALK_CONTINUE; }
void devinfo_set_default_properties (HalDevice *d, HalDevice *parent, di_node_t node, char *devfs_path) { char *driver_name, *s; const char *s1; char udi[HAL_PATH_MAX]; if (parent != NULL) { hal_device_property_set_string (d, "info.parent", hal_device_get_udi (parent)); } else { hal_device_property_set_string (d, "info.parent", "/org/freedesktop/Hal/devices/local"); } hal_util_compute_udi (hald_get_gdl (), udi, sizeof (udi), "/org/freedesktop/Hal/devices%s_%d", devfs_path, di_instance (node)); hal_device_set_udi (d, udi); hal_device_property_set_string (d, "info.udi", udi); if (di_prop_lookup_strings (DDI_DEV_T_ANY, node, "model", &s) > 0) { hal_device_property_set_string (d, "info.product", s); } else { hal_device_property_set_string (d, "info.product", di_node_name (node)); } hal_device_property_set_string (d, "solaris.devfs_path", devfs_path); if ((driver_name = di_driver_name (node)) != NULL) { hal_device_property_set_string (d, "info.solaris.driver", driver_name); } /* inherit parent's claim attributes */ if (hal_device_property_get_bool (parent, "info.claimed")) { s1 = hal_device_property_get_string (parent, "info.claimed.service"); if (s1 != NULL) { hal_device_property_set_bool (d, "info.claimed", TRUE); hal_device_property_set_string (d, "info.claimed.service", s1); } } }
static int walk_callback(di_node_t node, void *arg) { struct walk_arg *warg = (struct walk_arg *)arg; char *driver_name; char *path; driver_name = di_driver_name(node); if (driver_name != NULL) { if (strcmp(driver_name, warg->name) == 0 && di_instance(node) == warg->instance) { path = di_devfs_path(node); if (path != NULL) { warg->found = 1; (void) strncpy(warg->path, path, warg->pathlen); } return (DI_WALK_TERMINATE); } } return (DI_WALK_CONTINUE); }
/* * probe for port nodes */ static int probe_tree(di_node_t node, void *arg) { char *nodetype = NULL; char *devfs_path = NULL; char *bus_addr = NULL; char *drv_name = NULL; plist_t *listptr = NULL; port_info_t *port_info = NULL; frutree_port_type_t port_type = UNKNOWN_PORT; di_minor_t minor = DI_MINOR_NIL; if (arg == NULL) { return (DI_WALK_TERMINATE); } listptr = (plist_t *)arg; while ((minor = di_minor_next(node, minor)) != DI_MINOR_NIL) { nodetype = di_minor_nodetype(minor); if (nodetype == NULL) { continue; } if (strcmp(nodetype, DDI_NT_NET) == 0) { port_type = NETWORK_PORT; } else if (strcmp(nodetype, DDI_NT_PARALLEL) == 0) { port_type = PARALLEL_PORT; } else if ((strcmp(nodetype, DDI_NT_SERIAL) == 0) || (strcmp(nodetype, DDI_NT_SERIAL_MB) == 0) || (strcmp(nodetype, DDI_NT_SERIAL_DO) == 0) || (strcmp(nodetype, DDI_NT_SERIAL_MB_DO) == 0)) { port_type = SERIAL_PORT; } else { continue; } /* found port node */ devfs_path = di_devfs_path(node); if (devfs_path == NULL) { continue; } bus_addr = di_bus_addr(node); drv_name = di_driver_name(node); if ((bus_addr == NULL) || (drv_name == NULL)) { di_devfs_path_free(devfs_path); continue; } port_info = malloc(sizeof (port_info_t)); if (port_info == NULL) { di_devfs_path_free(devfs_path); return (PICL_NOSPACE); } (void) strncpy(port_info->devfs_path, devfs_path, sizeof (port_info->devfs_path)); (void) strncpy(port_info->bus_addr, bus_addr, sizeof (port_info->bus_addr)); (void) strncpy(port_info->drv_name, drv_name, sizeof (port_info->drv_name)); port_info->type = port_type; port_info->instance = di_instance(node); port_info->geo_addr = -1; port_info->next = NULL; switch (port_type) { case NETWORK_PORT: listptr->n_network++; break; case SERIAL_PORT: listptr->n_serial++; break; case PARALLEL_PORT: listptr->n_parallel++; break; } /* add to the list */ if (listptr->first == NULL) { /* 1st node */ listptr->first = port_info; listptr->last = NULL; } else if (listptr->last != NULL) { /* last node */ listptr->last->next = port_info; listptr->last = port_info; } else { /* 2nd node */ listptr->first->next = port_info; listptr->last = port_info; } di_devfs_path_free(devfs_path); return (DI_WALK_CONTINUE); } return (DI_WALK_CONTINUE); }
/*ARGSUSED*/ static int devfs_entry(di_node_t node, di_minor_t minor, void *arg) { char *devfspath; char resource[MAXPATHLEN]; char dev[MAXNAMELEN]; datalink_id_t linkid; char *drv; char *cp; net_cache_t *probe; cp = di_minor_nodetype(minor); if ((cp == NULL) || (strcmp(cp, DDI_NT_NET))) { /* doesn't look like a network device */ return (DI_WALK_CONTINUE); } drv = di_driver_name(node); if (drv == NULL) { /* what else can we do? */ return (DI_WALK_CONTINUE); } devfspath = di_devfs_path(node); if (!devfspath) { /* no devfs path?!? */ rcm_log_message(RCM_DEBUG, _("NET: missing devfs path\n")); return (DI_WALK_CONTINUE); } if (strncmp("/pseudo", devfspath, strlen("/pseudo")) == 0) { /* ignore pseudo devices, probably not really NICs */ rcm_log_message(RCM_DEBUG, _("NET: ignoring pseudo device %s\n"), devfspath); di_devfs_path_free(devfspath); return (DI_WALK_CONTINUE); } (void) snprintf(resource, sizeof (resource), "/devices%s", devfspath); di_devfs_path_free(devfspath); (void) snprintf(dev, sizeof (dev), "%s%d", drv, di_instance(node)); if (dladm_dev2linkid(dld_handle, dev, &linkid) != DLADM_STATUS_OK) { rcm_log_message(RCM_DEBUG, _("NET: failed to find the linkid for %s\n"), dev); return (DI_WALK_CONTINUE); } probe = cache_lookup(resource); if (probe != NULL) { rcm_log_message(RCM_DEBUG, _("NET: %s already registered (linkid %u)\n"), resource, linkid); probe->linkid = linkid; probe->flags &= ~(CACHE_STALE); } else { rcm_log_message(RCM_DEBUG, _("NET: %s is new resource (linkid %u)\n"), resource, linkid); probe = calloc(1, sizeof (net_cache_t)); if (!probe) { rcm_log_message(RCM_ERROR, _("NET: malloc failure")); return (DI_WALK_CONTINUE); } probe->resource = strdup(resource); probe->linkid = linkid; if (!probe->resource) { free_node(probe); return (DI_WALK_CONTINUE); } probe->flags |= CACHE_NEW; cache_insert(probe); } return (DI_WALK_CONTINUE); }
/* Converts a driver and instance number based logid into a physical path */ static int do_drv_dyn_to_devpath(di_node_t node, void *arg) { int inst, rv, match_minor; devpath_t *dptp; char *physpath, *drv; char *drvinst, *devpath; const size_t drvlen = MAXPATHLEN; size_t devlen; dptp = (devpath_t *)arg; assert(dptp->hba_phys != NULL && dptp->dyncomp != NULL); assert(dptp->path == NULL); /* * Skip stub nodes */ if (IS_STUB_NODE(node)) { return (DI_WALK_CONTINUE); } errno = 0; drv = di_driver_name(node); inst = di_instance(node); physpath = di_devfs_path(node); if (drv == NULL || inst == -1 || physpath == NULL) { rv = DI_WALK_CONTINUE; goto out; } devlen = strlen(DEVICES_DIR) + strlen(physpath) + 1; devpath = calloc(1, devlen); drvinst = calloc(1, drvlen); if (devpath == NULL || drvinst == NULL) { dptp->l_errno = errno; dptp->ret = SCFGA_LIB_ERR; rv = DI_WALK_TERMINATE; goto out; } (void) snprintf(drvinst, drvlen, "%s%d", drv, inst); /* Create the physical path */ (void) snprintf(devpath, devlen, "%s%s", DEVICES_DIR, physpath); /* Skip node if it is the HBA */ match_minor = 0; if (!dev_cmp(dptp->hba_phys, devpath, match_minor)) { rv = DI_WALK_CONTINUE; goto out; } /* Compare the base and dynamic components */ if (!hba_dev_cmp(dptp->hba_phys, devpath) && strcmp(dptp->dyncomp, drvinst) == 0) { dptp->ret = SCFGA_OK; dptp->path = devpath; rv = DI_WALK_TERMINATE; } else { rv = DI_WALK_CONTINUE; } /*FALLTHRU*/ out: S_FREE(drvinst); if (physpath != NULL) di_devfs_path_free(physpath); if (dptp->ret != SCFGA_OK) S_FREE(devpath); return (rv); }
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); }
/* * Retrieves the statistics for a specified port.phy on an adapter */ HBA_STATUS Sun_sasGetPhyStatistics(HBA_HANDLE handle, HBA_UINT32 port, HBA_UINT32 phy, SMHBA_PHYSTATISTICS *pStatistics) { const char ROUTINE[] = "Sun_sasGetPhyStatistics"; HBA_STATUS status = HBA_STATUS_OK; struct sun_sas_hba *hba_ptr; struct sun_sas_port *hba_port_ptr; struct phy_info *phy_ptr; PSMHBA_SASPHYSTATISTICS psas; kstat_ctl_t *kc; kstat_t *ksp; kstat_named_t *kname; char *charptr, path[MAXPATHLEN + 1]; char *driver_name, kstat_name[256]; di_node_t node; int instance = 0; int i; uint64_t iport_wwn; /* Validate the arguments */ if (pStatistics == NULL) { log(LOG_DEBUG, ROUTINE, "NULL Phy Statistics buffer of phyIndex: %08lx", phy); return (HBA_STATUS_ERROR_ARG); } psas = pStatistics->SASPhyStatistics; if (psas == NULL) { log(LOG_DEBUG, ROUTINE, "NULL SAS Phy Statistics buffer of phyIndex: %08lx", phy); return (HBA_STATUS_ERROR_ARG); } lock(&all_hbas_lock); if ((hba_ptr = Retrieve_Sun_sasHandle(handle)) == NULL) { log(LOG_DEBUG, ROUTINE, "Invalid HBA handler %08lx of phyIndex: %08lx", handle, phy); unlock(&all_hbas_lock); return (HBA_STATUS_ERROR_INVALID_HANDLE); } /* Check for stale data */ status = verifyAdapter(hba_ptr); if (status != HBA_STATUS_OK) { log(LOG_DEBUG, ROUTINE, "Verify Adapter failed for phyIndex: %08lx", phy); unlock(&all_hbas_lock); return (status); } for (hba_port_ptr = hba_ptr->first_port; hba_port_ptr != NULL; hba_port_ptr = hba_port_ptr->next) { if (hba_port_ptr->index == port) { break; } } if (hba_port_ptr == NULL) { log(LOG_DEBUG, ROUTINE, "Invalid port index of phyIndex: %08lx", phy); unlock(&all_hbas_lock); return (HBA_STATUS_ERROR_ILLEGAL_INDEX); } if (phy >= hba_port_ptr->port_attributes.PortSpecificAttribute. SASPort->NumberofPhys) { log(LOG_DEBUG, ROUTINE, "Invalid phy index %08lx", phy); unlock(&all_hbas_lock); return (HBA_STATUS_ERROR_ILLEGAL_INDEX); } /* We need to find out the phy identifier. */ for (phy_ptr = hba_port_ptr->first_phy; phy_ptr != NULL; phy_ptr = phy_ptr->next) { if (phy == phy_ptr->index) break; } if (phy_ptr == NULL) { log(LOG_DEBUG, ROUTINE, "Invalid phy index %08lx", phy); unlock(&all_hbas_lock); return (HBA_STATUS_ERROR_ILLEGAL_INDEX); } /* * for statistics that are not supported, its bits should all be * set to -1 */ (void) memset(pStatistics->SASPhyStatistics, 0xff, sizeof (SMHBA_SASPHYSTATISTICS)); /* First, we need the deivce path to locate the devinfo node. */ (void *) strlcpy(path, hba_port_ptr->device_path, sizeof (path)); charptr = strrchr(path, ':'); if (charptr) { *charptr = '\0'; } errno = 0; (void *) memset(kstat_name, 0, sizeof (kstat_name)); node = di_init(path, DINFOCPYONE); if (node == DI_NODE_NIL) { di_fini(node); log(LOG_DEBUG, ROUTINE, "Unable to take devinfo snapshot on HBA \"%s\" " "for phyIndex: %08lx due to %s", path, phy, strerror(errno)); unlock(&all_hbas_lock); return (HBA_STATUS_ERROR); } /* * Then we could fetch the instance number and driver name of this * device. */ instance = di_instance(node); if (instance == -1) { di_fini(node); log(LOG_DEBUG, ROUTINE, "An instance number has not been assigned to the " "device \"%s\" when get phyIndex: %08lx", path, phy); unlock(&all_hbas_lock); return (HBA_STATUS_ERROR); } driver_name = di_driver_name(node); if (driver_name == NULL) { di_fini(node); log(LOG_DEBUG, ROUTINE, "No driver bound to this device \"%s\" " "when get phyIndex: %08lx", path, phy); unlock(&all_hbas_lock); return (HBA_STATUS_ERROR); } di_fini(node); iport_wwn = wwnConversion(hba_port_ptr->port_attributes.\ PortSpecificAttribute.SASPort->LocalSASAddress.wwn); /* * Construct the kstat name here. */ (void) snprintf(kstat_name, sizeof (kstat_name), "%s.%016llx.%u.%u", driver_name, iport_wwn, instance, phy_ptr->phy.PhyIdentifier); /* retrieve all the statistics from kstat. */ kc = kstat_open(); if (kc == NULL) { log(LOG_DEBUG, ROUTINE, "kstat_open failed due to \"%s\" of phyIndex: %08lx", strerror(errno), phy); unlock(&all_hbas_lock); return (HBA_STATUS_ERROR); } ksp = kstat_lookup(kc, NULL, -1, kstat_name); if (ksp == NULL) { log(LOG_DEBUG, ROUTINE, "No matching kstat name found for \"%s\" " "of phyIndex: %08lx", kstat_name, phy); unlock(&all_hbas_lock); (void) kstat_close(kc); return (HBA_STATUS_ERROR); } /* Found the phy we're looking for. */ if (kstat_read(kc, ksp, NULL) == -1) { log(LOG_DEBUG, ROUTINE, "error reading kstat data due to \"%s\" " "of phyIndex: %08lx", strerror(errno), phy); unlock(&all_hbas_lock); (void) kstat_close(kc); return (HBA_STATUS_ERROR); } kname = (kstat_named_t *)ksp->ks_data; for (i = 0; i < ksp->ks_ndata; i++, kname++) { if (strcmp(kname->name, "SecondsSinceLastReset") == 0) { psas->SecondsSinceLastReset = kname->value.ull; continue; } if (strcmp(kname->name, "TxFrames") == 0) { psas->TxFrames = kname->value.ull; continue; } if (strcmp(kname->name, "RxFrames") == 0) { psas->RxFrames = kname->value.ull; continue; } if (strcmp(kname->name, "TxWords") == 0) { psas->TxWords = kname->value.ull; continue; } if (strcmp(kname->name, "RxWords") == 0) { psas->RxWords = kname->value.ull; continue; } if (strcmp(kname->name, "InvalidDwordCount") == 0) { psas->InvalidDwordCount = kname->value.ull; continue; } if (strcmp(kname->name, "RunningDisparityErrorCount") == 0) { psas->RunningDisparityErrorCount = kname->value.ull; continue; } if (strcmp(kname->name, "LossofDwordSyncCount") == 0) { psas->LossofDwordSyncCount = kname->value.ull; continue; } if (strcmp(kname->name, "PhyResetProblemCount") == 0) { psas->PhyResetProblemCount = kname->value.ull; } } unlock(&all_hbas_lock); (void) kstat_close(kc); return (HBA_STATUS_OK); }
static int getOidList(di_node_t root_node, MP_OID_LIST *pOidList) { int numNodes = 0; int instNum = 0; int majorNum = 0; di_node_t vh_node = DI_NODE_NIL; di_node_t ph_node = DI_NODE_NIL; MP_UINT64 osn = 0; int haveList = (NULL != pOidList); log(LOG_INFO, "getOidList()", " - enter"); vh_node = di_vhci_first_node(root_node); while (DI_NODE_NIL != vh_node) { if ((di_driver_name(vh_node) != NULL) && (strncmp(di_driver_name(vh_node), "scsi_vhci", 9) == 0)) { ph_node = di_phci_first_node(vh_node); while (DI_NODE_NIL != ph_node) { if (haveList) { instNum = di_instance(ph_node); majorNum = di_driver_major(ph_node); log(LOG_INFO, "getOidList()", "instNum = %d", instNum); log(LOG_INFO, "getOidList()", "majorNum = %d", majorNum); if (numNodes < pOidList->oidCount) { osn = 0; osn = MP_STORE_INST_TO_ID(instNum, osn); osn = MP_STORE_MAJOR_TO_ID(majorNum, osn); pOidList->oids[numNodes] .objectSequenceNumber = osn; pOidList->oids[numNodes]. objectType = MP_OBJECT_TYPE_INITIATOR_PORT; pOidList->oids[numNodes]. ownerId = g_pluginOwnerID; } } ++numNodes; ph_node = di_phci_next_node(ph_node); } } vh_node = di_vhci_next_node(vh_node); } log(LOG_INFO, "getOidList()", " - numNodes: %d", numNodes); log(LOG_INFO, "getOidList()", " - exit"); return (numNodes); }
/* * Determine whether the interface was configured manually. */ static boolean_t manual_if_init(void) { boolean_t ret = B_FALSE; char *ncs; char *devpath; di_node_t node; int instance; char *drvname; char ifname[IFNAMSIZ + 1]; /* * If net-config-strategy isn't "manual", don't go any further. */ if ((ncs = get_prop("chosen", BI_NET_CONFIG_STRATEGY, NULL)) == NULL || strcmp(ncs, "manual") != 0) { return (B_FALSE); } /* * First check the 'bootpath' property of /chosen to see whether * it specifies the path of a network device; if so, use this. */ if ((devpath = get_bootpath()) == NULL || (node = path2node(devpath)) == DI_NODE_NIL || !is_network_device(node)) { /* * Must have been booted from CD-ROM or disk; attempt to * use the path defined by the 'net' property of /aliases. */ free(devpath); if ((devpath = get_netalias()) == NULL || (node = path2node(devpath)) == DI_NODE_NIL || !is_network_device(node)) { goto cleanup; } } /* * Get the driver name and instance number of this node. * We may have to load the driver. */ if ((drvname = di_driver_name(node)) == NULL) { goto cleanup; } if ((instance = di_instance(node)) == -1) { di_node_t tmp; /* * Attempt to load the driver, create a new snapshot of the * (possibly changed) device tree and re-compute our node. */ if ((tmp = di_init_driver(drvname, 0)) != DI_NODE_NIL) { di_fini(tmp); if (!snapshot_devtree() || (node = path2node(devpath)) == DI_NODE_NIL) { goto cleanup; } } instance = di_instance(node); } /* * Construct the interface name. */ if (instance == -1) { (void) snprintf(ifname, sizeof (ifname), "%s", di_driver_name(node)); } else { (void) snprintf(ifname, sizeof (ifname), "%s%d", di_driver_name(node), instance); } ret = netif_init(ifname, "manual"); cleanup: free(devpath); return (ret); }
/* ARGSUSED */ static int nic_enum(topo_mod_t *mod, tnode_t *pnode, const char *name, topo_instance_t min, topo_instance_t max, void *modarg, void *data) { di_node_t din = data; datalink_id_t linkid; dladm_handle_t handle; dld_ioc_gettran_t dgt; uint_t ntrans, i; char dname[MAXNAMELEN]; if (strcmp(name, NIC) != 0) { topo_mod_dprintf(mod, "nic_enum: asked to enumerate unknown " "component: %s\n", name); return (-1); } if (din == NULL) { topo_mod_dprintf(mod, "nic_enum: missing data argument\n"); return (-1); } if ((handle = topo_mod_getspecific(mod)) == NULL) { topo_mod_dprintf(mod, "nic_enum: failed to get nic module " "specific data\n"); return (-1); } if (snprintf(dname, sizeof (dname), "%s%d", di_driver_name(din), di_instance(din)) >= sizeof (dname)) { topo_mod_dprintf(mod, "nic_enum: device name overflowed " "internal buffer\n"); return (-1); } if (dladm_dev2linkid(handle, dname, &linkid) != DLADM_STATUS_OK) return (-1); bzero(&dgt, sizeof (dgt)); dgt.dgt_linkid = linkid; dgt.dgt_tran_id = DLDIOC_GETTRAN_GETNTRAN; if (ioctl(dladm_dld_fd(handle), DLDIOC_GETTRAN, &dgt) != 0) { if (errno == ENOTSUP) return (0); return (-1); } ntrans = dgt.dgt_tran_id; if (ntrans == 0) return (0); if (port_range_create(mod, pnode, 0, ntrans - 1) != 0) return (-1); for (i = 0; i < ntrans; i++) { if (nic_create_transceiver(mod, pnode, handle, linkid, i) != 0) return (-1); } return (0); }
/* * This function is identical to the one in the picldevtree plugin. * Unfortunately we can't just reuse that code. */ static void add_devinfo_props(picl_nodehdl_t nodeh, di_node_t di_node) { int instance; char *di_val; di_prop_t di_prop; int di_ptype; ptree_propinfo_t propinfo; instance = di_instance(di_node); (void) ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION, PICL_PTYPE_INT, PICL_READ, sizeof (instance), PICL_PROP_INSTANCE, NULL, NULL); (void) ptree_create_and_add_prop(nodeh, &propinfo, &instance, NULL); di_val = di_bus_addr(di_node); if (di_val) { (void) ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION, PICL_PTYPE_CHARSTRING, PICL_READ, strlen(di_val) + 1, PICL_PROP_BUS_ADDR, NULL, NULL); (void) ptree_create_and_add_prop(nodeh, &propinfo, di_val, NULL); } di_val = di_binding_name(di_node); if (di_val) { (void) ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION, PICL_PTYPE_CHARSTRING, PICL_READ, strlen(di_val) + 1, PICL_PROP_BINDING_NAME, NULL, NULL); (void) ptree_create_and_add_prop(nodeh, &propinfo, di_val, NULL); } di_val = di_driver_name(di_node); if (di_val) { (void) ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION, PICL_PTYPE_CHARSTRING, PICL_READ, strlen(di_val) + 1, PICL_PROP_DRIVER_NAME, NULL, NULL); (void) ptree_create_and_add_prop(nodeh, &propinfo, di_val, NULL); } di_val = di_devfs_path(di_node); if (di_val) { (void) ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION, PICL_PTYPE_CHARSTRING, PICL_READ, strlen(di_val) + 1, PICL_PROP_DEVFS_PATH, NULL, NULL); (void) ptree_create_and_add_prop(nodeh, &propinfo, di_val, NULL); di_devfs_path_free(di_val); } for (di_prop = di_prop_next(di_node, DI_PROP_NIL); di_prop != DI_PROP_NIL; di_prop = di_prop_next(di_node, di_prop)) { di_val = di_prop_name(di_prop); di_ptype = di_prop_type(di_prop); switch (di_ptype) { case DI_PROP_TYPE_BOOLEAN: (void) ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION, PICL_PTYPE_VOID, PICL_READ, (size_t)0, di_val, NULL, NULL); (void) ptree_create_and_add_prop(nodeh, &propinfo, NULL, NULL); break; case DI_PROP_TYPE_INT: { int *idata; int len; len = di_prop_ints(di_prop, &idata); if (len < 0) /* Recieved error, so ignore prop */ break; if (len == 1) (void) ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION, PICL_PTYPE_INT, PICL_READ, len * sizeof (int), di_val, NULL, NULL); else (void) ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION, PICL_PTYPE_BYTEARRAY, PICL_READ, len * sizeof (int), di_val, NULL, NULL); (void) ptree_create_and_add_prop(nodeh, &propinfo, idata, NULL); } break; case DI_PROP_TYPE_STRING: { char *sdata; int len; len = di_prop_strings(di_prop, &sdata); if (len < 0) break; if (len == 1) { (void) ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION, PICL_PTYPE_CHARSTRING, PICL_READ, strlen(sdata) + 1, di_val, NULL, NULL); (void) ptree_create_and_add_prop(nodeh, &propinfo, sdata, NULL); } else { (void) add_string_list_prop(nodeh, di_val, sdata, len); } } break; case DI_PROP_TYPE_BYTE: { int len; unsigned char *bdata; len = di_prop_bytes(di_prop, &bdata); if (len < 0) break; (void) ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION, PICL_PTYPE_BYTEARRAY, PICL_READ, len, di_val, NULL, NULL); (void) ptree_create_and_add_prop(nodeh, &propinfo, bdata, NULL); } break; case DI_PROP_TYPE_UNKNOWN: break; case DI_PROP_TYPE_UNDEF_IT: break; default: break; } } }
static int add_devs(di_node_t node, di_minor_t minor, void *arg) { struct search_args *args; int result = DI_WALK_CONTINUE; args = (struct search_args *)arg; if (dm_debug > 1) { /* This is all just debugging code */ char *devpath; char dev_name[MAXPATHLEN]; devpath = di_devfs_path(node); (void) snprintf(dev_name, sizeof (dev_name), "%s:%s", devpath, di_minor_name(minor)); di_devfs_path_free((void *) devpath); (void) fprintf(stderr, "INFO: dev: %s, node: %s%d, minor: 0x%x, type: %s\n", dev_name, di_node_name(node), di_instance(node), di_minor_spectype(minor), (di_minor_nodetype(minor) != NULL ? di_minor_nodetype(minor) : "NULL")); } if (bus_type(node, minor, args->ph) != NULL) { if (add_bus(args, node, minor, NULL) == NULL) { args->dev_walk_status = ENOMEM; result = DI_WALK_TERMINATE; } } else if (is_ctrl(node, minor)) { if (add_controller(args, node, minor) == NULL) { args->dev_walk_status = ENOMEM; result = DI_WALK_TERMINATE; } } else if (di_minor_spectype(minor) == S_IFCHR && (is_drive(minor) || is_zvol(node, minor))) { char *devidstr; char kernel_name[MAXPATHLEN]; disk_t *diskp; (void) snprintf(kernel_name, sizeof (kernel_name), "%s%d", di_node_name(node), di_instance(node)); devidstr = get_str_prop(DEVICE_ID_PROP, node); args->node = node; args->minor = minor; /* * Check if we already got this disk and * this is another slice. */ if (!have_disk(args, devidstr, kernel_name, &diskp)) { args->dev_walk_status = 0; /* * This is a newly found disk, create the * disk structure. */ diskp = create_disk(devidstr, kernel_name, args); if (diskp == NULL) { args->dev_walk_status = ENOMEM; } if (diskp->drv_type != DM_DT_FLOPPY) { /* add the controller relationship */ if (args->dev_walk_status == 0) { if (add_disk2controller(diskp, args) != 0) { args->dev_walk_status = ENOMEM; } } } } if (is_zvol(node, minor)) { char zvdsk[MAXNAMELEN]; char *str; alias_t *ap; if (di_prop_lookup_strings(di_minor_devt(minor), node, "name", &str) == -1) return (DI_WALK_CONTINUE); (void) snprintf(zvdsk, MAXNAMELEN, "/dev/zvol/rdsk/%s", str); if ((ap = find_alias(diskp, kernel_name)) == NULL) { if (new_alias(diskp, kernel_name, zvdsk, args) != 0) { args->dev_walk_status = ENOMEM; } } else { /* * It is possible that we have already added * this devpath. * Do not add it again. new_devpath will * return a 0 if found, and not add the path. */ if (new_devpath(ap, zvdsk) != 0) { args->dev_walk_status = ENOMEM; } } } /* Add the devpaths for the drive. */ if (args->dev_walk_status == 0) { char *devpath; char slice_path[MAXPATHLEN]; char *pattern; /* * We will come through here once for each of * the raw slice device names. */ devpath = di_devfs_path(node); (void) snprintf(slice_path, sizeof (slice_path), "%s:%s", devpath, di_minor_name(minor)); di_devfs_path_free((void *) devpath); if (libdiskmgt_str_eq(di_minor_nodetype(minor), DDI_NT_FD)) { pattern = DEVLINK_FLOPPY_REGEX; } else { pattern = DEVLINK_REGEX; } /* Walk the /dev tree to get the devlinks. */ (void) di_devlink_walk(args->handle, pattern, slice_path, DI_PRIMARY_LINK, arg, add_devpath); } if (args->dev_walk_status != 0) { result = DI_WALK_TERMINATE; } } return (result); }
static int add_devpath(di_devlink_t devlink, void *arg) { struct search_args *args; char *devidstr; disk_t *diskp; char kernel_name[MAXPATHLEN]; args = (struct search_args *)arg; /* * Get the diskp value from calling have_disk. Can either be found * by kernel name or devid. */ diskp = NULL; devidstr = get_str_prop(DEVICE_ID_PROP, args->node); (void) snprintf(kernel_name, sizeof (kernel_name), "%s%d", di_node_name(args->node), di_instance(args->node)); (void) have_disk(args, devidstr, kernel_name, &diskp); /* * The devlink_path is usually of the form /dev/rdsk/c0t0d0s0. * For diskettes it is /dev/rdiskette*. * On Intel we would also get each fdisk partition as well * (e.g. /dev/rdsk/c0t0d0p0). */ if (diskp != NULL) { alias_t *ap; char *devlink_path; if (diskp->drv_type != DM_DT_FLOPPY) { /* * Add other controllers for multipath disks. * This will have no effect if the controller * relationship is already set up. */ if (add_disk2controller(diskp, args) != 0) { args->dev_walk_status = ENOMEM; } } (void) snprintf(kernel_name, sizeof (kernel_name), "%s%d", di_node_name(args->node), di_instance(args->node)); devlink_path = (char *)di_devlink_path(devlink); if (dm_debug > 1) { (void) fprintf(stderr, "INFO: devpath %s\n", devlink_path); } if ((ap = find_alias(diskp, kernel_name)) == NULL) { if (new_alias(diskp, kernel_name, devlink_path, args) != 0) { args->dev_walk_status = ENOMEM; } } else { /* * It is possible that we have already added this * devpath. Do not add it again. new_devpath will * return a 0 if found, and not add the path. */ if (new_devpath(ap, devlink_path) != 0) { args->dev_walk_status = ENOMEM; } } } return (DI_WALK_CONTINUE); }
static controller_t * add_controller(struct search_args *args, di_node_t node, di_minor_t minor) { char *devpath; controller_t *cp; char kstat_name[MAXPATHLEN]; char *c_type = DM_CTYPE_UNKNOWN; devpath = di_devfs_path(node); if ((cp = find_controller(args, devpath)) != NULL) { di_devfs_path_free((void *) devpath); return (cp); } /* Special handling for fp attachment node. */ if (strcmp(di_node_name(node), "fp") == 0) { di_node_t pnode; pnode = di_parent_node(node); if (pnode != DI_NODE_NIL) { di_devfs_path_free((void *) devpath); devpath = di_devfs_path(pnode); if ((cp = find_controller(args, devpath)) != NULL) { di_devfs_path_free((void *) devpath); return (cp); } /* not in the list, create it */ node = pnode; c_type = DM_CTYPE_FIBRE; } } if (dm_debug) { (void) fprintf(stderr, "INFO: add_controller %s\n", devpath); } cp = (controller_t *)calloc(1, sizeof (controller_t)); if (cp == NULL) { return (NULL); } cp->name = strdup(devpath); di_devfs_path_free((void *) devpath); if (cp->name == NULL) { cache_free_controller(cp); return (NULL); } if (strcmp(c_type, DM_CTYPE_UNKNOWN) == 0) { c_type = ctype(node, minor); } cp->ctype = c_type; (void) snprintf(kstat_name, sizeof (kstat_name), "%s%d", di_node_name(node), di_instance(node)); if ((cp->kstat_name = strdup(kstat_name)) == NULL) { cache_free_controller(cp); return (NULL); } if (libdiskmgt_str_eq(cp->ctype, "scsi")) { cp->scsi_options = get_prop(SCSI_OPTIONS_PROP, node); } if (libdiskmgt_str_eq(di_node_name(node), "scsi_vhci")) { cp->multiplex = 1; } else { cp->multiplex = 0; } cp->freq = get_prom_int("clock-frequency", node, args->ph); cp->disks = (disk_t **)calloc(1, sizeof (disk_t *)); if (cp->disks == NULL) { cache_free_controller(cp); return (NULL); } cp->disks[0] = NULL; cp->next = args->controller_listp; args->controller_listp = cp; cp->bus = add_bus(args, di_parent_node(node), di_minor_next(di_parent_node(node), NULL), cp); return (cp); }
static bus_t * add_bus(struct search_args *args, di_node_t node, di_minor_t minor, controller_t *cp) { char *btype; char *devpath; bus_t *bp; char kstat_name[MAXPATHLEN]; di_node_t pnode; if (node == DI_NODE_NIL) { return (NULL); } if ((btype = bus_type(node, minor, args->ph)) == NULL) { return (add_bus(args, di_parent_node(node), di_minor_next(di_parent_node(node), NULL), cp)); } devpath = di_devfs_path(node); if ((bp = find_bus(args, devpath)) != NULL) { di_devfs_path_free((void *) devpath); if (cp != NULL) { if (add_ptr2array(cp, (void ***)&bp->controllers) != 0) { args->dev_walk_status = ENOMEM; return (NULL); } } return (bp); } /* Special handling for root node. */ if (strcmp(devpath, "/") == 0) { di_devfs_path_free((void *) devpath); return (NULL); } if (dm_debug) { (void) fprintf(stderr, "INFO: add_bus %s\n", devpath); } bp = (bus_t *)calloc(1, sizeof (bus_t)); if (bp == NULL) { return (NULL); } bp->name = strdup(devpath); di_devfs_path_free((void *) devpath); if (bp->name == NULL) { args->dev_walk_status = ENOMEM; cache_free_bus(bp); return (NULL); } bp->btype = strdup(btype); if (bp->btype == NULL) { args->dev_walk_status = ENOMEM; cache_free_bus(bp); return (NULL); } (void) snprintf(kstat_name, sizeof (kstat_name), "%s%d", di_node_name(node), di_instance(node)); if ((bp->kstat_name = strdup(kstat_name)) == NULL) { args->dev_walk_status = ENOMEM; cache_free_bus(bp); return (NULL); } /* if parent node is a bus, get its name */ if ((pnode = get_parent_bus(node, args)) != NULL) { devpath = di_devfs_path(pnode); bp->pname = strdup(devpath); di_devfs_path_free((void *) devpath); if (bp->pname == NULL) { args->dev_walk_status = ENOMEM; cache_free_bus(bp); return (NULL); } } else { bp->pname = NULL; } bp->freq = get_prom_int("clock-frequency", node, args->ph); bp->controllers = (controller_t **)calloc(1, sizeof (controller_t *)); if (bp->controllers == NULL) { args->dev_walk_status = ENOMEM; cache_free_bus(bp); return (NULL); } bp->controllers[0] = NULL; if (cp != NULL) { if (add_ptr2array(cp, (void ***)&bp->controllers) != 0) { args->dev_walk_status = ENOMEM; return (NULL); } } bp->next = args->bus_listp; args->bus_listp = bp; return (bp); }
char *getDeviceFileName(MP_UINT64 objectSequenceNumber) { char *deviceFileName = NULL; di_node_t root_node = DI_NODE_NIL; di_node_t cur_node = DI_NODE_NIL; int instNum; int majorNum; MP_UINT64 osn; char *pathName = NULL; char *minorName = "c,raw"; char *devLink = NULL; char fullName[512]; walk_devlink_t warg; di_devlink_handle_t dlHandle = NULL; int diStatus = 0; log(LOG_INFO, "getDeviceFileName()", " - enter"); log(LOG_INFO, "getDeviceFileName()", " - objectSequenceNumber: %llx", objectSequenceNumber); root_node = di_init("/", DINFOCACHE); if (DI_NODE_NIL == root_node) { log(LOG_INFO, "MP_GetMultipathLusPlugin()", " - $ERROR, di_init() failed"); return (NULL); } cur_node = di_drv_first_node("scsi_vhci", root_node); if (DI_NODE_NIL == cur_node) { log(LOG_INFO, "getDeviceFileName()", " - $ERROR, di_drv_first_node() failed"); di_fini(root_node); return (NULL); } cur_node = di_child_node(cur_node); while (DI_NODE_NIL != cur_node) { instNum = di_instance(cur_node); majorNum = di_driver_major(cur_node); osn = 0; osn = MP_STORE_INST_TO_ID(instNum, osn); osn = MP_STORE_MAJOR_TO_ID(majorNum, osn); if (osn == objectSequenceNumber) { log(LOG_INFO, "getDeviceFileName()", " - found node."); break; } cur_node = di_sibling_node(cur_node); } if (DI_NODE_NIL != cur_node) { dlHandle = di_devlink_init(NULL, 0); if (NULL == dlHandle) { log(LOG_INFO, "getDeviceFileName()", " - $ERROR, di_devlink_init() failed."); di_fini(root_node); return (NULL); } pathName = di_devfs_path(cur_node); (void) snprintf(fullName, 511, "%s:%s", pathName, minorName); log(LOG_INFO, "getDeviceFileName()", " - fullName: {%s]", fullName); (void) memset(&warg, 0, sizeof (walk_devlink_t)); devLink = NULL; warg.linkpp = &devLink; diStatus = di_devlink_walk(dlHandle, NULL, fullName, DI_PRIMARY_LINK, (void *)&warg, get_devlink); if (diStatus != 0) { log(LOG_INFO, "getDeviceFileName()", "diStatus: %d", diStatus); if (diStatus < 0) { diStatus = errno; } log(LOG_INFO, "getDeviceFileName()", "diStatus: %d", diStatus); log(LOG_INFO, "getDeviceFileName()", "strerror(diStatus): %s", strerror(diStatus)); } if (NULL != devLink) { deviceFileName = (char *)calloc(1, strlen(devLink) + 1); (void) strncpy(deviceFileName, devLink, strlen(devLink)); } else { log(LOG_INFO, "getDeviceFileName()", " - $ERROR, devLink is NULL."); deviceFileName = (char *)calloc(1, 256); (void) strncpy(deviceFileName, pathName, 255); } di_devfs_path_free(pathName); (void) di_devlink_fini(&dlHandle); } di_fini(root_node); free(devLink); log(LOG_INFO, "getDeviceFileName()", " - exit"); return (deviceFileName); }
/* * initializes the port driver and instance fields based on libdevinfo */ picl_errno_t get_port_info(frutree_portnode_t *portp) { picl_errno_t rc; di_node_t rnode, curr, peer; char devfs_path[PICL_PROPNAMELEN_MAX]; char bus_addr[PICL_PROPNAMELEN_MAX]; char *di_busaddr = NULL, *di_drv = NULL; int di_int_busaddr, int_busaddr; if ((rc = ptree_get_propval_by_name(portp->portnodeh, PICL_PROP_DEVFS_PATH, devfs_path, sizeof (devfs_path))) != PICL_SUCCESS) { return (rc); } if (ptree_get_propval_by_name(portp->portnodeh, PICL_PROP_BUS_ADDR, bus_addr, sizeof (bus_addr)) != PICL_SUCCESS) { return (rc); } rnode = di_init(devfs_path, DINFOCPYALL); if (rnode == DI_NODE_NIL) { return (PICL_FAILURE); } peer = di_child_node(rnode); while (peer != DI_NODE_NIL) { curr = peer; peer = di_sibling_node(curr); di_busaddr = di_bus_addr(curr); if (di_busaddr == NULL) { continue; } /* compare the bus_addr */ if (strstr(bus_addr, ",") != NULL) { /* bus addr is of type 1,0 */ if (strcmp(bus_addr, di_busaddr) != 0) { continue; } } else { /* bus addr is of type 0x */ errno = 0; int_busaddr = strtol(bus_addr, (char **)NULL, 16); if (errno != 0) { continue; } errno = 0; di_int_busaddr = strtol(di_busaddr, (char **)NULL, 16); if (errno != 0) { continue; } if (di_int_busaddr != int_busaddr) { continue; } } di_drv = di_driver_name(curr); if (di_drv == NULL) { di_fini(rnode); return (PICL_FAILURE); } /* initialize the driver name and instance number */ (void) strncpy(portp->driver, di_drv, sizeof (portp->driver)); portp->instance = di_instance(curr); di_fini(rnode); return (PICL_SUCCESS); } di_fini(rnode); return (PICL_NODENOTFOUND); }