diff options
author | Martin Braun <martin.braun@ettus.com> | 2017-05-23 16:48:39 -0700 |
---|---|---|
committer | Martin Braun <martin.braun@ettus.com> | 2017-12-22 15:03:53 -0800 |
commit | 1ce038094d3b0d5021601533a3dbccbffa229574 (patch) | |
tree | dbd66444bc60f23dd34477fa6dc364783cbdb896 | |
parent | 0c0b0595bbbddf0eeb47bd55621b5822609bef93 (diff) | |
download | uhd-1ce038094d3b0d5021601533a3dbccbffa229574.tar.gz uhd-1ce038094d3b0d5021601533a3dbccbffa229574.tar.bz2 uhd-1ce038094d3b0d5021601533a3dbccbffa229574.zip |
mpm: Factored out eeprom code into its own module
-rw-r--r-- | mpm/python/usrp_mpm/CMakeLists.txt | 1 | ||||
-rw-r--r-- | mpm/python/usrp_mpm/eeprom.py | 143 | ||||
-rw-r--r-- | mpm/python/usrp_mpm/periph_manager/base.py | 135 |
3 files changed, 152 insertions, 127 deletions
diff --git a/mpm/python/usrp_mpm/CMakeLists.txt b/mpm/python/usrp_mpm/CMakeLists.txt index a08e3fea1..5c73fb5b0 100644 --- a/mpm/python/usrp_mpm/CMakeLists.txt +++ b/mpm/python/usrp_mpm/CMakeLists.txt @@ -23,6 +23,7 @@ SET(USRP_MPM_TOP_FILES ${CMAKE_CURRENT_SOURCE_DIR}/__init__.py ${CMAKE_CURRENT_SOURCE_DIR}/discovery.py ${CMAKE_CURRENT_SOURCE_DIR}/dtoverlay.py + ${CMAKE_CURRENT_SOURCE_DIR}/eeprom.py ${CMAKE_CURRENT_SOURCE_DIR}/mpmlog.py ${CMAKE_CURRENT_SOURCE_DIR}/nijesdcore.py ${CMAKE_CURRENT_SOURCE_DIR}/rpc_server.py diff --git a/mpm/python/usrp_mpm/eeprom.py b/mpm/python/usrp_mpm/eeprom.py new file mode 100644 index 000000000..67920e885 --- /dev/null +++ b/mpm/python/usrp_mpm/eeprom.py @@ -0,0 +1,143 @@ +# +# Copyright 2017 Ettus Research (National Instruments) +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +""" +EEPROM management code +""" + +import struct + +EEPROM_DEFAULT_HEADER = struct.Struct("!I I") + +class MboardEEPROM(object): + """ + Given a nvmem path, read out EEPROM values from the motherboard's EEPROM. + The format of data in the EEPROM must follow the following standard: + + - 4 bytes magic. This will always be the same value; checking this value is + a sanity check for if the read was successful. + - 4 bytes version. This is the version of the EEPROM format. + + The following bytes are version-dependent: + + Version 1: + + - 4x4 bytes mcu_flags -> throw them away + - 2 bytes hw_pid + - 2 bytes hw_rev (starting at 0) + - 8 bytes serial number (zero-terminated string of 7 characters) + - 6 bytes MAC address for eth0 + - 2 bytes padding + - 6 bytes MAC address for eth1 + - 2 bytes padding + - 6 bytes MAC address for eth2 + - 2 bytes padding + - 4 bytes CRC + + MAC addresses are ignored here; they are read elsewhere. If we really need + to know the MAC address of an interface, we can fish it out the raw data, + or ask the system. + """ + # Create one of these for every version of the EEPROM format: + eeprom_header_format = ( + None, # For laziness, we start at version 1 and thus index 0 stays empty + "!I I 16x H H 7s 25x I", # Version 1 + ) + eeprom_header_keys = ( + None, # For laziness, we start at version 1 and thus index 0 stays empty + ('magic', 'eeprom_version', 'pid', 'rev', 'serial', 'CRC'), # Version 1 + ) + +class DboardEEPROM(object): + """ + Given a nvmem path, read out EEPROM values from the daughterboard's EEPROM. + The format of data in the EEPROM must follow the following standard: + + - 4 bytes magic. This will always be the same value; checking this value is + a sanity check for if the read was successful. + - 4 bytes version. This is the version of the EEPROM format. + + The following bytes are version-dependent: + + Version 1: + + - 2 bytes hw_pid + - 2 bytes hw_rev (starting at 0) + - 8 bytes serial number (zero-terminated string of 7 characters) + - 4 bytes CRC + + MAC addresses are ignored here; they are read elsewhere. If we really need + to know the MAC address of an interface, we can fish it out the raw data, + or ask the system. + """ + # Create one of these for every version of the EEPROM format: + eeprom_header_format = ( + None, # For laziness, we start at version 1 and thus index 0 stays empty + "!I I H H 7s 1x I", # Version 1 + ) + eeprom_header_keys = ( + None, # For laziness, we start at version 1 and thus index 0 stays empty + ('magic', 'eeprom_version', 'pid', 'rev', 'serial', 'CRC'), # Version 1 + ) + + +def read_eeprom( + nvmem_path, + eeprom_header_format, + eeprom_header_keys, + expected_magic, + max_size=None +): + """ + Read the EEPROM located at nvmem_path and return a tuple (header, data) + Header is already parsed in the common header fields + Data contains the full eeprom data structure + + nvmem_path -- Path to readable file (typically something in sysfs) + eeprom_header_format -- List of header formats, by version + eeprom_header_keys -- List of keys for the entries in the EEPROM + expected_magic -- The magic value that is expected + max_size -- Max number of bytes to be read. If omitted, will read the full file. + """ + assert len(eeprom_header_format) == len(eeprom_header_keys) + def _parse_eeprom_data( + data, + version, + ): + """ + Parses the raw 'data' according to the version. + Returns a dictionary. + """ + eeprom_parser = struct.Struct(eeprom_header_format[version]) + eeprom_keys = eeprom_header_keys[version] + parsed_data = eeprom_parser.unpack_from(data) + return dict(zip(eeprom_keys, parsed_data)) + # Dawaj, dawaj + max_size = max_size or -1 + with open(nvmem_path, "rb") as nvmem_file: + data = nvmem_file.read(max_size) + eeprom_magic, eeprom_version = EEPROM_DEFAULT_HEADER.unpack_from(data) + if eeprom_magic != expected_magic: + raise RuntimeError( + "Received incorrect EEPROM magic. " \ + "Read: {:08X} Expected: {:08X}".format( + eeprom_magic, expected_magic + )) + if eeprom_version >= len(eeprom_header_format): + raise RuntimeError("Unexpected EEPROM version: `{}'".format(eeprom_version)) + return (_parse_eeprom_data(data, eeprom_version), data) + + diff --git a/mpm/python/usrp_mpm/periph_manager/base.py b/mpm/python/usrp_mpm/periph_manager/base.py index d7efb68b6..e52a75fcb 100644 --- a/mpm/python/usrp_mpm/periph_manager/base.py +++ b/mpm/python/usrp_mpm/periph_manager/base.py @@ -19,133 +19,13 @@ Mboard implementation base class """ import os -import struct from six import iteritems, itervalues from ..mpmlog import get_logger from .udev import get_eeprom_paths from .udev import get_spidev_nodes from usrp_mpm import net from usrp_mpm import dtoverlay - -EEPROM_DEFAULT_HEADER = struct.Struct("!I I") - -class MboardEEPROM(object): - """ - Given a nvmem path, read out EEPROM values from the motherboard's EEPROM. - The format of data in the EEPROM must follow the following standard: - - - 4 bytes magic. This will always be the same value; checking this value is - a sanity check for if the read was successful. - - 4 bytes version. This is the version of the EEPROM format. - - The following bytes are version-dependent: - - Version 1: - - - 4x4 bytes mcu_flags -> throw them away - - 2 bytes hw_pid - - 2 bytes hw_rev (starting at 0) - - 8 bytes serial number (zero-terminated string of 7 characters) - - 6 bytes MAC address for eth0 - - 2 bytes padding - - 6 bytes MAC address for eth1 - - 2 bytes padding - - 6 bytes MAC address for eth2 - - 2 bytes padding - - 4 bytes CRC - - MAC addresses are ignored here; they are read elsewhere. If we really need - to know the MAC address of an interface, we can fish it out the raw data, - or ask the system. - """ - # Create one of these for every version of the EEPROM format: - eeprom_header_format = ( - None, # For laziness, we start at version 1 and thus index 0 stays empty - "!I I 16x H H 7s 25x I", # Version 1 - ) - eeprom_header_keys = ( - None, # For laziness, we start at version 1 and thus index 0 stays empty - ('magic', 'eeprom_version', 'pid', 'rev', 'serial', 'CRC'), # Version 1 - ) - -class DboardEEPROM(object): - """ - Given a nvmem path, read out EEPROM values from the daughterboard's EEPROM. - The format of data in the EEPROM must follow the following standard: - - - 4 bytes magic. This will always be the same value; checking this value is - a sanity check for if the read was successful. - - 4 bytes version. This is the version of the EEPROM format. - - The following bytes are version-dependent: - - Version 1: - - - 2 bytes hw_pid - - 2 bytes hw_rev (starting at 0) - - 8 bytes serial number (zero-terminated string of 7 characters) - - 4 bytes CRC - - MAC addresses are ignored here; they are read elsewhere. If we really need - to know the MAC address of an interface, we can fish it out the raw data, - or ask the system. - """ - # Create one of these for every version of the EEPROM format: - eeprom_header_format = ( - None, # For laziness, we start at version 1 and thus index 0 stays empty - "!I I H H 7s 1x I", # Version 1 - ) - eeprom_header_keys = ( - None, # For laziness, we start at version 1 and thus index 0 stays empty - ('magic', 'eeprom_version', 'pid', 'rev', 'serial', 'CRC'), # Version 1 - ) - - -def read_eeprom( - nvmem_path, - eeprom_header_format, - eeprom_header_keys, - expected_magic, - max_size=None -): - """ - Read the EEPROM located at nvmem_path and return a tuple (header, data) - Header is already parsed in the common header fields - Data contains the full eeprom data structure - - nvmem_path -- Path to readable file (typically something in sysfs) - eeprom_header_format -- List of header formats, by version - eeprom_header_keys -- List of keys for the entries in the EEPROM - expected_magic -- The magic value that is expected - max_size -- Max number of bytes to be read. If omitted, will read the full file. - """ - assert len(eeprom_header_format) == len(eeprom_header_keys) - def _parse_eeprom_data( - data, - version, - ): - """ - Parses the raw 'data' according to the version. - Returns a dictionary. - """ - eeprom_parser = struct.Struct(eeprom_header_format[version]) - eeprom_keys = eeprom_header_keys[version] - parsed_data = eeprom_parser.unpack_from(data) - return dict(zip(eeprom_keys, parsed_data)) - # Dawaj, dawaj - max_size = max_size or -1 - with open(nvmem_path, "rb") as nvmem_file: - data = nvmem_file.read(max_size) - eeprom_magic, eeprom_version = EEPROM_DEFAULT_HEADER.unpack_from(data) - if eeprom_magic != expected_magic: - raise RuntimeError("Received incorrect EEPROM magic. " \ - "Read: {:08X} Expected: {:08X}".format( - eeprom_magic, expected_magic - )) - if eeprom_version >= len(eeprom_header_format): - raise RuntimeError("Unexpected EEPROM version: `{}'".format(eeprom_version)) - return (_parse_eeprom_data(data, eeprom_version), data) - +from usrp_mpm import eeprom def get_dboard_class_from_pid(pid): """ @@ -272,10 +152,10 @@ class PeriphManagerBase(object): """ if len(self.mboard_eeprom_addr): self.log.trace("Reading EEPROM from address `{}'...".format(self.mboard_eeprom_addr)) - (self._eeprom_head, self._eeprom_rawdata) = read_eeprom( + (self._eeprom_head, self._eeprom_rawdata) = eeprom.read_eeprom( get_eeprom_paths(self.mboard_eeprom_addr)[0], - MboardEEPROM.eeprom_header_format, - MboardEEPROM.eeprom_header_keys, + eeprom.MboardEEPROM.eeprom_header_format, + eeprom.MboardEEPROM.eeprom_header_keys, self.mboard_eeprom_magic, self.mboard_eeprom_max_len, ) @@ -299,6 +179,7 @@ class PeriphManagerBase(object): def _init_mboard_overlays(self, eeprom_md, device_args): """ + Load all required overlays for this motherboard """ requested_overlays = self.list_required_dt_overlays( eeprom_md, @@ -346,10 +227,10 @@ class PeriphManagerBase(object): self.dboards = [] for dboard_idx, dboard_eeprom_path in enumerate(dboard_eeprom_paths): self.log.debug("Initializing dboard {}...".format(dboard_idx)) - dboard_eeprom_md, dboard_eeprom_rawdata = read_eeprom( + dboard_eeprom_md, dboard_eeprom_rawdata = eeprom.read_eeprom( dboard_eeprom_path, - DboardEEPROM.eeprom_header_format, - DboardEEPROM.eeprom_header_keys, + eeprom.DboardEEPROM.eeprom_header_format, + eeprom.DboardEEPROM.eeprom_header_keys, self.dboard_eeprom_magic, self.dboard_eeprom_max_len, ) |