Example #1
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);
}
Example #2
0
/*
 * FCA driver's intercepted bus control operations.
 */
static int
fcoe_bus_ctl(dev_info_t *fcoe_dip, dev_info_t *rip,
    ddi_ctl_enum_t op, void *clientarg, void *result)
{
	int ret;
	switch (op) {
	case DDI_CTLOPS_REPORTDEV:
	case DDI_CTLOPS_IOMIN:
		ret = DDI_SUCCESS;
		break;

	case DDI_CTLOPS_INITCHILD:
		ret = fcoe_initchild(fcoe_dip, (dev_info_t *)clientarg);
		break;

	case DDI_CTLOPS_UNINITCHILD:
		ret = fcoe_uninitchild(fcoe_dip, (dev_info_t *)clientarg);
		break;

	default:
		ret = ddi_ctlops(fcoe_dip, rip, op, clientarg, result);
		break;
	}

	return (ret);
}
Example #3
0
unsigned long
dvma_pagesize(dev_info_t *dip)
{
	auto unsigned long dvmapgsz;

	(void) ddi_ctlops(dip, dip, DDI_CTLOPS_DVMAPAGESIZE,
	    NULL, (void *) &dvmapgsz);
	return (dvmapgsz);
}
Example #4
0
static void
i_attach_ctlop(dev_info_t *devi, ddi_attach_cmd_t cmd, ddi_pre_post_t w,
    int ret)
{
	int error;
	struct attachspec as;
	dev_info_t *pdip = ddi_get_parent(devi);

	as.cmd = cmd;
	as.when = w;
	as.pdip = pdip;
	as.result = ret;
	(void) ddi_ctlops(devi, devi, DDI_CTLOPS_ATTACH, &as, &error);
}
Example #5
0
static void
i_detach_ctlop(dev_info_t *devi, ddi_detach_cmd_t cmd, ddi_pre_post_t w,
    int ret)
{
	int error;
	struct detachspec ds;
	dev_info_t *pdip = ddi_get_parent(devi);

	ds.cmd = cmd;
	ds.when = w;
	ds.pdip = pdip;
	ds.result = ret;
	(void) ddi_ctlops(devi, devi, DDI_CTLOPS_DETACH, &ds, &error);
}
Example #6
0
int
pcieb_plat_peekpoke(dev_info_t *dip, dev_info_t *rdip, ddi_ctl_enum_t ctlop,
    void *arg, void *result)
{
	pcieb_devstate_t *pcieb = ddi_get_soft_state(pcieb_state,
	    ddi_get_instance(dip));

	if (!PCIE_IS_RP(PCIE_DIP2BUS(dip)))
		return (ddi_ctlops(dip, rdip, ctlop, arg, result));

	return (pci_peekpoke_check(dip, rdip, ctlop, arg, result,
	    ddi_ctlops, &pcieb->pcieb_err_mutex,
	    &pcieb->pcieb_peek_poke_mutex,
	    pcieb_peekpoke_cb));
}
Example #7
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));
}
Example #8
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));
		}
	}
}
Example #9
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);
}
Example #10
0
/*
 * nx1394_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
 *    (name is of the form GGGGGGGGGGGGGGGG[,AAAAAAAAAAAA], where
 *    GGGGGGGGGGGGGGGG is the GUID and AAAAAAAAAAAA is the optional unit
 *    address).
 */
static int
nx1394_bus_ctl(dev_info_t *dip, dev_info_t *rdip, ddi_ctl_enum_t op, void *arg,
    void *result)
{
	int status;

	TNF_PROBE_0_DEBUG(nx1394_bus_ctl_enter, S1394_TNF_SL_NEXUS_STACK, "");

	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));
		TNF_PROBE_0_DEBUG(nx1394_bus_ctl_exit, S1394_TNF_SL_NEXUS_STACK,
		    "");
		return (DDI_SUCCESS);
	}

	case DDI_CTLOPS_INITCHILD: {
		dev_info_t *ocdip, *cdip = (dev_info_t *)arg;
		dev_info_t *pdip = ddi_get_parent(cdip);
		int reglen, i;
		uint32_t *regptr;
		char addr[MAXNAMELEN];

		TNF_PROBE_1(nx1394_bus_ctl_init_child,
		    S1394_TNF_SL_HOTPLUG_STACK, "", tnf_opaque, dip, cdip);

		i = ddi_prop_lookup_int_array(DDI_DEV_T_ANY, cdip,
		    DDI_PROP_DONTPASS, "reg", (int **)&regptr,
		    (uint_t *)&reglen);

		if (i != DDI_PROP_SUCCESS) {
			cmn_err(CE_NOTE, "!%s(%d): \"reg\" property not found",
			    ddi_node_name(cdip), ddi_get_instance(cdip));
			TNF_PROBE_2(nx1394_bus_ctl,
			    S1394_TNF_SL_NEXUS_ERROR, "", tnf_string, msg,
			    "Reg property not found", tnf_int, reason, i);
			TNF_PROBE_1_DEBUG(nx1394_bus_ctl_exit,
			    S1394_TNF_SL_NEXUS_STACK, "", tnf_string, op,
			    "initchild");
			return (DDI_NOT_WELL_FORMED);
		}

		ASSERT(reglen != 0);

		/*
		 * addr is of the format GGGGGGGGGGGGGGGG[,AAAAAAAAAAAA]
		 */
		if (regptr[2] || regptr[3]) {
			(void) sprintf(addr, "%08x%08x,%04x%08x", regptr[0],
			    regptr[1], regptr[2], regptr[3]);
		} else {
			(void) sprintf(addr, "%08x%08x", regptr[0], regptr[1]);
		}
		ddi_prop_free(regptr);
		ddi_set_name_addr(cdip, addr);

		/*
		 * Check for a node with the same name & addr as the current
		 * node. If such a node exists, return failure.
		 */
		if ((ocdip = ndi_devi_find(pdip, ddi_node_name(cdip), addr)) !=
		    NULL && ocdip != cdip) {
			cmn_err(CE_NOTE,
			    "!%s(%d): Duplicate dev_info node found %s@%s",
			    ddi_node_name(cdip), ddi_get_instance(cdip),
			    ddi_node_name(ocdip), addr);
			TNF_PROBE_1(nx1394_bus_ctl,
			    S1394_TNF_SL_NEXUS_ERROR, "", tnf_string, msg,
			    "Duplicate nodes");
			TNF_PROBE_1_DEBUG(nx1394_bus_ctl_exit,
			    S1394_TNF_SL_NEXUS_STACK, "", tnf_string, op,
			    "initchild");
			ddi_set_name_addr(cdip, NULL);
			return (DDI_NOT_WELL_FORMED);
		}

		/*
		 * If HAL (parent dip) has "active-dma-flush" property, then
		 * add property to child as well.  Workaround for active
		 * context flushing bug in Schizo rev 2.1 and 2.2.
		 */
		if (ddi_prop_exists(DDI_DEV_T_ANY, pdip, DDI_PROP_DONTPASS,
		    "active-dma-flush") != 0) {
			status = ndi_prop_update_int(DDI_DEV_T_NONE, cdip,
			    "active-dma-flush", 1);
			if (status != NDI_SUCCESS) {
				cmn_err(CE_NOTE, "!%s(%d): Unable to add "
				    "\"active-dma-flush\" property",
				    ddi_node_name(cdip),
				    ddi_get_instance(cdip));
				TNF_PROBE_1(nx1394_bus_ctl,
				    S1394_TNF_SL_NEXUS_ERROR, "", tnf_string,
				    msg, "Unable to add \"active-dma-flush\" "
				    "property");
				TNF_PROBE_1_DEBUG(nx1394_bus_ctl_exit,
				    S1394_TNF_SL_NEXUS_STACK, "", tnf_string,
				    op, "initchild");
				ddi_set_name_addr(cdip, NULL);
				return (DDI_NOT_WELL_FORMED);
			}
		}

		TNF_PROBE_1_DEBUG(nx1394_bus_ctl_exit,
		    S1394_TNF_SL_NEXUS_STACK, "", tnf_string, op, "initchild");
		return (DDI_SUCCESS);
	}

	case DDI_CTLOPS_UNINITCHILD: {
		ddi_prop_remove_all((dev_info_t *)arg);
		ddi_set_name_addr((dev_info_t *)arg, NULL);
		TNF_PROBE_1_DEBUG(nx1394_bus_ctl_exit, S1394_TNF_SL_NEXUS_STACK,
		    "", tnf_string, op, "uninitchild");
		return (DDI_SUCCESS);
	}

	case DDI_CTLOPS_IOMIN: {
		status = ddi_ctlops(dip, rdip, op, arg, result);
		TNF_PROBE_1_DEBUG(nx1394_bus_ctl_exit, S1394_TNF_SL_NEXUS_STACK,
		    "", tnf_string, op, "iomin");
		return (status);
	}

	case DDI_CTLOPS_POWER: {
		return (DDI_SUCCESS);
	}

	/*
	 * These ops correspond to functions that "shouldn't" be called
	 * by a 1394 client driver.
	 */
	case DDI_CTLOPS_DMAPMAPC:
	case DDI_CTLOPS_REPORTINT:
	case DDI_CTLOPS_REGSIZE:
	case DDI_CTLOPS_NREGS:
	case DDI_CTLOPS_SIDDEV:
	case DDI_CTLOPS_SLAVEONLY:
	case DDI_CTLOPS_AFFINITY:
	case DDI_CTLOPS_POKE:
	case DDI_CTLOPS_PEEK: {
		cmn_err(CE_CONT, "!%s(%d): invalid op (%d) from %s(%d)",
		    ddi_node_name(dip), ddi_get_instance(dip),
		    op, ddi_node_name(rdip), ddi_get_instance(rdip));
		TNF_PROBE_2(nx1394_bus_ctl, S1394_TNF_SL_NEXUS_ERROR, "",
		    tnf_string, msg, "invalid op", tnf_int, op, op);
		TNF_PROBE_0_DEBUG(nx1394_bus_ctl_exit, S1394_TNF_SL_NEXUS_STACK,
		    "");
		return (DDI_FAILURE);
	}

	/*
	 * Everything else (e.g. PTOB/BTOP/BTOPR requests) we pass up
	 */
	default: {
		status = ddi_ctlops(dip, rdip, op, arg, result);
		TNF_PROBE_0_DEBUG(nx1394_bus_ctl_exit, S1394_TNF_SL_NEXUS_STACK,
		    "");
		return (status);
	}
	}
}
Example #11
0
/*ARGSUSED*/
static int
tvhci_ctl(dev_info_t *dip, dev_info_t *rdip,
	ddi_ctl_enum_t ctlop, void *arg, void *result)
{
	switch (ctlop) {
	case DDI_CTLOPS_REPORTDEV:
		if (rdip == (dev_info_t *)0)
			return (DDI_FAILURE);
		cmn_err(CE_CONT, "?tvhci-device: %s%d\n",
		    ddi_get_name(rdip), ddi_get_instance(rdip));
		return (DDI_SUCCESS);

	case DDI_CTLOPS_INITCHILD:
	{
		dev_info_t *child = (dev_info_t *)arg;
		return (tvhci_initchild(dip, child));
	}

	case DDI_CTLOPS_UNINITCHILD:
	{
		dev_info_t *child = (dev_info_t *)arg;
		return (tvhci_uninitchild(dip, child));
	}

	case DDI_CTLOPS_DMAPMAPC:
	case DDI_CTLOPS_REPORTINT:
	case DDI_CTLOPS_REGSIZE:
	case DDI_CTLOPS_NREGS:
	case DDI_CTLOPS_SIDDEV:
	case DDI_CTLOPS_SLAVEONLY:
	case DDI_CTLOPS_AFFINITY:
	case DDI_CTLOPS_POKE:
	case DDI_CTLOPS_PEEK:
		/*
		 * These ops correspond to functions that "shouldn't" be called
		 * by a pseudo driver.  So we whine when we're called.
		 */
		cmn_err(CE_CONT, "%s%d: invalid op (%d) from %s%d\n",
		    ddi_get_name(dip), ddi_get_instance(dip),
		    ctlop, ddi_get_name(rdip), ddi_get_instance(rdip));
		return (DDI_FAILURE);

	case DDI_CTLOPS_ATTACH:
	case DDI_CTLOPS_BTOP:
	case DDI_CTLOPS_BTOPR:
	case DDI_CTLOPS_DETACH:
	case DDI_CTLOPS_DVMAPAGESIZE:
	case DDI_CTLOPS_IOMIN:
	case DDI_CTLOPS_POWER:
	case DDI_CTLOPS_PTOB:
	default:
		/*
		 * The ops that we pass up (default).  We pass up memory
		 * allocation oriented ops that we receive - these may be
		 * associated with pseudo HBA drivers below us with target
		 * drivers below them that use ddi memory allocation
		 * interfaces like scsi_alloc_consistent_buf.
		 */
		return (ddi_ctlops(dip, rdip, ctlop, arg, result));
	}
}
Example #12
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));
	}
}
static int
pseudonex_ctl(dev_info_t *dip, dev_info_t *rdip, ddi_ctl_enum_t ctlop,
    void *arg, void *result)
{
	switch (ctlop) {
	case DDI_CTLOPS_REPORTDEV:
		if (rdip == NULL)
			return (DDI_FAILURE);
		cmn_err(CE_CONT, "?pseudo-device: %s%d\n",
		    ddi_driver_name(rdip), ddi_get_instance(rdip));
		return (DDI_SUCCESS);

	case DDI_CTLOPS_INITCHILD:
	{
		char name[12];	/* enough for a decimal integer */
		int instance = -1;
		dev_info_t *child = (dev_info_t *)arg;
		const char *childname = ddi_driver_name(child);
		char **childlist;
		uint_t nelems;
		int auto_assign = 0;

		/*
		 * If this pseudonex node has a valid-children property,
		 * then that acts as an access control list for children
		 * allowed to attach beneath this node.  Honor it.
		 */
		if (ddi_prop_lookup_string_array(DDI_DEV_T_ANY, dip,
		    DDI_PROP_DONTPASS, "valid-children", &childlist,
		    &nelems) == DDI_PROP_SUCCESS) {
			int i, ok = 0;
			for (i = 0; i < nelems; i++) {
				if (strcmp(childlist[i], childname) == 0) {
					ok = 1;
					break;
				}
			}
			ddi_prop_free(childlist);
			if (!ok)
				return (DDI_FAILURE);
		}

		/*
		 * Look up the "instance" property. If it does not exist,
		 * check to see if the "auto-assign-instance" property is set.
		 * If not, default to using instance 0; while not ideal, this
		 * is a legacy behavior we must continue to support.
		 */
		instance = ddi_prop_get_int(DDI_DEV_T_ANY, child,
		    DDI_PROP_DONTPASS, "instance", -1);
		auto_assign = ddi_prop_exists(DDI_DEV_T_ANY, child,
		    DDI_PROP_DONTPASS, "auto-assign-instance");
		NDI_CONFIG_DEBUG((CE_NOTE,
		    "pseudonex: DDI_CTLOPS_INITCHILD(instance=%d, "
		    "auto-assign=%d)", instance, auto_assign));

		if (instance != -1 && auto_assign != 0) {
			NDI_CONFIG_DEBUG((CE_NOTE, "both instance and "
			    "auto-assign-instance properties specified. "
			    "Node rejected."));
			return (DDI_FAILURE);
		}

		if (instance == -1 && auto_assign == 0) {
			/* default to instance 0 if not specified */
			NDI_CONFIG_DEBUG((CE_NOTE, "defaulting to 0"));
			instance = 0;
		}

		/*
		 * If an instance has been specified, determine if this
		 * instance is already in use; if we need to pick an instance,
		 * we do it here.
		 */
		if (auto_assign) {
			if ((instance = pseudonex_auto_assign(child)) == -1) {
				NDI_CONFIG_DEBUG((CE_NOTE, "failed to "
				    "auto-select instance for %s", childname));
				return (DDI_FAILURE);
			}
			NDI_CONFIG_DEBUG((CE_NOTE,
			    "auto-selected instance for %s: %d",
			    childname, instance));
		} else {
			if (pseudonex_check_assignment(child, instance) ==
			    DDI_FAILURE) {
				NDI_CONFIG_DEBUG((CE_WARN,
				    "Duplicate instance %d of node \"%s\" "
				    "ignored.", instance, childname));
				return (DDI_FAILURE);
			}
			NDI_CONFIG_DEBUG((CE_NOTE,
			    "using fixed-assignment instance for %s: %d",
			    childname, instance));
		}

		/*
		 * Attach the instance number to the node. This allows
		 * us to have multiple instances of the same pseudo
		 * device, they will be named 'device@instance'. If this
		 * breaks programs, we may need to special-case instance 0
		 * into 'device'. Ick. devlinks appears to handle the
		 * new names ok, so if only names in /dev are used
		 * this may not be necessary.
		 */
		(void) snprintf(name, sizeof (name), "%d", instance);
		DEVI(child)->devi_instance = instance;
		ddi_set_name_addr(child, name);
		return (DDI_SUCCESS);
	}

	case DDI_CTLOPS_UNINITCHILD:
	{
		dev_info_t *child = (dev_info_t *)arg;

		NDI_CONFIG_DEBUG((CE_NOTE,
		    "DDI_CTLOPS_UNINITCHILD(%s, instance=%d)",
		    ddi_driver_name(child), DEVI(child)->devi_instance));

		ddi_set_name_addr(child, NULL);

		return (DDI_SUCCESS);
	}

	case DDI_CTLOPS_DMAPMAPC:
	case DDI_CTLOPS_REPORTINT:
	case DDI_CTLOPS_REGSIZE:
	case DDI_CTLOPS_NREGS:
	case DDI_CTLOPS_SIDDEV:
	case DDI_CTLOPS_SLAVEONLY:
	case DDI_CTLOPS_AFFINITY:
	case DDI_CTLOPS_POKE:
	case DDI_CTLOPS_PEEK:
		/*
		 * These ops correspond to functions that "shouldn't" be called
		 * by a pseudo driver.  So we whine when we're called.
		 */
		cmn_err(CE_CONT, "%s%d: invalid op (%d) from %s%d\n",
		    ddi_driver_name(dip), ddi_get_instance(dip), ctlop,
		    ddi_driver_name(rdip), ddi_get_instance(rdip));
		return (DDI_FAILURE);

	case DDI_CTLOPS_ATTACH:
	case DDI_CTLOPS_BTOP:
	case DDI_CTLOPS_BTOPR:
	case DDI_CTLOPS_DETACH:
	case DDI_CTLOPS_DVMAPAGESIZE:
	case DDI_CTLOPS_IOMIN:
	case DDI_CTLOPS_POWER:
	case DDI_CTLOPS_PTOB:
	default:
		/*
		 * The ops that we pass up (default).  We pass up memory
		 * allocation oriented ops that we receive - these may be
		 * associated with pseudo HBA drivers below us with target
		 * drivers below them that use ddi memory allocation
		 * interfaces like scsi_alloc_consistent_buf.
		 */
		return (ddi_ctlops(dip, rdip, ctlop, arg, result));
	}
}
Example #14
0
/*ARGSUSED*/
static int
pci_ctlops(dev_info_t *dip, dev_info_t *rdip,
	ddi_ctl_enum_t ctlop, void *arg, void *result)
{
	pci_regspec_t *drv_regp;
	uint_t	reglen;
	int	rn;
	int	totreg;
	pci_state_t *pcip;
	struct  attachspec *asp;

	switch (ctlop) {
	case DDI_CTLOPS_REPORTDEV:
		if (rdip == (dev_info_t *)0)
			return (DDI_FAILURE);
		cmn_err(CE_CONT, "?PCI-device: %s@%s, %s%d\n",
		    ddi_node_name(rdip), ddi_get_name_addr(rdip),
		    ddi_driver_name(rdip),
		    ddi_get_instance(rdip));
		return (DDI_SUCCESS);

	case DDI_CTLOPS_INITCHILD:
		return (pci_initchild((dev_info_t *)arg));

	case DDI_CTLOPS_UNINITCHILD:
		return (pci_removechild((dev_info_t *)arg));

	case DDI_CTLOPS_SIDDEV:
		return (DDI_SUCCESS);

	case DDI_CTLOPS_REGSIZE:
	case DDI_CTLOPS_NREGS:
		if (rdip == (dev_info_t *)0)
			return (DDI_FAILURE);

		*(int *)result = 0;
		if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, rdip,
		    DDI_PROP_DONTPASS, "reg", (int **)&drv_regp,
		    &reglen) != DDI_PROP_SUCCESS) {
			return (DDI_FAILURE);
		}

		totreg = (reglen * sizeof (int)) / sizeof (pci_regspec_t);
		if (ctlop == DDI_CTLOPS_NREGS)
			*(int *)result = totreg;
		else if (ctlop == DDI_CTLOPS_REGSIZE) {
			rn = *(int *)arg;
			if (rn >= totreg) {
				ddi_prop_free(drv_regp);
				return (DDI_FAILURE);
			}
			*(off_t *)result = drv_regp[rn].pci_size_low;
		}
		ddi_prop_free(drv_regp);

		return (DDI_SUCCESS);

	case DDI_CTLOPS_POWER: {
		power_req_t	*reqp = (power_req_t *)arg;
		/*
		 * We currently understand reporting of PCI_PM_IDLESPEED
		 * capability. Everything else is passed up.
		 */
		if ((reqp->request_type == PMR_REPORT_PMCAP) &&
		    (reqp->req.report_pmcap_req.cap ==  PCI_PM_IDLESPEED)) {

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

	case DDI_CTLOPS_PEEK:
	case DDI_CTLOPS_POKE:
		pcip = ddi_get_soft_state(pci_statep, ddi_get_instance(dip));
		return (pci_peekpoke_check(dip, rdip, ctlop, arg, result,
		    pci_common_peekpoke, &pcip->pci_err_mutex,
		    &pcip->pci_peek_poke_mutex, pci_peekpoke_cb));

	/* for now only X86 systems support PME wakeup from suspended state */
	case DDI_CTLOPS_ATTACH:
		asp = (struct attachspec *)arg;
		if (asp->cmd == DDI_RESUME && asp->when == DDI_PRE)
			if (pci_pre_resume(rdip) != DDI_SUCCESS)
				return (DDI_FAILURE);
		return (ddi_ctlops(dip, rdip, ctlop, arg, result));

	case DDI_CTLOPS_DETACH:
		asp = (struct attachspec *)arg;
		if (asp->cmd == DDI_SUSPEND && asp->when == DDI_POST)
			if (pci_post_suspend(rdip) != DDI_SUCCESS)
				return (DDI_FAILURE);
		return (ddi_ctlops(dip, rdip, ctlop, arg, result));

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

	/* NOTREACHED */

}
Example #15
0
/*ARGSUSED*/
static int
ppb_ctlops(dev_info_t *dip, dev_info_t *rdip,
	ddi_ctl_enum_t ctlop, void *arg, void *result)
{
	pci_regspec_t *drv_regp;
	int	reglen;
	int	rn;
	int	totreg;
	ppb_devstate_t *ppb = ddi_get_soft_state(ppb_state,
	    ddi_get_instance(dip));
	struct detachspec *dsp;
	struct attachspec *asp;

	switch (ctlop) {
	case DDI_CTLOPS_REPORTDEV:
		if (rdip == (dev_info_t *)0)
			return (DDI_FAILURE);
		cmn_err(CE_CONT, "?PCI-device: %s@%s, %s%d\n",
		    ddi_node_name(rdip), ddi_get_name_addr(rdip),
		    ddi_driver_name(rdip),
		    ddi_get_instance(rdip));
		return (DDI_SUCCESS);

	case DDI_CTLOPS_INITCHILD:
		return (ppb_initchild((dev_info_t *)arg));

	case DDI_CTLOPS_UNINITCHILD:
		ppb_removechild((dev_info_t *)arg);
		return (DDI_SUCCESS);

	case DDI_CTLOPS_SIDDEV:
		return (DDI_SUCCESS);

	case DDI_CTLOPS_REGSIZE:
	case DDI_CTLOPS_NREGS:
		if (rdip == (dev_info_t *)0)
			return (DDI_FAILURE);
		break;

	/* X86 systems support PME wakeup from suspend */
	case DDI_CTLOPS_ATTACH:
		if (!pcie_is_child(dip, rdip))
			return (DDI_SUCCESS);

		asp = (struct attachspec *)arg;
		if ((ppb->parent_bus == PCIE_PCIECAP_DEV_TYPE_PCIE_DEV) &&
		    (asp->when == DDI_POST) && (asp->result == DDI_SUCCESS))
			pf_init(rdip, (void *)ppb->ppb_fm_ibc, asp->cmd);

		if (asp->cmd == DDI_RESUME && asp->when == DDI_PRE)
			if (pci_pre_resume(rdip) != DDI_SUCCESS)
				return (DDI_FAILURE);

		return (DDI_SUCCESS);

	case DDI_CTLOPS_DETACH:
		if (!pcie_is_child(dip, rdip))
			return (DDI_SUCCESS);

		dsp = (struct detachspec *)arg;
		if ((ppb->parent_bus == PCIE_PCIECAP_DEV_TYPE_PCIE_DEV) &&
		    (dsp->when == DDI_PRE))
			pf_fini(rdip, dsp->cmd);

		if (dsp->cmd == DDI_SUSPEND && dsp->when == DDI_POST)
			if (pci_post_suspend(rdip) != DDI_SUCCESS)
				return (DDI_FAILURE);

		return (DDI_SUCCESS);

	case DDI_CTLOPS_PEEK:
	case DDI_CTLOPS_POKE:
		if (strcmp(ddi_driver_name(ddi_get_parent(dip)), "npe") != 0)
			return (ddi_ctlops(dip, rdip, ctlop, arg, result));
		return (pci_peekpoke_check(dip, rdip, ctlop, arg, result,
		    ddi_ctlops, &ppb->ppb_err_mutex,
		    &ppb->ppb_peek_poke_mutex, ppb_peekpoke_cb));

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

	*(int *)result = 0;
	if (ddi_getlongprop(DDI_DEV_T_ANY, rdip,
	    DDI_PROP_DONTPASS | DDI_PROP_CANSLEEP, "reg",
	    (caddr_t)&drv_regp, &reglen) != DDI_SUCCESS)
		return (DDI_FAILURE);

	totreg = reglen / sizeof (pci_regspec_t);
	if (ctlop == DDI_CTLOPS_NREGS)
		*(int *)result = totreg;
	else if (ctlop == DDI_CTLOPS_REGSIZE) {
		rn = *(int *)arg;
		if (rn >= totreg) {
			kmem_free(drv_regp, reglen);
			return (DDI_FAILURE);
		}
		*(off_t *)result = drv_regp[rn].pci_size_low;
	}

	kmem_free(drv_regp, reglen);
	return (DDI_SUCCESS);
}
Example #16
0
/*
 * control ops entry point:
 *
 * Requests handled completely:
 *	DDI_CTLOPS_INITCHILD
 *	DDI_CTLOPS_UNINITCHILD
 *	DDI_CTLOPS_REPORTDEV
 *	DDI_CTLOPS_REGSIZE
 *	DDI_CTLOPS_NREGS
 *
 * All others passed to parent.
 */
static int
acebus_ctlops(dev_info_t *dip, dev_info_t *rdip,
	ddi_ctl_enum_t op, void *arg, void *result)
{
#ifdef DEBUG
	ebus_devstate_t *ebus_p = get_acebus_soft_state(ddi_get_instance(dip));
#endif
	ebus_regspec_t *ebus_rp;
	int32_t reglen;
	int i, n;
	char name[10];

	switch (op) {
	case DDI_CTLOPS_INITCHILD: {
		dev_info_t *child = (dev_info_t *)arg;
		/*
		 * Set the address portion of the node name based on the
		 * address/offset.
		 */
		DBG2(D_CTLOPS, ebus_p, "DDI_CTLOPS_INITCHILD: rdip=%s%d\n",
		    ddi_get_name(child), ddi_get_instance(child));

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

			DBG(D_CTLOPS, ebus_p, "can't get reg property\n");
			return (DDI_FAILURE);

		}

		(void) sprintf(name, "%x,%x", ebus_rp->addr_hi,
		    ebus_rp->addr_low);
		ddi_set_name_addr(child, name);
		kmem_free((caddr_t)ebus_rp, reglen);

		ddi_set_parent_data(child, NULL);

		return (DDI_SUCCESS);

	}

	case DDI_CTLOPS_UNINITCHILD:
		DBG2(D_CTLOPS, ebus_p, "DDI_CTLOPS_UNINITCHILD: rdip=%s%d\n",
		    ddi_get_name((dev_info_t *)arg),
		    ddi_get_instance((dev_info_t *)arg));
		ddi_set_name_addr((dev_info_t *)arg, NULL);
		ddi_remove_minor_node((dev_info_t *)arg, NULL);
		impl_rem_dev_props((dev_info_t *)arg);
		return (DDI_SUCCESS);

	case DDI_CTLOPS_REPORTDEV:

		DBG2(D_CTLOPS, ebus_p, "DDI_CTLOPS_REPORTDEV: rdip=%s%d\n",
		    ddi_get_name(rdip), ddi_get_instance(rdip));
		cmn_err(CE_CONT, "?%s%d at %s%d: offset %s\n",
		    ddi_driver_name(rdip), ddi_get_instance(rdip),
		    ddi_driver_name(dip), ddi_get_instance(dip),
		    ddi_get_name_addr(rdip));
		return (DDI_SUCCESS);

	case DDI_CTLOPS_REGSIZE:

		DBG2(D_CTLOPS, ebus_p, "DDI_CTLOPS_REGSIZE: rdip=%s%d\n",
		    ddi_get_name(rdip), ddi_get_instance(rdip));
		if (getprop(rdip, "reg", &ebus_rp, &i) != DDI_SUCCESS) {
			DBG(D_CTLOPS, ebus_p, "can't get reg property\n");
			return (DDI_FAILURE);
		}
		n = i / sizeof (ebus_regspec_t);
		if (*(int *)arg < 0 || *(int *)arg >= n) {
			DBG(D_MAP, ebus_p, "rnumber out of range\n");
			kmem_free((caddr_t)ebus_rp, i);
			return (DDI_FAILURE);
		}
		*((off_t *)result) = ebus_rp[*(int *)arg].size;
		kmem_free((caddr_t)ebus_rp, i);
		return (DDI_SUCCESS);

	case DDI_CTLOPS_NREGS:

		DBG2(D_CTLOPS, ebus_p, "DDI_CTLOPS_NREGS: rdip=%s%d\n",
		    ddi_get_name(rdip), ddi_get_instance(rdip));
		if (getprop(rdip, "reg", &ebus_rp, &i) != DDI_SUCCESS) {
			DBG(D_CTLOPS, ebus_p, "can't get reg property\n");
			return (DDI_FAILURE);
		}
		*((uint_t *)result) = i / sizeof (ebus_regspec_t);
		kmem_free((caddr_t)ebus_rp, i);
		return (DDI_SUCCESS);
	}

	/*
	 * Now pass the request up to our parent.
	 */
	DBG2(D_CTLOPS, ebus_p, "passing request to parent: rdip=%s%d\n",
	    ddi_get_name(rdip), ddi_get_instance(rdip));
	return (ddi_ctlops(dip, rdip, op, arg, result));
}
Example #17
0
/*ARGSUSED*/
static int
ppb_ctlops(dev_info_t *dip, dev_info_t *rdip,
	ddi_ctl_enum_t ctlop, void *arg, void *result)
{
	pci_regspec_t *drv_regp;
	int	reglen;
	int	rn;
	struct	attachspec *as;
	struct	detachspec *ds;
	int	totreg;
	ppb_devstate_t *ppb_p;

	ppb_p = (ppb_devstate_t *)ddi_get_soft_state(ppb_state,
	    ddi_get_instance(dip));

	switch (ctlop) {
	case DDI_CTLOPS_REPORTDEV:
		if (rdip == (dev_info_t *)0)
			return (DDI_FAILURE);
		cmn_err(CE_CONT, "?PCI-device: %s@%s, %s%d\n",
		    ddi_node_name(rdip), ddi_get_name_addr(rdip),
		    ddi_driver_name(rdip),
		    ddi_get_instance(rdip));
		return (DDI_SUCCESS);

	case DDI_CTLOPS_INITCHILD:
		return (ppb_initchild((dev_info_t *)arg));

	case DDI_CTLOPS_UNINITCHILD:
		ppb_uninitchild((dev_info_t *)arg);
		return (DDI_SUCCESS);

	case DDI_CTLOPS_ATTACH:
		if (!pcie_is_child(dip, rdip))
			return (DDI_SUCCESS);

		as = (struct attachspec *)arg;
		if ((ppb_p->parent_bus == PCIE_PCIECAP_DEV_TYPE_PCIE_DEV) &&
		    (as->when == DDI_POST) && (as->result == DDI_SUCCESS))
			pf_init(rdip, ppb_p->fm_ibc, as->cmd);

		return (DDI_SUCCESS);

	case DDI_CTLOPS_DETACH:
		if (!pcie_is_child(dip, rdip))
			return (DDI_SUCCESS);

		ds = (struct detachspec *)arg;
		if ((ppb_p->parent_bus == PCIE_PCIECAP_DEV_TYPE_PCIE_DEV) &&
		    (ds->when == DDI_PRE))
			pf_fini(rdip, ds->cmd);

		return (DDI_SUCCESS);

	case DDI_CTLOPS_SIDDEV:
		return (DDI_SUCCESS);

	case DDI_CTLOPS_REGSIZE:
	case DDI_CTLOPS_NREGS:
		if (rdip == (dev_info_t *)0)
			return (DDI_FAILURE);
		break;
	default:
		return (ddi_ctlops(dip, rdip, ctlop, arg, result));
	}

	*(int *)result = 0;
	if (ddi_getlongprop(DDI_DEV_T_ANY, rdip,
	    DDI_PROP_DONTPASS | DDI_PROP_CANSLEEP, "reg",
	    (caddr_t)&drv_regp, &reglen) != DDI_SUCCESS)
		return (DDI_FAILURE);

	totreg = reglen / sizeof (pci_regspec_t);
	if (ctlop == DDI_CTLOPS_NREGS)
		*(int *)result = totreg;
	else if (ctlop == DDI_CTLOPS_REGSIZE) {
		rn = *(int *)arg;
		if (rn >= totreg) {
			kmem_free(drv_regp, reglen);
			return (DDI_FAILURE);
		}
		*(off_t *)result = drv_regp[rn].pci_size_low |
		    ((uint64_t)drv_regp[rn].pci_size_hi << 32);
	}

	kmem_free(drv_regp, reglen);
	return (DDI_SUCCESS);
}
Example #18
0
static int
cnex_ctl(dev_info_t *dip, dev_info_t *rdip, ddi_ctl_enum_t ctlop,
    void *arg, void *result)
{
	char		name[MAXNAMELEN];
	uint32_t	reglen;
	int		*cnex_regspec;

	switch (ctlop) {
	case DDI_CTLOPS_REPORTDEV:
		if (rdip == NULL)
			return (DDI_FAILURE);
		cmn_err(CE_CONT, "?channel-device: %s%d\n",
		    ddi_driver_name(rdip), ddi_get_instance(rdip));
		return (DDI_SUCCESS);

	case DDI_CTLOPS_INITCHILD:
	{
		dev_info_t *child = (dev_info_t *)arg;

		if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, child,
		    DDI_PROP_DONTPASS, "reg",
		    &cnex_regspec, &reglen) != DDI_SUCCESS) {
			return (DDI_FAILURE);
		}

		(void) snprintf(name, sizeof (name), "%x", *cnex_regspec);
		ddi_set_name_addr(child, name);
		ddi_set_parent_data(child, NULL);
		ddi_prop_free(cnex_regspec);
		return (DDI_SUCCESS);
	}

	case DDI_CTLOPS_UNINITCHILD:
	{
		dev_info_t *child = (dev_info_t *)arg;

		NDI_CONFIG_DEBUG((CE_NOTE,
		    "DDI_CTLOPS_UNINITCHILD(%s, instance=%d)",
		    ddi_driver_name(child), DEVI(child)->devi_instance));

		ddi_set_name_addr(child, NULL);

		return (DDI_SUCCESS);
	}

	case DDI_CTLOPS_DMAPMAPC:
	case DDI_CTLOPS_REPORTINT:
	case DDI_CTLOPS_REGSIZE:
	case DDI_CTLOPS_NREGS:
	case DDI_CTLOPS_SIDDEV:
	case DDI_CTLOPS_SLAVEONLY:
	case DDI_CTLOPS_AFFINITY:
	case DDI_CTLOPS_POKE:
	case DDI_CTLOPS_PEEK:
		/*
		 * These ops correspond to functions that "shouldn't" be called
		 * by a channel-device driver.  So we whine when we're called.
		 */
		cmn_err(CE_WARN, "%s%d: invalid op (%d) from %s%d\n",
		    ddi_driver_name(dip), ddi_get_instance(dip), ctlop,
		    ddi_driver_name(rdip), ddi_get_instance(rdip));
		return (DDI_FAILURE);

	case DDI_CTLOPS_ATTACH:
	case DDI_CTLOPS_BTOP:
	case DDI_CTLOPS_BTOPR:
	case DDI_CTLOPS_DETACH:
	case DDI_CTLOPS_DVMAPAGESIZE:
	case DDI_CTLOPS_IOMIN:
	case DDI_CTLOPS_POWER:
	case DDI_CTLOPS_PTOB:
	default:
		/*
		 * Everything else (e.g. PTOB/BTOP/BTOPR requests) we pass up
		 */
		return (ddi_ctlops(dip, rdip, ctlop, arg, result));
	}
}
Example #19
0
/*
 * control ops entry point:
 *
 * Requests handled completely:
 *	DDI_CTLOPS_INITCHILD	see init_child() for details
 *	DDI_CTLOPS_UNINITCHILD
 *	DDI_CTLOPS_REPORTDEV	see report_dev() for details
 *	DDI_CTLOPS_IOMIN	cache line size if streaming otherwise 1
 *	DDI_CTLOPS_REGSIZE
 *	DDI_CTLOPS_NREGS
 *	DDI_CTLOPS_DVMAPAGESIZE
 *	DDI_CTLOPS_POKE
 *	DDI_CTLOPS_PEEK
 *
 * All others passed to parent.
 */
int
px_ctlops(dev_info_t *dip, dev_info_t *rdip,
	ddi_ctl_enum_t op, void *arg, void *result)
{
	px_t *px_p = DIP_TO_STATE(dip);
	struct detachspec *ds;
	struct attachspec *as;

	switch (op) {
	case DDI_CTLOPS_INITCHILD:
		return (px_init_child(px_p, (dev_info_t *)arg));

	case DDI_CTLOPS_UNINITCHILD:
		return (px_uninit_child(px_p, (dev_info_t *)arg));

	case DDI_CTLOPS_ATTACH:
		if (!pcie_is_child(dip, rdip))
			return (DDI_SUCCESS);

		as = (struct attachspec *)arg;
		switch (as->when) {
		case DDI_PRE:
			if (as->cmd == DDI_ATTACH) {
				DBG(DBG_PWR, dip, "PRE_ATTACH for %s@%d\n",
				    ddi_driver_name(rdip),
				    ddi_get_instance(rdip));
				return (pcie_pm_hold(dip));
			}
			if (as->cmd == DDI_RESUME) {
				DBG(DBG_PWR, dip, "PRE_RESUME for %s@%d\n",
				    ddi_driver_name(rdip),
				    ddi_get_instance(rdip));

				pcie_clear_errors(rdip);
			}
			return (DDI_SUCCESS);

		case DDI_POST:
			DBG(DBG_PWR, dip, "POST_ATTACH for %s@%d\n",
			    ddi_driver_name(rdip), ddi_get_instance(rdip));
			if (as->cmd == DDI_ATTACH &&
			    as->result != DDI_SUCCESS) {
				/*
				 * Attach failed for the child device. The child
				 * driver may have made PM calls before the
				 * attach failed. pcie_pm_remove_child() should
				 * cleanup PM state and holds (if any)
				 * associated with the child device.
				 */
				return (pcie_pm_remove_child(dip, rdip));
			}

			if (as->result == DDI_SUCCESS)
				pf_init(rdip, (void *)px_p->px_fm_ibc, as->cmd);

			(void) pcie_postattach_child(rdip);

			return (DDI_SUCCESS);
		default:
			break;
		}
		break;

	case DDI_CTLOPS_DETACH:
		if (!pcie_is_child(dip, rdip))
			return (DDI_SUCCESS);

		ds = (struct detachspec *)arg;
		switch (ds->when) {
		case DDI_POST:
			if (ds->cmd == DDI_DETACH &&
			    ds->result == DDI_SUCCESS) {
				DBG(DBG_PWR, dip, "POST_DETACH for %s@%d\n",
				    ddi_driver_name(rdip),
				    ddi_get_instance(rdip));
				return (pcie_pm_remove_child(dip, rdip));
			}
			return (DDI_SUCCESS);
		case DDI_PRE:
			pf_fini(rdip, ds->cmd);
			return (DDI_SUCCESS);
		default:
			break;
		}
		break;

	case DDI_CTLOPS_REPORTDEV:
		if (ddi_get_parent(rdip) == dip)
			return (px_report_dev(rdip));

		(void) px_lib_fabric_sync(rdip);
		return (DDI_SUCCESS);

	case DDI_CTLOPS_IOMIN:
		return (DDI_SUCCESS);

	case DDI_CTLOPS_REGSIZE:
		*((off_t *)result) = px_get_reg_set_size(rdip, *((int *)arg));
		return (*((off_t *)result) == 0 ? DDI_FAILURE : DDI_SUCCESS);

	case DDI_CTLOPS_NREGS:
		*((uint_t *)result) = px_get_nreg_set(rdip);
		return (DDI_SUCCESS);

	case DDI_CTLOPS_DVMAPAGESIZE:
		*((ulong_t *)result) = MMU_PAGE_SIZE;
		return (DDI_SUCCESS);

	case DDI_CTLOPS_POKE:	/* platform dependent implementation. */
		return (px_lib_ctlops_poke(dip, rdip,
		    (peekpoke_ctlops_t *)arg));

	case DDI_CTLOPS_PEEK:	/* platform dependent implementation. */
		return (px_lib_ctlops_peek(dip, rdip,
		    (peekpoke_ctlops_t *)arg, result));

	case DDI_CTLOPS_POWER:
	default:
		break;
	}

	/*
	 * Now pass the request up to our parent.
	 */
	DBG(DBG_CTLOPS, dip, "passing request to parent: rdip=%s%d\n",
	    ddi_driver_name(rdip), ddi_get_instance(rdip));
	return (ddi_ctlops(dip, rdip, op, arg, result));
}
Example #20
0
/*ARGSUSED*/
static int
isa_ctlops(dev_info_t *dip, dev_info_t *rdip,
	ddi_ctl_enum_t ctlop, void *arg, void *result)
{
	int rn;
	struct ddi_parent_private_data *pdp;

	switch (ctlop) {
	case DDI_CTLOPS_REPORTDEV:
		if (rdip == (dev_info_t *)0)
			return (DDI_FAILURE);
		cmn_err(CE_CONT, "?ISA-device: %s%d\n",
		    ddi_driver_name(rdip), ddi_get_instance(rdip));
		return (DDI_SUCCESS);

	case DDI_CTLOPS_INITCHILD:
		/*
		 * older drivers aren't expecting the "standard" device
		 * node format used by the hardware nodes.  these drivers
		 * only expect their own properties set in their driver.conf
		 * files.  so they tell us not to call them with hardware
		 * nodes by setting the property "ignore-hardware-nodes".
		 */
		if (old_driver((dev_info_t *)arg)) {
			return (DDI_NOT_WELL_FORMED);
		}

		return (isa_initchild((dev_info_t *)arg));

	case DDI_CTLOPS_UNINITCHILD:
		impl_ddi_sunbus_removechild((dev_info_t *)arg);
		return (DDI_SUCCESS);

	case DDI_CTLOPS_SIDDEV:
		if (ndi_dev_is_persistent_node(rdip))
			return (DDI_SUCCESS);
		/*
		 * All ISA devices need to do confirming probes
		 * unless they are PnP ISA.
		 */
		if (is_pnpisa(rdip))
			return (DDI_SUCCESS);
		else
			return (DDI_FAILURE);

	case DDI_CTLOPS_REGSIZE:
	case DDI_CTLOPS_NREGS:
		if (rdip == (dev_info_t *)0)
			return (DDI_FAILURE);

		if ((pdp = ddi_get_parent_data(rdip)) == NULL)
			return (DDI_FAILURE);

		if (ctlop == DDI_CTLOPS_NREGS) {
			*(int *)result = pdp->par_nreg;
		} else {
			rn = *(int *)arg;
			if (rn >= pdp->par_nreg)
				return (DDI_FAILURE);
			*(off_t *)result = (off_t)pdp->par_reg[rn].regspec_size;
		}
		return (DDI_SUCCESS);

	case DDI_CTLOPS_ATTACH:
	case DDI_CTLOPS_DETACH:
	case DDI_CTLOPS_PEEK:
	case DDI_CTLOPS_POKE:
		return (DDI_FAILURE);

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