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.
This commit is contained in:
Marcel Moolenaar 2015-07-03 05:47:56 +00:00
parent 42d3ab5d1b
commit 4af242aad1
5 changed files with 146 additions and 24 deletions

View File

@ -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));
}

View File

@ -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_ */

View File

@ -277,6 +277,21 @@ busdma_md_load(PyObject *self, PyObject *args)
Py_RETURN_NONE;
}
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)
{
@ -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)
{
PyObject *bus, *busdma;
Py_InitModule("bus", bus_methods);
Py_InitModule("busdma", busdma_methods);
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));
}

View File

@ -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)
{
@ -344,6 +358,29 @@ bd_md_load(int mdid, void *buf, u_long len, u_int flags)
return (error);
}
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)
{
@ -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);
}

View File

@ -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_ */