|
http://www.waste.org/~winkles/hardware/pci.htm 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. .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. 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: ---------------------------------------------------------------- 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 for pciview.exe -------------------------------------------------------------------------------------- bit 31=1 (bit is
always set for a PCI access) 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.
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. 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. feel free to contact me with questions or comments. -jeff! |
