static int
pca9556_close(dev_t dev, int flags, int otyp, cred_t *credp)
{
	int		instance;
	pca9556_unit_t 	*pcap;

	_NOTE(ARGUNUSED(flags, credp))

	/*
	 * Make sure the close is for the right file type
	 */
	if (otyp != OTYP_CHR)
		return (EINVAL);

	instance = MINOR_TO_INST(getminor(dev));

	pcap = (pca9556_unit_t *)
	    ddi_get_soft_state(pca9556_soft_statep, instance);
	if (pcap == NULL)
		return (ENXIO);

	mutex_enter(&pcap->pca9556_mutex);
	pcap->pca9556_oflag = 0;
	mutex_exit(&pcap->pca9556_mutex);
	return (0);
}
Exemple #2
0
/* ARGSUSED */
static int
tcli_info(dev_info_t *dip, ddi_info_cmd_t infocmd, void *arg, void **result)
{
	dev_t	dev;
	int	instance;

	if (infocmd != DDI_INFO_DEVT2INSTANCE)
		return (DDI_FAILURE);

	dev = (dev_t)arg;
	instance = MINOR_TO_INST(getminor(dev));
	*result = (void *)(uintptr_t)instance;
	return (DDI_SUCCESS);
}
Exemple #3
0
/*ARGSUSED*/
static int
tcli_ioctl(dev_t dev, int cmd, intptr_t arg, int mode, cred_t *credp,
    int *rvalp)
{
	struct dstate *dstatep;
	int instance;

	instance = MINOR_TO_INST(getminor(dev));
	dstatep = ddi_get_soft_state(dstates, instance);

	if (dstatep == NULL)
		return (ENXIO);

	return (0);
}
Exemple #4
0
/*ARGSUSED*/
static int
gen_close(dev_t dev, int flag, int otyp, cred_t *cred)
{
	struct dstate *dstatep;
	minor_t minor = getminor(dev);

	if (otyp != OTYP_BLK && otyp != OTYP_CHR)
		return (EINVAL);

	dstatep = ddi_get_soft_state(dstates, MINOR_TO_INST(minor));

	if (dstatep == NULL)
		return (ENXIO);

	mutex_enter(&dstatep->lock);
	dstatep->flag &= ~OPEN_FLAG;
	mutex_exit(&dstatep->lock);

	GEN_DEBUG((CE_CONT,
	    "%s%d close",
	    dstatep->nodename, MINOR_TO_INST(minor)));

	return (0);
}
Exemple #5
0
/*ARGSUSED*/
static int
gen_open(dev_t *devp, int flag, int otyp, cred_t *cred)
{
	minor_t minor;
	struct dstate *dstatep;

	if (otyp != OTYP_BLK && otyp != OTYP_CHR)
		return (EINVAL);

	minor = getminor(*devp);
	if ((dstatep = ddi_get_soft_state(dstates,
	    MINOR_TO_INST(minor))) == NULL)
		return (ENXIO);

	mutex_enter(&dstatep->lock);
	dstatep->flag |= OPEN_FLAG;
	mutex_exit(&dstatep->lock);

	GEN_DEBUG((CE_CONT,
	    "%s%d open",
	    dstatep->nodename, MINOR_TO_INST(minor)));

	return (0);
}
Exemple #6
0
/*ARGSUSED*/
static int
tcli_close(dev_t dev, int flag, int otyp, cred_t *cred)
{
	struct dstate *dstatep;
	minor_t minor = getminor(dev);

	if (otyp != OTYP_BLK && otyp != OTYP_CHR)
		return (EINVAL);

	dstatep = ddi_get_soft_state(dstates, MINOR_TO_INST(minor));

	if (dstatep == NULL)
		return (ENXIO);

	dstatep->oflag = 0;

	return (0);
}
Exemple #7
0
/*ARGSUSED*/
static int
tcli_open(dev_t *devp, int flag, int otyp, cred_t *cred)
{
	minor_t minor;
	struct dstate *dstatep;

	if (otyp != OTYP_BLK && otyp != OTYP_CHR)
		return (EINVAL);

	minor = getminor(*devp);
	if ((dstatep = ddi_get_soft_state(dstates,
	    MINOR_TO_INST(minor))) == NULL)
		return (ENXIO);

	dstatep->oflag = 1;

	return (0);
}
static int
pca9556_open(dev_t *devp, int flags, int otyp, cred_t *credp)
{
	int			instance;
	pca9556_unit_t		*pcap;
	int			err = EBUSY;

	/*
	 * Make sure the open is for the right file type
	 */
	if (otyp != OTYP_CHR)
		return (EINVAL);

	instance = MINOR_TO_INST(getminor(*devp));

	pcap = (pca9556_unit_t *)
	    ddi_get_soft_state(pca9556_soft_statep, instance);
	if (pcap == NULL)
		return (ENXIO);

	/* must be privileged to access this device */
	if (drv_priv(credp) != 0)
		return (EPERM);

	/*
	 * Enforce exclusive access if required
	 */
	mutex_enter(&pcap->pca9556_mutex);
	if (flags & FEXCL) {
		if (pcap->pca9556_oflag == 0) {
			pcap->pca9556_oflag = FEXCL;
			err = DDI_SUCCESS;
		}
	} else if (pcap->pca9556_oflag != FEXCL) {
		pcap->pca9556_oflag = (uint16_t)FOPEN;
		err = DDI_SUCCESS;
	}
	mutex_exit(&pcap->pca9556_mutex);
	return (err);
}
static int
pca9556_info(dev_info_t *dip, ddi_info_cmd_t cmd, void *arg, void **result)
{
	_NOTE(ARGUNUSED(dip))

	pca9556_unit_t	*pcap;
	int		instance = MINOR_TO_INST(getminor((dev_t)arg));

	switch (cmd) {
	case DDI_INFO_DEVT2DEVINFO:
		pcap = ddi_get_soft_state(pca9556_soft_statep, instance);
		if (pcap == NULL)
			return (DDI_FAILURE);
		*result = (void *)pcap->pca9556_dip;
		return (DDI_SUCCESS);
	case DDI_INFO_DEVT2INSTANCE:
		*result = (void *)(uintptr_t)instance;
		return (DDI_SUCCESS);
	default:
		return (DDI_FAILURE);
	}
}
static int
pca9556_ioctl(dev_t dev, int cmd, intptr_t arg, int mode, cred_t *credp,
	int *rvalp)
{
	pca9556_unit_t		*pcap;
	int			err = 0;
	int			instance = MINOR_TO_INST(getminor(dev));
	int			port;
	i2c_gpio_t		g_buf;
	uchar_t			temp;
	boolean_t		write_io = B_FALSE;

	_NOTE(ARGUNUSED(credp, rvalp))

	pcap = (pca9556_unit_t *)
	    ddi_get_soft_state(pca9556_soft_statep, instance);

	if (pcap->pca9555_device) {
		port =  MINOR_TO_PORT(getminor(dev));
	}
	if (pca9556_debug) {
		prom_printf("pca9556_ioctl: instance=%d\n", instance);
	}

	/*
	 * We serialize here and  block any pending transacations.
	 */
	mutex_enter(&pcap->pca9556_mutex);
	while ((pcap->pca9556_flags & PCA9556_BUSYFLAG) == PCA9556_BUSYFLAG) {
		if (cv_wait_sig(&pcap->pca9556_cv,
		    &pcap->pca9556_mutex) <= 0) {
			mutex_exit(&pcap->pca9556_mutex);
			return (EINTR);
		}
	}
	pcap->pca9556_flags |= PCA9556_BUSYFLAG;
	mutex_exit(&pcap->pca9556_mutex);
	if (ddi_copyin((caddr_t)arg, &g_buf,
	    sizeof (i2c_gpio_t), mode) != DDI_SUCCESS) {

		err = EFAULT;

		goto cleanup;
	}
	pcap->pca9556_transfer->i2c_flags = I2C_WR_RD;
	pcap->pca9556_transfer->i2c_wlen = 1;
	pcap->pca9556_transfer->i2c_rlen = 1;

	/*
	 * Evaluate which register is to be read or modified
	 */

	switch (cmd) {
	case GPIO_GET_INPUT:
		if (pcap->pca9555_device)
			pcap->pca9556_transfer->i2c_wbuf[0] =
			    PCA9555_INPUT_REG + port;
		else
			pcap->pca9556_transfer->i2c_wbuf[0] =
			    PCA9556_INPUT_REG;
		break;

	case GPIO_SET_OUTPUT:
		write_io = B_TRUE;
		/*FALLTHROUGH*/

	case GPIO_GET_OUTPUT:
		if (pcap->pca9555_device)
			pcap->pca9556_transfer->i2c_wbuf[0] =
			    PCA9555_OUTPUT_REG + port;
		else
			pcap->pca9556_transfer->i2c_wbuf[0] =
			    PCA9556_OUTPUT_REG;
		break;

	case GPIO_SET_POLARITY:
		write_io = B_TRUE;
		/*FALLTHROUGH*/

	case GPIO_GET_POLARITY:
		if (pcap->pca9555_device)
			pcap->pca9556_transfer->i2c_wbuf[0] =
			    PCA9555_POLARITY_REG + port;
		else
			pcap->pca9556_transfer->i2c_wbuf[0] =
			    PCA9556_POLARITY_REG;
		break;

	case GPIO_SET_CONFIG:
		write_io = B_TRUE;
		/*FALLTHROUGH*/

	case GPIO_GET_CONFIG:
		if (pcap->pca9555_device)
			pcap->pca9556_transfer->i2c_wbuf[0] =
			    PCA9555_CONFIG_REG + port;
		else
			pcap->pca9556_transfer->i2c_wbuf[0] =
			    PCA9556_CONFIG_REG;
		break;
	}

	/*
	 * Read the required register
	 */
	if (i2c_transfer(pcap->pca9556_hdl, pcap->pca9556_transfer)
	    != I2C_SUCCESS) {
		err = EIO;

		goto cleanup;
	}
	/*
	 * Evaluate whether the register is to be read or modified
	 */
	if (!write_io) {
		g_buf.reg_val = g_buf.reg_mask &
		    pcap->pca9556_transfer->i2c_rbuf[0];
		err = ddi_copyout(&g_buf, (caddr_t)arg,
		    sizeof (i2c_gpio_t), mode);
	} else {
		pcap->pca9556_transfer->i2c_flags = I2C_WR;
		pcap->pca9556_transfer->i2c_wlen = 2;
		pcap->pca9556_transfer->i2c_rlen = 0;

		/*
		 * Modify register without overwriting existing contents
		 */

		temp = pcap->pca9556_transfer->i2c_rbuf[0] & (~g_buf.reg_mask);
		pcap->pca9556_transfer->i2c_wbuf[1] = temp|
		    (g_buf.reg_val & g_buf.reg_mask);
		if (i2c_transfer(pcap->pca9556_hdl, pcap->pca9556_transfer)
		    != I2C_SUCCESS) {
				err = EIO;
		}

	}
cleanup:
	mutex_enter(&pcap->pca9556_mutex);
	pcap->pca9556_flags  = pcap->pca9556_flags & ~PCA9556_BUSYFLAG;
	cv_signal(&pcap->pca9556_cv);
	mutex_exit(&pcap->pca9556_mutex);
	return (err);
	}
Exemple #11
0
/*ARGSUSED*/
static int
gen_ioctl(dev_t dev, int cmd, intptr_t arg, int mode, cred_t *credp, int *rvalp)
{
	struct dstate *dstatep;
	ddi_eventcookie_t cookie;
	int instance;
	int rval = 0;
	char *nodename;
	int i;
	struct devctl_iocdata *dcp;
	uint_t state;
	int ret;
	int level_tmp;

	instance = MINOR_TO_INST(getminor(dev));
	dstatep = ddi_get_soft_state(dstates, instance);
	nodename = dstatep->nodename;

	if (dstatep == NULL)
		return (ENXIO);

	/*
	 * read devctl ioctl data
	 */
	if (ndi_dc_allochdl((void *)arg, &dcp) != NDI_SUCCESS)
		return (EFAULT);

	switch (cmd) {
	case GENDRV_IOFAULT_SIMULATE:
		if (ddi_get_eventcookie(dstatep->dip, DDI_DEVI_FAULT_EVENT,
			    &(cookie)) != NDI_SUCCESS)
			return (DDI_FAILURE);

		return (ndi_post_event(dstatep->dip, dstatep->dip, cookie,
			    NULL));

	case GENDRV_NDI_EVENT_TEST:
		if (ddi_get_eventcookie(dstatep->dip, "pshot_dev_offline",
		    &cookie) == NDI_SUCCESS) {
			(void) ndi_post_event(dstatep->dip, dstatep->dip,
			    cookie, NULL);
		}

		if (ddi_get_eventcookie(dstatep->dip, "pshot_dev_reset",
		    &cookie) == NDI_SUCCESS) {
			(void) ndi_post_event(dstatep->dip, dstatep->dip,
			    cookie, NULL);
		}

		if (ddi_get_eventcookie(dstatep->dip, "pshot_bus_reset",
		    &cookie) == NDI_SUCCESS) {
			(void) ndi_post_event(dstatep->dip, dstatep->dip,
			    cookie, NULL);
		}

		if (ddi_get_eventcookie(dstatep->dip, "pshot_bus_quiesce",
		    &cookie) == NDI_SUCCESS) {
			(void) ndi_post_event(dstatep->dip, dstatep->dip,
			    cookie, NULL);
		}

		if (ddi_get_eventcookie(dstatep->dip, "pshot_bus_unquiesce",
		    &cookie) == NDI_SUCCESS) {
			(void) ndi_post_event(dstatep->dip, dstatep->dip,
			    cookie, NULL);
		}

		if (ddi_get_eventcookie(dstatep->dip, "pshot_bus_test_post",
		    &cookie) == NDI_SUCCESS) {
			(void) ndi_post_event(dstatep->dip, dstatep->dip,
			    cookie, NULL);
		}

		break;

	case DEVCTL_PM_PWR_HAS_CHANGED_ON_RESUME:
		/*
		 * Issue pm_power_has_changed() call on DDI_RESUME
		 */
		mutex_enter(&dstatep->lock);
		dstatep->flag |= PWR_HAS_CHANGED_ON_RESUME_FLAG;
		mutex_exit(&dstatep->lock);
		GEN_DEBUG((CE_CONT, "%s%d:"
		    " DEVCTL_PM_PWR_HAS_CHANGED_ON_RESUME", nodename,
		    instance));

		break;

	case DEVCTL_PM_FAIL_SUSPEND:
		/*
		 * Fail the suspend attempt in DDI_SUSPEND
		 */
		mutex_enter(&dstatep->lock);
		dstatep->flag |= FAIL_SUSPEND_FLAG;
		mutex_exit(&dstatep->lock);
		GEN_DEBUG((CE_CONT, "%s%d: DEVCTL_PM_FAIL_SUSPEND",
		    nodename, instance));

		break;

	case DEVCTL_PM_PUP_WITH_PWR_HAS_CHANGED:
		/*
		 * Use pm_power_has_changed() to power up comp 0 when
		 * enforcing the comp 0 vs comp-not 0 dependency:
		 * Power up comp 0 first, if request for comp-not-0
		 * comes in.
		 * Else, default to pm_raise_power().
		 */
		mutex_enter(&dstatep->lock);
		dstatep->flag |= PUP_WITH_PWR_HAS_CHANGED_FLAG;
		mutex_exit(&dstatep->lock);
		GEN_DEBUG((CE_CONT, "%s%d: DEVCTL_PM_PUP_WITH_PWR_HAS_CHANGED",
		    nodename, instance));

		break;

	case DEVCTL_PM_BUSY_COMP:
		/*
		 * mark component 0 busy via a pm_busy_component() call.
		 * update the busy[] array.
		 */
		mutex_enter(&dstatep->lock);
		++dstatep->busy[0];
		GEN_DEBUG((CE_CONT, "%s%d: DEVCTL_PM_BUSY_COMP: comp 0:"
		    " busy=%d", nodename, instance, dstatep->busy[0]));
		mutex_exit(&dstatep->lock);
		ret = pm_busy_component(dstatep->dip, 0);
		ASSERT(ret == DDI_SUCCESS);

		break;

	case DEVCTL_PM_BUSY_COMP_TEST:
		/*
		 * test busy state on component 0
		 */
		mutex_enter(&dstatep->lock);
		state = dstatep->busy[0];
		if (copyout(&state, dcp->cpyout_buf,
		    sizeof (uint_t)) != 0) {
			cmn_err(CE_WARN, "%s%d:"
			    " DEVCTL_PM_BUSY_COMP_TEST: copyout failed\n",
			    nodename, instance);
			rval = EINVAL;
		}
		GEN_DEBUG((CE_CONT, "%s%d: DEVCTL_PM_BUSY_COMP_TEST:"
		    " comp 0 busy %d",
		    nodename, instance, state));
		mutex_exit(&dstatep->lock);

		break;

	case DEVCTL_PM_IDLE_COMP:
		/*
		 * mark component 0 idle via a pm_idle_component() call.
		 * NOP if dstatep->busy[0] == 0.
		 */
		mutex_enter(&dstatep->lock);
		if (dstatep->busy[0] > 0) {
			--dstatep->busy[0];
			GEN_DEBUG((CE_CONT, "%s%d: DEVCTL_PM_IDLE_COMP:"
			    " comp 0: busy=%d", nodename, instance,
			    dstatep->busy[0]));
			mutex_exit(&dstatep->lock);
			ret = pm_idle_component(dstatep->dip, 0);
			ASSERT(ret == DDI_SUCCESS);
		} else {
			mutex_exit(&dstatep->lock);
		}

		break;

	case DEVCTL_PM_PROM_PRINTF:
		(void) prom_printf("%s%d: PROM_PRINTF FROM GEN_DRV\n",
		    nodename, instance);

		break;

	case DEVCTL_PM_RAISE_PWR:
		/*
		 * power up both components to MAXPWR via
		 * pm_raise_power() calls. this ioctl() cmd
		 * assumes that the current level is 0
		 */
		for (i = 0; i < COMPONENTS; i++) {
			GEN_DEBUG((CE_CONT, "%s%d: DEVCTL_PM_RAISE_PWR:"
			    " comp %d old 0 new %d",
			    nodename, instance, i, maxpwr[i]));
			if (pm_raise_power(dstatep->dip, 0, maxpwr[i])
			    != DDI_SUCCESS) {
				rval = EINVAL;
			}
		}

		break;

	case DEVCTL_PM_CHANGE_PWR_LOW:
		/*
		 * power off both components via pm_power_has_changed() calls
		 */
		for (i = (COMPONENTS - 1); i >= 0; --i) {
			GEN_DEBUG((CE_CONT, "%s%d: DEVCTL_PM_CHANGE_PWR_LOW:"
			    " comp %d new 0",
			    nodename, instance, i));
			mutex_enter(&dstatep->lock);
			level_tmp = dstatep->level[i];
			dstatep->level[i] = 0;
			if (pm_power_has_changed(dstatep->dip, i, 0)
			    != DDI_SUCCESS) {
				dstatep->level[i] = level_tmp;
				rval = EINVAL;
			}
			mutex_exit(&dstatep->lock);
		}

		break;

	case DEVCTL_PM_CHANGE_PWR_HIGH:
		/*
		 * power up both components to MAXPWR via
		 * pm_power_has_changed() calls
		 */
		for (i = 0; i < COMPONENTS; i++) {
			GEN_DEBUG((CE_CONT, "%s%d: DEVCTL_PM_CHANGE_PWR_HIGH:"
			    " comp %d new %d",
			    nodename, instance, i, maxpwr[i]));
			mutex_enter(&dstatep->lock);
			level_tmp = dstatep->level[i];
			dstatep->level[i] = maxpwr[i];
			if (pm_power_has_changed(dstatep->dip, i, maxpwr[i])
			    != DDI_SUCCESS) {
				dstatep->level[i] = level_tmp;
				rval = EINVAL;
			}
			mutex_exit(&dstatep->lock);
		}

		break;

	case DEVCTL_PM_POWER:
		/*
		 * test if the gen_drv_power() routine has been called,
		 * then clear
		 */
		mutex_enter(&dstatep->lock);
		state = (dstatep->flag & POWER_FLAG) ? 1 : 0;
		if (copyout(&state, dcp->cpyout_buf,
		    sizeof (uint_t)) != 0) {
			cmn_err(CE_WARN, "%s%d: DEVCTL_PM_POWER:"
			    " copyout failed\n", nodename, instance);
			rval = EINVAL;
		}
		GEN_DEBUG((CE_CONT, "%s%d: %s POWER_FLAG: %d",
		    nodename, instance, "DEVCTL_PM_POWER", state));
		dstatep->flag &= ~POWER_FLAG;
		mutex_exit(&dstatep->lock);
		break;

	case DEVCTL_PM_NO_LOWER_POWER:
		/*
		 * issue to not invoke pm_lower_power() on detach
		 */
		mutex_enter(&dstatep->lock);
		dstatep->flag &= ~LOWER_POWER_FLAG;
		mutex_exit(&dstatep->lock);
		GEN_DEBUG((CE_CONT, "%s%d: DEVCTL_PM_NO_LOWER_POWER",
			    nodename, instance));
		break;

	default:
		return (ENOTTY);
	}

	return (rval);
}