1 /*- 2 * Copyright (c) 2014, 2015 Marcel Moolenaar 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 16 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 17 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 18 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 19 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 20 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 22 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 */ 26 27 #include <sys/cdefs.h> 28 __FBSDID("$FreeBSD$"); 29 30 #include <Python.h> 31 32 #include "bus.h" 33 #include "busdma.h" 34 35 static PyObject * 36 bus_read_1(PyObject *self, PyObject *args) 37 { 38 long ofs; 39 int rid; 40 uint8_t val; 41 42 if (!PyArg_ParseTuple(args, "il", &rid, &ofs)) 43 return (NULL); 44 if (!bs_read(rid, ofs, &val, sizeof(val))) { 45 PyErr_SetString(PyExc_IOError, strerror(errno)); 46 return (NULL); 47 } 48 return (Py_BuildValue("B", val)); 49 } 50 51 static PyObject * 52 bus_read_2(PyObject *self, PyObject *args) 53 { 54 long ofs; 55 int rid; 56 uint16_t val; 57 58 if (!PyArg_ParseTuple(args, "il", &rid, &ofs)) 59 return (NULL); 60 if (!bs_read(rid, ofs, &val, sizeof(val))) { 61 PyErr_SetString(PyExc_IOError, strerror(errno)); 62 return (NULL); 63 } 64 return (Py_BuildValue("H", val)); 65 } 66 67 static PyObject * 68 bus_read_4(PyObject *self, PyObject *args) 69 { 70 long ofs; 71 int rid; 72 uint32_t val; 73 74 if (!PyArg_ParseTuple(args, "il", &rid, &ofs)) 75 return (NULL); 76 if (!bs_read(rid, ofs, &val, sizeof(val))) { 77 PyErr_SetString(PyExc_IOError, strerror(errno)); 78 return (NULL); 79 } 80 return (Py_BuildValue("I", val)); 81 } 82 83 static PyObject * 84 bus_write_1(PyObject *self, PyObject *args) 85 { 86 long ofs; 87 int rid; 88 uint8_t val; 89 90 if (!PyArg_ParseTuple(args, "ilB", &rid, &ofs, &val)) 91 return (NULL); 92 if (!bs_write(rid, ofs, &val, sizeof(val))) { 93 PyErr_SetString(PyExc_IOError, strerror(errno)); 94 return (NULL); 95 } 96 Py_RETURN_NONE; 97 } 98 99 static PyObject * 100 bus_write_2(PyObject *self, PyObject *args) 101 { 102 long ofs; 103 int rid; 104 uint16_t val; 105 106 if (!PyArg_ParseTuple(args, "ilH", &rid, &ofs, &val)) 107 return (NULL); 108 if (!bs_write(rid, ofs, &val, sizeof(val))) { 109 PyErr_SetString(PyExc_IOError, strerror(errno)); 110 return (NULL); 111 } 112 Py_RETURN_NONE; 113 } 114 115 static PyObject * 116 bus_write_4(PyObject *self, PyObject *args) 117 { 118 long ofs; 119 int rid; 120 uint32_t val; 121 122 if (!PyArg_ParseTuple(args, "ilI", &rid, &ofs, &val)) 123 return (NULL); 124 if (!bs_write(rid, ofs, &val, sizeof(val))) { 125 PyErr_SetString(PyExc_IOError, strerror(errno)); 126 return (NULL); 127 } 128 Py_RETURN_NONE; 129 } 130 131 static PyObject * 132 bus_map(PyObject *self, PyObject *args) 133 { 134 char *dev; 135 int rid; 136 137 if (!PyArg_ParseTuple(args, "s", &dev)) 138 return (NULL); 139 rid = bs_map(dev); 140 if (rid == -1) { 141 PyErr_SetString(PyExc_IOError, strerror(errno)); 142 return (NULL); 143 } 144 return (Py_BuildValue("i", rid)); 145 } 146 147 static PyObject * 148 bus_unmap(PyObject *self, PyObject *args) 149 { 150 int rid; 151 152 if (!PyArg_ParseTuple(args, "i", &rid)) 153 return (NULL); 154 if (!bs_unmap(rid)) { 155 PyErr_SetString(PyExc_IOError, strerror(errno)); 156 return (NULL); 157 } 158 Py_RETURN_NONE; 159 } 160 161 static PyObject * 162 bus_subregion(PyObject *self, PyObject *args) 163 { 164 long ofs, sz; 165 int rid0, rid; 166 167 if (!PyArg_ParseTuple(args, "ill", &rid0, &ofs, &sz)) 168 return (NULL); 169 rid = bs_subregion(rid0, ofs, sz); 170 if (rid == -1) { 171 PyErr_SetString(PyExc_IOError, strerror(errno)); 172 return (NULL); 173 } 174 return (Py_BuildValue("i", rid)); 175 } 176 177 static PyObject * 178 busdma_tag_create(PyObject *self, PyObject *args) 179 { 180 char *dev; 181 u_long align, bndry, maxaddr, maxsz, maxsegsz; 182 u_int nsegs, datarate, flags; 183 int tid; 184 185 if (!PyArg_ParseTuple(args, "skkkkIkII", &dev, &align, &bndry, 186 &maxaddr, &maxsz, &nsegs, &maxsegsz, &datarate, &flags)) 187 return (NULL); 188 tid = bd_tag_create(dev, align, bndry, maxaddr, maxsz, nsegs, 189 maxsegsz, datarate, flags); 190 if (tid == -1) { 191 PyErr_SetString(PyExc_IOError, strerror(errno)); 192 return (NULL); 193 } 194 return (Py_BuildValue("i", tid)); 195 } 196 197 static PyObject * 198 busdma_tag_derive(PyObject *self, PyObject *args) 199 { 200 u_long align, bndry, maxaddr, maxsz, maxsegsz; 201 u_int nsegs, datarate, flags; 202 int ptid, tid; 203 204 if (!PyArg_ParseTuple(args, "ikkkkIkII", &ptid, &align, &bndry, 205 &maxaddr, &maxsz, &nsegs, &maxsegsz, &datarate, &flags)) 206 return (NULL); 207 tid = bd_tag_derive(ptid, align, bndry, maxaddr, maxsz, nsegs, 208 maxsegsz, datarate, flags); 209 if (tid == -1) { 210 PyErr_SetString(PyExc_IOError, strerror(errno)); 211 return (NULL); 212 } 213 return (Py_BuildValue("i", tid)); 214 } 215 216 static PyObject * 217 busdma_tag_destroy(PyObject *self, PyObject *args) 218 { 219 int error, tid; 220 221 if (!PyArg_ParseTuple(args, "i", &tid)) 222 return (NULL); 223 error = bd_tag_destroy(tid); 224 if (error) { 225 PyErr_SetString(PyExc_IOError, strerror(error)); 226 return (NULL); 227 } 228 Py_RETURN_NONE; 229 } 230 231 static PyObject * 232 busdma_md_create(PyObject *self, PyObject *args) 233 { 234 u_int flags; 235 int error, mdid, tid; 236 237 if (!PyArg_ParseTuple(args, "iI", &tid, &flags)) 238 return (NULL); 239 mdid = bd_md_create(tid, flags); 240 if (mdid == -1) { 241 PyErr_SetString(PyExc_IOError, strerror(errno)); 242 return (NULL); 243 } 244 return (Py_BuildValue("i", mdid)); 245 } 246 247 static PyObject * 248 busdma_md_destroy(PyObject *self, PyObject *args) 249 { 250 int error, mdid; 251 252 if (!PyArg_ParseTuple(args, "i", &mdid)) 253 return (NULL); 254 error = bd_md_destroy(mdid); 255 if (error) { 256 PyErr_SetString(PyExc_IOError, strerror(error)); 257 return (NULL); 258 } 259 Py_RETURN_NONE; 260 } 261 262 static PyObject * 263 busdma_md_load(PyObject *self, PyObject *args) 264 { 265 void *buf; 266 u_long len; 267 u_int flags; 268 int error, mdid; 269 270 if (!PyArg_ParseTuple(args, "iwkI", &mdid, &buf, &len, &flags)) 271 return (NULL); 272 error = bd_md_load(mdid, buf, len, flags); 273 if (error) { 274 PyErr_SetString(PyExc_IOError, strerror(error)); 275 return (NULL); 276 } 277 Py_RETURN_NONE; 278 } 279 280 static PyObject * 281 busdma_mem_alloc(PyObject *self, PyObject *args) 282 { 283 u_int flags; 284 int mdid, tid; 285 286 if (!PyArg_ParseTuple(args, "iI", &tid, &flags)) 287 return (NULL); 288 mdid = bd_mem_alloc(tid, flags); 289 if (mdid == -1) { 290 PyErr_SetString(PyExc_IOError, strerror(errno)); 291 return (NULL); 292 } 293 return (Py_BuildValue("i", mdid)); 294 } 295 296 static PyObject * 297 busdma_mem_free(PyObject *self, PyObject *args) 298 { 299 int error, mdid; 300 301 if (!PyArg_ParseTuple(args, "i", &mdid)) 302 return (NULL); 303 error = bd_mem_free(mdid); 304 if (error) { 305 PyErr_SetString(PyExc_IOError, strerror(error)); 306 return (NULL); 307 } 308 Py_RETURN_NONE; 309 } 310 311 static PyObject * 312 busdma_md_first_seg(PyObject *self, PyObject *args) 313 { 314 int error, mdid, sid, what; 315 316 if (!PyArg_ParseTuple(args, "ii", &mdid, &what)) 317 return (NULL); 318 sid = bd_md_first_seg(mdid, what); 319 if (sid == -1) { 320 PyErr_SetString(PyExc_IOError, strerror(errno)); 321 return (NULL); 322 } 323 return (Py_BuildValue("i", sid)); 324 } 325 326 static PyObject * 327 busdma_md_next_seg(PyObject *self, PyObject *args) 328 { 329 int error, mdid, sid; 330 331 if (!PyArg_ParseTuple(args, "ii", &mdid, &sid)) 332 return (NULL); 333 sid = bd_md_next_seg(mdid, sid); 334 if (sid == -1) { 335 PyErr_SetString(PyExc_IOError, strerror(errno)); 336 return (NULL); 337 } 338 return (Py_BuildValue("i", sid)); 339 } 340 341 static PyObject * 342 busdma_seg_get_addr(PyObject *self, PyObject *args) 343 { 344 u_long addr; 345 int error, sid; 346 347 if (!PyArg_ParseTuple(args, "i", &sid)) 348 return (NULL); 349 error = bd_seg_get_addr(sid, &addr); 350 if (error) { 351 PyErr_SetString(PyExc_IOError, strerror(error)); 352 return (NULL); 353 } 354 return (Py_BuildValue("k", addr)); 355 } 356 357 static PyObject * 358 busdma_seg_get_size(PyObject *self, PyObject *args) 359 { 360 u_long size; 361 int error, sid; 362 363 if (!PyArg_ParseTuple(args, "i", &sid)) 364 return (NULL); 365 error = bd_seg_get_size(sid, &size); 366 if (error) { 367 PyErr_SetString(PyExc_IOError, strerror(error)); 368 return (NULL); 369 } 370 return (Py_BuildValue("k", size)); 371 } 372 373 static PyMethodDef bus_methods[] = { 374 { "read_1", bus_read_1, METH_VARARGS, "Read a 1-byte data item." }, 375 { "read_2", bus_read_2, METH_VARARGS, "Read a 2-byte data item." }, 376 { "read_4", bus_read_4, METH_VARARGS, "Read a 4-byte data item." }, 377 378 { "write_1", bus_write_1, METH_VARARGS, "Write a 1-byte data item." }, 379 { "write_2", bus_write_2, METH_VARARGS, "Write a 2-byte data item." }, 380 { "write_4", bus_write_4, METH_VARARGS, "Write a 4-byte data item." }, 381 382 { "map", bus_map, METH_VARARGS, 383 "Return a resource ID for a device file created by proto(4)" }, 384 { "unmap", bus_unmap, METH_VARARGS, 385 "Free a resource ID" }, 386 { "subregion", bus_subregion, METH_VARARGS, 387 "Return a resource ID for a subregion of another resource ID" }, 388 389 { NULL, NULL, 0, NULL } 390 }; 391 392 static PyMethodDef busdma_methods[] = { 393 { "tag_create", busdma_tag_create, METH_VARARGS, 394 "Create a root tag." }, 395 { "tag_derive", busdma_tag_derive, METH_VARARGS, 396 "Derive a child tag." }, 397 { "tag_destroy", busdma_tag_destroy, METH_VARARGS, 398 "Destroy a tag." }, 399 400 { "md_create", busdma_md_create, METH_VARARGS, 401 "Create a new and empty memory descriptor." }, 402 { "md_destroy", busdma_md_destroy, METH_VARARGS, 403 "Destroy a previously created memory descriptor." }, 404 { "md_load", busdma_md_load, METH_VARARGS, 405 "Load a buffer into a memory descriptor." }, 406 407 { "mem_alloc", busdma_mem_alloc, METH_VARARGS, 408 "Allocate memory according to the DMA constraints." }, 409 { "mem_free", busdma_mem_free, METH_VARARGS, 410 "Free allocated memory." }, 411 412 { "md_first_seg", busdma_md_first_seg, METH_VARARGS, 413 "Return first segment in one of the segment lists." }, 414 { "md_next_seg", busdma_md_next_seg, METH_VARARGS, 415 "Return next segment in the segment list." }, 416 { "seg_get_addr", busdma_seg_get_addr, METH_VARARGS, 417 "Return the address of the segment." }, 418 { "seg_get_size", busdma_seg_get_size, METH_VARARGS, 419 "Return the size of the segment." }, 420 { NULL, NULL, 0, NULL } 421 }; 422 423 PyMODINIT_FUNC 424 initbus(void) 425 { 426 427 Py_InitModule("bus", bus_methods); 428 Py_InitModule("busdma", busdma_methods); 429 } 430