コード例 #1
0
/*
 * Common function for DMA map synchronization.  May be called
 * by bus-specific DMA map synchronization functions.
 */
void
_dmamap_sync(bus_dma_tag_t t, bus_dmamap_t map, bus_addr_t addr,
    bus_size_t size, int op)
{
	int nsegs;
	int curseg;
	int cacheop;
	struct cpu_info *ci = curcpu();

	nsegs = map->dm_nsegs;
	curseg = 0;

	while (size && nsegs) {
		vaddr_t vaddr;
		paddr_t paddr;
		bus_size_t ssize;

		ssize = map->dm_segs[curseg].ds_len;
		paddr = map->dm_segs[curseg]._ds_paddr;
		vaddr = map->dm_segs[curseg]._ds_vaddr;

		if (addr != 0) {
			if (addr >= ssize) {
				addr -= ssize;
				ssize = 0;
			} else {
				vaddr += addr;
				paddr += addr;
				ssize -= addr;
				addr = 0;
			}
		}
		if (ssize > size)
			ssize = size;

		if (IS_XKPHYS(vaddr) && XKPHYS_TO_CCA(vaddr) == CCA_NC) {
			size -= ssize;
			ssize = 0;
		}

		if (ssize != 0) {
			/*
			 * If only PREWRITE is requested, writeback.
			 * PREWRITE with PREREAD writebacks
			 * and invalidates (if noncoherent) *all* cache levels.
			 * Otherwise, just invalidate (if noncoherent).
			 */
			if (op & BUS_DMASYNC_PREWRITE) {
				if (op & BUS_DMASYNC_PREREAD)
					cacheop = CACHE_SYNC_X;
				else
					cacheop = CACHE_SYNC_W;
			} else {
				if (op & BUS_DMASYNC_PREREAD)
					cacheop = CACHE_SYNC_R;
				else if (op & BUS_DMASYNC_POSTREAD)
					cacheop = CACHE_SYNC_R;
				else
					cacheop = -1;
			}

			if (cacheop >= 0)
				Mips_IOSyncDCache(ci, vaddr, ssize, cacheop);
			size -= ssize;
		}
		curseg++;
		nsegs--;
	}

#ifdef DIAGNOSTIC
	if (size != 0) {
		panic("_dmamap_sync: ran off map!");
	}
#endif
}
コード例 #2
0
ファイル: bus_dma.c プロジェクト: enukane/openbsd-work
/*
 * Common function for DMA map synchronization.  May be called
 * by bus-specific DMA map synchronization functions.
 */
void
_dmamap_sync(bus_dma_tag_t t, bus_dmamap_t map, bus_addr_t addr,
    bus_size_t size, int op)
{
	int nsegs;
	int curseg;
	struct cpu_info *ci;

#ifdef TGT_COHERENT
	if ((op & BUS_DMASYNC_PREWRITE) == 0)
		return;
#endif

	ci = curcpu();
	nsegs = map->dm_nsegs;
	curseg = 0;

	while (size && nsegs) {
		paddr_t paddr;
		vaddr_t vaddr;
		bus_size_t ssize;

		ssize = map->dm_segs[curseg].ds_len;
		paddr = map->dm_segs[curseg]._ds_paddr;
		vaddr = map->dm_segs[curseg]._ds_vaddr;

		if (addr != 0) {
			if (addr >= ssize) {
				addr -= ssize;
				ssize = 0;
			} else {
				vaddr += addr;
				paddr += addr;
				ssize -= addr;
				addr = 0;
			}
		}
		if (ssize > size)
			ssize = size;

#ifndef TGT_COHERENT
		if (IS_XKPHYS(vaddr) && XKPHYS_TO_CCA(vaddr) == CCA_NC) {
			size -= ssize;
			ssize = 0;
		}
#endif

		if (ssize != 0) {
#ifdef TGT_COHERENT
			/* we only need to writeback here */
			Mips_IOSyncDCache(ci, vaddr, ssize, CACHE_SYNC_W);
#else
			/*
			 * If only PREWRITE is requested, writeback.
			 * PREWRITE with PREREAD writebacks
			 * and invalidates (if noncoherent) *all* cache levels.
			 * Otherwise, just invalidate (if noncoherent).
			 */
			if (op & BUS_DMASYNC_PREWRITE) {
				if (op & BUS_DMASYNC_PREREAD)
					Mips_IOSyncDCache(ci, vaddr,
					    ssize, CACHE_SYNC_X);
				else
					Mips_IOSyncDCache(ci, vaddr,
					    ssize, CACHE_SYNC_W);
			} else
			if (op & (BUS_DMASYNC_PREREAD | BUS_DMASYNC_POSTREAD)) {
				Mips_IOSyncDCache(ci, vaddr,
				    ssize, CACHE_SYNC_R);
			}
#endif
			size -= ssize;
		}
		curseg++;
		nsegs--;
	}

#ifdef DIAGNOSTIC
	if (size != 0)
		panic("_dmamap_sync: ran off map!");
#endif
}