[Previous]
[Contents]
[Next]

_CA_PCI_Find_Device()

find the PCI device with a given device ID and vendor ID

Synopsis:

#include <sys/pci.h>
int _CA_PCI_Find_Device ( unsigned devid,
                          unsigned venid,
                          unsigned index,
                          unsigned *busnum,
                          unsigned *devfuncnum );

Description:

This function returns the location of the nth PCI device that has the specified Device ID and Vendor ID.

The arguments are as follows:

devid
the Device ID
venid
the Vendor ID
index
the index (n) of the device or function sought
busnum
the Bus Number of the device or function found
devfuncnum
the Device or Function ID of the nth device or function found with the specified Device and Vendor IDs The device number is in bits 7 through 3, and the function number in bits 2 through 0.

Note: You can find all the devices having the same Device and Vendor IDs by making successive calls to this function, starting with an index of 0, and incrementing it until PCI_DEVICE_NOT_FOUND is returned.

Returns:

PCI_SUCCESS
the device or function was found
PCI_DEVICE_NOT_FOUND
the device or function was not found
PCI_BAD_VENDOR_ID
an invalid Vendor ID was given

Examples:

The following example shows how to detect a device:

#include <stdlib.h>
#include <stddef.h>
#include <stdio.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <sys/osinfo.h>
#include <sys/pci.h>
#include <i86.h>

// Define the following constants as appropriate

#define YOUR_PCI_DEVICE_ID 0x####
#define YOUR_PCI_VENDOR_ID 0x####

int main( void )
{
    struct _osinfo      info;
    unsigned            busnum, devfuncnum;
    long                address;
    char                *mem_base;
    long                io_base;
    unsigned char       irq;
    int                 pci_index = 0;

// NOTE 1: pci_index is a value between 0 and the number 
//         of devices of your type on the bus.  That is, 
//         specifying a value of 1 will detect the second 
//         occurrence of your device.
// NOTE 2: There is no relationship between the pci_index 
//         and the bus slot numbers.
// The Net drivers have a command line option for setting 
// the pci_index.

    if( qnx_osinfo( 0, &info ) == -1 ) {
        printf("Error qnx_osinfo\n");
        exit( EXIT_FAILURE );    }

    // we have a PCI BIOS
    if( !( info.sflags & _PSF_PCI_BIOS ) ) {        
        printf("No PCI BIOS\n");
        return 0;
    }

    if( _CA_PCI_Find_Device( YOUR_PCI_DEVICE_ID, 
            YOUR_PCI_VENDOR_ID, pci_index, &busnum, 
            &devfuncnum ) != PCI_SUCCESS ) {
        printf("Can not find device\n");
        exit( EXIT_FAILURE );
    }

    // determine device interrupt
    if( _CA_PCI_Read_Config_Byte( busnum, devfuncnum, 
             offsetof(struct _pci_config_regs, 
                      Interrupt_Line),
             1, &irq) != PCI_SUCCESS ) {
        printf("Error reading interrupt\n");
        exit( EXIT_FAILURE );
    }

// NOTE:  You will need to know how the configuration space 
//        has been initialized for your device to determine 
//        the I/O and memory base addresses.  You might have 
//        to change the Base_Address_Regs index.  That is, 
//        some devices may define offset 0 to be the memory
//        base, while others define it as the I/O base.

    // determine device I/O and memory base addresses
    if(_CA_PCI_Read_Config_DWord(busnum, devfuncnum, 
            offsetof(struct _pci_config_regs, 
                     Base_Address_Regs[0]),
            1, (char *)&address) != PCI_SUCCESS) {
        printf("Error reading address\n");
        exit( EXIT_FAILURE );
    }
    
    if( PCI_IS_MEM( address ) ) {        // memory base address
        int fd;
        char *page_ptr;

        // you might want to map in the memory area 
        fd = shm_open( "Physical", O_RDWR, 0777 );
        if ( fd == -1 ) {
            perror("Error shm_open:");
            exit( EXIT_FAILURE );
        }
        page_ptr = mmap( 0, 4096, PROT_READ|PROT_WRITE, MAP_SHARED,
                         fd, PCI_MEM_ADDR( address ) & ~0xfff );
        if(page_ptr == (char *) -1) {
            perror("Error mmap:");
            exit( EXIT_FAILURE );
        }
        mem_base = page_ptr + (PCI_MEM_ADDR( address ) & 0xfff);
        close(fd);
    }
    else {                                // I/O base address
        io_base = PCI_IO_ADDR( address );
    }

    printf( "IO address:  %lx\n", io_base );
    printf( "MEM address: %lx\n", PCI_MEM_ADDR( address ) );
    if( PCI_IS_MEM( address ) ) 
        printf( "mapped at  : %lx\n", mem_base );
    printf( "IRQ:         %x\n", irq );

    exit( EXIT_SUCCESS );
}

Classification:

Intel

Safety:
Interrupt handler No
Signal handler No
Thread No

Caveats:

When you use the _CA_PCI_... functions:

See also:

_CA_PCI_BIOS_Present(), _CA_PCI_Find_Class(), _CA_PCI_GenerateSpecialCycle(), _CA_PCI_Read_Config_Byte(), _CA_PCI_Read_Config_DWord(), _CA_PCI_Read_Config_Word(), _CA_PCI_Write_Config_Byte(), _CA_PCI_Write_Config_DWord(), _CA_PCI_Write_Config_Word()


[Previous]
[Contents]
[Next]