PCI: Difference between revisions

Clean up whole page
[unchecked revision][unchecked revision]
m (→‎Enabling MSI-X: Capitalize properly)
(Clean up whole page)
Line 12:
 
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 Space Access Mechanism #1 ===
Line 36 ⟶ 35:
| Device Number
| Function Number
| Register Offset¹<sup>1</sup>
|}
¹<sup>1</sup> Register Offset has to point to consecutive DWORDs, ie. bits 1:0 are always 0b00 (they are still part of the Register Offset).
 
The following code segment illustrates the use of configuration mechanism #1 to read 16-bit fields from configuration space. Note that this segment, the outl(port, value) and inl(port) functions refer to the OUTL and INL Pentium assembly language instructions.
 
<source lang="c">
uint16_t pciConfigReadWord (uint8_t bus, uint8_t slot, uint8_t func, uint8_t offset) {
uint32_t address;
uint32_t lbus = (uint32_t)bus;
Line 50 ⟶ 49:
uint16_t tmp = 0;
/*/ createCreate configuration address as per Figure 1 */
address = (uint32_t)((lbus << 16) | (lslot << 11) |
(lfunc << 8) | (offset & 0xfc) | ((uint32_t)0x80000000));
/*/ writeWrite out the address */
outl(0xCF8, address);
/*/ readRead in the data */
/*/ (offset & 2) * 8) = 0 will choose the first word of the 32 bits-bit register */
tmp = (uint16_t)((inl(0xCFC) >> ((offset & 2) * 8)) & 0xffff0xFFFF);
return (tmp);
}
</source>
Line 68 ⟶ 67:
uint16_t pciCheckVendor(uint8_t bus, uint8_t slot) {
uint16_t vendor, device;
/* tryTry 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);
}
</source>
 
 
=== Configuration Space Access Mechanism #2 ===
Line 82 ⟶ 80:
This configuration space access mechanism was deprecated in PCI version 2.0. This means it's only likely to exist on hardware from around 1992 (when PCI 1.0 was introduced) to 1993 (when PCI 2.0 was introduced), which limits it to 80486 and early Pentium motherboards.
 
For access mechanism #2, the IO port at 0x0CF80xCF8 is an 8-bit port and is used to enable/disable the access mechanism and set the function number. It has the following format:
 
{| {{wikitable}}
Line 95 ⟶ 93:
|}
 
The IO port at 0x0CFA0xCFA (the "Forwarding Register") is also an 8-bit port, and is used to set the bus number for subsequent PCI configuration space accesses.
 
Once the access mechanism has been enabled; accesses to IO ports 0xC000 to 0xCFFF are used to access PCI configuration space. The IO port number has the following format:
Line 113 ⟶ 111:
 
Note that this limits the system to 16 devices per PCI bus.
 
 
=== Memory Mapped PCI Configuration Space Access ===
Line 119 ⟶ 116:
PCI Express introduced a new way to access PCI configuration space, where it's simply memory mapped and no IO ports are used. This access mechanism is described in [[PCI Express]].
 
Note that systems that do provide the memory mapped access mechanism are also required to support PCI access mechanism #1 for backwardbackwards compatibility.
 
 
=== Detecting Configuration Space Access Mechanism/s ===
 
In general there are 4 cases:
* computerComputer doesn't support PCI (either the computer is too old, or your OS is being run at some time in the future after PCI has been superseded)
* computerComputer supports mechanism #2
* computerComputer supports mechanism #1 but doesn't support the memory mapped access mechanism
* computerComputer supports both mechanism #1 and the memory mapped access mechanism
 
For BIOS systems, "int 0x1A, AX=0xB101 (PCI BIOS presence check)" will tell you if the system uses mechanism #1 or mechanism #2. If this function doesn't exist you can't be sure if the computer supports PCI or not. If it says mechanism #1 is supported you won't know if the memory mapped access mechanism is also supported or not.
Line 136 ⟶ 132:
For both BIOS and UEFI systems, you can check the ACPI tables to determine if the memory mapped access mechanism is supported.
 
This leaves a few cases uncovered (e.g. where you don't know if whether mechanism #1 or #2 are supported despite trying all of the above). For these cases the only option left is manual probing. This means 2 specific tests - whether mechanism #1 is supported, and if not whether mechanism #2 is supported. Please note that manual probing has risks; in that if there is no PCI (e.g. the system only has ISA) the IO port accesses might cause undefined behaviour (especially on systems where the ISA bus ignores highest 6 bits of the IO port address, where accessing IO port 0x0CF8 is the same as accessing IO port 0x00F80xF8).
 
 
=== 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.
 
 
==== Common Header Fields ====
Line 157 ⟶ 151:
* ''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 beginning at byte 0x10 of the header and also specifies whether or not the device has multiple functions. Where a value of 0x000x0 specifies a general device, a value of 0x010x1 specifies a PCI-to-PCI bridge, and a value of 0x020x2 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 32-bit 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.
 
==== Header Type 0x0 ====
 
====This table is applicable if the Header Type 0x00is 0x0. (Figure ====2)
 
This table is applicable if the Header Type is 00h. (Figure 2)
{| {{wikitable}}
|-
! registerRegister !! offsetOffset !! bitsBits 31-24 !! bitsBits 23-16 !! bitsBits 15-8 !! bitsBits 7-0
|-
| 000x0
| 000x0
| colspan="2" | Device ID
| colspan="2" | Vendor ID
|-
| 010x1
| 040x4
| colspan="2" | Status
| colspan="2" | Command
|-
| 020x2
| 080x8
| Class code || Subclass || Prog IF || Revision ID
|-
| 030x3
| 0C0xC
| BIST
| Header type
Line 190 ⟶ 183:
| Cache Line Size
|-
| 040x4
| 100x10
| colspan="4" | Base address #0 (BAR0)
|-
| 050x5
| 140x14
| colspan="4" | Base address #1 (BAR1)
|-
| 060x6
| 180x18
| colspan="4" | Base address #2 (BAR2)
|-
| 070x7
| 1C0x1C
| colspan="4" | Base address #3 (BAR3)
|-
| 080x8
| 200x20
| colspan="4" | Base address #4 (BAR4)
|-
| 090x9
| 240x24
| colspan="4" | Base address #5 (BAR5)
|-
| 0A0xA
| 280x28
| colspan="4" | Cardbus CIS Pointer
|-
| 0B0xB
| 2C0x2C
| colspan="2" | Subsystem ID
| colspan="2" | Subsystem Vendor ID
|-
| 0C0xC
| 300x30
| colspan="4" | Expansion ROM base address
|-
| 0D0xD
| 340x34
| colspan="3" | Reserved
| colspace="1" | Capabilities Pointer
|-
| 0E0xE
| 380x38
| colspan="4" | Reserved
|-
| 0F0xF
| 3C0x3C
| Max latency || Min Grant || Interrupt PIN || Interrupt Line
|}
 
The following field descriptions apply if the Header Type is 0x000x0:
 
* ''CardBus CIS Pointer:'' Points to the Card Information Structure and is used by devices that share silicon between CardBus and PCI.
Line 247 ⟶ 240:
* ''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 0x010x1 is INTA#, 0x020x2 is INTB#, 0x030x3 is INTC#, 0x040x4 is INTD#, and 0x000x0 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).
Line 255 ⟶ 248:
* ''Capabilities Pointer:'' Points (i.e. an offset into this function's configuration space) 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 01h0x1 (PCI-to-PCI bridge) (Figure 3)====
 
====This table is applicable if the Header Type 0x01is 0x1 (PCI-to-PCI bridge) ====(Figure 3)
 
This table is applicable if the Header Type is 01h (PCI-to-PCI bridge) (Figure 3)
 
{| {{wikitable}}
|-
! registerRegister !! offsetOffset !! bitsBits 31-24 !! bitsBits 23-16 !! bitsBits 15-8 !! bitsBits 7-0
|-
| 000x0
| 000x0
| colspan="2" | Device ID
| colspan="2" | Vendor ID
|-
| 010x1
| 040x4
| colspan="2" | Status
| colspan="2" | Command
|-
| 020x2
| 080x8
| Class code || Subclass || Prog IF || Revision ID
|-
| 030x3
| 0C0xC
| BIST
| Header type
Line 285 ⟶ 277:
| Cache Line Size
|-
| 040x4
| 100x10
| colspan="4" | Base address #0 (BAR0)
|-
| 050x5
| 140x14
| colspan="4" | Base address #1 (BAR1)
|-
| 060x6
| 180x18
| Secondary Latency Timer
| Subordinate Bus Number
Line 300 ⟶ 292:
| Primary Bus Number
|-
| 070x7
| 1C0x1C
| colspan="2" | Secondary Status
| I/O Limit
| I/O Base
|-
| 080x8
| 200x20
| colspan="2" | Memory Limit
| colspan="2" | Memory Base
|-
| 090x9
| 240x24
| colspan="2" | Prefetchable Memory Limit
| colspan="2" | Prefetchable Memory Base
|-
| 0A0xA
| 280x28
| colspan="4" | Prefetchable Base Upper 32 Bits
|-
| 0B0xB
| 2C0x2C
| colspan="4" | Prefetchable Limit Upper 32 Bits
|-
| 0C0xC
| 300x30
| colspan="2" | I/O Limit Upper 16 Bits
| colspan="2" | I/O Base Upper 16 Bits
|-
| 0D0xD
| 340x34
| colspan="3" | Reserved
| Capability Pointer
|-
| 0E0xE
| 380x38
| colspan="4" | Expansion ROM base address
|-
| 0F0xF
| 3C0x3C
| colspan="2" | Bridge Control || Interrupt PIN || Interrupt Line
|}
Line 349 ⟶ 341:
{| {{wikitable}}
|-
! Bit 7 !! Bits 6 to -0
|-
| MF
Line 356 ⟶ 348:
 
* ''MF'' - If MF = 1 Then this device has multiple functions.
* ''Header Type'' - 00h0x0 Standard Header - 01h0x1 PCI-to-PCI Bridge - 02h0x2 CardBus Bridge
 
===== BIST Register =====
Line 364 ⟶ 356:
{| {{wikitable}}
|-
! Bit 7 !! Bit 6 !! Bits 4 and -5 !! Bits 0 to -3
|-
| BIST Capable || Start BIST || Reserved || Completion Code
Line 373 ⟶ 365:
* ''Completion Code'' - Will return 0, after BIST execution, if the test completed successfully.
 
This table is applicable if the==== Header Type is 02h0x2 (PCI-to-CardBus bridge) ====
 
====This table is applicable if the Header Type 0x02is 0x2 (PCI-to-CardBus bridge) ====
 
This table is applicable if the Header Type is 02h (PCI-to-CardBus bridge)
 
{| {{wikitable}}
|-
! registerRegister !! offsetOffset !! bitsBits 31-24 !! bitsBits 23-16 !! bitsBits 15-8 !! bitsBits 7-0
|-
| 000x0
| 000x0
| colspan="2" | Device ID
| colspan="2" | Vendor ID
|-
| 010x1
| 040x4
| colspan="2" | Status
| colspan="2" | Command
|-
| 020x2
| 080x8
| Class code || Subclass || Prog IF || Revision ID
|-
| 030x3
| 0C0xC
| BIST
| Header type
Line 403 ⟶ 394:
| Cache Line Size
|-
| 040x4
| 100x10
| colspan="4" | CardBus Socket/ExCa base address
|-
| 050x5
| 140x14
| colspan="2" | Secondary status
| Reserved
| Offset of capabilities list
|-
| 060x6
| 180x18
| CardBus latency timer
| Subordinate bus number
Line 420 ⟶ 411:
| PCI bus number
|-
| 070x7
| 1C0x1C
| colspan="4" | Memory Base Address 0
|-
| 080x8
| 200x20
| colspan="4" | Memory Limit 0
|-
| 090x9
| 240x24
| colspan="4" | Memory Base Address 1
|-
| 0A0xA
| 280x28
| colspan="4" | Memory Limit 1
|-
| 0B0xB
| 2C0x2C
| colspan="4" | I/O Base Address 0
|-
| 0C0xC
| 300x30
| colspan="4" | I/O Limit 0
|-
| 0D0xD
| 340x34
| colspan="4" | I/O Base Address 1
|-
| 0E0xE
| 380x38
| colspan="4" | I/O Limit 1
|-
| 0F0xF
| 3C0x3C
| colspan="2" | Bridge Control
| Interrupt PIN
| Interrupt Line
|-
| 100x10
| 400x40
| colspan="2" | Subsystem Vendor ID
| colspan="2" | Subsystem Device ID
|-
| 110x11
| 440x44
| colspan="4" | 16-bit PC Card legacy mode base address
|}
Line 474 ⟶ 465:
{| {{wikitable}}
|-
! Bits 11 to -15 !! Bit 10 !! Bit 9 !! Bit 8 !! Bit 7 !! Bit 6 !! Bit 5 !! Bit 4 !! Bit 3 !! Bit 2 !! Bit 1 !! Bit 0
|-
| Reserved
Line 510 ⟶ 501:
{| {{wikitable}}
|-
! Bit 15 !! Bit 14 !! Bit 13 !! Bit 12 !! Bit 11 !! Bits 9 and -10 !! Bit 8 !! Bit 7 !! Bit 6 !! Bit 5 !! Bit 4 !! Bit 3 !! Bits 0 to -2
|-
| Detected Parity Error
Line 535 ⟶ 526:
* ''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 localLocal busBus 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 ===
Line 561 ⟶ 550:
| Always 0
|}
 
 
{|{{wikitable}}
Line 575 ⟶ 563:
|}
 
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 0x000x0 then the base register is 32-bits wide and can be mapped anywhere in the 32-bit Memory Space. A value of 0x020x2 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 0x010x1 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-Bitbit Memory Space BARs, you calculate <code>(BAR[x] & 0xFFF0)</code>. For 32-Bitbit Memory Space BARs, you calculate <code>(BAR[x] & 0xFFFFFFF0)</code>. For 64-Bitbit Memory Space BARs, you calculate <code>((BAR[x] & 0xFFFFFFF0) + ((BAR[x + 1] & 0xFFFFFFFF) << 32))</code> For I/O Space BARs, you calculate <code>(BAR[x] & 0xFFFFFFFC)</code>.
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).
 
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 bitwise NOT ('~' in C), 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 (0x010000000x1000000 after decoding) and you can only modify the upper 8-bits. [httphttps://web.archive.org/web/20150101180929/https://www.pcisig.com/reflector/msg05233.html]
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 bitwise NOT ('~' in C), 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. [http://www.pcisig.com/reflector/msg05233.html]
 
When a base address register is marked as Prefetchable, it means that the region does not have read side effects (reading from that memory range doesn't change any state), and it is allowed for the CPU to cache loads from that memory region and read it in bursts (typically cache line sized). Hardware is also allowed to merge repeated stores to the same address into one store of the latest value. If you are using paging and want maximum performance, you should map prefetchable MMIO regions as WT (write-through) instead of UC (uncacheable). On x86, frame buffers are the exception, they should be almost always be mapped WC (write-combining).
 
 
=== Class Codes ===
Line 595 ⟶ 581:
! Class Code !! Subclass !! Prog IF
|-
| rowspan="2" | 0x000x0 - Unclassified
| 0x000x0 - Non-VGA-Compatible Unclassified Device || --
|-
| 0x010x1 - VGA-Compatible Unclassified Device || --
|-
| rowspan="22" | 0x010x1 - Mass Storage Controller
| 0x000x0 - SCSI Bus Controller || --
|-
| rowspan="8" | 0x010x1 - IDE Controller
| 0x000x0 - ISA Compatibility mode-only controller
|-
| 0x050x5 - PCI native mode-only controller
|-
| 0x0A0xA - ISA Compatibility mode controller, supports both channels switched to PCI native mode
|-
| 0x0F0xF - PCI native mode controller, supports both channels switched to ISA compatibility mode
|-
| 0x80 - ISA Compatibility mode-only controller, supports bus mastering
Line 620 ⟶ 606:
| 0x8F - PCI native mode controller, supports both channels switched to ISA compatibility mode, supports bus mastering
|-
| 0x020x2 - Floppy Disk Controller || --
|-
| 0x030x3 - IPI Bus Controller || --
|-
| 0x040x4 - RAID Controller || --
|-
| rowspan="2" | 0x050x5 - ATA Controller
| 0x20 - Single DMA
|-
| 0x30 - Chained DMA
|-
| rowspan="3" | 0x060x6 - Serial ATA Controller
| 0x000x0 - Vendor Specific Interface
|-
| 0x010x1 - AHCI 1.0
|-
| 0x020x2 - Serial Storage Bus
|-
| rowspan="2" | 0x070x7 - Serial Attached SCSI Controller
| 0x000x0 - SAS
|-
| 0x010x1 - Serial Storage Bus
|-
| rowspan="2" | 0x080x8 - Non-Volatile Memory Controller
| 0x010x1 - NVMHCI
|-
| 0x020x2 - NVM Express
|-
| 0x80 - Other || --
|-
| rowspan="10" | 0x020x2 - Network Controller
| 0x000x0 - Ethernet Controller || --
|-
| 0x010x1 - Token Ring Controller || --
|-
| 0x020x2 - FDDI Controller || --
|-
| 0x030x3 - ATM Controller || --
|-
| 0x040x4 - ISDN Controller || --
|-
| 0x050x5 - WorldFip Controller || --
|-
| 0x060x6 - PICMG 2.14 Multi Computing Controller || --
|-
| 0x070x7 - Infiniband Controller || --
|-
| 0x080x8 - Fabric Controller || --
|-
| 0x80 - Other || --
|-
| rowspan="5" | 0x030x3 - Display Controller
| rowspan="2" | 0x000x0 - VGA Compatible Controller
| 0x000x0 - VGA Controller
|-
| 0x010x1 - 8514-Compatible Controller
|-
| 0x010x1 - XGA Controller || --
|-
| 0x020x2 - 3D Controller (Not VGA-Compatible) || --
|-
| 0x80 - Other || --
|-
| rowspan="5" | 0x040x4 - Multimedia Controller
| 0x000x0 - Multimedia Video Controller || --
|-
| 0x010x1 - Multimedia Audio Controller || --
|-
| 0x020x2 - Computer Telephony Device || --
|-
| 0x030x3 - Audio Device || --
|-
| 0x80 - Other || --
|-
| rowspan="3" | 0x050x5 - Memory Controller
| 0x000x0 - RAM Controller || --
|-
| 0x010x1 - Flash Controller || --
|-
| 0x80 - Other || --
|-
| rowspan="15" | 0x060x6 - Bridge
| 0x000x0 - Host Bridge || --
|-
| 0x010x1 - ISA Bridge || --
|-
| 0x020x2 - EISA Bridge || --
|-
| 0x030x3 - MCA Bridge || --
|-
| rowspan="2" | 0x040x4 - PCI-to-PCI Bridge
| 0x000x0 - Normal Decode
|-
| 0x010x1 - Subtractive Decode
|-
| 0x050x5 - PCMCIA Bridge || --
|-
| 0x060x6 - NuBus Bridge || --
|-
| 0x070x7 - CardBus Bridge || --
|-
| rowspan="2" | 0x080x8 - RACEway Bridge
| 0x000x0 - Transparent Mode
|-
| 0x010x1 - Endpoint Mode
|-
| rowspan="2" | 0x090x9 - PCI-to-PCI Bridge
| 0x40 - Semi-Transparent, Primary bus towards host CPU
|-
Line 735 ⟶ 721:
| 0x80 - Other || --
|-
| rowspan="21" | 0x070x7 - Simple Communication Controller
| rowspan="7" | 0x000x0 - Serial Controller
| 0x000x0 - 8250-Compatible (Generic XT)
|-
| 0x010x1 - 16450-Compatible
|-
| 0x020x2 - 16550-Compatible
|-
| 0x030x3 - 16650-Compatible
|-
| 0x040x4 - 16750-Compatible
|-
| 0x050x5 - 16850-Compatible
|-
| 0x060x6 - 16950-Compatible
|-
| rowspan="5" | 0x010x1 - Parallel Controller
| 0x000x0 - Standard Parallel Port
|-
| 0x010x1 - Bi-Directional Parallel Port
|-
| 0x020x2 - ECP 1.X Compliant Parallel Port
|-
| 0x030x3 - IEEE 1284 Controller
|-
| 0xFE - IEEE 1284 Target Device
|-
| 0x020x2 - Multiport Serial Controller || --
|-
| rowspan="5" | 0x030x3 - Modem
| 0x000x0 - Generic Modem
|-
| 0x010x1 - Hayes 16450-Compatible Interface
|-
| 0x020x2 - Hayes 16550-Compatible Interface
|-
| 0x030x3 - Hayes 16650-Compatible Interface
|-
| 0x040x4 - Hayes 16750-Compatible Interface
|-
| 0x040x4 - IEEE 488.1/2 (GPIB) Controller || --
|-
| 0x050x5 - Smart Card Controller || --
|-
| 0x80 - Other || --
|-
| rowspan="18" | 0x080x8 - Base System Peripheral
| rowspan="5" | 0x000x0 - PIC
| 0x000x0 - Generic 8259-Compatible
|-
| 0x010x1 - ISA-Compatible
|-
| 0x020x2 - EISA-Compatible
|-
| 0x10 - I/O APIC Interrupt Controller
Line 809 ⟶ 795:
| 0x03 - HPET
|-
| rowspan="2" | 0x030x3 - RTC Controller
| 0x000x0 - Generic RTC
|-
| 0x010x1 - ISA-Compatible
|-
| 0x040x4 - PCI Hot-Plug Controller || --
|-
| 0x050x5 - SD Host controller || --
|-
| 0x060x6 - IOMMU || --
|-
| 0x80 - Other || --
|-
| rowspan="7" | 0x090x9 - Input Device Controller
| 0x000x0 - Keyboard Controller || --
|-
| 0x010x1 - Digitizer Pen || --
|-
| 0x020x2 - Mouse Controller || --
|-
| 0x030x3 - Scanner Controller || --
|-
| rowspan="2" | 0x040x4 - Gameport Controller
| 0x000x0 - Generic
|-
| 0x10 - Extended
Line 838 ⟶ 824:
| 0x80 - Other || --
|-
| rowspan="2" | 0x0A0xA - Docking Station
| 0x000x0 - Generic || --
|-
| 0x80 - Other || --
|-
| rowspan="9" | 0x0B0xB - Processor
| 0x000x0 - 386 || --
|-
| 0x010x1 - 486 || --
|-
| 0x020x2 - Pentium || --
|-
| 0x030x3 - Pentium Pro || --
|-
| 0x10 - Alpha || --
Line 862 ⟶ 848:
| 0x80 - Other || --
|-
| rowspan="19" | 0x0C0xC - Serial Bus Controller
| rowspan="2" | 0x000x0 - FireWire (IEEE 1394) Controller
| 0x000x0 - Generic
|-
| 0x10 - OHCI
|-
| 0x010x1 - ACCESS Bus Controller || --
|-
| 0x020x2 - SSA || --
|-
| rowspan="6" | 0x030x3 - USB Controller
| 0x000x0 - UHCI Controller
|-
| 0x10 - OHCI Controller
Line 885 ⟶ 871:
| 0xFE - USB Device (Not a host controller)
|-
| 0x040x4 - Fibre Channel || --
|-
| 0x050x5 - SMBus Controller || --
|-
| 0x060x6 - InfiniBand Controller || --
|-
| rowspan="3" | 0x070x7 - IPMI Interface
| 0x000x0 - SMIC
|-
| 0x010x1 - Keyboard Controller Style
|-
| 0x020x2 - Block Transfer
|-
| 0x080x8 - SERCOS Interface (IEC 61491) || --
|-
| 0x090x9 - CANbus Controller || --
|-
| 0x80 - Other || --
|-
| rowspan="8" | 0x0D0xD - Wireless Controller
| 0x000x0 - iRDA Compatible Controller || --
|-
| 0x010x1 - Consumer IR Controller || --
|-
| 0x10 - RF Controller || --
Line 921 ⟶ 907:
| 0x80 - Other || --
|-
| 0x0E0xE - Intelligent Controller || 0x000x0 - I20 || --
|-
| rowspan="4" | 0x0F0xF - Satellite Communication Controller
| 0x010x1 - Satellite TV Controller || --
|-
| 0x020x2 - Satellite Audio Controller || --
|-
| 0x030x3 - Satellite Voice Controller || --
|-
| 0x040x4 - Satellite Data Controller || --
|-
| rowspan="3" | 0x10 - Encryption Controller
| 0x000x0 - Network and Computing Encrpytion/Decryption || --
|-
| 0x10 - Entertainment Encryption/Decryption || --
Line 940 ⟶ 926:
|-
| rowspan="5" | 0x11 - Signal Processing Controller
| 0x000x0 - DPIO Modules || --
|-
| 0x010x1 - Performance Counters || --
|-
| 0x10 - Communication Synchronizer || --
Line 975 ⟶ 961:
 
vendorID = getVendorID(bus, device, function);
if (vendorID == 0xFFFF) return; // Device doesn't exist
checkFunction(bus, device, function);
headerType = getHeaderType(bus, device, function);
if( (headerType & 0x80) != 0) {
/*/ It is's a multi-function device, so check remaining functions */
for (function = 1; function < 8; function++) {
if (getVendorID(bus, device, function) != 0xFFFF) {
checkFunction(bus, device, function);
}
Line 1,003 ⟶ 989:
uint8_t device;
 
for (bus = 0; bus < 256; bus++) {
for (device = 0; device < 32; device++) {
checkDevice(bus, device);
}
Line 1,021 ⟶ 1,007:
uint8_t device;
 
for (device = 0; device < 32; device++) {
checkDevice(bus, device);
}
Line 1,039 ⟶ 1,025:
baseClass = getBaseClass(bus, device, function);
subClass = getSubClass(bus, device, function);
if( ((baseClass == 0x060x6) && (subClass == 0x040x4) ) {
secondaryBus = getSecondaryBus(bus, device, function);
checkBus(secondaryBus);
Line 1,046 ⟶ 1,032:
</source>
 
The final step is to handle systems with multiple PCI host controllers correctly. Start by checking if the device at bus 0, device 0 is a multi-function device. If it's not a multi-function device, then there is only one PCI host controller and bus 0, device 0, function 0 will be the PCI host controller responsible for bus 0. If it is's a multifunctionmulti-function device, then bus 0, device 0, function 0 will be the PCI host controller responsible for bus 0; bus 0, device 0, function 1 will be the PCI host controller responsible for bus 1, etc (up to the number of functions supported).
 
Pseudo-code might look like this:
Line 1,056 ⟶ 1,042:
 
headerType = getHeaderType(0, 0, 0);
if( ((headerType & 0x80) == 0) {
/*/ Single PCI host controller */
checkBus(0);
} else {
/*/ Multiple PCI host controllers */
for (function = 0; function < 8; function++) {
if (getVendorID(0, 0, function) != 0xFFFF) break;
bus = function;
checkBus(bus);
Line 1,072 ⟶ 1,058:
=== Recursive Scan With Bus Configuration ===
 
This is similar to the recursive scan above; except that you set the "secondary bus" field in PCI to PCI bridges (using something like "<code>setSecondaryBus(bus, device, function, nextBusNumber++);"</code> instead of the "<code>getSecondaryBus();"</code>). However; if you are configuring PCI buses you are also responsible for configuring the memory areas/BARs in PCI functions, and ensuring that PCI bridges forward requests from their primary bus to their secondary buses.
 
Writing code to support this without a deep understanding of PCI specifications is not recommended; and if you have a deep understanding of PCI specifications you have no need for pseudo code. For this reason there will be no example code for this method here.
 
=== Configuring PCI-to-PCI bridges ===
To configure this the kernel has to forget about BIOS for a moment, first scan the root PCI device, (check if it is multifunctionmulti-function to scan multiple buses). Root bus is always 0.
 
Secondary and subordinate bus acts as a range start-end of what buses the PCI-to-PCI bridge will manage.
 
Then, after this step it's up to implementation: Scan each device, then if a bridge is found, allocate a bus number to it (note: PCI-to-PCI bridges can have multiple bridges within them). Scan that bus and find more devices, once you find more bridges add +1 to the subordinate bus for each bridge found, because PCI-to-PCI bridges can manage multiple bridges.
 
And this is just the beginning: After allocating bus numbers, you need to allocate MMIO, it would be trivial if it wasn't for the fact that PCI has 3 areas the kernel manages: IO, Prefetch and Memory.
 
A bridge can manage multiple buses, but that means it spans all the memory of these buses, if device 1 is behind bridge 2, which is behind bridge 1, then bridge 2 will contain the memory area of device 1 + any other device's areas, supposing IO is 4M, Memory is 16M and Prefetch is 5MB (supposing there are 3 devices in bridge's 2 bus), bridge 2 would contain those, take in reference table for Header type 0x010x1. However, bridge 1 will contain the areas of bridge 2 + any other devices in bridge's 1 bus.
 
Once all memory areas are allocated, the devices can be used. Note that PCI-to-PCI bridges also have BAR's.
 
If the kernel does not configure a PCI-to-PCI bridge, the BIOS will probably do, however on enviromentsenvironments without BIOS, this method is mandatory otherwise devices behind that bridge won't show up.
 
== IRQ Handling ==
Line 1,103 ⟶ 1,089:
 
== Message Signaled Interrupts ==
Message Signaled Interrupts, or MSI, have been supported since PCI v22.2. However, support for them is ''mandatory'' in PCIe devices, so you can be sure that they're usable on modern hardware.
 
Use of MSI and MSI-X are mutually exclusive.
Line 1,279 ⟶ 1,265:
Message Address and Data are as they were for MSI - architecture specific. However, unlike with MSI, you can specify independent vectors for all the interrupts, only limited by having the same upper 32-bit message address.
 
== MultifunctionMulti-function Devices ==
MultifunctionMulti-function devices behave in the same manner as normal PCI devices. The easiest way to detect a multifunctionmulti-function device is bit 7 of the header type field. If it is set (value = 0x80), the device is multifunctionmulti-function -- else it is not. Make sure you mask this bit when you determine header type. To detect the number of functions you need to scan the PCI configuration space for every function - unused functions have vendor 0xFFFF. Device IDs and Class codes vary between functions. Functions are not neccesarilynecessarily in order - you can have function 0x0, 0x1 and 0x7 in use.
 
== Disclaimer ==
Line 1,301 ⟶ 1,287:
* [https://pci-ids.ucw.cz More up to date PCI vendor and device numbers]
* [https://msdn.microsoft.com/en-us/library/ms903537.aspx Structure describes that PCI configuration space for PCI devices]
 
[[Category:Buses]]
[[Category:PCI]]
73

edits