26 std::string UioAccess::lookupUioDevFromDtNode(
const std::string dtNodeNname) {
27 std::string path =
"/sys/class/uio/";
28 for(
const auto& entry :
std::filesystem::directory_iterator(path)) {
29 std::ifstream ifs{entry.path() /
"name"};
34 std::string currentName;
36 if(currentName == dtNodeNname) {
37 return entry.path().filename();
44 if(std::filesystem::is_symlink(_deviceFilePath)) {
45 _deviceFilePath = std::filesystem::canonical(_deviceFilePath);
47 std::string fileName = _deviceFilePath.filename().string();
48 std::string resolvedUioDev = lookupUioDevFromDtNode(fileName);
49 if(!resolvedUioDev.empty()) {
50 fileName = resolvedUioDev;
51 _deviceFilePath =
"/dev/" + fileName;
54 _deviceKernelBase = (
void*)readUint64HexFromFile(
"/sys/class/uio/" + fileName +
"/maps/map0/addr");
55 _deviceMemSize = readUint64HexFromFile(
"/sys/class/uio/" + fileName +
"/maps/map0/size");
56 _lastInterruptCount = readUint32FromFile(
"/sys/class/uio/" + fileName +
"/event");
59 _deviceFileDescriptor =
::open(_deviceFilePath.c_str(), O_RDWR);
60 if(_deviceFileDescriptor < 0) {
75 void UioAccess::read(uint64_t map, uint64_t address, int32_t* __restrict__ data,
size_t sizeInBytes) {
81 address = address %
reinterpret_cast<uint64_t
>(_deviceKernelBase);
83 if(address + sizeInBytes > _deviceMemSize) {
87 volatile int32_t* rptr =
static_cast<volatile int32_t*
>(_deviceUserBase) + address /
sizeof(int32_t);
88 while(sizeInBytes >=
sizeof(int32_t)) {
89 *(data++) = *(rptr++);
90 sizeInBytes -=
sizeof(int32_t);
94 void UioAccess::write(uint64_t map, uint64_t address, int32_t
const* data,
size_t sizeInBytes) {
100 address = address %
reinterpret_cast<uint64_t
>(_deviceKernelBase);
102 if(address + sizeInBytes > _deviceMemSize) {
106 volatile int32_t* __restrict__ wptr =
static_cast<volatile int32_t*
>(_deviceUserBase) + address /
sizeof(int32_t);
107 while(sizeInBytes >=
sizeof(int32_t)) {
108 *(wptr++) = *(data++);
109 sizeInBytes -=
sizeof(int32_t);
115 uint32_t totalInterruptCount = 0;
117 uint32_t occurredInterruptCount = 0;
120 pfd.fd = _deviceFileDescriptor;
123 int ret = poll(&pfd, 1, timeoutMs);
127 ret =
::read(_deviceFileDescriptor, &totalInterruptCount,
sizeof(totalInterruptCount));
129 if(ret != (ssize_t)
sizeof(totalInterruptCount)) {
134 occurredInterruptCount = subtractUint32OverflowSafe(totalInterruptCount, _lastInterruptCount);
135 _lastInterruptCount = totalInterruptCount;
139 occurredInterruptCount = 0;
144 return occurredInterruptCount;
149 ssize_t ret =
::write(_deviceFileDescriptor, &unmask,
sizeof(unmask));
151 if(ret != (ssize_t)
sizeof(unmask)) {
157 return _deviceFilePath.string();
160 void UioAccess::UioMMap() {
161 _deviceUserBase = mmap(NULL, _deviceMemSize, PROT_READ | PROT_WRITE, MAP_SHARED, _deviceFileDescriptor, 0);
162 if(_deviceUserBase == MAP_FAILED) {
163 ::close(_deviceFileDescriptor);
169 void UioAccess::UioUnmap() {
170 munmap(_deviceUserBase, _deviceMemSize);
173 uint32_t UioAccess::subtractUint32OverflowSafe(uint32_t minuend, uint32_t subtrahend) {
174 if(subtrahend > minuend) {
176 (uint32_t)(
static_cast<uint64_t
>(std::numeric_limits<uint32_t>::max()) -
static_cast<uint64_t
>(subtrahend));
179 return minuend - subtrahend;
183 uint32_t UioAccess::readUint32FromFile(std::string fileName) {
185 std::ifstream inputFile(fileName);
187 if(inputFile.is_open()) {
191 return (uint32_t)value;
194 uint64_t UioAccess::readUint64HexFromFile(std::string fileName) {
196 std::ifstream inputFile(fileName);
198 if(inputFile.is_open()) {
199 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.