/* * 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 }
/* * 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 }