pci_attach_device not recognizing base addresses

Is there a reason that pci_attach_device wouldn’t recognize the base
addresses for a PCI card? I can see the base addresses when I use
pci_read_config16 instead of pci_attach_device, but I can’t seem to use mmap
to connect to it? Does an application have to use pci_attach_device?

For those who like a little background. I am converting a QNX 4 application
that has a PCI based I/O card. I’m using QNX6.1 and its running on the same
computer and using the same card as the QNX 4 application I’m converting.
No extra cards or features have been added. I can still reboot and run the
QNX4 application. When reading the cards PCI data with the pci_read_configX
functions, the PCI registers (including base addresses) are read exactly as
they were with the QNX 4 application.

Currently I’m using a simple test program taken from QNX’s web site
(included below) to test the card. Walking through in debug I find that
pci_attach_device finds my card, but only partially fills in the
information. The fields that get data are BusNumber, DevFunc, Revision, and
Class. Irq also gets filled but it is with 0xff which, of course, is
incorrect.

This test program works fine for the other PCI cards on my system. When
using command line ‘pci -v’ there are five PCI devices and pci-bios was
started with no options.

Any thoughts or suggestions would be appreciated. Thanks

struct pci_dev_info info;
void *hdl;
int i;

memset(&info, 0, sizeof (info));

if (pci_attach(0) < 0) {
perror(“pci_attach”);
exit(EXIT_FAILURE);
}

/*

  • Fill in the Vendor and Device ID for a 3dfx VooDoo3
  • graphics adapter.
    */
    info.VendorId = VENDOR_ID ;
    info.DeviceId = DEVICE_ID ;

if ((hdl = pci_attach_device(0,
PCI_SHARE|PCI_INIT_ALL, 0, &info)) == 0) {
perror(“pci_attach_device”);
exit(EXIT_FAILURE);
}

for (i = 0; i < 6; i++) {
if (info.BaseAddressSize > 0)
printf("Aperture %d: "
“Base 0x%llx Length %d bytes Type %s\n”, i,
PCI_IS_MEM(info.CpuBaseAddress) ?
PCI_MEM_ADDR(info.CpuBaseAddress) :
PCI_IO_ADDR(info.CpuBaseAddress),
info.BaseAddressSize,
PCI_IS_MEM(info.CpuBaseAddress) ? “MEM” : “IO”);
}

printf(“IRQ 0x%x\n”, info.Irq);

pci_detach_device(hdl);

Known behavior, if your pci-device belongs to the class bridge-device.
If so, you have to update the eeprom of your card with a sensefull
class-code.

Michael

Tom Stave wrote:

Is there a reason that pci_attach_device wouldn’t recognize the base
addresses for a PCI card? I can see the base addresses when I use
pci_read_config16 instead of pci_attach_device, but I can’t seem to use mmap
to connect to it? Does an application have to use pci_attach_device?

For those who like a little background. I am converting a QNX 4 application
that has a PCI based I/O card. I’m using QNX6.1 and its running on the same
computer and using the same card as the QNX 4 application I’m converting.
No extra cards or features have been added. I can still reboot and run the
QNX4 application. When reading the cards PCI data with the pci_read_configX
functions, the PCI registers (including base addresses) are read exactly as
they were with the QNX 4 application.

Currently I’m using a simple test program taken from QNX’s web site
(included below) to test the card. Walking through in debug I find that
pci_attach_device finds my card, but only partially fills in the
information. The fields that get data are BusNumber, DevFunc, Revision, and
Class. Irq also gets filled but it is with 0xff which, of course, is
incorrect.

This test program works fine for the other PCI cards on my system. When
using command line ‘pci -v’ there are five PCI devices and pci-bios was
started with no options.

Any thoughts or suggestions would be appreciated. Thanks

struct pci_dev_info info;
void *hdl;
int i;

memset(&info, 0, sizeof (info));

if (pci_attach(0) < 0) {
perror(“pci_attach”);
exit(EXIT_FAILURE);
}

/*

  • Fill in the Vendor and Device ID for a 3dfx VooDoo3
  • graphics adapter.
    */
    info.VendorId = VENDOR_ID ;
    info.DeviceId = DEVICE_ID ;

if ((hdl = pci_attach_device(0,
PCI_SHARE|PCI_INIT_ALL, 0, &info)) == 0) {
perror(“pci_attach_device”);
exit(EXIT_FAILURE);
}

for (i = 0; i < 6; i++) {
if (info.BaseAddressSize > > 0)
printf("Aperture %d: "
“Base 0x%llx Length %d bytes Type %s\n”, i,
PCI_IS_MEM(info.CpuBaseAddress> ) ?
PCI_MEM_ADDR(info.CpuBaseAddress> ) :
PCI_IO_ADDR(info.CpuBaseAddress> ),
info.BaseAddressSize> ,
PCI_IS_MEM(info.CpuBaseAddress> ) ? “MEM” : “IO”);
}

printf(“IRQ 0x%x\n”, info.Irq);

pci_detach_device(hdl);

My device is a class bridge device. Thanks for the response.

I was able to gain access to my card by doing the following:

  • Getting the base addresses and requested size by using the
    pci_read_config32 and pci_write_config32 functions.
  • Allocate these resources to the system by using the rsrcdbmgr_create
    function.
  • Use mmap to access the cards memory by my application.

(code follows)

Since my short term goals were to just gain access to this device to do some
testing - this solution was great.

My question is, can I leave the code as written or do I need to seek another
solution. Does anyone know if this approach will cause me problems later
on?


long pciMemSetup( int bus_nm, int devfc_nm, unsigned ofst_vl,
int *port_nm, char **mem_ad )
{
unsigned long cur_ad ;
unsigned long size_vl ;
unsigned long wrk_vl = ~0 ;
rsrc_alloc_t rsrc_rc ;

memset( &rsrc_rc, ‘\0’, sizeof( rsrc_rc ) ) ;

// Get the Base Address register and the requested size.
// - read the base address
// - write all 1’s to the base address register
// - read the size value (the size is the first non zero bit)
// - write the address back to the base address register.

pci_read_config32( bus_nm, devfc_nm, ofst_vl, 1, ( char *)&cur_ad ) ;
pci_write_config32( bus_nm, devfc_nm, ofst_vl, 1, ( char *)&wrk_vl ) ;
pci_read_config32( bus_nm, devfc_nm, ofst_vl, 1, ( char *)&size_vl ) ;
pci_write_config32( bus_nm, devfc_nm, ofst_vl, 1, ( char *)&cur_ad ) ;

if ( PCI_IS_IO( cur_ad ) )
{
size_vl = ~( size_vl & PCI_BASE_ADDRESS_IO_MASK ) + 1 ;
rsrc_rc.start = PCI_IO_ADDR( cur_ad ) ;
rsrc_rc.end = rsrc_rc.start + size_vl - 1 ;
rsrc_rc.flags = RSRCDBMGR_IO_PORT ;
if ( rsrcdbmgr_create( &rsrc_rc, 1 ) == -1 )
{
size_vl = 0 ;
}
else
{
*port_nm = rsrc_rc.start ;
}
}
else
{
size_vl = ~( size_vl & PCI_BASE_ADDRESS_MEM_MASK ) + 1 ;
cur_ad = PCI_MEM_ADDR( cur_ad ) ;
rsrc_rc.start = cur_ad ;
rsrc_rc.end = rsrc_rc.start + size_vl - 1 ;
rsrc_rc.flags = RSRCDBMGR_PCI_MEMORY ;
if ( rsrcdbmgr_create( &rsrc_rc, 1 ) == -1 )
{
size_vl = 0 ;
}
else
if ( ( *mem_ad = mmap_device_memory( 0, size_vl, PROT_READ | PROT_WRITE |
PROT_NOCACHE, 0, cur_ad ) ) == MAP_FAILED )
{
size_vl = 0 ;
}
}

return( size_vl ) ;
}

“Michael Tasche” <michael.tasche@privat.kkf.net> wrote in message
news:f8orva.786.ln@pccomm.tnet

Known behavior, if your pci-device belongs to the class bridge-device.
If so, you have to update the eeprom of your card with a sensefull
class-code.

Michael

Tom Stave wrote:
Is there a reason that pci_attach_device wouldn’t recognize the base
addresses for a PCI card? I can see the base addresses when I use
pci_read_config16 instead of pci_attach_device, but I can’t seem to use
mmap
to connect to it? Does an application have to use pci_attach_device?

For those who like a little background. I am converting a QNX 4
application
that has a PCI based I/O card. I’m using QNX6.1 and its running on the
same
computer and using the same card as the QNX 4 application I’m
converting.
No extra cards or features have been added. I can still reboot and run
the
QNX4 application. When reading the cards PCI data with the
pci_read_configX
functions, the PCI registers (including base addresses) are read exactly
as
they were with the QNX 4 application.

Currently I’m using a simple test program taken from QNX’s web site
(included below) to test the card. Walking through in debug I find that
pci_attach_device finds my card, but only partially fills in the
information. The fields that get data are BusNumber, DevFunc, Revision,
and
Class. Irq also gets filled but it is with 0xff which, of course, is
incorrect.

This test program works fine for the other PCI cards on my system. When
using command line ‘pci -v’ there are five PCI devices and pci-bios was
started with no options.

Any thoughts or suggestions would be appreciated. Thanks

struct pci_dev_info info;
void *hdl;
int i;

memset(&info, 0, sizeof (info));

if (pci_attach(0) < 0) {
perror(“pci_attach”);
exit(EXIT_FAILURE);
}

/*

  • Fill in the Vendor and Device ID for a 3dfx VooDoo3
  • graphics adapter.
    */
    info.VendorId = VENDOR_ID ;
    info.DeviceId = DEVICE_ID ;

if ((hdl = pci_attach_device(0,
PCI_SHARE|PCI_INIT_ALL, 0, &info)) == 0) {
perror(“pci_attach_device”);
exit(EXIT_FAILURE);
}

for (i = 0; i < 6; i++) {
if (info.BaseAddressSize > > 0)
printf("Aperture %d: "
“Base 0x%llx Length %d bytes Type %s\n”, i,
PCI_IS_MEM(info.CpuBaseAddress> ) ?
PCI_MEM_ADDR(info.CpuBaseAddress> ) :
PCI_IO_ADDR(info.CpuBaseAddress> ),
info.BaseAddressSize> ,
PCI_IS_MEM(info.CpuBaseAddress> ) ? “MEM” : “IO”);
}

printf(“IRQ 0x%x\n”, info.Irq);

pci_detach_device(hdl);