Good morning,
I am writing code to perform DMA access for a PCI target card
developed here. My system configuration is QNX 6.3 SP2 running on a
Pentium M platform.
In a previous posting, I express some difficulties accessing onboard
memory (IO and MEM) as the card was assigned a bridge class. Since,
the class was changed to a Data Acquisition card (118000h).
I can access the card IO space using mmap_device_io() along with in*
and out* instructions.
However, I cannot access the onboard memory space. After obtaining the
memory offset (using mem_offset()), I get a segmentation violation
(SIGSEGV) error, whether I use the following instructions:
volatile uint32_t *pAddr;
off_t stMemOffset;
mem_offset( mem_hndl, NOFD, 1024, &stMemOffset, NULL);
pAddr = (uint32_t*)stMemOffset;
fprintf(stdout,"\n addr = 0x%p", pAddr );
fprintf(stdout,"\t value at read addr = 0x%x", *pAddr );
or
uint32_t dwDMAAccessLength = 8 * sizeof( uint32_t);
uint32_t dwDMAAccess[8]; // Read/Write 8 DWORD at the
time
mem_offset( mem_hndl, NOFD, 1024, &stMemOffset, NULL);
memcpy( &dwDMAAccess, (uint32_t*)stMemOffset,
dwDMAAccessLength);
where mem_hndl was obtained using mmap()
addr_hndl = PCI_MEM_ADDR( stDevInfo.CpuBaseAddress[2]);
mem_hndl = mmap( NULL,
stDevInfo.BaseAddressSize[2],
(PROT_READ | PROT_WRITE |
PROT_NOCACHE),
(MAP_PHYS | MAP_ANON),
NOFD,
addr_hndl);
Note: the prefetchable attribute bit was cleared when required before
calling mmap().
In addition, the offset value returned by mem_offset() changes between
different execution of the test program. This is a mystery to me as
the system’s configuration does not change between execution.
If mem_offset() converts virtual to physical address, one would assume
a peripheral physical address does not change between calls to
mem_offset(). Or am I missing the point of the mmap() and
mem_offset() calling sequence?
I also used both mmap() and mmap64() with the corresponding
mem_offset(). The returned values are the same whether mmap() or
mmap64() is used.
Also, the number of munmap() matches the number of mmap().
To eliminate the possibility that the HW might be incorrect, I have
tried to access the onboard memory on a second peripheral - a frame
grabber defined as Multimedia (Unknown) - Class Codes = 048000h.
Again, I get a segmentation error when accessing the memory.
This is the pci - v listing for both cards is as follow:
Class = Data Acquisition (Unknown)
Vendor ID = 1895h, Unknown
Device ID = 1h, Unknown Unknown
PCI index = 0h
Class Codes = 118000h
Revision ID = 1h
Bus number = 2
Device number = 12
Function num = 0
Status Reg = 2b0h
Command Reg = 103h
Header type = 0h Single-function
BIST = 0h Build-in-self-test not supported
Latency Timer = 42h
Cache Line Size= 10h un-cacheable
PCI IO Address = 3000h length 4096 enabled
PCI Mem Address = e0900000h prefetchable 32bit length 1048576 enabled
PCI Mem Address = e0800000h prefetchable 32bit length 1048576 enabled
PCI Mem Address = e0700000h prefetchable 32bit length 1048576 enabled
PCI Mem Address = e0600000h prefetchable 32bit length 1048576 enabled
Max Lat = 26ns
Min Gnt = 8ns
PCI Int Pin = INT A
Interrupt line = 5
CPU Interrupt = 5h
Capabilities Pointer = 80h
Capability ID = 6h
Capabilities = 0h - 0h
Class = Multimedia (Unknown)
Vendor ID = 1131h, Philips Semiconductors
Device ID = 7146h, SAA7146 Multi Media Bridge Scaler
PCI index = 0h
Class Codes = 048000h
Revision ID = 1h
Bus number = 2
Device number = 15
Function num = 0
Status Reg = 280h
Command Reg = 202h
Header type = 0h Single-function
BIST = 0h Build-in-self-test not supported
Latency Timer = 7bh
Cache Line Size= 0h
PCI Mem Address = e0300000h 32bit length 512 enabled
Subsystem Vendor ID = 18c9h
Subsystem ID = 2011h
Max Lat = 38ns
Min Gnt = 15ns
PCI Int Pin = INT A
Interrupt line = 11
CPU Interrupt = bh
Any suggestions?
Thank you for your time
Daniel