ChimeraTK-DeviceAccess  03.18.00
CtrlIntf.cc
Go to the documentation of this file.
1 // SPDX-FileCopyrightText: Deutsches Elektronen-Synchrotron DESY, MSK, ChimeraTK Project <chimeratk-support@desy.de>
2 // SPDX-License-Identifier: LGPL-3.0-or-later
3 
4 #include "CtrlIntf.h"
5 
6 #include "DeviceFile.h"
7 #include "Exception.h"
8 #include <sys/mman.h>
9 
10 #include <cstring>
11 #include <fcntl.h>
12 #include <iostream>
13 #include <sstream>
14 
15 namespace ChimeraTK {
16 
17  CtrlIntf::CtrlIntf(const std::string& devicePath) : _file(devicePath + "/user", O_RDWR) {
18  for(_mmapSize = _mmapSizeMax; _mmapSize >= _mmapSizeMin; _mmapSize /= 2) {
19  _mem = ::mmap(NULL, _mmapSize, PROT_READ | PROT_WRITE, MAP_SHARED, _file, 0);
20  if(_mem != reinterpret_cast<void*>(-1)) {
21  // Successfully mapped the BAR
22 #ifdef _DEBUG
23  std::cout << "XDMA: mapped " << _mmapSize << " bytes" << std::endl;
24 #endif
25  return;
26  }
27  }
28  char mmap_err[100];
29  std::stringstream err_msg;
30  err_msg << "XDMA: couldn't mmap the minimum size of " << _mmapSizeMin
31  << " bytes: " << strerror_r(errno, mmap_err, sizeof(mmap_err));
32  throw ChimeraTK::runtime_error(err_msg.str());
33  }
34 
36  ::munmap(_mem, _mmapSize);
37  }
38 
39  volatile int32_t* CtrlIntf::_reg_ptr(uintptr_t offs) const {
40  return static_cast<volatile int32_t*>(_mem) + offs / 4;
41  }
42 
43  void CtrlIntf::_check_range(const std::string access_type, uintptr_t address, size_t nBytes) const {
44  if((address + nBytes) <= _mmapSize) {
45  return;
46  }
47  std::stringstream err_msg;
48  err_msg << "XDMA: attempt to " << access_type << " beyond mapped area: " << nBytes << " bytes at 0x" << std::hex
49  << address << std::dec << " (" << _mmapSize << " bytes mapped)";
50  throw ChimeraTK::runtime_error(err_msg.str());
51  }
52 
53  void CtrlIntf::read(uintptr_t address, int32_t* __restrict__ buf, size_t nBytes) {
54  _check_range("read", address, nBytes);
55  volatile int32_t* rptr = _reg_ptr(address);
56  while(nBytes >= sizeof(int32_t)) {
57  *buf++ = *rptr++;
58  nBytes -= sizeof(int32_t);
59  }
60  // with mmap, device error is not automatically noticed, so add explicit check here
61  if(!_file.goodState()) {
62  throw runtime_error("read from bad device node " + _file.name());
63  }
64  }
65 
66  void CtrlIntf::write(uintptr_t address, const int32_t* data, size_t nBytes) {
67  _check_range("write", address, nBytes);
68  volatile int32_t* __restrict__ wptr = _reg_ptr(address);
69  while(nBytes >= sizeof(int32_t)) {
70  *wptr++ = *data++;
71  nBytes -= sizeof(int32_t);
72  }
73  if(!_file.goodState()) {
74  throw runtime_error("write to bad device node " + _file.name());
75  }
76  }
77 
78 } // namespace ChimeraTK
DeviceFile.h
ChimeraTK::DeviceFile::goodState
bool goodState() const
Definition: DeviceFile.cc:50
ChimeraTK::DeviceFile::name
std::string name() const
Definition: DeviceFile.cc:46
ChimeraTK::CtrlIntf::write
void write(uintptr_t address, const int32_t *data, size_t nBytes) override
Definition: CtrlIntf.cc:66
ChimeraTK::runtime_error
Exception thrown when a runtime error has occured.
Definition: Exception.h:18
ChimeraTK::CtrlIntf::read
void read(uintptr_t address, int32_t *__restrict__ buf, size_t nBytes) override
Definition: CtrlIntf.cc:53
CtrlIntf.h
ChimeraTK::CtrlIntf::~CtrlIntf
virtual ~CtrlIntf()
Definition: CtrlIntf.cc:35
ChimeraTK::CtrlIntf::CtrlIntf
CtrlIntf()=delete
Exception.h
ChimeraTK
Definition: DummyBackend.h:16