Device Discovery An introduction to the PCI configuration space registers

advertisement
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 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 (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 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
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 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 4 serial-port UARTs (Universal
Asynchronous Receiver/Transmitter)
• IBM’s PC designers reserved four I/O-port
address-ranges for these devices:
–
–
–
–
COM1:
COM2:
COM3:
COM4:
0x03F8-0x03FF
0x02F8-0x02FF
0x03E8-0x03EF
0x02E8-0x02EF
</dev/ttyS0>
</dev/ttyS1>
</dev/ttyS2>
</dev/ttyS3>
…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
.short
0x03F8, 0x02F8, 0x03E8, 0x02E8
0
# loop to count the number of 16550 serial-port devices installed
nxtry:
fail:
xor
mov
add
mov
mov
outb
in
xor
jne
incw
incl
cmp
jb
%esi, %esi
ports(, %esi, 2), %dx
$7, %dx
$0x55, %al
%al, %ah
%al, %dx
%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 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 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
Register
Latency
Timer
Cache
Line
Size
31
0
Device
ID
Vendor
ID
Class Code
Class/SubClass/ProgIF
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
CardBus 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
MultiFunction
Device
flag
6
0
Header Type
Configuration Header Format ID
0 = Single-Function Device
1 = Multi-Function Device
Interface to PCI Configuration Space
PCI Configuration Space Address Port (32-bits)
31
CONFADD
( 0x0CF8)
E
N
23
reserved
16 15
bus
(8-bits)
11 10
device
(5-bits)
8 7
function
(3-bits)
2
doubleword
(6-bits)
0
00
Enable Configuration Space Mapping (1=yes, 0=no)
PCI Configuration Space Data Port (32-bits)
31
CONFDAT
( 0x0CFC)
0
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
$0x8000000C, %eax
# setup address in EAX
movw
$0x0CF8, %dx
# setup port-number in DX
outl
%eax, %dx
# output address to port
mov
inl
shr
movb
$0x0CFC, %dx
%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
•
•
•
•
•
•
•
•
•
•
•
•
0x8086 – Intel Corporation
0x1022 – Advanced Micro Devices, Inc
0x1002 – Advanced Technologies, Inc
0x10EC – RealTek, Incorporated
0x10DE – Nvidia Corporation
0x10B7 – 3Com Corporation
0x101C – Western Digital, Inc
0x1014 – IBM Corporation
0x0E11 – Compaq Corporation
0x1057 – Motorola Corporation
0x106B – Apple Computers, Inc
0x5333 – Silicon Integrated Systems, Inc
Examples of DEVICE-IDs
•
•
•
•
•
0x5347:
0x4C58:
0x5950:
0x436E:
0x438C:
ATI RAGE128 SG
ATI RADEON LX
ATI RS480
ATI IXP300 SATA
ATI IXP600 IDE
See this Linux header-file for lots more:
</usr/src/linux/include/linux/pci_ids.h>
Defined PCI Class Codes
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
0x00: Legacy Device (i.e., built before class-codes were defined)
0x01: Mass Storage controller
0x02: Network controller
0x03: Display controller
0x04: Multimedia device
0x05: Memory Controller
0x06: Bridge device
0x07: Simple Communications controller
0x08: Base System peripherals
0x09: Input device
0x0A: Docking stations
0x0B: Processors
0x0C: Serial Bus controllers
0x0D: Wireless controllers
0x0E: Intelligent I/O controllers
0x0F: Encryption/Decryption controllers
0x10: Satellite Communications controllers
0x11: Data Acquisition and Signal Processing controllers
Example of Sub-Class Codes
• Class Code 0x01: Mass Storage controller
– 0x00: SCSI controller
– 0x01: IDE controller
– 0x02: Floppy Disk controller
– 0x03: IPI controller
– 0x04: RAID controller
– 0x80: Other Mass Storage controller
Example of Sub-Class Codes
• Class Code 0x02: Network controller
– 0x00: Ethernet controller
– 0x01: Token Ring controller
– 0x02: FDDI controller
– 0x03: ATM controller
– 0x04: ISDN controller
– 0x80: Other Network controller
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 0x1A,
with function-number 0xB1 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 0x02, Sub-Class is 0x00)
# code-example: Finding the Vendor-ID for your computer’s ethernet controller
mov
mov
xor
int
jnc
jmp
$0xB103, %ax
$0x020000, %ecx
%esi, %esi
$0x1A
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
$0xB109, %ax
# PCI Read Configuration Word
mov
$0x0000, %di
# PCI Register-Number
int
$0x1A
# 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 CS630 website)
• Tom Shanley and Don Anderson,
“PCI System Architecture (4th Edition),”
MindShare, Inc. (Addison-Wesley, 1999)
Demo Program
• We created a short Linux utility that searches for
a system’s PCI devices (named “pciprobe.cpp”
on CS630 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 “iopl3”) that will allow
your command-shell to acquire root privileges
In-Class Exercise
• After you have experimented with running
the “pciprobe.cpp” utility (be sure you run
the “iopl3” 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
Download