find the PCI device with a given device ID and vendor ID
#include <sys/pci.h> int _CA_PCI_Find_Device ( unsigned devid, unsigned venid, unsigned index, unsigned *busnum, unsigned *devfuncnum );
This function returns the location of the nth PCI device that has the specified Device ID and Vendor ID.
The arguments are as follows:
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. |
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 ); }
Intel
Safety: | |
---|---|
Interrupt handler | No |
Signal handler | No |
Thread | No |
When you use the _CA_PCI_... functions:
_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()