aboutsummaryrefslogtreecommitdiff
path: root/sys/kern/subr_uio.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/kern/subr_uio.c')
-rw-r--r--sys/kern/subr_uio.c54
1 files changed, 54 insertions, 0 deletions
diff --git a/sys/kern/subr_uio.c b/sys/kern/subr_uio.c
index aac6eb6f5e94..ec64b91f75c7 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)
{