diff options
author | Konstantin Belousov <kib@FreeBSD.org> | 2013-02-12 16:57:20 +0000 |
---|---|---|
committer | Konstantin Belousov <kib@FreeBSD.org> | 2013-02-12 16:57:20 +0000 |
commit | dd0b4fb6d50631c140e800bdfac48d02e7e4c875 (patch) | |
tree | e550f2c754f1edf951a8b93963ebcfc4fa0d20ce /sys/kern/subr_uio.c | |
parent | 44c169253de5caec5de2a397c522ad3e359f86e6 (diff) | |
download | src-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.c | 46 |
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) { |