* Utility function to load a linear buffer. segp contains * the starting segment on entrace, and the ending segment on exit. */
| 889 | * the starting segment on entrace, and the ending segment on exit. |
| 890 | */ |
| 891 | static int |
| 892 | bounce_bus_dmamap_load_buffer(bus_dma_tag_t dmat, bus_dmamap_t map, void *buf, |
| 893 | bus_size_t buflen, pmap_t pmap, int flags, bus_dma_segment_t *segs, |
| 894 | int *segp) |
| 895 | { |
| 896 | struct sync_list *sl; |
| 897 | bus_size_t sgsize; |
| 898 | bus_addr_t curaddr, sl_pend; |
| 899 | vm_offset_t kvaddr, vaddr, sl_vend; |
| 900 | int error; |
| 901 | |
| 902 | KASSERT((map->flags & DMAMAP_FROM_DMAMEM) != 0 || |
| 903 | dmat->common.alignment <= PAGE_SIZE, |
| 904 | ("loading user buffer with alignment bigger than PAGE_SIZE is not " |
| 905 | "supported")); |
| 906 | |
| 907 | if (segs == NULL) |
| 908 | segs = dmat->segments; |
| 909 | |
| 910 | if (flags & BUS_DMA_LOAD_MBUF) |
| 911 | map->flags |= DMAMAP_MBUF; |
| 912 | |
| 913 | if (might_bounce(dmat, map, (bus_addr_t)buf, buflen)) { |
| 914 | _bus_dmamap_count_pages(dmat, map, pmap, buf, buflen, flags); |
| 915 | if (map->pagesneeded != 0) { |
| 916 | error = _bus_dmamap_reserve_pages(dmat, map, flags); |
| 917 | if (error) |
| 918 | return (error); |
| 919 | } |
| 920 | } |
| 921 | |
| 922 | /* |
| 923 | * XXX Optimally we should parse input buffer for physically |
| 924 | * continuous segments first and then pass these segment into |
| 925 | * load loop. |
| 926 | */ |
| 927 | sl = map->slist + map->sync_count - 1; |
| 928 | vaddr = (vm_offset_t)buf; |
| 929 | sl_pend = 0; |
| 930 | sl_vend = 0; |
| 931 | |
| 932 | while (buflen > 0) { |
| 933 | /* |
| 934 | * Get the physical address for this segment. |
| 935 | */ |
| 936 | if (__predict_true(pmap == kernel_pmap)) { |
| 937 | curaddr = pmap_kextract(vaddr); |
| 938 | kvaddr = vaddr; |
| 939 | } else { |
| 940 | curaddr = pmap_extract(pmap, vaddr); |
| 941 | kvaddr = 0; |
| 942 | } |
| 943 | |
| 944 | /* |
| 945 | * Compute the segment size, and adjust counts. |
| 946 | */ |
| 947 | sgsize = MIN(buflen, dmat->common.maxsegsz); |
| 948 | if ((map->flags & DMAMAP_FROM_DMAMEM) == 0) |
nothing calls this directly
no test coverage detected