Date: Sat, 6 Jun 2015 16:14:04 +0000 (UTC) From: Marcel Moolenaar <marcel@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r284080 - in head/tools/bus_space: . C Python Message-ID: <201506061614.t56GE4SV025621@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: marcel Date: Sat Jun 6 16:14:03 2015 New Revision: 284080 URL: https://svnweb.freebsd.org/changeset/base/284080 Log: Add DMA tag management to the C library and Python binding. Added: head/tools/bus_space/busdma.c (contents, props changed) head/tools/bus_space/busdma.h (contents, props changed) Modified: head/tools/bus_space/C/Makefile head/tools/bus_space/C/lang.c head/tools/bus_space/C/libbus_space.h head/tools/bus_space/Makefile.inc head/tools/bus_space/Python/lang.c Modified: head/tools/bus_space/C/Makefile ============================================================================== --- head/tools/bus_space/C/Makefile Sat Jun 6 16:09:25 2015 (r284079) +++ head/tools/bus_space/C/Makefile Sat Jun 6 16:14:03 2015 (r284080) @@ -3,6 +3,7 @@ LIB= bus_space SHLIB_MAJOR= 0 SRCS= lang.c +INCS= libbus_space.h CFLAGS+= -I${.CURDIR}/.. Modified: head/tools/bus_space/C/lang.c ============================================================================== --- head/tools/bus_space/C/lang.c Sat Jun 6 16:09:25 2015 (r284079) +++ head/tools/bus_space/C/lang.c Sat Jun 6 16:14:03 2015 (r284080) @@ -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, l 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)); +} + Modified: head/tools/bus_space/C/libbus_space.h ============================================================================== --- head/tools/bus_space/C/libbus_space.h Sat Jun 6 16:09:25 2015 (r284079) +++ head/tools/bus_space/C/libbus_space.h Sat Jun 6 16:14:03 2015 (r284080) @@ -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_ */ Modified: head/tools/bus_space/Makefile.inc ============================================================================== --- head/tools/bus_space/Makefile.inc Sat Jun 6 16:09:25 2015 (r284079) +++ head/tools/bus_space/Makefile.inc Sat Jun 6 16:14:03 2015 (r284080) @@ -1,4 +1,4 @@ # $FreeBSD$ .PATH: ${.CURDIR}/.. -SRCS+= bus_space.c +SRCS+= bus_space.c busdma.c Modified: head/tools/bus_space/Python/lang.c ============================================================================== --- head/tools/bus_space/Python/lang.c Sat Jun 6 16:09:25 2015 (r284079) +++ head/tools/bus_space/Python/lang.c Sat Jun 6 16:14:03 2015 (r284080) @@ -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 * 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); } Added: head/tools/bus_space/busdma.c ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ head/tools/bus_space/busdma.c Sat Jun 6 16:14:03 2015 (r284080) @@ -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); +} Added: head/tools/bus_space/busdma.h ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ head/tools/bus_space/busdma.h Sat Jun 6 16:14:03 2015 (r284080) @@ -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_ */
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201506061614.t56GE4SV025621>