Device Discovery An introduction to the PCI configuration

  • Slides: 25
Download presentation
Device Discovery An introduction to the PCI configuration space registers

Device Discovery An introduction to the PCI configuration space registers

In the beginning… • The original IBM-PC was built using an assortment of off-the-shelf

In the beginning… • The original IBM-PC was built using an assortment of off-the-shelf components produced by a variety of manufacturers • Certain peripheral components were a mandatory part of the design (e. g. , timer, keyboard, diskette-drive, etc), while others were considered optional “add-ons” (e. g. , color display, floating-point coprocessor, line-printer, modem, mouse, etc)

…there was chaos! • The PC’s operating system was a massproduced piece of software

…there was chaos! • The PC’s operating system was a massproduced piece of software (e. g. PC-DOS) that needed to execute successfully on all the different PC equipment configurations • There had to be a way for the OS to find out which kinds of devices were actually attached to the particular machine it was running on – so it could avoid attempts at using hardware which wasn’t present

The ROM-BIOS POST • During startup, the ROM-BIOS code did a “Power-On Self-Test” routine

The ROM-BIOS POST • During startup, the ROM-BIOS code did a “Power-On Self-Test” routine to detect the presence of those peripheral components that were standard features of the PC, and also to initialize them where necessary • For example, the Programmable Interrupt Controller needed its mask-register to be initialized, and the Programmable Interval Timer’s latch-registers needed to be setup

Simplified Block Diagram optional FPU main memory (amount varies) CPU optional EMS system bus

Simplified Block Diagram optional FPU main memory (amount varies) CPU optional EMS system bus keyboard controller interrupt controller programmable timer/counter serial 1 serial 2 serial 3 serial 4 …plus other peripheral components (not shown) parallel 1 parallel 2 parallel 3

Components were all different • There was no standard way to detect the various

Components were all different • There was no standard way to detect the various peripheral devices – each needed its own “non-reusable” code-sequence for discovering it and configuring it to operate • System programmers had to learn details of the unique designs for all the different possible microprocessors’ capabilities

Older probing methods… • Originally the IBM PC/AT’s hardware and BIOS supported up to

Older probing methods… • Originally the IBM PC/AT’s hardware and BIOS supported up to 4 serial-port UARTs (Universal Asynchronous Receiver/Transmitter) • IBM’s PC designers reserved four I/O-port address-ranges for these devices: – – COM 1: COM 2: COM 3: COM 4: 0 x 03 F 8 -0 x 03 FF 0 x 02 F 8 -0 x 02 FF 0 x 03 E 8 -0 x 03 EF 0 x 02 E 8 -0 x 02 EF </dev/tty. S 0> </dev/tty. S 1> </dev/tty. S 2> </dev/tty. S 3>

…checked ‘reserved’ ports • Example: Any 16550 serial-UART device always has a “scratch” register

…checked ‘reserved’ ports • Example: Any 16550 serial-UART device always has a “scratch” register (at offset 7) – a register that performs no functions, but it can be used by programmers to save, and read back, values • Thus system software can detect the presence of these serial UARTs by attempting to write and read back some test-values at these ‘reserved’ port-locations: if those values can be read back successfully, it means this UART is installed

Probing for 16550 UARTs ports: ndevs: . short 0 x 03 F 8, 0

Probing for 16550 UARTs ports: ndevs: . short 0 x 03 F 8, 0 x 02 F 8, 0 x 03 E 8, 0 x 02 E 8 0 # loop to count the number of 16550 serial-port devices installed nxtry: fail: xor mov add mov outb in xor jne incw incl cmp jb %esi, %esi ports(, %esi, 2), %dx $7, %dx $0 x 55, %al, %ah %al, %dx, %al %ah, %al fail ndevs %esi $4, %esi nxtry # array-index and loop-counter # base of port-address range # plus offset to scratch-register # setup test-value in AL # save copy of test-value in AH # try writing to the scratch register # try reading back that test-value # see if these two values agree # the scratch-register isn’t there! # else count this 16550 UART # advance array-index # all reserved ranges checked? # no, try next expected location # when we arrive here, the ‘ndevs’ variable holds the number of UART devices found

Some background on PCI • • ISA: Industry Standard Architecture (1981) PCI: Peripheral Component

Some background on PCI • • ISA: Industry Standard Architecture (1981) PCI: Peripheral Component Interconnect An Intel-backed industry initiative (1992 -9) Main goals: – Reduce the diversity inherent in legacy ISA – Improve data-xfers to/from peripheral devices – Eliminate (or reduce) platform dependencies – Simplify adding/removing peripheral devices – Lower total consumption of electrical power

PCI Configuration Space A non-volatile parameter-storage area for each PCI device-function PCI Configuration Space

PCI Configuration Space A non-volatile parameter-storage area for each PCI device-function PCI Configuration Space Header (16 doublewords – fixed format) 64 doublewords PCI Configuration Space Body (48 doublewords – variable format)

Example: Header Type 0 16 doublewords 31 0 Status Register BIST Header Type Command

Example: Header Type 0 16 doublewords 31 0 Status Register BIST Header Type Command Register Latency Timer Cache Line Size 31 0 Device ID Vendor ID Class Code Class/Sub. Class/Prog. IF Revision ID Dwords 1 - 0 3 - 2 Base Address 1 Base Address 0 5 - 4 Base Address 3 Base Address 2 7 - 6 Base Address 5 Base Address 4 9 - 8 Card. Bus CIS Pointer 11 - 10 Subsystem Device ID Subsystem Vendor ID reserved capabilities pointer Expansion ROM Base Address 13 - 12 Maximum Minimum Interrupt Latency Grant Pin Interrupt Line reserved 15 - 14

The ‘Header Type’ field 7 Multi. Function Device flag 6 0 Header Type Configuration

The ‘Header Type’ field 7 Multi. Function Device flag 6 0 Header Type Configuration Header Format ID 0 = Single-Function Device 1 = Multi-Function Device

Interface to PCI Configuration Space Address Port (32 -bits) 31 CONFADD ( 0 x

Interface to PCI Configuration Space Address Port (32 -bits) 31 CONFADD ( 0 x 0 CF 8) E N 23 reserved 16 15 bus (8 -bits) 11 10 device (5 -bits) 8 7 function (3 -bits) doubleword (6 -bits) 2 0 00 Enable Configuration Space Mapping (1=yes, 0=no) PCI Configuration Space Data Port (32 -bits) 31 CONFDAT ( 0 x 0 CFC) 0

Reading PCI Configuration Data • Step one: Output the desired longword’s address (bus, device,

Reading PCI Configuration Data • Step one: Output the desired longword’s address (bus, device, function, and dword) with bit 31 set to 1 (to enable access) to the Configuration-Space Address-Port • Step two: Read the designated data from the Configuration-Space Data-Port: # read the PCI Header-Type field (byte 2 of dword 3) for bus=0, device=0, function=0 movl $0 x 8000000 C, %eax # setup address in EAX movw $0 x 0 CF 8, %dx # setup port-number in DX outl %eax, %dx # output address to port mov inl shr movb $0 x 0 CFC, %dx, %eax $16, %eax %al, header_type # setup port-number in DX # input configuration longword # shift word 2 into AL register # store Header Type in variable

Examples of VENDOR-IDs • • • 0 x 8086 – Intel Corporation 0 x

Examples of VENDOR-IDs • • • 0 x 8086 – Intel Corporation 0 x 1022 – Advanced Micro Devices, Inc 0 x 1002 – Advanced Technologies, Inc 0 x 10 EC – Real. Tek, Incorporated 0 x 10 DE – Nvidia Corporation 0 x 10 B 7 – 3 Com Corporation 0 x 101 C – Western Digital, Inc 0 x 1014 – IBM Corporation 0 x 0 E 11 – Compaq Corporation 0 x 1057 – Motorola Corporation 0 x 106 B – Apple Computers, Inc 0 x 5333 – Silicon Integrated Systems, Inc

Examples of DEVICE-IDs • • • 0 x 5347: 0 x 4 C 58:

Examples of DEVICE-IDs • • • 0 x 5347: 0 x 4 C 58: 0 x 5950: 0 x 436 E: 0 x 438 C: ATI RAGE 128 SG ATI RADEON LX ATI RS 480 ATI IXP 300 SATA ATI IXP 600 IDE See this Linux header-file for lots more: </usr/src/linux/include/linux/pci_ids. h>

Defined PCI Class Codes • • • • • 0 x 00: Legacy Device

Defined PCI Class Codes • • • • • 0 x 00: Legacy Device (i. e. , built before class-codes were defined) 0 x 01: Mass Storage controller 0 x 02: Network controller 0 x 03: Display controller 0 x 04: Multimedia device 0 x 05: Memory Controller 0 x 06: Bridge device 0 x 07: Simple Communications controller 0 x 08: Base System peripherals 0 x 09: Input device 0 x 0 A: Docking stations 0 x 0 B: Processors 0 x 0 C: Serial Bus controllers 0 x 0 D: Wireless controllers 0 x 0 E: Intelligent I/O controllers 0 x 0 F: Encryption/Decryption controllers 0 x 10: Satellite Communications controllers 0 x 11: Data Acquisition and Signal Processing controllers

Example of Sub-Class Codes • Class Code 0 x 01: Mass Storage controller –

Example of Sub-Class Codes • Class Code 0 x 01: Mass Storage controller – 0 x 00: SCSI controller – 0 x 01: IDE controller – 0 x 02: Floppy Disk controller – 0 x 03: IPI controller – 0 x 04: RAID controller – 0 x 80: Other Mass Storage controller

Example of Sub-Class Codes • Class Code 0 x 02: Network controller – 0

Example of Sub-Class Codes • Class Code 0 x 02: Network controller – 0 x 00: Ethernet controller – 0 x 01: Token Ring controller – 0 x 02: FDDI controller – 0 x 03: ATM controller – 0 x 04: ISDN controller – 0 x 80: Other Network controller

Using the BIOS PCI services • To assist system software authors in doing “device

Using the BIOS PCI services • To assist system software authors in doing “device detection”, the PC’s ROM-BIOS now includes service-functions that search for particular devices or classes of devices • These service-functions are invoked while in real-mode via software interrupt 0 x 1 A, with function-number 0 x. B 1 in register AH and with a PCI sub-function ID-number in register AL (about a dozen sub-functions)

PCI BIOS example • Search for your PC’s ethernet controller (Device Class is 0

PCI BIOS example • Search for your PC’s ethernet controller (Device Class is 0 x 02, Sub-Class is 0 x 00) # code-example: Finding the Vendor-ID for your computer’s ethernet controller mov xor int jnc jmp $0 x. B 103, %ax $0 x 020000, %ecx %esi, %esi $0 x 1 A found error # PCI Find Class function # PCI Class (network/ethernet) # initialize search index # request BIOS service # function was successful # else the function failed found: # if successful, BX = bus/device/function mov $0 x. B 109, %ax # PCI Read Configuration Word mov $0 x 0000, %di # PCI Register-Number int $0 x 1 A # request BIOS service jc success # vendor-ID is in register CX jmp error # else the function failed # NOTE: This code was written for execution while the Pentium is in real-mode

Some references • Professor Ralf Brown’s Interrupt List (see the online link on our

Some references • Professor Ralf Brown’s Interrupt List (see the online link on our CS 630 website) • Tom Shanley and Don Anderson, “PCI System Architecture (4 th Edition), ” Mind. Share, Inc. (Addison-Wesley, 1999)

Demo Program • We created a short Linux utility that searches for a system’s

Demo Program • We created a short Linux utility that searches for a system’s PCI devices (named “pciprobe. cpp” on CS 630 website) • It uses some C++ macros that expand to Intel input/output instructions -- which normally are ‘privileged’ instructions that a Linux applicationprogram is not allowed to execute (segfault!) • Our system administrator (Alex Fedosov) has created a utility (named “iopl 3”) that will allow your command-shell to acquire root privileges

In-Class Exercise • After you have experimented with running the “pciprobe. cpp” utility (be

In-Class Exercise • After you have experimented with running the “pciprobe. cpp” utility (be sure you run the “iopl 3” program first), see if you can modify “pciprobe” so that it will display the Class Code for each PCI device-function that it identifies as being present • This will give you practice in reading some useful data from PCI Configuration Space