10 #include <sys/ioctl.h>
12 #include <boost/bind/bind.hpp>
13 #include <boost/shared_ptr.hpp>
27 :
NumericAddressedBackend(mapFileName), _deviceID(0), _ioctlPhysicalSlot(0), _ioctlDriverVersion(0), _ioctlDMA(0),
28 _deviceNodeName(std::move(deviceNodeName)) {}
36 std::cout <<
"open pcie dev" << std::endl;
39 if(checkConnection())
return;
42 _deviceID =
::open(_deviceNodeName.c_str(), O_RDWR);
47 determineDriverAndConfigureIoctl();
52 void PcieBackend::determineDriverAndConfigureIoctl() {
61 _readDMAFunction = [&](uint8_t bar, uint32_t address, int32_t* data,
size_t sizeInBytes) {
62 PcieBackend::readDMAViaIoctl(bar, address, data, sizeInBytes);
64 _writeFunction = [&](uint8_t bar, uint32_t address, int32_t
const* data,
size_t sizeInBytes) {
65 writeWithStruct(bar, address, data, sizeInBytes);
67 _readFunction = [&](uint8_t bar, uint32_t address, int32_t* data,
size_t sizeInBytes) {
68 readWithStruct(bar, address, data, sizeInBytes);
78 _readDMAFunction = [&](uint8_t bar, uint32_t address, int32_t* data,
size_t sizeInBytes) {
79 PcieBackend::readDMAViaStruct(bar, address, data, sizeInBytes);
81 _writeFunction = [&](uint8_t bar, uint32_t address, int32_t
const* data,
size_t sizeInBytes) {
82 writeWithStruct(bar, address, data, sizeInBytes);
84 _readFunction = [&](uint8_t bar, uint32_t address, int32_t* data,
size_t sizeInBytes) {
85 readWithStruct(bar, address, data, sizeInBytes);
95 _readDMAFunction = [&](uint8_t bar, uint32_t address, int32_t* data,
size_t sizeInBytes) {
96 PcieBackend::readDMAViaIoctl(bar, address, data, sizeInBytes);
98 _writeFunction = [&](uint8_t bar, uint32_t address, int32_t
const* data,
size_t sizeInBytes) {
99 directWrite(bar, address, data, sizeInBytes);
101 _readFunction = [&](uint8_t bar, uint32_t address, int32_t* data,
size_t sizeInBytes) {
102 directRead(bar, address, data, sizeInBytes);
108 std::cerr <<
"Unsupported driver. " << createErrorStringWithErrnoText(
"Error is ") << std::endl;
120 bool PcieBackend::checkConnection()
const {
136 void PcieBackend::readInternal(uint8_t bar, uint32_t address, int32_t* data) {
149 *data =
static_cast<int32_t
>(l_RW.
data_rw);
152 void PcieBackend::directRead(uint8_t bar, uint32_t address, int32_t* data,
size_t sizeInBytes) {
155 loff_t virtualOffset = PCIEUNI_BAR_OFFSETS[bar] + address;
157 if(pread(_deviceID, data, sizeInBytes, virtualOffset) !=
static_cast<int>(sizeInBytes)) {
162 void PcieBackend::writeInternal(uint8_t bar, uint32_t address, int32_t
const* data) {
178 void PcieBackend::directWrite(uint8_t bar, uint32_t address, int32_t
const* data,
size_t sizeInBytes) {
181 loff_t virtualOffset = PCIEUNI_BAR_OFFSETS[bar] + address;
183 if(pwrite(_deviceID, data, sizeInBytes, virtualOffset) !=
static_cast<int>(sizeInBytes)) {
188 void PcieBackend::readWithStruct(uint8_t bar, uint32_t address, int32_t* data,
size_t sizeInBytes) {
190 assert(sizeInBytes % 4 == 0);
191 for(uint32_t i = 0; i < sizeInBytes / 4; i++) {
192 readInternal(bar, address + i * 4, data + i);
200 _readFunction(bar, address, data, sizeInBytes);
203 _readDMAFunction(bar, address, data, sizeInBytes);
207 void PcieBackend::writeWithStruct(uint8_t bar, uint32_t address, int32_t
const* data,
size_t sizeInBytes) {
209 assert(sizeInBytes % 4 == 0);
210 for(uint32_t i = 0; i < sizeInBytes / 4; i++) {
211 writeInternal(bar, address + i * 4, (data + i));
218 _writeFunction(bar, address, data, sizeInBytes);
221 void PcieBackend::readDMAViaStruct(uint8_t , uint32_t address, int32_t* data,
size_t sizeInBytes) {
234 pl_RW =
reinterpret_cast<device_rw*
>(data);
245 if(ret != (ssize_t)sizeInBytes) {
249 memcpy(data, pl_RW, sizeInBytes);
253 void PcieBackend::readDMAViaIoctl(uint8_t , uint32_t address, int32_t* data,
size_t sizeInBytes) {
269 int ret = ioctl(_deviceID, _ioctlDMA, (
void*)data);
276 int ret = ioctl(_deviceID, _ioctlDMA, (
void*)&DMA_RW);
280 memcpy(&DMA_RW, (
void*)data, sizeInBytes);
286 std::ostringstream os;
288 if(ioctl(_deviceID, _ioctlPhysicalSlot, &ioctlData) < 0) {
291 os <<
"SLOT: " << ioctlData.
data;
292 if(ioctl(_deviceID, _ioctlDriverVersion, &ioctlData) < 0) {
296 os <<
" DRV VER: " << ioctlData.
data <<
"." << ioctlData.
offset;
300 std::string PcieBackend::createErrorStringWithErrnoText(std::string
const& startText) {
301 char errorBuffer[255];
302 return startText + _deviceNodeName +
": " + strerror_r(errno, errorBuffer,
sizeof(errorBuffer));
308 std::string address, std::map<std::string, std::string> parameters) {
309 if(address.empty()) {
313 return boost::shared_ptr<DeviceBackend>(
new PcieBackend(
"/dev/" + address, parameters[
"map"]));