PCI mmap - How do I access a PCI board address space?

gregory.menke at gsfc.nasa.gov gregory.menke at gsfc.nasa.gov
Thu Sep 25 15:14:35 UTC 2003



Look at the RTEMS network drivers, in c/src/lib/libchip/network,
several of them support PCI addressing both for PPC and x86.

In general, PCI memory access is just the same as regular ram, except
there are address translations involved.  The address you get from the
card's base address register is in "pci space", meaning some region in
a 2^32 space.  The processor has a different perspective on memory
because everything is "downstream" from it, including the pci space.
On the PPC, the PCI chipset implements a register pair that identifies
the range of addresses as seen by the processor that will be applied
to the PCI bus.  So, to translate the base address given by the board,
you add the lower bound of the region to it, shifting the PCI address
into the region that the processor is decoding as PCI.  Then, accesses
into that region are directed towards the PCI bus.  Its all memory
accesses from the perspective of the processor.

Secondly, using memcpy or pointer dereferencing to manipulate data in
pci space is not portable, it will probably work on many
architectures, but its better to use the IO primitives given by RTEMS,
just like you would in Linux.  They come in 8, 16 and 32 bit
variations and will handle endianness properly on big endian
processors.


Gregm



Hugo writes:
 > Hi!
 > 
 > I am using RTEMS for an i386 target architecture.
 > 
 > I am trying to communicate with a PCI board.
 > 
 > I have tryed the board outside RTEMS and it works fine. 
 > 
 > I was able to read the base address where the board should be mapped
 > into memory.
 > 
 > The Board should be mapped into memory at address 0x1400, unfortunately
 > I am unable to operate the board properly.
 > 
 > I am guessing that I have been unable to access the board space
 > properly.
 > 
 > Since there is no mmap function in RTEMS could anyone please tell me how
 > do I access the board address space?
 > 
 > 
 > If I could use the memcpy function I would want to do something like:
 > 
 > 
 > /* This is very simplified */
 > 
 > unsigned short data[4];
 > unsigned short status;
 > 
 > ....
 > 
 > 
 > for( index=0; index<4; index++ ) {
 > 
 >   memcpy( 0x1400 + index*2, &(data[index]), 2 );
 > 
 >   do {
 >     /* I should sleep a bit here */
 > 
 >     memcpy( &status, 0x1400, 2 );
 > 
 >   } while ( status & 0x0001 );
 > 
 > }
 > 
 > 
 > 
 > 
 > 
 > 




More information about the users mailing list