diff options
author | marcel <marcel@FreeBSD.org> | 2015-07-03 05:47:56 +0000 |
---|---|---|
committer | marcel <marcel@FreeBSD.org> | 2015-07-03 05:47:56 +0000 |
commit | fac325d35189afbad0cf6276d1e1a195e78ceafd (patch) | |
tree | d48c492ec6003859eac44c9fc58e6201d161d6f2 /tools | |
parent | 2c1d4a4ec108315dde35ee29b168bcf39be807ac (diff) | |
download | FreeBSD-src-fac325d35189afbad0cf6276d1e1a195e78ceafd.zip FreeBSD-src-fac325d35189afbad0cf6276d1e1a195e78ceafd.tar.gz |
Implement busdma_md_unload() and busdma_sync().
While here:
1. have the Python bindings contain constants for the space
identifiers and the sync operation.
2. change the segment iterators to return None when done,
not ENXIO.
Diffstat (limited to 'tools')
-rw-r--r-- | tools/bus_space/C/lang.c | 14 | ||||
-rw-r--r-- | tools/bus_space/C/libbus.h | 8 | ||||
-rw-r--r-- | tools/bus_space/Python/lang.c | 70 | ||||
-rw-r--r-- | tools/bus_space/busdma.c | 77 | ||||
-rw-r--r-- | tools/bus_space/busdma.h | 3 |
5 files changed, 147 insertions, 25 deletions
diff --git a/tools/bus_space/C/lang.c b/tools/bus_space/C/lang.c index ab7d36f..d9c3f52 100644 --- a/tools/bus_space/C/lang.c +++ b/tools/bus_space/C/lang.c @@ -182,6 +182,13 @@ busdma_md_load(busdma_md_t md, void *buf, size_t len, u_int flags) return (bd_md_load(md, buf, len, flags)); } +int +busdma_md_unload(busdma_md_t md) +{ + + return (bd_md_unload(md)); +} + busdma_seg_t busdma_md_first_seg(busdma_md_t md, int space) { @@ -218,3 +225,10 @@ busdma_seg_get_size(busdma_seg_t seg) error = bd_seg_get_size(seg, &size); return ((error) ? ~0UL : size); } + +int +busdma_sync(busdma_md_t md, int op, bus_addr_t base, bus_size_t size) +{ + + return (bd_sync(md, op, base, size)); +} diff --git a/tools/bus_space/C/libbus.h b/tools/bus_space/C/libbus.h index 16cdade..50efd38 100644 --- a/tools/bus_space/C/libbus.h +++ b/tools/bus_space/C/libbus.h @@ -61,6 +61,7 @@ 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); +int busdma_md_unload(busdma_md_t md); #define BUSDMA_MD_BUS_SPACE 0 #define BUSDMA_MD_PHYS_SPACE 1 @@ -72,4 +73,11 @@ int busdma_md_next_seg(busdma_md_t, busdma_seg_t seg); bus_addr_t busdma_seg_get_addr(busdma_seg_t seg); bus_size_t busdma_seg_get_size(busdma_seg_t seg); +#define BUSDMA_SYNC_PREREAD 1 +#define BUSDMA_SYNC_POSTREAD 2 +#define BUSDMA_SYNC_PREWRITE 4 +#define BUSDMA_SYNC_POSTWRITE 8 + +int busdma_sync(busdma_md_t md, int op, bus_addr_t, bus_size_t); + #endif /* _LIBBUS_SPACE_H_ */ diff --git a/tools/bus_space/Python/lang.c b/tools/bus_space/Python/lang.c index a90e0bd..0b96db3 100644 --- a/tools/bus_space/Python/lang.c +++ b/tools/bus_space/Python/lang.c @@ -278,6 +278,21 @@ busdma_md_load(PyObject *self, PyObject *args) } static PyObject * +busdma_md_unload(PyObject *self, PyObject *args) +{ + int error, mdid; + + if (!PyArg_ParseTuple(args, "i", &mdid)) + return (NULL); + error = bd_md_unload(mdid); + 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; @@ -316,10 +331,8 @@ busdma_md_first_seg(PyObject *self, PyObject *args) if (!PyArg_ParseTuple(args, "ii", &mdid, &what)) return (NULL); sid = bd_md_first_seg(mdid, what); - if (sid == -1) { - PyErr_SetString(PyExc_IOError, strerror(errno)); - return (NULL); - } + if (sid == -1) + Py_RETURN_NONE; return (Py_BuildValue("i", sid)); } @@ -331,10 +344,8 @@ busdma_md_next_seg(PyObject *self, PyObject *args) if (!PyArg_ParseTuple(args, "ii", &mdid, &sid)) return (NULL); sid = bd_md_next_seg(mdid, sid); - if (sid == -1) { - PyErr_SetString(PyExc_IOError, strerror(errno)); - return (NULL); - } + if (sid == -1) + Py_RETURN_NONE; return (Py_BuildValue("i", sid)); } @@ -370,6 +381,22 @@ busdma_seg_get_size(PyObject *self, PyObject *args) return (Py_BuildValue("k", size)); } +static PyObject * +busdma_sync(PyObject *self, PyObject *args) +{ + u_long base, size; + int error, mdid, op; + + if (!PyArg_ParseTuple(args, "iikk", &mdid, &op, &base, &size)) + return (NULL); + error = bd_sync(mdid, op, base, size); + if (error) { + PyErr_SetString(PyExc_IOError, strerror(error)); + return (NULL); + } + Py_RETURN_NONE; +} + static PyMethodDef bus_methods[] = { { "read_1", bus_read_1, METH_VARARGS, "Read a 1-byte data item." }, { "read_2", bus_read_2, METH_VARARGS, "Read a 2-byte data item." }, @@ -403,6 +430,8 @@ static PyMethodDef busdma_methods[] = { "Destroy a previously created memory descriptor." }, { "md_load", busdma_md_load, METH_VARARGS, "Load a buffer into a memory descriptor." }, + { "md_unload", busdma_md_unload, METH_VARARGS, + "Unload a memory descriptor." }, { "mem_alloc", busdma_mem_alloc, METH_VARARGS, "Allocate memory according to the DMA constraints." }, @@ -417,13 +446,32 @@ static PyMethodDef busdma_methods[] = { "Return the address of the segment." }, { "seg_get_size", busdma_seg_get_size, METH_VARARGS, "Return the size of the segment." }, + + { "sync", busdma_sync, METH_VARARGS, + "Keep memory/caches coherent WRT to DMA." }, + { NULL, NULL, 0, NULL } }; PyMODINIT_FUNC initbus(void) { - - Py_InitModule("bus", bus_methods); - Py_InitModule("busdma", busdma_methods); + PyObject *bus, *busdma; + + bus = Py_InitModule("bus", bus_methods); + if (bus == NULL) + return; + busdma = Py_InitModule("busdma", busdma_methods); + if (busdma == NULL) + return; + PyModule_AddObject(bus, "dma", busdma); + + PyModule_AddObject(busdma, "MD_BUS_SPACE", Py_BuildValue("i", 0)); + PyModule_AddObject(busdma, "MD_PHYS_SPACE", Py_BuildValue("i", 1)); + PyModule_AddObject(busdma, "MD_VIRT_SPACE", Py_BuildValue("i", 2)); + + PyModule_AddObject(busdma, "SYNC_PREREAD", Py_BuildValue("i", 1)); + PyModule_AddObject(busdma, "SYNC_POSTREAD", Py_BuildValue("i", 2)); + PyModule_AddObject(busdma, "SYNC_PREWRITE", Py_BuildValue("i", 4)); + PyModule_AddObject(busdma, "SYNC_POSTWRITE", Py_BuildValue("i", 8)); } diff --git a/tools/bus_space/busdma.c b/tools/bus_space/busdma.c index 5ec124f..44c7b68 100644 --- a/tools/bus_space/busdma.c +++ b/tools/bus_space/busdma.c @@ -262,6 +262,20 @@ bd_md_add_seg(struct obj *md, int type, u_long addr, u_long size) return (0); } +static int +bd_md_del_segs(struct obj *md, int type, int unmap) +{ + struct obj *seg, *seg0; + + for (seg = md->u.md.seg[type]; seg != NULL; seg = seg0) { + if (unmap) + munmap((void *)seg->u.seg.address, seg->u.seg.size); + seg0 = seg->u.seg.next; + obj_free(seg); + } + return (0); +} + int bd_md_create(int tid, u_int flags) { @@ -345,6 +359,29 @@ bd_md_load(int mdid, void *buf, u_long len, u_int flags) } int +bd_md_unload(int mdid) +{ + 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_UNLOAD; + ioc.key = md->key; + if (ioctl(md->fd, PROTO_IOC_BUSDMA, &ioc) == -1) + return (errno); + + bd_md_del_segs(md, BUSDMA_MD_VIRT, 0); + bd_md_del_segs(md, BUSDMA_MD_PHYS, 0); + bd_md_del_segs(md, BUSDMA_MD_BUS, 0); + return (0); +} + +int bd_mem_alloc(int tid, u_int flags) { struct proto_ioc_busdma ioc; @@ -409,31 +446,21 @@ int bd_mem_free(int mdid) { struct proto_ioc_busdma ioc; - struct obj *md, *seg, *seg0; + struct obj *md; md = obj_lookup(mdid, OBJ_TYPE_MD); if (md == NULL) return (errno); - for (seg = md->u.md.seg[BUSDMA_MD_VIRT]; seg != NULL; seg = seg0) { - munmap((void *)seg->u.seg.address, seg->u.seg.size); - seg0 = seg->u.seg.next; - obj_free(seg); - } - for (seg = md->u.md.seg[BUSDMA_MD_PHYS]; seg != NULL; seg = seg0) { - seg0 = seg->u.seg.next; - obj_free(seg); - } - for (seg = md->u.md.seg[BUSDMA_MD_BUS]; seg != NULL; seg = seg0) { - seg0 = seg->u.seg.next; - obj_free(seg); - } memset(&ioc, 0, sizeof(ioc)); ioc.request = PROTO_IOC_BUSDMA_MEM_FREE; ioc.key = md->key; if (ioctl(md->fd, PROTO_IOC_BUSDMA, &ioc) == -1) return (errno); + bd_md_del_segs(md, BUSDMA_MD_VIRT, 1); + bd_md_del_segs(md, BUSDMA_MD_PHYS, 0); + bd_md_del_segs(md, BUSDMA_MD_BUS, 0); md->parent->refcnt--; obj_free(md); return (0); @@ -509,3 +536,25 @@ bd_seg_get_size(int sid, u_long *size_p) *size_p = seg->u.seg.size; return (0); } + +int +bd_sync(int mdid, u_int op, u_long base, u_long size) +{ + 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_SYNC; + ioc.key = md->key; + ioc.u.sync.op = op; + ioc.u.sync.base = base; + ioc.u.sync.size = size; + if (ioctl(md->fd, PROTO_IOC_BUSDMA, &ioc) == -1) + return (errno); + + return (0); +} diff --git a/tools/bus_space/busdma.h b/tools/bus_space/busdma.h index 23a9250..cf9d4f2 100644 --- a/tools/bus_space/busdma.h +++ b/tools/bus_space/busdma.h @@ -40,6 +40,7 @@ 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_md_unload(int mdid); int bd_mem_alloc(int tid, u_int flags); int bd_mem_free(int mdid); @@ -50,4 +51,6 @@ int bd_md_next_seg(int mdid, int sid); int bd_seg_get_addr(int sid, u_long *); int bd_seg_get_size(int sid, u_long *); +int bd_sync(int mdid, u_int op, u_long base, u_long size); + #endif /* _TOOLS_BUS_DMA_H_ */ |