/*ARGSUSED*/ static int smb_close(dev_t dev, int flag, int otyp, cred_t *cred) { (void) ddi_prop_remove(dev, smb_devi, "size"); smb_clones[getminor(dev)].c_hdl = NULL; return (0); }
/*ARGSUSED*/ int gfxp_vgatext_detach(dev_info_t *devi, ddi_detach_cmd_t cmd, gfxp_vgatext_softc_ptr_t ptr) { struct vgatext_softc *softc = (struct vgatext_softc *)ptr; (void) ddi_prop_remove(DDI_DEV_T_ANY, devi, "primary-controller"); switch (cmd) { case DDI_SUSPEND: return (vgatext_suspend(softc)); /* break; */ case DDI_DETACH: if (softc->fb.mapped) ddi_regs_map_free(&softc->fb.handle); if (softc->regs.mapped) ddi_regs_map_free(&softc->regs.handle); mutex_destroy(&(softc->lock)); return (DDI_SUCCESS); default: cmn_err(CE_WARN, "gfxp_vgatext_detach: unknown cmd 0x%x\n", cmd); return (DDI_FAILURE); } }
/* ARGSUSED */ static int ksyms_close(dev_t dev, int flag, int otyp, struct cred *cred) { minor_t clone = getminor(dev); (void) as_unmap(curproc->p_as, ksyms_clones[clone].ksyms_base, roundup(ksyms_clones[clone].ksyms_size, PAGESIZE)); ksyms_clones[clone].ksyms_base = 0; modunload_enable(); (void) ddi_prop_remove(dev, ksyms_devi, "size"); return (0); }
/* * Remove PM state for nexus. */ static void ppb_pwr_teardown(ppb_devstate_t *ppb, dev_info_t *dip) { int low_lvl; /* * Determine the lowest power level supported. */ if (ppb->ppb_pwr_p->pwr_flags & PCI_PWR_B3_CAPABLE) { low_lvl = PM_LEVEL_B3; } else { low_lvl = PM_LEVEL_B2; } if (pm_lower_power(dip, PCI_PM_COMP_0, low_lvl) != DDI_SUCCESS) { cmn_err(CE_WARN, "%s%d failed to lower power", ddi_driver_name(dip), ddi_get_instance(dip)); } pci_config_teardown(&ppb->ppb_conf_hdl); mutex_destroy(&ppb->ppb_pwr_p->pwr_mutex); kmem_free(ppb->ppb_pwr_p, sizeof (pci_pwr_t)); if (ddi_prop_remove(DDI_DEV_T_NONE, dip, "pm-components") != DDI_PROP_SUCCESS) { cmn_err(CE_WARN, "%s%d unable to remove prop pm-components", ddi_driver_name(dip), ddi_get_instance(dip)); } if (ddi_prop_remove(DDI_DEV_T_NONE, dip, "pm-want-child-notification?") != DDI_PROP_SUCCESS) { cmn_err(CE_WARN, "%s%d unable to remove prop pm-want_child_notification?", ddi_driver_name(dip), ddi_get_instance(dip)); } }
/*ARGSUSED*/ static int ppb_detach(dev_info_t *devi, ddi_detach_cmd_t cmd) { ppb_devstate_t *ppb; int ret = DDI_SUCCESS; switch (cmd) { case DDI_DETACH: /* * And finally free the per-pci soft state after * uninitializing hotplug support for this bus. */ ppb = (ppb_devstate_t *) ddi_get_soft_state(ppb_state, ddi_get_instance(devi)); ppb_fm_fini(ppb); if (ppb->parent_bus == PCIE_PCIECAP_DEV_TYPE_PCIE_DEV) ret = pcie_uninit(devi); else if (ppb->hotplug_capable == B_TRUE) ret = pcihp_init(devi); else ddi_remove_minor_node(devi, "devctl"); if (ret != DDI_SUCCESS) return (DDI_FAILURE); (void) ddi_prop_remove(DDI_DEV_T_NONE, devi, "device_type"); if (ppb->ppb_pwr_p != NULL) { ppb_pwr_teardown(ppb, devi); } mutex_destroy(&ppb->ppb_mutex); ddi_soft_state_free(ppb_state, ddi_get_instance(devi)); return (DDI_SUCCESS); case DDI_SUSPEND: ppb = (ppb_devstate_t *) ddi_get_soft_state(ppb_state, ddi_get_instance(devi)); pci_pwr_suspend(devi, ppb->ppb_pwr_p); return (DDI_SUCCESS); } return (DDI_FAILURE); }
/*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); }
/* * Save the configuration registers for cdip as a property * so that it persists after detach/uninitchild. */ int pci_save_config_regs(dev_info_t *dip) { ddi_acc_handle_t confhdl; pci_config_header_state_t *chsp; pci_cap_save_desc_t *pci_cap_descp; int ret; uint32_t i, ncaps, nwords; uint32_t *regbuf, *p; uint8_t *maskbuf; size_t maskbufsz, regbufsz, capbufsz; ddi_acc_hdl_t *hp; off_t offset = 0; uint8_t cap_ptr, cap_id; int pcie = 0; PMD(PMD_SX, ("pci_save_config_regs %s:%d\n", ddi_driver_name(dip), ddi_get_instance(dip))) if (pci_config_setup(dip, &confhdl) != DDI_SUCCESS) { cmn_err(CE_WARN, "%s%d can't get config handle", ddi_driver_name(dip), ddi_get_instance(dip)); return (DDI_FAILURE); } /* * Determine if it is a pci express device. If it is, save entire * 4k config space treating it as a array of 32 bit integers. * If it is not, do it in a usual PCI way. */ cap_ptr = pci_config_get8(confhdl, PCI_BCNF_CAP_PTR); /* * Walk the capabilities searching for pci express capability */ while (cap_ptr != PCI_CAP_NEXT_PTR_NULL) { cap_id = pci_config_get8(confhdl, cap_ptr + PCI_CAP_ID); if (cap_id == PCI_CAP_ID_PCI_E) { pcie = 1; break; } cap_ptr = pci_config_get8(confhdl, cap_ptr + PCI_CAP_NEXT_PTR); } if (pcie) { /* PCI express device. Can have data in all 4k space */ regbuf = (uint32_t *)kmem_zalloc((size_t)PCIE_CONF_HDR_SIZE, KM_SLEEP); p = regbuf; /* * Allocate space for mask. * mask size is 128 bytes (4096 / 4 / 8 ) */ maskbufsz = (size_t)((PCIE_CONF_HDR_SIZE/ sizeof (uint32_t)) >> INDEX_SHIFT); maskbuf = (uint8_t *)kmem_zalloc(maskbufsz, KM_SLEEP); hp = impl_acc_hdl_get(confhdl); for (i = 0; i < (PCIE_CONF_HDR_SIZE / sizeof (uint32_t)); i++) { if (ddi_peek32(dip, (int32_t *)(hp->ah_addr + offset), (int32_t *)p) == DDI_SUCCESS) { /* it is readable register. set the bit */ maskbuf[i >> INDEX_SHIFT] |= (uint8_t)(1 << (i & BITMASK)); } p++; offset += sizeof (uint32_t); } if ((ret = ndi_prop_update_byte_array(DDI_DEV_T_NONE, dip, SAVED_CONFIG_REGS_MASK, (uchar_t *)maskbuf, maskbufsz)) != DDI_PROP_SUCCESS) { cmn_err(CE_WARN, "couldn't create %s property while" "saving config space for %s@%d\n", SAVED_CONFIG_REGS_MASK, ddi_driver_name(dip), ddi_get_instance(dip)); } else if ((ret = ndi_prop_update_byte_array(DDI_DEV_T_NONE, dip, SAVED_CONFIG_REGS, (uchar_t *)regbuf, (size_t)PCIE_CONF_HDR_SIZE)) != DDI_PROP_SUCCESS) { (void) ddi_prop_remove(DDI_DEV_T_NONE, dip, SAVED_CONFIG_REGS_MASK); cmn_err(CE_WARN, "%s%d can't update prop %s", ddi_driver_name(dip), ddi_get_instance(dip), SAVED_CONFIG_REGS); } kmem_free(maskbuf, (size_t)maskbufsz); kmem_free(regbuf, (size_t)PCIE_CONF_HDR_SIZE); } else {
/* * If bridge is PM capable, set up PM state for nexus. */ static void ppb_pwr_setup(ppb_devstate_t *ppb, dev_info_t *pdip) { char *comp_array[5]; int i; ddi_acc_handle_t conf_hdl; uint8_t pmcsr_bse; uint16_t pmcap; /* * Determine if bridge is PM capable. If not, leave ppb_pwr_p NULL * and return. */ if (pci_config_setup(pdip, &ppb->ppb_conf_hdl) != DDI_SUCCESS) { return; } conf_hdl = ppb->ppb_conf_hdl; /* * Locate and store the power management cap_ptr for future references. */ if ((PCI_CAP_LOCATE(conf_hdl, PCI_CAP_ID_PM, &ppb->ppb_pm_cap_ptr)) == DDI_FAILURE) { DEBUG0(DBG_PWR, pdip, "bridge does not support PM. PCI" " PM data structure not found in config header\n"); pci_config_teardown(&conf_hdl); return; } /* * Allocate PM state structure for ppb. */ ppb->ppb_pwr_p = (pci_pwr_t *) kmem_zalloc(sizeof (pci_pwr_t), KM_SLEEP); ppb->ppb_pwr_p->pwr_fp = 0; pmcsr_bse = PCI_CAP_GET8(conf_hdl, NULL, ppb->ppb_pm_cap_ptr, PCI_PMCSR_BSE); pmcap = PCI_CAP_GET16(conf_hdl, NULL, ppb->ppb_pm_cap_ptr, PCI_PMCAP); if (pmcap == PCI_CAP_EINVAL16 || pmcsr_bse == PCI_CAP_EINVAL8) { pci_config_teardown(&conf_hdl); return; } if (pmcap & PCI_PMCAP_D1) { DEBUG0(DBG_PWR, pdip, "setup: B1 state supported\n"); ppb->ppb_pwr_p->pwr_flags |= PCI_PWR_B1_CAPABLE; } else { DEBUG0(DBG_PWR, pdip, "setup: B1 state NOT supported\n"); } if (pmcap & PCI_PMCAP_D2) { DEBUG0(DBG_PWR, pdip, "setup: B2 state supported\n"); ppb->ppb_pwr_p->pwr_flags |= PCI_PWR_B2_CAPABLE; } else { DEBUG0(DBG_PWR, pdip, "setup: B2 via D2 NOT supported\n"); } if (pmcsr_bse & PCI_PMCSR_BSE_BPCC_EN) { DEBUG0(DBG_PWR, pdip, "setup: bridge power/clock control enable\n"); } else { DEBUG0(DBG_PWR, pdip, "setup: bridge power/clock control disabled\n"); kmem_free(ppb->ppb_pwr_p, sizeof (pci_pwr_t)); ppb->ppb_pwr_p = NULL; pci_config_teardown(&conf_hdl); return; } /* * PCI states D0 and D3 always are supported for normal PCI * devices. D1 and D2 are optional which are checked for above. * Bridge function states D0-D3 correspond to secondary bus states * B0-B3, EXCEPT if PCI_PMCSR_BSE_B2_B3 is set. In this case, setting * the bridge function to D3 will set the bridge bus to state B2 instead * of B3. D2 will not correspond to B2 (and in fact, probably * won't be D2 capable). Implicitly, this means that if * PCI_PMCSR_BSE_B2_B3 is set, the bus will not be B3 capable. */ if (pmcsr_bse & PCI_PMCSR_BSE_B2_B3) { ppb->ppb_pwr_p->pwr_flags |= PCI_PWR_B2_CAPABLE; DEBUG0(DBG_PWR, pdip, "B2 supported via D3\n"); } else { ppb->ppb_pwr_p->pwr_flags |= PCI_PWR_B3_CAPABLE; DEBUG0(DBG_PWR, pdip, "B3 supported via D3\n"); } ppb->ppb_pwr_p->pwr_dip = pdip; mutex_init(&ppb->ppb_pwr_p->pwr_mutex, NULL, MUTEX_DRIVER, NULL); i = 0; comp_array[i++] = "NAME=PCI bridge PM"; if (ppb->ppb_pwr_p->pwr_flags & PCI_PWR_B3_CAPABLE) { comp_array[i++] = "0=Clock/Power Off (B3)"; } if (ppb->ppb_pwr_p->pwr_flags & PCI_PWR_B2_CAPABLE) { comp_array[i++] = "1=Clock Off (B2)"; } if (ppb->ppb_pwr_p->pwr_flags & PCI_PWR_B1_CAPABLE) { comp_array[i++] = "2=Bus Inactive (B1)"; } comp_array[i++] = "3=Full Power (B0)"; /* * Create pm-components property. It does not already exist. */ if (ddi_prop_update_string_array(DDI_DEV_T_NONE, pdip, "pm-components", comp_array, i) != DDI_PROP_SUCCESS) { cmn_err(CE_WARN, "%s%d pm-components prop update failed", ddi_driver_name(pdip), ddi_get_instance(pdip)); pci_config_teardown(&conf_hdl); mutex_destroy(&ppb->ppb_pwr_p->pwr_mutex); kmem_free(ppb->ppb_pwr_p, sizeof (pci_pwr_t)); ppb->ppb_pwr_p = NULL; return; } if (ddi_prop_create(DDI_DEV_T_NONE, pdip, DDI_PROP_CANSLEEP, "pm-want-child-notification?", NULL, NULL) != DDI_PROP_SUCCESS) { cmn_err(CE_WARN, "%s%d fail to create pm-want-child-notification? prop", ddi_driver_name(pdip), ddi_get_instance(pdip)); (void) ddi_prop_remove(DDI_DEV_T_NONE, pdip, "pm-components"); pci_config_teardown(&conf_hdl); mutex_destroy(&ppb->ppb_pwr_p->pwr_mutex); kmem_free(ppb->ppb_pwr_p, sizeof (pci_pwr_t)); ppb->ppb_pwr_p = NULL; return; } ppb->ppb_pwr_p->current_lvl = pci_pwr_current_lvl(ppb->ppb_pwr_p); }
static int ds1287_attach(dev_info_t *dip, ddi_attach_cmd_t cmd) { struct ds1287 *softsp; DPRINTF("ds1287_attach\n"); switch (cmd) { case DDI_ATTACH: break; case DDI_RESUME: return (DDI_SUCCESS); default: return (DDI_FAILURE); } if (instance != -1) { cmn_err(CE_WARN, "ds1287_attach: Another instance is already " "attached."); return (DDI_FAILURE); } instance = ddi_get_instance(dip); if (v_rtc_addr_reg == NULL) { cmn_err(CE_WARN, "ds1287_attach: v_rtc_addr_reg is NULL"); return (DDI_FAILURE); } /* * Allocate softc information. */ if (ddi_soft_state_zalloc(ds1287_state, instance) != DDI_SUCCESS) { cmn_err(CE_WARN, "ds1287_attach: Failed to allocate " "soft states."); return (DDI_FAILURE); } softsp = ddi_get_soft_state(ds1287_state, instance); DPRINTF("ds1287_attach: instance=%d softsp=0x%p\n", instance, (void *)softsp); softsp->dip = dip; if (ddi_prop_create(DDI_DEV_T_NONE, dip, DDI_PROP_CANSLEEP, "interrupt-priorities", (caddr_t)&ds1287_interrupt_priority, sizeof (int)) != DDI_PROP_SUCCESS) { cmn_err(CE_WARN, "ds1287_attach: Failed to create \"" "interrupt-priorities\" property."); goto error; } /* add the softint */ ds1287_lo_iblock = (ddi_iblock_cookie_t)(uintptr_t) ipltospl(ds1287_softint_priority); if (ddi_add_softintr(dip, DDI_SOFTINT_FIXED, &ds1287_softintr_id, &ds1287_lo_iblock, NULL, ds1287_softintr, (caddr_t)softsp) != DDI_SUCCESS) { cmn_err(CE_WARN, "ds1287_attach: Failed to add low interrupt."); goto error1; } /* add the hi interrupt */ if (ddi_add_intr(dip, 0, NULL, (ddi_idevice_cookie_t *) &ds1287_hi_iblock, ds1287_intr, NULL) != DDI_SUCCESS) { cmn_err(CE_WARN, "ds1287_attach: Failed to add high " "interrupt."); goto error2; } /* * Combination of instance number and clone number 0 is used for * creating the minor node. */ if (ddi_create_minor_node(dip, "power_button", S_IFCHR, (instance << 8) + 0, "ddi_power_button", NULL) == DDI_FAILURE) { cmn_err(CE_WARN, "ds1287_attach: Failed to create minor node"); goto error3; } ddi_report_dev(dip); return (DDI_SUCCESS); error3: ddi_remove_intr(dip, 0, NULL); error2: ddi_remove_softintr(ds1287_softintr_id); error1: (void) ddi_prop_remove(DDI_DEV_T_NONE, dip, "interrupt-priorities"); error: ddi_soft_state_free(ds1287_state, instance); return (DDI_FAILURE); }