aboutsummaryrefslogtreecommitdiff
path: root/sys/kern/subr_uio.c
diff options
context:
space:
mode:
authorKonstantin Belousov <kib@FreeBSD.org>2013-02-12 16:57:20 +0000
committerKonstantin Belousov <kib@FreeBSD.org>2013-02-12 16:57:20 +0000
commitdd0b4fb6d50631c140e800bdfac48d02e7e4c875 (patch)
treee550f2c754f1edf951a8b93963ebcfc4fa0d20ce /sys/kern/subr_uio.c
parent44c169253de5caec5de2a397c522ad3e359f86e6 (diff)
downloadsrc-dd0b4fb6d50631c140e800bdfac48d02e7e4c875.tar.gz
src-dd0b4fb6d50631c140e800bdfac48d02e7e4c875.zip
Reform the busdma API so that new types may be added without modifying
every architecture's busdma_machdep.c. It is done by unifying the bus_dmamap_load_buffer() routines so that they may be called from MI code. The MD busdma is then given a chance to do any final processing in the complete() callback. The cam changes unify the bus_dmamap_load* handling in cam drivers. The arm and mips implementations are updated to track virtual addresses for sync(). Previously this was done in a type specific way. Now it is done in a generic way by recording the list of virtuals in the map. Submitted by: jeff (sponsored by EMC/Isilon) Reviewed by: kan (previous version), scottl, mjacob (isp(4), no objections for target mode changes) Discussed with: ian (arm changes) Tested by: marius (sparc64), mips (jmallet), isci(4) on x86 (jharris), amd64 (Fabian Keil <freebsd-listen@fabiankeil.de>)
Notes
Notes: svn path=/head/; revision=246713
Diffstat (limited to 'sys/kern/subr_uio.c')
-rw-r--r--sys/kern/subr_uio.c46
1 files changed, 46 insertions, 0 deletions
diff --git a/sys/kern/subr_uio.c b/sys/kern/subr_uio.c
index 7b59348750ef..2b4739523d93 100644
--- a/sys/kern/subr_uio.c
+++ b/sys/kern/subr_uio.c
@@ -152,6 +152,52 @@ copyout_nofault(const void *kaddr, void *udaddr, size_t len)
return (error);
}
+#define PHYS_PAGE_COUNT(len) (howmany(len, PAGE_SIZE) + 1)
+
+int
+physcopyin(void *src, vm_paddr_t dst, size_t len)
+{
+ vm_page_t m[PHYS_PAGE_COUNT(len)];
+ struct iovec iov[1];
+ struct uio uio;
+ int i;
+
+ iov[0].iov_base = src;
+ iov[0].iov_len = len;
+ uio.uio_iov = iov;
+ uio.uio_iovcnt = 1;
+ uio.uio_offset = 0;
+ uio.uio_resid = len;
+ uio.uio_segflg = UIO_SYSSPACE;
+ uio.uio_rw = UIO_WRITE;
+ for (i = 0; i < PHYS_PAGE_COUNT(len); i++, dst += PAGE_SIZE)
+ m[i] = PHYS_TO_VM_PAGE(dst);
+ return (uiomove_fromphys(m, dst & PAGE_MASK, len, &uio));
+}
+
+int
+physcopyout(vm_paddr_t src, void *dst, size_t len)
+{
+ vm_page_t m[PHYS_PAGE_COUNT(len)];
+ struct iovec iov[1];
+ struct uio uio;
+ int i;
+
+ iov[0].iov_base = dst;
+ iov[0].iov_len = len;
+ uio.uio_iov = iov;
+ uio.uio_iovcnt = 1;
+ uio.uio_offset = 0;
+ uio.uio_resid = len;
+ uio.uio_segflg = UIO_SYSSPACE;
+ uio.uio_rw = UIO_READ;
+ for (i = 0; i < PHYS_PAGE_COUNT(len); i++, src += PAGE_SIZE)
+ m[i] = PHYS_TO_VM_PAGE(src);
+ return (uiomove_fromphys(m, src & PAGE_MASK, len, &uio));
+}
+
+#undef PHYS_PAGE_COUNT
+
int
uiomove(void *cp, int n, struct uio *uio)
{