PCI

 

 

 

PCI configuration space

From Wikipedia, the free encyclopedia

Contents

  [hide]

[edit]Technical information

One of the major improvements the PCI Local Bus had over other I/O architectures was its configuration mechanism. In addition to the normal memory-mapped and I/O port spaces, each device on the bus has a configuration space. This is 256 bytes that are addressable by knowing the 8-bit PCI bus, 5-bit device, and 3-bit function numbers for the device (commonly referred to as the BDF). This allows up to 256 buses, each with up to 32 devices, each supporting 8 functions. A single PCI expansion card can respond as a device and must implement at least function number zero. The first 64 bytes of configuration space are standardized; the remainder are available for vendor-defined purposes.

In order to allow more parts of configuration space to be standardized without conflicting with existing uses, there can be a list of capabilities defined within the first 192 bytes of PCI configuration space. Each capability has one byte that describes which capability it is, and one byte to point to the next capability. The number of additional bytes depends on the capability ID. If capabilities are being used, a bit in the Status register is set, and a pointer to the first in a linked list of capabilities is provided in the Cap. pointer register defined in the Standardized Registers.

PCI-X 2.0 introduced an extended configuration space, up to 4096 bytes. The only standardized part of extended configuration space is the first 4 bytes at 0x100 which are the start of an extended capability list. Extended capabilities are very much like normal capabilities except that they can refer to any byte in the extended configuration space (by using 12 bits instead of 8), have a 4-bit version number and a 16-bit capability ID. Extended capability IDs overlap with normal capability IDs, but there is no chance of confusion as they are in separate lists.

[edit]Standardized registers

Standard registers of PCI Type 0 (Non-Bridge) Configuration Space Header

The Vendor ID and Device ID registers identify the device, and are commonly called the PCI ID. The 16-bit vendor ID is allocated by the PCI-SIG. The 16-bit device ID is then assigned by the vendor. There is an ongoing project to collect all known Vendor and Device IDs. (See external links (below).)

The Subsystem Vendor ID and the Subsystem Device ID further identify the device. The Vendor ID is that of the chip manufacturer, and the Subsystem Vendor ID is that of the card manufacturer. The Subsystem Device ID is assigned by the subsystem vendor, but is assigned from the same number space as the Device ID.

The Status register is used to report which features are supported and whether certain kinds of error have occurred.

The Command register contains a bitmask of features that can be individually enabled and disabled.

The Cache Line Size register must be programmed before the device is told it can use the memory-write-and-invalidate transaction. This should normally match the CPU's cache line size, but the correct setting is system dependent.

[edit]Bus enumeration

In order to address a PCI device it must be mapped into the I/O port address space or the memory mapped address space of the system. The systems firmware/device drivers or the OS will program the Base Address Registers (commonly called BARs) to inform the device of its address mapping by writing configuration commands to the PCI controller. Because all PCI devices are in an inactive state upon system reset, they will not have any addresses assigned to them by which the operating system or device drivers can communicate with them. Either the BIOS or the operating system geographically addresses the PCI slots (e.g. the first PCI slot, the second PCI slot, or the third PCI slot, etc., on the motherboard) through the PCI controller using the per slot IDSEL signals.

Since there is no direct method for the BIOS or OS to determine which PCI slots have devices installed (nor the functions the device implements) the PCI bus(es) must be enumerated. Bus enumeration is performed by attempting to read the Vendor- and Device ID register for each combination of bus number and device number, at the device's function #0.

If there is no device that implements the function zero (ie. vendor and device ID registers), the bus master performs an abort and returns all 1s in binary (hexadecimal FFFFFFFF). All ones is an invalid VID/DID value, thus a device driver can tell that the specified combination bus/device/function (B/D/F) does not exist. So, when a read to a function ID of zero for given bus/device causes the master (initiator) to abort, it must then be presumed that no working device exists on that bus because devices are required to implement function number zero. In this case, reads to the remaining functions numbers (1–7) are not necessary as they also will not exist.

When a read to a specified BDF combination vendor ID register succeeds, the BIOS or OS knows it exists, and can then program the memory mapped and I/O port addresses the function will respond to into the devices' BAR configuration register. These addresses stay valid as long as the system remains turned on. On power off, all these settings are lost and on the next system boot, the configuration procedure is repeated all over again. Since this entire process is fully automated, the computer user is spared the task of configuring any newly added hardware manually by modifying settings of dip switches on the cards themselves. This is how plug and play is implemented.

If a PCI to PCI bridge is found, the system must assign the secondary PCI bus beyond the bridge a bus number other than 0, and then enumerate the devices on that secondary bus.

Each non-bridge PCI device can implement up to 6 BARs, each of which can respond to different addresses in I/O port and memory mapped address space. Each BAR describes a region[1][2]:

PCI BAR Bits
BitsDescriptionValues
For all PCI BARs
0Region Type0 = Memory
1 = I/O (deprecated)
For Memory BARs
2-1Locatable0 = any 32-bit
1 = < 1MiB
2 = any 64-bit
3Prefetchable0 = no
1 = yes
31-4Base Address16-byte aligned
For I/O BARs (Deprecated)
1Reserved 
31-2Base Address4-byte aligned

A device can have a ROM which can contain driver code or configuration information.

[edit]Hardware implementation

When performing a configuration space access, a PCI device does not decode the address to determine if it should respond, but instead looks at the signal IDSEL. There is a system-wide unique activation method for each IDSEL signal. The IDSEL is different for each PCI device/adapter slot. Further, the device is required to decode only the lowest order 11 bits of the address space (AD10 to AD0) address/data signals, and can ignore the high order 21 A/D signals [AD[31] – AD[11]) completely.

Thus typically, an implementation has each slot's IDSEL pin connected to a different address/data line AD[11] through AD[31]. To configure the card in slot n, the PCI bus bridge performs a configuration-space access cycle with the PCI devices register to be addressed on lines AD[7:2] (AD[1:0] are always zero since registers are double words (32-bits)), and the PCI function number specified on bits AD[10:8], with all higher-order bits zeros except for AD[n+11] being used as the IDSEL signal on a given slot.

To reduce electrical loading on the timing critical (and thus loading sensitive) AD[] bus, usually the IDSEL signal on the slot connector is connected to an AD[n+11] through a resistor. This causes the IDSEL signal to get to its active condition more slowly than other PCI bus signals (due to the RC time constant of the resistor and the IDSEL pin's input capacitance), so configuration space accesses are performed more slowly to allow time for the IDSEL signal to reach a valid level.

The scanning on the bus is performed on the Intel platform by accessing two defined standardized ports. These ports are the Configuration Space Address (CF8h)I/O port and Configuration Space Data (CFCh) I/O port. The value written to the Configuration Space Address I/O port is created by combining D/B/F values and the registers address value into a 32-bit word.

[edit]Software implementation

Configuration reads and writes can be initiated from the CPU in two ways: one legacy method via I/O addresses 0xCF8 and 0xCFC, and another called memory mapped configuration.

The legacy method was present in the original PCI, and it is called Configuration Access Mechanism (CAM). It allows for 256 bytes of a device's address space to be reached indirectly via two registers called PCI CONFIG_ADDRESS and PCI CONFIG_DATA. These registers live at addresses 0xCF8 and 0xCFC in the x86 I/O address space. For example, a software driver (firmware, OS kernel or kernel driver) can use these registers to configure a PCI device by putting the data that is supposed to be written to the device into CONFIG_DATA, and by writing the address of the device's register into CONFIG_ADDRESS. Since this process requires one to write to a register in order to write the device’s register, and it is referred to as "indirection."

The format of CONFIG_ADDRESS is the following:

bus << 16  |  device << 11  |  function <<  8  |  offset

As explained previously, addressing a device via Bus, Device, and Function (BDF) is also referred to as "addressing a device geographically." See arch/i386/pci/early.c in the Linux Kernel code for an example of code that uses geographical addressing.

The second method was created for PCI Express. It is called Enhanced Configuration Access Mechanism (ECAM). It extends device's configuration space to 4k, with the bottom 256 bytes overlapping the original (legacy) configuration space in PCI. The section of the addressable space is "stolen" so that the accesses from the CPU don't go to memory but rather reach a given device in the PCI Express fabric. During system initialization, firmware determines the base address for this “stolen” address region and communicates it to the root complex and to the operating system. This communication method is implementation-specific, and not defined in the PCI express specification.

[edit]See also

[edit]External links

 

 

 

PCI

Contents

  [hide]

The PCI Bus

The PCI bus was defined to establish a high performance and low cost local bus that would remain through several generations of products. By combining a transparent upgrade path from 132 MB/s (32-bit at 33 MHz) to 528 MB/s (64-bit at 66 MHz) and both 5 volt and 3.3 volt signaling environments, the PCI bus meets the needs of both low end desktop systems as well as that of high-end LAN servers. The PCI bus component and add-in card interface is processor independent, enabling an efficient transition to future processors, as well as use with multiple processor architectures. The disadvantage of the PCI bus is the limited number of electrical loads it can drive. A single PCI bus can drive a maximum of 10 loads. (Remember when counting the number of loads on the bus, a connector counts as one load and the PCI device counts as another, and sometimes two.)

Configuration Space

The PCI specification provides for totally software driven initialization and configuration of each device (or target) on the PCI Bus via a separate Configuration Address Space. All PCI devices, except host bus bridges, are required to provide 256 bytes of configuration registers for this purpose.

Configuration read/write cycles are used to access the Configuration Space of each target device. A target is selected during a configuration access when its IDSEL signal is asserted. The IDSEL acts as the classic "chip select" signal. During the address phase of the configuration cycle, the processor can address one of 64 32-bit registers within the configuration space by placing the required register number on address lines 2 through 7 (AD[7..2]) and the byte enable lines.

PCI devices are inherently little ENDIAN , meaning all multiple byte fields have the least significant values at the lower addresses. This requires a Big ENDIAN" processor, such as a Power PC, to perform the proper byte-swapping of data read from or written to the PCI device, including any accesses to the Configuration Address Space.

Systems must provide a mechanism that allows access to the PCI configuration space, as most CPUs do not have any such mechanism. This task is usually performed by the Host to PCI Bridge (Host Bridge). Two distinct mechanisms are defined to allow the software to generate the required configuration accesses. Configuration mechanism #1 is the preferred method, while mechanism #2 is provided for backward compatibility. Only configuration mechanism #1 will be described here, as it is the only access mechanism that will be used in the future.

Configuration Mechanism #1

Two 32-bit I/O locations are used, the first location (0xCF8) is named CONFIG_ADDRESS, and the second (0xCFC) is called CONFIG_DATA. CONFIG_ADDRESS specifies the configuration address that is required to be accesses, while accesses to CONFIG_DATA will actually generate the configuration access and will transfer the data to or from the CONFIG_DATA register.

The CONFIG_ADDRESS is a 32-bit register with the format shown in following figure. Bit 31 is an enable flag for determining when accesses to CONFIG_DATA should be translated to configuration cycles. Bits 23 through 16 allow the configuration software to choose a specific PCI bus in the system. Bits 15 through 11 select the specific device on the PCI Bus. Bits 10 through 8 choose a specific function in a device (if the device supports multiple functions). Bits 7 through 2 select the specific 32-bit area in the device's configuration space.

3130 - 2423 - 1615 - 1110 - 87 - 21 - 0
Enable BitReservedBus NumberDevice NumberFunction NumberRegister Number00

The following code segment illustrates the use of configuration mechanism #1. Note that this segment, the functions sysOutLong and sysInLong are assembly language functions that make use of the OUTL and INPL Pentium assembly language instructions.

 unsigned short pciConfigReadWord (unsigned short bus, unsigned short slot,
                                   unsigned short func, unsigned short offset)
 {
    unsigned long address;
    unsigned long lbus = (unsigned long)bus;
    unsigned long lslot = (unsigned long)slot;
    unsigned long lfunc = (unsigned long)func;
    unsigned short tmp = 0;
 
    /* create configuration address as per Figure 1 */
    address = (unsigned long)((lbus << 16) | (lslot << 11) |
              (lfunc << 8) | (offset & 0xfc) | ((UINT32)0x80000000));
 
    /* write out the address */
    sysOutLong (0xCF8, address);
    /* read in the data */
    tmp = (unsigned short)((sysInLong (0xCFC) >> ((offset & 2) * 8)) & 0xffff);
    return (tmp);
 }

When a configuration access attempts to select a device that does not exist, the host bridge will complete the access without error, dropping all data on writes and returning all ones on reads. The following code segment illustrates the read of a non-existent device.

 unsigned short pciCheckVendor(unsigned short bus, unsigned short slot)
 {
    unsigned short vendor,device;
    /* try and read the first configuration register. Since there are no */
    /* vendors that == 0xFFFF, it must be a non-existent device. */
    if ((vendor = pciConfigReadWord(bus,slot,0,0)) != 0xFFFF) {
       device = pciConfigReadWord(bus,slot,0,2);
       . . .
    } return (vendor);
 }

PCI Device Structure

The PCI Specification defines the organization of the 256-byte Configuration Space registers and imposes a specific template for the space. Figures 2 & 3 show the layout of the 256-byte Configuration space. All PCI compliant devices must support the Vendor ID, Device ID, Command and Status, Revision ID, Class Code and Header Type fields. Implementation of the other registers is optional, depending upon the devices functionality.


The following field descriptions are common to all Header Types:

  • Device ID: Identifies the particular device. Where valid IDs are allocated by the vendor.
  • Vendor ID: Identifies the manufacturer of the device. Where valid IDs are allocated by PCI-SIG to ensure uniqueness and 0xFFFF is an invalid value that will be returned on read accesses to Configuration Space registers of non-existent devices.
  • Status: A register used to record status information for PCI bus related events.
  • Command: Provides control over a device's ability to generate and respond to PCI cycles. Where the only functionality guaranteed to be supported by all devices is, when a 0 is written to this register, the device is disconnected from the PCI bus for all accesses except Configuration Space access.
  • Class Code: A read-only register that specifies the type of function the device performs.
  • Subclass: A read-only register that specifies the specific function the device performs.
  • Prog IF: A read-only register that specifies a register-level programming interface the device has, if it has any at all.
  • Revision ID: Specifies a revision identifier for a particular device. Where valid IDs are allocated by the vendor.
  • BIST: Represents that status and allows control of a devices BIST (built-in self test).
  • Header Type: Identifies the layout of the rest of the header begining at byte 0x10 of the header and also specifies whether or not the device has multiple functions. Where a value of 0x00 specifies a general device, a value of 0x01 specifies a PCI-to-PCI bridge, and a value of 0x02 specifies a CardBus bridge. If bit 7 of this register is set, the device has multiple functions; otherwise, it is a single function device.
  • Latency Timer: Specifies the latency timer in units of PCI bus clocks.
  • Cache Line Size: Specifies the system cache line size in word (2-byte) units. A device can limit the number of cacheline sizes it can support, if a unsupported value is written to this field, the device will behave as if a value of 0 was written.

This table is applicable if the Header Type is 00h. (Figure 2)

registerbits 31-24bits 23-16bits 15-8bits 7-0
00Device IDVendor ID
04StatusCommand
08Class codeSubclassProg IFRevision ID
0CBISTHeader typeLatency TimerCache Line Size
10Base address #0 (BAR0)
14Base address #1 (BAR1)
18Base address #2 (BAR2)
1CBase address #3 (BAR3)
20Base address #4 (BAR4)
24Base address #5 (BAR5)
28Cardbus CIS Pointer
2CSubsystem IDSubsystem Vendor ID
30Expansion ROM base address
34ReservedCapabilities Pointer
38Reserved
3CMax latencyMin GrantInterrupt PINInterrupt Line

The following field descriptions apply if the Header Type is 0x00:

  • CardBus CIS Pointer: Points to the Card Information Structure and is used by devices that share silicon between CardBus and PCI.
  • Interrupt Line: Specifies which input of the system interrupt controllers the device's interrupt pin is connected to and is implemented by any device that makes use of an interrupt pin. For the x86 architecture this register corresponds to the PIC IRQ numbers 0-15 (and not I/O APIC IRQ numbers) and a value of 0xFF defines no connection.
  • Interrupt Pin: Specifies which interrupt pin the device uses. Where a value of 0x01 is INTA#, 0x02 is INTB#, 0x03 is INTC#, 0x04 is INTD#, and 0x00 means the device does not use an interrupt pin.
  • Max Latency: A read-only register that specifies how often the device needs access to the PCI bus (in 1/4 microsecond units).
  • Min Grant: A read-only register that specifies the burst period length, in 1/4 microsecond units, that the device needs (assuming a 33 MHz clock rate).
  • Capabilities Pointer: Points to a linked list of new capabilities implemented by the device. Used if bit 4 of the status register (Capabilities List bit) is set to 1. The bottom two bits are reserved and should be masked before the Pointer is used to access the Configuration Space.


This table is applicable if the Header Type is 01h (PCI-to-PCI bridge) (Figure 3)

registerbits 31-24bits 23-16bits 15-8bits 7-0
00Device IDVendor ID
04StatusCommand
08Class codeSubclassProg IFRevision ID
0CBISTHeader typeLatency TimerCache Line Size
10Base address #0 (BAR0)
14Base address #1 (BAR1)
18Secondary Latency TimerSubordinate Bus NumberSecondary Bus NumberPrimary Bus Number
1CSecondary StatusI/O LimitI/O Base
20Memory LimitMemory Base
24Prefetchable Memory LimitPrefetchable Memory Base
28Prefetchable Base Upper 32 Bits
2CPrefetchable Limit Upper 32 Bits
30I/O Limit Upper 16 BitsI/O Base Upper 16 Bits
34ReservedCapability Pointer
38Expansion ROM base address
3CBridge ControlInterrupt PINInterrupt Line


Here is the layout of the Header Type register:

Bit 7Bits 6 to 0
MFHeader Type

MF - If MF = 1 Then this device has multiple functions.

Header Type - 00h Standard Header - 01h PCI-to-PCI Bridge - 02h CardBus Bridge


Here is the layout of the BIST register:

Bit 7Bit 6Bits 4 and 5Bits 0 to 3
BIST CapableStart BISTReservedCompletion Code

BIST Capable - Will return 1 the device supports BIST.

Start BIST - When set to 1 the BIST is invoked. This bit is reset when BIST completes. If BIST does not complete after 2 seconds the device should be failed by system software.

Completion Code - Will return 0, after BIST execution, if the test completed successfully.

This table is applicable if the Header Type is 02h (PCI-to-CardBus bridge)

registerbits 31-24bits 23-16bits 15-8bits 7-0
00Device IDVendor ID
04StatusCommand
08Class codeSubclassProg IFRevision ID
0CBISTHeader typeLatency TimerCache Line Size
10CardBus Socket/ExCa base address
14Secondary statusReservedOffset of capabilities list
18CardBus latency timerSubordinate bus numberCardBus bus numberPCI bus number
1CMemory Base Address 0
20Memory Limit 0
24Memory Base Address 1
28Memory Limit 1
2CI/O Base Address 0
30I/O Limit 0
34I/O Base Address 1
38I/O Limit 1
3CBridge ControlInterrupt PINInterrupt Line
40Subsystem Vendor IDSubsystem Device ID
4416-bit PC Card legacy mode base address

Here is the layout of the Command register:

Bits 11 to 15Bit 10Bit 9Bit 8Bit 7Bit 6Bit 5Bit 4Bit 3Bit 2Bit 1Bit 0
ReservedInterupt DisableFast Back-to-Back EnableSERR# EnableReservedParity Error ResponseVGA Palette SnoopMemory Write and Invalidate EnableSpecial CyclesBus MasterMemory SpaceI/O Space

Interrupt Disable - If set to 1 the assertion of the devices INTx# signal is disabled; otherwise, assertion of the signal is enabled.

Fast Back-Back Enable - If set to 1 indicates a device is allowed to generate fast back-to-back transactions; otherwise, fast back-to-back transactions are only allowed to the same agent.

SERR# Enable - If set to 1 the SERR# driver is enabled; otherwise, the driver is disabled.

Bit 7 - As of revision 3.0 of the PCI local bus specification this bit is hardwired to 0. In earlier versions of the specification this bit was used by devices and may have been hardwired to 0, 1, or implemented as a read/write bit.

Parity Error Response - If set to 1 the device will take its normal action when a parity error is detected; otherwise, when an error is detected, the device will set bit 15 of the Status register (Detected Parity Error Status Bit), but will not assert the PERR# (Parity Error) pin and will continue operation as normal.

VGA Palette Snoop - If set to 1 the device does not respond to palette register writes and will snoop the data; otherwise, the device will trate palette write accesses like all other accesses.

Memory Write and Invalidate Enable - If set to 1 the device can generate the Memory Write and Invalidate command; otherwise, the Memory Write command must be used.

Special Cycles - If set to 1 the device can monitor Special Cycle operations; otherwise, the device will ignore them.

Bus Master - If set to 1 the device can behave as a bus master; otherwise, the device can not generate PCI accesses.

Memory Space - If set to 1 the device can respond to Memory Space accesses; otherwise, the device's response is disabled.

I/O Space - If set to 1 the device can respond to I/O Space accesses; otherwise, the device's response is disabled.


Here is the layout of the Status register:

Bit 15Bit 14Bit 13Bit 12Bit 11Bits 9 and 10Bit 8Bit 7Bit 6Bit 5Bit 4Bit 3Bits 0 to 2
Detected Parity ErrorSignaled System ErrorReceived Master AbortReceived Target AbortSignaled Target AbortDEVSEL TimingMaster Data Parity ErrorFast Back-to-Back CapableReserved66 MHz CapableCapabilities ListInterrupt StatusReserved

Detected Parity Error - This bit will be set to 1 whenever the device detects a parity error, even if parity error handling is disabled.

Signaled System Error - This bit will be set to 1 whenever the device asserts SERR#.

Received Master Abort - This bit will be set to 1, by a master device, whenever its transaction (except for Special Cycle transactions) is terminated with Master-Abort.

Received Target Abort - This bit will be set to 1, by a master device, whenever its transaction is terminated with Target-Abort.

Signaled Target Abort - This bit will be set to 1 whenever a target device terminates a transaction with Target-Abort.

DEVSEL Timing - Read only bits that represent the slowest time that a device will assert DEVSEL# for any bus command except Configuration Space read and writes. Where a value of 0x00 represents fast timing, a value of 0x01 represents medium timing, and a value of 0x02 represents slow timing.

Master Data Parity Error - This bit is only set when the following conditions are met. The bus agent asserted PERR# on a read or observed an assertion of PERR# on a write, the agent setting the bit acted as the bus master for the operation in which the error occurred, and bit 6 of the Command register (Parity Error Response bit) is set to 1.

Fast Back-to-Back Capable - If set to 1 the device can accept fast back-to-back transactions that are not from the same agent; otherwise, transactions can only be accepted from the same agent.

Bit 6 - As of revision 3.0 of the PCI local bus specification this bit is reserved. In revision 2.1 of the specification this bit was used to indicate whether or not a device supported User Definable Features.

66 Mhz Capable - If set to 1 the device is capable of running at 66 Mhz; otherwise, the device runs at 33 MHz.

Capabilities List - If set to 1 the device implements the pointer for a New Capabilities Linked list at offset 0x34; otherwise, the linked list is not available.

Interrupt Status - Represents the state of the device's INTx# signal. If set to 1 and bit 10 of the Command register (Interrupt Disable bit) is set to 0 the signal will be asserted; otherwise, the signal will be ignored.


Recall that the PCI devices follow little ENDIAN ordering. The lower addresses contain the least significant portions of the field. Software to manipulate this structure must take particular care that the endian-ordering follows the PCI devices, not the CPUs.

Base Address Registers

Base address Registers (or BARs) can be used to hold memory addresses used by the device, or offsets for port addresses. Typically, memory address BARs need to be located in physical ram while I/O space BARs can reside at any memory address (even beyond physical memory). To distinguish between them, you can check the value of the lowest bit. The following tables describe the two types of BARs:

Memory Space BAR Layout
31 - 432 - 10
16-Byte Aligned Base AddressPrefetchableTypeAlways 0

 

I/O Space BAR Layout
31 - 210
4-Byte Aligned Base AddressReservedAlways 1


The Type field of the Memory Space BAR Layout specifies the size of the base register and where in memory it can be mapped. If it has a value of 0x00 then the base register is 32-bits wide and can be mapped anywhere in the 32-bit Memory Space. A value of 0x02 means the base register is 64-bits wide and can be mapped anywhere in the 64-bit Memory Space (A 64-bit base address register consumes 2 of the base address registers available). A value of 0x01 is reserved as of revision 3.0 of the PCI Local Bus Specification. In earlier versions it was used to support memory space below 1MB (16-bit wide base register that can be mapped anywhere in the 16-bit Memory Space).

When you want to retrieve the actual base address of a BAR, be sure to mask the lower bits. For 16-Bit Memory Space BARs, you calculate (BAR[x] & 0xFFF0). For 32-Bit Memory Space BARs, you calculate (BAR[x] & 0xFFFFFFF0). For 64-Bit Memory Space BARs, you calculate ((BAR[x] & 0xFFFFFFF0) + ((BAR[x+1] & 0xFFFFFFFF) << 32)) For I/O Space BARs, you calculate (BAR[x] & 0xFFFFFFFC).

To determine the amount of address space needed by a PCI device, you must save the original value of the BAR, write a value of all 1's to the register, then read it back. The amount of memory can then be determined by masking the information bits, performing a logical NOT, and incrementing the value by 1. The original value of the BAR should then be restored. The BAR register is naturally aligned and as such you can only modify the bits that are set. For example, if a device utilizes 16 MB it will have BAR0 filled with 0xFF000000 (0x01000000 after decoding) and you can only modify the upper 8-bits. [1]

 

Class Codes

The Class Code, Subclass, and Prog IF registers are used to identify the device's type, the device's function, and the device's register-level programming interface, respectively.

The following table represents the possible device types:

Class CodeDescription
0x00Device was built prior definition of the class code field
0x01Mass Storage Controller
0x02Network Controller
0x03Display Controller
0x04Multimedia Controller
0x05Memory Controller
0x06Bridge Device
0x07Simple Communication Controllers
0x08Base System Peripherals
0x09Input Devices
0x0ADocking Stations
0x0BProcessors
0x0CSerial Bus Controllers
0x0DWireless Controllers
0x0EIntelligent I/O Controllers
0x0FSatellite Communication Controllers
0x10Encryption/Decryption Controllers
0x11Data Acquisition and Signal Processing Controllers
0x12 - 0xFEReserved
0xFFDevice does not fit any defined class.


The following table represents the possible device functions

Class CodeSubclassProg IFDescription
0x000x000x00Any device except for VGA-Compatible devices
0x010x00VGA-Compatible Device
0x010x000x00SCSI Bus Controller
0x010x--IDE Controller
0x020x00Floppy Disk Controller
0x030x00IPI Bus Controller
0x040x00RAID Controller
0x050x20ATA Controller (Single DMA)
0x30ATA Controller (Chained DMA)
0x060x00Serial ATA (Direct Port Access)
0x800x00Other Mass Storage Controller
0x020x000x00Ethernet Controller
0x010x00Token Ring Controller
0x020x00FDDI Controller
0x030x00ATM Controller
0x040x00ISDN Controller
0x050x00WorldFip Controller
0x060x--PICMG 2.14 Multi Computing
0x800x00Other Network Controller
0x030x000x00VGA-Compatible Controller
0x018512-Compatible Controller
0x010x00XGA Controller
0x020x003D Controller (Not VGA-Compatible)
0x800x00Other Display Controller
0x040x000x00Video Device
0x010x00Audio Device
0x020x00Computer Telephony Device
0x800x00Other Multimedia Device
0x050x000x00RAM Controller
0x010x00Flash Controller
0x800x00Other Memory Controller
0x060x000x00Host Bridge
0x010x00ISA Bridge
0x020x00EISA Bridge
0x030x00MCA Bridge
0x040x00PCI-to-PCI Bridge
0x01PCI-to-PCI Bridge (Subtractive Decode)
0x050x00PCMCIA Bridge
0x060x00NuBus Bridge
0x070x00CardBus Bridge
0x080x--RACEway Bridge
0x090x40PCI-to-PCI Bridge (Semi-Transparent, Primary)
0x80PCI-to-PCI Bridge (Semi-Transparent, Secondary)
0x0A0x00InfiniBrand-to-PCI Host Bridge
0x800x00Other Bridge Device
0x070x000x00Generic XT-Compatible Serial Controller
0x0116450-Compatible Serial Controller
0x0216550-Compatible Serial Controller
0x0316650-Compatible Serial Controller
0x0416750-Compatible Serial Controller
0x0516850-Compatible Serial Controller
0x0616950-Compatible Serial Controller
0x010x00Parallel Port
0x01Bi-Directional Parallel Port
0x02ECP 1.X Compliant Parallel Port
0x03IEEE 1284 Controller
0xFEIEEE 1284 Target Device
0x020x00Multiport Serial Controller
0x030x00Generic Modem
0x01Hayes Compatible Modem (16450-Compatible Interface)
0x02Hayes Compatible Modem (16550-Compatible Interface)
0x03Hayes Compatible Modem (16650-Compatible Interface)
0x04Hayes Compatible Modem (16750-Compatible Interface)
0x040x00IEEE 488.1/2 (GPIB) Controller
0x050x00Smart Card
0x800x00Other Communications Device
0x080x000x00Generic 8259 PIC
0x01ISA PIC
0x02EISA PIC
0x10I/O APIC Interrupt Controller
0x20I/O(x) APIC Interrupt Controller
0x010x00Generic 8237 DMA Controller
0x01ISA DMA Controller
0x02EISA DMA Controller
0x020x00Generic 8254 System Timer
0x01ISA System Timer
0x02EISA System Timer
0x030x00Generic RTC Controller
0x01ISA RTC Controller
0x040x00Generic PCI Hot-Plug Controller
0x800x00Other System Peripheral
0x090x000x00Keyboard Controller
0x010x00Digitizer
0x020x00Mouse Controller
0x030x00Scanner Controller
0x040x00Gameport Controller (Generic)
0x10Gameport Contrlller (Legacy)
0x800x00Other Input Controller
0x0A0x000x00Generic Docking Station
0x800x00Other Docking Station
0x0B0x000x00386 Processor
0x010x00486 Processor
0x020x00Pentium Processor
0x100x00Alpha Processor
0x200x00PowerPC Processor
0x300x00MIPS Processor
0x400x00Co-Processor
0x0C0x000x00IEEE 1394 Controller (FireWire)
0x10IEEE 1394 Controller (1394 OpenHCI Spec)
0x010x00ACCESS.bus
0x020x00SSA
0x030x00USB (Universal Host Controller Spec)
0x10USB (Open Host Controller Spec
0x20USB2 Host Controller (Intel Enhanced Host Controller Interface)
0x80USB
0xFEUSB (Not Host Controller)
0x040x00Fibre Channel
0x050x00SMBus
0x060x00InfiniBand
0x070x00IPMI SMIC Interface
0x01IPMI Kybd Controller Style Interface
0x02IPMI Block Transfer Interface
0x080x00SERCOS Interface Standard (IEC 61491)
0x090x00CANbus
0x0D0x000x00iRDA Compatible Controller
0x010x00Consumer IR Controller
0x100x00RF Controller
0x110x00Bluetooth Controller
0x120x00Broadband Controller
0x200x00Ethernet Controller (802.11a)
0x210x00Ethernet Controller (802.11b)
0x800x00Other Wireless Controller
0x0E0x000x--I20 Architecture
0x00Message FIFO
0x0F0x010x00TV Controller
0x020x00Audio Controller
0x030x00Voice Controller
0x040x00Data Controller
0x100x000x00Network and Computing Encrpytion/Decryption
0x100x00Entertainment Encryption/Decryption
0x800x00Other Encryption/Decryption
0x110x000x00DPIO Modules
0x010x00Performance Counters
0x100x00Communications Syncrhonization Plus Time and Frequency Test/Measurment
0x200x00Management Card
0x800x00Other Data Acquisition/Signal Processing Controller

 

Disclaimer

This text originates from "Pentium on VME", unknown author, md5sum d292807a3c56881c6faba7a1ecfd4c79. The original document is apparently no longer present on the Web ...

Closest match: [2]

References

  • PCI Local Bus Specification, revision 3.0, PCI Special Interest Group, August 12, 2002

See Also

External Links

 

 

 

PCI bus info and code from a programmer's perspective.

nov 2007 updated for PCIe!
aug 2010 updated again for PCIe!

There are 4 components to the PCI subsytem:

Bus Number  
Device Number
Function Number
Register Number

There are up to 256 available Buses on a PCI system, most commonly all the cards and chips will be located on Bus 0 and Bus 1.
When scanning for hardware, it's a good idea to scan all 256 buses as it won't take that much additional time.

A Device is a physical thing on the PCI bus.  It could be a video card, an ethernet card, a Northbridge, anything.  There is a software maximum of 32 devices that can exist on each bus.  The physical hardware limit is much lower than this due to electrical loading issues, but we won't get into that.
Devices on a motherboard are typically scattered throughout the 32 devices, holes can and will exist. Your software must scan all 32 devices on each bus.

All devices have at least 1 function.  Multi-function devices, such as a combination modem/soundcard will usually have 2 devices, typically numbered 0 and 1.   There are 8 possible functions per device, numbered 0-7.  Any device that has more than 1 function is (hey clever!) called a multi-function device.  Functions start numbering at 0 and work up to 7.  

Every function of a device has 256 eight-bit registers.  Registers 0-3F are defined by the PCI specification and provide a wealth of information about the particular function.  Registers 40-FF are vendor defined and control the properties of the function itself.  Without vendor specific documentation, these registers should probably be left untouched.

A typical PCI function looks like this:

          x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xA xB xC xD xE xF
00000000: B7 10 55 90 17 01 10 02 30 00 00 02 08 50 00 00 
00000010: 81 10 00 00 00 00 00 0C 00 00 00 00 00 00 00 00 
00000020: 00 00 00 00 00 00 00 00 00 00 00 00 B7 10 55 90 
00000030: 00 00 00 00 DC 00 00 00 00 00 00 00 0B 01 0A 0A 
00000040: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
00000050: 00 00 00 00 40 00 00 00 00 00 00 00 00 00 00 00 
00000060: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
00000070: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
00000080: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
00000090: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
000000A0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
000000B0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
000000C0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
000000D0: 00 00 00 00 00 00 00 00 00 00 00 00 01 00 01 F6 
000000E0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
000000F0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00

Registers 0 and 1 are defined by the PCI spec as being the vendor ID.  The vendor ID is a 16bit value, in this case 10B7h 
Register 2 and 3 are the device ID, 9055h in this example.

By looking up the vendor ID number 10b7 in the PCI vendor database you can see this is a 3COM card.  The 9055h is a 3COM generated number which describes what model card this is.

Other registers can tell us it's an Ethernet controller, it's using IRQ 11, uses a base I/O address of 1080h and more.  Refer to a pci specification to get all the details, as those are outside the scope of this document.

 

So, how do you get to all these registers in PCI space?


Accessing these registers is sorta like accessing CMOS memory in that you first send an index value (a pointer to the register you want to access) to the index port, then you read or write the data to/from the data port.  The index is going to be a combination of all 4 above mentioned components, (bus, device, function, register) 

In the x86 world, the index port always located at 0CF8h and the data port is always located at 0CFCh in I/O space.  Most system BIOSes have software interfaces to abstract the index/data port access from you.  I describe both methods below.  Refer to Ralph Brown's interrupt list for details on the BIOS method of reading/writing PCI

 

Before you can get to any PCI function's registers, you should probably make sure the PCI interface exists first!

 

Detecting the PCI bus

you can detect the PCI bus a couple different ways.  the easist one is to call the PCI BIOS interface directly and do an installation check.
note that you can also do a non-80386+ check by issuing this call and only check DX for "CP" (4350h), but when have you ever seen a 286 with a PCI bus?

.386
        mov     ax, 0b101h                       ; interrupt 1a function b101
        int     1ah                              ; will tell us if there is a PCI
        cmp     edx," ICP"                       ; bus on the board.
        jz      yup                              ; EDX=20494350h
        ; nope
yup:

------------------------------------

You can also find the PCI bus using I/O by just doing a quick read to port CFCh.  

	mov	dx, 0cfch			; config data port
	in	eax, dx
	cmp	eax, -1			; FFFFFFFF?
	jz	nope			; something must exist in PCI land
	; yup
nope:

you will simply receive the data from the last PCI operation that was completed.   This is by no means a foolproof method, but can do the job for quick-n-dirty type applications.

 

 

 

finding a device on the PCI bus:

there are 2 ways of finding a PCI device on the bus.  You can either use the PCI BIOS interface call, or direct hardware I/O.
Here's the BIOS way:

INTEL_VENDOR_ID	EQU	8086h			; intel's unique sig #
INTEL_EXP_NIC	EQU	1227h			; sample PCI device etherexpress 10/100 NIC
.386
	mov	ax, 0b102h                      	; interrupt 1a function b102
	mov	dx, INTEL_VENDOR_ID
	mov	cx, INTEL_EXP_NIC
	xor	si, si				; 0=1st device, 1=2nd etc.
	int	1ah                              
	jc	nope

; once returned from this call, BH=bus number, BL=device/function #
nope:

----------------------------------------------------------------
in the above example, SI will normally be zero, unless you are trying to locate the 2nd or more instance of the same PCI device.
(ie, you had 3 PCI intel etherexpress cards installed)

an extremely handy utility for snooping through the PCI bus on your system is a DOS program called PCIVIEW.EXE.  i was able to locate this utility on the net by simply searching forpciview.exe

--------------------------------------------------------------------------------------
the non-BIOS way:  
locating a specific device on the PCI bus requires you to understand how the PCI configuration cycle is broken down.
it's a 32bit value that looks like this:

bit 31=1        (bit is always set for a PCI access)
bits30:24=0 (reserved)
bit 23:16=bus number (0-255)
bits15:11=device # (0-31)
bits10:8=function # (0-7)
bits7:0=register number (0-255)

you send the above bit-encoded value out to the index port (cf8h) and then do a 32bit read from the data port (cfch)
here's how to read the vendor and device ID from a device sitting at bus 0, device 7, function 3.

BUS             EQU     0
DEV             EQU     7
FN              EQU     3
VEN_ID          EQU     0		; vendor ID=PCI regs 0,1
PCI_INDEX       EQU     0CF8h
PCI_DATA        EQU     0CFCh
.386
        mov     ax, 8000h               ; set bit 31 (after shift)
        or      al, BUS                 ; add in bus number
        shl     eax, 16                 
        mov     ax, DEV
        shl     ax, 11                  ; slide device # up to bits 15:11
        mov     al, FN
        or      ah, al                  ; add function into bits 10:8
        mov     al, VEN_ID
        cli
        mov     dx, PCI_INDEX
        out     dx, eax                 ; send our request out
        mov     dx, PCI_DATA            
        in      eax, dx                 ; read back 32bit value.
        sti

 

Remember that PCI registers are 8 bit values.  The above read from PCI_DATA reads a 32bit value, or 4 PCI registers.  In the above example, after the read, EAX = device ID, AX = vendor ID.  
Per the PCI specification, the vendor ID is always registers 0 and 1, and the device ID is registers 2 and 3.
Thus, AL=register 0, AH=register 1, EAL=register 2, EAH=register 3.

 

 

PCIe update:

PCI express did some minor tweaks to the interface. Specifically, they changed the number of config registers from 255 to 4096. The 1st 255 registers still look and feel just like regular PCI registers-in fact, they are also readable and writable using the same methods described above.

The additional registers however, are only available through a memory mapped subsystem, and it's a total pain in the cheeks to get to them. **update, aug 2010, see below!**

For PCIe, it turns out that the *ENTIRE* PCI subsystem has been mapped into a 256MB chunk of system memory. On the 2 machines that I had a chance to play with, this memory map started at phsyical address 0xe0000000. That's way up near the top of 4Gig of memory. I suggest you grab a memory browser/editor that allows you to poke around in memory out there and explore the area for yourself.

At 0xe0000000, you'll see a copy of every PCI(e) register from Bus 0, Device 0, Function 0.
Function 1 follows at 0xe0001000, Function 2 at 0xe0002000, etc, all the way up to Bus 255, Device 31, Function 7. Each PCI function, PCIe or not, is mapped to consume 0x1000 (4k) of space.
(thanks to Lihan Liang for the clarification!)

Any time there was no PCI device, such as BUS 89, Device 9, Function 3, the memory just returns all FF's because nothing is there to respond to the read. To me, it seems like a HUGE waste of memory space, considering that there is already a perfectly good mechanism for accessing PCI, and all they'd need to do is use a couple of the reserved bits in the 32bit index port to allow access to all the extended PCIe registers, but I digress...


Changing any register value here in memory is just like changing them via I/O ports the old way; the memory map is just a mirror of whatever you see through the index and data ports and vice versa.

On your machine, your PCIe memory map might not be at 0xe0000000. How did I find this magic value? This is where the pain in the cheeks starts, with ACPI.

Tucked away in the ACPI Root System Description Table (RSDT) is an entry for the PCI Express memory mapped configuration space base address Description Table, or MCFG for short.

In order to get there, you have to parse the ACPI tables. Here's how to do it:

1) search in memory (real mode) in the BIOS segments 0xE000 or 0xF000 for the byte sequence:
"RSD PTR "
2) add 0x10 to the address that "RSD PTR " is found, to get a 32bit pointer to where the main ACPI RSDT tables are located.
3) You will need to be in protected mode, or unreal mode to access memory to do this next part.
Starting at the 32bit address of the RSDT tables (should be in high memory, my NVidia board put them at 0x7FEF3040) search for the keyword "MCFG" or parse through all the tables until you get to one labeled "MCFG". At offset 0x2c from "MCFG" will be another 32bit pointer to the PCIe memory map. 

My Nvidia board's "MCFG" table looks like this:

4D434647 3C000000 012C4E76 69646961     MCFG<....,Nvidia    
4E564441 41435049 312E3042 4E564441     NVDAACPI1.0BNVDA
00000000 00000000 00000000 000000E0     ...............�
00000000 000000FF 00000000 00000000     ...............

I've got an ACPI dump program (for DOS) here:  http://www.waste.org/~winkles/acpidump although it is out of date and won't dump out the MCFG table, it'll at least point you in the right direction of where to look.


It appeared to me that very few PCIe devices have any additional registers above the 255 that are available through the index and data ports, so getting to them this way appears to a bit of moot point, but I'm sure eventually something will come up, so now you know.




August 2010 update:
Wow, you learn something new every day. Today I learned that PCIe devices also have an index/data pair to allow for clunky old software that can't get access to high memory to still be able to access all 4k of config registers! It turns out that the last 2 DWORDS in config space are actually index/data pairs to allow you to get access to the other registers. So you're technically using an index/data pair of IO writes (CF8/CFC) to now access another index/data pair in PCI config space (F8 and FC)! clever. You will want to check the PCIe specification for details, but you would write the offset of the 32bit config register in PCIe that you want to access in register F8, then read the data out of FC.
I'll post some more information here when i get a chance to see the spec myself... feel free to contact me with questions or comments.
-jeff!

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值