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