/*ARGSUSED*/ int px_dma_unbindhdl(dev_info_t *dip, dev_info_t *rdip, ddi_dma_handle_t handle) { ddi_dma_impl_t *mp = (ddi_dma_impl_t *)handle; px_t *px_p = DIP_TO_STATE(dip); px_mmu_t *mmu_p = px_p->px_mmu_p; DBG(DBG_DMA_UNBINDH, dip, "rdip=%s%d, mp=%p\n", ddi_driver_name(rdip), ddi_get_instance(rdip), handle); if ((mp->dmai_flags & PX_DMAI_FLAGS_INUSE) == 0) { DBG(DBG_DMA_UNBINDH, dip, "handle not inuse\n"); return (DDI_FAILURE); } mp->dmai_error.err_cf = NULL; /* * Here if the handle is using the iommu. Unload all the iommu * translations. */ switch (PX_DMA_TYPE(mp)) { case PX_DMAI_FLAGS_DVMA: px_mmu_unmap_window(mmu_p, mp); px_dvma_unmap(mmu_p, mp); px_dma_freepfn(mp); break; case PX_DMAI_FLAGS_BYPASS: case PX_DMAI_FLAGS_PTP: px_dma_freewin(mp); break; default: cmn_err(CE_PANIC, "%s%d: px_dma_unbindhdl:bad dma type %p", ddi_driver_name(rdip), ddi_get_instance(rdip), mp); /*NOTREACHED*/ } if (mmu_p->mmu_dvma_clid != 0) { DBG(DBG_DMA_UNBINDH, dip, "run dvma callback\n"); ddi_run_callback(&mmu_p->mmu_dvma_clid); } if (px_kmem_clid) { DBG(DBG_DMA_UNBINDH, dip, "run handle callback\n"); ddi_run_callback(&px_kmem_clid); } mp->dmai_flags &= PX_DMAI_FLAGS_PRESERVE; return (DDI_SUCCESS); }
int px_fdvma_release(dev_info_t *dip, px_t *px_p, ddi_dma_impl_t *mp) { px_mmu_t *mmu_p = px_p->px_mmu_p; size_t npages; fdvma_t *fdvma_p = (fdvma_t *)mp->dmai_fdvma; if (px_disable_fdvma) return (DDI_FAILURE); /* validate fdvma handle */ if (!(mp->dmai_rflags & DMP_BYPASSNEXUS)) { DBG(DBG_DMA_CTL, dip, "DDI_DMA_RELEASE: not fast dma\n"); return (DDI_FAILURE); } /* flush all reserved dvma addresses from mmu */ px_mmu_unmap_window(mmu_p, mp); npages = mp->dmai_ndvmapages; vmem_xfree(mmu_p->mmu_dvma_map, (void *)mp->dmai_mapping, MMU_PTOB(npages)); mmu_p->mmu_dvma_reserve += npages; mp->dmai_ndvmapages = 0; /* see if there is anyone waiting for dvma space */ if (mmu_p->mmu_dvma_clid != 0) { DBG(DBG_DMA_CTL, dip, "run dvma callback\n"); ddi_run_callback(&mmu_p->mmu_dvma_clid); } /* free data structures */ kmem_free(fdvma_p->pagecnt, npages * sizeof (uint_t)); kmem_free(fdvma_p, sizeof (fdvma_t)); kmem_free(mp, sizeof (px_dma_hdl_t)); /* see if there is anyone waiting for kmem */ if (px_kmem_clid != 0) { DBG(DBG_DMA_CTL, dip, "run handle callback\n"); ddi_run_callback(&px_kmem_clid); } return (DDI_SUCCESS); }
/* * bus dma win entry point: */ int px_dma_win(dev_info_t *dip, dev_info_t *rdip, ddi_dma_handle_t handle, uint_t win, off_t *offp, size_t *lenp, ddi_dma_cookie_t *cookiep, uint_t *ccountp) { ddi_dma_impl_t *mp = (ddi_dma_impl_t *)handle; int ret; DBG(DBG_DMA_WIN, dip, "rdip=%s%d\n", ddi_driver_name(rdip), ddi_get_instance(rdip)); px_dump_dma_handle(DBG_DMA_WIN, dip, mp); if (win >= mp->dmai_nwin) { DBG(DBG_DMA_WIN, dip, "%x out of range\n", win); return (DDI_FAILURE); } switch (PX_DMA_TYPE(mp)) { case PX_DMAI_FLAGS_DVMA: if (win != PX_DMA_CURWIN(mp)) { px_t *px_p = DIP_TO_STATE(dip); px_mmu_t *mmu_p = px_p->px_mmu_p; px_mmu_unmap_window(mmu_p, mp); /* map_window sets dmai_mapping/size/offset */ px_mmu_map_window(mmu_p, mp, win); if ((ret = px_mmu_map_window(mmu_p, mp, win)) != DDI_SUCCESS) return (ret); } if (cookiep) MAKE_DMA_COOKIE(cookiep, mp->dmai_mapping, mp->dmai_size); if (ccountp) *ccountp = 1; break; case PX_DMAI_FLAGS_PTP: case PX_DMAI_FLAGS_BYPASS: { int i; ddi_dma_cookie_t *ck_p; px_dma_win_t *win_p = mp->dmai_winlst; for (i = 0; i < win; win_p = win_p->win_next, i++) {}; ck_p = (ddi_dma_cookie_t *)(win_p + 1); *cookiep = *ck_p; mp->dmai_offset = win_p->win_offset; mp->dmai_size = win_p->win_size; mp->dmai_mapping = ck_p->dmac_laddress; mp->dmai_cookie = ck_p + 1; win_p->win_curseg = 0; if (ccountp) *ccountp = win_p->win_ncookies; } break; default: cmn_err(CE_WARN, "%s%d: px_dma_win:bad dma type 0x%x", ddi_driver_name(rdip), ddi_get_instance(rdip), PX_DMA_TYPE(mp)); return (DDI_FAILURE); } if (cookiep) DBG(DBG_DMA_WIN, dip, "cookie - dmac_address=%x dmac_size=%x\n", cookiep->dmac_address, cookiep->dmac_size); if (offp) *offp = (off_t)mp->dmai_offset; if (lenp) *lenp = mp->dmai_size; return (DDI_SUCCESS); }