simple PCI questions...

Hi…

On a cPCI system, we have a PCI configuration Space with some
registers. In a program I perform a pci_attach_device() call (see
program at the end of this message), and all works. But…

  1. when I do a pci -v I get:

PCI Mem Address = f4100000h 32bit length 32768 enabled
PCI Mem Address = f4108000h 32bit length 4096 enabled
PCI IO Address = 2000h length 256 enabled

when I do a pci_attach_device() I get:

PciBaseAddress[0] = f4100000
PciBaseAddress[1] = 0
CpuBaseAddress[0] = f4108000
CpuBaseAddress[1] = 0
BaseAddressSize[0] = f4100000
BaseAddressSize[1] = 0

What is the relation between the [pci -v] reported ‘PCI Mem Address’ and
the [pci_attach_device()] reported data shown above?

  1. the [pci -v] report shows a -correct- size for the pci mem address.
    However, the ‘BaseAddressSize’ member of the pci_dev_info struct does
    not report this number. How can I get the size of the memory
    programmatically?

  2. how or form where do I get the ‘PCI IO Address = 2000h’ and
    corresponding length reported by [pci -v]?? How do I do this
    programmatically?

  3. what is the difference between ‘PCI Mem Address’ and ‘PCI IO Address’
    reported by [pci -v]??

  4. Now I need to set bits in a control register at some offset from [PCI
    Mem Address = f4108000h]. Do I have to use ‘pci_write_config()’ to do
    this, use ‘mmap_device_memory()’ to map the address to another place, or
    do I use ‘inX/outX()’ functions?? I guess that I am a bit confused, and
    can’t really post a half intelligent question here. Any help is
    appreciated.

  5. I suppose that I can map the ‘PCI Mem Address’ to some shared memory
    space. Any pointers to any documented examples on how to do this?

  6. the [pci -v] command reports

Status Reg = 400h
Command Reg = 117h

However, these are not the command and status registers associated with
the pci device. Are these memory mapped by the BIOS somehow? Or are
these two registers associated with the OS and the PCI bus/bridge/(?)
?? What are these precisely? (note: these addresses are not related to
the cPCI documented registers).

  1. Finally, any links to places that may hold answers to some of these
    questions? I guess that I could go to the CVS files. Would this be the
    thing to do?? Where would be the code for the ‘pci’ command?

Thanks.

Best Regards…

Miguel.

P.S. Please find the output of pci -v, and the output of a small program
bellow.

\

$ pci -v

PCI version = 2.10

Class = Unknown (Unknown)
Vendor ID = 114ah, VMIC
Device ID = 6504h, Unknown Unknown
PCI index = 0h
Class Codes = ff0000h
Revision ID = 1h
Bus number = 1
Device number = 4
Function num = 0
Status Reg = 400h
Command Reg = 117h
Header type = 0h Single-function
BIST = 0h Build-in-self-test not supported
Latency Timer = 40h
Cache Line Size= 8h un-cacheable
PCI Mem Address = f4100000h 32bit length 32768 enabled
PCI Mem Address = f4108000h 32bit length 4096 enabled
PCI IO Address = 2000h length 256 enabled
Subsystem Vendor ID = 114ah
Subsystem ID = 7755h
Max Lat = 0ns
Min Gnt = 0ns
PCI Int Pin = INT A
Interrupt line = 11

=========================
==== program output =====

Bridge device found
Vendor Id = 114a
Device Id = 6504
Subsystem Id = 7755
Subsystem Vendor Id = 114a
Bus Number = 1
Device Function Number = 20
Revision = 1
Class = ff0000
IRQ = b
PciBaseAddress[0] = f4100000
PciBaseAddress[1] = 0
CpuBaseAddress[0] = f4108000
CpuBaseAddress[1] = 0
BaseAddressSize[0] = f4100000
BaseAddressSize[1] = 0
CpuIoTranslation = f4108000
CpuMemTranslation = 0
CpuBmstrTranslation = 8000
RomSize = 1000

vendor ID = 0x114a, base addr: ram = 0xf4100000, timer = 0xf4108000

/////////////////////////////////
// ==== program ====
/////////////////////////////////
#include <fcntl.h>
#include <stdio.h>
#include <hw/pci.h>
#include <sys/mman.h>

int main( int argc, char **argv )
{
struct pci_dev_info vmic7755;
void *bridgeBase;
void *bridgeHandle;
int pci_handle;
unsigned long BaseAddr_ram, off;
unsigned long BaseAddr_timer;
unsigned short valA;

if( pci_handle = pci_attach( 0 ) < 0 )
{
perror( “Error attaching to the PCI server” );
return ( -1 );
}

/*

  • Locate the embedded PCI functions resources
    */
    memset( &vmic7755, 0, sizeof( vmic7755 ) );
    vmic7755.VendorId = 0x114A;
    vmic7755.DeviceId = 0x6504;

bridgeHandle = pci_attach_device( NULL, PCI_SEARCH_VENDEV |
PCI_SHARE, 0, &vmic7755 );

if( NULL == bridgeHandle )
{ perror( “pci_attach_device” );
return ( -1 );
}

printf( “Bridge device found\n”
" Vendor Id = %x\n"
" Device Id = %x\n"
" Subsystem Id = %x\n"
" Subsystem Vendor Id = %x\n"
" Bus Number = %x\n"
" Device Function Number = %x\n"
" Revision = %x\n"
" Class = %x\n"
" IRQ = %x\n"
" PciBaseAddress[0] = %x\n"
" PciBaseAddress[1] = %x\n"
" CpuBaseAddress[0] = %x\n"
" CpuBaseAddress[1] = %x\n"
" BaseAddressSize[0] = %x\n"
" BaseAddressSize[1] = %x\n"
" CpuIoTranslation = %x\n"
" CpuMemTranslation = %x\n"
" CpuBmstrTranslation = %x\n"
" RomSize = %x\n",
vmic7755.VendorId, vmic7755.DeviceId, vmic7755.SubsystemId,
vmic7755.SubsystemVendorId, vmic7755.BusNumber,
vmic7755.DevFunc, vmic7755.Revision, vmic7755.Class,
vmic7755.Irq,
vmic7755.PciBaseAddress[0], vmic7755.PciBaseAddress[1],
vmic7755.CpuBaseAddress[0], vmic7755.CpuBaseAddress[1],
vmic7755.BaseAddressSize[0], vmic7755.BaseAddressSize[1],
vmic7755.CpuIoTranslation, vmic7755.CpuMemTranslation,
vmic7755.CpuBmstrTranslation,
vmic7755.RomSize );

/*

  • Get the base address of the CSR’s
    */
    if( pci_read_config( bridgeHandle, 0x10, 1, sizeof( BaseAddr_ram ),
    &BaseAddr_ram ) !=
    PCI_SUCCESS )
    { perror( “pci_read_config” );
    return ( -1 );
    }
    if( pci_read_config( bridgeHandle, 0x14, 1, sizeof( BaseAddr_timer ),
    &BaseAddr_timer ) !=
    PCI_SUCCESS )
    { perror( “pci_read_config” );
    return ( -1 );
    }
    if( pci_read_config( bridgeHandle, 0 , 1, sizeof( valA ), &valA ) !=
    PCI_SUCCESS )
    { perror( “pci_read_config” );
    return ( -1 );
    }
    printf( “\n vendor ID = 0x%x, base addr: ram = 0x%x, timer = 0x%x \n”,
    valA, BaseAddr_ram, BaseAddr_timer );
    }

============================

my opinions are mine, only mine, solely mine, and they are not related
in any possible way to the institution(s) in which I study and work.

Miguel Simon
Research Engineer
School of Aerospace and Mechanical Engineering
University of Oklahoma
http://www.amerobotics.ou.edu/
http://www.saic.com

Previously, Miguel Simon wrote in qdn.public.qnxrtp.applications:

Hi…

On a cPCI system, we have a PCI configuration Space with some
registers. In a program I perform a pci_attach_device() call (see
program at the end of this message), and all works. But…

  1. when I do a pci -v I get:

PCI Mem Address = f4100000h 32bit length 32768 enabled
PCI Mem Address = f4108000h 32bit length 4096 enabled
PCI IO Address = 2000h length 256 enabled

when I do a pci_attach_device() I get:

PciBaseAddress[0] = f4100000
PciBaseAddress[1] = 0
CpuBaseAddress[0] = f4108000
CpuBaseAddress[1] = 0
BaseAddressSize[0] = f4100000
BaseAddressSize[1] = 0

Yes, take a look at at the pci_dev_info structure. The BaseAddress registers
are all 64-bit registers, so you need to use “%llx” in your printf’s. try
compiling your program with the -w3 switch and see the warnings!

What is the relation between the [pci -v] reported ‘PCI Mem Address’ and
the [pci_attach_device()] reported data shown above?

  1. the [pci -v] report shows a -correct- size for the pci mem address.
    However, the ‘BaseAddressSize’ member of the pci_dev_info struct does
    not report this number. How can I get the size of the memory
    programmatically?

  2. how or form where do I get the ‘PCI IO Address = 2000h’ and
    corresponding length reported by [pci -v]?? How do I do this
    programmatically?

  3. what is the difference between ‘PCI Mem Address’ and ‘PCI IO Address’
    reported by [pci -v]??

Some PCI adapters allow you to do either memory mapped or I/O mapped I/O,
hence the 2 addresses. These are implementation specific.

  1. Now I need to set bits in a control register at some offset from [PCI
    Mem Address = f4108000h]. Do I have to use ‘pci_write_config()’ to do
    this, use ‘mmap_device_memory()’ to map the address to another place, or
    do I use ‘inX/outX()’ functions?? I guess that I am a bit confused, and
    can’t really post a half intelligent question here. Any help is
    appreciated.

You can set the bits in the control register with either an out…()
instruction (after performing an mmap_device_io() on the CpuBaseAddress)
or you can do memory mapped I/O by using a pointer (after performing
an mmap_device_memory() on the CpuBaseAddress).

  1. I suppose that I can map the ‘PCI Mem Address’ to some shared memory
    space. Any pointers to any documented examples on how to do this?

See above.

  1. the [pci -v] command reports

Status Reg = 400h
Command Reg = 117h

However, these are not the command and status registers associated with
the pci device. Are these memory mapped by the BIOS somehow? Or are
these two registers associated with the OS and the PCI bus/bridge/(?)
?? What are these precisely? (note: these addresses are not related to
the cPCI documented registers).

These are PCI Command and Status registers.

  1. Finally, any links to places that may hold answers to some of these
    questions? I guess that I could go to the CVS files. Would this be the
    thing to do?? Where would be the code for the ‘pci’ command?

I suggest you read the Mindshare PCI System Architecture manual.

Thanks.

Best Regards…

Miguel.

P.S. Please find the output of pci -v, and the output of a small program
bellow.

\

$ pci -v

PCI version = 2.10

Class = Unknown (Unknown)
Vendor ID = 114ah, VMIC
Device ID = 6504h, Unknown Unknown
PCI index = 0h
Class Codes = ff0000h
Revision ID = 1h
Bus number = 1
Device number = 4
Function num = 0
Status Reg = 400h
Command Reg = 117h
Header type = 0h Single-function
BIST = 0h Build-in-self-test not supported
Latency Timer = 40h
Cache Line Size= 8h un-cacheable
PCI Mem Address = f4100000h 32bit length 32768 enabled
PCI Mem Address = f4108000h 32bit length 4096 enabled
PCI IO Address = 2000h length 256 enabled
Subsystem Vendor ID = 114ah
Subsystem ID = 7755h
Max Lat = 0ns
Min Gnt = 0ns
PCI Int Pin = INT A
Interrupt line = 11

=========================
==== program output =====

Bridge device found
Vendor Id = 114a
Device Id = 6504
Subsystem Id = 7755
Subsystem Vendor Id = 114a
Bus Number = 1
Device Function Number = 20
Revision = 1
Class = ff0000
IRQ = b
PciBaseAddress[0] = f4100000
PciBaseAddress[1] = 0
CpuBaseAddress[0] = f4108000
CpuBaseAddress[1] = 0
BaseAddressSize[0] = f4100000
BaseAddressSize[1] = 0
CpuIoTranslation = f4108000
CpuMemTranslation = 0
CpuBmstrTranslation = 8000
RomSize = 1000

vendor ID = 0x114a, base addr: ram = 0xf4100000, timer = 0xf4108000

/////////////////////////////////
// ==== program ====
/////////////////////////////////
#include <fcntl.h
#include <stdio.h
#include <hw/pci.h
#include <sys/mman.h

int main( int argc, char **argv )
{
struct pci_dev_info vmic7755;
void *bridgeBase;
void *bridgeHandle;
int pci_handle;
unsigned long BaseAddr_ram, off;
unsigned long BaseAddr_timer;
unsigned short valA;

if( pci_handle = pci_attach( 0 ) < 0 )
{
perror( “Error attaching to the PCI server” );
return ( -1 );
}

/*

  • Locate the embedded PCI functions resources
    */
    memset( &vmic7755, 0, sizeof( vmic7755 ) );
    vmic7755.VendorId = 0x114A;
    vmic7755.DeviceId = 0x6504;

bridgeHandle = pci_attach_device( NULL, PCI_SEARCH_VENDEV |
PCI_SHARE, 0, &vmic7755 );

if( NULL == bridgeHandle )
{ perror( “pci_attach_device” );
return ( -1 );
}

printf( “Bridge device found\n”
" Vendor Id = %x\n"
" Device Id = %x\n"
" Subsystem Id = %x\n"
" Subsystem Vendor Id = %x\n"
" Bus Number = %x\n"
" Device Function Number = %x\n"
" Revision = %x\n"
" Class = %x\n"
" IRQ = %x\n"
" PciBaseAddress[0] = %x\n"
" PciBaseAddress[1] = %x\n"
" CpuBaseAddress[0] = %x\n"
" CpuBaseAddress[1] = %x\n"
" BaseAddressSize[0] = %x\n"
" BaseAddressSize[1] = %x\n"
" CpuIoTranslation = %x\n"
" CpuMemTranslation = %x\n"
" CpuBmstrTranslation = %x\n"
" RomSize = %x\n",
vmic7755.VendorId, vmic7755.DeviceId, vmic7755.SubsystemId,
vmic7755.SubsystemVendorId, vmic7755.BusNumber,
vmic7755.DevFunc, vmic7755.Revision, vmic7755.Class,
vmic7755.Irq,
vmic7755.PciBaseAddress[0], vmic7755.PciBaseAddress[1],
vmic7755.CpuBaseAddress[0], vmic7755.CpuBaseAddress[1],
vmic7755.BaseAddressSize[0], vmic7755.BaseAddressSize[1],
vmic7755.CpuIoTranslation, vmic7755.CpuMemTranslation,
vmic7755.CpuBmstrTranslation,
vmic7755.RomSize );

/*

  • Get the base address of the CSR’s
    */
    if( pci_read_config( bridgeHandle, 0x10, 1, sizeof( BaseAddr_ram ),
    &BaseAddr_ram ) !=
    PCI_SUCCESS )
    { perror( “pci_read_config” );
    return ( -1 );
    }
    if( pci_read_config( bridgeHandle, 0x14, 1, sizeof( BaseAddr_timer ),
    &BaseAddr_timer ) !=
    PCI_SUCCESS )
    { perror( “pci_read_config” );
    return ( -1 );
    }
    if( pci_read_config( bridgeHandle, 0 , 1, sizeof( valA ), &valA ) !=
    PCI_SUCCESS )
    { perror( “pci_read_config” );
    return ( -1 );
    }
    printf( “\n vendor ID = 0x%x, base addr: ram = 0x%x, timer = 0x%x \n”,
    valA, BaseAddr_ram, BaseAddr_timer );
    }

============================

my opinions are mine, only mine, solely mine, and they are not related
in any possible way to the institution(s) in which I study and work.

Miguel Simon
Research Engineer
School of Aerospace and Mechanical Engineering
University of Oklahoma
http://www.amerobotics.ou.edu/
http://www.saic.com