Exemplo n.º 1
0
static void
ppb_removechild(dev_info_t *dip)
{
	ppb_devstate_t *ppb;

	ppb = (ppb_devstate_t *)ddi_get_soft_state(ppb_state,
	    ddi_get_instance(ddi_get_parent(dip)));

	if (PM_CAPABLE(ppb->ppb_pwr_p)) {

		DEBUG2(DBG_PWR, ddi_get_parent(dip),
		    "UNINITCHILD: removing pwr_info for %s@%s\n",
		    ddi_node_name(dip), ddi_get_name_addr(dip));
		pci_pwr_rm_info(ppb->ppb_pwr_p, dip);
	}

	ddi_set_name_addr(dip, NULL);

	/*
	 * Strip the node to properly convert it back to prototype form
	 */
	ddi_remove_minor_node(dip, NULL);

	impl_rem_dev_props(dip);
}
Exemplo n.º 2
0
/*
 * Recursive ascent
 *
 * This now only does half the job.  It finds the node, then the caller
 * has to search the node for the binding name
 */
static in_node_t *
in_devwalk(dev_info_t *dip, in_node_t **ap, char *addr)
{
	in_node_t *np;
	char *name;

	ASSERT(dip);
	ASSERT(e_ddi_inst_state.ins_busy);
	if (dip == ddi_root_node()) {
		*ap = NULL;
		return (e_ddi_inst_state.ins_root);
	}
	/*
	 * call up to find parent, then look through the list of kids
	 * for a match
	 */
	np = in_devwalk(ddi_get_parent(dip), ap, NULL);
	if (np == NULL)
		return (np);
	*ap = np;
	np = np->in_child;
	name = ddi_node_name(dip);
	if (addr == NULL)
		addr = ddi_get_name_addr(dip);

	while (np) {
		if (in_eqstr(np->in_node_name, name) &&
		    in_eqstr(np->in_unit_addr, addr)) {
			return (np);
		}
		np = np->in_sibling;
	}
	return (np);
}
Exemplo n.º 3
0
/*
 * vdds_match_niu_node -- callback function to verify a node is the
 *	NIU Hybrid node.
 */
static int
vdds_match_niu_node(dev_info_t *dip, void *arg)
{
	vdds_cb_arg_t	*warg = (vdds_cb_arg_t *)arg;
	char		*name;
	vdds_reg_t	*reg_p;
	uint_t		reglen;
	int		rv;
	uint32_t	addr_hi;

	name = ddi_node_name(dip);
	if (strcmp(name, "network")  != 0) {
		return (DDI_WALK_CONTINUE);
	}
	rv = ddi_prop_lookup_int_array(DDI_DEV_T_ANY, dip,
	    DDI_PROP_DONTPASS, "reg", (int **)&reg_p, &reglen);
	if (rv != DDI_PROP_SUCCESS) {
		DWARN(NULL, "Failed to get reg property dip=0x%p", dip);
		return (DDI_WALK_CONTINUE);
	}

	addr_hi = reg_p->addr_hi;
	DBG1(NULL, "addr_hi = 0x%x dip=0x%p", addr_hi, dip);
	ddi_prop_free(reg_p);
	if (addr_hi == HVCOOKIE(warg->cookie)) {
		warg->dip = dip;
		if (!e_ddi_branch_held(dip))
			e_ddi_branch_hold(dip);
		DBG1(NULL, "Found dip = 0x%p", dip);
		return (DDI_WALK_TERMINATE);
	}
	return (DDI_WALK_CONTINUE);
}
Exemplo n.º 4
0
static int
fco_invalidate(dev_info_t *ap, fco_handle_t rp, fc_ci_t *cp)
{
	dev_info_t *root, *child;
	struct fc_device_tree *subtree = fc_handle_to_dtree(rp);
	int configured = (rp->cdip_state == FC_CDIP_CONFIG);

	/*
	 * If we created any children, delete them. The root node is the
	 * config child, if one exists for this bus, otherwise it's the
	 * attachment point.
	 *
	 * Our copy of the subtree only contains records of nodes we created
	 * under the subtree root and contains the parent->child linkage
	 * that isn't yet established in the real device tree.
	 *
	 * XXX: What we don't do is restore the config child node to it's
	 * pre-interpretive state. (We may have added properties to
	 * that node. It's not clear if its necessary to clean them up.)
	 */
	root = rp->child ? rp->child : ap;

	while ((child = fc_child_node(root, subtree)) != NULL) {
		FC_DEBUG2(1, CE_CONT, "fco_invalidate: remove subtree "
		    "<%s> dip %p\n", ddi_node_name(child), child);
		remove_subtree(child, subtree);
	}

	if (configured)
		(void) ndi_devi_offline(root, NDI_UNCONFIG);

	cp->nresults = fc_int2cell(0);
	return (fc_success_op(ap, rp, cp));
}
Exemplo n.º 5
0
void
npe_enable_htmsi_children(dev_info_t *dip)
{
	dev_info_t *cdip = ddi_get_child(dip);
	ddi_acc_handle_t cfg_hdl;

	if (!npe_enable_htmsi_flag)
		return;

	/*
	 * Hypertransport MSI remapping only applies to AMD CPUs using
	 * Hypertransport (K8 and above) and not other platforms with non-AMD
	 * CPUs that may be using Hypertransport internally in the chipset(s)
	 */
	if (!(cpuid_getvendor(CPU) == X86_VENDOR_AMD &&
	    cpuid_getfamily(CPU) >= 0xf))
		return;

	for (; cdip != NULL; cdip = ddi_get_next_sibling(cdip)) {
		if (pci_config_setup(cdip, &cfg_hdl) != DDI_SUCCESS) {
			cmn_err(CE_NOTE, "!npe_enable_htmsi_children: "
			    "pci_config_setup failed for %s",
			    ddi_node_name(cdip));
			return;
		}

		(void) npe_enable_htmsi(cfg_hdl);
		pci_config_teardown(&cfg_hdl);
	}
}
Exemplo n.º 6
0
static int
sbbc_find_dip(dev_info_t *dip, void *arg)
{
	char		*node_name;
	sbbc_find_dip_t	*dip_struct = (sbbc_find_dip_t *)arg;
	char		status[OBP_MAXPROPNAME];

	/*
	 * Need to find a node named "bootbus-controller" that is neither
	 * disabled nor failed.  If a node is not ok, there will be an
	 * OBP status property.  Therefore, we will look for a node
	 * without the status property.
	 */
	node_name = ddi_node_name(dip);
	if (strcmp(node_name, "bootbus-controller") == 0 && DDI_CF2(dip) &&
		(prom_getprop(ddi_get_nodeid(dip),
		"status", (caddr_t)status) == -1) &&
		(prom_getprop(ddi_get_nodeid(ddi_get_parent(dip)),
		"status", (caddr_t)status) == -1)) {

		if (dip != dip_struct->cur_dip) {
			dip_struct->new_dip = (void *)dip;
			return (DDI_WALK_TERMINATE);
		}
	}

	return (DDI_WALK_CONTINUE);
}
Exemplo n.º 7
0
/*
 * Create a pci_pwr_chld_t structure for a given devinfo node.
 */
void
pci_pwr_create_info(pci_pwr_t *pwr_p, dev_info_t *dip)
{
	pci_pwr_chld_t *p;

	ASSERT(PM_CAPABLE(pwr_p));

	DEBUG2(DBG_PWR, ddi_get_parent(dip), "ADDING NEW PWR_INFO %s@%s\n",
	    ddi_node_name(dip), ddi_get_name_addr(dip));

	p = kmem_zalloc(sizeof (struct pci_pwr_chld), KM_SLEEP);
	p->dip = dip;

	mutex_enter(&pwr_p->pwr_mutex);

	/*
	 * Until components are created for this device, bus
	 * should be at full power since power of child device
	 * is unknown.  Increment # children requiring "full power"
	 */
	p->flags |= PWR_FP_HOLD;
	pwr_p->pwr_fp++;

	p->next =  pwr_p->pwr_info;
	pwr_p->pwr_info = p;

	pci_pwr_change(pwr_p, pwr_p->current_lvl, pci_pwr_new_lvl(pwr_p));

	mutex_exit(&pwr_p->pwr_mutex);
}
Exemplo n.º 8
0
/*
 * Control ops entry point:
 *
 * Requests handled completely:
 *      DDI_CTLOPS_INITCHILD
 *      DDI_CTLOPS_UNINITCHILD
 * All others are passed to the parent.
 */
static int
acpinex_ctlops(dev_info_t *dip, dev_info_t *rdip, ddi_ctl_enum_t op, void *arg,
    void *result)
{
	int rval = DDI_SUCCESS;

	switch (op) {
	case DDI_CTLOPS_INITCHILD:
		rval = init_child((dev_info_t *)arg);
		break;

	case DDI_CTLOPS_UNINITCHILD:
		impl_ddi_sunbus_removechild((dev_info_t *)arg);
		break;

	case DDI_CTLOPS_REPORTDEV: {
		if (rdip == (dev_info_t *)0)
			return (DDI_FAILURE);
		cmn_err(CE_CONT, "?acpinex: %s@%s, %s%d\n",
		    ddi_node_name(rdip), ddi_get_name_addr(rdip),
		    ddi_driver_name(rdip), ddi_get_instance(rdip));
		break;
	}

	default:
		rval = ddi_ctlops(dip, rdip, op, arg, result);
		break;
	}

	return (rval);
}
Exemplo n.º 9
0
/*
 * pcmu_init_child
 *
 * This function is called from our control ops routine on a
 * DDI_CTLOPS_INITCHILD request.  It builds and sets the device's
 * parent private data area.
 *
 * used by: pcmu_ctlops()
 *
 * return value: none
 */
int
pcmu_init_child(pcmu_t *pcmu_p, dev_info_t *child)
{
	char name[10];
	ddi_acc_handle_t config_handle;
	uint8_t bcr;
	uint8_t header_type;

	if (name_child(child, name, 10) != DDI_SUCCESS)
		return (DDI_FAILURE);
	ddi_set_name_addr(child, name);

	PCMU_DBG2(PCMU_DBG_PWR, ddi_get_parent(child),
	    "INITCHILD: config regs setup for %s@%s\n",
	    ddi_node_name(child), ddi_get_name_addr(child));

	/*
	 * Map the child configuration space to for initialization.
	 * We assume the obp will do the following in the devices
	 * config space:
	 *
	 *	Set the latency-timer register to values appropriate
	 *	for the devices on the bus (based on other devices
	 *	MIN_GNT and MAX_LAT registers.
	 *
	 *	Set the fast back-to-back enable bit in the command
	 *	register if it's supported and all devices on the bus
	 *	have the capability.
	 *
	 */
	if (pci_config_setup(child, &config_handle) != DDI_SUCCESS) {
		ddi_set_name_addr(child, NULL);
		return (DDI_FAILURE);
	}

	/*
	 * Determine the configuration header type.
	 */
	header_type = pci_config_get8(config_handle, PCI_CONF_HEADER);
	PCMU_DBG2(PCMU_DBG_INIT_CLD, pcmu_p->pcmu_dip, "%s: header_type=%x\n",
	    ddi_driver_name(child), header_type);

	/*
	 * If the device has a bus control register then program it
	 * based on the settings in the command register.
	 */
	if ((header_type & PCI_HEADER_TYPE_M) == PCI_HEADER_ONE) {
		bcr = pci_config_get8(config_handle, PCI_BCNF_BCNTRL);
		if (pcmu_command_default & PCI_COMM_PARITY_DETECT)
			bcr |= PCI_BCNF_BCNTRL_PARITY_ENABLE;
		if (pcmu_command_default & PCI_COMM_SERR_ENABLE)
			bcr |= PCI_BCNF_BCNTRL_SERR_ENABLE;
		bcr |= PCI_BCNF_BCNTRL_MAST_AB_MODE;
		pci_config_put8(config_handle, PCI_BCNF_BCNTRL, bcr);
	}

	pci_config_teardown(&config_handle);
	return (DDI_SUCCESS);
}
Exemplo n.º 10
0
/*
 * cpunex_bus_ctl()
 *    This routine implements nexus bus ctl operations. Of importance are
 *    DDI_CTLOPS_REPORTDEV, DDI_CTLOPS_INITCHILD, DDI_CTLOPS_UNINITCHILD
 *    and DDI_CTLOPS_POWER. For DDI_CTLOPS_INITCHILD, it tries to lookup
 *    reg property on the child node and builds and sets the name.
 */
static int
cpunex_bus_ctl(dev_info_t *dip, dev_info_t *rdip, ddi_ctl_enum_t op, void *arg,
    void *result)
{
	switch (op) {
		case DDI_CTLOPS_REPORTDEV: {
			dev_info_t *pdip = ddi_get_parent(rdip);
			cmn_err(CE_CONT, "?%s%d at %s%d",
			    ddi_node_name(rdip), ddi_get_instance(rdip),
			    ddi_node_name(pdip), ddi_get_instance(pdip));
			return (DDI_SUCCESS);
		}

		case DDI_CTLOPS_INITCHILD: {
			dev_info_t *cdip = (dev_info_t *)arg;
			int i;
			char caddr[MAXNAMELEN];

			i = ddi_prop_get_int(DDI_DEV_T_ANY, cdip,
			    DDI_PROP_DONTPASS, "reg", -1);

			if (i == -1) {
				cmn_err(CE_NOTE, "!%s(%d): \"reg\" property "
				    "not found", ddi_node_name(cdip),
				    ddi_get_instance(cdip));
				return (DDI_NOT_WELL_FORMED);
			}

			(void) sprintf(caddr, "%d", i);
			ddi_set_name_addr(cdip, caddr);

			return (DDI_SUCCESS);
		}

		case DDI_CTLOPS_UNINITCHILD: {
			ddi_prop_remove_all((dev_info_t *)arg);
			ddi_set_name_addr((dev_info_t *)arg, NULL);
			return (DDI_SUCCESS);
		}

		default: {
			return (ddi_ctlops(dip, rdip, op, arg, result));
		}
	}
}
Exemplo n.º 11
0
void
load_platform_drivers(void)
{
	dev_info_t 		*dip;		/* dip of the isa driver */
	int			simba_present = 0;
	dev_info_t		*root_child_node;


	/*
	 * Install Isa driver. This is required for the southbridge IDE
	 * workaround - to reset the IDE channel during IDE bus reset.
	 * Panic the system in case ISA driver could not be loaded or
	 * any problem in accessing its pci config space. Since the register
	 * to reset the channel for IDE is in ISA config space!.
	 */
	root_child_node = ddi_get_child(ddi_root_node());

	while (root_child_node != NULL) {
		if (strcmp(ddi_node_name(root_child_node), "pci") == 0) {
			root_child_node = ddi_get_child(root_child_node);
			if (strcmp(ddi_node_name(root_child_node), "pci") == 0)
				simba_present = 1;
			break;
		}
		root_child_node = ddi_get_next_sibling(root_child_node);
	}


	if (simba_present)
	    dip = e_ddi_hold_devi_by_path(PLATFORM_ISA_PATHNAME_WITH_SIMBA, 0);
	else
	    dip = e_ddi_hold_devi_by_path(PLATFORM_ISA_PATHNAME, 0);

	if (dip == NULL) {
		cmn_err(CE_PANIC, "Could not install the isa driver\n");
		return;
	}

	if (pci_config_setup(dip, &platform_isa_handle) != DDI_SUCCESS) {
		cmn_err(CE_PANIC, "Could not get the config space of isa\n");
		return;
	}
}
Exemplo n.º 12
0
/*
 * name_child
 *
 * This function is called from pcmu_init_child to name a node. It is
 * also passed as a callback for node merging functions.
 *
 * return value: DDI_SUCCESS, DDI_FAILURE
 */
static int
name_child(dev_info_t *child, char *name, int namelen)
{
	pci_regspec_t *pcmu_rp;
	int reglen;
	uint_t func;
	char **unit_addr;
	uint_t n;

	/*
	 * Set the address portion of the node name based on
	 * unit-address property, if it exists.
	 * The interpretation of the unit-address is DD[,F]
	 * where DD is the device id and F is the function.
	 */
	if (ddi_prop_lookup_string_array(DDI_DEV_T_ANY, child,
	    DDI_PROP_DONTPASS, "unit-address", &unit_addr, &n) ==
	    DDI_PROP_SUCCESS) {
		if (n != 1 || *unit_addr == NULL || **unit_addr == 0) {
			cmn_err(CE_WARN, "unit-address property in %s.conf"
			    " not well-formed", ddi_driver_name(child));
			ddi_prop_free(unit_addr);
			return (DDI_FAILURE);
		}
		(void) snprintf(name, namelen, "%s", *unit_addr);
		ddi_prop_free(unit_addr);
		return (DDI_SUCCESS);
	}

	/*
	 * The unit-address property is does not exist. Set the address
	 * portion of the node name based on the function and device number.
	 */
	if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, child, DDI_PROP_DONTPASS,
	    "reg", (int **)&pcmu_rp, (uint_t *)&reglen) == DDI_SUCCESS) {
		if (((reglen * sizeof (int)) % sizeof (pci_regspec_t)) != 0) {
			cmn_err(CE_WARN, "reg property not well-formed");
			return (DDI_FAILURE);
		}

		func = PCI_REG_FUNC_G(pcmu_rp[0].pci_phys_hi);
		if (func != 0) {
			(void) snprintf(name, namelen, "%x,%x",
				PCI_REG_DEV_G(pcmu_rp[0].pci_phys_hi), func);
		} else {
			(void) snprintf(name, namelen, "%x",
				PCI_REG_DEV_G(pcmu_rp[0].pci_phys_hi));
		}
		ddi_prop_free(pcmu_rp);
		return (DDI_SUCCESS);
	}
	cmn_err(CE_WARN, "cannot name pci child '%s'", ddi_node_name(child));
	return (DDI_FAILURE);
}
Exemplo n.º 13
0
/*
 * pcmu_report_dev
 *
 * This function is called from our control ops routine on a
 * DDI_CTLOPS_REPORTDEV request.
 *
 * The display format is
 *
 *	<name><inst> at <pname><pinst> device <dev> function <func>
 *
 * where
 *
 *	<name>		this device's name property
 *	<inst>		this device's instance number
 *	<name>		parent device's name property
 *	<inst>		parent device's instance number
 *	<dev>		this device's device number
 *	<func>		this device's function number
 */
int
pcmu_report_dev(dev_info_t *dip)
{
	if (dip == (dev_info_t *)0) {
		return (DDI_FAILURE);
	}
	cmn_err(CE_CONT, "?PCI-device: %s@%s, %s%d\n", ddi_node_name(dip),
	    ddi_get_name_addr(dip), ddi_driver_name(dip),
	    ddi_get_instance(dip));
	return (DDI_SUCCESS);
}
Exemplo n.º 14
0
/*
 * save config regs for HyperTransport devices without drivers of classes:
 * memory controller and hostbridge
 */
int
npe_save_htconfig_children(dev_info_t *dip)
{
	dev_info_t *cdip = ddi_get_child(dip);
	ddi_acc_handle_t cfg_hdl;
	uint16_t ptr;
	int rval = DDI_SUCCESS;
	uint8_t cl, scl;

	for (; cdip != NULL; cdip = ddi_get_next_sibling(cdip)) {
		if (ddi_driver_major(cdip) != DDI_MAJOR_T_NONE)
			continue;

		if (pci_config_setup(cdip, &cfg_hdl) != DDI_SUCCESS)
			return (DDI_FAILURE);

		cl = pci_config_get8(cfg_hdl, PCI_CONF_BASCLASS);
		scl = pci_config_get8(cfg_hdl, PCI_CONF_SUBCLASS);

		if (((cl == PCI_CLASS_MEM && scl == PCI_MEM_RAM) ||
		    (cl == PCI_CLASS_BRIDGE && scl == PCI_BRIDGE_HOST)) &&
		    pci_htcap_locate(cfg_hdl, 0, 0, &ptr) == DDI_SUCCESS) {

			if (pci_save_config_regs(cdip) != DDI_SUCCESS) {
				cmn_err(CE_WARN, "Failed to save HT config "
				    "regs for %s\n", ddi_node_name(cdip));
				rval = DDI_FAILURE;

			} else if (ddi_prop_update_int(DDI_DEV_T_NONE, cdip,
			    "htconfig-saved", 1) != DDI_SUCCESS) {
				cmn_err(CE_WARN, "Failed to set htconfig-saved "
				    "property for %s\n", ddi_node_name(cdip));
				rval = DDI_FAILURE;
			}
		}

		pci_config_teardown(&cfg_hdl);
	}

	return (rval);
}
Exemplo n.º 15
0
/*
 * fco_finish_device ( phandle -- )
 */
static int
fco_finish_device(dev_info_t *ap, fco_handle_t rp, fc_ci_t *cp)
{
	fc_phandle_t h;
	dev_info_t *cdev;

	if (fc_cell2int(cp->nargs) != 1)
		return (fc_syntax_error(cp, "nargs must be 1"));

	if (rp->cdip_state != FC_CDIP_STARTED)
		return (fc_priv_error(cp, "bad node-creation state"));

	h = fc_cell2phandle(fc_arg(cp, 0));
	cdev = fc_phandle_to_dip(fc_handle_to_phandle_head(rp), h);
	if (cdev != rp->cdip)
		return (fc_priv_error(cp, "bad phandle"));

	/*
	 * We don't want to online children of the attachment point.
	 * We'll 'config' them online later.
	 *
	 * XXX - APA - I've changed this a bit.  The only time we don't
	 * want to bind the device is if the parent is the attachment point
	 * and the device is the same as the device that was passed to
	 * the interpreter.  We assume the configurator will do the binding.
	 */
	if ((ddi_get_parent(cdev) == ap) && (cdev == rp->child)) {
		FC_DEBUG2(5, CE_CONT, "fc_finish_device: "
		    "*not* binding <%s> dip %p\n", ddi_node_name(cdev), cdev);
	} else {
		FC_DEBUG2(5, CE_CONT, "fc_finish_device: binding <%s> dip %p\n",
		    ddi_node_name(cdev), cdev);

		(void) ndi_devi_bind_driver(cdev, 0);
	}

	rp->cdip_state = FC_CDIP_DONE;
	cp->nresults = fc_int2cell(0);
	return (fc_success_op(ap, rp, cp));
}
Exemplo n.º 16
0
/*ARGSUSED*/
static int
check_xpvd(dev_info_t *dip, void *arg)
{
	char *name;

	name = ddi_node_name(dip);
	if (name == NULL || strcmp(name, "xpvd")) {
		return (DDI_WALK_CONTINUE);
	} else {
		xpvd_dip = dip;
		return (DDI_WALK_TERMINATE);
	}
}
Exemplo n.º 17
0
static int
pmubus_ctlops(dev_info_t *dip, dev_info_t *rdip,
    ddi_ctl_enum_t op, void *arg, void *result)
{
	dev_info_t *child = (dev_info_t *)arg;
	pmubus_obpregspec_t *pmubus_rp;
	char name[9];
	int reglen;

	switch (op) {
	case DDI_CTLOPS_INITCHILD:

		if (ddi_getlongprop(DDI_DEV_T_ANY, child,
		    DDI_PROP_DONTPASS, "reg", (caddr_t)&pmubus_rp,
		    &reglen) != DDI_SUCCESS) {

			return (DDI_FAILURE);
		}

		if ((reglen % sizeof (pmubus_obpregspec_t)) != 0) {
			cmn_err(CE_WARN,
			    "pmubus: reg property not well-formed for "
			    "%s size=%d\n", ddi_node_name(child), reglen);
			kmem_free(pmubus_rp, reglen);

			return (DDI_FAILURE);
		}
		(void) snprintf(name, sizeof (name), "%x,%x",
		    pmubus_rp->reg_addr_hi, pmubus_rp->reg_addr_lo);
		ddi_set_name_addr(child, name);
		kmem_free(pmubus_rp, reglen);

		return (DDI_SUCCESS);

	case DDI_CTLOPS_UNINITCHILD:

		ddi_set_name_addr(child, NULL);
		ddi_remove_minor_node(child, NULL);
		impl_rem_dev_props(child);

		return (DDI_SUCCESS);
	default:
		break;
	}

	return (ddi_ctlops(dip, rdip, op, arg, result));
}
Exemplo n.º 18
0
void
npe_enable_htmsi_children(dev_info_t *dip)
{
	dev_info_t *cdip = ddi_get_child(dip);
	ddi_acc_handle_t cfg_hdl;

	for (; cdip != NULL; cdip = ddi_get_next_sibling(cdip)) {
		if (pci_config_setup(cdip, &cfg_hdl) != DDI_SUCCESS) {
			cmn_err(CE_NOTE, "!npe_enable_htmsi_children: "
			    "pci_config_setup failed for %s",
			    ddi_node_name(cdip));
		}

		(void) npe_enable_htmsi(cfg_hdl);
		pci_config_teardown(&cfg_hdl);
	}
}
Exemplo n.º 19
0
/*
 * Allocate space for component state information in pci_pwr_chld_t
 */
void
pci_pwr_add_components(pci_pwr_t *pwr_p, dev_info_t *cdip, pci_pwr_chld_t *p)
{
	int num_comps = PM_NUMCMPTS(cdip);
	int i;

	ASSERT(MUTEX_HELD(&pwr_p->pwr_mutex));
	/*
	 * Assume the power level of a component is UNKNOWN until
	 * notified otherwise.
	 */
	if (num_comps > 0) {
		p->comp_pwr =
		    kmem_alloc(sizeof (int) * num_comps, KM_SLEEP);
		p->num_comps = num_comps;

		DEBUG3(DBG_PWR, ddi_get_parent(cdip),
		    "ADDING %d COMPONENTS FOR %s@%s\n", num_comps,
		    ddi_node_name(cdip), ddi_get_name_addr(cdip));
	} else {
		cmn_err(CE_WARN, "%s%d device has %d components",
		    ddi_driver_name(cdip), ddi_get_instance(cdip),
		    num_comps);

		return;
	}

	/*
	 * Release the fp hold that was made when the device
	 * was created.
	 */
	ASSERT((p->flags & PWR_FP_HOLD) == PWR_FP_HOLD);
	p->flags &= ~PWR_FP_HOLD;
	pwr_p->pwr_fp--;

	for (i = 0; i < num_comps; i++) {
		/*
		 * Initialize the component lvl so that the
		 * state reference counts will be updated correctly.
		 */
		p->comp_pwr[i] = PM_LEVEL_NOLEVEL;
		pci_pwr_update_comp(pwr_p, p, i, PM_LEVEL_UNKNOWN);
	}
}
Exemplo n.º 20
0
int
iommulib_nexus_unregister(iommulib_nexhandle_t handle)
{
	dev_info_t *dip;
	int instance;
	const char *driver;
	iommulib_nex_t *nexp = (iommulib_nex_t *)handle;
	const char *f = "iommulib_nexus_unregister";

	ASSERT(nexp);

	if (nexp->nex_ref != 0)
		return (DDI_FAILURE);

	mutex_enter(&iommulib_nexus_lock);

	dip = nexp->nex_dip;
	driver = ddi_driver_name(dip);
	instance = ddi_get_instance(dip);

	/* A future enhancement would be to add ref-counts */

	if (nexp->nex_prev == NULL) {
		iommulib_nexus_list = nexp->nex_next;
	} else {
		nexp->nex_prev->nex_next = nexp->nex_next;
	}

	if (nexp->nex_next != NULL)
		nexp->nex_next->nex_prev = nexp->nex_prev;

	mutex_exit(&iommulib_nexus_lock);

	kmem_free(nexp, sizeof (iommulib_nex_t));

	cmn_err(CE_NOTE, "!%s: %s%d: NEXUS (%s) handle successfully "
	    "unregistered from IOMMULIB", f, driver, instance,
	    ddi_node_name(dip));

	ndi_rele_devi(dip);

	return (DDI_SUCCESS);
}
Exemplo n.º 21
0
/*ARGSUSED*/
static int
eibnx_bus_ctl(dev_info_t *dip, dev_info_t *rdip, ddi_ctl_enum_t ctlop,
    void *arg, void *result)
{
	dev_info_t *child = arg;
	int ret;
	char name[MAXNAMELEN];

	switch (ctlop) {
	case DDI_CTLOPS_REPORTDEV:
		ENX_DPRINTF_DEBUG("EoIB device: %s@%s, %s%d",
		    ddi_node_name(rdip), ddi_get_name_addr(rdip),
		    ddi_driver_name(rdip), ddi_get_instance(rdip));
		/*FALLTHROUGH*/

	case DDI_CTLOPS_ATTACH:
	case DDI_CTLOPS_DETACH:
	case DDI_CTLOPS_POWER:
	case DDI_CTLOPS_SIDDEV:
	case DDI_CTLOPS_IOMIN:
		ret = DDI_SUCCESS;
		break;

	case DDI_CTLOPS_INITCHILD:
		if ((ret = eibnx_name_child(child, name,
		    sizeof (name))) == DDI_SUCCESS) {
			ddi_set_name_addr(child, name);
		}
		break;

	case DDI_CTLOPS_UNINITCHILD:
		ddi_set_name_addr(child, NULL);
		ret = DDI_SUCCESS;
		break;

	default:
		ret = ddi_ctlops(dip, rdip, ctlop, arg, result);
		break;
	}

	return (ret);
}
Exemplo n.º 22
0
int
npe_restore_htconfig_children(dev_info_t *dip)
{
	dev_info_t *cdip = ddi_get_child(dip);
	int rval = DDI_SUCCESS;

	for (; cdip != NULL; cdip = ddi_get_next_sibling(cdip)) {
		if (ddi_prop_get_int(DDI_DEV_T_ANY, cdip, DDI_PROP_DONTPASS,
		    "htconfig-saved", 0) == 0)
			continue;

		if (pci_restore_config_regs(cdip) != DDI_SUCCESS) {
			cmn_err(CE_WARN, "Failed to restore HT config "
			    "regs for %s\n", ddi_node_name(cdip));
			rval = DDI_FAILURE;
		}
	}

	return (rval);
}
Exemplo n.º 23
0
/*
 * Retreive the pci_pwr_chld_t structure for a given devinfo node.
 */
pci_pwr_chld_t *
pci_pwr_get_info(pci_pwr_t *pwr_p, dev_info_t *dip)
{
	pci_pwr_chld_t *p;

	ASSERT(PM_CAPABLE(pwr_p));
	ASSERT(MUTEX_HELD(&pwr_p->pwr_mutex));

	for (p = pwr_p->pwr_info; p != NULL; p = p->next) {
		if (p->dip == dip) {

			return (p);
		}
	}

	cmn_err(CE_PANIC, "unable to find pwr info data for %s@%s",
	    ddi_node_name(dip), ddi_get_name_addr(dip));

	/*NOTREACHED*/
	return (NULL);
}
Exemplo n.º 24
0
/*
 * vdds_match_niu_nexus -- callback function to verify a node is the
 *	NIU nexus node.
 */
static int
vdds_match_niu_nexus(dev_info_t *dip, void *arg)
{
	vdds_cb_arg_t	*warg = (vdds_cb_arg_t *)arg;
	vdds_reg_t	*reg_p;
	char		*name;
	uint64_t	hdl;
	uint_t		reglen;
	int		rv;

	if (dip == ddi_root_node()) {
		return (DDI_WALK_CONTINUE);
	}

	name = ddi_node_name(dip);
	if (strcmp(name, "niu")  != 0) {
		return (DDI_WALK_CONTINUE);
	}
	rv = ddi_prop_lookup_int_array(DDI_DEV_T_ANY, dip,
	    DDI_PROP_DONTPASS, "reg", (int **)&reg_p, &reglen);
	if (rv != DDI_PROP_SUCCESS) {
		DWARN(NULL, "Failed to get reg property dip=0x%p", dip);
		return (DDI_WALK_CONTINUE);
	}

	hdl =  reg_p->addr_hi & 0x0FFFFFFF;
	ddi_prop_free(reg_p);

	DBG2(NULL, "Handle = 0x%lx dip=0x%p", hdl, dip);
	if (hdl == NIUCFGHDL(warg->cookie)) {
		/* Hold before returning */
		if (!e_ddi_branch_held(dip))
			e_ddi_branch_hold(dip);
		warg->dip = dip;
		DBG2(NULL, "Found dip = 0x%p", dip);
		return (DDI_WALK_TERMINATE);
	}
	return (DDI_WALK_CONTINUE);
}
Exemplo n.º 25
0
/*
 * Return the devinfo node to a boot device
 */
static dev_info_t *
path_to_devinfo(char *path)
{
	struct i_path_findnode fn;
	extern dev_info_t *top_devinfo;

	/*
	 * Get the nodeid of the given pathname, if such a mapping exists.
	 */
	fn.dip = NULL;
	fn.nodeid = prom_finddevice(path);
	if (fn.nodeid != OBP_BADNODE) {
		/*
		 * Find the nodeid in our copy of the device tree and return
		 * whatever name we used to bind this node to a driver.
		 */
		ddi_walk_devs(top_devinfo, i_path_find_node, (void *)(&fn));
	}

#ifdef	DEBUG
	/*
	 * If we're bound to something other than the nodename,
	 * note that in the message buffer and system log.
	 */
	if (fn.dip) {
		char *p, *q;

		p = ddi_binding_name(fn.dip);
		q = ddi_node_name(fn.dip);
		if (p && q && (strcmp(p, q) != 0)) {
			BMDPRINTF(("path_to_devinfo: %s bound to %s\n",
			    path, p));
		}
	}
#endif	/* DEBUG */

	return (fn.dip);
}
Exemplo n.º 26
0
/*
 * The VGA device could be under a subtractive PCI bridge on some systems.
 * Though the PCI_BCNF_BCNTRL_VGA_ENABLE bit is not set on such subtractive
 * PCI bridge, the subtractive PCI bridge can forward VGA access if no other
 * agent claims the access.
 * The vga_enable element in param acts as a flag, if not set, ignore the
 * checking for the PCI_BCNF_BCNTRL_VGA_ENABLE bit of the PCI bridge during
 * the search.
 */
static int
find_fb_dev(dev_info_t *dip, void *param)
{
	struct find_fb_dev_param *p = param;
	char *dev_type;
	dev_info_t *pdip;
	char *parent_type;

	if (dip == ddi_root_node())
		return (DDI_WALK_CONTINUE);

	if (ddi_prop_lookup_string(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS,
	    "device_type", &dev_type) != DDI_SUCCESS)
		return (DDI_WALK_PRUNECHILD);

	if ((strcmp(dev_type, "isa") == 0) || (strcmp(dev_type, "eisa") == 0)) {
		ddi_prop_free(dev_type);
		return (DDI_WALK_CONTINUE);
	}

	if ((strcmp(dev_type, "pci") == 0) ||
	    (strcmp(dev_type, "pciex") == 0)) {
		ddi_acc_handle_t pci_conf;
		uint16_t data16;
		char *nodename;

		ddi_prop_free(dev_type);

		if (!p->vga_enable)
			return (DDI_WALK_CONTINUE);

		nodename = ddi_node_name(dip);

		/*
		 * If the node is not a PCI-to-PCI bridge, continue traversing
		 * (it could be the root node), otherwise, check for the
		 * VGAEnable bit to be set in the Bridge Control Register.
		 */
		if (strcmp(nodename, "pci") == 0) {
			if (is_pci_bridge(dip) == B_FALSE)
				return (DDI_WALK_CONTINUE);
		}

		if (i_ddi_attach_node_hierarchy(dip) != DDI_SUCCESS)
			return (DDI_WALK_PRUNECHILD);

		if (pci_config_setup(dip, &pci_conf) != DDI_SUCCESS)
			return (DDI_WALK_PRUNECHILD);

		data16 = pci_config_get16(pci_conf, PCI_BCNF_BCNTRL);
		pci_config_teardown(&pci_conf);

		if (data16 & PCI_BCNF_BCNTRL_VGA_ENABLE)
			return (DDI_WALK_CONTINUE);

		return (DDI_WALK_PRUNECHILD);
	}

	if (strcmp(dev_type, "display") != 0) {
		ddi_prop_free(dev_type);
		return (DDI_WALK_CONTINUE);
	}

	ddi_prop_free(dev_type);

	if ((pdip = ddi_get_parent(dip)) == NULL)
		return (DDI_WALK_PRUNECHILD);

	if (ddi_prop_lookup_string(DDI_DEV_T_ANY, pdip, DDI_PROP_DONTPASS,
	    "device_type", &parent_type) != DDI_SUCCESS)
		return (DDI_WALK_PRUNECHILD);

	if ((strcmp(parent_type, "isa") == 0) ||
	    (strcmp(parent_type, "eisa") == 0)) {
		p->found_dip = dip;
		ddi_prop_free(parent_type);
		return (DDI_WALK_TERMINATE);
	}

	if ((strcmp(parent_type, "pci") == 0) ||
	    (strcmp(parent_type, "pciex") == 0)) {
		ddi_acc_handle_t pci_conf;
		uint16_t data16;

		ddi_prop_free(parent_type);

		if (i_ddi_attach_node_hierarchy(dip) != DDI_SUCCESS)
			return (DDI_WALK_PRUNECHILD);

		if (pci_config_setup(dip, &pci_conf) != DDI_SUCCESS)
			return (DDI_WALK_PRUNECHILD);

		data16 = pci_config_get16(pci_conf, PCI_CONF_COMM);
		pci_config_teardown(&pci_conf);

		if (!(data16 & PCI_COMM_IO))
			return (DDI_WALK_PRUNECHILD);

		p->found_dip = dip;
		return (DDI_WALK_TERMINATE);
	}

	ddi_prop_free(parent_type);
	return (DDI_WALK_PRUNECHILD);
}
Exemplo n.º 27
0
/*
 * attach the module
 */
static int
tvhci_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
{
	char *vclass;
	int instance, vhci_regis = 0;
	struct tvhci_state *vhci = NULL;
	dev_info_t *pdip;

	instance = ddi_get_instance(dip);

	switch (cmd) {
	case DDI_ATTACH:
		break;

	case DDI_RESUME:
	case DDI_PM_RESUME:
		return (0);	/* nothing to do */

	default:
		return (DDI_FAILURE);
	}

	/*
	 * Allocate vhci data structure.
	 */
	if (ddi_soft_state_zalloc(tvhci_state, instance) != DDI_SUCCESS) {
		return (DDI_FAILURE);
	}

	vhci = ddi_get_soft_state(tvhci_state, instance);
	ASSERT(vhci != NULL);
	vhci->dip = dip;

	/* parent must be /pshot */
	pdip = ddi_get_parent(dip);
	if (strcmp(ddi_driver_name(pdip), "pshot") != 0 ||
	    ddi_get_parent(pdip) != ddi_root_node()) {
		cmn_err(CE_NOTE, "tvhci must be under /pshot/");
		goto attach_fail;
	}

	/*
	 * XXX add mpxio-disable property. need to remove the check
	 *	from the framework
	 */
	(void) ddi_prop_update_string(DDI_DEV_T_NONE, dip,
	    "mpxio-disable", "no");

	/* bus_addr is the <vhci_class> */
	vclass = ddi_get_name_addr(dip);
	if (vclass == NULL || vclass[1] == '\0') {
		cmn_err(CE_NOTE, "tvhci invalid vhci class");
		goto attach_fail;
	}

	/*
	 * Attach this instance with the mpxio framework
	 */
	if (mdi_vhci_register(vclass, dip, &tvhci_opinfo, 0) != MDI_SUCCESS) {
		cmn_err(CE_WARN, "%s mdi_vhci_register failed",
		    ddi_node_name(dip));
		goto attach_fail;
	}
	vhci_regis++;

	if (ddi_create_minor_node(dip, "devctl", S_IFCHR,
	    instance, DDI_NT_SCSI_NEXUS, 0) != DDI_SUCCESS) {
		cmn_err(CE_NOTE, "%s ddi_create_minor_node failed",
		    ddi_node_name(dip));
		goto attach_fail;
	}

	(void) ddi_prop_update_int(DDI_DEV_T_NONE, dip, DDI_NO_AUTODETACH, 1);
	ddi_report_dev(dip);
	return (DDI_SUCCESS);

attach_fail:
	if (vhci_regis)
		(void) mdi_vhci_unregister(dip, 0);

	ddi_soft_state_free(tvhci_state, instance);
	return (DDI_FAILURE);
}
Exemplo n.º 28
0
/*
 * fco_create_property ( propname-cstr buf len phandle -- )
 */
static int
fco_create_property(dev_info_t *ap, fco_handle_t rp, fc_ci_t *cp)
{
	char *buf, *bp, *pnp;
	size_t len;
	fc_phandle_t h;
	dev_info_t *dev;
	int error;
	char propname[OBP_MAXPROPNAME];

	if (fc_cell2int(cp->nargs) != 4)
		return (fc_syntax_error(cp, "nargs must be 4"));

	h = fc_cell2phandle(fc_arg(cp, 0));
	len = fc_cell2size(fc_arg(cp, 1));
	bp = fc_cell2ptr(fc_arg(cp, 2));
	pnp = fc_cell2ptr(fc_arg(cp, 3));

	dev = fc_phandle_to_dip(fc_handle_to_phandle_head(rp), h);
	if (dev == NULL)
		return (fc_priv_error(cp, "bad phandle"));

	bzero(propname, OBP_MAXPROPNAME);
	if (copyinstr(pnp, propname, OBP_MAXPROPNAME - 1, NULL))
		return (fc_priv_error(cp, "EFAULT copying in propname"));

	buf = NULL;
	if (len != 0) {
		buf = kmem_zalloc(len, KM_SLEEP);
		if (copyin(bp, buf, len)) {
			kmem_free(buf, len);
			return (fc_priv_error(cp, "EFAULT copying in propval"));
		}
	}

	/*
	 * check for propname: 'name' ... we don't allow it
	 * by changed here.  It has to be specified when the node
	 * is created.
	 */
	if (strcmp(propname, "name") == 0) {
		char *n = ddi_node_name(dev);

		if (len == 0)
			return (fc_priv_error(cp, "setting <name> to NULL"));
		if ((len < (strlen(n) + 1)) || (strcmp(n, buf) != 0)) {
			kmem_free(buf, len);
			return (fc_priv_error(cp, "changing <name> property"));
		}
		/*
		 * Since we're not changing the value, and we already created
		 * the 'name' property when we created the node ...
		 */
		kmem_free(buf, len);
		cp->nresults = fc_int2cell(0);
		return (fc_success_op(ap, rp, cp));
	}

	error = fc_ndi_prop_update(DDI_DEV_T_NONE, dev, propname,
	    (uchar_t *)buf, len);

	if (len != 0)
		kmem_free(buf, len);

	if (error)
		return (fc_priv_error(cp, "Can't create property"));

	cp->nresults = fc_int2cell(0);
	return (fc_success_op(ap, rp, cp));
}
Exemplo n.º 29
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));
}
Exemplo n.º 30
0
/*ARGSUSED*/
static int
pcmem_ctlops(dev_info_t *dip, dev_info_t *rdip,
	ddi_ctl_enum_t ctlop, void *arg, void *result)
{

	char    name[MAXNAMELEN];
	int	techreg, cissp;

	switch (ctlop) {
	case DDI_CTLOPS_REPORTDEV:
		if (rdip == (dev_info_t *)0) {
			return (DDI_FAILURE);
		}
		PCMEM_DEBUG((CE_CONT,
		    "?pcmem_ctlops: %s%d at %s in socket %d\n",
		    ddi_get_name(rdip), ddi_get_instance(rdip),
		    ddi_get_name(dip),
		    ddi_getprop(DDI_DEV_T_NONE, rdip,
			DDI_PROP_DONTPASS, "socket", -1)));

		return (DDI_SUCCESS);

	case DDI_CTLOPS_INITCHILD:

		PCMEM_DEBUG((CE_CONT,
		    "pcmem_ctlops - DDI_CTLOPS_INITCHILD persistent=%x\n",
		    ndi_dev_is_persistent_node((dev_info_t *)arg)));

		if (!ndi_dev_is_persistent_node((dev_info_t *)arg))
			return (DDI_FAILURE);
		/*
		 * XXXX - Read card CIS to determine technology
		 *	region(tn) and CIS space(dn).
		 *	Refer to Bugid 1179336.
		 */

		/*
		 * see cis_handler.h for CISTPL_DEVICE
		 *	and CISTPL_DEVICE_A
		 *
		 * CISTPL_DEVICE_DTYPE_NULL	0x00	NULL device
		 * CISTPL_DEVICE_DTYPE_ROM	0x01	ROM
		 * CISTPL_DEVICE_DTYPE_OTPROM	0x02	OTPROM
		 * CISTPL_DEVICE_DTYPE_EPROM	0x03    EPROM
		 * CISTPL_DEVICE_DTYPE_EEPROM	0x04	EEPROM
		 * CISTPL_DEVICE_DTYPE_FLASH	0x05	FLASH
		 * CISTPL_DEVICE_DTYPE_SRAM	0x06	SRAM
		 * CISTPL_DEVICE_DTYPE_DRAM	0x07	DRAM
		 *
		 */
		/*
		 * XXXX - For now set to default SRAM device
		 */
		techreg = CISTPL_DEVICE_DTYPE_SRAM;
		cissp = 0;
		(void) sprintf(name, "%d,%d", techreg, cissp);
		ddi_set_name_addr((dev_info_t *)arg, name);

		PCMEM_DEBUG((CE_CONT,
		    "pcmem_ctlops - DDI_CTLOPS_INITCHILD name=%s\n", name));

		return (DDI_SUCCESS);

	case DDI_CTLOPS_UNINITCHILD:
		ddi_set_name_addr((dev_info_t *)arg, NULL);

		PCMEM_DEBUG((CE_CONT,
		    "pcmem_ctlops - DDI_CTLOPS_UNINITCHILD child: %s(%d)\n",
		    ddi_node_name(arg), ddi_get_instance(arg)));

		return (DDI_SUCCESS);

	default:
		return (ddi_ctlops(dip, rdip, ctlop, arg, result));
	}
}