Skip site navigation (1)Skip section navigation (2)
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>