13#include <boost/bind/bind.hpp>
14#include <boost/shared_ptr.hpp>
29 :
NumericAddressedBackend(mapFileName), _deviceID(0), _ioctlPhysicalSlot(0), _ioctlDriverVersion(0), _ioctlDMA(0),
30 _deviceNodeName(
std::move(deviceNodeName)) {}
38 std::cout <<
"open pcie dev" << std::endl;
41 if(checkConnection())
return;
44 _deviceID =
::open(_deviceNodeName.c_str(), O_RDWR);
49 determineDriverAndConfigureIoctl();
54 void PcieBackend::determineDriverAndConfigureIoctl() {
63 _readDMAFunction = [&](uint8_t bar, uint32_t address, int32_t* data,
size_t sizeInBytes) {
64 PcieBackend::readDMAViaIoctl(bar, address, data, sizeInBytes);
66 _writeFunction = [&](uint8_t bar, uint32_t address, int32_t
const* data,
size_t sizeInBytes) {
67 writeWithStruct(bar, address, data, sizeInBytes);
69 _readFunction = [&](uint8_t bar, uint32_t address, int32_t* data,
size_t sizeInBytes) {
70 readWithStruct(bar, address, data, sizeInBytes);
80 _readDMAFunction = [&](uint8_t bar, uint32_t address, int32_t* data,
size_t sizeInBytes) {
81 PcieBackend::readDMAViaStruct(bar, address, data, sizeInBytes);
83 _writeFunction = [&](uint8_t bar, uint32_t address, int32_t
const* data,
size_t sizeInBytes) {
84 writeWithStruct(bar, address, data, sizeInBytes);
86 _readFunction = [&](uint8_t bar, uint32_t address, int32_t* data,
size_t sizeInBytes) {
87 readWithStruct(bar, address, data, sizeInBytes);
97 _readDMAFunction = [&](uint8_t bar, uint32_t address, int32_t* data,
size_t sizeInBytes) {
98 PcieBackend::readDMAViaIoctl(bar, address, data, sizeInBytes);
100 _writeFunction = [&](uint8_t bar, uint32_t address, int32_t
const* data,
size_t sizeInBytes) {
101 directWrite(bar, address, data, sizeInBytes);
103 _readFunction = [&](uint8_t bar, uint32_t address, int32_t* data,
size_t sizeInBytes) {
104 directRead(bar, address, data, sizeInBytes);
110 std::cerr <<
"Unsupported driver. " << createErrorStringWithErrnoText(
"Error is ") << std::endl;
122 bool PcieBackend::checkConnection()
const {
138 void PcieBackend::readInternal(uint8_t bar, uint32_t address, int32_t* data) {
151 *data =
static_cast<int32_t
>(l_RW.
data_rw);
154 void PcieBackend::directRead(uint8_t bar, uint32_t address, int32_t* data,
size_t sizeInBytes) {
157 loff_t virtualOffset = PCIEUNI_BAR_OFFSETS[bar] + address;
159 if(pread(_deviceID, data, sizeInBytes, virtualOffset) !=
static_cast<int>(sizeInBytes)) {
164 void PcieBackend::writeInternal(uint8_t bar, uint32_t address, int32_t
const* data) {
180 void PcieBackend::directWrite(uint8_t bar, uint32_t address, int32_t
const* data,
size_t sizeInBytes) {
183 loff_t virtualOffset = PCIEUNI_BAR_OFFSETS[bar] + address;
185 if(pwrite(_deviceID, data, sizeInBytes, virtualOffset) !=
static_cast<int>(sizeInBytes)) {
190 void PcieBackend::readWithStruct(uint8_t bar, uint32_t address, int32_t* data,
size_t sizeInBytes) {
192 assert(sizeInBytes % 4 == 0);
193 for(uint32_t i = 0; i < sizeInBytes / 4; i++) {
194 readInternal(bar, address + i * 4, data + i);
202 _readFunction(bar, address, data, sizeInBytes);
205 _readDMAFunction(bar, address, data, sizeInBytes);
209 void PcieBackend::writeWithStruct(uint8_t bar, uint32_t address, int32_t
const* data,
size_t sizeInBytes) {
211 assert(sizeInBytes % 4 == 0);
212 for(uint32_t i = 0; i < sizeInBytes / 4; i++) {
213 writeInternal(bar, address + i * 4, (data + i));
220 _writeFunction(bar, address, data, sizeInBytes);
223 void PcieBackend::readDMAViaStruct(uint8_t , uint32_t address, int32_t* data,
size_t sizeInBytes) {
236 pl_RW =
reinterpret_cast<device_rw*
>(data);
247 if(ret != (ssize_t)sizeInBytes) {
251 memcpy(data, pl_RW, sizeInBytes);
255 void PcieBackend::readDMAViaIoctl(uint8_t , uint32_t address, int32_t* data,
size_t sizeInBytes) {
271 int ret = ioctl(_deviceID, _ioctlDMA, (
void*)data);
278 int ret = ioctl(_deviceID, _ioctlDMA, (
void*)&DMA_RW);
282 memcpy(&DMA_RW, (
void*)data, sizeInBytes);
288 std::ostringstream os;
290 if(ioctl(_deviceID, _ioctlPhysicalSlot, &ioctlData) < 0) {
293 os <<
"SLOT: " << ioctlData.
data;
294 if(ioctl(_deviceID, _ioctlDriverVersion, &ioctlData) < 0) {
298 os <<
" DRV VER: " << ioctlData.
data <<
"." << ioctlData.
offset;
302 std::string PcieBackend::createErrorStringWithErrnoText(std::string
const& startText) {
303 char errorBuffer[255];
304 return startText + _deviceNodeName +
": " + strerror_r(errno, errorBuffer,
sizeof(errorBuffer));
310 std::string address, std::map<std::string, std::string> parameters) {
311 if(address.empty()) {
315 return boost::shared_ptr<DeviceBackend>(
new PcieBackend(
"/dev/" + address, parameters[
"map"]));
void setOpenedAndClearException() noexcept
Backends should call this function at the end of a (successful) open() call.
void checkActiveException() final
Function to be called by backends when needing to check for an active exception.
std::atomic< bool > _opened
flag if backend is opened
Base class for address-based device backends (e.g.
void close() final
Deactivates all asynchronous accessors and calls closeImpl().
A class to provide the Pcie device functionality.
static boost::shared_ptr< DeviceBackend > createInstance(std::string address, std::map< std::string, std::string > parameters)
void read(uint8_t bar, uint32_t address, int32_t *data, size_t sizeInBytes) override
Deprecated read function using 32bit address for backwards compatibility.
PcieBackend(std::string deviceNodeName, const std::string &mapFileName="")
constructor called through createInstance to create device object
void write(uint8_t bar, uint32_t address, int32_t const *data, size_t sizeInBytes) override
Deprecated write function using 32bit address for backwards compatibility.
void open() override
Open the device.
std::string readDeviceInfo() override
Return a device information string containing hardware details like the firmware version number or th...
void closeImpl() override
All backends derrived from NumericAddressedBackend must implement closeImpl() instead of close.
Exception thrown when a logic error has occured.
Exception thrown when a runtime error has occured.
#define LLRFDRV_DRIVER_VERSION
#define LLRFDRV_PHYSICAL_SLOT
#define PCIEDEV_PHYSICAL_SLOT
#define PCIEDEV_DRIVER_VERSION
#define PCIEUNI_DRIVER_VERSION
#define PCIEUNI_PHYSICAL_SLOT
unsigned int dma_reserved2
unsigned int dma_reserved1