Add busdma_mem_alloc & busdma_mem_free.

This commit is contained in:
Marcel Moolenaar 2015-06-08 03:23:20 +00:00
parent 5b53111b63
commit 6f769b730c
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=284146
5 changed files with 206 additions and 74 deletions

View File

@ -137,3 +137,21 @@ busdma_tag_destroy(busdma_tag_t tag)
return (bd_tag_destroy(tag));
}
int
busdma_mem_alloc(busdma_tag_t tag, u_int flags, busdma_md_t *out_p)
{
int res;
res = bd_mem_alloc(tag, flags);
if (res == -1)
return (errno);
*out_p = res;
return (0);
}
int
busdma_mem_free(busdma_md_t md)
{
return (bd_mem_free(md));
}

View File

@ -42,6 +42,7 @@ int bus_space_write_4(int rid, long ofs, uint32_t val);
typedef unsigned long bus_addr_t;
typedef unsigned long bus_size_t;
typedef int busdma_tag_t;
typedef int busdma_md_t;
int busdma_tag_create(const char *dev, bus_addr_t align, bus_addr_t bndry,
bus_addr_t maxaddr, bus_size_t maxsz, u_int nsegs,
@ -53,4 +54,7 @@ int busdma_tag_derive(busdma_tag_t tag, bus_addr_t align, bus_addr_t bndry,
busdma_tag_t *out_p);
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);
#endif /* _LIBBUS_SPACE_H_ */

View File

@ -178,12 +178,13 @@ static PyObject *
busdma_tag_create(PyObject *self, PyObject *args)
{
char *dev;
long align, bndry, maxaddr, maxsz, maxsegsz;
int tid, nsegs, datarate, flags;
u_long align, bndry, maxaddr, maxsz, maxsegsz;
u_int nsegs, datarate, flags;
int tid;
if (!PyArg_ParseTuple(args, "sllllilii", &dev, &align, &bndry,
if (!PyArg_ParseTuple(args, "skkkkIkII", &dev, &align, &bndry,
&maxaddr, &maxsz, &nsegs, &maxsegsz, &datarate, &flags))
return (NULL);
return (NULL);
tid = bd_tag_create(dev, align, bndry, maxaddr, maxsz, nsegs,
maxsegsz, datarate, flags);
if (tid == -1) {
@ -196,10 +197,11 @@ busdma_tag_create(PyObject *self, PyObject *args)
static PyObject *
busdma_tag_derive(PyObject *self, PyObject *args)
{
long align, bndry, maxaddr, maxsz, maxsegsz;
int ptid, tid, nsegs, datarate, flags;
u_long align, bndry, maxaddr, maxsz, maxsegsz;
u_int nsegs, datarate, flags;
int ptid, tid;
if (!PyArg_ParseTuple(args, "illllilii", &ptid, &align, &bndry,
if (!PyArg_ParseTuple(args, "ikkkkIkII", &ptid, &align, &bndry,
&maxaddr, &maxsz, &nsegs, &maxsegsz, &datarate, &flags))
return (NULL);
tid = bd_tag_derive(ptid, align, bndry, maxaddr, maxsz, nsegs,
@ -226,6 +228,37 @@ busdma_tag_destroy(PyObject *self, PyObject *args)
Py_RETURN_NONE;
}
static PyObject *
busdma_mem_alloc(PyObject *self, PyObject *args)
{
u_int flags;
int mdid, tid;
if (!PyArg_ParseTuple(args, "iI", &tid, &flags))
return (NULL);
mdid = bd_mem_alloc(tid, flags);
if (mdid == -1) {
PyErr_SetString(PyExc_IOError, strerror(errno));
return (NULL);
}
return (Py_BuildValue("i", mdid));
}
static PyObject *
busdma_mem_free(PyObject *self, PyObject *args)
{
int error, mdid;
if (!PyArg_ParseTuple(args, "i", &mdid))
return (NULL);
error = bd_mem_free(mdid);
if (error) {
PyErr_SetString(PyExc_IOError, strerror(error));
return (NULL);
}
Py_RETURN_NONE;
}
static PyMethodDef bus_space_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." },
@ -246,9 +279,16 @@ static PyMethodDef bus_space_methods[] = {
};
static PyMethodDef busdma_methods[] = {
{ "tag_create", busdma_tag_create, METH_VARARGS, "Create a root tag." },
{ "tag_derive", busdma_tag_derive, METH_VARARGS, "Derive a child tag." },
{ "tag_destroy", busdma_tag_destroy, METH_VARARGS, "Destroy a tag." },
{ "tag_create", busdma_tag_create, METH_VARARGS,
"Create a root tag." },
{ "tag_derive", busdma_tag_derive, METH_VARARGS,
"Derive a child tag." },
{ "tag_destroy", busdma_tag_destroy, METH_VARARGS,
"Destroy a tag." },
{ "mem_alloc", busdma_mem_alloc, METH_VARARGS,
"Allocate memory according to the DMA constraints." },
{ "mem_free", busdma_mem_free, METH_VARARGS,
"Free allocated memory." },
{ NULL, NULL, 0, NULL }
};

View File

@ -40,82 +40,101 @@ __FBSDID("$FreeBSD$");
#include "../../sys/dev/proto/proto_dev.h"
struct tag {
int tid;
struct obj {
int oid;
u_int type;
#define OBJ_TYPE_NONE 0
#define OBJ_TYPE_TAG 1
#define OBJ_TYPE_MD 2
u_int refcnt;
int fd;
struct tag *ptag;
struct obj *parent;
u_long key;
u_long align;
u_long bndry;
u_long maxaddr;
union {
struct {
unsigned long align;
unsigned long bndry;
unsigned long maxaddr;
unsigned long maxsz;
unsigned long maxsegsz;
unsigned long nsegs;
unsigned long datarate;
} tag;
struct {
} md;
} u;
};
static struct tag **tidtbl = NULL;
static int ntids = 0;
static struct obj **oidtbl = NULL;
static int noids = 0;
static struct tag *
tag_alloc(void)
static struct obj *
obj_alloc(u_int type)
{
struct tag **newtbl, *tag;
int tid;
struct obj **newtbl, *obj;
int oid;
tag = malloc(sizeof(struct tag));
tag->refcnt = 0;
obj = malloc(sizeof(struct obj));
obj->type = type;
obj->refcnt = 0;
for (tid = 0; tid < ntids; tid++) {
if (tidtbl[tid] == 0)
for (oid = 0; oid < noids; oid++) {
if (oidtbl[oid] == 0)
break;
}
if (tid == ntids) {
newtbl = realloc(tidtbl, sizeof(struct tag *) * (ntids + 1));
if (oid == noids) {
newtbl = realloc(oidtbl, sizeof(struct obj *) * (noids + 1));
if (newtbl == NULL) {
free(tag);
free(obj);
return (NULL);
}
tidtbl = newtbl;
ntids++;
oidtbl = newtbl;
noids++;
}
tidtbl[tid] = tag;
tag->tid = tid;
return (tag);
oidtbl[oid] = obj;
obj->oid = oid;
return (obj);
}
static int
tag_free(struct tag *tag)
obj_free(struct obj *obj)
{
tidtbl[tag->tid] = NULL;
free(tag);
oidtbl[obj->oid] = NULL;
free(obj);
return (0);
}
static struct tag *
tid_lookup(int tid)
static struct obj *
obj_lookup(int oid, u_int type)
{
struct tag *tag;
struct obj *obj;
if (tid < 0 || tid >= ntids) {
if (oid < 0 || oid >= noids) {
errno = EINVAL;
return (NULL);
}
tag = tidtbl[tid];
if (tag->refcnt == 0) {
obj = oidtbl[oid];
if (obj->refcnt == 0) {
errno = ENXIO;
return (NULL);
}
return (tag);
if (type != OBJ_TYPE_NONE && obj->type != type) {
errno = ENODEV;
return (NULL);
}
return (obj);
}
struct tag *
bd_tag_new(struct tag *ptag, int fd, u_long align, u_long bndry,
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)
{
struct proto_ioc_busdma ioc;
struct tag *tag;
struct obj *tag;
tag = tag_alloc();
tag = obj_alloc(OBJ_TYPE_TAG);
if (tag == NULL)
return (NULL);
@ -132,16 +151,20 @@ bd_tag_new(struct tag *ptag, int fd, u_long align, u_long bndry,
ioc.u.tag.datarate = datarate;
ioc.u.tag.flags = flags;
if (ioctl(fd, PROTO_IOC_BUSDMA, &ioc) == -1) {
tag_free(tag);
obj_free(tag);
return (NULL);
}
tag->refcnt = 1;
tag->fd = fd;
tag->ptag = ptag;
tag->key = ioc.key;
tag->align = ioc.u.tag.align;
tag->bndry = ioc.u.tag.bndry;
tag->maxaddr = ioc.u.tag.maxaddr;
tag->parent = ptag;
tag->key = ioc.result;
tag->u.tag.align = ioc.u.tag.align;
tag->u.tag.bndry = ioc.u.tag.bndry;
tag->u.tag.maxaddr = ioc.u.tag.maxaddr;
tag->u.tag.maxsz = ioc.u.tag.maxsz;
tag->u.tag.maxsegsz = ioc.u.tag.maxsegsz;
tag->u.tag.nsegs = ioc.u.tag.nsegs;
tag->u.tag.datarate = ioc.u.tag.datarate;
return (tag);
}
@ -149,7 +172,7 @@ int
bd_tag_create(const char *dev, u_long align, u_long bndry, u_long maxaddr,
u_long maxsz, u_int nsegs, u_long maxsegsz, u_int datarate, u_int flags)
{
struct tag *tag;
struct obj *tag;
int fd;
fd = open(dev, O_RDWR);
@ -162,16 +185,16 @@ bd_tag_create(const char *dev, u_long align, u_long bndry, u_long maxaddr,
close(fd);
return (-1);
}
return (tag->tid);
return (tag->oid);
}
int
bd_tag_derive(int ptid, u_long align, u_long bndry, u_long maxaddr,
u_long maxsz, u_int nsegs, u_long maxsegsz, u_int datarate, u_int flags)
{
struct tag *ptag, *tag;
struct obj *ptag, *tag;
ptag = tid_lookup(ptid);
ptag = obj_lookup(ptid, OBJ_TYPE_TAG);
if (ptag == NULL)
return (-1);
@ -179,20 +202,17 @@ bd_tag_derive(int ptid, u_long align, u_long bndry, u_long maxaddr,
maxsegsz, datarate, flags);
if (tag == NULL)
return (-1);
while (ptag != NULL) {
ptag->refcnt++;
ptag = ptag->ptag;
}
return (tag->tid);
ptag->refcnt++;
return (tag->oid);
}
int
bd_tag_destroy(int tid)
{
struct proto_ioc_busdma ioc;
struct tag *ptag, *tag;
struct obj *ptag, *tag;
tag = tid_lookup(tid);
tag = obj_lookup(tid, OBJ_TYPE_TAG);
if (tag == NULL)
return (errno);
if (tag->refcnt > 1)
@ -204,15 +224,62 @@ bd_tag_destroy(int tid)
if (ioctl(tag->fd, PROTO_IOC_BUSDMA, &ioc) == -1)
return (errno);
ptag = tag->ptag;
if (ptag == NULL)
if (tag->parent != NULL)
tag->parent->refcnt--;
else
close(tag->fd);
else {
do {
ptag->refcnt--;
ptag = ptag->ptag;
} while (ptag != NULL);
}
tag_free(tag);
obj_free(tag);
return (0);
}
int
bd_mem_alloc(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_MEM_ALLOC;
ioc.u.mem.tag = tag->key;
ioc.u.mem.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_mem_free(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_MEM_FREE;
ioc.key = md->key;
if (ioctl(md->fd, PROTO_IOC_BUSDMA, &ioc) == -1)
return (errno);
md->parent->refcnt--;
obj_free(md);
return (0);
}

View File

@ -37,4 +37,7 @@ 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_mem_alloc(int tid, u_int flags);
int bd_mem_free(int mdid);
#endif /* _TOOLS_BUS_DMA_H_ */