aboutsummaryrefslogtreecommitdiffstats
path: root/mpm/lib
diff options
context:
space:
mode:
authorMartin Braun <martin.braun@ettus.com>2017-11-29 17:39:21 -0800
committerMartin Braun <martin.braun@ettus.com>2017-12-22 15:05:58 -0800
commit3cff6298cea5f3699aa5db5921cd6933f557a034 (patch)
tree10f95a3ec0083b87d76449f2e416bd4b5753ae78 /mpm/lib
parentcb6d78d9e8d4ebda3e31b15868e509711816bfaa (diff)
downloaduhd-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.txt1
-rw-r--r--mpm/lib/types/mmap_regs_iface.cpp117
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)
+ );
+}