mirror of
https://git.FreeBSD.org/src.git
synced 2025-01-29 16:44:03 +00:00
Add DMA tag management to the C library and Python binding.
This commit is contained in:
parent
4f027abddb
commit
9c2cdb1a7e
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=284080
@ -3,6 +3,7 @@
|
||||
LIB= bus_space
|
||||
SHLIB_MAJOR= 0
|
||||
SRCS= lang.c
|
||||
INCS= libbus_space.h
|
||||
|
||||
CFLAGS+= -I${.CURDIR}/..
|
||||
|
||||
|
@ -31,9 +31,10 @@ __FBSDID("$FreeBSD$");
|
||||
#include <errno.h>
|
||||
|
||||
#include "bus_space.h"
|
||||
#include "busdma.h"
|
||||
#include "libbus_space.h"
|
||||
|
||||
int
|
||||
int16_t
|
||||
bus_space_read_1(int rid, long ofs)
|
||||
{
|
||||
uint8_t val;
|
||||
@ -41,7 +42,7 @@ bus_space_read_1(int rid, long ofs)
|
||||
return ((!bs_read(rid, ofs, &val, sizeof(val))) ? -1 : (int)val);
|
||||
}
|
||||
|
||||
int
|
||||
int32_t
|
||||
bus_space_read_2(int rid, long ofs)
|
||||
{
|
||||
uint16_t val;
|
||||
@ -98,3 +99,41 @@ bus_space_subregion(int rid, long ofs, long sz)
|
||||
|
||||
return (bs_subregion(rid, ofs, sz));
|
||||
}
|
||||
|
||||
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, bus_size_t maxsegsz,
|
||||
u_int datarate, u_int flags, busdma_tag_t *out_p)
|
||||
{
|
||||
int res;
|
||||
|
||||
res = bd_tag_create(dev, align, bndry, maxaddr, maxsz, nsegs, maxsegsz,
|
||||
datarate, flags);
|
||||
if (res == -1)
|
||||
return (errno);
|
||||
*out_p = res;
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
busdma_tag_derive(busdma_tag_t tag, bus_addr_t align, bus_addr_t bndry,
|
||||
bus_addr_t maxaddr, bus_size_t maxsz, u_int nsegs, bus_size_t maxsegsz,
|
||||
u_int datarate, u_int flags, busdma_tag_t *out_p)
|
||||
{
|
||||
int res;
|
||||
|
||||
res = bd_tag_derive(tag, align, bndry, maxaddr, maxsz, nsegs, maxsegsz,
|
||||
datarate, flags);
|
||||
if (res == -1)
|
||||
return (errno);
|
||||
*out_p = res;
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
busdma_tag_destroy(busdma_tag_t tag)
|
||||
{
|
||||
|
||||
return (bd_tag_destroy(tag));
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
@ -29,14 +29,28 @@
|
||||
#ifndef _LIBBUS_SPACE_H_
|
||||
#define _LIBBUS_SPACE_H_
|
||||
|
||||
int bus_space_map(const char *dev);
|
||||
int bus_space_read_1(int rid, long ofs);
|
||||
int bus_space_read_2(int rid, long ofs);
|
||||
int bus_space_map(const char *dev);
|
||||
int16_t bus_space_read_1(int rid, long ofs);
|
||||
int32_t bus_space_read_2(int rid, long ofs);
|
||||
int64_t bus_space_read_4(int rid, long ofs);
|
||||
int bus_space_subregion(int rid, long ofs, long sz);
|
||||
int bus_space_unmap(int rid);
|
||||
int bus_space_write_1(int rid, long ofs, uint8_t val);
|
||||
int bus_space_write_2(int rid, long ofs, uint16_t val);
|
||||
int bus_space_write_4(int rid, long ofs, uint32_t val);
|
||||
int bus_space_subregion(int rid, long ofs, long sz);
|
||||
int bus_space_unmap(int rid);
|
||||
int bus_space_write_1(int rid, long ofs, uint8_t val);
|
||||
int bus_space_write_2(int rid, long ofs, uint16_t val);
|
||||
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;
|
||||
|
||||
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,
|
||||
bus_size_t maxsegsz, u_int datarate, u_int flags,
|
||||
busdma_tag_t *out_p);
|
||||
int busdma_tag_derive(busdma_tag_t tag, bus_addr_t align, bus_addr_t bndry,
|
||||
bus_addr_t maxaddr, bus_size_t maxsz, u_int nsegs,
|
||||
bus_size_t maxsegsz, u_int datarate, u_int flags,
|
||||
busdma_tag_t *out_p);
|
||||
int busdma_tag_destroy(busdma_tag_t tag);
|
||||
|
||||
#endif /* _LIBBUS_SPACE_H_ */
|
||||
|
@ -1,4 +1,4 @@
|
||||
# $FreeBSD$
|
||||
|
||||
.PATH: ${.CURDIR}/..
|
||||
SRCS+= bus_space.c
|
||||
SRCS+= bus_space.c busdma.c
|
||||
|
@ -30,6 +30,7 @@ __FBSDID("$FreeBSD$");
|
||||
#include <Python.h>
|
||||
|
||||
#include "bus_space.h"
|
||||
#include "busdma.h"
|
||||
|
||||
static PyObject *
|
||||
bus_read_1(PyObject *self, PyObject *args)
|
||||
@ -173,6 +174,58 @@ bus_subregion(PyObject *self, PyObject *args)
|
||||
return (Py_BuildValue("i", rid));
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
busdma_tag_create(PyObject *self, PyObject *args)
|
||||
{
|
||||
char *dev;
|
||||
long align, bndry, maxaddr, maxsz, maxsegsz;
|
||||
int tid, nsegs, datarate, flags;
|
||||
|
||||
if (!PyArg_ParseTuple(args, "sllllilii", &dev, &align, &bndry,
|
||||
&maxaddr, &maxsz, &nsegs, &maxsegsz, &datarate, &flags))
|
||||
return (NULL);
|
||||
tid = bd_tag_create(dev, align, bndry, maxaddr, maxsz, nsegs,
|
||||
maxsegsz, datarate, flags);
|
||||
if (tid == -1) {
|
||||
PyErr_SetString(PyExc_IOError, strerror(errno));
|
||||
return (NULL);
|
||||
}
|
||||
return (Py_BuildValue("i", tid));
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
busdma_tag_derive(PyObject *self, PyObject *args)
|
||||
{
|
||||
long align, bndry, maxaddr, maxsz, maxsegsz;
|
||||
int ptid, tid, nsegs, datarate, flags;
|
||||
|
||||
if (!PyArg_ParseTuple(args, "illllilii", &ptid, &align, &bndry,
|
||||
&maxaddr, &maxsz, &nsegs, &maxsegsz, &datarate, &flags))
|
||||
return (NULL);
|
||||
tid = bd_tag_derive(ptid, align, bndry, maxaddr, maxsz, nsegs,
|
||||
maxsegsz, datarate, flags);
|
||||
if (tid == -1) {
|
||||
PyErr_SetString(PyExc_IOError, strerror(errno));
|
||||
return (NULL);
|
||||
}
|
||||
return (Py_BuildValue("i", tid));
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
busdma_tag_destroy(PyObject *self, PyObject *args)
|
||||
{
|
||||
int error, tid;
|
||||
|
||||
if (!PyArg_ParseTuple(args, "i", &tid))
|
||||
return (NULL);
|
||||
error = bd_tag_destroy(tid);
|
||||
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." },
|
||||
@ -192,9 +245,17 @@ static PyMethodDef bus_space_methods[] = {
|
||||
{ NULL, NULL, 0, NULL }
|
||||
};
|
||||
|
||||
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." },
|
||||
{ NULL, NULL, 0, NULL }
|
||||
};
|
||||
|
||||
PyMODINIT_FUNC
|
||||
initbus_space(void)
|
||||
{
|
||||
|
||||
Py_InitModule("bus_space", bus_space_methods);
|
||||
Py_InitModule("busdma", busdma_methods);
|
||||
}
|
||||
|
218
tools/bus_space/busdma.c
Normal file
218
tools/bus_space/busdma.c
Normal file
@ -0,0 +1,218 @@
|
||||
/*-
|
||||
* Copyright (c) 2015 Marcel Moolenaar
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/mman.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <limits.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "busdma.h"
|
||||
|
||||
#include "../../sys/dev/proto/proto_dev.h"
|
||||
|
||||
struct tag {
|
||||
int tid;
|
||||
u_int refcnt;
|
||||
int fd;
|
||||
struct tag *ptag;
|
||||
u_long key;
|
||||
u_long align;
|
||||
u_long bndry;
|
||||
u_long maxaddr;
|
||||
};
|
||||
|
||||
static struct tag **tidtbl = NULL;
|
||||
static int ntids = 0;
|
||||
|
||||
static struct tag *
|
||||
tag_alloc(void)
|
||||
{
|
||||
struct tag **newtbl, *tag;
|
||||
int tid;
|
||||
|
||||
tag = malloc(sizeof(struct tag));
|
||||
tag->refcnt = 0;
|
||||
|
||||
for (tid = 0; tid < ntids; tid++) {
|
||||
if (tidtbl[tid] == 0)
|
||||
break;
|
||||
}
|
||||
if (tid == ntids) {
|
||||
newtbl = realloc(tidtbl, sizeof(struct tag *) * (ntids + 1));
|
||||
if (newtbl == NULL) {
|
||||
free(tag);
|
||||
return (NULL);
|
||||
}
|
||||
tidtbl = newtbl;
|
||||
ntids++;
|
||||
}
|
||||
tidtbl[tid] = tag;
|
||||
tag->tid = tid;
|
||||
return (tag);
|
||||
}
|
||||
|
||||
static int
|
||||
tag_free(struct tag *tag)
|
||||
{
|
||||
|
||||
tidtbl[tag->tid] = NULL;
|
||||
free(tag);
|
||||
return (0);
|
||||
}
|
||||
|
||||
static struct tag *
|
||||
tid_lookup(int tid)
|
||||
{
|
||||
struct tag *tag;
|
||||
|
||||
if (tid < 0 || tid >= ntids) {
|
||||
errno = EINVAL;
|
||||
return (NULL);
|
||||
}
|
||||
tag = tidtbl[tid];
|
||||
if (tag->refcnt == 0) {
|
||||
errno = ENXIO;
|
||||
return (NULL);
|
||||
}
|
||||
return (tag);
|
||||
}
|
||||
|
||||
struct tag *
|
||||
bd_tag_new(struct tag *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;
|
||||
|
||||
tag = tag_alloc();
|
||||
if (tag == NULL)
|
||||
return (NULL);
|
||||
|
||||
memset(&ioc, 0, sizeof(ioc));
|
||||
ioc.request = (ptag != NULL) ? PROTO_IOC_BUSDMA_TAG_DERIVE :
|
||||
PROTO_IOC_BUSDMA_TAG_CREATE;
|
||||
ioc.key = (ptag != NULL) ? ptag->key : 0;
|
||||
ioc.u.tag.align = align;
|
||||
ioc.u.tag.bndry = bndry;
|
||||
ioc.u.tag.maxaddr = maxaddr;
|
||||
ioc.u.tag.maxsz = maxsz;
|
||||
ioc.u.tag.nsegs = nsegs;
|
||||
ioc.u.tag.maxsegsz = maxsegsz;
|
||||
ioc.u.tag.datarate = datarate;
|
||||
ioc.u.tag.flags = flags;
|
||||
if (ioctl(fd, PROTO_IOC_BUSDMA, &ioc) == -1) {
|
||||
tag_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;
|
||||
return (tag);
|
||||
}
|
||||
|
||||
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;
|
||||
int fd;
|
||||
|
||||
fd = open(dev, O_RDWR);
|
||||
if (fd == -1)
|
||||
return (-1);
|
||||
|
||||
tag = bd_tag_new(NULL, fd, align, bndry, maxaddr, maxsz, nsegs,
|
||||
maxsegsz, datarate, flags);
|
||||
if (tag == NULL) {
|
||||
close(fd);
|
||||
return (-1);
|
||||
}
|
||||
return (tag->tid);
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
ptag = tid_lookup(ptid);
|
||||
if (ptag == NULL)
|
||||
return (-1);
|
||||
|
||||
tag = bd_tag_new(ptag, ptag->fd, align, bndry, maxaddr, maxsz, nsegs,
|
||||
maxsegsz, datarate, flags);
|
||||
if (tag == NULL)
|
||||
return (-1);
|
||||
while (ptag != NULL) {
|
||||
ptag->refcnt++;
|
||||
ptag = ptag->ptag;
|
||||
}
|
||||
return (tag->tid);
|
||||
}
|
||||
|
||||
int
|
||||
bd_tag_destroy(int tid)
|
||||
{
|
||||
struct proto_ioc_busdma ioc;
|
||||
struct tag *ptag, *tag;
|
||||
|
||||
tag = tid_lookup(tid);
|
||||
if (tag == NULL)
|
||||
return (errno);
|
||||
if (tag->refcnt > 1)
|
||||
return (EBUSY);
|
||||
|
||||
memset(&ioc, 0, sizeof(ioc));
|
||||
ioc.request = PROTO_IOC_BUSDMA_TAG_DESTROY;
|
||||
ioc.key = tag->key;
|
||||
if (ioctl(tag->fd, PROTO_IOC_BUSDMA, &ioc) == -1)
|
||||
return (errno);
|
||||
|
||||
ptag = tag->ptag;
|
||||
if (ptag == NULL)
|
||||
close(tag->fd);
|
||||
else {
|
||||
do {
|
||||
ptag->refcnt--;
|
||||
ptag = ptag->ptag;
|
||||
} while (ptag != NULL);
|
||||
}
|
||||
tag_free(tag);
|
||||
return (0);
|
||||
}
|
40
tools/bus_space/busdma.h
Normal file
40
tools/bus_space/busdma.h
Normal file
@ -0,0 +1,40 @@
|
||||
/*-
|
||||
* Copyright (c) 2015 Marcel Moolenaar
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#ifndef _TOOLS_BUS_DMA_H_
|
||||
#define _TOOLS_BUS_DMA_H_
|
||||
|
||||
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);
|
||||
int bd_tag_derive(int tid, u_long align, u_long bndry, u_long maxaddr,
|
||||
u_long maxsz, u_int nsegs, u_long maxsegsz, u_int datarate,
|
||||
u_int flags);
|
||||
int bd_tag_destroy(int tid);
|
||||
|
||||
#endif /* _TOOLS_BUS_DMA_H_ */
|
Loading…
Reference in New Issue
Block a user