xref: /freebsd/tools/bus_space/Python/lang.c (revision 7ef62cebc2f965b0f640263e179276928885e33d)
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, *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 *
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_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 *
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 *
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 *
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 *
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 *
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 *
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 *
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 *
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 *
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
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
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