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 *
bus_read_1(PyObject * self,PyObject * args)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 *
bus_read_2(PyObject * self,PyObject * args)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 *
bus_read_4(PyObject * self,PyObject * args)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 *
bus_write_1(PyObject * self,PyObject * args)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 *
bus_write_2(PyObject * self,PyObject * args)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 *
bus_write_4(PyObject * self,PyObject * args)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 *
bus_map(PyObject * self,PyObject * args)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 *
bus_unmap(PyObject * self,PyObject * args)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 *
bus_subregion(PyObject * self,PyObject * args)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 *
busdma_tag_create(PyObject * self,PyObject * args)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 *
busdma_tag_derive(PyObject * self,PyObject * args)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 *
busdma_tag_destroy(PyObject * self,PyObject * args)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 *
busdma_md_create(PyObject * self,PyObject * args)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 *
busdma_md_destroy(PyObject * self,PyObject * args)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 *
busdma_md_load(PyObject * self,PyObject * args)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 *
busdma_md_unload(PyObject * self,PyObject * args)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 *
busdma_mem_alloc(PyObject * self,PyObject * args)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 *
busdma_mem_free(PyObject * self,PyObject * args)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 *
busdma_md_first_seg(PyObject * self,PyObject * args)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 *
busdma_md_next_seg(PyObject * self,PyObject * args)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 *
busdma_seg_get_addr(PyObject * self,PyObject * args)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 *
busdma_seg_get_size(PyObject * self,PyObject * args)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 *
busdma_sync(PyObject * self,PyObject * args)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 *
busdma_sync_range(PyObject * self,PyObject * args)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 *
module_initialize(PyObject * bus,PyObject * busdma)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
PyInit_bus(void)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
initbus(void)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