summaryrefslogtreecommitdiffstats
path: root/tools/bus_space
diff options
context:
space:
mode:
authormarcel <marcel@FreeBSD.org>2015-06-08 03:23:20 +0000
committermarcel <marcel@FreeBSD.org>2015-06-08 03:23:20 +0000
commit440bb648898820e493ba0291411c6cd04de5c277 (patch)
tree5f5223455f8675c7e07131edae60a2f0560bad61 /tools/bus_space
parent1698c446dcd301bd89394c4faf4327cdc9537bc2 (diff)
downloadFreeBSD-src-440bb648898820e493ba0291411c6cd04de5c277.zip
FreeBSD-src-440bb648898820e493ba0291411c6cd04de5c277.tar.gz
Add busdma_mem_alloc & busdma_mem_free.
Diffstat (limited to 'tools/bus_space')
-rw-r--r--tools/bus_space/C/lang.c18
-rw-r--r--tools/bus_space/C/libbus_space.h4
-rw-r--r--tools/bus_space/Python/lang.c60
-rw-r--r--tools/bus_space/busdma.c193
-rw-r--r--tools/bus_space/busdma.h3
5 files changed, 205 insertions, 73 deletions
diff --git a/tools/bus_space/C/lang.c b/tools/bus_space/C/lang.c
index 84fd780..9d3c7fb 100644
--- a/tools/bus_space/C/lang.c
+++ b/tools/bus_space/C/lang.c
@@ -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));
+}
diff --git a/tools/bus_space/C/libbus_space.h b/tools/bus_space/C/libbus_space.h
index c7ff06c..5522238 100644
--- a/tools/bus_space/C/libbus_space.h
+++ b/tools/bus_space/C/libbus_space.h
@@ -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_ */
diff --git a/tools/bus_space/Python/lang.c b/tools/bus_space/Python/lang.c
index a515549..2247360 100644
--- a/tools/bus_space/Python/lang.c
+++ b/tools/bus_space/Python/lang.c
@@ -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 }
};
diff --git a/tools/bus_space/busdma.c b/tools/bus_space/busdma.c
index 1c502e1..2b1b7ff 100644
--- a/tools/bus_space/busdma.c
+++ b/tools/bus_space/busdma.c
@@ -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);
+ 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);
}
- tag_free(tag);
+
+ 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);
}
diff --git a/tools/bus_space/busdma.h b/tools/bus_space/busdma.h
index 7b8686e..357cb30 100644
--- a/tools/bus_space/busdma.h
+++ b/tools/bus_space/busdma.h
@@ -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_ */
OpenPOWER on IntegriCloud