pci.c File Reference

PCI bus. More...

#include <stdint.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <gpxe/tables.h>
#include <gpxe/device.h>
#include <gpxe/pci.h>

Go to the source code of this file.

Functions

 FILE_LICENCE (GPL2_OR_LATER)
static void pcibus_remove (struct root_device *rootdev)
 Remove PCI root bus.
static unsigned long pci_bar (struct pci_device *pci, unsigned int reg)
 Read PCI BAR.
unsigned long pci_bar_start (struct pci_device *pci, unsigned int reg)
 Find the start of a PCI BAR.
static void pci_read_bases (struct pci_device *pci)
 Read membase and ioaddr for a PCI device.
void adjust_pci_device (struct pci_device *pci)
 Enable PCI device.
static int pci_probe (struct pci_device *pci)
 Probe a PCI device.
static void pci_remove (struct pci_device *pci)
 Remove a PCI device.
static int pcibus_probe (struct root_device *rootdev)
 Probe PCI root bus.

Variables

static struct root_driver pci_root_driver
 PCI bus root device driver.
struct root_device pci_root_device __root_device
 PCI bus root device.


Detailed Description

PCI bus.

Definition in file pci.c.


Function Documentation

FILE_LICENCE ( GPL2_OR_LATER   ) 

static void pcibus_remove ( struct root_device rootdev  )  [static]

Remove PCI root bus.

Parameters:
rootdev PCI bus root device

Definition at line 319 of file pci.c.

References device::children, pci_device::dev, root_device::dev, free(), list_del, list_for_each_entry_safe, pci_remove(), and device::siblings.

Referenced by pcibus_probe().

00319                                                           {
00320         struct pci_device *pci;
00321         struct pci_device *tmp;
00322 
00323         list_for_each_entry_safe ( pci, tmp, &rootdev->dev.children,
00324                                    dev.siblings ) {
00325                 pci_remove ( pci );
00326                 list_del ( &pci->dev.siblings );
00327                 free ( pci );
00328         }
00329 }

static unsigned long pci_bar ( struct pci_device pci,
unsigned int  reg 
) [static]

Read PCI BAR.

Parameters:
pci PCI device
reg PCI register number
Return values:
bar Base address register
Reads the specified PCI base address register, including the flags portion. 64-bit BARs will be handled automatically. If the value of the 64-bit BAR exceeds the size of an unsigned long (i.e. if the high dword is non-zero on a 32-bit platform), then the value returned will be zero plus the flags for a 64-bit BAR. Unreachable 64-bit BARs are therefore returned as uninitialised 64-bit BARs.

Definition at line 55 of file pci.c.

References DBG, PCI_BASE_ADDRESS_MEM_TYPE_64, PCI_BASE_ADDRESS_MEM_TYPE_MASK, PCI_BASE_ADDRESS_SPACE, PCI_BASE_ADDRESS_SPACE_MEMORY, and pci_read_config_dword().

Referenced by pci_bar_start(), and pci_read_bases().

00055                                                                           {
00056         uint32_t low;
00057         uint32_t high;
00058 
00059         pci_read_config_dword ( pci, reg, &low );
00060         if ( ( low & (PCI_BASE_ADDRESS_SPACE|PCI_BASE_ADDRESS_MEM_TYPE_MASK) )
00061              == (PCI_BASE_ADDRESS_SPACE_MEMORY|PCI_BASE_ADDRESS_MEM_TYPE_64) ){
00062                 pci_read_config_dword ( pci, reg + 4, &high );
00063                 if ( high ) {
00064                         if ( sizeof ( unsigned long ) > sizeof ( uint32_t ) ) {
00065                                 return ( ( ( uint64_t ) high << 32 ) | low );
00066                         } else {
00067                                 DBG ( "Unhandled 64-bit BAR %08x%08x\n",
00068                                       high, low );
00069                                 return PCI_BASE_ADDRESS_MEM_TYPE_64;
00070                         }
00071                 }
00072         }
00073         return low;
00074 }

unsigned long pci_bar_start ( struct pci_device pci,
unsigned int  reg 
)

Find the start of a PCI BAR.

Parameters:
pci PCI device
reg PCI register number
Return values:
start BAR start address
Reads the specified PCI base address register, and returns the address portion of the BAR (i.e. without the flags).

If the address exceeds the size of an unsigned long (i.e. if a 64-bit BAR has a non-zero high dword on a 32-bit machine), the return value will be zero.

Definition at line 90 of file pci.c.

References pci_bar(), PCI_BASE_ADDRESS_IO_MASK, PCI_BASE_ADDRESS_MEM_MASK, PCI_BASE_ADDRESS_SPACE, and PCI_BASE_ADDRESS_SPACE_MEMORY.

Referenced by amd8111e_probe(), arbel_probe(), bnx2_init_board(), dmfe_probe(), e1000_probe(), e1000e_probe(), efab_probe(), forcedeth_probe(), hermon_probe(), igb_probe(), mtnic_init_pci(), ns83820_probe(), phantom_map_crb(), skge_probe(), sky2_probe(), tg3_probe(), undipci_find_rom(), velocity_get_pci_info(), and vxge_probe().

00090                                                                          {
00091         unsigned long bar;
00092 
00093         bar = pci_bar ( pci, reg );
00094         if ( (bar & PCI_BASE_ADDRESS_SPACE) == PCI_BASE_ADDRESS_SPACE_MEMORY ){
00095                 return ( bar & PCI_BASE_ADDRESS_MEM_MASK );
00096         } else {
00097                 return ( bar & PCI_BASE_ADDRESS_IO_MASK );
00098         }
00099 }

static void pci_read_bases ( struct pci_device pci  )  [static]

Read membase and ioaddr for a PCI device.

Parameters:
pci PCI device
This scans through all PCI BARs on the specified device. The first valid memory BAR is recorded as pci_device::membase, and the first valid IO BAR is recorded as pci_device::ioaddr.

64-bit BARs are handled automatically. On a 32-bit platform, if a 64-bit BAR has a non-zero high dword, it will be regarded as invalid.

Definition at line 114 of file pci.c.

References pci_device::ioaddr, pci_device::membase, pci_bar(), PCI_BASE_ADDRESS_0, PCI_BASE_ADDRESS_5, PCI_BASE_ADDRESS_IO_MASK, PCI_BASE_ADDRESS_MEM_MASK, PCI_BASE_ADDRESS_MEM_TYPE_64, and PCI_BASE_ADDRESS_SPACE_IO.

Referenced by pcibus_probe().

00114                                                       {
00115         unsigned long bar;
00116         int reg;
00117 
00118         for ( reg = PCI_BASE_ADDRESS_0; reg <= PCI_BASE_ADDRESS_5; reg += 4 ) {
00119                 bar = pci_bar ( pci, reg );
00120                 if ( bar & PCI_BASE_ADDRESS_SPACE_IO ) {
00121                         if ( ! pci->ioaddr )
00122                                 pci->ioaddr = 
00123                                         ( bar & PCI_BASE_ADDRESS_IO_MASK );
00124                 } else {
00125                         if ( ! pci->membase )
00126                                 pci->membase =
00127                                         ( bar & PCI_BASE_ADDRESS_MEM_MASK );
00128                         /* Skip next BAR if 64-bit */
00129                         if ( bar & PCI_BASE_ADDRESS_MEM_TYPE_64 )
00130                                 reg += 4;
00131                 }
00132         }
00133 }

void adjust_pci_device ( struct pci_device pci  ) 

Enable PCI device.

Parameters:
pci PCI device
Set device to be a busmaster in case BIOS neglected to do so. Also adjust PCI latency timer to a reasonable value, 32.

Definition at line 143 of file pci.c.

References pci_device::bus, DBG, pci_device::devfn, PCI_COMMAND, PCI_COMMAND_IO, PCI_COMMAND_MASTER, PCI_COMMAND_MEM, PCI_FUNC, PCI_LATENCY_TIMER, pci_read_config_byte(), pci_read_config_word(), PCI_SLOT, pci_write_config_byte(), and pci_write_config_word().

Referenced by a3c90x_probe(), amd8111e_probe(), arbel_probe(), ath5k_probe(), atl1e_probe(), b44_probe(), bnx2_init_board(), dmfe_probe(), e1000_probe(), e1000e_probe(), efab_probe(), forcedeth_probe(), hermon_probe(), ifec_pci_probe(), igb_probe(), linda_probe(), mtd_probe(), mtnic_probe(), myri10ge_pci_probe(), natsemi_probe(), ns83820_probe(), pcnet32_probe(), phantom_probe(), pnic_probe(), rhine_probe(), rtl8169_probe(), rtl818x_probe(), rtl_probe(), sis190_init_board(), sis900_probe(), skge_probe(), sky2_probe(), sundance_probe(), tg3_probe(), tlan_probe(), tulip_probe(), velocity_get_pci_info(), virtnet_probe(), vxge_probe(), and w89c840_probe().

00143                                                   {
00144         unsigned short new_command, pci_command;
00145         unsigned char pci_latency;
00146 
00147         pci_read_config_word ( pci, PCI_COMMAND, &pci_command );
00148         new_command = ( pci_command | PCI_COMMAND_MASTER |
00149                         PCI_COMMAND_MEM | PCI_COMMAND_IO );
00150         if ( pci_command != new_command ) {
00151                 DBG ( "PCI BIOS has not enabled device %02x:%02x.%x! "
00152                       "Updating PCI command %04x->%04x\n", pci->bus,
00153                       PCI_SLOT ( pci->devfn ), PCI_FUNC ( pci->devfn ),
00154                       pci_command, new_command );
00155                 pci_write_config_word ( pci, PCI_COMMAND, new_command );
00156         }
00157 
00158         pci_read_config_byte ( pci, PCI_LATENCY_TIMER, &pci_latency);
00159         if ( pci_latency < 32 ) {
00160                 DBG ( "PCI device %02x:%02x.%x latency timer is unreasonably "
00161                       "low at %d. Setting to 32.\n", pci->bus,
00162                       PCI_SLOT ( pci->devfn ), PCI_FUNC ( pci->devfn ),
00163                       pci_latency );
00164                 pci_write_config_byte ( pci, PCI_LATENCY_TIMER, 32);
00165         }
00166 }

static int pci_probe ( struct pci_device pci  )  [static]

Probe a PCI device.

Parameters:
pci PCI device
Return values:
rc Return status code
Searches for a driver for the PCI device. If a driver is found, its probe() routine is called.

Definition at line 177 of file pci.c.

References pci_device::bus, DBG, pci_device::devfn, pci_device_id::device, pci_device::device, pci_device::driver, pci_device::driver_name, ENOTTY, for_each_table_entry, id, pci_driver::id_count, pci_driver::ids, pci_device::ioaddr, pci_device::irq, pci_device::membase, PCI_ANY_ID, PCI_DRIVERS, PCI_FUNC, PCI_SLOT, pci_driver::probe, pci_device_id::vendor, and pci_device::vendor.

Referenced by pcibus_probe().

00177                                                 {
00178         struct pci_driver *driver;
00179         struct pci_device_id *id;
00180         unsigned int i;
00181         int rc;
00182 
00183         DBG ( "Adding PCI device %02x:%02x.%x (%04x:%04x mem %lx io %lx "
00184               "irq %d)\n", pci->bus, PCI_SLOT ( pci->devfn ),
00185               PCI_FUNC ( pci->devfn ), pci->vendor, pci->device,
00186               pci->membase, pci->ioaddr, pci->irq );
00187 
00188         for_each_table_entry ( driver, PCI_DRIVERS ) {
00189                 for ( i = 0 ; i < driver->id_count ; i++ ) {
00190                         id = &driver->ids[i];
00191                         if ( ( id->vendor != PCI_ANY_ID ) &&
00192                              ( id->vendor != pci->vendor ) )
00193                                 continue;
00194                         if ( ( id->device != PCI_ANY_ID ) &&
00195                              ( id->device != pci->device ) )
00196                                 continue;
00197                         pci->driver = driver;
00198                         pci->driver_name = id->name;
00199                         DBG ( "...using driver %s\n", pci->driver_name );
00200                         if ( ( rc = driver->probe ( pci, id ) ) != 0 ) {
00201                                 DBG ( "......probe failed\n" );
00202                                 continue;
00203                         }
00204                         return 0;
00205                 }
00206         }
00207 
00208         DBG ( "...no driver found\n" );
00209         return -ENOTTY;
00210 }

static void pci_remove ( struct pci_device pci  )  [static]

Remove a PCI device.

Parameters:
pci PCI device

Definition at line 217 of file pci.c.

References pci_device::bus, DBG, pci_device::devfn, pci_device::driver, PCI_FUNC, PCI_SLOT, and pci_driver::remove.

Referenced by pcibus_remove().

00217                                                   {
00218         pci->driver->remove ( pci );
00219         DBG ( "Removed PCI device %02x:%02x.%x\n", pci->bus,
00220               PCI_SLOT ( pci->devfn ), PCI_FUNC ( pci->devfn ) );
00221 }

static int pcibus_probe ( struct root_device rootdev  )  [static]

Probe PCI root bus.

Parameters:
rootdev PCI bus root device
Scans the PCI bus for devices and registers all devices it can find.

Definition at line 231 of file pci.c.

References pci_device::bus, device_description::bus_type, BUS_TYPE_PCI, device::children, device_description::class, pci_device::class, device::desc, root_device::dev, pci_device::dev, pci_device::devfn, device_description::device, pci_device::device, ENOMEM, free(), INIT_LIST_HEAD, pci_device::ioaddr, device_description::ioaddr, device_description::irq, pci_device::irq, list_add, list_del, device_description::location, malloc(), memset(), device::name, NULL, device::parent, PCI_BUSDEVFN, PCI_FUNC, PCI_HEADER_TYPE, PCI_INTERRUPT_LINE, pci_max_bus(), pci_probe(), pci_read_bases(), pci_read_config_byte(), pci_read_config_dword(), PCI_REVISION, PCI_SLOT, PCI_VENDOR_ID, pcibus_remove(), device::siblings, snprintf(), device_description::vendor, and pci_device::vendor.

00231                                                         {
00232         struct pci_device *pci = NULL;
00233         unsigned int max_bus;
00234         unsigned int bus;
00235         unsigned int devfn;
00236         uint8_t hdrtype = 0;
00237         uint32_t tmp;
00238         int rc;
00239 
00240         max_bus = pci_max_bus();
00241         for ( bus = 0 ; bus <= max_bus ; bus++ ) {
00242                 for ( devfn = 0 ; devfn <= 0xff ; devfn++ ) {
00243 
00244                         /* Allocate struct pci_device */
00245                         if ( ! pci )
00246                                 pci = malloc ( sizeof ( *pci ) );
00247                         if ( ! pci ) {
00248                                 rc = -ENOMEM;
00249                                 goto err;
00250                         }
00251                         memset ( pci, 0, sizeof ( *pci ) );
00252                         pci->bus = bus;
00253                         pci->devfn = devfn;
00254                         
00255                         /* Skip all but the first function on
00256                          * non-multifunction cards
00257                          */
00258                         if ( PCI_FUNC ( devfn ) == 0 ) {
00259                                 pci_read_config_byte ( pci, PCI_HEADER_TYPE,
00260                                                        &hdrtype );
00261                         } else if ( ! ( hdrtype & 0x80 ) ) {
00262                                         continue;
00263                         }
00264 
00265                         /* Check for physical device presence */
00266                         pci_read_config_dword ( pci, PCI_VENDOR_ID, &tmp );
00267                         if ( ( tmp == 0xffffffff ) || ( tmp == 0 ) )
00268                                 continue;
00269                         
00270                         /* Populate struct pci_device */
00271                         pci->vendor = ( tmp & 0xffff );
00272                         pci->device = ( tmp >> 16 );
00273                         pci_read_config_dword ( pci, PCI_REVISION, &tmp );
00274                         pci->class = ( tmp >> 8 );
00275                         pci_read_config_byte ( pci, PCI_INTERRUPT_LINE,
00276                                                &pci->irq );
00277                         pci_read_bases ( pci );
00278 
00279                         /* Add to device hierarchy */
00280                         snprintf ( pci->dev.name, sizeof ( pci->dev.name ),
00281                                    "PCI%02x:%02x.%x", bus,
00282                                    PCI_SLOT ( devfn ), PCI_FUNC ( devfn ) );
00283                         pci->dev.desc.bus_type = BUS_TYPE_PCI;
00284                         pci->dev.desc.location = PCI_BUSDEVFN (bus, devfn);
00285                         pci->dev.desc.vendor = pci->vendor;
00286                         pci->dev.desc.device = pci->device;
00287                         pci->dev.desc.class = pci->class;
00288                         pci->dev.desc.ioaddr = pci->ioaddr;
00289                         pci->dev.desc.irq = pci->irq;
00290                         pci->dev.parent = &rootdev->dev;
00291                         list_add ( &pci->dev.siblings, &rootdev->dev.children);
00292                         INIT_LIST_HEAD ( &pci->dev.children );
00293                         
00294                         /* Look for a driver */
00295                         if ( pci_probe ( pci ) == 0 ) {
00296                                 /* pcidev registered, we can drop our ref */
00297                                 pci = NULL;
00298                         } else {
00299                                 /* Not registered; re-use struct pci_device */
00300                                 list_del ( &pci->dev.siblings );
00301                         }
00302                 }
00303         }
00304 
00305         free ( pci );
00306         return 0;
00307 
00308  err:
00309         free ( pci );
00310         pcibus_remove ( rootdev );
00311         return rc;
00312 }


Variable Documentation

struct root_driver pci_root_driver [static]

Initial value:

 {
        .probe = pcibus_probe,
        .remove = pcibus_remove,
}
PCI bus root device driver.

Definition at line 332 of file pci.c.

struct root_device pci_root_device __root_device

Initial value:

 {
        .dev = { .name = "PCI" },
        .driver = &pci_root_driver,
}
PCI bus root device.

Definition at line 338 of file pci.c.


Generated on Tue Apr 6 20:01:16 2010 for gPXE by  doxygen 1.5.7.1