static void pcmem_create_pcram_node(dev_info_t *dip) { dev_info_t *child = NULL; PCMEM_DEBUG((CE_CONT, "pcmem_create_pcram_node dip=%p\n", (void *)dip)); if (ndi_devi_alloc(dip, "pcram", (pnode_t)DEVI_SID_NODEID, &child) != NDI_SUCCESS) { cmn_err(CE_WARN, "pcmem: unable to create node [%s]\n", "pcram"); return; } if (ndi_devi_online(child, 0) == NDI_FAILURE) { cmn_err(CE_WARN, "pcmem: ndi_devi_online failure\n"); (void) ndi_devi_free(child); return; } }
/* * fco_new_device ( name-cstr unit-addr-cstr parent.phandle phandle -- ) */ static int fco_new_device(dev_info_t *ap, fco_handle_t rp, fc_ci_t *cp) { fc_phandle_t ph, ch; dev_info_t *pdev, *cdev; char *s; int createmode = 0; char *unit_address = NULL; char nodename[OBP_MAXPROPNAME]; if (fc_cell2int(cp->nargs) != 4) return (fc_syntax_error(cp, "nargs must be 4")); /* * Make sure these are handles we gave out ... and we have * a corresponding parent devinfo node. */ ph = fc_cell2phandle(fc_arg(cp, 1)); pdev = fc_phandle_to_dip(fc_handle_to_phandle_head(rp), ph); if (pdev == NULL) return (fc_priv_error(cp, "unknown parent phandle")); ch = fc_cell2phandle(fc_arg(cp, 0)); cdev = fc_phandle_to_dip(fc_handle_to_phandle_head(rp), ch); switch (rp->cdip_state) { case FC_CDIP_NOSTATE: /* * The first child must be a child of the attachment point. */ if (pdev != ap) return (fc_priv_error(cp, "first child must be a " "child of the attachment point")); /* * If this bus has a config child, the first child must * be the configuration child. Otherwise, the child must * be a new (unknown) node. */ if (cdev != NULL) { if (rp->child != NULL) { if (cdev != rp->child) return (fc_priv_error(cp, "first " "child must be the " "configuration child")); } else { return (fc_priv_error(cp, "known child -- " "unknown child expected")); } } break; case FC_CDIP_DONE: /* * If we've already created the first child, this * child must be unknown and the parent must be a known * child of the attachment point. */ if (cdev) return (fc_priv_error(cp, "known child -- " "unknown child expected")); if (fc_find_node(pdev, fc_handle_to_dtree(rp)) == NULL) return (fc_priv_error(cp, "parent is an unknown " "child of the attachment point")); break; default: /* * If we're in some other state, we shouldn't be here. */ return (fc_priv_error(cp, "bad node-creation state")); /* NOTREACHED */ } /* * Get the nodename and the unit address. */ s = fc_cell2ptr(fc_arg(cp, 3)); bzero(nodename, OBP_MAXPROPNAME); if (copyinstr(s, nodename, OBP_MAXPROPNAME - 1, NULL)) return (fc_priv_error(cp, "EFAULT copying in nodename")); s = fc_cell2ptr(fc_arg(cp, 2)); unit_address = kmem_zalloc(OBP_MAXPATHLEN, KM_SLEEP); if (copyinstr(s, unit_address, OBP_MAXPATHLEN - 1, NULL)) { kmem_free(unit_address, OBP_MAXPATHLEN); return (fc_priv_error(cp, "EFAULT copying in unit address")); } /* * If cdev is NULL, we have to create the child, otherwise, the * child already exists and we're just merging properties into * the existing node. The node must be unbound. */ if (cdev == NULL) createmode = 1; if (createmode) { struct fc_resource *ip; int nodeid; /* * Make sure 'ch' is a nodeid we gave the interpreter. * It must be on our resource list. */ if ((ip = find_nodeid_resource(rp, (int)ch)) == NULL) { kmem_free(unit_address, OBP_MAXPATHLEN); return (fc_priv_error(cp, "Unknown phandle")); } /* * Allocate a self-identifying, persistent node with * the auto-free attribute. */ if (ndi_devi_alloc(pdev, nodename, DEVI_SID_NODEID, &cdev)) { kmem_free(unit_address, OBP_MAXPATHLEN); return (fc_priv_error(cp, "Can't create node")); } /* * Free the nodeid we just allocated here, and use * the one we handed in. Retain the attributes of * the original SID nodetype. */ nodeid = ddi_get_nodeid(cdev); i_ndi_set_nodeid(cdev, (int)ch); impl_ddi_free_nodeid(nodeid); /* * Remove nodeid 'ch' from our resource list, now that it * will be managed by the ddi framework. */ fc_rem_resource(rp, ip); kmem_free(ip, sizeof (struct fc_resource)); } else if (strcmp(ddi_node_name(cdev), nodename) != 0) { FC_DEBUG2(1, CE_CONT, "Changing <%s> nodename to <%s>\n", ddi_node_name(cdev), nodename); if (ndi_devi_set_nodename(cdev, nodename, 0)) { kmem_free(unit_address, OBP_MAXPATHLEN); return (fc_priv_error(cp, "Can't set ndi nodename")); } } if (fc_ndi_prop_update(DDI_DEV_T_NONE, cdev, "name", (uchar_t *)nodename, strlen(nodename) + 1)) { kmem_free(unit_address, OBP_MAXPATHLEN); if (createmode) (void) ndi_devi_free(cdev); return (fc_priv_error(cp, "Can't create name property")); } /* * Add the dip->phandle translation to our list of known phandles. */ fc_add_dip_to_phandle(fc_handle_to_phandle_head(rp), cdev, ch); /* * Add the new node to our copy of the subtree. */ fc_add_child(cdev, pdev, fc_handle_to_dtree(rp)); rp->cdip = cdev; rp->cdip_state = FC_CDIP_STARTED; kmem_free(unit_address, OBP_MAXPATHLEN); cp->nresults = fc_int2cell(0); return (fc_success_op(ap, rp, cp)); }