Esempio n. 1
0
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;
	}
}
Esempio n. 2
0
/*
 * 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));
}