diff options
author | Martin Braun <martin.braun@ettus.com> | 2017-11-29 17:39:21 -0800 |
---|---|---|
committer | Martin Braun <martin.braun@ettus.com> | 2017-12-22 15:05:58 -0800 |
commit | 3cff6298cea5f3699aa5db5921cd6933f557a034 (patch) | |
tree | 10f95a3ec0083b87d76449f2e416bd4b5753ae78 /mpm/lib | |
parent | cb6d78d9e8d4ebda3e31b15868e509711816bfaa (diff) | |
download | uhd-3cff6298cea5f3699aa5db5921cd6933f557a034.tar.gz uhd-3cff6298cea5f3699aa5db5921cd6933f557a034.tar.bz2 uhd-3cff6298cea5f3699aa5db5921cd6933f557a034.zip |
mpm: Add mmap_regs_iface
This is a C++-based peek/poke interface into mmaped objects. Useful for
better control over UIO devices.
Reviewed-By: Brent Stapleton <brent.stapleton@ettus.com>
Diffstat (limited to 'mpm/lib')
-rw-r--r-- | mpm/lib/types/CMakeLists.txt | 1 | ||||
-rw-r--r-- | mpm/lib/types/mmap_regs_iface.cpp | 117 |
2 files changed, 118 insertions, 0 deletions
diff --git a/mpm/lib/types/CMakeLists.txt b/mpm/lib/types/CMakeLists.txt index 10ce8a28c..029dddc85 100644 --- a/mpm/lib/types/CMakeLists.txt +++ b/mpm/lib/types/CMakeLists.txt @@ -1,6 +1,7 @@ SET(TYPES_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/lockable.cpp ${CMAKE_CURRENT_SOURCE_DIR}/log_buf.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/mmap_regs_iface.cpp ) USRP_PERIPHS_ADD_OBJECT(types ${TYPES_SOURCES}) diff --git a/mpm/lib/types/mmap_regs_iface.cpp b/mpm/lib/types/mmap_regs_iface.cpp new file mode 100644 index 000000000..3af47a61a --- /dev/null +++ b/mpm/lib/types/mmap_regs_iface.cpp @@ -0,0 +1,117 @@ +// +// Copyright 2017 Ettus Research, National Instruments Company +// +// SPDX-License-Identifier: GPL-3.0 +// + +#include <mpm/types/mmap_regs_iface.hpp> +#include <mpm/exception.hpp> +#include <boost/format.hpp> +#include <iostream> +#include <sys/types.h> +#include <sys/stat.h> +#include <sys/mman.h> +#include <unistd.h> +#include <fcntl.h> +#include <sstream> + +using namespace mpm::types; + + +mmap_regs_iface::mmap_regs_iface( + const std::string &path, + const size_t length, + const size_t offset, + const bool read_only, + const bool open_now +) : _path(path) + , _length(length) + , _offset(offset) + , _read_only(read_only) +{ + if (open_now) { + open(); + } +} + +mmap_regs_iface::~mmap_regs_iface() +{ + try { + close(); + } catch (...) { + // This is not good + } +} + +void mmap_regs_iface::open() +{ + if (_fd < 0) { + _fd = ::open(_path.c_str(), _read_only ? O_RDONLY : O_RDWR); + if (_fd < 0) { + throw mpm::runtime_error("Could not open file descriptor!"); + } + } + + if (!_mmap) { + _mmap = (uint32_t *) ::mmap( + NULL, + _length, + PROT_READ | (_read_only ? 0 : PROT_WRITE), + MAP_SHARED, + _fd, + (off_t) _offset + ); + if (((void *) _mmap) == MAP_FAILED) { + throw mpm::runtime_error("Failed to mmap!"); + } + } + log(mpm::types::log_level_t::TRACE, _path, + "Opened mmap_regs_iface"); +} + +void mmap_regs_iface::close() +{ + if (_mmap) { + int err = munmap((void *) _mmap, _length); + if (err) { + throw mpm::runtime_error("Couldn't munmap!"); + } + _mmap = NULL; + } + + if (_fd >= 0) { + if (::close(_fd)) { + throw mpm::runtime_error("Couldn't close file descriptor!"); + } + _fd = -1; + } + log(mpm::types::log_level_t::TRACE, _path, + "Closed mmap_regs_iface"); +} + +void mmap_regs_iface::poke32( + const uint32_t addr, + const uint32_t data +) { + MPM_ASSERT_THROW(_mmap); + _mmap[addr / sizeof(uint32_t)] = data; +} + +uint32_t mmap_regs_iface::peek32(const uint32_t addr) +{ + MPM_ASSERT_THROW(_mmap); + return _mmap[addr / sizeof(uint32_t)]; +} + +void mmap_regs_iface::log( + mpm::types::log_level_t level, + const std::string path, + const char *comment +) { + mpm::types::log_buf::make_singleton()->post( + level, + "MMAP_REGS_IFACE", + str(boost::format("[UIO %s] %s") + % path % comment) + ); +} |