Index: head/tools/bus_space/Python/Makefile =================================================================== --- head/tools/bus_space/Python/Makefile (revision 349550) +++ head/tools/bus_space/Python/Makefile (revision 349551) @@ -1,9 +1,13 @@ # $FreeBSD$ SHLIB_NAME= bus.so SRCS= lang.c -CFLAGS+= -I${.CURDIR}/.. -I/usr/local/include/python2.7 -LDFLAGS+= -L/usr/local/lib -lpython2.7 +# Set PYTHON to the version to compile against. +# E.g. "python2.7", "python3.6", etc... +PYTHON= python3.6m + +CFLAGS+= -I${.CURDIR}/.. -I/usr/local/include/${PYTHON} +LDFLAGS+= -L/usr/local/lib -l${PYTHON} .include Index: head/tools/bus_space/Python/lang.c =================================================================== --- head/tools/bus_space/Python/lang.c (revision 349550) +++ head/tools/bus_space/Python/lang.c (revision 349551) @@ -1,494 +1,542 @@ /*- * Copyright (c) 2014, 2015 Marcel Moolenaar * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); #include #include "bus.h" #include "busdma.h" static PyObject * bus_read_1(PyObject *self, PyObject *args) { long ofs; int rid; uint8_t val; if (!PyArg_ParseTuple(args, "il", &rid, &ofs)) return (NULL); if (!bs_read(rid, ofs, &val, sizeof(val))) { PyErr_SetString(PyExc_IOError, strerror(errno)); return (NULL); } return (Py_BuildValue("B", val)); } static PyObject * bus_read_2(PyObject *self, PyObject *args) { long ofs; int rid; uint16_t val; if (!PyArg_ParseTuple(args, "il", &rid, &ofs)) return (NULL); if (!bs_read(rid, ofs, &val, sizeof(val))) { PyErr_SetString(PyExc_IOError, strerror(errno)); return (NULL); } return (Py_BuildValue("H", val)); } static PyObject * bus_read_4(PyObject *self, PyObject *args) { long ofs; int rid; uint32_t val; if (!PyArg_ParseTuple(args, "il", &rid, &ofs)) return (NULL); if (!bs_read(rid, ofs, &val, sizeof(val))) { PyErr_SetString(PyExc_IOError, strerror(errno)); return (NULL); } return (Py_BuildValue("I", val)); } static PyObject * bus_write_1(PyObject *self, PyObject *args) { long ofs; int rid; uint8_t val; if (!PyArg_ParseTuple(args, "ilB", &rid, &ofs, &val)) return (NULL); if (!bs_write(rid, ofs, &val, sizeof(val))) { PyErr_SetString(PyExc_IOError, strerror(errno)); return (NULL); } Py_RETURN_NONE; } static PyObject * bus_write_2(PyObject *self, PyObject *args) { long ofs; int rid; uint16_t val; if (!PyArg_ParseTuple(args, "ilH", &rid, &ofs, &val)) return (NULL); if (!bs_write(rid, ofs, &val, sizeof(val))) { PyErr_SetString(PyExc_IOError, strerror(errno)); return (NULL); } Py_RETURN_NONE; } static PyObject * bus_write_4(PyObject *self, PyObject *args) { long ofs; int rid; uint32_t val; if (!PyArg_ParseTuple(args, "ilI", &rid, &ofs, &val)) return (NULL); if (!bs_write(rid, ofs, &val, sizeof(val))) { PyErr_SetString(PyExc_IOError, strerror(errno)); return (NULL); } Py_RETURN_NONE; } static PyObject * bus_map(PyObject *self, PyObject *args) { char *dev, *resource; int rid; if (!PyArg_ParseTuple(args, "ss", &dev, &resource)) return (NULL); rid = bs_map(dev, resource); if (rid == -1) { PyErr_SetString(PyExc_IOError, strerror(errno)); return (NULL); } return (Py_BuildValue("i", rid)); } static PyObject * bus_unmap(PyObject *self, PyObject *args) { int rid; if (!PyArg_ParseTuple(args, "i", &rid)) return (NULL); if (!bs_unmap(rid)) { PyErr_SetString(PyExc_IOError, strerror(errno)); return (NULL); } Py_RETURN_NONE; } static PyObject * bus_subregion(PyObject *self, PyObject *args) { long ofs, sz; int rid0, rid; if (!PyArg_ParseTuple(args, "ill", &rid0, &ofs, &sz)) return (NULL); rid = bs_subregion(rid0, ofs, sz); if (rid == -1) { PyErr_SetString(PyExc_IOError, strerror(errno)); return (NULL); } return (Py_BuildValue("i", rid)); } static PyObject * busdma_tag_create(PyObject *self, PyObject *args) { char *dev; u_long align, bndry, maxaddr, maxsz, maxsegsz; u_int nsegs, datarate, flags; int tid; if (!PyArg_ParseTuple(args, "skkkkIkII", &dev, &align, &bndry, &maxaddr, &maxsz, &nsegs, &maxsegsz, &datarate, &flags)) return (NULL); tid = bd_tag_create(dev, align, bndry, maxaddr, maxsz, nsegs, maxsegsz, datarate, flags); if (tid == -1) { PyErr_SetString(PyExc_IOError, strerror(errno)); return (NULL); } return (Py_BuildValue("i", tid)); } static PyObject * busdma_tag_derive(PyObject *self, PyObject *args) { u_long align, bndry, maxaddr, maxsz, maxsegsz; u_int nsegs, datarate, flags; int ptid, tid; if (!PyArg_ParseTuple(args, "ikkkkIkII", &ptid, &align, &bndry, &maxaddr, &maxsz, &nsegs, &maxsegsz, &datarate, &flags)) return (NULL); tid = bd_tag_derive(ptid, align, bndry, maxaddr, maxsz, nsegs, maxsegsz, datarate, flags); if (tid == -1) { PyErr_SetString(PyExc_IOError, strerror(errno)); return (NULL); } return (Py_BuildValue("i", tid)); } static PyObject * busdma_tag_destroy(PyObject *self, PyObject *args) { int error, tid; if (!PyArg_ParseTuple(args, "i", &tid)) return (NULL); error = bd_tag_destroy(tid); if (error) { PyErr_SetString(PyExc_IOError, strerror(error)); return (NULL); } Py_RETURN_NONE; } static PyObject * busdma_md_create(PyObject *self, PyObject *args) { u_int flags; int error, mdid, tid; if (!PyArg_ParseTuple(args, "iI", &tid, &flags)) return (NULL); mdid = bd_md_create(tid, flags); if (mdid == -1) { PyErr_SetString(PyExc_IOError, strerror(errno)); return (NULL); } return (Py_BuildValue("i", mdid)); } static PyObject * busdma_md_destroy(PyObject *self, PyObject *args) { int error, mdid; if (!PyArg_ParseTuple(args, "i", &mdid)) return (NULL); error = bd_md_destroy(mdid); if (error) { PyErr_SetString(PyExc_IOError, strerror(error)); return (NULL); } Py_RETURN_NONE; } static PyObject * busdma_md_load(PyObject *self, PyObject *args) { void *buf; u_long len; u_int flags; int error, mdid; if (!PyArg_ParseTuple(args, "iwkI", &mdid, &buf, &len, &flags)) return (NULL); error = bd_md_load(mdid, buf, len, flags); if (error) { PyErr_SetString(PyExc_IOError, strerror(error)); return (NULL); } Py_RETURN_NONE; } static PyObject * busdma_md_unload(PyObject *self, PyObject *args) { int error, mdid; if (!PyArg_ParseTuple(args, "i", &mdid)) return (NULL); error = bd_md_unload(mdid); if (error) { PyErr_SetString(PyExc_IOError, strerror(error)); return (NULL); } Py_RETURN_NONE; } static PyObject * busdma_mem_alloc(PyObject *self, PyObject *args) { u_int flags; int mdid, tid; if (!PyArg_ParseTuple(args, "iI", &tid, &flags)) return (NULL); mdid = bd_mem_alloc(tid, flags); if (mdid == -1) { PyErr_SetString(PyExc_IOError, strerror(errno)); return (NULL); } return (Py_BuildValue("i", mdid)); } static PyObject * busdma_mem_free(PyObject *self, PyObject *args) { int error, mdid; if (!PyArg_ParseTuple(args, "i", &mdid)) return (NULL); error = bd_mem_free(mdid); if (error) { PyErr_SetString(PyExc_IOError, strerror(error)); return (NULL); } Py_RETURN_NONE; } static PyObject * busdma_md_first_seg(PyObject *self, PyObject *args) { int error, mdid, sid, what; if (!PyArg_ParseTuple(args, "ii", &mdid, &what)) return (NULL); sid = bd_md_first_seg(mdid, what); if (sid == -1) Py_RETURN_NONE; return (Py_BuildValue("i", sid)); } static PyObject * busdma_md_next_seg(PyObject *self, PyObject *args) { int error, mdid, sid; if (!PyArg_ParseTuple(args, "ii", &mdid, &sid)) return (NULL); sid = bd_md_next_seg(mdid, sid); if (sid == -1) Py_RETURN_NONE; return (Py_BuildValue("i", sid)); } static PyObject * busdma_seg_get_addr(PyObject *self, PyObject *args) { u_long addr; int error, sid; if (!PyArg_ParseTuple(args, "i", &sid)) return (NULL); error = bd_seg_get_addr(sid, &addr); if (error) { PyErr_SetString(PyExc_IOError, strerror(error)); return (NULL); } return (Py_BuildValue("k", addr)); } static PyObject * busdma_seg_get_size(PyObject *self, PyObject *args) { u_long size; int error, sid; if (!PyArg_ParseTuple(args, "i", &sid)) return (NULL); error = bd_seg_get_size(sid, &size); if (error) { PyErr_SetString(PyExc_IOError, strerror(error)); return (NULL); } return (Py_BuildValue("k", size)); } static PyObject * busdma_sync(PyObject *self, PyObject *args) { int error, mdid, op; if (!PyArg_ParseTuple(args, "ii", &mdid, &op)) return (NULL); error = bd_sync(mdid, op, 0UL, ~0UL); if (error) { PyErr_SetString(PyExc_IOError, strerror(error)); return (NULL); } Py_RETURN_NONE; } static PyObject * busdma_sync_range(PyObject *self, PyObject *args) { u_long ofs, len; int error, mdid, op; if (!PyArg_ParseTuple(args, "iikk", &mdid, &op, &ofs, &len)) return (NULL); error = bd_sync(mdid, op, ofs, len); if (error) { PyErr_SetString(PyExc_IOError, strerror(error)); return (NULL); } Py_RETURN_NONE; } +/* + * Module methods and initialization. + */ + +static char bus_docstr[] = "Access to H/W bus memory and register areas."; + static PyMethodDef bus_methods[] = { { "read_1", bus_read_1, METH_VARARGS, "Read a 1-byte data item." }, { "read_2", bus_read_2, METH_VARARGS, "Read a 2-byte data item." }, { "read_4", bus_read_4, METH_VARARGS, "Read a 4-byte data item." }, { "write_1", bus_write_1, METH_VARARGS, "Write a 1-byte data item." }, { "write_2", bus_write_2, METH_VARARGS, "Write a 2-byte data item." }, { "write_4", bus_write_4, METH_VARARGS, "Write a 4-byte data item." }, { "map", bus_map, METH_VARARGS, "Return a resource ID for a device file created by proto(4)" }, { "unmap", bus_unmap, METH_VARARGS, "Free a resource ID" }, { "subregion", bus_subregion, METH_VARARGS, "Return a resource ID for a subregion of another resource ID" }, { NULL, NULL, 0, NULL } }; +static char busdma_docstr[] = "A bus- and device-independent interface" + " to Direct Memory Access (DMA) mechanisms."; + static PyMethodDef busdma_methods[] = { { "tag_create", busdma_tag_create, METH_VARARGS, "Create a root tag." }, { "tag_derive", busdma_tag_derive, METH_VARARGS, "Derive a child tag." }, { "tag_destroy", busdma_tag_destroy, METH_VARARGS, "Destroy a tag." }, { "md_create", busdma_md_create, METH_VARARGS, "Create a new and empty memory descriptor." }, { "md_destroy", busdma_md_destroy, METH_VARARGS, "Destroy a previously created memory descriptor." }, { "md_load", busdma_md_load, METH_VARARGS, "Load a buffer into a memory descriptor." }, { "md_unload", busdma_md_unload, METH_VARARGS, "Unload a memory descriptor." }, { "mem_alloc", busdma_mem_alloc, METH_VARARGS, "Allocate memory according to the DMA constraints." }, { "mem_free", busdma_mem_free, METH_VARARGS, "Free allocated memory." }, { "md_first_seg", busdma_md_first_seg, METH_VARARGS, "Return first segment in one of the segment lists." }, { "md_next_seg", busdma_md_next_seg, METH_VARARGS, "Return next segment in the segment list." }, { "seg_get_addr", busdma_seg_get_addr, METH_VARARGS, "Return the address of the segment." }, { "seg_get_size", busdma_seg_get_size, METH_VARARGS, "Return the size of the segment." }, { "sync", busdma_sync, METH_VARARGS, "Make the entire memory descriptor coherent WRT to DMA." }, { "sync_range", busdma_sync_range, METH_VARARGS, "Make part of the memory descriptor coherent WRT to DMA." }, { NULL, NULL, 0, NULL } }; -PyMODINIT_FUNC -initbus(void) +static PyObject * +module_initialize(PyObject *bus, PyObject *busdma) { - PyObject *bus, *busdma; - bus = Py_InitModule("bus", bus_methods); - if (bus == NULL) - return; - busdma = Py_InitModule("busdma", busdma_methods); - if (busdma == NULL) - return; - PyModule_AddObject(bus, "dma", busdma); + if (bus == NULL || busdma == NULL) + return (NULL); PyModule_AddObject(busdma, "MD_BUS_SPACE", Py_BuildValue("i", 0)); PyModule_AddObject(busdma, "MD_PHYS_SPACE", Py_BuildValue("i", 1)); PyModule_AddObject(busdma, "MD_VIRT_SPACE", Py_BuildValue("i", 2)); PyModule_AddObject(busdma, "SYNC_PREREAD", Py_BuildValue("i", 1)); PyModule_AddObject(busdma, "SYNC_POSTREAD", Py_BuildValue("i", 2)); PyModule_AddObject(busdma, "SYNC_PREWRITE", Py_BuildValue("i", 4)); PyModule_AddObject(busdma, "SYNC_POSTWRITE", Py_BuildValue("i", 8)); + + PyModule_AddObject(bus, "dma", busdma); + return (bus); } + +#if PY_MAJOR_VERSION >= 3 + +static struct PyModuleDef bus_module = { + PyModuleDef_HEAD_INIT, + "bus", + bus_docstr, + -1, + bus_methods, +}; + +static struct PyModuleDef busdma_module = { + PyModuleDef_HEAD_INIT, + "busdma", + busdma_docstr, + -1, + busdma_methods, +}; + +PyMODINIT_FUNC +PyInit_bus(void) +{ + PyObject *bus, *busdma; + + bus = PyModule_Create(&bus_module); + busdma = PyModule_Create(&busdma_module); + return (module_initialize(bus, busdma)); +} + +#else /* PY_MAJOR_VERSION >= 3 */ + +PyMODINIT_FUNC +initbus(void) +{ + PyObject *bus, *busdma; + + bus = Py_InitModule3("bus", bus_methods, bus_docstr); + busdma = Py_InitModule3("busdma", busdma_methods, busdma_docstr); + (void)module_initialize(bus, busdma); +} + +#endif /* PY_MAJOR_VERSION >= 3 */ Index: head/tools/bus_space/examples/am79c900_diag.py =================================================================== --- head/tools/bus_space/examples/am79c900_diag.py (revision 349550) +++ head/tools/bus_space/examples/am79c900_diag.py (revision 349551) @@ -1,344 +1,344 @@ #!/usr/bin/env python # # Copyright (c) 2014 Marcel Moolenaar # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # 1. Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # 2. Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR # IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES # OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. # IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT # NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF # THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # # $FreeBSD$ # ''' Simple diagnostics program fo the AMD Am89c900 series ILACC. This ethernet controller is emulated by VMware Fusion among possibly other virtualization platforms. The datasheet can be found here: http://support.amd.com/TechDocs/18219.pdf This example program sends a single DHCP discovery packet, waits 2 seconds and then iterates over the receive ring for a targeted packet. For this program to function, connect the network interface to a network with a DHCP server. In VMware Fusion this can best be done by configuring the interface as a NAT interface using the "Share with my Mac" setting. ''' import ctypes import logging import os import sys import time sys.path.append('/usr/lib') import bus -import busdma +from bus import dma as busdma # ILACC initialization block definition class initblock(ctypes.LittleEndianStructure): _fields_ = [('mode', ctypes.c_uint32), ('hwaddr', ctypes.c_uint8 * 6), ('_pad1_', ctypes.c_uint16), ('filter', ctypes.c_uint16 * 4), ('rxdesc', ctypes.c_uint32), ('txdesc', ctypes.c_uint32), ('_pad2_', ctypes.c_uint32)] # ILACC ring buffer descriptor class bufdesc(ctypes.LittleEndianStructure): _fields_ = [('buffer', ctypes.c_uint32), ('flags', ctypes.c_uint32), ('length', ctypes.c_uint32), ('_pad_', ctypes.c_uint32)] # The DHCP packet definition (incl. all headers) class packet(ctypes.BigEndianStructure): _pack_ = 1 _fields_ = [('eth_dest', ctypes.c_uint8 * 6), ('eth_src', ctypes.c_uint8 * 6), ('eth_type', ctypes.c_uint16), ('ip_vl', ctypes.c_uint8), ('ip_de', ctypes.c_uint8), ('ip_len', ctypes.c_uint16), ('ip_id', ctypes.c_uint16), ('ip_ff', ctypes.c_uint16), ('ip_ttl', ctypes.c_uint8), ('ip_proto', ctypes.c_uint8), ('ip_cksum', ctypes.c_uint16), ('ip_src', ctypes.c_uint32), ('ip_dest', ctypes.c_uint32), ('udp_src', ctypes.c_uint16), ('udp_dest', ctypes.c_uint16), ('udp_len', ctypes.c_uint16), ('udp_cksum', ctypes.c_uint16), ('bootp_op', ctypes.c_uint8), ('bootp_htype', ctypes.c_uint8), ('bootp_hlen', ctypes.c_uint8), ('bootp_hops', ctypes.c_uint8), ('bootp_xid', ctypes.c_uint32), ('bootp_secs', ctypes.c_uint16), ('bootp_flags', ctypes.c_uint16), ('bootp_ciaddr', ctypes.c_uint32), ('bootp_yiaddr', ctypes.c_uint32), ('bootp_siaddr', ctypes.c_uint32), ('bootp_giaddr', ctypes.c_uint32), ('bootp_chaddr', ctypes.c_uint8 * 16), ('bootp_sname', ctypes.c_uint8 * 64), ('bootp_file', ctypes.c_uint8 * 128), ('dhcp_magic', ctypes.c_uint32), ('dhcp_options', ctypes.c_uint8 * 60)] MACFMT = '%02x:%02x:%02x:%02x:%02x:%02x' dev = 'pci0:2:1:0' logging.basicConfig(level=logging.DEBUG) pcicfg = bus.map(dev, 'pcicfg') logging.debug('pcicfg=%s (%s)' % (pcicfg, dev)) vendor = bus.read_2(pcicfg, 0) device = bus.read_2(pcicfg, 2) if vendor != 0x1022 or device != 0x2000: logging.error('Not an AMD PCnet-PCI (vendor=%x, device=%x)' % (vendor, device)) sys.exit(1) command = bus.read_2(pcicfg, 4) if not (command & 1): logging.info('enabling I/O port decoding') command |= 1 bus.write_2(pcicfg, 4, command) if not (command & 4): logging.info('enabling bus mastering') command |= 4 bus.write_2(pcicfg, 4, command) bus.unmap(pcicfg) io = bus.map(dev, '10.io') logging.debug('io=%s (%s)' % (io, dev)) def delay(msec): time.sleep(msec / 1000.0) def ffs(x): y = (1 + (x ^ (x-1))) >> 1 return y.bit_length() def ip_str(a): return '%d.%d.%d.%d' % ((a >> 24) & 255, (a >> 16) & 255, (a >> 8) & 255, a & 255) def mac_is(l, r): - for i in xrange(6): + for i in range(6): if l[i] != r[i]: return False return True def mac_str(m): return MACFMT % (m[0], m[1], m[2], m[3], m[4], m[5]) def rdbcr(reg): bus.write_2(io, 0x12, reg & 0xffff) return bus.read_2(io, 0x16) def wrbcr(reg, val): bus.write_2(io, 0x12, reg & 0xffff) bus.write_2(io, 0x16, val & 0xffff) def rdcsr(reg): bus.write_2(io, 0x12, reg & 0xffff) return bus.read_2(io, 0x10) def wrcsr(reg, val): bus.write_2(io, 0x12, reg & 0xffff) bus.write_2(io, 0x10, val & 0xffff) def start(): wrcsr(0, 0x42) delay(100) def stop(): wrcsr(0, 4) delay(100) mac = () bcast = () -for o in xrange(6): +for o in range(6): mac += (bus.read_1(io, o),) bcast += (0xff,) logging.info('ethernet address = ' + MACFMT % mac) stop() wrbcr(20, 2) # reset wrcsr(3, 0) # byte swapping mode wrbcr(2, rdbcr(2) | 2) # Autoneg memsize = 32*1024 bufsize = 1536 nrxbufs = 16 ntxbufs = 4 logging.debug("DMA memory: size = %#x (TX buffers: %u, RX buffers: %u)" % (memsize, ntxbufs, nrxbufs)) mem_tag = busdma.tag_create(dev, 16, 0, 0xffffffff, memsize, 1, memsize, 0, 0) dmamem = busdma.mem_alloc(mem_tag, 0) busseg = busdma.md_first_seg(dmamem, busdma.MD_BUS_SPACE) cpuseg = busdma.md_first_seg(dmamem, busdma.MD_VIRT_SPACE) busaddr = busdma.seg_get_addr(busseg) cpuaddr = busdma.seg_get_addr(cpuseg) logging.debug("DMA memory: CPU address: %#x, device address: %#x" % (cpuaddr, busaddr)) addr_initblock = cpuaddr addr_rxdesc = addr_initblock + ctypes.sizeof(initblock) addr_txdesc = addr_rxdesc + ctypes.sizeof(bufdesc) * nrxbufs addr_rxbufs = addr_txdesc + ctypes.sizeof(bufdesc) * ntxbufs addr_txbufs = addr_rxbufs + bufsize * nrxbufs ib = initblock.from_address(addr_initblock) ib.mode = ((ffs(ntxbufs) - 1) << 28) | ((ffs(nrxbufs) - 1) << 20) -for i in xrange(len(mac)): +for i in range(len(mac)): ib.hwaddr[i] = mac[i] -for i in xrange(4): +for i in range(4): ib.filter[i] = 0xffff ib.rxdesc = busaddr + (addr_rxdesc - cpuaddr) ib.txdesc = busaddr + (addr_txdesc - cpuaddr) ib._pad1_ = 0 ib._pad2_ = 0 -for i in xrange(nrxbufs): +for i in range(nrxbufs): bd = bufdesc.from_address(addr_rxdesc + ctypes.sizeof(bufdesc) * i) bd.buffer = busaddr + (addr_rxbufs - cpuaddr) + bufsize * i bd.flags = (1 << 31) | (15 << 12) | (-bufsize & 0xfff) bd.length = 0 bd._pad_ = 0 -for i in xrange(ntxbufs): +for i in range(ntxbufs): bd = bufdesc.from_address(addr_txdesc + ctypes.sizeof(bufdesc) * i) bd.buffer = busaddr + (addr_txbufs - cpuaddr) + bufsize * i bd.flags = (15 << 12) bd.length = 0 bd._pad_ = 0 busdma.sync_range(dmamem, busdma.SYNC_PREWRITE, 0, addr_rxbufs - cpuaddr) # Program address of DMA memory wrcsr(1, busaddr) wrcsr(2, busaddr >> 16) delay(100) # Initialize hardware wrcsr(0, 1) logging.debug('Waiting for initialization to complete') csr = rdcsr(0) while (csr & 0x100) == 0: logging.debug('CSR=%#x' % (csr)) csr = rdcsr(0) start() pkt = packet.from_address(addr_txbufs) ctypes.memset(addr_txbufs, 0, ctypes.sizeof(pkt)) options = [53, 1, 1] -for i in xrange(len(options)): +for i in range(len(options)): pkt.dhcp_options[i] = options[i] pkt.dhcp_magic = 0x63825363 -for i in xrange(6): +for i in range(6): pkt.bootp_chaddr[i] = mac[i] pkt.bootp_hlen = 6 pkt.bootp_htype = 1 pkt.bootp_op = 1 pkt.udp_len = ctypes.sizeof(pkt) - 34 pkt.udp_dest = 67 pkt.udp_src = 68 pkt.ip_dest = 0xffffffff pkt.ip_cksum = 0x79a6 pkt.ip_proto = 17 pkt.ip_ttl = 64 pkt.ip_len = ctypes.sizeof(pkt) - 14 pkt.ip_vl = 0x45 pkt.eth_type = 0x0800 -for i in xrange(6): +for i in range(6): pkt.eth_src[i] = mac[i] pkt.eth_dest[i] = bcast[i] pktlen = ctypes.sizeof(pkt) busdma.sync_range(dmamem, busdma.SYNC_PREWRITE, addr_txbufs - cpuaddr, bufsize) bd = bufdesc.from_address(addr_txdesc) bd.length = 0 bd.flags = (1 << 31) | (1 << 25) | (1 << 24) | (0xf << 12) | (-pktlen & 0xfff) busdma.sync_range(dmamem, busdma.SYNC_PREWRITE, addr_txdesc - cpuaddr, ctypes.sizeof(bufdesc)) wrcsr(0, 0x48) logging.info('DHCP discovery packet sent') # Now wait 2 seconds for a DHCP offer to be received. logging.debug('Waiting 2 seconds for an offer to be received') time.sleep(2) stop() busdma.sync_range(dmamem, busdma.SYNC_PREWRITE, addr_rxdesc - cpuaddr, ctypes.sizeof(bufdesc) * nrxbufs) -for i in xrange(nrxbufs): +for i in range(nrxbufs): bd = bufdesc.from_address(addr_rxdesc + ctypes.sizeof(bufdesc) * i) if (bd.flags & 0x80000000): continue pkt = packet.from_address(addr_rxbufs + i * bufsize) if mac_is(pkt.eth_dest, bcast): logging.debug('RX #%d: broadcast packet: length %u' % (i, bd.length)) continue if not mac_is(pkt.eth_dest, mac): logging.debug('RX #%d: packet for %s?' % (i, mac_str(pkt.eth_dest))) continue logging.debug('RX %d: packet from %s!' % (i, mac_str(pkt.eth_src))) logging.info('Our IP address = %s' % (ip_str(pkt.ip_dest))) busdma.mem_free(dmamem) busdma.tag_destroy(mem_tag) bus.unmap(io)