static void gp2_unmap_phys(ddi_acc_handle_t *handlep) { ddi_map_req_t mr; ddi_acc_hdl_t *hp; struct regspec_t *ph; hp = impl_acc_hdl_get(*handlep); ASSERT(hp); ph = hp->ah_bus_private; mr.map_op = DDI_MO_UNMAP; mr.map_type = DDI_MT_REGSPEC; mr.map_obj.rp = (struct regspec *)ph; mr.map_prot = PROT_READ | PROT_WRITE; mr.map_flags = DDI_MF_KERNEL_MAPPING; mr.map_handlep = hp; mr.map_vers = DDI_MAP_VERSION; (void) ddi_map(hp->ah_dip, &mr, hp->ah_offset, hp->ah_len, &hp->ah_addr); impl_acc_hdl_free(*handlep); kmem_free(ph, sizeof (struct regspec)); /* Free the cached copy */ *handlep = (ddi_acc_handle_t)NULL; }
uint64_t pci_config_get64(ddi_acc_handle_t handle, off_t offset) { caddr_t cfgaddr; ddi_acc_hdl_t *hp; hp = impl_acc_hdl_get(handle); cfgaddr = hp->ah_addr + offset; return (ddi_get64(handle, (uint64_t *)cfgaddr)); }
void pci_config_putll(ddi_acc_handle_t handle, off_t offset, uint64_t value) { caddr_t cfgaddr; ddi_acc_hdl_t *hp; hp = impl_acc_hdl_get(handle); cfgaddr = hp->ah_addr + offset; ddi_put64(handle, (uint64_t *)cfgaddr, value); }
/* ARGSUSED */ static int impl_acc_check(dev_info_t *dip, const void *handle, const void *addr, const void *not_used) { pfn_t pfn, fault_pfn; ddi_acc_hdl_t *hp; hp = impl_acc_hdl_get((ddi_acc_handle_t)handle); ASSERT(hp); if (addr != NULL) { pfn = hp->ah_pfn; fault_pfn = mmu_btop(*(uint64_t *)addr); if (fault_pfn >= pfn && fault_pfn < (pfn + hp->ah_pnum)) return (DDI_FM_NONFATAL); } return (DDI_FM_UNKNOWN); }
static int gp2_map_phys(dev_info_t *dip, struct regspec *phys_spec, caddr_t *addrp, ddi_device_acc_attr_t *accattrp, ddi_acc_handle_t *handlep) { ddi_map_req_t mr; ddi_acc_hdl_t *hp; int result; struct regspec *ph; *handlep = impl_acc_hdl_alloc(KM_SLEEP, NULL); hp = impl_acc_hdl_get(*handlep); hp->ah_vers = VERS_ACCHDL; hp->ah_dip = dip; hp->ah_rnumber = 0; hp->ah_offset = 0; hp->ah_len = 0; hp->ah_acc = *accattrp; ph = kmem_zalloc(sizeof (struct regspec), KM_SLEEP); *ph = *phys_spec; hp->ah_bus_private = ph; /* cache a copy of the reg spec */ mr.map_op = DDI_MO_MAP_LOCKED; mr.map_type = DDI_MT_REGSPEC; mr.map_obj.rp = (struct regspec *)phys_spec; mr.map_prot = PROT_READ | PROT_WRITE; mr.map_flags = DDI_MF_KERNEL_MAPPING; mr.map_handlep = hp; mr.map_vers = DDI_MAP_VERSION; result = ddi_map(dip, &mr, 0, 0, addrp); if (result != DDI_SUCCESS) { impl_acc_hdl_free(*handlep); *handlep = (ddi_acc_handle_t)NULL; } else { hp->ah_addr = *addrp; } return (result); }
/* * The isadma_map routine determines if it's child is attempting to map a * shared reg. If it is, it installs it's own vectors and bus private pointer * and stacks those ops that were already defined. */ static int isadma_map(dev_info_t *dip, dev_info_t *rdip, ddi_map_req_t *mp, off_t off, off_t len, caddr_t *addrp) { isadma_devstate_t *isadmap = ddi_get_soft_state(per_isadma_state, ddi_get_instance(dip)); dev_info_t *pdip = (dev_info_t *)DEVI(dip)->devi_parent; ebus_regspec_t *child_regp, *regp; int32_t rnumber = mp->map_obj.rnumber; int32_t reglen; int ret; ddi_acc_impl_t *hp; /* * Get child regspec since the mapping struct may not have it yet */ if (ddi_getlongprop(DDI_DEV_T_ANY, rdip, DDI_PROP_DONTPASS, "reg", (caddr_t)®p, ®len) != DDI_SUCCESS) { return (DDI_FAILURE); } child_regp = regp + rnumber; DPRINTF(ISADMA_MAP_DEBUG, ("isadma_map: child regp %p " "parent regp %p Child reg array %p\n", child_regp, isadmap->isadma_regp, regp)); /* Figure out if we're mapping or unmapping */ switch (mp->map_op) { case DDI_MO_MAP_LOCKED: /* Call up device tree to establish mapping */ ret = (DEVI(pdip)->devi_ops->devo_bus_ops->bus_map) (pdip, rdip, mp, off, len, addrp); if ((ret != DDI_SUCCESS) || !IS_SAME_REG(child_regp, isadmap->isadma_regp)) break; /* Post-process the mapping request. */ hp = kmem_alloc(sizeof (ddi_acc_impl_t), KM_SLEEP); *hp = *(ddi_acc_impl_t *)mp->map_handlep; impl_acc_hdl_get((ddi_acc_handle_t)mp->map_handlep)-> ah_platform_private = hp; hp = (ddi_acc_impl_t *)mp->map_handlep; hp->ahi_common.ah_bus_private = isadmap; hp->ahi_get8 = isadma_get8; hp->ahi_get16 = isadma_get16; hp->ahi_get32 = isadma_noget32; hp->ahi_get64 = isadma_noget64; hp->ahi_put8 = isadma_put8; hp->ahi_put16 = isadma_put16; hp->ahi_put32 = isadma_noput32; hp->ahi_put64 = isadma_noput64; hp->ahi_rep_get8 = isadma_norep_get8; hp->ahi_rep_get16 = isadma_norep_get16; hp->ahi_rep_get32 = isadma_norep_get32; hp->ahi_rep_get64 = isadma_norep_get64; hp->ahi_rep_put8 = isadma_norep_put8; hp->ahi_rep_put16 = isadma_norep_put16; hp->ahi_rep_put32 = isadma_norep_put32; hp->ahi_rep_put64 = isadma_norep_put64; break; case DDI_MO_UNMAP: if (IS_SAME_REG(child_regp, isadmap->isadma_regp)) { hp = impl_acc_hdl_get( (ddi_acc_handle_t)mp->map_handlep)-> ah_platform_private; *(ddi_acc_impl_t *)mp->map_handlep = *hp; kmem_free(hp, sizeof (ddi_acc_impl_t)); } /* Call up tree to tear down mapping */ ret = (DEVI(pdip)->devi_ops->devo_bus_ops->bus_map) (pdip, rdip, mp, off, len, addrp); break; default: ret = DDI_FAILURE; break; } kmem_free(regp, reglen); return (ret); }
/* * 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 {