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 #include <Python.h> 29 30 #include "bus.h" 31 #include "busdma.h" 32 33 static PyObject * 34 bus_read_1(PyObject *self, PyObject *args) 35 { 36 long ofs; 37 int rid; 38 uint8_t val; 39 40 if (!PyArg_ParseTuple(args, "il", &rid, &ofs)) 41 return (NULL); 42 if (!bs_read(rid, ofs, &val, sizeof(val))) { 43 PyErr_SetString(PyExc_IOError, strerror(errno)); 44 return (NULL); 45 } 46 return (Py_BuildValue("B", val)); 47 } 48 49 static PyObject * 50 bus_read_2(PyObject *self, PyObject *args) 51 { 52 long ofs; 53 int rid; 54 uint16_t val; 55 56 if (!PyArg_ParseTuple(args, "il", &rid, &ofs)) 57 return (NULL); 58 if (!bs_read(rid, ofs, &val, sizeof(val))) { 59 PyErr_SetString(PyExc_IOError, strerror(errno)); 60 return (NULL); 61 } 62 return (Py_BuildValue("H", val)); 63 } 64 65 static PyObject * 66 bus_read_4(PyObject *self, PyObject *args) 67 { 68 long ofs; 69 int rid; 70 uint32_t val; 71 72 if (!PyArg_ParseTuple(args, "il", &rid, &ofs)) 73 return (NULL); 74 if (!bs_read(rid, ofs, &val, sizeof(val))) { 75 PyErr_SetString(PyExc_IOError, strerror(errno)); 76 return (NULL); 77 } 78 return (Py_BuildValue("I", val)); 79 } 80 81 static PyObject * 82 bus_write_1(PyObject *self, PyObject *args) 83 { 84 long ofs; 85 int rid; 86 uint8_t val; 87 88 if (!PyArg_ParseTuple(args, "ilB", &rid, &ofs, &val)) 89 return (NULL); 90 if (!bs_write(rid, ofs, &val, sizeof(val))) { 91 PyErr_SetString(PyExc_IOError, strerror(errno)); 92 return (NULL); 93 } 94 Py_RETURN_NONE; 95 } 96 97 static PyObject * 98 bus_write_2(PyObject *self, PyObject *args) 99 { 100 long ofs; 101 int rid; 102 uint16_t val; 103 104 if (!PyArg_ParseTuple(args, "ilH", &rid, &ofs, &val)) 105 return (NULL); 106 if (!bs_write(rid, ofs, &val, sizeof(val))) { 107 PyErr_SetString(PyExc_IOError, strerror(errno)); 108 return (NULL); 109 } 110 Py_RETURN_NONE; 111 } 112 113 static PyObject * 114 bus_write_4(PyObject *self, PyObject *args) 115 { 116 long ofs; 117 int rid; 118 uint32_t val; 119 120 if (!PyArg_ParseTuple(args, "ilI", &rid, &ofs, &val)) 121 return (NULL); 122 if (!bs_write(rid, ofs, &val, sizeof(val))) { 123 PyErr_SetString(PyExc_IOError, strerror(errno)); 124 return (NULL); 125 } 126 Py_RETURN_NONE; 127 } 128 129 static PyObject * 130 bus_map(PyObject *self, PyObject *args) 131 { 132 char *dev, *resource; 133 int rid; 134 135 if (!PyArg_ParseTuple(args, "ss", &dev, &resource)) 136 return (NULL); 137 rid = bs_map(dev, resource); 138 if (rid == -1) { 139 PyErr_SetString(PyExc_IOError, strerror(errno)); 140 return (NULL); 141 } 142 return (Py_BuildValue("i", rid)); 143 } 144 145 static PyObject * 146 bus_unmap(PyObject *self, PyObject *args) 147 { 148 int rid; 149 150 if (!PyArg_ParseTuple(args, "i", &rid)) 151 return (NULL); 152 if (!bs_unmap(rid)) { 153 PyErr_SetString(PyExc_IOError, strerror(errno)); 154 return (NULL); 155 } 156 Py_RETURN_NONE; 157 } 158 159 static PyObject * 160 bus_subregion(PyObject *self, PyObject *args) 161 { 162 long ofs, sz; 163 int rid0, rid; 164 165 if (!PyArg_ParseTuple(args, "ill", &rid0, &ofs, &sz)) 166 return (NULL); 167 rid = bs_subregion(rid0, ofs, sz); 168 if (rid == -1) { 169 PyErr_SetString(PyExc_IOError, strerror(errno)); 170 return (NULL); 171 } 172 return (Py_BuildValue("i", rid)); 173 } 174 175 static PyObject * 176 busdma_tag_create(PyObject *self, PyObject *args) 177 { 178 char *dev; 179 u_long align, bndry, maxaddr, maxsz, maxsegsz; 180 u_int nsegs, datarate, flags; 181 int tid; 182 183 if (!PyArg_ParseTuple(args, "skkkkIkII", &dev, &align, &bndry, 184 &maxaddr, &maxsz, &nsegs, &maxsegsz, &datarate, &flags)) 185 return (NULL); 186 tid = bd_tag_create(dev, align, bndry, maxaddr, maxsz, nsegs, 187 maxsegsz, datarate, flags); 188 if (tid == -1) { 189 PyErr_SetString(PyExc_IOError, strerror(errno)); 190 return (NULL); 191 } 192 return (Py_BuildValue("i", tid)); 193 } 194 195 static PyObject * 196 busdma_tag_derive(PyObject *self, PyObject *args) 197 { 198 u_long align, bndry, maxaddr, maxsz, maxsegsz; 199 u_int nsegs, datarate, flags; 200 int ptid, tid; 201 202 if (!PyArg_ParseTuple(args, "ikkkkIkII", &ptid, &align, &bndry, 203 &maxaddr, &maxsz, &nsegs, &maxsegsz, &datarate, &flags)) 204 return (NULL); 205 tid = bd_tag_derive(ptid, align, bndry, maxaddr, maxsz, nsegs, 206 maxsegsz, datarate, flags); 207 if (tid == -1) { 208 PyErr_SetString(PyExc_IOError, strerror(errno)); 209 return (NULL); 210 } 211 return (Py_BuildValue("i", tid)); 212 } 213 214 static PyObject * 215 busdma_tag_destroy(PyObject *self, PyObject *args) 216 { 217 int error, tid; 218 219 if (!PyArg_ParseTuple(args, "i", &tid)) 220 return (NULL); 221 error = bd_tag_destroy(tid); 222 if (error) { 223 PyErr_SetString(PyExc_IOError, strerror(error)); 224 return (NULL); 225 } 226 Py_RETURN_NONE; 227 } 228 229 static PyObject * 230 busdma_md_create(PyObject *self, PyObject *args) 231 { 232 u_int flags; 233 int error, mdid, tid; 234 235 if (!PyArg_ParseTuple(args, "iI", &tid, &flags)) 236 return (NULL); 237 mdid = bd_md_create(tid, flags); 238 if (mdid == -1) { 239 PyErr_SetString(PyExc_IOError, strerror(errno)); 240 return (NULL); 241 } 242 return (Py_BuildValue("i", mdid)); 243 } 244 245 static PyObject * 246 busdma_md_destroy(PyObject *self, PyObject *args) 247 { 248 int error, mdid; 249 250 if (!PyArg_ParseTuple(args, "i", &mdid)) 251 return (NULL); 252 error = bd_md_destroy(mdid); 253 if (error) { 254 PyErr_SetString(PyExc_IOError, strerror(error)); 255 return (NULL); 256 } 257 Py_RETURN_NONE; 258 } 259 260 static PyObject * 261 busdma_md_load(PyObject *self, PyObject *args) 262 { 263 void *buf; 264 u_long len; 265 u_int flags; 266 int error, mdid; 267 268 if (!PyArg_ParseTuple(args, "iwkI", &mdid, &buf, &len, &flags)) 269 return (NULL); 270 error = bd_md_load(mdid, buf, len, flags); 271 if (error) { 272 PyErr_SetString(PyExc_IOError, strerror(error)); 273 return (NULL); 274 } 275 Py_RETURN_NONE; 276 } 277 278 static PyObject * 279 busdma_md_unload(PyObject *self, PyObject *args) 280 { 281 int error, mdid; 282 283 if (!PyArg_ParseTuple(args, "i", &mdid)) 284 return (NULL); 285 error = bd_md_unload(mdid); 286 if (error) { 287 PyErr_SetString(PyExc_IOError, strerror(error)); 288 return (NULL); 289 } 290 Py_RETURN_NONE; 291 } 292 293 static PyObject * 294 busdma_mem_alloc(PyObject *self, PyObject *args) 295 { 296 u_int flags; 297 int mdid, tid; 298 299 if (!PyArg_ParseTuple(args, "iI", &tid, &flags)) 300 return (NULL); 301 mdid = bd_mem_alloc(tid, flags); 302 if (mdid == -1) { 303 PyErr_SetString(PyExc_IOError, strerror(errno)); 304 return (NULL); 305 } 306 return (Py_BuildValue("i", mdid)); 307 } 308 309 static PyObject * 310 busdma_mem_free(PyObject *self, PyObject *args) 311 { 312 int error, mdid; 313 314 if (!PyArg_ParseTuple(args, "i", &mdid)) 315 return (NULL); 316 error = bd_mem_free(mdid); 317 if (error) { 318 PyErr_SetString(PyExc_IOError, strerror(error)); 319 return (NULL); 320 } 321 Py_RETURN_NONE; 322 } 323 324 static PyObject * 325 busdma_md_first_seg(PyObject *self, PyObject *args) 326 { 327 int error, mdid, sid, what; 328 329 if (!PyArg_ParseTuple(args, "ii", &mdid, &what)) 330 return (NULL); 331 sid = bd_md_first_seg(mdid, what); 332 if (sid == -1) 333 Py_RETURN_NONE; 334 return (Py_BuildValue("i", sid)); 335 } 336 337 static PyObject * 338 busdma_md_next_seg(PyObject *self, PyObject *args) 339 { 340 int error, mdid, sid; 341 342 if (!PyArg_ParseTuple(args, "ii", &mdid, &sid)) 343 return (NULL); 344 sid = bd_md_next_seg(mdid, sid); 345 if (sid == -1) 346 Py_RETURN_NONE; 347 return (Py_BuildValue("i", sid)); 348 } 349 350 static PyObject * 351 busdma_seg_get_addr(PyObject *self, PyObject *args) 352 { 353 u_long addr; 354 int error, sid; 355 356 if (!PyArg_ParseTuple(args, "i", &sid)) 357 return (NULL); 358 error = bd_seg_get_addr(sid, &addr); 359 if (error) { 360 PyErr_SetString(PyExc_IOError, strerror(error)); 361 return (NULL); 362 } 363 return (Py_BuildValue("k", addr)); 364 } 365 366 static PyObject * 367 busdma_seg_get_size(PyObject *self, PyObject *args) 368 { 369 u_long size; 370 int error, sid; 371 372 if (!PyArg_ParseTuple(args, "i", &sid)) 373 return (NULL); 374 error = bd_seg_get_size(sid, &size); 375 if (error) { 376 PyErr_SetString(PyExc_IOError, strerror(error)); 377 return (NULL); 378 } 379 return (Py_BuildValue("k", size)); 380 } 381 382 static PyObject * 383 busdma_sync(PyObject *self, PyObject *args) 384 { 385 int error, mdid, op; 386 387 if (!PyArg_ParseTuple(args, "ii", &mdid, &op)) 388 return (NULL); 389 error = bd_sync(mdid, op, 0UL, ~0UL); 390 if (error) { 391 PyErr_SetString(PyExc_IOError, strerror(error)); 392 return (NULL); 393 } 394 Py_RETURN_NONE; 395 } 396 397 static PyObject * 398 busdma_sync_range(PyObject *self, PyObject *args) 399 { 400 u_long ofs, len; 401 int error, mdid, op; 402 403 if (!PyArg_ParseTuple(args, "iikk", &mdid, &op, &ofs, &len)) 404 return (NULL); 405 error = bd_sync(mdid, op, ofs, len); 406 if (error) { 407 PyErr_SetString(PyExc_IOError, strerror(error)); 408 return (NULL); 409 } 410 Py_RETURN_NONE; 411 } 412 413 /* 414 * Module methods and initialization. 415 */ 416 417 static char bus_docstr[] = "Access to H/W bus memory and register areas."; 418 419 static PyMethodDef bus_methods[] = { 420 { "read_1", bus_read_1, METH_VARARGS, "Read a 1-byte data item." }, 421 { "read_2", bus_read_2, METH_VARARGS, "Read a 2-byte data item." }, 422 { "read_4", bus_read_4, METH_VARARGS, "Read a 4-byte data item." }, 423 424 { "write_1", bus_write_1, METH_VARARGS, "Write a 1-byte data item." }, 425 { "write_2", bus_write_2, METH_VARARGS, "Write a 2-byte data item." }, 426 { "write_4", bus_write_4, METH_VARARGS, "Write a 4-byte data item." }, 427 428 { "map", bus_map, METH_VARARGS, 429 "Return a resource ID for a device file created by proto(4)" }, 430 { "unmap", bus_unmap, METH_VARARGS, 431 "Free a resource ID" }, 432 { "subregion", bus_subregion, METH_VARARGS, 433 "Return a resource ID for a subregion of another resource ID" }, 434 435 { NULL, NULL, 0, NULL } 436 }; 437 438 static char busdma_docstr[] = "A bus- and device-independent interface" 439 " to Direct Memory Access (DMA) mechanisms."; 440 441 static PyMethodDef busdma_methods[] = { 442 { "tag_create", busdma_tag_create, METH_VARARGS, 443 "Create a root tag." }, 444 { "tag_derive", busdma_tag_derive, METH_VARARGS, 445 "Derive a child tag." }, 446 { "tag_destroy", busdma_tag_destroy, METH_VARARGS, 447 "Destroy a tag." }, 448 449 { "md_create", busdma_md_create, METH_VARARGS, 450 "Create a new and empty memory descriptor." }, 451 { "md_destroy", busdma_md_destroy, METH_VARARGS, 452 "Destroy a previously created memory descriptor." }, 453 { "md_load", busdma_md_load, METH_VARARGS, 454 "Load a buffer into a memory descriptor." }, 455 { "md_unload", busdma_md_unload, METH_VARARGS, 456 "Unload a memory descriptor." }, 457 458 { "mem_alloc", busdma_mem_alloc, METH_VARARGS, 459 "Allocate memory according to the DMA constraints." }, 460 { "mem_free", busdma_mem_free, METH_VARARGS, 461 "Free allocated memory." }, 462 463 { "md_first_seg", busdma_md_first_seg, METH_VARARGS, 464 "Return first segment in one of the segment lists." }, 465 { "md_next_seg", busdma_md_next_seg, METH_VARARGS, 466 "Return next segment in the segment list." }, 467 { "seg_get_addr", busdma_seg_get_addr, METH_VARARGS, 468 "Return the address of the segment." }, 469 { "seg_get_size", busdma_seg_get_size, METH_VARARGS, 470 "Return the size of the segment." }, 471 472 { "sync", busdma_sync, METH_VARARGS, 473 "Make the entire memory descriptor coherent WRT to DMA." }, 474 { "sync_range", busdma_sync_range, METH_VARARGS, 475 "Make part of the memory descriptor coherent WRT to DMA." }, 476 477 { NULL, NULL, 0, NULL } 478 }; 479 480 static PyObject * 481 module_initialize(PyObject *bus, PyObject *busdma) 482 { 483 484 if (bus == NULL || busdma == NULL) 485 return (NULL); 486 487 PyModule_AddObject(busdma, "MD_BUS_SPACE", Py_BuildValue("i", 0)); 488 PyModule_AddObject(busdma, "MD_PHYS_SPACE", Py_BuildValue("i", 1)); 489 PyModule_AddObject(busdma, "MD_VIRT_SPACE", Py_BuildValue("i", 2)); 490 491 PyModule_AddObject(busdma, "SYNC_PREREAD", Py_BuildValue("i", 1)); 492 PyModule_AddObject(busdma, "SYNC_POSTREAD", Py_BuildValue("i", 2)); 493 PyModule_AddObject(busdma, "SYNC_PREWRITE", Py_BuildValue("i", 4)); 494 PyModule_AddObject(busdma, "SYNC_POSTWRITE", Py_BuildValue("i", 8)); 495 496 PyModule_AddObject(bus, "dma", busdma); 497 return (bus); 498 } 499 500 #if PY_MAJOR_VERSION >= 3 501 502 static struct PyModuleDef bus_module = { 503 PyModuleDef_HEAD_INIT, 504 "bus", 505 bus_docstr, 506 -1, 507 bus_methods, 508 }; 509 510 static struct PyModuleDef busdma_module = { 511 PyModuleDef_HEAD_INIT, 512 "busdma", 513 busdma_docstr, 514 -1, 515 busdma_methods, 516 }; 517 518 PyMODINIT_FUNC 519 PyInit_bus(void) 520 { 521 PyObject *bus, *busdma; 522 523 bus = PyModule_Create(&bus_module); 524 busdma = PyModule_Create(&busdma_module); 525 return (module_initialize(bus, busdma)); 526 } 527 528 #else /* PY_MAJOR_VERSION >= 3 */ 529 530 PyMODINIT_FUNC 531 initbus(void) 532 { 533 PyObject *bus, *busdma; 534 535 bus = Py_InitModule3("bus", bus_methods, bus_docstr); 536 busdma = Py_InitModule3("busdma", busdma_methods, busdma_docstr); 537 (void)module_initialize(bus, busdma); 538 } 539 540 #endif /* PY_MAJOR_VERSION >= 3 */ 541