* Utility function to load a linear buffer. segp contains * the starting segment on entrance, and the ending segment on exit. * first indicates if this is the first invocation of this function. */
| 976 | * first indicates if this is the first invocation of this function. |
| 977 | */ |
| 978 | int |
| 979 | _bus_dmamap_load_buffer(bus_dma_tag_t dmat, bus_dmamap_t map, void *buf, |
| 980 | bus_size_t buflen, struct pmap *pmap, int flags, bus_dma_segment_t *segs, |
| 981 | int *segp) |
| 982 | { |
| 983 | bus_size_t sgsize; |
| 984 | bus_addr_t curaddr; |
| 985 | struct sync_list *sl; |
| 986 | vm_offset_t vaddr = (vm_offset_t)buf; |
| 987 | int error = 0; |
| 988 | |
| 989 | if (segs == NULL) |
| 990 | segs = dmat->segments; |
| 991 | if ((flags & BUS_DMA_LOAD_MBUF) != 0) |
| 992 | map->flags |= DMAMAP_CACHE_ALIGNED; |
| 993 | |
| 994 | if ((dmat->flags & BUS_DMA_COULD_BOUNCE) != 0) { |
| 995 | _bus_dmamap_count_pages(dmat, map, pmap, buf, buflen, flags); |
| 996 | if (map->pagesneeded != 0) { |
| 997 | error = _bus_dmamap_reserve_pages(dmat, map, flags); |
| 998 | if (error) |
| 999 | return (error); |
| 1000 | } |
| 1001 | } |
| 1002 | CTR3(KTR_BUSDMA, "lowaddr= %d boundary= %d, " |
| 1003 | "alignment= %d", dmat->lowaddr, dmat->boundary, dmat->alignment); |
| 1004 | |
| 1005 | while (buflen > 0) { |
| 1006 | /* |
| 1007 | * Get the physical address for this segment. |
| 1008 | * |
| 1009 | * XXX Don't support checking for coherent mappings |
| 1010 | * XXX in user address space. |
| 1011 | */ |
| 1012 | KASSERT(kernel_pmap == pmap, ("pmap is not kernel pmap")); |
| 1013 | curaddr = pmap_kextract(vaddr); |
| 1014 | |
| 1015 | /* |
| 1016 | * Compute the segment size, and adjust counts. |
| 1017 | */ |
| 1018 | sgsize = PAGE_SIZE - ((u_long)curaddr & PAGE_MASK); |
| 1019 | if (sgsize > dmat->maxsegsz) |
| 1020 | sgsize = dmat->maxsegsz; |
| 1021 | if (buflen < sgsize) |
| 1022 | sgsize = buflen; |
| 1023 | |
| 1024 | if (((dmat->flags & BUS_DMA_COULD_BOUNCE) != 0) && |
| 1025 | map->pagesneeded != 0 && run_filter(dmat, curaddr)) { |
| 1026 | curaddr = add_bounce_page(dmat, map, vaddr, curaddr, |
| 1027 | sgsize); |
| 1028 | } else { |
| 1029 | sl = &map->slist[map->sync_count - 1]; |
| 1030 | if (map->sync_count == 0 || |
| 1031 | vaddr != sl->vaddr + sl->datacount) { |
| 1032 | if (++map->sync_count > dmat->nsegments) |
| 1033 | goto cleanup; |
| 1034 | sl++; |
| 1035 | sl->vaddr = vaddr; |
nothing calls this directly
no test coverage detected