diff options
author | marcel <marcel@FreeBSD.org> | 2015-06-08 21:47:44 +0000 |
---|---|---|
committer | marcel <marcel@FreeBSD.org> | 2015-06-08 21:47:44 +0000 |
commit | 21b395f61276e9d47940a84cb4c9055ce8713596 (patch) | |
tree | e5243541b6953a7b29361b79720a6132bbb68a18 | |
parent | 03d0a54e3cc610c487abdeeee2f71c2b564c215a (diff) | |
download | FreeBSD-src-21b395f61276e9d47940a84cb4c9055ce8713596.zip FreeBSD-src-21b395f61276e9d47940a84cb4c9055ce8713596.tar.gz |
Implement mmap(2) for the busdma resource.
-rw-r--r-- | sys/dev/proto/proto_busdma.c | 20 | ||||
-rw-r--r-- | sys/dev/proto/proto_busdma.h | 5 | ||||
-rw-r--r-- | sys/dev/proto/proto_core.c | 26 |
3 files changed, 39 insertions, 12 deletions
diff --git a/sys/dev/proto/proto_busdma.c b/sys/dev/proto/proto_busdma.c index 80d7e58..ced4eed 100644 --- a/sys/dev/proto/proto_busdma.c +++ b/sys/dev/proto/proto_busdma.c @@ -146,16 +146,17 @@ proto_busdma_mem_alloc(struct proto_busdma *busdma, struct proto_tag *tag, free(md, M_PROTO_BUSDMA); return (error); } - error = bus_dmamem_alloc(md->bd_tag, &md->kva, 0, &md->bd_map); + error = bus_dmamem_alloc(md->bd_tag, &md->virtaddr, 0, &md->bd_map); if (error) { bus_dma_tag_destroy(md->bd_tag); free(md, M_PROTO_BUSDMA); return (error); } + md->physaddr = pmap_kextract((uintptr_t)(md->virtaddr)); LIST_INSERT_HEAD(&tag->mds, md, peers); LIST_INSERT_HEAD(&busdma->mds, md, mds); ioc->u.mem.nsegs = 1; - ioc->u.mem.physaddr = pmap_kextract((uintptr_t)(md->kva)); + ioc->u.mem.physaddr = md->physaddr; ioc->result = (uintptr_t)(void *)md; return (0); } @@ -166,7 +167,7 @@ proto_busdma_mem_free(struct proto_busdma *busdma, struct proto_md *md) LIST_REMOVE(md, mds); LIST_REMOVE(md, peers); - bus_dmamem_free(md->bd_tag, md->kva, md->bd_map); + bus_dmamem_free(md->bd_tag, md->virtaddr, md->bd_map); bus_dma_tag_destroy(md->bd_tag); free(md, M_PROTO_BUSDMA); return (0); @@ -267,3 +268,16 @@ proto_busdma_ioctl(struct proto_softc *sc, struct proto_busdma *busdma, } return (error); } + +int +proto_busdma_mmap_allowed(struct proto_busdma *busdma, vm_paddr_t physaddr) +{ + struct proto_md *md; + + LIST_FOREACH(md, &busdma->mds, mds) { + if (physaddr >= trunc_page(md->physaddr) && + physaddr <= trunc_page(md->physaddr + md->tag->maxsz)) + return (1); + } + return (0); +} diff --git a/sys/dev/proto/proto_busdma.h b/sys/dev/proto/proto_busdma.h index d07046f..b4957f5 100644 --- a/sys/dev/proto/proto_busdma.h +++ b/sys/dev/proto/proto_busdma.h @@ -50,7 +50,8 @@ struct proto_md { LIST_ENTRY(proto_md) mds; LIST_ENTRY(proto_md) peers; struct proto_tag *tag; - void *kva; + void *virtaddr; + vm_paddr_t physaddr; bus_dma_tag_t bd_tag; bus_dmamap_t bd_map; }; @@ -69,4 +70,6 @@ int proto_busdma_cleanup(struct proto_softc *, struct proto_busdma *); int proto_busdma_ioctl(struct proto_softc *, struct proto_busdma *, struct proto_ioc_busdma *); +int proto_busdma_mmap_allowed(struct proto_busdma *, vm_paddr_t); + #endif /* _DEV_PROTO_BUSDMA_H_ */ diff --git a/sys/dev/proto/proto_core.c b/sys/dev/proto/proto_core.c index 1b70cea..86f08eb 100644 --- a/sys/dev/proto/proto_core.c +++ b/sys/dev/proto/proto_core.c @@ -402,19 +402,29 @@ proto_mmap(struct cdev *cdev, vm_ooffset_t offset, vm_paddr_t *paddr, { struct proto_res *r; - r = cdev->si_drv2; - - if (r->r_type != SYS_RES_MEMORY) - return (ENXIO); if (offset & PAGE_MASK) return (EINVAL); if (prot & PROT_EXEC) return (EACCES); - if (offset >= r->r_size) - return (EINVAL); - *paddr = rman_get_start(r->r_d.res) + offset; + + r = cdev->si_drv2; + + switch (r->r_type) { + case SYS_RES_MEMORY: + if (offset >= r->r_size) + return (EINVAL); + *paddr = rman_get_start(r->r_d.res) + offset; #ifndef __sparc64__ - *memattr = VM_MEMATTR_UNCACHEABLE; + *memattr = VM_MEMATTR_UNCACHEABLE; #endif + break; + case PROTO_RES_BUSDMA: + if (!proto_busdma_mmap_allowed(r->r_d.busdma, offset)) + return (EINVAL); + *paddr = offset; + break; + default: + return (ENXIO); + } return (0); } |