svn commit: r284253 - in head/tools/bus_space: . C Python

Marcel Moolenaar marcel at FreeBSD.org
Thu Jun 11 03:02:42 UTC 2015


Author: marcel
Date: Thu Jun 11 03:02:40 2015
New Revision: 284253
URL: https://svnweb.freebsd.org/changeset/base/284253

Log:
  Add accessor functions for iterating over segments. A segment
  can be in bus address space, physical memory space or virtual
  memory space.

Modified:
  head/tools/bus_space/C/lang.c
  head/tools/bus_space/C/libbus.h
  head/tools/bus_space/Python/lang.c
  head/tools/bus_space/busdma.c
  head/tools/bus_space/busdma.h

Modified: head/tools/bus_space/C/lang.c
==============================================================================
--- head/tools/bus_space/C/lang.c	Thu Jun 11 02:29:39 2015	(r284252)
+++ head/tools/bus_space/C/lang.c	Thu Jun 11 03:02:40 2015	(r284253)
@@ -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);
+}

Modified: head/tools/bus_space/C/libbus.h
==============================================================================
--- head/tools/bus_space/C/libbus.h	Thu Jun 11 02:29:39 2015	(r284252)
+++ head/tools/bus_space/C/libbus.h	Thu Jun 11 03:02:40 2015	(r284253)
@@ -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_ */

Modified: head/tools/bus_space/Python/lang.c
==============================================================================
--- head/tools/bus_space/Python/lang.c	Thu Jun 11 02:29:39 2015	(r284252)
+++ head/tools/bus_space/Python/lang.c	Thu Jun 11 03:02:40 2015	(r284253)
@@ -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
 	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 }
 };
 

Modified: head/tools/bus_space/busdma.c
==============================================================================
--- head/tools/bus_space/busdma.c	Thu Jun 11 02:29:39 2015	(r284252)
+++ head/tools/bus_space/busdma.c	Thu Jun 11 03:02:40 2015	(r284253)
@@ -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);
+}

Modified: head/tools/bus_space/busdma.h
==============================================================================
--- head/tools/bus_space/busdma.h	Thu Jun 11 02:29:39 2015	(r284252)
+++ head/tools/bus_space/busdma.h	Thu Jun 11 03:02:40 2015	(r284253)
@@ -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_ */


More information about the svn-src-all mailing list