[Previous] [Contents] [Next]

pci_attach_device()

Attach a driver to a PCI device

Synopsis:

#include <hw/pci.h>

void* pci_attach_device( void* handle,
                         uint32_t flags,
                         uint16_t idx,
                         struct pci_dev_info* info );

Library:

libc

Description:

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:

PCI_IS_IO(address)
Test whether the address is an I/O address.
PCI_IS_MEM(address)
Test whether the address is a memory address.
PCI_IO_ADDR(address)
Convert the address returned by the PCI server to an I/O address.
PCI_MEM_ADDR(address)
Convert the address returned by the PCI server to a memory address.
PCI_ROM_ADDR(address)
Convert the address returned by the PCI server to a ROM address.

For example:

{
uint64_t	port;

	if (PCI_IS_IO(addr))	/* The address returned by the pci server */
		port = (PCI_IO_ADDR(addr));
}

Returns:

A handle to be used for other pci_* calls associated with a handle, or NULL if an error occurs.

Errors:

EBUSY
An application has already attached to the device. If it's safe to share the device, specify PCI_SHARE in the flags field.
EINVAL
The function couldn't attach a resource to the device.
ENODEV
This device wasn't found.

Examples:

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;
}

Classification:

QNX 6

Safety:
Cancellation point Yes
Interrupt handler No
Signal handler Yes
Thread Yes

See also:

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()


[Previous] [Contents] [Next]