mem_offset question

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

Hi Daniel:

I think that you might have things backwards :slight_smile:. You already have the
physical address for the memory (which is what you passed into the mmap
call). The mmap call gives you the virtual address which is the address
that you would pass into your memcpy routine to copy data from the CPU
to the PCI card.

Just as a side note, this isn’t DMA. With DMA, you take your RAM
(which has to be allocated using mmap to obtain physically contiguous
memory) and you program a piece of hardware with the RAM physical
address (obtained using mem_offset), the device physical address and a
length and tell it to “go” (essentially, you replace a software memcpy
with a hardware operation)…

Hope that helps,
Robert


dlabonte wrote:

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

You must also mmap the memory address. Don’t use mem_offset. Use the
mmap_device_memory() function to map in the memory.

“dlabonte” <labonte_d@yahoo-dot-ca.no-spam.invalid> wrote in message
news:e1j836$rgi$1@inn.qnx.com

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

I have almost the same problem!
I cannot access the onboard memory space using mmap_device_memory()!

#define TS5600_MMCRBASE 0xDF000
/* Offset for PIO registers */
#define PIO_0_15_SET 0xC34

volatile uint32_t *MMCR;

int main(int argc, char *argv[])
{
uint16_t val16;

/* Mapping MMCR */
MMCR = mmap_device_memory(0, 0xFFFF, PROT_READ | PROT_WRITE, 0 ,
TS5600_MMCRBASE);
if ( MMCR == MAP_FAILED )
{
fprintf(stderr,“mmap failed : %d\n”, errno);
return EXIT_FAILURE;
}

fprintf(stdout,"\n addr = 0x%p", MMCR );
fprintf(stdout,"\t value at read addr = 0x%x", *MMCR );

memcpy( &val16, (uint32_t*)(MMCR+PIO_0_15_SET),
sizeof(uint16_t));
val16 = 0x80F0;
memcpy((uint32_t*)(MMCR+PIO_0_15_SET), &val16,
sizeof(uint16_t));
memcpy( &val16, (uint32_t*)(MMCR+PIO_0_15_SET),
sizeof(uint16_t));

====> Value doesn’t change :frowning:

Also tried :

// set PIO 4-7,15 to one
val16 = MMCR[PIO_0_15_SET];
MMCR[PIO_0_15_SET] = 0x80F0;
val16 = MMCR[PIO_0_15_SET];

===> Value doesn’t change…

Also tried using mmap_device_io() along with in* and out*
instructions. But same result :frowning:

Any suggestions?
Thanks!

Oli

“dumbool_82” <dumbool_82@hotmail-dot-com.no-spam.invalid> wrote in message
news:e2krps$mm1$1@inn.qnx.com

I have almost the same problem!
I cannot access the onboard memory space using mmap_device_memory()!

#define TS5600_MMCRBASE 0xDF000
/* Offset for PIO registers */
#define PIO_0_15_SET 0xC34

volatile uint32_t *MMCR;

int main(int argc, char *argv[])
{
uint16_t val16;

/* Mapping MMCR */
MMCR = mmap_device_memory(0, 0xFFFF, PROT_READ | PROT_WRITE, 0 ,
TS5600_MMCRBASE);
if ( MMCR == MAP_FAILED )
{
fprintf(stderr,“mmap failed : %d\n”, errno);
return EXIT_FAILURE;
}

fprintf(stdout,"\n addr = 0x%p", MMCR );
fprintf(stdout,"\t value at read addr = 0x%x", *MMCR );

Are the offset in bytes or in 4bytes? Since MCCR is a pointer to int

what you get is actually ( MMCR+ (POIO_0_15_SET * 4 ))

memcpy( &val16, (uint32_t*)(MMCR+PIO_0_15_SET),
sizeof(uint16_t));
val16 = 0x80F0;
memcpy((uint32_t*)(MMCR+PIO_0_15_SET), &val16,
sizeof(uint16_t));
memcpy( &val16, (uint32_t*)(MMCR+PIO_0_15_SET),
sizeof(uint16_t));

====> Value doesn’t change > :frowning:

Also tried :

// set PIO 4-7,15 to one
val16 = MMCR[PIO_0_15_SET];
MMCR[PIO_0_15_SET] = 0x80F0;
val16 = MMCR[PIO_0_15_SET];

===> Value doesn’t change…

Also tried using mmap_device_io() along with in* and out*
instructions. But same result > :frowning:

Any suggestions?
Thanks!

Oli