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); }
/* 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); }
/*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); }
/*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); }
/*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); }
/*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); }
/*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); }
/*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); }