/*ARGSUSED*/ static int pci_detach(dev_info_t *devi, ddi_detach_cmd_t cmd) { int instance = ddi_get_instance(devi); pci_state_t *pcip; pcip = ddi_get_soft_state(pci_statep, ddi_get_instance(devi)); switch (cmd) { case DDI_DETACH: if (pcip->pci_fmcap & DDI_FM_ERRCB_CAPABLE) { ddi_fm_handler_unregister(devi); pci_ereport_teardown(devi); } mutex_destroy(&pcip->pci_peek_poke_mutex); mutex_destroy(&pcip->pci_err_mutex); mutex_destroy(&pcip->pci_mutex); ddi_fm_fini(devi); /* Uninitialize pcitool support. */ pcitool_uninit(devi); /* Uninitialize hotplug support on this bus. */ (void) pcihp_uninit(devi); ddi_soft_state_free(pci_statep, instance); return (DDI_SUCCESS); case DDI_SUSPEND: return (DDI_SUCCESS); default: return (DDI_FAILURE); } }
/* * Breakdown our FMA resources */ static void ppb_fm_fini(ppb_devstate_t *ppb_p) { /* * Clean up allocated fm structures */ ddi_fm_handler_unregister(ppb_p->dip); pci_ereport_teardown(ppb_p->dip); ddi_fm_fini(ppb_p->dip); }
/*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); }
/*ARGSUSED*/ static int ppb_attach(dev_info_t *devi, ddi_attach_cmd_t cmd) { dev_info_t *root = ddi_root_node(); int instance; ppb_devstate_t *ppb; dev_info_t *pdip; ddi_acc_handle_t config_handle; char *bus; int ret; switch (cmd) { case DDI_ATTACH: /* * Make sure the "device_type" property exists. */ (void) ddi_prop_update_string(DDI_DEV_T_NONE, devi, "device_type", "pci"); /* * Allocate and get soft state structure. */ instance = ddi_get_instance(devi); if (ddi_soft_state_zalloc(ppb_state, instance) != DDI_SUCCESS) return (DDI_FAILURE); ppb = ddi_get_soft_state(ppb_state, instance); ppb->dip = devi; /* * don't enable ereports if immediate child of npe */ if (strcmp(ddi_driver_name(ddi_get_parent(devi)), "npe") == 0) ppb->ppb_fmcap = DDI_FM_ERRCB_CAPABLE | DDI_FM_ACCCHK_CAPABLE | DDI_FM_DMACHK_CAPABLE; else ppb->ppb_fmcap = DDI_FM_EREPORT_CAPABLE | DDI_FM_ERRCB_CAPABLE | DDI_FM_ACCCHK_CAPABLE | DDI_FM_DMACHK_CAPABLE; ddi_fm_init(devi, &ppb->ppb_fmcap, &ppb->ppb_fm_ibc); mutex_init(&ppb->ppb_mutex, NULL, MUTEX_DRIVER, NULL); mutex_init(&ppb->ppb_err_mutex, NULL, MUTEX_DRIVER, (void *)ppb->ppb_fm_ibc); mutex_init(&ppb->ppb_peek_poke_mutex, NULL, MUTEX_DRIVER, (void *)ppb->ppb_fm_ibc); if (ppb->ppb_fmcap & (DDI_FM_ERRCB_CAPABLE | DDI_FM_EREPORT_CAPABLE)) pci_ereport_setup(devi); if (ppb->ppb_fmcap & DDI_FM_ERRCB_CAPABLE) ddi_fm_handler_register(devi, ppb_fm_callback, NULL); if (pci_config_setup(devi, &config_handle) != DDI_SUCCESS) { 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); ddi_fm_fini(devi); ddi_soft_state_free(ppb_state, instance); return (DDI_FAILURE); } ppb->parent_bus = PCIE_PCIECAP_DEV_TYPE_PCI_PSEUDO; for (pdip = ddi_get_parent(devi); pdip && (pdip != root) && (ppb->parent_bus != PCIE_PCIECAP_DEV_TYPE_PCIE_DEV); pdip = ddi_get_parent(pdip)) { if (ddi_prop_lookup_string(DDI_DEV_T_ANY, pdip, DDI_PROP_DONTPASS, "device_type", &bus) != DDI_PROP_SUCCESS) break; if (strcmp(bus, "pciex") == 0) ppb->parent_bus = PCIE_PCIECAP_DEV_TYPE_PCIE_DEV; ddi_prop_free(bus); } if (ppb_support_ht_msimap == 1) (void) ppb_ht_msimap_set(config_handle, HT_MSIMAP_ENABLE); else if (ppb_support_ht_msimap == -1) (void) ppb_ht_msimap_set(config_handle, HT_MSIMAP_DISABLE); pci_config_teardown(&config_handle); /* * Initialize hotplug support on this bus. */ if (ppb->parent_bus == PCIE_PCIECAP_DEV_TYPE_PCIE_DEV) ret = pcie_init(devi, NULL); else ret = pcihp_init(devi); if (ret != DDI_SUCCESS) { cmn_err(CE_WARN, "pci: Failed to setup hotplug framework"); (void) ppb_detach(devi, DDI_DETACH); return (ret); } ddi_report_dev(devi); return (DDI_SUCCESS); case DDI_RESUME: /* * Get the soft state structure for the bridge. */ ppb = ddi_get_soft_state(ppb_state, ddi_get_instance(devi)); ppb_restore_config_regs(ppb); return (DDI_SUCCESS); default: break; } return (DDI_FAILURE); }