27 std::string UioAccess::lookupUioDevFromDtNode(
const std::string dtNodeNname) {
28 std::string path =
"/sys/class/uio/";
29 for(
const auto& entry :
std::filesystem::directory_iterator(path)) {
30 std::ifstream ifs{entry.path() /
"name"};
35 std::string currentName;
37 if(currentName == dtNodeNname) {
38 return entry.path().filename();
45 if(std::filesystem::is_symlink(_deviceFilePath)) {
46 _deviceFilePath = std::filesystem::canonical(_deviceFilePath);
48 std::string fileName = _deviceFilePath.filename().string();
49 std::string resolvedUioDev = lookupUioDevFromDtNode(fileName);
50 if(!resolvedUioDev.empty()) {
51 fileName = resolvedUioDev;
52 _deviceFilePath =
"/dev/" + fileName;
55 _deviceKernelBase = (
void*)readUint64HexFromFile(
"/sys/class/uio/" + fileName +
"/maps/map0/addr");
56 _deviceMemSize = readUint64HexFromFile(
"/sys/class/uio/" + fileName +
"/maps/map0/size");
57 _lastInterruptCount = readUint32FromFile(
"/sys/class/uio/" + fileName +
"/event");
60 _deviceFileDescriptor =
::open(_deviceFilePath.c_str(), O_RDWR);
61 if(_deviceFileDescriptor < 0) {
76 void UioAccess::read(uint64_t map, uint64_t address, int32_t* __restrict__ data,
size_t sizeInBytes) {
82 address = address %
reinterpret_cast<uint64_t
>(_deviceKernelBase);
84 if(address + sizeInBytes > _deviceMemSize) {
88 volatile int32_t* rptr =
static_cast<volatile int32_t*
>(_deviceUserBase) + address /
sizeof(int32_t);
89 while(sizeInBytes >=
sizeof(int32_t)) {
90 *(data++) = *(rptr++);
91 sizeInBytes -=
sizeof(int32_t);
95 void UioAccess::write(uint64_t map, uint64_t address, int32_t
const* data,
size_t sizeInBytes) {
101 address = address %
reinterpret_cast<uint64_t
>(_deviceKernelBase);
103 if(address + sizeInBytes > _deviceMemSize) {
107 volatile int32_t* __restrict__ wptr =
static_cast<volatile int32_t*
>(_deviceUserBase) + address /
sizeof(int32_t);
108 while(sizeInBytes >=
sizeof(int32_t)) {
109 *(wptr++) = *(data++);
110 sizeInBytes -=
sizeof(int32_t);
116 uint32_t totalInterruptCount = 0;
118 uint32_t occurredInterruptCount = 0;
121 pfd.fd = _deviceFileDescriptor;
124 int ret = poll(&pfd, 1, timeoutMs);
128 ret =
::read(_deviceFileDescriptor, &totalInterruptCount,
sizeof(totalInterruptCount));
130 if(ret != (ssize_t)
sizeof(totalInterruptCount)) {
135 occurredInterruptCount = subtractUint32OverflowSafe(totalInterruptCount, _lastInterruptCount);
136 _lastInterruptCount = totalInterruptCount;
140 occurredInterruptCount = 0;
145 return occurredInterruptCount;
150 ssize_t ret =
::write(_deviceFileDescriptor, &unmask,
sizeof(unmask));
152 if(ret != (ssize_t)
sizeof(unmask)) {
158 return _deviceFilePath.string();
161 void UioAccess::UioMMap() {
162 _deviceUserBase = mmap(NULL, _deviceMemSize, PROT_READ | PROT_WRITE, MAP_SHARED, _deviceFileDescriptor, 0);
163 if(_deviceUserBase == MAP_FAILED) {
164 ::close(_deviceFileDescriptor);
170 void UioAccess::UioUnmap() {
171 munmap(_deviceUserBase, _deviceMemSize);
174 uint32_t UioAccess::subtractUint32OverflowSafe(uint32_t minuend, uint32_t subtrahend) {
175 if(subtrahend > minuend) {
177 (uint32_t)(
static_cast<uint64_t
>(std::numeric_limits<uint32_t>::max()) -
static_cast<uint64_t
>(subtrahend));
180 return minuend - subtrahend;
184 uint32_t UioAccess::readUint32FromFile(std::string fileName) {
186 std::ifstream inputFile(fileName);
188 if(inputFile.is_open()) {
192 return (uint32_t)value;
195 uint64_t UioAccess::readUint64HexFromFile(std::string fileName) {
197 std::ifstream inputFile(fileName);
199 if(inputFile.is_open()) {
200 inputFile >> std::hex >> value;
void read(uint64_t map, uint64_t address, int32_t *data, size_t sizeInBytes)
Read data from the specified memory offset address.
void open()
Opens UIO device for read and write operations and interrupt handling.
std::string getDeviceFilePath()
Return UIO device file path.
uint32_t waitForInterrupt(int timeoutMs)
Wait for hardware interrupt to occur within specified timeout period.
void write(uint64_t map, uint64_t address, int32_t const *data, size_t sizeInBytes)
Write data to the specified memory offset address.
UioAccess(const std::string &deviceFilePath)
void clearInterrupts()
Clear all pending interrupts.
void close()
Closes UIO device.
Exception thrown when a logic error has occured.
Exception thrown when a runtime error has occured.