/* ARGSUSED */ static int ppb_ioctl(dev_t dev, int cmd, intptr_t arg, int mode, cred_t *credp, int *rvalp) { int instance = PCI_MINOR_NUM_TO_INSTANCE(getminor(dev)); ppb_devstate_t *ppb_p = ddi_get_soft_state(ppb_state, instance); struct devctl_iocdata *dcp; uint_t bus_state; dev_info_t *self; int rv = 0; if (ppb_p == NULL) return (ENXIO); /* * Ioctls will be handled by SPARC PCI Express framework for all * PCIe platforms */ if (ppb_p->parent_bus == PCIE_PCIECAP_DEV_TYPE_PCIE_DEV) return (pcie_ioctl(ppb_p->dip, dev, cmd, arg, mode, credp, rvalp)); else if (ppb_p->hotplug_capable == B_TRUE) return ((pcihp_get_cb_ops())->cb_ioctl(dev, cmd, arg, mode, credp, rvalp)); self = ppb_p->dip; /* * We can use the generic implementation for these ioctls */ switch (cmd) { case DEVCTL_DEVICE_GETSTATE: case DEVCTL_DEVICE_ONLINE: case DEVCTL_DEVICE_OFFLINE: case DEVCTL_BUS_GETSTATE: return (ndi_devctl_ioctl(self, cmd, arg, mode, 0)); } /* * read devctl ioctl data */ if (ndi_dc_allochdl((void *)arg, &dcp) != NDI_SUCCESS) return (EFAULT); switch (cmd) { case DEVCTL_DEVICE_RESET: rv = ENOTSUP; break; case DEVCTL_BUS_QUIESCE: if (ndi_get_bus_state(self, &bus_state) == NDI_SUCCESS) if (bus_state == BUS_QUIESCED) break; (void) ndi_set_bus_state(self, BUS_QUIESCED); break; case DEVCTL_BUS_UNQUIESCE: if (ndi_get_bus_state(self, &bus_state) == NDI_SUCCESS) if (bus_state == BUS_ACTIVE) break; (void) ndi_set_bus_state(self, BUS_ACTIVE); break; case DEVCTL_BUS_RESET: rv = ENOTSUP; break; case DEVCTL_BUS_RESETALL: rv = ENOTSUP; break; default: rv = ENOTTY; } ndi_dc_freehdl(dcp); return (rv); }
/* ARGSUSED */ static int pci_devctl_ioctl(dev_info_t *dip, int cmd, intptr_t arg, int mode, cred_t *credp, int *rvalp) { int rv = 0; struct devctl_iocdata *dcp; uint_t bus_state; /* * We can use the generic implementation for these ioctls */ switch (cmd) { case DEVCTL_DEVICE_GETSTATE: case DEVCTL_DEVICE_ONLINE: case DEVCTL_DEVICE_OFFLINE: case DEVCTL_BUS_GETSTATE: return (ndi_devctl_ioctl(dip, cmd, arg, mode, 0)); } /* * read devctl ioctl data */ if (ndi_dc_allochdl((void *)arg, &dcp) != NDI_SUCCESS) return (EFAULT); switch (cmd) { case DEVCTL_DEVICE_RESET: DEBUG0(DBG_IOCTL, dip, "DEVCTL_DEVICE_RESET\n"); rv = ENOTSUP; break; case DEVCTL_BUS_QUIESCE: DEBUG0(DBG_IOCTL, dip, "DEVCTL_BUS_QUIESCE\n"); if (ndi_get_bus_state(dip, &bus_state) == NDI_SUCCESS) if (bus_state == BUS_QUIESCED) break; (void) ndi_set_bus_state(dip, BUS_QUIESCED); break; case DEVCTL_BUS_UNQUIESCE: DEBUG0(DBG_IOCTL, dip, "DEVCTL_BUS_UNQUIESCE\n"); if (ndi_get_bus_state(dip, &bus_state) == NDI_SUCCESS) if (bus_state == BUS_ACTIVE) break; (void) ndi_set_bus_state(dip, BUS_ACTIVE); break; case DEVCTL_BUS_RESET: DEBUG0(DBG_IOCTL, dip, "DEVCTL_BUS_RESET\n"); rv = ENOTSUP; break; case DEVCTL_BUS_RESETALL: DEBUG0(DBG_IOCTL, dip, "DEVCTL_BUS_RESETALL\n"); rv = ENOTSUP; break; default: rv = ENOTTY; } ndi_dc_freehdl(dcp); return (rv); }
/*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); }