diff options
Diffstat (limited to 'sys/kern/subr_uio.c')
-rw-r--r-- | sys/kern/subr_uio.c | 54 |
1 files changed, 54 insertions, 0 deletions
diff --git a/sys/kern/subr_uio.c b/sys/kern/subr_uio.c index 87892fd..3712f92 100644 --- a/sys/kern/subr_uio.c +++ b/sys/kern/subr_uio.c @@ -62,6 +62,8 @@ __FBSDID("$FreeBSD$"); #include <vm/vm_pageout.h> #include <vm/vm_map.h> +#include <machine/bus.h> + SYSCTL_INT(_kern, KERN_IOV_MAX, iov_max, CTLFLAG_RD, SYSCTL_NULL_INT_PTR, UIO_MAXIOV, "Maximum number of elements in an I/O vector; sysconf(_SC_IOV_MAX)"); @@ -136,6 +138,58 @@ physcopyout(vm_paddr_t src, void *dst, size_t len) #undef PHYS_PAGE_COUNT int +physcopyin_vlist(bus_dma_segment_t *src, off_t offset, vm_paddr_t dst, + size_t len) +{ + size_t seg_len; + int error; + + error = 0; + while (offset >= src->ds_len) { + offset -= src->ds_len; + src++; + } + + while (len > 0 && error == 0) { + seg_len = MIN(src->ds_len - offset, len); + error = physcopyin((void *)(uintptr_t)(src->ds_addr + offset), + dst, seg_len); + offset = 0; + src++; + len -= seg_len; + dst += seg_len; + } + + return (error); +} + +int +physcopyout_vlist(vm_paddr_t src, bus_dma_segment_t *dst, off_t offset, + size_t len) +{ + size_t seg_len; + int error; + + error = 0; + while (offset >= dst->ds_len) { + offset -= dst->ds_len; + dst++; + } + + while (len > 0 && error == 0) { + seg_len = MIN(dst->ds_len - offset, len); + error = physcopyout(src, (void *)(uintptr_t)(dst->ds_addr + + offset), seg_len); + offset = 0; + dst++; + len -= seg_len; + src += seg_len; + } + + return (error); +} + +int uiomove(void *cp, int n, struct uio *uio) { |