I am developing a PCIe driver for Altera (Intel) Avalon-MM FPGA. My OS is Windows 10 64bit and I am currently using Jungo’s Windriver framework. (hopefully it is not a mistake as indicated here)
The hardware maps 4096 bytes of its DDR memory to BAR2. I can successfully use Windriver API WDC_WriteAddr32 or WDC_WriteAddrBlock to write to this memory range.
My final goal is to be able to receive a physical pointer (bus address) to this mapped region, hand it to another device driver so it can perform DMA transfers directly to the FPGA DDR (by using AMD DirectGMA technology for instance).
As a preliminary stage, I am trying to work solely with user mode virtual addresses and simply write to the pointer I receive from Windriver API. Here is the code:
PWDC_DEVICE device = static_cast<PWDC_DEVICE>(_hWDCDevice); // _hWDCDevice is of type WDC_DEVICE_HANDLE
const WDC_ADDR_DESC& bar2AddressDescriptor = device->pAddrDesc[2];
static_assert(sizeof(UPTR) == sizeof(uint32_t*));
uint32_t* ptr = reinterpret_cast<uint32_t*>(bar2AddressDescriptor.pUserDirectMemAddr);
ptr[0] = 123; // this line causes the system to hang.
A different approach I tried is obtaining the virtual address from the WD_PCI_CARD_INFO structure:
WD_PCI_CARD_INFO deviceInfo{};
deviceInfo.pciSlot = slot;
WDC_CHECK(WDC_PciGetDeviceInfo(&deviceInfo));
WDC_CHECK(WDC_PciDeviceOpen(&_hWDCDevice, &deviceInfo, &_deviceContext));
for (auto i = 0u; i < deviceInfo.Card.dwItems; i++)
{
const auto& item = deviceInfo.Card.Item[i];
if (item.item == ITEM_MEMORY)
{
if (item.I.Mem.dwBar == 2)
{
_busAddress = item.I.Mem.pPhysicalAddr; // is this the bus address?
auto ptr = item.I.Mem.pUserDirectAddr;
assert(ptr); // this fails, pUserDirectAddr is 0!
}
}
}
with this approach I get a 0 pUserDirectAddr (even though qwBytes of the same struct is equal to the expected 4096 bytes).
To sum up, here are my specific questions:
- What is the correct method to obtain a valid pointer to the memory mapped range?
- Why does the system hangs when writing to pointer obtained from pUserDirectMemAddr?
- What is the difference between pUserDirectMemAddr obtained by the first method and pUserDirectAddr obtained by the second method? and why is pUserDirectAddr equals 0?
- how can I get the bus address for this memory range?
link to the same question on SO:
https://stackoverflow.com/questions/53189471/jungo-pcie-driver-writing-to-puserdirectmemaddr-causes-the-system-to-hang