1303233Sdim/*- 2303233Sdim * Copyright (c) 2014, 2015 Marcel Moolenaar 3303233Sdim * All rights reserved. 4353358Sdim * 5353358Sdim * Redistribution and use in source and binary forms, with or without 6353358Sdim * modification, are permitted provided that the following conditions 7303233Sdim * are met: 8303233Sdim * 9303233Sdim * 1. Redistributions of source code must retain the above copyright 10303233Sdim * notice, this list of conditions and the following disclaimer. 11303233Sdim * 2. Redistributions in binary form must reproduce the above copyright 12303233Sdim * notice, this list of conditions and the following disclaimer in the 13303233Sdim * documentation and/or other materials provided with the distribution. 14303233Sdim * 15303233Sdim * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 16303233Sdim * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 17303233Sdim * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 18341825Sdim * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 19341825Sdim * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 20303233Sdim * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21303233Sdim * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 22341825Sdim * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23341825Sdim * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24303233Sdim * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25341825Sdim */ 26341825Sdim 27341825Sdim#include <sys/cdefs.h> 28303233Sdim__FBSDID("$FreeBSD$"); 29303233Sdim 30341825Sdim#include <Python.h> 31341825Sdim 32341825Sdim#include "bus.h" 33303233Sdim#include "busdma.h" 34341825Sdim 35341825Sdimstatic PyObject * 36341825Sdimbus_read_1(PyObject *self, PyObject *args) 37303233Sdim{ 38303233Sdim long ofs; 39341825Sdim int rid; 40341825Sdim uint8_t val; 41341825Sdim 42303233Sdim if (!PyArg_ParseTuple(args, "il", &rid, &ofs)) 43341825Sdim return (NULL); 44341825Sdim if (!bs_read(rid, ofs, &val, sizeof(val))) { 45341825Sdim PyErr_SetString(PyExc_IOError, strerror(errno)); 46303233Sdim return (NULL); 47303233Sdim } 48341825Sdim return (Py_BuildValue("B", val)); 49341825Sdim} 50341825Sdim 51303233Sdimstatic PyObject * 52341825Sdimbus_read_2(PyObject *self, PyObject *args) 53341825Sdim{ 54341825Sdim long ofs; 55303233Sdim int rid; 56303233Sdim uint16_t val; 57341825Sdim 58341825Sdim if (!PyArg_ParseTuple(args, "il", &rid, &ofs)) 59303233Sdim return (NULL); 60341825Sdim if (!bs_read(rid, ofs, &val, sizeof(val))) { 61341825Sdim PyErr_SetString(PyExc_IOError, strerror(errno)); 62303233Sdim return (NULL); 63303233Sdim } 64341825Sdim return (Py_BuildValue("H", val)); 65341825Sdim} 66341825Sdim 67303233Sdimstatic PyObject * 68341825Sdimbus_read_4(PyObject *self, PyObject *args) 69341825Sdim{ 70341825Sdim long ofs; 71303233Sdim int rid; 72303233Sdim uint32_t val; 73341825Sdim 74341825Sdim if (!PyArg_ParseTuple(args, "il", &rid, &ofs)) 75341825Sdim return (NULL); 76303233Sdim if (!bs_read(rid, ofs, &val, sizeof(val))) { 77341825Sdim PyErr_SetString(PyExc_IOError, strerror(errno)); 78341825Sdim return (NULL); 79341825Sdim } 80303233Sdim return (Py_BuildValue("I", val)); 81303233Sdim} 82341825Sdim 83341825Sdimstatic PyObject * 84341825Sdimbus_write_1(PyObject *self, PyObject *args) 85303233Sdim{ 86341825Sdim long ofs; 87341825Sdim int rid; 88341825Sdim uint8_t val; 89303233Sdim 90303233Sdim if (!PyArg_ParseTuple(args, "ilB", &rid, &ofs, &val)) 91341825Sdim return (NULL); 92303233Sdim if (!bs_write(rid, ofs, &val, sizeof(val))) { 93303233Sdim PyErr_SetString(PyExc_IOError, strerror(errno)); 94341825Sdim return (NULL); 95303233Sdim } 96303233Sdim Py_RETURN_NONE; 97341825Sdim} 98303233Sdim 99303233Sdimstatic PyObject * 100341825Sdimbus_write_2(PyObject *self, PyObject *args) 101341825Sdim{ 102341825Sdim long ofs; 103303233Sdim int rid; 104303233Sdim uint16_t val; 105341825Sdim 106303233Sdim if (!PyArg_ParseTuple(args, "ilH", &rid, &ofs, &val)) 107303233Sdim return (NULL); 108303233Sdim if (!bs_write(rid, ofs, &val, sizeof(val))) { 109341825Sdim PyErr_SetString(PyExc_IOError, strerror(errno)); 110341825Sdim return (NULL); 111341825Sdim } 112303233Sdim Py_RETURN_NONE; 113303233Sdim} 114341825Sdim 115303233Sdimstatic PyObject * 116303233Sdimbus_write_4(PyObject *self, PyObject *args) 117341825Sdim{ 118303233Sdim long ofs; 119303233Sdim int rid; 120341825Sdim uint32_t val; 121303233Sdim 122303233Sdim if (!PyArg_ParseTuple(args, "ilI", &rid, &ofs, &val)) 123303233Sdim return (NULL); 124341825Sdim if (!bs_write(rid, ofs, &val, sizeof(val))) { 125341825Sdim PyErr_SetString(PyExc_IOError, strerror(errno)); 126341825Sdim return (NULL); 127303233Sdim } 128303233Sdim Py_RETURN_NONE; 129341825Sdim} 130303233Sdim 131303233Sdimstatic PyObject * 132303233Sdimbus_map(PyObject *self, PyObject *args) 133341825Sdim{ 134341825Sdim char *dev, *resource; 135341825Sdim int rid; 136303233Sdim 137303233Sdim if (!PyArg_ParseTuple(args, "ss", &dev, &resource)) 138341825Sdim return (NULL); 139344779Sdim rid = bs_map(dev, resource); 140303233Sdim if (rid == -1) { 141344779Sdim PyErr_SetString(PyExc_IOError, strerror(errno)); 142303233Sdim return (NULL); 143303233Sdim } 144341825Sdim return (Py_BuildValue("i", rid)); 145344779Sdim} 146344779Sdim 147303233Sdimstatic PyObject * 148344779Sdimbus_unmap(PyObject *self, PyObject *args) 149344779Sdim{ 150344779Sdim int rid; 151303233Sdim 152303233Sdim if (!PyArg_ParseTuple(args, "i", &rid)) 153341825Sdim return (NULL); 154344779Sdim if (!bs_unmap(rid)) { 155303233Sdim PyErr_SetString(PyExc_IOError, strerror(errno)); 156344779Sdim return (NULL); 157344779Sdim } 158344779Sdim Py_RETURN_NONE; 159303233Sdim} 160303233Sdim 161341825Sdimstatic PyObject * 162344779Sdimbus_subregion(PyObject *self, PyObject *args) 163303233Sdim{ 164344779Sdim long ofs, sz; 165303233Sdim int rid0, rid; 166303233Sdim 167341825Sdim if (!PyArg_ParseTuple(args, "ill", &rid0, &ofs, &sz)) 168344779Sdim return (NULL); 169344779Sdim rid = bs_subregion(rid0, ofs, sz); 170303233Sdim if (rid == -1) { 171344779Sdim PyErr_SetString(PyExc_IOError, strerror(errno)); 172344779Sdim return (NULL); 173344779Sdim } 174303233Sdim return (Py_BuildValue("i", rid)); 175303233Sdim} 176341825Sdim 177344779Sdimstatic PyObject * 178303233Sdimbusdma_tag_create(PyObject *self, PyObject *args) 179344779Sdim{ 180344779Sdim char *dev; 181344779Sdim u_long align, bndry, maxaddr, maxsz, maxsegsz; 182303233Sdim u_int nsegs, datarate, flags; 183303233Sdim int tid; 184303233Sdim 185341825Sdim if (!PyArg_ParseTuple(args, "skkkkIkII", &dev, &align, &bndry, 186341825Sdim &maxaddr, &maxsz, &nsegs, &maxsegsz, &datarate, &flags)) 187303233Sdim return (NULL); 188303233Sdim 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 197static PyObject * 198busdma_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 216static PyObject * 217busdma_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 231static PyObject * 232busdma_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 247static PyObject * 248busdma_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 262static PyObject * 263busdma_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 280static PyObject * 281busdma_md_unload(PyObject *self, PyObject *args) 282{ 283 int error, mdid; 284 285 if (!PyArg_ParseTuple(args, "i", &mdid)) 286 return (NULL); 287 error = bd_md_unload(mdid); 288 if (error) { 289 PyErr_SetString(PyExc_IOError, strerror(error)); 290 return (NULL); 291 } 292 Py_RETURN_NONE; 293} 294 295static PyObject * 296busdma_mem_alloc(PyObject *self, PyObject *args) 297{ 298 u_int flags; 299 int mdid, tid; 300 301 if (!PyArg_ParseTuple(args, "iI", &tid, &flags)) 302 return (NULL); 303 mdid = bd_mem_alloc(tid, flags); 304 if (mdid == -1) { 305 PyErr_SetString(PyExc_IOError, strerror(errno)); 306 return (NULL); 307 } 308 return (Py_BuildValue("i", mdid)); 309} 310 311static PyObject * 312busdma_mem_free(PyObject *self, PyObject *args) 313{ 314 int error, mdid; 315 316 if (!PyArg_ParseTuple(args, "i", &mdid)) 317 return (NULL); 318 error = bd_mem_free(mdid); 319 if (error) { 320 PyErr_SetString(PyExc_IOError, strerror(error)); 321 return (NULL); 322 } 323 Py_RETURN_NONE; 324} 325 326static PyObject * 327busdma_md_first_seg(PyObject *self, PyObject *args) 328{ 329 int error, mdid, sid, what; 330 331 if (!PyArg_ParseTuple(args, "ii", &mdid, &what)) 332 return (NULL); 333 sid = bd_md_first_seg(mdid, what); 334 if (sid == -1) 335 Py_RETURN_NONE; 336 return (Py_BuildValue("i", sid)); 337} 338 339static PyObject * 340busdma_md_next_seg(PyObject *self, PyObject *args) 341{ 342 int error, mdid, sid; 343 344 if (!PyArg_ParseTuple(args, "ii", &mdid, &sid)) 345 return (NULL); 346 sid = bd_md_next_seg(mdid, sid); 347 if (sid == -1) 348 Py_RETURN_NONE; 349 return (Py_BuildValue("i", sid)); 350} 351 352static PyObject * 353busdma_seg_get_addr(PyObject *self, PyObject *args) 354{ 355 u_long addr; 356 int error, sid; 357 358 if (!PyArg_ParseTuple(args, "i", &sid)) 359 return (NULL); 360 error = bd_seg_get_addr(sid, &addr); 361 if (error) { 362 PyErr_SetString(PyExc_IOError, strerror(error)); 363 return (NULL); 364 } 365 return (Py_BuildValue("k", addr)); 366} 367 368static PyObject * 369busdma_seg_get_size(PyObject *self, PyObject *args) 370{ 371 u_long size; 372 int error, sid; 373 374 if (!PyArg_ParseTuple(args, "i", &sid)) 375 return (NULL); 376 error = bd_seg_get_size(sid, &size); 377 if (error) { 378 PyErr_SetString(PyExc_IOError, strerror(error)); 379 return (NULL); 380 } 381 return (Py_BuildValue("k", size)); 382} 383 384static PyObject * 385busdma_sync(PyObject *self, PyObject *args) 386{ 387 int error, mdid, op; 388 389 if (!PyArg_ParseTuple(args, "ii", &mdid, &op)) 390 return (NULL); 391 error = bd_sync(mdid, op, 0UL, ~0UL); 392 if (error) { 393 PyErr_SetString(PyExc_IOError, strerror(error)); 394 return (NULL); 395 } 396 Py_RETURN_NONE; 397} 398 399static PyObject * 400busdma_sync_range(PyObject *self, PyObject *args) 401{ 402 u_long ofs, len; 403 int error, mdid, op; 404 405 if (!PyArg_ParseTuple(args, "iikk", &mdid, &op, &ofs, &len)) 406 return (NULL); 407 error = bd_sync(mdid, op, ofs, len); 408 if (error) { 409 PyErr_SetString(PyExc_IOError, strerror(error)); 410 return (NULL); 411 } 412 Py_RETURN_NONE; 413} 414 415static PyMethodDef bus_methods[] = { 416 { "read_1", bus_read_1, METH_VARARGS, "Read a 1-byte data item." }, 417 { "read_2", bus_read_2, METH_VARARGS, "Read a 2-byte data item." }, 418 { "read_4", bus_read_4, METH_VARARGS, "Read a 4-byte data item." }, 419 420 { "write_1", bus_write_1, METH_VARARGS, "Write a 1-byte data item." }, 421 { "write_2", bus_write_2, METH_VARARGS, "Write a 2-byte data item." }, 422 { "write_4", bus_write_4, METH_VARARGS, "Write a 4-byte data item." }, 423 424 { "map", bus_map, METH_VARARGS, 425 "Return a resource ID for a device file created by proto(4)" }, 426 { "unmap", bus_unmap, METH_VARARGS, 427 "Free a resource ID" }, 428 { "subregion", bus_subregion, METH_VARARGS, 429 "Return a resource ID for a subregion of another resource ID" }, 430 431 { NULL, NULL, 0, NULL } 432}; 433 434static PyMethodDef busdma_methods[] = { 435 { "tag_create", busdma_tag_create, METH_VARARGS, 436 "Create a root tag." }, 437 { "tag_derive", busdma_tag_derive, METH_VARARGS, 438 "Derive a child tag." }, 439 { "tag_destroy", busdma_tag_destroy, METH_VARARGS, 440 "Destroy a tag." }, 441 442 { "md_create", busdma_md_create, METH_VARARGS, 443 "Create a new and empty memory descriptor." }, 444 { "md_destroy", busdma_md_destroy, METH_VARARGS, 445 "Destroy a previously created memory descriptor." }, 446 { "md_load", busdma_md_load, METH_VARARGS, 447 "Load a buffer into a memory descriptor." }, 448 { "md_unload", busdma_md_unload, METH_VARARGS, 449 "Unload a memory descriptor." }, 450 451 { "mem_alloc", busdma_mem_alloc, METH_VARARGS, 452 "Allocate memory according to the DMA constraints." }, 453 { "mem_free", busdma_mem_free, METH_VARARGS, 454 "Free allocated memory." }, 455 456 { "md_first_seg", busdma_md_first_seg, METH_VARARGS, 457 "Return first segment in one of the segment lists." }, 458 { "md_next_seg", busdma_md_next_seg, METH_VARARGS, 459 "Return next segment in the segment list." }, 460 { "seg_get_addr", busdma_seg_get_addr, METH_VARARGS, 461 "Return the address of the segment." }, 462 { "seg_get_size", busdma_seg_get_size, METH_VARARGS, 463 "Return the size of the segment." }, 464 465 { "sync", busdma_sync, METH_VARARGS, 466 "Make the entire memory descriptor coherent WRT to DMA." }, 467 { "sync_range", busdma_sync_range, METH_VARARGS, 468 "Make part of the memory descriptor coherent WRT to DMA." }, 469 470 { NULL, NULL, 0, NULL } 471}; 472 473PyMODINIT_FUNC 474initbus(void) 475{ 476 PyObject *bus, *busdma; 477 478 bus = Py_InitModule("bus", bus_methods); 479 if (bus == NULL) 480 return; 481 busdma = Py_InitModule("busdma", busdma_methods); 482 if (busdma == NULL) 483 return; 484 PyModule_AddObject(bus, "dma", busdma); 485 486 PyModule_AddObject(busdma, "MD_BUS_SPACE", Py_BuildValue("i", 0)); 487 PyModule_AddObject(busdma, "MD_PHYS_SPACE", Py_BuildValue("i", 1)); 488 PyModule_AddObject(busdma, "MD_VIRT_SPACE", Py_BuildValue("i", 2)); 489 490 PyModule_AddObject(busdma, "SYNC_PREREAD", Py_BuildValue("i", 1)); 491 PyModule_AddObject(busdma, "SYNC_POSTREAD", Py_BuildValue("i", 2)); 492 PyModule_AddObject(busdma, "SYNC_PREWRITE", Py_BuildValue("i", 4)); 493 PyModule_AddObject(busdma, "SYNC_POSTWRITE", Py_BuildValue("i", 8)); 494} 495