예제 #1
0
파일: smbios.c 프로젝트: andreiw/polaris
/*ARGSUSED*/
static int
smb_close(dev_t dev, int flag, int otyp, cred_t *cred)
{
	(void) ddi_prop_remove(dev, smb_devi, "size");
	smb_clones[getminor(dev)].c_hdl = NULL;
	return (0);
}
예제 #2
0
/*ARGSUSED*/
int
gfxp_vgatext_detach(dev_info_t *devi, ddi_detach_cmd_t cmd,
	gfxp_vgatext_softc_ptr_t ptr)
{
	struct vgatext_softc *softc = (struct vgatext_softc *)ptr;

	(void) ddi_prop_remove(DDI_DEV_T_ANY, devi, "primary-controller");

	switch (cmd) {

	case DDI_SUSPEND:
		return (vgatext_suspend(softc));
		/* break; */
	case DDI_DETACH:
		if (softc->fb.mapped)
			ddi_regs_map_free(&softc->fb.handle);
		if (softc->regs.mapped)
			ddi_regs_map_free(&softc->regs.handle);
		mutex_destroy(&(softc->lock));
		return (DDI_SUCCESS);

	default:
		cmn_err(CE_WARN, "gfxp_vgatext_detach: unknown cmd 0x%x\n",
		    cmd);
		return (DDI_FAILURE);
	}
}
예제 #3
0
파일: ksyms.c 프로젝트: bahamas10/openzfs
/* ARGSUSED */
static int
ksyms_close(dev_t dev, int flag, int otyp, struct cred *cred)
{
	minor_t clone = getminor(dev);

	(void) as_unmap(curproc->p_as, ksyms_clones[clone].ksyms_base,
	    roundup(ksyms_clones[clone].ksyms_size, PAGESIZE));
	ksyms_clones[clone].ksyms_base = 0;
	modunload_enable();
	(void) ddi_prop_remove(dev, ksyms_devi, "size");
	return (0);
}
예제 #4
0
/*
 * Remove PM state for nexus.
 */
static void
ppb_pwr_teardown(ppb_devstate_t *ppb, dev_info_t *dip)
{
	int low_lvl;

	/*
	 * Determine the lowest power level supported.
	 */
	if (ppb->ppb_pwr_p->pwr_flags & PCI_PWR_B3_CAPABLE) {
		low_lvl = PM_LEVEL_B3;
	} else {
		low_lvl = PM_LEVEL_B2;
	}

	if (pm_lower_power(dip, PCI_PM_COMP_0, low_lvl) != DDI_SUCCESS) {
		cmn_err(CE_WARN, "%s%d failed to lower power",
		    ddi_driver_name(dip), ddi_get_instance(dip));
	}

	pci_config_teardown(&ppb->ppb_conf_hdl);
	mutex_destroy(&ppb->ppb_pwr_p->pwr_mutex);
	kmem_free(ppb->ppb_pwr_p, sizeof (pci_pwr_t));

	if (ddi_prop_remove(DDI_DEV_T_NONE, dip, "pm-components") !=
	    DDI_PROP_SUCCESS) {
		cmn_err(CE_WARN, "%s%d unable to remove prop pm-components",
		    ddi_driver_name(dip), ddi_get_instance(dip));
	}

	if (ddi_prop_remove(DDI_DEV_T_NONE, dip,
	    "pm-want-child-notification?") != DDI_PROP_SUCCESS) {
		cmn_err(CE_WARN,
		    "%s%d unable to remove prop pm-want_child_notification?",
		    ddi_driver_name(dip), ddi_get_instance(dip));
	}
}
예제 #5
0
/*ARGSUSED*/
static int
ppb_detach(dev_info_t *devi, ddi_detach_cmd_t cmd)
{
	ppb_devstate_t *ppb;
	int		ret = DDI_SUCCESS;

	switch (cmd) {
	case DDI_DETACH:
		/*
		 * And finally free the per-pci soft state after
		 * uninitializing hotplug support for this bus.
		 */
		ppb = (ppb_devstate_t *)
		    ddi_get_soft_state(ppb_state, ddi_get_instance(devi));

		ppb_fm_fini(ppb);

		if (ppb->parent_bus == PCIE_PCIECAP_DEV_TYPE_PCIE_DEV)
			ret = pcie_uninit(devi);
		else if (ppb->hotplug_capable == B_TRUE)
			ret = pcihp_init(devi);
		else
			ddi_remove_minor_node(devi, "devctl");

		if (ret != DDI_SUCCESS)
			return (DDI_FAILURE);

		(void) ddi_prop_remove(DDI_DEV_T_NONE, devi, "device_type");

		if (ppb->ppb_pwr_p != NULL) {
			ppb_pwr_teardown(ppb, devi);
		}
		mutex_destroy(&ppb->ppb_mutex);
		ddi_soft_state_free(ppb_state, ddi_get_instance(devi));

		return (DDI_SUCCESS);

	case DDI_SUSPEND:
		ppb = (ppb_devstate_t *)
		    ddi_get_soft_state(ppb_state, ddi_get_instance(devi));

		pci_pwr_suspend(devi, ppb->ppb_pwr_p);

		return (DDI_SUCCESS);
	}
	return (DDI_FAILURE);
}
예제 #6
0
/*ARGSUSED*/
static int
ppb_detach(dev_info_t *devi, ddi_detach_cmd_t cmd)
{
	ppb_devstate_t *ppb;
	int		ret;

	switch (cmd) {
	case DDI_DETACH:
		(void) ddi_prop_remove(DDI_DEV_T_NONE, devi, "device_type");

		ppb = ddi_get_soft_state(ppb_state, ddi_get_instance(devi));
		if (ppb->ppb_fmcap & DDI_FM_ERRCB_CAPABLE)
			ddi_fm_handler_unregister(devi);
		if (ppb->ppb_fmcap & (DDI_FM_ERRCB_CAPABLE |
		    DDI_FM_EREPORT_CAPABLE))
			pci_ereport_teardown(devi);

		/*
		 * Uninitialize hotplug support on this bus.
		 */
		ret = (ppb->parent_bus == PCIE_PCIECAP_DEV_TYPE_PCIE_DEV) ?
		    pcie_uninit(devi) : pcihp_uninit(devi);
		if (ret != DDI_SUCCESS)
			return (DDI_FAILURE);

		mutex_destroy(&ppb->ppb_peek_poke_mutex);
		mutex_destroy(&ppb->ppb_err_mutex);
		mutex_destroy(&ppb->ppb_mutex);
		ddi_fm_fini(devi);

		/*
		 * And finally free the per-pci soft state.
		 */
		ddi_soft_state_free(ppb_state, ddi_get_instance(devi));

		return (DDI_SUCCESS);

	case DDI_SUSPEND:
		ppb = ddi_get_soft_state(ppb_state, ddi_get_instance(devi));
		ppb_save_config_regs(ppb);
		return (DDI_SUCCESS);

	default:
		break;
	}
	return (DDI_FAILURE);
}
예제 #7
0
/*
 * Save the configuration registers for cdip as a property
 * so that it persists after detach/uninitchild.
 */
int
pci_save_config_regs(dev_info_t *dip)
{
	ddi_acc_handle_t confhdl;
	pci_config_header_state_t *chsp;
	pci_cap_save_desc_t *pci_cap_descp;
	int ret;
	uint32_t i, ncaps, nwords;
	uint32_t *regbuf, *p;
	uint8_t *maskbuf;
	size_t maskbufsz, regbufsz, capbufsz;
	ddi_acc_hdl_t *hp;
	off_t offset = 0;
	uint8_t cap_ptr, cap_id;
	int pcie = 0;
	PMD(PMD_SX, ("pci_save_config_regs %s:%d\n", ddi_driver_name(dip),
	    ddi_get_instance(dip)))

	if (pci_config_setup(dip, &confhdl) != DDI_SUCCESS) {
		cmn_err(CE_WARN, "%s%d can't get config handle",
		    ddi_driver_name(dip), ddi_get_instance(dip));

		return (DDI_FAILURE);
	}
	/*
	 * Determine if it is a pci express device. If it is, save entire
	 * 4k config space treating it as a array of 32 bit integers.
	 * If it is not, do it in a usual PCI way.
	 */
	cap_ptr = pci_config_get8(confhdl, PCI_BCNF_CAP_PTR);
	/*
	 * Walk the capabilities searching for pci express capability
	 */
	while (cap_ptr != PCI_CAP_NEXT_PTR_NULL) {
		cap_id = pci_config_get8(confhdl,
		    cap_ptr + PCI_CAP_ID);
		if (cap_id == PCI_CAP_ID_PCI_E) {
			pcie = 1;
			break;
		}
		cap_ptr = pci_config_get8(confhdl,
		    cap_ptr + PCI_CAP_NEXT_PTR);
	}

	if (pcie) {
		/* PCI express device. Can have data in all 4k space */
		regbuf = (uint32_t *)kmem_zalloc((size_t)PCIE_CONF_HDR_SIZE,
		    KM_SLEEP);
		p = regbuf;
		/*
		 * Allocate space for mask.
		 * mask size is 128 bytes (4096 / 4 / 8 )
		 */
		maskbufsz = (size_t)((PCIE_CONF_HDR_SIZE/ sizeof (uint32_t)) >>
		    INDEX_SHIFT);
		maskbuf = (uint8_t *)kmem_zalloc(maskbufsz, KM_SLEEP);
		hp = impl_acc_hdl_get(confhdl);
		for (i = 0; i < (PCIE_CONF_HDR_SIZE / sizeof (uint32_t)); i++) {
			if (ddi_peek32(dip, (int32_t *)(hp->ah_addr + offset),
			    (int32_t *)p) == DDI_SUCCESS) {
				/* it is readable register. set the bit */
				maskbuf[i >> INDEX_SHIFT] |=
				    (uint8_t)(1 << (i & BITMASK));
			}
			p++;
			offset += sizeof (uint32_t);
		}

		if ((ret = ndi_prop_update_byte_array(DDI_DEV_T_NONE, dip,
		    SAVED_CONFIG_REGS_MASK, (uchar_t *)maskbuf,
		    maskbufsz)) != DDI_PROP_SUCCESS) {
			cmn_err(CE_WARN, "couldn't create %s property while"
			    "saving config space for %s@%d\n",
			    SAVED_CONFIG_REGS_MASK, ddi_driver_name(dip),
			    ddi_get_instance(dip));
		} else if ((ret = ndi_prop_update_byte_array(DDI_DEV_T_NONE,
		    dip, SAVED_CONFIG_REGS, (uchar_t *)regbuf,
		    (size_t)PCIE_CONF_HDR_SIZE)) != DDI_PROP_SUCCESS) {
			(void) ddi_prop_remove(DDI_DEV_T_NONE, dip,
			    SAVED_CONFIG_REGS_MASK);
			cmn_err(CE_WARN, "%s%d can't update prop %s",
			    ddi_driver_name(dip), ddi_get_instance(dip),
			    SAVED_CONFIG_REGS);
		}

		kmem_free(maskbuf, (size_t)maskbufsz);
		kmem_free(regbuf, (size_t)PCIE_CONF_HDR_SIZE);
	} else {
예제 #8
0
/*
 * If bridge is PM capable, set up PM state for nexus.
 */
static void
ppb_pwr_setup(ppb_devstate_t *ppb, dev_info_t *pdip)
{
	char *comp_array[5];
	int i;
	ddi_acc_handle_t conf_hdl;
	uint8_t pmcsr_bse;
	uint16_t pmcap;

	/*
	 * Determine if bridge is PM capable.  If not, leave ppb_pwr_p NULL
	 * and return.
	 */
	if (pci_config_setup(pdip, &ppb->ppb_conf_hdl) != DDI_SUCCESS) {

		return;
	}

	conf_hdl = ppb->ppb_conf_hdl;

	/*
	 * Locate and store the power management cap_ptr for future references.
	 */
	if ((PCI_CAP_LOCATE(conf_hdl, PCI_CAP_ID_PM, &ppb->ppb_pm_cap_ptr))
	    == DDI_FAILURE) {
		DEBUG0(DBG_PWR, pdip, "bridge does not support PM. PCI"
		    " PM data structure not found in config header\n");
		pci_config_teardown(&conf_hdl);

		return;
	}

	/*
	 * Allocate PM state structure for ppb.
	 */
	ppb->ppb_pwr_p = (pci_pwr_t *)
	    kmem_zalloc(sizeof (pci_pwr_t), KM_SLEEP);
	ppb->ppb_pwr_p->pwr_fp = 0;

	pmcsr_bse = PCI_CAP_GET8(conf_hdl, NULL, ppb->ppb_pm_cap_ptr,
	    PCI_PMCSR_BSE);

	pmcap = PCI_CAP_GET16(conf_hdl, NULL, ppb->ppb_pm_cap_ptr,
	    PCI_PMCAP);

	if (pmcap == PCI_CAP_EINVAL16 || pmcsr_bse == PCI_CAP_EINVAL8) {
		pci_config_teardown(&conf_hdl);
		return;
	}

	if (pmcap & PCI_PMCAP_D1) {
		DEBUG0(DBG_PWR, pdip, "setup: B1 state supported\n");
		ppb->ppb_pwr_p->pwr_flags |= PCI_PWR_B1_CAPABLE;
	} else {
		DEBUG0(DBG_PWR, pdip, "setup: B1 state NOT supported\n");
	}
	if (pmcap & PCI_PMCAP_D2) {
		DEBUG0(DBG_PWR, pdip, "setup: B2 state supported\n");
		ppb->ppb_pwr_p->pwr_flags |= PCI_PWR_B2_CAPABLE;
	} else {
		DEBUG0(DBG_PWR, pdip, "setup: B2 via D2 NOT supported\n");
	}

	if (pmcsr_bse & PCI_PMCSR_BSE_BPCC_EN) {
		DEBUG0(DBG_PWR, pdip,
		"setup: bridge power/clock control enable\n");
	} else {
		DEBUG0(DBG_PWR, pdip,
		"setup: bridge power/clock control disabled\n");

		kmem_free(ppb->ppb_pwr_p, sizeof (pci_pwr_t));
		ppb->ppb_pwr_p = NULL;
		pci_config_teardown(&conf_hdl);

		return;
	}

	/*
	 * PCI states D0 and D3 always are supported for normal PCI
	 * devices.  D1 and D2 are optional which are checked for above.
	 * Bridge function states D0-D3 correspond to secondary bus states
	 * B0-B3, EXCEPT if PCI_PMCSR_BSE_B2_B3 is set.  In this case, setting
	 * the bridge function to D3 will set the bridge bus to state B2 instead
	 * of B3.  D2 will not correspond to B2 (and in fact, probably
	 * won't be D2 capable).  Implicitly, this means that if
	 * PCI_PMCSR_BSE_B2_B3 is set, the bus will not be B3 capable.
	 */
	if (pmcsr_bse & PCI_PMCSR_BSE_B2_B3) {
		ppb->ppb_pwr_p->pwr_flags |= PCI_PWR_B2_CAPABLE;
		DEBUG0(DBG_PWR, pdip, "B2 supported via D3\n");
	} else {
		ppb->ppb_pwr_p->pwr_flags |= PCI_PWR_B3_CAPABLE;
		DEBUG0(DBG_PWR, pdip, "B3 supported via D3\n");
	}

	ppb->ppb_pwr_p->pwr_dip = pdip;
	mutex_init(&ppb->ppb_pwr_p->pwr_mutex, NULL, MUTEX_DRIVER, NULL);

	i = 0;
	comp_array[i++] = "NAME=PCI bridge PM";
	if (ppb->ppb_pwr_p->pwr_flags & PCI_PWR_B3_CAPABLE) {
		comp_array[i++] = "0=Clock/Power Off (B3)";
	}
	if (ppb->ppb_pwr_p->pwr_flags & PCI_PWR_B2_CAPABLE) {
		comp_array[i++] = "1=Clock Off (B2)";
	}
	if (ppb->ppb_pwr_p->pwr_flags & PCI_PWR_B1_CAPABLE) {
		comp_array[i++] = "2=Bus Inactive (B1)";
	}
	comp_array[i++] = "3=Full Power (B0)";

	/*
	 * Create pm-components property. It does not already exist.
	 */
	if (ddi_prop_update_string_array(DDI_DEV_T_NONE, pdip,
	    "pm-components", comp_array, i) != DDI_PROP_SUCCESS) {
		cmn_err(CE_WARN,
		    "%s%d pm-components prop update failed",
		    ddi_driver_name(pdip), ddi_get_instance(pdip));
		pci_config_teardown(&conf_hdl);
		mutex_destroy(&ppb->ppb_pwr_p->pwr_mutex);
		kmem_free(ppb->ppb_pwr_p, sizeof (pci_pwr_t));
		ppb->ppb_pwr_p = NULL;

		return;
	}

	if (ddi_prop_create(DDI_DEV_T_NONE, pdip, DDI_PROP_CANSLEEP,
	    "pm-want-child-notification?", NULL, NULL) != DDI_PROP_SUCCESS) {
		cmn_err(CE_WARN,
		    "%s%d fail to create pm-want-child-notification? prop",
		    ddi_driver_name(pdip), ddi_get_instance(pdip));

		(void) ddi_prop_remove(DDI_DEV_T_NONE, pdip, "pm-components");
		pci_config_teardown(&conf_hdl);
		mutex_destroy(&ppb->ppb_pwr_p->pwr_mutex);
		kmem_free(ppb->ppb_pwr_p, sizeof (pci_pwr_t));
		ppb->ppb_pwr_p = NULL;

		return;
	}

	ppb->ppb_pwr_p->current_lvl =
	    pci_pwr_current_lvl(ppb->ppb_pwr_p);
}
예제 #9
0
static int
ds1287_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
{
	struct ds1287 *softsp;

	DPRINTF("ds1287_attach\n");
	switch (cmd) {
	case DDI_ATTACH:
		break;
	case DDI_RESUME:
		return (DDI_SUCCESS);
	default:
		return (DDI_FAILURE);
	}

	if (instance != -1) {
		cmn_err(CE_WARN, "ds1287_attach: Another instance is already "
		    "attached.");
		return (DDI_FAILURE);
	}

	instance = ddi_get_instance(dip);

	if (v_rtc_addr_reg == NULL) {
		cmn_err(CE_WARN, "ds1287_attach: v_rtc_addr_reg is NULL");
		return (DDI_FAILURE);
	}

	/*
	 * Allocate softc information.
	 */
	if (ddi_soft_state_zalloc(ds1287_state, instance) != DDI_SUCCESS) {
		cmn_err(CE_WARN, "ds1287_attach: Failed to allocate "
		    "soft states.");
		return (DDI_FAILURE);
	}

	softsp = ddi_get_soft_state(ds1287_state, instance);
	DPRINTF("ds1287_attach: instance=%d softsp=0x%p\n", instance,
	    (void *)softsp);

	softsp->dip = dip;

	if (ddi_prop_create(DDI_DEV_T_NONE, dip, DDI_PROP_CANSLEEP,
	    "interrupt-priorities", (caddr_t)&ds1287_interrupt_priority,
	    sizeof (int)) != DDI_PROP_SUCCESS) {
		cmn_err(CE_WARN, "ds1287_attach: Failed to create \""
		    "interrupt-priorities\" property.");
		goto error;
	}

	/* add the softint */
	ds1287_lo_iblock = (ddi_iblock_cookie_t)(uintptr_t)
	    ipltospl(ds1287_softint_priority);

	if (ddi_add_softintr(dip, DDI_SOFTINT_FIXED, &ds1287_softintr_id,
	    &ds1287_lo_iblock, NULL, ds1287_softintr, (caddr_t)softsp) !=
	    DDI_SUCCESS) {
		cmn_err(CE_WARN, "ds1287_attach: Failed to add low interrupt.");
		goto error1;
	}

	/* add the hi interrupt */
	if (ddi_add_intr(dip, 0, NULL, (ddi_idevice_cookie_t *)
	    &ds1287_hi_iblock, ds1287_intr, NULL) != DDI_SUCCESS) {
		cmn_err(CE_WARN, "ds1287_attach: Failed to add high "
		    "interrupt.");
		goto error2;
	}

	/*
	 * Combination of instance number and clone number 0 is used for
	 * creating the minor node.
	 */
	if (ddi_create_minor_node(dip, "power_button", S_IFCHR,
	    (instance << 8) + 0, "ddi_power_button", NULL) == DDI_FAILURE) {
		cmn_err(CE_WARN, "ds1287_attach: Failed to create minor node");
		goto error3;
	}

	ddi_report_dev(dip);

	return (DDI_SUCCESS);

error3:
	ddi_remove_intr(dip, 0, NULL);
error2:
	ddi_remove_softintr(ds1287_softintr_id);
error1:
	(void) ddi_prop_remove(DDI_DEV_T_NONE, dip, "interrupt-priorities");
error:
	ddi_soft_state_free(ds1287_state, instance);
	return (DDI_FAILURE);
}