xref: /freebsd/tools/bus_space/Python/lang.c (revision 22cf89c938886d14f5796fc49f9f020c23ea8eaf)
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