summaryrefslogtreecommitdiff
path: root/usr/src/uts/sun4u/io/iommu.c
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src/uts/sun4u/io/iommu.c')
-rw-r--r--usr/src/uts/sun4u/io/iommu.c330
1 files changed, 3 insertions, 327 deletions
diff --git a/usr/src/uts/sun4u/io/iommu.c b/usr/src/uts/sun4u/io/iommu.c
index 66d7a46dc2..75937f0b0f 100644
--- a/usr/src/uts/sun4u/io/iommu.c
+++ b/usr/src/uts/sun4u/io/iommu.c
@@ -22,6 +22,9 @@
* Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
+/*
+ * Copyright 2012 Garrett D'Amore <garrett@damore.org>. All rights reserved.
+ */
#include <sys/types.h>
#include <sys/param.h>
@@ -59,12 +62,7 @@
#define IOMMU_DMAMCTL_SYNC_DEBUG 0x8
#define IOMMU_DMAMCTL_HTOC_DEBUG 0x10
#define IOMMU_DMAMCTL_KVADDR_DEBUG 0x20
-#define IOMMU_DMAMCTL_NEXTWIN_DEBUG 0x40
-#define IOMMU_DMAMCTL_NEXTSEG_DEBUG 0x80
-#define IOMMU_DMAMCTL_MOVWIN_DEBUG 0x100
-#define IOMMU_DMAMCTL_REPWIN_DEBUG 0x200
#define IOMMU_DMAMCTL_GETERR_DEBUG 0x400
-#define IOMMU_DMAMCTL_COFF_DEBUG 0x800
#define IOMMU_DMAMCTL_DMA_FREE_DEBUG 0x1000
#define IOMMU_REGISTERS_DEBUG 0x2000
#define IOMMU_DMA_SETUP_DEBUG 0x4000
@@ -1304,85 +1302,6 @@ iommu_map_window(ddi_dma_impl_t *mp, off_t newoff, size_t winsize)
}
-int
-iommu_dma_map(dev_info_t *dip, dev_info_t *rdip,
- struct ddi_dma_req *dmareq, ddi_dma_handle_t *handlep)
-{
- ddi_dma_lim_t *dma_lim = dmareq->dmar_limits;
- ddi_dma_impl_t *mp;
- ddi_dma_attr_t *dma_attr;
- struct dma_impl_priv *mppriv;
- ioaddr_t addrlow, addrhigh;
- ioaddr_t segalign;
- int rval;
- struct sbus_soft_state *softsp =
- (struct sbus_soft_state *)ddi_get_soft_state(sbusp,
- ddi_get_instance(dip));
-
- addrlow = dma_lim->dlim_addr_lo;
- addrhigh = dma_lim->dlim_addr_hi;
- if ((addrhigh <= addrlow) ||
- (addrhigh < (ioaddr_t)softsp->iommu_dvma_base)) {
- return (DDI_DMA_NOMAPPING);
- }
-
- /*
- * Setup DMA burstsizes and min-xfer counts.
- */
- (void) iommu_dma_lim_setup(dip, rdip, softsp, &dma_lim->dlim_burstsizes,
- (uint_t)dma_lim->dlim_burstsizes, &dma_lim->dlim_minxfer,
- dmareq->dmar_flags);
-
- if (dma_lim->dlim_burstsizes == 0)
- return (DDI_DMA_NOMAPPING);
- /*
- * If not an advisory call, get a DMA handle
- */
- if (!handlep) {
- return (DDI_DMA_MAPOK);
- }
-
- mppriv = kmem_zalloc(sizeof (*mppriv),
- (dmareq->dmar_fp == DDI_DMA_SLEEP) ? KM_SLEEP : KM_NOSLEEP);
- if (mppriv == NULL) {
- if (dmareq->dmar_fp != DDI_DMA_DONTWAIT) {
- ddi_set_callback(dmareq->dmar_fp,
- dmareq->dmar_arg, &softsp->dvma_call_list_id);
- }
- return (DDI_DMA_NORESOURCES);
- }
- mp = (ddi_dma_impl_t *)mppriv;
- mp->dmai_rdip = rdip;
- mp->dmai_rflags = dmareq->dmar_flags & DMP_DDIFLAGS;
- mp->dmai_minxfer = dma_lim->dlim_minxfer;
- mp->dmai_burstsizes = dma_lim->dlim_burstsizes;
- mp->dmai_offset = 0;
- mp->dmai_ndvmapages = 0;
- mp->dmai_minfo = 0;
- mp->dmai_inuse = 0;
- segalign = dma_lim->dlim_cntr_max;
- /* See if the DMA engine has any limit restrictions. */
- if (segalign == UINT32_MAX && addrhigh == UINT32_MAX &&
- addrlow == 0) {
- mp->dmai_rflags |= DMP_NOLIMIT;
- }
- mppriv->softsp = softsp;
- mppriv->phys_sync_flag = va_to_pa((caddr_t)&mppriv->sync_flag);
- dma_attr = &mp->dmai_attr;
- dma_attr->dma_attr_align = 1;
- dma_attr->dma_attr_addr_lo = addrlow;
- dma_attr->dma_attr_addr_hi = addrhigh;
- dma_attr->dma_attr_seg = segalign;
- dma_attr->dma_attr_burstsizes = dma_lim->dlim_burstsizes;
- rval = iommu_dma_bindhdl(dip, rdip, (ddi_dma_handle_t)mp,
- dmareq, NULL, NULL);
- if (rval && (rval != DDI_DMA_PARTIAL_MAP)) {
- kmem_free(mppriv, sizeof (*mppriv));
- } else {
- *handlep = (ddi_dma_handle_t)mp;
- }
- return (rval);
-}
/*ARGSUSED*/
int
@@ -1390,57 +1309,11 @@ iommu_dma_mctl(dev_info_t *dip, dev_info_t *rdip,
ddi_dma_handle_t handle, enum ddi_dma_ctlops request,
off_t *offp, size_t *lenp, caddr_t *objp, uint_t cache_flags)
{
- ioaddr_t addr;
- uint_t offset;
pgcnt_t npages;
- size_t size;
- ddi_dma_cookie_t *cp;
ddi_dma_impl_t *mp = (ddi_dma_impl_t *)handle;
DPRINTF(IOMMU_DMAMCTL_DEBUG, ("dma_mctl: handle %p ", (void *)mp));
switch (request) {
- case DDI_DMA_FREE:
- {
- struct dma_impl_priv *mppriv = (struct dma_impl_priv *)mp;
- struct sbus_soft_state *softsp = mppriv->softsp;
- ASSERT(softsp != NULL);
-
- /*
- * 'Free' the dma mappings.
- */
- addr = (ioaddr_t)(mp->dmai_mapping & ~IOMMU_PAGEOFFSET);
- npages = mp->dmai_ndvmapages;
- size = iommu_ptob(npages);
-
- DPRINTF(IOMMU_DMAMCTL_DMA_FREE_DEBUG, ("iommu_dma_mctl dmafree:"
- "freeing vaddr %x for %x pages.\n", addr,
- mp->dmai_ndvmapages));
- /* sync the entire object */
- if (!(mp->dmai_rflags & DDI_DMA_CONSISTENT)) {
- /* flush stream write buffers */
- sync_stream_buf(softsp, addr, npages,
- (int *)&mppriv->sync_flag, mppriv->phys_sync_flag);
- }
-
-#if defined(DEBUG) && defined(IO_MEMDEBUG)
- iommu_remove_mappings(mp);
-#endif /* DEBUG && IO_MEMDEBUG */
-
- ASSERT(npages > (uint_t)0);
- if (mp->dmai_rflags & DMP_NOLIMIT)
- vmem_free(softsp->dvma_arena,
- (void *)(uintptr_t)addr, size);
- else
- vmem_xfree(softsp->dvma_arena,
- (void *)(uintptr_t)addr, size);
-
- kmem_free(mppriv, sizeof (*mppriv));
-
- if (softsp->dvma_call_list_id != 0)
- ddi_run_callback(&softsp->dvma_call_list_id);
-
- break;
- }
case DDI_DMA_SET_SBUS64:
{
@@ -1451,203 +1324,6 @@ iommu_dma_mctl(dev_info_t *dip, dev_info_t *rdip,
DDI_DMA_SBUS_64BIT));
}
- case DDI_DMA_HTOC:
- DPRINTF(IOMMU_DMAMCTL_HTOC_DEBUG, ("htoc off %lx mapping %lx "
- "size %x\n", *offp, mp->dmai_mapping,
- mp->dmai_size));
-
- if ((uint_t)(*offp) >= mp->dmai_size)
- return (DDI_FAILURE);
-
- cp = (ddi_dma_cookie_t *)objp;
- cp->dmac_notused = 0;
- cp->dmac_address = (mp->dmai_mapping + (uint_t)(*offp));
- cp->dmac_size =
- mp->dmai_mapping + mp->dmai_size - cp->dmac_address;
- cp->dmac_type = 0;
-
- break;
-
- case DDI_DMA_KVADDR:
- /*
- * If a physical address mapping has percolated this high,
- * that is an error (maybe?).
- */
- if (mp->dmai_rflags & DMP_PHYSADDR) {
- DPRINTF(IOMMU_DMAMCTL_KVADDR_DEBUG, ("kvaddr of phys "
- "mapping\n"));
- return (DDI_FAILURE);
- }
-
- return (DDI_FAILURE);
-
- case DDI_DMA_NEXTWIN:
- {
- ddi_dma_win_t *owin, *nwin;
- uint_t winsize, newoff;
- int rval;
-
- DPRINTF(IOMMU_DMAMCTL_NEXTWIN_DEBUG, ("nextwin\n"));
-
- mp = (ddi_dma_impl_t *)handle;
- owin = (ddi_dma_win_t *)offp;
- nwin = (ddi_dma_win_t *)objp;
- if (mp->dmai_rflags & DDI_DMA_PARTIAL) {
- if (*owin == NULL) {
- DPRINTF(IOMMU_DMAMCTL_NEXTWIN_DEBUG,
- ("nextwin: win == NULL\n"));
- mp->dmai_offset = 0;
- *nwin = (ddi_dma_win_t)mp;
- return (DDI_SUCCESS);
- }
-
- offset = (uint_t)(mp->dmai_mapping & IOMMU_PAGEOFFSET);
- winsize = iommu_ptob(mp->dmai_ndvmapages -
- iommu_btopr(offset));
-
- newoff = (uint_t)(mp->dmai_offset + winsize);
- if (newoff > mp->dmai_object.dmao_size -
- mp->dmai_minxfer)
- return (DDI_DMA_DONE);
-
- if ((rval = iommu_map_window(mp, newoff, winsize))
- != DDI_SUCCESS)
- return (rval);
- } else {
- DPRINTF(IOMMU_DMAMCTL_NEXTWIN_DEBUG, ("nextwin: no "
- "partial mapping\n"));
- if (*owin != NULL)
- return (DDI_DMA_DONE);
- mp->dmai_offset = 0;
- *nwin = (ddi_dma_win_t)mp;
- }
- break;
- }
-
- case DDI_DMA_NEXTSEG:
- {
- ddi_dma_seg_t *oseg, *nseg;
-
- DPRINTF(IOMMU_DMAMCTL_NEXTSEG_DEBUG, ("nextseg:\n"));
-
- oseg = (ddi_dma_seg_t *)lenp;
- if (*oseg != NULL)
- return (DDI_DMA_DONE);
- nseg = (ddi_dma_seg_t *)objp;
- *nseg = *((ddi_dma_seg_t *)offp);
- break;
- }
-
- case DDI_DMA_SEGTOC:
- {
- ddi_dma_seg_impl_t *seg;
-
- seg = (ddi_dma_seg_impl_t *)handle;
- cp = (ddi_dma_cookie_t *)objp;
- cp->dmac_notused = 0;
- cp->dmac_address = (ioaddr_t)seg->dmai_mapping;
- cp->dmac_size = *lenp = seg->dmai_size;
- cp->dmac_type = 0;
- *offp = seg->dmai_offset;
- break;
- }
-
- case DDI_DMA_MOVWIN:
- {
- uint_t winsize;
- uint_t newoff;
- int rval;
-
- offset = (uint_t)(mp->dmai_mapping & IOMMU_PAGEOFFSET);
- winsize = iommu_ptob(mp->dmai_ndvmapages - iommu_btopr(offset));
-
- DPRINTF(IOMMU_DMAMCTL_MOVWIN_DEBUG, ("movwin off %lx len %lx "
- "winsize %x\n", *offp, *lenp, winsize));
-
- if ((mp->dmai_rflags & DDI_DMA_PARTIAL) == 0)
- return (DDI_FAILURE);
-
- if (*lenp != (uint_t)-1 && *lenp != winsize) {
- DPRINTF(IOMMU_DMAMCTL_MOVWIN_DEBUG, ("bad length\n"));
- return (DDI_FAILURE);
- }
- newoff = (uint_t)*offp;
- if (newoff & (winsize - 1)) {
- DPRINTF(IOMMU_DMAMCTL_MOVWIN_DEBUG, ("bad off\n"));
- return (DDI_FAILURE);
- }
-
- if (newoff == mp->dmai_offset) {
- /*
- * Nothing to do...
- */
- break;
- }
-
- /*
- * Check out new address...
- */
- if (newoff > mp->dmai_object.dmao_size - mp->dmai_minxfer) {
- DPRINTF(IOMMU_DMAMCTL_MOVWIN_DEBUG, ("newoff out of "
- "range\n"));
- return (DDI_FAILURE);
- }
-
- rval = iommu_map_window(mp, newoff, winsize);
- if (rval != DDI_SUCCESS)
- return (rval);
-
- if ((cp = (ddi_dma_cookie_t *)objp) != 0) {
- cp->dmac_notused = 0;
- cp->dmac_address = (ioaddr_t)mp->dmai_mapping;
- cp->dmac_size = mp->dmai_size;
- cp->dmac_type = 0;
- }
- *offp = (off_t)newoff;
- *lenp = (uint_t)winsize;
- break;
- }
-
- case DDI_DMA_REPWIN:
- if ((mp->dmai_rflags & DDI_DMA_PARTIAL) == 0) {
- DPRINTF(IOMMU_DMAMCTL_REPWIN_DEBUG, ("repwin fail\n"));
- return (DDI_FAILURE);
- }
-
- *offp = (off_t)mp->dmai_offset;
-
- addr = mp->dmai_ndvmapages -
- iommu_btopr(mp->dmai_mapping & IOMMU_PAGEOFFSET);
-
- *lenp = (uint_t)iommu_ptob(addr);
-
- DPRINTF(IOMMU_DMAMCTL_REPWIN_DEBUG, ("repwin off %lx len %x\n",
- mp->dmai_offset, mp->dmai_size));
-
- break;
-
- case DDI_DMA_GETERR:
- DPRINTF(IOMMU_DMAMCTL_GETERR_DEBUG,
- ("iommu_dma_mctl: geterr\n"));
-
- break;
-
- case DDI_DMA_COFF:
- cp = (ddi_dma_cookie_t *)offp;
- addr = cp->dmac_address;
-
- if (addr < mp->dmai_mapping ||
- addr >= mp->dmai_mapping + mp->dmai_size)
- return (DDI_FAILURE);
-
- *objp = (caddr_t)(addr - mp->dmai_mapping);
-
- DPRINTF(IOMMU_DMAMCTL_COFF_DEBUG, ("coff off %lx mapping %lx "
- "size %x\n", (ulong_t)*objp, mp->dmai_mapping,
- mp->dmai_size));
-
- break;
-
case DDI_DMA_RESERVE:
{
struct ddi_dma_req *dmareq = (struct ddi_dma_req *)offp;