Implement mmap(2) for the busdma resource.
This commit is contained in:
parent
90acdcbc88
commit
cff0f135c1
@ -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);
|
||||
}
|
||||
|
@ -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_ */
|
||||
|
@ -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);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user