dev_info_t * i_ddi_create_branch(dev_info_t *pdip, int nid) { char *buf; dev_info_t *dip = NULL; if (pdip == NULL || nid == OBP_NONODE || nid == OBP_BADNODE) return (NULL); buf = kmem_alloc(OBP_MAXPROPNAME, KM_SLEEP); if (getlongprop_buf(nid, OBP_NAME, buf, OBP_MAXPROPNAME) > 0) { if (check_status(nid, buf, pdip) == DDI_SUCCESS) dip = ddi_add_child(pdip, buf, nid, -1); } kmem_free(buf, OBP_MAXPROPNAME); if (dip == NULL) return (NULL); /* * Don't create any siblings of the branch root, just * children. */ (void) get_neighbors(dip, DDI_WALK_PRUNESIB); di_dfs(ddi_get_child(dip), get_neighbors, 0); return (dip); }
/*ARGSUSED*/ int check_status(int id, char *buf, dev_info_t *parent) { char status_buf[64]; char devtype_buf[OBP_MAXPROPNAME]; char board_buf[32]; char path[OBP_MAXPATHLEN]; int boardnum; int retval = DDI_FAILURE; extern int status_okay(int, char *, int); /* * is the status okay? */ if (status_okay(id, status_buf, sizeof (status_buf))) return (DDI_SUCCESS); /* * a status property indicating bad memory will be associated * with a node which has a "device_type" property with a value of * "memory-controller". in this situation, return DDI_SUCCESS */ if (getlongprop_buf(id, OBP_DEVICETYPE, devtype_buf, sizeof (devtype_buf)) > 0) { if (strcmp(devtype_buf, "memory-controller") == 0) retval = DDI_SUCCESS; } /* * get the full OBP pathname of this node */ if (prom_phandle_to_path((phandle_t)id, path, sizeof (path)) < 0) cmn_err(CE_WARN, "prom_phandle_to_path(%d) failed", id); /* * get the board number, if one exists */ if ((boardnum = get_boardnum(id, parent)) >= 0) (void) sprintf(board_buf, " on board %d", boardnum); else board_buf[0] = '\0'; /* * print the status property information */ cmn_err(CE_WARN, "status '%s' for '%s'%s", status_buf, path, board_buf); return (retval); }
/*ARGSUSED1*/ static int get_neighbors(dev_info_t *di, int flag) { register int nid, snid, cnid; dev_info_t *parent; char buf[OBP_MAXPROPNAME]; if (di == NULL) return (DDI_WALK_CONTINUE); nid = ddi_get_nodeid(di); snid = cnid = 0; switch (flag) { case DDI_WALK_PRUNESIB: cnid = (int)prom_childnode((pnode_t)nid); break; case DDI_WALK_PRUNECHILD: snid = (int)prom_nextnode((pnode_t)nid); break; case 0: snid = (int)prom_nextnode((pnode_t)nid); cnid = (int)prom_childnode((pnode_t)nid); break; default: return (DDI_WALK_TERMINATE); } if (snid && (snid != -1) && ((parent = ddi_get_parent(di)) != NULL)) { /* * add the first sibling that passes check_status() */ for (; snid && (snid != -1); snid = (int)prom_nextnode((pnode_t)snid)) { if (getlongprop_buf(snid, OBP_NAME, buf, sizeof (buf)) > 0) { if (check_status(snid, buf, parent) == DDI_SUCCESS) { (void) ddi_add_child(parent, buf, snid, -1); break; } } } } if (cnid && (cnid != -1)) { /* * add the first child that passes check_status() */ if (getlongprop_buf(cnid, OBP_NAME, buf, sizeof (buf)) > 0) { if (check_status(cnid, buf, di) == DDI_SUCCESS) { (void) ddi_add_child(di, buf, cnid, -1); } else { for (cnid = (int)prom_nextnode((pnode_t)cnid); cnid && (cnid != -1); cnid = (int)prom_nextnode((pnode_t)cnid)) { if (getlongprop_buf(cnid, OBP_NAME, buf, sizeof (buf)) > 0) { if (check_status(cnid, buf, di) == DDI_SUCCESS) { (void) ddi_add_child( di, buf, cnid, -1); break; } } } } } } return (DDI_WALK_CONTINUE); }