Index: head/tools/bus_space/C/lang.c =================================================================== --- head/tools/bus_space/C/lang.c (revision 285902) +++ head/tools/bus_space/C/lang.c (revision 285903) @@ -1,234 +1,234 @@ /*- * Copyright (c) 2014 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 __FBSDID("$FreeBSD$"); #include #include #include "bus.h" #include "busdma.h" #include "libbus.h" int16_t bus_read_1(int rid, long ofs) { uint8_t val; return ((!bs_read(rid, ofs, &val, sizeof(val))) ? -1 : (int)val); } int32_t bus_read_2(int rid, long ofs) { uint16_t val; return ((!bs_read(rid, ofs, &val, sizeof(val))) ? -1 : (int)val); } int64_t bus_read_4(int rid, long ofs) { uint32_t val; return ((!bs_read(rid, ofs, &val, sizeof(val))) ? -1 : (int64_t)val); } int bus_write_1(int rid, long ofs, uint8_t val) { return ((!bs_write(rid, ofs, &val, sizeof(val))) ? errno : 0); } int bus_write_2(int rid, long ofs, uint16_t val) { return ((!bs_write(rid, ofs, &val, sizeof(val))) ? errno : 0); } int bus_write_4(int rid, long ofs, uint32_t val) { return ((!bs_write(rid, ofs, &val, sizeof(val))) ? errno : 0); } int -bus_map(const char *dev) +bus_map(const char *dev, const char *resource) { - return (bs_map(dev)); + return (bs_map(dev, resource)); } int bus_unmap(int rid) { return ((!bs_unmap(rid)) ? errno : 0); } int bus_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)); } int busdma_mem_alloc(busdma_tag_t tag, u_int flags, busdma_md_t *out_p) { int res; res = bd_mem_alloc(tag, flags); if (res == -1) return (errno); *out_p = res; return (0); } int busdma_mem_free(busdma_md_t md) { return (bd_mem_free(md)); } int busdma_md_create(busdma_tag_t tag, u_int flags, busdma_md_t *out_p) { int res; res = bd_md_create(tag, flags); if (res == -1) return (errno); *out_p = res; return (0); } int busdma_md_destroy(busdma_md_t md) { return (bd_md_destroy(md)); } int busdma_md_load(busdma_md_t md, void *buf, size_t len, u_int flags) { return (bd_md_load(md, buf, len, flags)); } int busdma_md_unload(busdma_md_t md) { return (bd_md_unload(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); } int busdma_sync(busdma_md_t md, int op, bus_addr_t base, bus_size_t size) { return (bd_sync(md, op, base, size)); } Index: head/tools/bus_space/C/libbus.h =================================================================== --- head/tools/bus_space/C/libbus.h (revision 285902) +++ head/tools/bus_space/C/libbus.h (revision 285903) @@ -1,83 +1,83 @@ /*- * Copyright (c) 2014, 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 _LIBBUS_SPACE_H_ #define _LIBBUS_SPACE_H_ -int bus_map(const char *dev); +int bus_map(const char *dev, const char *resource); int16_t bus_read_1(int rid, long ofs); int32_t bus_read_2(int rid, long ofs); int64_t bus_read_4(int rid, long ofs); int bus_subregion(int rid, long ofs, long sz); int bus_unmap(int rid); int bus_write_1(int rid, long ofs, uint8_t val); int bus_write_2(int rid, long ofs, uint16_t val); int bus_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; 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, 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); int busdma_mem_alloc(busdma_tag_t tag, u_int flags, busdma_md_t *out_p); int busdma_mem_free(busdma_md_t md); int busdma_md_create(busdma_tag_t tag, u_int flags, busdma_md_t *out_p); int busdma_md_destroy(busdma_md_t md); int busdma_md_load(busdma_md_t md, void *buf, size_t len, u_int flags); int busdma_md_unload(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); #define BUSDMA_SYNC_PREREAD 1 #define BUSDMA_SYNC_POSTREAD 2 #define BUSDMA_SYNC_PREWRITE 4 #define BUSDMA_SYNC_POSTWRITE 8 int busdma_sync(busdma_md_t md, int op, bus_addr_t, bus_size_t); #endif /* _LIBBUS_SPACE_H_ */ Index: head/tools/bus_space/Python/lang.c =================================================================== --- head/tools/bus_space/Python/lang.c (revision 285902) +++ head/tools/bus_space/Python/lang.c (revision 285903) @@ -1,477 +1,477 @@ /*- * Copyright (c) 2014, 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 __FBSDID("$FreeBSD$"); #include #include "bus.h" #include "busdma.h" static PyObject * bus_read_1(PyObject *self, PyObject *args) { long ofs; int rid; uint8_t val; if (!PyArg_ParseTuple(args, "il", &rid, &ofs)) return (NULL); if (!bs_read(rid, ofs, &val, sizeof(val))) { PyErr_SetString(PyExc_IOError, strerror(errno)); return (NULL); } return (Py_BuildValue("B", val)); } static PyObject * bus_read_2(PyObject *self, PyObject *args) { long ofs; int rid; uint16_t val; if (!PyArg_ParseTuple(args, "il", &rid, &ofs)) return (NULL); if (!bs_read(rid, ofs, &val, sizeof(val))) { PyErr_SetString(PyExc_IOError, strerror(errno)); return (NULL); } return (Py_BuildValue("H", val)); } static PyObject * bus_read_4(PyObject *self, PyObject *args) { long ofs; int rid; uint32_t val; if (!PyArg_ParseTuple(args, "il", &rid, &ofs)) return (NULL); if (!bs_read(rid, ofs, &val, sizeof(val))) { PyErr_SetString(PyExc_IOError, strerror(errno)); return (NULL); } return (Py_BuildValue("I", val)); } static PyObject * bus_write_1(PyObject *self, PyObject *args) { long ofs; int rid; uint8_t val; if (!PyArg_ParseTuple(args, "ilB", &rid, &ofs, &val)) return (NULL); if (!bs_write(rid, ofs, &val, sizeof(val))) { PyErr_SetString(PyExc_IOError, strerror(errno)); return (NULL); } Py_RETURN_NONE; } static PyObject * bus_write_2(PyObject *self, PyObject *args) { long ofs; int rid; uint16_t val; if (!PyArg_ParseTuple(args, "ilH", &rid, &ofs, &val)) return (NULL); if (!bs_write(rid, ofs, &val, sizeof(val))) { PyErr_SetString(PyExc_IOError, strerror(errno)); return (NULL); } Py_RETURN_NONE; } static PyObject * bus_write_4(PyObject *self, PyObject *args) { long ofs; int rid; uint32_t val; if (!PyArg_ParseTuple(args, "ilI", &rid, &ofs, &val)) return (NULL); if (!bs_write(rid, ofs, &val, sizeof(val))) { PyErr_SetString(PyExc_IOError, strerror(errno)); return (NULL); } Py_RETURN_NONE; } static PyObject * bus_map(PyObject *self, PyObject *args) { - char *dev; + char *dev, *resource; int rid; - if (!PyArg_ParseTuple(args, "s", &dev)) + if (!PyArg_ParseTuple(args, "ss", &dev, &resource)) return (NULL); - rid = bs_map(dev); + rid = bs_map(dev, resource); if (rid == -1) { PyErr_SetString(PyExc_IOError, strerror(errno)); return (NULL); } return (Py_BuildValue("i", rid)); } static PyObject * bus_unmap(PyObject *self, PyObject *args) { int rid; if (!PyArg_ParseTuple(args, "i", &rid)) return (NULL); if (!bs_unmap(rid)) { PyErr_SetString(PyExc_IOError, strerror(errno)); return (NULL); } Py_RETURN_NONE; } static PyObject * bus_subregion(PyObject *self, PyObject *args) { long ofs, sz; int rid0, rid; if (!PyArg_ParseTuple(args, "ill", &rid0, &ofs, &sz)) return (NULL); rid = bs_subregion(rid0, ofs, sz); if (rid == -1) { PyErr_SetString(PyExc_IOError, strerror(errno)); return (NULL); } return (Py_BuildValue("i", rid)); } static PyObject * busdma_tag_create(PyObject *self, PyObject *args) { char *dev; u_long align, bndry, maxaddr, maxsz, maxsegsz; u_int nsegs, datarate, flags; int tid; if (!PyArg_ParseTuple(args, "skkkkIkII", &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) { u_long align, bndry, maxaddr, maxsz, maxsegsz; u_int nsegs, datarate, flags; int ptid, tid; if (!PyArg_ParseTuple(args, "ikkkkIkII", &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 PyObject * busdma_md_create(PyObject *self, PyObject *args) { u_int flags; int error, mdid, tid; if (!PyArg_ParseTuple(args, "iI", &tid, &flags)) return (NULL); mdid = bd_md_create(tid, flags); if (mdid == -1) { PyErr_SetString(PyExc_IOError, strerror(errno)); return (NULL); } return (Py_BuildValue("i", mdid)); } static PyObject * busdma_md_destroy(PyObject *self, PyObject *args) { int error, mdid; if (!PyArg_ParseTuple(args, "i", &mdid)) return (NULL); error = bd_md_destroy(mdid); if (error) { PyErr_SetString(PyExc_IOError, strerror(error)); return (NULL); } Py_RETURN_NONE; } static PyObject * busdma_md_load(PyObject *self, PyObject *args) { void *buf; u_long len; u_int flags; int error, mdid; if (!PyArg_ParseTuple(args, "iwkI", &mdid, &buf, &len, &flags)) return (NULL); error = bd_md_load(mdid, buf, len, flags); if (error) { PyErr_SetString(PyExc_IOError, strerror(error)); return (NULL); } Py_RETURN_NONE; } static PyObject * busdma_md_unload(PyObject *self, PyObject *args) { int error, mdid; if (!PyArg_ParseTuple(args, "i", &mdid)) return (NULL); error = bd_md_unload(mdid); if (error) { PyErr_SetString(PyExc_IOError, strerror(error)); return (NULL); } Py_RETURN_NONE; } static PyObject * busdma_mem_alloc(PyObject *self, PyObject *args) { u_int flags; int mdid, tid; if (!PyArg_ParseTuple(args, "iI", &tid, &flags)) return (NULL); mdid = bd_mem_alloc(tid, flags); if (mdid == -1) { PyErr_SetString(PyExc_IOError, strerror(errno)); return (NULL); } return (Py_BuildValue("i", mdid)); } static PyObject * busdma_mem_free(PyObject *self, PyObject *args) { int error, mdid; if (!PyArg_ParseTuple(args, "i", &mdid)) return (NULL); error = bd_mem_free(mdid); if (error) { PyErr_SetString(PyExc_IOError, strerror(error)); return (NULL); } 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) Py_RETURN_NONE; 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) Py_RETURN_NONE; 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 PyObject * busdma_sync(PyObject *self, PyObject *args) { u_long base, size; int error, mdid, op; if (!PyArg_ParseTuple(args, "iikk", &mdid, &op, &base, &size)) return (NULL); error = bd_sync(mdid, op, base, size); if (error) { PyErr_SetString(PyExc_IOError, strerror(error)); return (NULL); } Py_RETURN_NONE; } 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." }, { "read_4", bus_read_4, METH_VARARGS, "Read a 4-byte data item." }, { "write_1", bus_write_1, METH_VARARGS, "Write a 1-byte data item." }, { "write_2", bus_write_2, METH_VARARGS, "Write a 2-byte data item." }, { "write_4", bus_write_4, METH_VARARGS, "Write a 4-byte data item." }, { "map", bus_map, METH_VARARGS, "Return a resource ID for a device file created by proto(4)" }, { "unmap", bus_unmap, METH_VARARGS, "Free a resource ID" }, { "subregion", bus_subregion, METH_VARARGS, "Return a resource ID for a subregion of another resource ID" }, { 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." }, { "md_create", busdma_md_create, METH_VARARGS, "Create a new and empty memory descriptor." }, { "md_destroy", busdma_md_destroy, METH_VARARGS, "Destroy a previously created memory descriptor." }, { "md_load", busdma_md_load, METH_VARARGS, "Load a buffer into a memory descriptor." }, { "md_unload", busdma_md_unload, METH_VARARGS, "Unload a memory descriptor." }, { "mem_alloc", busdma_mem_alloc, METH_VARARGS, "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." }, { "sync", busdma_sync, METH_VARARGS, "Keep memory/caches coherent WRT to DMA." }, { NULL, NULL, 0, NULL } }; PyMODINIT_FUNC initbus(void) { PyObject *bus, *busdma; bus = Py_InitModule("bus", bus_methods); if (bus == NULL) return; busdma = Py_InitModule("busdma", busdma_methods); if (busdma == NULL) return; PyModule_AddObject(bus, "dma", busdma); PyModule_AddObject(busdma, "MD_BUS_SPACE", Py_BuildValue("i", 0)); PyModule_AddObject(busdma, "MD_PHYS_SPACE", Py_BuildValue("i", 1)); PyModule_AddObject(busdma, "MD_VIRT_SPACE", Py_BuildValue("i", 2)); PyModule_AddObject(busdma, "SYNC_PREREAD", Py_BuildValue("i", 1)); PyModule_AddObject(busdma, "SYNC_POSTREAD", Py_BuildValue("i", 2)); PyModule_AddObject(busdma, "SYNC_PREWRITE", Py_BuildValue("i", 4)); PyModule_AddObject(busdma, "SYNC_POSTWRITE", Py_BuildValue("i", 8)); } Index: head/tools/bus_space/bus.c =================================================================== --- head/tools/bus_space/bus.c (revision 285902) +++ head/tools/bus_space/bus.c (revision 285903) @@ -1,263 +1,270 @@ /*- * Copyright (c) 2014 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 __FBSDID("$FreeBSD$"); #include #include #include #include #include +#include #include #include #include "bus.h" #include "../../sys/dev/proto/proto_dev.h" struct resource { int rid; int fd; long addr; long size; off_t ofs; caddr_t ptr; }; static struct resource *ridtbl = NULL; static int nrids = 0; static int rid_alloc(void) { void *newtbl; int rid; for (rid = 0; rid < nrids; rid++) { if (ridtbl[rid].fd == -1) break; } if (rid == nrids) { nrids++; newtbl = realloc(ridtbl, sizeof(struct resource) * nrids); if (newtbl == NULL) { nrids--; return (-1); } else ridtbl = newtbl; } ridtbl[rid].fd = INT_MAX; return (rid); } static struct resource * rid_lookup(int rid) { struct resource *r; if (rid < 0 || rid >= nrids) { errno = EINVAL; return (NULL); } r = ridtbl + rid; if (r->fd == -1) { errno = ENXIO; return (NULL); } return (r); } int -bs_map(const char *dev) +bs_map(const char *dev, const char *res) { + char path[PATH_MAX]; struct proto_ioc_region region; struct resource *r; - int rid; + int len, rid; + len = snprintf(path, PATH_MAX, "/dev/proto/%s/%s", dev, res); + if (len >= PATH_MAX) { + errno = EINVAL; + return (-1); + } rid = rid_alloc(); if (rid == -1) return (-1); r = rid_lookup(rid); if (r == NULL) return (-1); - r->fd = open(dev, O_RDWR); + r->fd = open(path, O_RDWR); if (r->fd == -1) return (-1); r->rid = -1; if (ioctl(r->fd, PROTO_IOC_REGION, ®ion) == -1) { close(r->fd); r->fd = -1; return (-1); } r->addr = region.address; r->size = region.size; r->ofs = 0; r->ptr = mmap(NULL, r->size, PROT_READ | PROT_WRITE, MAP_NOCORE | MAP_SHARED, r->fd, r->ofs); return (rid); } int bs_read(int rid, off_t ofs, void *buf, ssize_t bufsz) { struct resource *r; volatile void *ptr; off_t o; ssize_t s; r = rid_lookup(rid); if (r == NULL) return (0); if (ofs < 0 || ofs > r->size - bufsz) { errno = ESPIPE; return (0); } ofs += r->ofs; if (r->ptr != MAP_FAILED) { ptr = r->ptr + ofs; switch (bufsz) { case 1: *((uint8_t *)buf) = *((volatile uint8_t *)ptr); break; case 2: *((uint16_t *)buf) = *((volatile uint16_t *)ptr); break; case 4: *((uint32_t *)buf) = *((volatile uint32_t *)ptr); break; default: errno = EIO; return (0); } } else { o = lseek(r->fd, ofs, SEEK_SET); if (o != ofs) return (0); s = read(r->fd, buf, bufsz); if (s != bufsz) return (0); } return (1); } int bs_subregion(int rid0, long ofs, long sz) { struct resource *r; void *ptr0; long addr0, ofs0; int fd0, rid; r = rid_lookup(rid0); if (r == NULL) return (-1); if (ofs < 0 || sz < 1) { errno = EINVAL; return (-1); } if (ofs + sz > r->size) { errno = ENOSPC; return (-1); } fd0 = r->fd; addr0 = r->addr; ofs0 = r->ofs; ptr0 = r->ptr; rid = rid_alloc(); if (rid == -1) return (-1); r = rid_lookup(rid); if (r == NULL) return (-1); r->rid = rid0; r->fd = fd0; r->addr = addr0 + ofs; r->size = sz; r->ofs = ofs0 + ofs; r->ptr = ptr0; return (rid); } int bs_unmap(int rid) { struct resource *r; r = rid_lookup(rid); if (r == NULL) return (0); if (r->rid == -1) { if (r->ptr != MAP_FAILED) munmap(r->ptr, r->size); close(r->fd); } r->fd = -1; return (1); } int bs_write(int rid, off_t ofs, void *buf, ssize_t bufsz) { struct resource *r; volatile void *ptr; off_t o; ssize_t s; r = rid_lookup(rid); if (r == NULL) return (0); if (ofs < 0 || ofs > r->size - bufsz) { errno = ESPIPE; return (0); } ofs += r->ofs; if (r->ptr != MAP_FAILED) { ptr = r->ptr + ofs; switch (bufsz) { case 1: *((volatile uint8_t *)ptr) = *((uint8_t *)buf); break; case 2: *((volatile uint16_t *)ptr) = *((uint16_t *)buf); break; case 4: *((volatile uint32_t *)ptr) = *((uint32_t *)buf); break; default: errno = EIO; return (0); } } else { o = lseek(r->fd, ofs, SEEK_SET); if (o != ofs) return (0); s = write(r->fd, buf, bufsz); if (s != bufsz) return (0); } return (1); } Index: head/tools/bus_space/bus.h =================================================================== --- head/tools/bus_space/bus.h (revision 285902) +++ head/tools/bus_space/bus.h (revision 285903) @@ -1,38 +1,38 @@ /*- * Copyright (c) 2014 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_SPACE_H_ #define _TOOLS_BUS_SPACE_H_ -int bs_map(const char *dev); +int bs_map(const char *dev, const char *res); int bs_read(int rid, off_t ofs, void *buf, ssize_t bufsz); int bs_subregion(int rid0, long ofs, long sz); int bs_unmap(int rid); int bs_write(int rid, off_t ofs, void *buf, ssize_t bufsz); #endif /* _TOOLS_BUS_SPACE_H_ */ Index: head/tools/bus_space/busdma.c =================================================================== --- head/tools/bus_space/busdma.c (revision 285902) +++ head/tools/bus_space/busdma.c (revision 285903) @@ -1,551 +1,558 @@ /*- * 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 __FBSDID("$FreeBSD$"); #include #include #include #include #include #include +#include #include #include #include #include "busdma.h" #include "../../sys/dev/proto/proto_dev.h" struct obj { int oid; u_int type; #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; u_long key; union { struct { unsigned long align; unsigned long bndry; unsigned long maxaddr; unsigned long maxsz; unsigned long maxsegsz; unsigned long nsegs; unsigned long datarate; } tag; struct { 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; }; static struct obj **oidtbl = NULL; static int noids = 0; static struct obj * obj_alloc(u_int type) { struct obj **newtbl, *obj; int oid; obj = calloc(1, sizeof(struct obj)); obj->type = type; for (oid = 0; oid < noids; oid++) { if (oidtbl[oid] == 0) break; } if (oid == noids) { newtbl = realloc(oidtbl, sizeof(struct obj *) * (noids + 1)); if (newtbl == NULL) { free(obj); return (NULL); } oidtbl = newtbl; noids++; } oidtbl[oid] = obj; obj->oid = oid; return (obj); } static int obj_free(struct obj *obj) { oidtbl[obj->oid] = NULL; free(obj); return (0); } static struct obj * obj_lookup(int oid, u_int type) { struct obj *obj; if (oid < 0 || oid >= noids) { errno = EINVAL; return (NULL); } obj = oidtbl[oid]; if (obj->refcnt == 0) { errno = ENXIO; return (NULL); } if (type != OBJ_TYPE_NONE && obj->type != type) { errno = ENODEV; return (NULL); } return (obj); } static struct obj * bd_tag_new(struct obj *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 obj *tag; tag = obj_alloc(OBJ_TYPE_TAG); 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) { obj_free(tag); return (NULL); } tag->refcnt = 1; tag->fd = fd; tag->parent = ptag; tag->key = ioc.result; tag->u.tag.align = ioc.u.tag.align; tag->u.tag.bndry = ioc.u.tag.bndry; tag->u.tag.maxaddr = ioc.u.tag.maxaddr; tag->u.tag.maxsz = ioc.u.tag.maxsz; tag->u.tag.maxsegsz = ioc.u.tag.maxsegsz; tag->u.tag.nsegs = ioc.u.tag.nsegs; tag->u.tag.datarate = ioc.u.tag.datarate; 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) { + char path[PATH_MAX]; struct obj *tag; - int fd; + int fd, len; - fd = open(dev, O_RDWR); + len = snprintf(path, PATH_MAX, "/dev/proto/%s/busdma", dev); + if (len >= PATH_MAX) { + errno = EINVAL; + return (-1); + } + fd = open(path, 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->oid); } 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 obj *ptag, *tag; ptag = obj_lookup(ptid, OBJ_TYPE_TAG); 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); ptag->refcnt++; return (tag->oid); } int bd_tag_destroy(int tid) { struct proto_ioc_busdma ioc; struct obj *ptag, *tag; tag = obj_lookup(tid, OBJ_TYPE_TAG); 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); if (tag->parent != NULL) tag->parent->refcnt--; else close(tag->fd); obj_free(tag); return (0); } static int bd_md_add_seg(struct obj *md, int type, u_long addr, u_long size) { struct obj *seg; seg = obj_alloc(OBJ_TYPE_SEG); if (seg == NULL) return (errno); seg->refcnt = 1; seg->parent = md; seg->u.seg.address = addr; seg->u.seg.size = size; md->u.md.seg[type] = seg; md->u.md.nsegs[type] = 1; return (0); } static int bd_md_del_segs(struct obj *md, int type, int unmap) { struct obj *seg, *seg0; for (seg = md->u.md.seg[type]; seg != NULL; seg = seg0) { if (unmap) munmap((void *)seg->u.seg.address, seg->u.seg.size); seg0 = seg->u.seg.next; obj_free(seg); } return (0); } int bd_md_create(int tid, u_int flags) { struct proto_ioc_busdma ioc; struct obj *md, *tag; tag = obj_lookup(tid, OBJ_TYPE_TAG); if (tag == NULL) return (-1); md = obj_alloc(OBJ_TYPE_MD); if (md == NULL) return (-1); memset(&ioc, 0, sizeof(ioc)); ioc.request = PROTO_IOC_BUSDMA_MD_CREATE; ioc.u.md.tag = tag->key; ioc.u.md.flags = flags; if (ioctl(tag->fd, PROTO_IOC_BUSDMA, &ioc) == -1) { obj_free(md); return (-1); } md->refcnt = 1; md->fd = tag->fd; md->parent = tag; tag->refcnt++; md->key = ioc.result; return (md->oid); } int bd_md_destroy(int mdid) { struct proto_ioc_busdma ioc; struct obj *md; md = obj_lookup(mdid, OBJ_TYPE_MD); if (md == NULL) return (errno); memset(&ioc, 0, sizeof(ioc)); ioc.request = PROTO_IOC_BUSDMA_MD_DESTROY; ioc.key = md->key; if (ioctl(md->fd, PROTO_IOC_BUSDMA, &ioc) == -1) return (errno); md->parent->refcnt--; obj_free(md); return (0); } int bd_md_load(int mdid, void *buf, u_long len, u_int flags) { struct proto_ioc_busdma ioc; struct obj *md; int error; md = obj_lookup(mdid, OBJ_TYPE_MD); if (md == NULL) return (errno); memset(&ioc, 0, sizeof(ioc)); ioc.request = PROTO_IOC_BUSDMA_MD_LOAD; ioc.key = md->key; ioc.u.md.flags = flags; ioc.u.md.virt_addr = (uintptr_t)buf; ioc.u.md.virt_size = len; if (ioctl(md->fd, PROTO_IOC_BUSDMA, &ioc) == -1) return (errno); error = bd_md_add_seg(md, BUSDMA_MD_VIRT, ioc.u.md.virt_addr, len); error = bd_md_add_seg(md, BUSDMA_MD_PHYS, ioc.u.md.phys_addr, len); error = bd_md_add_seg(md, BUSDMA_MD_BUS, ioc.u.md.bus_addr, len); return (error); } int bd_md_unload(int mdid) { struct proto_ioc_busdma ioc; struct obj *md; int error; md = obj_lookup(mdid, OBJ_TYPE_MD); if (md == NULL) return (errno); memset(&ioc, 0, sizeof(ioc)); ioc.request = PROTO_IOC_BUSDMA_MD_UNLOAD; ioc.key = md->key; if (ioctl(md->fd, PROTO_IOC_BUSDMA, &ioc) == -1) return (errno); bd_md_del_segs(md, BUSDMA_MD_VIRT, 0); bd_md_del_segs(md, BUSDMA_MD_PHYS, 0); bd_md_del_segs(md, BUSDMA_MD_BUS, 0); return (0); } int bd_mem_alloc(int tid, u_int flags) { struct proto_ioc_busdma ioc; struct obj *md, *tag; uintptr_t addr; int error; tag = obj_lookup(tid, OBJ_TYPE_TAG); if (tag == NULL) return (-1); md = obj_alloc(OBJ_TYPE_MD); if (md == NULL) return (-1); memset(&ioc, 0, sizeof(ioc)); ioc.request = PROTO_IOC_BUSDMA_MEM_ALLOC; ioc.u.md.tag = tag->key; ioc.u.md.flags = flags; if (ioctl(tag->fd, PROTO_IOC_BUSDMA, &ioc) == -1) { obj_free(md); return (-1); } md->refcnt = 1; md->fd = tag->fd; md->parent = tag; tag->refcnt++; md->key = ioc.result; /* XXX we need to support multiple segments */ assert(ioc.u.md.phys_nsegs == 1); assert(ioc.u.md.bus_nsegs == 1); error = bd_md_add_seg(md, BUSDMA_MD_PHYS, ioc.u.md.phys_addr, tag->u.tag.maxsz); error = bd_md_add_seg(md, BUSDMA_MD_BUS, ioc.u.md.bus_addr, tag->u.tag.maxsz); addr = (uintptr_t)mmap(NULL, tag->u.tag.maxsz, PROT_READ | PROT_WRITE, MAP_NOCORE | MAP_SHARED, md->fd, ioc.u.md.phys_addr); if (addr == (uintptr_t)MAP_FAILED) goto fail; error = bd_md_add_seg(md, BUSDMA_MD_VIRT, addr, tag->u.tag.maxsz); return (md->oid); fail: memset(&ioc, 0, sizeof(ioc)); ioc.request = PROTO_IOC_BUSDMA_MEM_FREE; ioc.key = md->key; ioctl(md->fd, PROTO_IOC_BUSDMA, &ioc); md->parent->refcnt--; obj_free(md); return (-1); } int bd_mem_free(int mdid) { struct proto_ioc_busdma ioc; struct obj *md; md = obj_lookup(mdid, OBJ_TYPE_MD); if (md == NULL) return (errno); memset(&ioc, 0, sizeof(ioc)); ioc.request = PROTO_IOC_BUSDMA_MEM_FREE; ioc.key = md->key; if (ioctl(md->fd, PROTO_IOC_BUSDMA, &ioc) == -1) return (errno); bd_md_del_segs(md, BUSDMA_MD_VIRT, 1); bd_md_del_segs(md, BUSDMA_MD_PHYS, 0); bd_md_del_segs(md, BUSDMA_MD_BUS, 0); md->parent->refcnt--; 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); } int bd_sync(int mdid, u_int op, u_long base, u_long size) { struct proto_ioc_busdma ioc; struct obj *md; md = obj_lookup(mdid, OBJ_TYPE_MD); if (md == NULL) return (errno); memset(&ioc, 0, sizeof(ioc)); ioc.request = PROTO_IOC_BUSDMA_SYNC; ioc.key = md->key; ioc.u.sync.op = op; ioc.u.sync.base = base; ioc.u.sync.size = size; if (ioctl(md->fd, PROTO_IOC_BUSDMA, &ioc) == -1) return (errno); return (0); }