Add accessor functions for iterating over segments. A segment
can be in bus address space, physical memory space or virtual memory space.
This commit is contained in:
parent
a0be738b20
commit
cc6064789f
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=284253
@ -155,3 +155,40 @@ busdma_mem_free(busdma_md_t md)
|
||||
|
||||
return (bd_mem_free(md));
|
||||
}
|
||||
|
||||
busdma_seg_t
|
||||
busdma_md_first_seg(busdma_md_t md, int space)
|
||||
{
|
||||
busdma_seg_t seg;
|
||||
|
||||
seg = bd_md_first_seg(md, space);
|
||||
return (seg);
|
||||
}
|
||||
|
||||
busdma_seg_t
|
||||
busdma_md_next_seg(busdma_md_t md, busdma_seg_t seg)
|
||||
{
|
||||
|
||||
seg = bd_md_next_seg(md, seg);
|
||||
return (seg);
|
||||
}
|
||||
|
||||
bus_addr_t
|
||||
busdma_seg_get_addr(busdma_seg_t seg)
|
||||
{
|
||||
u_long addr;
|
||||
int error;
|
||||
|
||||
error = bd_seg_get_addr(seg, &addr);
|
||||
return ((error) ? ~0UL : addr);
|
||||
}
|
||||
|
||||
bus_size_t
|
||||
busdma_seg_get_size(busdma_seg_t seg)
|
||||
{
|
||||
u_long size;
|
||||
int error;
|
||||
|
||||
error = bd_seg_get_size(seg, &size);
|
||||
return ((error) ? ~0UL : size);
|
||||
}
|
||||
|
@ -43,6 +43,7 @@ typedef unsigned long bus_addr_t;
|
||||
typedef unsigned long bus_size_t;
|
||||
typedef int busdma_tag_t;
|
||||
typedef int busdma_md_t;
|
||||
typedef int busdma_seg_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,
|
||||
@ -57,4 +58,14 @@ 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);
|
||||
|
||||
#define BUSDMA_MD_BUS_SPACE 0
|
||||
#define BUSDMA_MD_PHYS_SPACE 1
|
||||
#define BUSDMA_MD_VIRT_SPACE 2
|
||||
|
||||
int busdma_md_first_seg(busdma_md_t, int space);
|
||||
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);
|
||||
|
||||
#endif /* _LIBBUS_SPACE_H_ */
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*-
|
||||
* Copyright (c) 2014 Marcel Moolenaar
|
||||
* Copyright (c) 2014, 2015 Marcel Moolenaar
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@ -259,6 +259,68 @@ busdma_mem_free(PyObject *self, PyObject *args)
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
busdma_md_first_seg(PyObject *self, PyObject *args)
|
||||
{
|
||||
int error, mdid, sid, what;
|
||||
|
||||
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);
|
||||
}
|
||||
return (Py_BuildValue("i", sid));
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
busdma_md_next_seg(PyObject *self, PyObject *args)
|
||||
{
|
||||
int error, mdid, sid;
|
||||
|
||||
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);
|
||||
}
|
||||
return (Py_BuildValue("i", sid));
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
busdma_seg_get_addr(PyObject *self, PyObject *args)
|
||||
{
|
||||
u_long addr;
|
||||
int error, sid;
|
||||
|
||||
if (!PyArg_ParseTuple(args, "i", &sid))
|
||||
return (NULL);
|
||||
error = bd_seg_get_addr(sid, &addr);
|
||||
if (error) {
|
||||
PyErr_SetString(PyExc_IOError, strerror(error));
|
||||
return (NULL);
|
||||
}
|
||||
return (Py_BuildValue("k", addr));
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
busdma_seg_get_size(PyObject *self, PyObject *args)
|
||||
{
|
||||
u_long size;
|
||||
int error, sid;
|
||||
|
||||
if (!PyArg_ParseTuple(args, "i", &sid))
|
||||
return (NULL);
|
||||
error = bd_seg_get_size(sid, &size);
|
||||
if (error) {
|
||||
PyErr_SetString(PyExc_IOError, strerror(error));
|
||||
return (NULL);
|
||||
}
|
||||
return (Py_BuildValue("k", size));
|
||||
}
|
||||
|
||||
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." },
|
||||
@ -289,6 +351,15 @@ static PyMethodDef busdma_methods[] = {
|
||||
"Allocate memory according to the DMA constraints." },
|
||||
{ "mem_free", busdma_mem_free, METH_VARARGS,
|
||||
"Free allocated memory." },
|
||||
|
||||
{ "md_first_seg", busdma_md_first_seg, METH_VARARGS,
|
||||
"Return first segment in one of the segment lists." },
|
||||
{ "md_next_seg", busdma_md_next_seg, METH_VARARGS,
|
||||
"Return next segment in the segment list." },
|
||||
{ "seg_get_addr", busdma_seg_get_addr, METH_VARARGS,
|
||||
"Return the address of the segment." },
|
||||
{ "seg_get_size", busdma_seg_get_size, METH_VARARGS,
|
||||
"Return the size of the segment." },
|
||||
{ NULL, NULL, 0, NULL }
|
||||
};
|
||||
|
||||
|
@ -29,6 +29,7 @@ __FBSDID("$FreeBSD$");
|
||||
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/mman.h>
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <limits.h>
|
||||
@ -46,6 +47,7 @@ struct obj {
|
||||
#define OBJ_TYPE_NONE 0
|
||||
#define OBJ_TYPE_TAG 1
|
||||
#define OBJ_TYPE_MD 2
|
||||
#define OBJ_TYPE_SEG 3
|
||||
u_int refcnt;
|
||||
int fd;
|
||||
struct obj *parent;
|
||||
@ -61,9 +63,17 @@ struct obj {
|
||||
unsigned long datarate;
|
||||
} tag;
|
||||
struct {
|
||||
unsigned long physaddr;
|
||||
void *virtaddr;
|
||||
} mem;
|
||||
struct obj *seg[3];
|
||||
int nsegs[3];
|
||||
#define BUSDMA_MD_BUS 0
|
||||
#define BUSDMA_MD_PHYS 1
|
||||
#define BUSDMA_MD_VIRT 2
|
||||
} md;
|
||||
struct {
|
||||
struct obj *next;
|
||||
unsigned long address;
|
||||
unsigned long size;
|
||||
} seg;
|
||||
} u;
|
||||
};
|
||||
|
||||
@ -76,9 +86,8 @@ obj_alloc(u_int type)
|
||||
struct obj **newtbl, *obj;
|
||||
int oid;
|
||||
|
||||
obj = malloc(sizeof(struct obj));
|
||||
obj = calloc(1, sizeof(struct obj));
|
||||
obj->type = type;
|
||||
obj->refcnt = 0;
|
||||
|
||||
for (oid = 0; oid < noids; oid++) {
|
||||
if (oidtbl[oid] == 0)
|
||||
@ -239,6 +248,7 @@ bd_mem_alloc(int tid, u_int flags)
|
||||
{
|
||||
struct proto_ioc_busdma ioc;
|
||||
struct obj *md, *tag;
|
||||
struct obj *bseg, *pseg, *vseg;
|
||||
|
||||
tag = obj_lookup(tid, OBJ_TYPE_TAG);
|
||||
if (tag == NULL)
|
||||
@ -262,10 +272,35 @@ bd_mem_alloc(int tid, u_int flags)
|
||||
md->parent = tag;
|
||||
tag->refcnt++;
|
||||
md->key = ioc.result;
|
||||
md->u.mem.physaddr = ioc.u.mem.physaddr;
|
||||
md->u.mem.virtaddr = mmap(NULL, tag->u.tag.maxsz,
|
||||
|
||||
assert(ioc.u.mem.phys_nsegs == 1);
|
||||
pseg = obj_alloc(OBJ_TYPE_SEG);
|
||||
pseg->refcnt = 1;
|
||||
pseg->parent = md;
|
||||
pseg->u.seg.address = ioc.u.mem.phys_addr;
|
||||
pseg->u.seg.size = tag->u.tag.maxsz;
|
||||
md->u.md.seg[BUSDMA_MD_PHYS] = pseg;
|
||||
md->u.md.nsegs[BUSDMA_MD_PHYS] = ioc.u.mem.phys_nsegs;
|
||||
|
||||
assert(ioc.u.mem.bus_nsegs == 1);
|
||||
bseg = obj_alloc(OBJ_TYPE_SEG);
|
||||
bseg->refcnt = 1;
|
||||
bseg->parent = md;
|
||||
bseg->u.seg.address = ioc.u.mem.bus_addr;
|
||||
bseg->u.seg.size = tag->u.tag.maxsz;
|
||||
md->u.md.seg[BUSDMA_MD_BUS] = bseg;
|
||||
md->u.md.nsegs[BUSDMA_MD_BUS] = ioc.u.mem.bus_nsegs;
|
||||
|
||||
vseg = obj_alloc(OBJ_TYPE_SEG);
|
||||
vseg->refcnt = 1;
|
||||
vseg->parent = md;
|
||||
vseg->u.seg.address = (uintptr_t)mmap(NULL, pseg->u.seg.size,
|
||||
PROT_READ | PROT_WRITE, MAP_NOCORE | MAP_SHARED, md->fd,
|
||||
md->u.mem.physaddr);
|
||||
pseg->u.seg.address);
|
||||
vseg->u.seg.size = pseg->u.seg.size;
|
||||
md->u.md.seg[BUSDMA_MD_VIRT] = vseg;
|
||||
md->u.md.nsegs[BUSDMA_MD_VIRT] = 1;
|
||||
|
||||
return (md->oid);
|
||||
}
|
||||
|
||||
@ -273,14 +308,16 @@ int
|
||||
bd_mem_free(int mdid)
|
||||
{
|
||||
struct proto_ioc_busdma ioc;
|
||||
struct obj *md;
|
||||
struct obj *md, *seg;
|
||||
|
||||
md = obj_lookup(mdid, OBJ_TYPE_MD);
|
||||
if (md == NULL)
|
||||
return (errno);
|
||||
|
||||
if (md->u.mem.virtaddr != MAP_FAILED)
|
||||
munmap(md->u.mem.virtaddr, md->parent->u.tag.maxsz);
|
||||
for (seg = md->u.md.seg[BUSDMA_MD_VIRT];
|
||||
seg != NULL;
|
||||
seg = seg->u.seg.next)
|
||||
munmap((void *)seg->u.seg.address, seg->u.seg.size);
|
||||
memset(&ioc, 0, sizeof(ioc));
|
||||
ioc.request = PROTO_IOC_BUSDMA_MEM_FREE;
|
||||
ioc.key = md->key;
|
||||
@ -291,3 +328,74 @@ bd_mem_free(int mdid)
|
||||
obj_free(md);
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
bd_md_first_seg(int mdid, int space)
|
||||
{
|
||||
struct obj *md, *seg;
|
||||
|
||||
md = obj_lookup(mdid, OBJ_TYPE_MD);
|
||||
if (md == NULL)
|
||||
return (-1);
|
||||
|
||||
if (space != BUSDMA_MD_BUS && space != BUSDMA_MD_PHYS &&
|
||||
space != BUSDMA_MD_VIRT) {
|
||||
errno = EINVAL;
|
||||
return (-1);
|
||||
}
|
||||
seg = md->u.md.seg[space];
|
||||
if (seg == NULL) {
|
||||
errno = ENXIO;
|
||||
return (-1);
|
||||
}
|
||||
return (seg->oid);
|
||||
}
|
||||
|
||||
int
|
||||
bd_md_next_seg(int mdid, int sid)
|
||||
{
|
||||
struct obj *seg;
|
||||
|
||||
seg = obj_lookup(sid, OBJ_TYPE_SEG);
|
||||
if (seg == NULL)
|
||||
return (-1);
|
||||
|
||||
seg = seg->u.seg.next;
|
||||
if (seg == NULL) {
|
||||
errno = ENXIO;
|
||||
return (-1);
|
||||
}
|
||||
return (seg->oid);
|
||||
}
|
||||
|
||||
int
|
||||
bd_seg_get_addr(int sid, u_long *addr_p)
|
||||
{
|
||||
struct obj *seg;
|
||||
|
||||
if (addr_p == NULL)
|
||||
return (EINVAL);
|
||||
|
||||
seg = obj_lookup(sid, OBJ_TYPE_SEG);
|
||||
if (seg == NULL)
|
||||
return (errno);
|
||||
|
||||
*addr_p = seg->u.seg.address;
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
bd_seg_get_size(int sid, u_long *size_p)
|
||||
{
|
||||
struct obj *seg;
|
||||
|
||||
if (size_p == NULL)
|
||||
return (EINVAL);
|
||||
|
||||
seg = obj_lookup(sid, OBJ_TYPE_SEG);
|
||||
if (seg == NULL)
|
||||
return (errno);
|
||||
|
||||
*size_p = seg->u.seg.size;
|
||||
return (0);
|
||||
}
|
||||
|
@ -40,4 +40,10 @@ int bd_tag_destroy(int tid);
|
||||
int bd_mem_alloc(int tid, u_int flags);
|
||||
int bd_mem_free(int mdid);
|
||||
|
||||
int bd_md_first_seg(int mdid, int what);
|
||||
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 *);
|
||||
|
||||
#endif /* _TOOLS_BUS_DMA_H_ */
|
||||
|
Loading…
Reference in New Issue
Block a user