![]() |
![]() |
![]() |
Attach a driver to a PCI device
#include <hw/pci.h> void* pci_attach_device( void* handle, uint32_t flags, uint16_t idx, struct pci_dev_info* info );
libc
The pci_attach_device() function attaches a driver to a PCI device.
This function fills in a struct pci_dev_info structure that describes an occurrence of a device. This structure has the following members:
Member | Description |
---|---|
uint16_t DeviceId | Device ID (input/output) |
uint16_t VendorId | Vendor ID (input/output) |
uint16_t SubsystemId | Subsystem ID (output) |
uint16_t SubsystemVendorId | Subsystem Vendor ID (output) |
uint8_t BusNumber | Bus number (output) |
uint8_t DevFunc | Device/function number (output) |
uint8_t Revision | Device revision (output) |
uint8_t Class | Class code (input/output) |
uint32_t Irq | Interrupt (output) |
uint64_t CpuIoTranslation | CPU to PCI translation value (pci_addr = cpu_addr - translation) |
uint64_t CpuMemTranslation | CPU to PCI memory translation (pci_addr = cpu_addr - translation) |
uint64_t CpuBmstrTranslation | CPU busmaster address to PCI busmaster address (pci_addr = cpu_addr + translation) |
uint64_t PciBaseAddress [6] | PCI base address (array of six uint64_t items) |
uint64_t CpuBaseAddress [6] | CPU base address (array of six uint64_t items) |
uint32_t BaseAddressSize [6] | Size of the base address aperture into the board (array of six uint32_t items) |
uint64_t PciRom | PCI ROM address |
uint64_t CpuRom | CPU ROM address |
uint32_t RomSize | Size of the aperture into the board |
The server can scan based on a class code, vendor/device ID, or bus number and device/function number. Server scanning is controlled by initializing the appropriate fields of the info structure and setting the appropriate flags. The idx parameter tells the server for which occurrence to return information.
The flags parameter tells the PCI server how resources are to be handled, which resources to scan for, and which resources to allocate.
These bits control how resources are handled:
Bit | Resource handling: |
---|---|
PCI_SHARE | Allow resources to be shared with other drivers. If this isn't set, no other driver can attach to the device. |
PCI_PERSIST | Resources persist after the device is detached. |
The following bits ask the PCI server to scan for a device based on fields specified in the structure pointed to by info:
Bit | Scan for: |
---|---|
PCI_SEARCH_VEND | VendorID |
PCI_SEARCH_VENDEV | DeviceId and VendorId |
PCI_SEARCH_CLASS | Class |
PCI_SEARCH_BUSDEV | BusNumber and DevFunc |
These bits specify which members of the structure the server should initialize:
Bit | Initialize: |
---|---|
PCI_INIT_IRQ | Irq |
PCI_INIT_ROM | PciRom and CpuRom |
PCI_INIT_BASE0 ... PCI_INIT_BASE5 | The specified entries of the PciBaseAddress and CpuBaseAddress arrays |
PCI_INIT_ALL | All members except PciRom and CpuRom |
The first time you call this function, set the handle parameter to NULL. This function returns a handle that can be used in a subsequent call to allocate resources for the device.
Calling this routine automatically reserves the device, but this can be overridden with the PCI_SHARE flag.
To facilitate the testing of addresses returned by the PCI server, at least the following macros are defined in the <pci.h> header file:
For example:
{ uint64_t port; if (PCI_IS_IO(addr)) /* The address returned by the pci server */ port = (PCI_IO_ADDR(addr)); }
A handle to be used for other pci_* calls associated with a handle, or NULL if an error occurs.
Attach to and allocate all resources for the first occurrence of an Adaptec 2940 adapter:
#include <hw/pci.h> #include <hw/pci_devices.h> #include <stdio.h> #include <stdlib.h> int main( void ) { int pidx; void* hdl; int phdl; struct pci_dev_info inf; /* Connect to the PCI server */ phdl = pci_attach( 0 ); if( phdl == -1 ) { fprintf( stderr, "Unable to initialize PCI\n" ); return EXIT_FAILURE; } /* Initialize the pci_dev_info structure */ memset( &inf, 0, sizeof( inf ) ); pidx = 0; inf.VendorId = PCI_VENDOR_ID_ADAPTEC; inf.DeviceId = PCI_DEVICE_ID_ADAPTEC_2940F; hdl = pci_attach_device( NULL, PCI_INIT_ALL, pidx, &inf ); if( hdl == NULL ) { fprintf( stderr, "Unable to locate adapter\n" ); } else { /* Do something to the adapter */ pci_detach_device( hdl ); } /* Disconnect from the PCI server */ pci_detach( phdl ); return EXIT_SUCCESS; }
Attach to the first occurrence of an Adapter 2940 adapter and allocate resources in a second call:
#include <hw/pci.h> #include <hw/pci_devices.h> #include <stdio.h> #include <stdlib.h> int main( void ) { int pidx; void* hdl; void* retval; int phdl; struct pci_dev_info inf; phdl = pci_attach( 0 ); if( phdl == -1 ) { fprintf( stderr, "Unable to initialize PCI\n" ); return EXIT_FAILURE; } memset( &inf, 0, sizeof( inf ) ); pidx = 0; inf.VendorId = PCI_VENDOR_ID_ADAPTEC; inf.DeviceId = PCI_DEVICE_ID_ADAPTEC_2940F; hdl = pci_attach_device( NULL, 0, pidx, &inf ); if( hdl == NULL ) { fprintf( stderr, "Unable to locate adapter\n" ); } retval = pci_attach_device( hdl, PCI_INIT_ALL, pidx, &inf ); if( retval == NULL ) { fprintf( stderr, "Unable allocate resources\n" ); } pci_detach( phdl ); return EXIT_SUCCESS; }
Safety: | |
---|---|
Cancellation point | Yes |
Interrupt handler | No |
Signal handler | Yes |
Thread | Yes |
pci_attach(), pci_detach(), pci_detach_device(), pci_find_class(), pci_find_device(), pci_present(), pci_read_config(), pci_read_config8(), pci_read_config16(), pci_read_config32(), pci_rescan_bus(), pci_write_config()
![]() |
![]() |
![]() |