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 *
bus_read_1(PyObject * self,PyObject * args)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 *
bus_read_2(PyObject * self,PyObject * args)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 *
bus_read_4(PyObject * self,PyObject * args)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 *
bus_write_1(PyObject * self,PyObject * args)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 *
bus_write_2(PyObject * self,PyObject * args)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 *
bus_write_4(PyObject * self,PyObject * args)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 *
bus_map(PyObject * self,PyObject * args)132 bus_map(PyObject *self, PyObject *args)
133 {
134 char *dev, *resource;
135 int rid;
136
137 if (!PyArg_ParseTuple(args, "ss", &dev, &resource))
138 return (NULL);
139 rid = bs_map(dev, resource);
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 *
bus_unmap(PyObject * self,PyObject * args)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 *
bus_subregion(PyObject * self,PyObject * args)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 *
busdma_tag_create(PyObject * self,PyObject * args)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 *
busdma_tag_derive(PyObject * self,PyObject * args)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 *
busdma_tag_destroy(PyObject * self,PyObject * args)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 *
busdma_md_create(PyObject * self,PyObject * args)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 *
busdma_md_destroy(PyObject * self,PyObject * args)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 *
busdma_md_load(PyObject * self,PyObject * args)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 *
busdma_md_unload(PyObject * self,PyObject * args)281 busdma_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
295 static PyObject *
busdma_mem_alloc(PyObject * self,PyObject * args)296 busdma_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
311 static PyObject *
busdma_mem_free(PyObject * self,PyObject * args)312 busdma_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
326 static PyObject *
busdma_md_first_seg(PyObject * self,PyObject * args)327 busdma_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
339 static PyObject *
busdma_md_next_seg(PyObject * self,PyObject * args)340 busdma_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
352 static PyObject *
busdma_seg_get_addr(PyObject * self,PyObject * args)353 busdma_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
368 static PyObject *
busdma_seg_get_size(PyObject * self,PyObject * args)369 busdma_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
384 static PyObject *
busdma_sync(PyObject * self,PyObject * args)385 busdma_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
399 static PyObject *
busdma_sync_range(PyObject * self,PyObject * args)400 busdma_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
415 /*
416 * Module methods and initialization.
417 */
418
419 static char bus_docstr[] = "Access to H/W bus memory and register areas.";
420
421 static PyMethodDef bus_methods[] = {
422 { "read_1", bus_read_1, METH_VARARGS, "Read a 1-byte data item." },
423 { "read_2", bus_read_2, METH_VARARGS, "Read a 2-byte data item." },
424 { "read_4", bus_read_4, METH_VARARGS, "Read a 4-byte data item." },
425
426 { "write_1", bus_write_1, METH_VARARGS, "Write a 1-byte data item." },
427 { "write_2", bus_write_2, METH_VARARGS, "Write a 2-byte data item." },
428 { "write_4", bus_write_4, METH_VARARGS, "Write a 4-byte data item." },
429
430 { "map", bus_map, METH_VARARGS,
431 "Return a resource ID for a device file created by proto(4)" },
432 { "unmap", bus_unmap, METH_VARARGS,
433 "Free a resource ID" },
434 { "subregion", bus_subregion, METH_VARARGS,
435 "Return a resource ID for a subregion of another resource ID" },
436
437 { NULL, NULL, 0, NULL }
438 };
439
440 static char busdma_docstr[] = "A bus- and device-independent interface"
441 " to Direct Memory Access (DMA) mechanisms.";
442
443 static PyMethodDef busdma_methods[] = {
444 { "tag_create", busdma_tag_create, METH_VARARGS,
445 "Create a root tag." },
446 { "tag_derive", busdma_tag_derive, METH_VARARGS,
447 "Derive a child tag." },
448 { "tag_destroy", busdma_tag_destroy, METH_VARARGS,
449 "Destroy a tag." },
450
451 { "md_create", busdma_md_create, METH_VARARGS,
452 "Create a new and empty memory descriptor." },
453 { "md_destroy", busdma_md_destroy, METH_VARARGS,
454 "Destroy a previously created memory descriptor." },
455 { "md_load", busdma_md_load, METH_VARARGS,
456 "Load a buffer into a memory descriptor." },
457 { "md_unload", busdma_md_unload, METH_VARARGS,
458 "Unload a memory descriptor." },
459
460 { "mem_alloc", busdma_mem_alloc, METH_VARARGS,
461 "Allocate memory according to the DMA constraints." },
462 { "mem_free", busdma_mem_free, METH_VARARGS,
463 "Free allocated memory." },
464
465 { "md_first_seg", busdma_md_first_seg, METH_VARARGS,
466 "Return first segment in one of the segment lists." },
467 { "md_next_seg", busdma_md_next_seg, METH_VARARGS,
468 "Return next segment in the segment list." },
469 { "seg_get_addr", busdma_seg_get_addr, METH_VARARGS,
470 "Return the address of the segment." },
471 { "seg_get_size", busdma_seg_get_size, METH_VARARGS,
472 "Return the size of the segment." },
473
474 { "sync", busdma_sync, METH_VARARGS,
475 "Make the entire memory descriptor coherent WRT to DMA." },
476 { "sync_range", busdma_sync_range, METH_VARARGS,
477 "Make part of the memory descriptor coherent WRT to DMA." },
478
479 { NULL, NULL, 0, NULL }
480 };
481
482 static PyObject *
module_initialize(PyObject * bus,PyObject * busdma)483 module_initialize(PyObject *bus, PyObject *busdma)
484 {
485
486 if (bus == NULL || busdma == NULL)
487 return (NULL);
488
489 PyModule_AddObject(busdma, "MD_BUS_SPACE", Py_BuildValue("i", 0));
490 PyModule_AddObject(busdma, "MD_PHYS_SPACE", Py_BuildValue("i", 1));
491 PyModule_AddObject(busdma, "MD_VIRT_SPACE", Py_BuildValue("i", 2));
492
493 PyModule_AddObject(busdma, "SYNC_PREREAD", Py_BuildValue("i", 1));
494 PyModule_AddObject(busdma, "SYNC_POSTREAD", Py_BuildValue("i", 2));
495 PyModule_AddObject(busdma, "SYNC_PREWRITE", Py_BuildValue("i", 4));
496 PyModule_AddObject(busdma, "SYNC_POSTWRITE", Py_BuildValue("i", 8));
497
498 PyModule_AddObject(bus, "dma", busdma);
499 return (bus);
500 }
501
502 #if PY_MAJOR_VERSION >= 3
503
504 static struct PyModuleDef bus_module = {
505 PyModuleDef_HEAD_INIT,
506 "bus",
507 bus_docstr,
508 -1,
509 bus_methods,
510 };
511
512 static struct PyModuleDef busdma_module = {
513 PyModuleDef_HEAD_INIT,
514 "busdma",
515 busdma_docstr,
516 -1,
517 busdma_methods,
518 };
519
520 PyMODINIT_FUNC
PyInit_bus(void)521 PyInit_bus(void)
522 {
523 PyObject *bus, *busdma;
524
525 bus = PyModule_Create(&bus_module);
526 busdma = PyModule_Create(&busdma_module);
527 return (module_initialize(bus, busdma));
528 }
529
530 #else /* PY_MAJOR_VERSION >= 3 */
531
532 PyMODINIT_FUNC
initbus(void)533 initbus(void)
534 {
535 PyObject *bus, *busdma;
536
537 bus = Py_InitModule3("bus", bus_methods, bus_docstr);
538 busdma = Py_InitModule3("busdma", busdma_methods, busdma_docstr);
539 (void)module_initialize(bus, busdma);
540 }
541
542 #endif /* PY_MAJOR_VERSION >= 3 */
543