/*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, ®len) != 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); }
/*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, ®len) != 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); }