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:
parent
42d3ab5d1b
commit
4af242aad1
@ -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));
|
||||
}
|
||||
|
@ -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_ */
|
||||
|
@ -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));
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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_ */
|
||||
|
Loading…
Reference in New Issue
Block a user