diff options
author | Marcel Moolenaar <marcel@FreeBSD.org> | 2015-07-03 02:06:47 +0000 |
---|---|---|
committer | Marcel Moolenaar <marcel@FreeBSD.org> | 2015-07-03 02:06:47 +0000 |
commit | 22900685fd7640bdc6eb8f09c44d2126e360ddb8 (patch) | |
tree | dc7a73b15347e172d9087c8cd7ba8fb72abc7196 /tools/bus_space | |
parent | e08d13cf837ac74b4c6088539a00600ac6677ff4 (diff) | |
download | src-22900685fd7640bdc6eb8f09c44d2126e360ddb8.tar.gz src-22900685fd7640bdc6eb8f09c44d2126e360ddb8.zip |
Notes
Diffstat (limited to 'tools/bus_space')
-rw-r--r-- | tools/bus_space/C/lang.c | 26 | ||||
-rw-r--r-- | tools/bus_space/C/libbus.h | 4 | ||||
-rw-r--r-- | tools/bus_space/Python/lang.c | 57 | ||||
-rw-r--r-- | tools/bus_space/busdma.c | 168 | ||||
-rw-r--r-- | tools/bus_space/busdma.h | 4 |
5 files changed, 212 insertions, 47 deletions
diff --git a/tools/bus_space/C/lang.c b/tools/bus_space/C/lang.c index 345957efdbe7..ab7d36fee538 100644 --- a/tools/bus_space/C/lang.c +++ b/tools/bus_space/C/lang.c @@ -156,6 +156,32 @@ busdma_mem_free(busdma_md_t md) return (bd_mem_free(md)); } +int +busdma_md_create(busdma_tag_t tag, u_int flags, busdma_md_t *out_p) +{ + int res; + + res = bd_md_create(tag, flags); + if (res == -1) + return (errno); + *out_p = res; + return (0); +} + +int +busdma_md_destroy(busdma_md_t md) +{ + + return (bd_md_destroy(md)); +} + +int +busdma_md_load(busdma_md_t md, void *buf, size_t len, u_int flags) +{ + + return (bd_md_load(md, buf, len, flags)); +} + busdma_seg_t busdma_md_first_seg(busdma_md_t md, int space) { diff --git a/tools/bus_space/C/libbus.h b/tools/bus_space/C/libbus.h index 76ab40225145..16cdadea4fa1 100644 --- a/tools/bus_space/C/libbus.h +++ b/tools/bus_space/C/libbus.h @@ -58,6 +58,10 @@ int busdma_tag_destroy(busdma_tag_t tag); int busdma_mem_alloc(busdma_tag_t tag, u_int flags, busdma_md_t *out_p); int busdma_mem_free(busdma_md_t md); +int busdma_md_create(busdma_tag_t tag, u_int flags, busdma_md_t *out_p); +int busdma_md_destroy(busdma_md_t md); +int busdma_md_load(busdma_md_t md, void *buf, size_t len, u_int flags); + #define BUSDMA_MD_BUS_SPACE 0 #define BUSDMA_MD_PHYS_SPACE 1 #define BUSDMA_MD_VIRT_SPACE 2 diff --git a/tools/bus_space/Python/lang.c b/tools/bus_space/Python/lang.c index 2127df57fa4f..a90e0bd89565 100644 --- a/tools/bus_space/Python/lang.c +++ b/tools/bus_space/Python/lang.c @@ -229,6 +229,55 @@ busdma_tag_destroy(PyObject *self, PyObject *args) } static PyObject * +busdma_md_create(PyObject *self, PyObject *args) +{ + u_int flags; + int error, mdid, tid; + + if (!PyArg_ParseTuple(args, "iI", &tid, &flags)) + return (NULL); + mdid = bd_md_create(tid, flags); + if (mdid == -1) { + PyErr_SetString(PyExc_IOError, strerror(errno)); + return (NULL); + } + return (Py_BuildValue("i", mdid)); +} + +static PyObject * +busdma_md_destroy(PyObject *self, PyObject *args) +{ + int error, mdid; + + if (!PyArg_ParseTuple(args, "i", &mdid)) + return (NULL); + error = bd_md_destroy(mdid); + if (error) { + PyErr_SetString(PyExc_IOError, strerror(error)); + return (NULL); + } + Py_RETURN_NONE; +} + +static PyObject * +busdma_md_load(PyObject *self, PyObject *args) +{ + void *buf; + u_long len; + u_int flags; + int error, mdid; + + if (!PyArg_ParseTuple(args, "iwkI", &mdid, &buf, &len, &flags)) + return (NULL); + error = bd_md_load(mdid, buf, len, flags); + if (error) { + PyErr_SetString(PyExc_IOError, strerror(error)); + return (NULL); + } + Py_RETURN_NONE; +} + +static PyObject * busdma_mem_alloc(PyObject *self, PyObject *args) { u_int flags; @@ -347,6 +396,14 @@ static PyMethodDef busdma_methods[] = { "Derive a child tag." }, { "tag_destroy", busdma_tag_destroy, METH_VARARGS, "Destroy a tag." }, + + { "md_create", busdma_md_create, METH_VARARGS, + "Create a new and empty memory descriptor." }, + { "md_destroy", busdma_md_destroy, METH_VARARGS, + "Destroy a previously created memory descriptor." }, + { "md_load", busdma_md_load, METH_VARARGS, + "Load a buffer into a memory descriptor." }, + { "mem_alloc", busdma_mem_alloc, METH_VARARGS, "Allocate memory according to the DMA constraints." }, { "mem_free", busdma_mem_free, METH_VARARGS, diff --git a/tools/bus_space/busdma.c b/tools/bus_space/busdma.c index e1e5a00885b5..5ec124f918d7 100644 --- a/tools/bus_space/busdma.c +++ b/tools/bus_space/busdma.c @@ -33,6 +33,7 @@ __FBSDID("$FreeBSD$"); #include <errno.h> #include <fcntl.h> #include <limits.h> +#include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> @@ -137,7 +138,7 @@ obj_lookup(int oid, u_int type) return (obj); } -struct obj * +static struct obj * bd_tag_new(struct obj *ptag, int fd, u_long align, u_long bndry, u_long maxaddr, u_long maxsz, u_int nsegs, u_long maxsegsz, u_int datarate, u_int flags) @@ -243,12 +244,113 @@ bd_tag_destroy(int tid) return (0); } +static int +bd_md_add_seg(struct obj *md, int type, u_long addr, u_long size) +{ + struct obj *seg; + + seg = obj_alloc(OBJ_TYPE_SEG); + if (seg == NULL) + return (errno); + seg->refcnt = 1; + seg->parent = md; + seg->u.seg.address = addr; + seg->u.seg.size = size; + + md->u.md.seg[type] = seg; + md->u.md.nsegs[type] = 1; + return (0); +} + +int +bd_md_create(int tid, u_int flags) +{ + struct proto_ioc_busdma ioc; + struct obj *md, *tag; + + tag = obj_lookup(tid, OBJ_TYPE_TAG); + if (tag == NULL) + return (-1); + + md = obj_alloc(OBJ_TYPE_MD); + if (md == NULL) + return (-1); + + memset(&ioc, 0, sizeof(ioc)); + ioc.request = PROTO_IOC_BUSDMA_MD_CREATE; + ioc.u.md.tag = tag->key; + ioc.u.md.flags = flags; + if (ioctl(tag->fd, PROTO_IOC_BUSDMA, &ioc) == -1) { + obj_free(md); + return (-1); + } + + md->refcnt = 1; + md->fd = tag->fd; + md->parent = tag; + tag->refcnt++; + md->key = ioc.result; + return (md->oid); +} + +int +bd_md_destroy(int mdid) +{ + struct proto_ioc_busdma ioc; + struct obj *md; + + md = obj_lookup(mdid, OBJ_TYPE_MD); + if (md == NULL) + return (errno); + + memset(&ioc, 0, sizeof(ioc)); + ioc.request = PROTO_IOC_BUSDMA_MD_DESTROY; + ioc.key = md->key; + if (ioctl(md->fd, PROTO_IOC_BUSDMA, &ioc) == -1) + return (errno); + + md->parent->refcnt--; + obj_free(md); + return (0); +} + +int +bd_md_load(int mdid, void *buf, u_long len, u_int flags) +{ + struct proto_ioc_busdma ioc; + struct obj *md; + int error; + + md = obj_lookup(mdid, OBJ_TYPE_MD); + if (md == NULL) + return (errno); + + memset(&ioc, 0, sizeof(ioc)); + ioc.request = PROTO_IOC_BUSDMA_MD_LOAD; + ioc.key = md->key; + ioc.u.md.flags = flags; + ioc.u.md.virt_addr = (uintptr_t)buf; + ioc.u.md.virt_size = len; + if (ioctl(md->fd, PROTO_IOC_BUSDMA, &ioc) == -1) + return (errno); + + printf("XXX: %s: phys(%d, %#lx), bus(%d, %#lx)\n", __func__, + ioc.u.md.phys_nsegs, ioc.u.md.phys_addr, + ioc.u.md.bus_nsegs, ioc.u.md.bus_addr); + + error = bd_md_add_seg(md, BUSDMA_MD_VIRT, ioc.u.md.virt_addr, len); + error = bd_md_add_seg(md, BUSDMA_MD_PHYS, ioc.u.md.phys_addr, len); + error = bd_md_add_seg(md, BUSDMA_MD_BUS, ioc.u.md.bus_addr, len); + return (error); +} + int bd_mem_alloc(int tid, u_int flags) { struct proto_ioc_busdma ioc; struct obj *md, *tag; - struct obj *bseg, *pseg, *vseg; + uintptr_t addr; + int error; tag = obj_lookup(tid, OBJ_TYPE_TAG); if (tag == NULL) @@ -260,8 +362,8 @@ bd_mem_alloc(int tid, u_int flags) memset(&ioc, 0, sizeof(ioc)); ioc.request = PROTO_IOC_BUSDMA_MEM_ALLOC; - ioc.u.mem.tag = tag->key; - ioc.u.mem.flags = flags; + ioc.u.md.tag = tag->key; + ioc.u.md.flags = flags; if (ioctl(tag->fd, PROTO_IOC_BUSDMA, &ioc) == -1) { obj_free(md); return (-1); @@ -273,55 +375,27 @@ bd_mem_alloc(int tid, u_int flags) tag->refcnt++; md->key = ioc.result; - /* XXX we need to support multiple segments */ - assert(ioc.u.mem.phys_nsegs == 1); - assert(ioc.u.mem.bus_nsegs == 1); - - bseg = pseg = vseg = NULL; + printf("XXX: %s: phys(%d, %#lx), bus(%d, %#lx)\n", __func__, + ioc.u.md.phys_nsegs, ioc.u.md.phys_addr, + ioc.u.md.bus_nsegs, ioc.u.md.bus_addr); - bseg = obj_alloc(OBJ_TYPE_SEG); - if (bseg == NULL) - goto fail; - bseg->refcnt = 1; - bseg->parent = md; - bseg->u.seg.address = ioc.u.mem.bus_addr; - bseg->u.seg.size = tag->u.tag.maxsz; - md->u.md.seg[BUSDMA_MD_BUS] = bseg; - md->u.md.nsegs[BUSDMA_MD_BUS] = ioc.u.mem.bus_nsegs; - - pseg = obj_alloc(OBJ_TYPE_SEG); - if (pseg == NULL) - goto fail; - pseg->refcnt = 1; - pseg->parent = md; - pseg->u.seg.address = ioc.u.mem.phys_addr; - pseg->u.seg.size = tag->u.tag.maxsz; - md->u.md.seg[BUSDMA_MD_PHYS] = pseg; - md->u.md.nsegs[BUSDMA_MD_PHYS] = ioc.u.mem.phys_nsegs; - - vseg = obj_alloc(OBJ_TYPE_SEG); - if (vseg == NULL) - goto fail; - vseg->refcnt = 1; - vseg->parent = md; - vseg->u.seg.address = (uintptr_t)mmap(NULL, pseg->u.seg.size, - PROT_READ | PROT_WRITE, MAP_NOCORE | MAP_SHARED, md->fd, - pseg->u.seg.address); - if (vseg->u.seg.address == (uintptr_t)MAP_FAILED) + /* XXX we need to support multiple segments */ + assert(ioc.u.md.phys_nsegs == 1); + assert(ioc.u.md.bus_nsegs == 1); + error = bd_md_add_seg(md, BUSDMA_MD_PHYS, ioc.u.md.phys_addr, + tag->u.tag.maxsz); + error = bd_md_add_seg(md, BUSDMA_MD_BUS, ioc.u.md.bus_addr, + tag->u.tag.maxsz); + + addr = (uintptr_t)mmap(NULL, tag->u.tag.maxsz, PROT_READ | PROT_WRITE, + MAP_NOCORE | MAP_SHARED, md->fd, ioc.u.md.phys_addr); + if (addr == (uintptr_t)MAP_FAILED) goto fail; - vseg->u.seg.size = pseg->u.seg.size; - md->u.md.seg[BUSDMA_MD_VIRT] = vseg; - md->u.md.nsegs[BUSDMA_MD_VIRT] = 1; + error = bd_md_add_seg(md, BUSDMA_MD_VIRT, addr, tag->u.tag.maxsz); return (md->oid); fail: - if (vseg != NULL) - obj_free(vseg); - if (pseg != NULL) - obj_free(pseg); - if (bseg != NULL) - obj_free(bseg); memset(&ioc, 0, sizeof(ioc)); ioc.request = PROTO_IOC_BUSDMA_MEM_FREE; ioc.key = md->key; diff --git a/tools/bus_space/busdma.h b/tools/bus_space/busdma.h index 7394b267fcdc..23a9250b42d1 100644 --- a/tools/bus_space/busdma.h +++ b/tools/bus_space/busdma.h @@ -37,6 +37,10 @@ int bd_tag_derive(int tid, u_long align, u_long bndry, u_long maxaddr, u_int flags); int bd_tag_destroy(int tid); +int bd_md_create(int tid, u_int flags); +int bd_md_destroy(int mdid); +int bd_md_load(int mdid, void *buf, u_long len, u_int flags); + int bd_mem_alloc(int tid, u_int flags); int bd_mem_free(int mdid); |