📄 pci.pas
字号:
Program PCI;
{$G+}
{$R-}
{$S-}
{$I+}
{$N+}
{$E+}
{$Q-}
uses newdelay,dos,crt;
{$I classes.pas}
{
This code is Written by Craig Hart in 1996-2005. It is released as freeware;
please use and modify at will. No guarantees are made or implied.
Please read the accompaning documentation PCI.DOC for all the info
relating to this program!
}
const
revision: string[5]='1.1';
type treedata =
record
b,
d,
f: byte;
vid,
did: word;
end;
var
olb,
lastd,
lastb,
agpbusnum,
lw,
wrlncount,
PCIverhi,
PCIverlo,
PCIchar,
PCI_hibus,
errcode,
deviceid,
func,
info,
lb,
bus,
sum,
disp,
cap_ptr,
max: byte;
showtree,
pdatareg,
found,
businfo,
userev,
tableok,
dorouting,
dopcirouting,
summary,
bogusid,
genssid,
dumpregs,
usebios,
failed,
first,
installermode: boolean;
irqmap: array[0..15] of byte;
pdata: array[0..15] of byte;
pscale: array[0..15] of byte;
presult: array[0..15] of byte;
tree: array[0..199] of treedata;
pmcsr,
romsize,
romresult,
rom_backup: longint;
spl: real;
count,
mb,
ml,
conmap,
len,
addr,
index,
i,
j,
l,
v: word;
f: text;
revchk,
oemidnum,
oemidstr,
cmdstr,
vstr,
cmpstr: string;
infotbl: array[0..$ff] of byte;
irqbuff: array[0..1023] of byte;
linecounter : word;
org_output: pointer;
cardbus: array[1..16] of byte;
cbu,
cardptr: byte;
procedure pagefilter1(var t:text);assembler;
asm
push ax
push di
push es
push cx
les di,[t]
mov cx,es:[di+TextRec.BufPos]
les di,es:[di+TextRec.BufPtr]
cld
mov al,10
@sl:
jcxz @ret
dec cx
scasb
jne @sl
inc linecounter
jmp @sl
@ret:
pop cx
pop es
pop di
pop ax
end;
procedure pagefilter2;assembler;
asm
push ax
mov ax,WindMax
shr ax,8
cmp linecounter,ax
jb @ret
sub ax,ax
int $16
mov linecounter,0
@ret:
pop ax
end;
procedure page_output_FlushFunc;assembler;
asm
push es
push bx
call pagefilter1
push es
push bx
call [org_output]
call pagefilter2
retf 4
end;
function cvtb(b:byte) : byte;
begin
if b>9 then cvtb:=b+ord('A')-10 else cvtb:=b+ord('0');
end;
function wrhexb(byt:byte): string;
begin
wrhexb:=chr(cvtb(byt and $0f));
end;
function wrhex(byt:byte) : string;
begin
wrhex:=chr(cvtb((byt and $f0) shr 4))+chr(cvtb(byt and $0f));
end;
function wrhexw(wor:word): string;
begin
wrhexw:=chr(cvtb(wor shr 12))+chr(cvtb((wor shr 8) and $f))+chr(cvtb((wor shr 4) and $f))+chr(cvtb(wor and $f));
end;
(* Make the PCI configuration status register printout pretty *)
(* Input = the string to be output *)
function IORedirected : boolean ; Assembler;
asm
push ds
mov ax,prefixseg
mov ds,ax
xor bx,bx
les bx,[bx + $34]
mov al,es:[bx]
mov ah,es:[bx +1]
pop ds
cmp al,ah
mov al,true
jne @exit
mov al,false
@exit:
end;
function lookup_bios(deviceid,func,bus:byte;index:word) : byte;
var inf:byte;
begin
asm
mov ax,$b108
mov bl,deviceid
shl bl,3
add bl,func
mov bh,bus
mov di,index
int $1a
jc @exit
mov failed,false
mov inf,cl
@exit:
mov errcode,ah
end;
lookup_bios:=inf;
end;
function lookup_hw(deviceid,func,bus:byte;index:word) : byte;
var inf:byte;
begin
asm
mov ax,$8000
mov al,bus
db $66;shl ax,16
mov ax,index
and ax,00fch
mov ah,deviceid
shl ah,3
add ah,func
mov dx,0cf8h
db $66;out dx,ax
mov ax,index
and ax,3
mov bl,8
mul bl
mov cx,ax
mov dx,0cfch
db $66;in ax,dx
db $66;shr ax,cl
mov inf,al
mov failed,false
db $66;xor ax,ax
mov dx,0cf8h
db $66;out dx,ax
end;
lookup_hw:=inf;
end;
procedure showinstallerinfo;
begin
if infotbl[$b]=1 then
begin
write('V:',wrhexw(infotbl[1] shl 8+infotbl[0]),' ');
write('D:',wrhexw(infotbl[3] shl 8+infotbl[2]),' ');
write('S:');
if infotbl[$e] and $7f=0 then
begin
write(wrhexw(infotbl[$2f] shl 8+infotbl[$2e]));
write(wrhexw(infotbl[$2d] shl 8+infotbl[$2c]),' ');
end else write('00000000 ');
write('B:',bus,' ');
write('E:');
if deviceid<10 then write('0');
write(deviceid,' ');
write('F:',func,' ');
write('I:');
if (infotbl[$3c]<16) and (infotbl[$3c]>0) then
begin
if infotbl[$3c]<10 then write('0');
write(infotbl[$3c],' ');
end else write('00 ');
write('N:');
if (infotbl[$3c]<16) and (infotbl[$3c]>0) then
begin
if infotbl[$3d]=0 then write('- ') else write(chr(infotbl[$3d]+64),' ');
end else write('- ');
write('C:');
write(wrhex(infotbl[$b]),' ');
write('U:');
write(wrhex(infotbl[$a]),' ');
write('P:');
write(wrhex(infotbl[$9]),' ');
write('R:');
write(wrhex(infotbl[$8]),' ');
writeln;
end;
end;
procedure showallinfo;
var
j,
i : integer;
pp,
nn,
x: byte;
gotit: boolean;
begin
showinstallerinfo;
end;
begin
agpbusnum:=$ff;
businfo:=false;
dorouting:=true;
dopcirouting:=false;
dumpregs:=false;
usebios:=true;
summary:=false;
installermode:=false;
cardptr:=0;
{ the following hack permits MS-DOS display output redirection to work }
if ioredirected then
begin
writeln('Craig Hart''s PCI+AGP bus sniffer, version ',revision,', freeware made in 1996-2001.');
assign(output,'');
rewrite(output);
end else
{ code to do page pausing }
begin
ClrScr;
linecounter:=0;
with TextRec(Output) do
begin
org_output:=FlushFunc;
FlushFunc:=@page_output_FlushFunc;
end;
end;
for i:=0 to 15 do irqmap[i]:=0;
failed:=true;
if paramcount>0 then
begin
for i:=1 to paramcount do
begin
cmdstr:=paramstr(i);
for j:=1 to length(cmdstr) do cmdstr[j]:=upcase(cmdstr[j]);
if (cmdstr='/R') or (cmdstr='-R') then showtree:=true;
if (cmdstr='/H') or (cmdstr='-H') then usebios:=false;
if (cmdstr='/D') or (cmdstr='-D') then dumpregs:=true;
if (cmdstr='/T') or (cmdstr='-T') then dorouting:=false;
if (cmdstr='/P') or (cmdstr='-P') then dopcirouting:=true;
if (cmdstr='/B') or (cmdstr='-B') then businfo:=true;
if (cmdstr='/S') or (cmdstr='-S') then summary:=true;
if (cmdstr='/I') or (cmdstr='-I') then installermode:=true;
if (cmdstr='?') or (cmdstr='/?') or (cmdstr='-?') then
begin
textmode(co80);
writeln(' Help for PCI (Version ',revision,')');
textcolor(8);
writeln('哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪?);
textcolor(7);
writeln;
writeln('Usage: PCI [-H][-D][-S][-T][-B][-P][-R][-?] [ ] indicates optional parameter');
writeln;
writeln('-H : Use direct hardware access (instead of the BIOS) to retrieve PCI Info');
writeln(' May be required for accurate reporting on Intel 430FX chipset+Award BIOS');
writeln('-D : Do a hex-dump of each device''s entire configuration space');
writeln('-S : Create a brief, summary report only; only devices and IRQs listed');
writeln('-T : Disable the test ROM IRQ Routing Table function');
writeln('-B : Enable display of the Bus, Device & Function information');
writeln('-P : Enable display of PCI slot routing data');
writeln('-I : Installer mode: produce raw data dump (for use with auto-setup programs)');
writeln('-R : Draw a Tree of Busses, Devices and Device Functions');
writeln('-? : Displays this help screen!');
writeln;
writeln('PCI Supports generating reports to a file or printer using MS-DOS pipes; i.e.');
writeln;
writeln(' PCI -D > REPORT.TXT (Save report to file), PCI > LPT1: (Print report)');
writeln;
writeln('PCI is written by Craig Hart, and is released as freeware, with no restictions');
write('on use or copying. Visit ');
textcolor(11);
write('http://members.datafast.net.au/dft0802 ');
textcolor(7);
writeln('for updates to');
writeln('the program and the PCI Database file PCIDEVS.TXT');
halt(10);
end;
end;
end;
{ fix up conflicting commandline switches }
if installermode then
begin
dorouting:=false;
dopcirouting:=false;
dumpregs:=false;
businfo:=false;
summary:=false;
end;
{
if summary then
begin
dumpregs:=false;
dopcirouting:=false;
dorouting:=false;
end;
}
if test8086<2 then
begin
writeln('PCI Halted:');
writeln;
writeln('The PC Must be at least a 386 to possibly have a PCI or AGP bus!');
halt(1);
end;
{ Look for PCI BIOS }
asm
mov ax,$b101
int $1a
jc @exit
{ check signature bytes OK }
cmp dx,$4350
jne @exit
{ check no error code returned > AH=00=Success }
cmp ah,0
jne @exit
mov PCIchar,al
mov PCI_hibus,cl
mov PCIverlo,bl
mov PCIverhi,bh
mov failed,false
@exit:
end;
if failed then
begin
writeln('PCI Halted:');
writeln;
writeln('No PCI BIOS was detected! (NB: I don''t work under Windows NT/2000/XP/2003 etc!)');
writeln;
writeln('For PCI reports under Win NT-era OS''s such as NT/2K/XP/2K3, use PCI32.EXE');
writeln('which is available from the same website as this program (See PCI /? for the');
writeln('website address.)');
writeln;
halt(2);
end;
{ OK, we have PCI... do our stuff.. }
begin
for bus:=0 to pci_hibus do{ fix bugs for 440LX chipset, 2 PCI buses, AGP=1 bus! }
begin
for deviceid:=0 to $1f do
begin
func:=0;
repeat
index:=0;
repeat
if usebios then info:=lookup_bios(deviceid,func,bus,index) else info:=lookup_hw(deviceid,func,bus,index);
infotbl[index]:=info;
inc(index);
{don't try to read cfg-space of non-existant devices: hangs some chipsets!}
if index=2 then if (infotbl[0]=$ff) and (infotbl[1]=$ff) then index:=$100;
{don't read past $3f if in short-info modes; avoids crashing on intolerant hardware!}
if index=$40 then if installermode or summary then index:=$100;
until (index=$100);
if (infotbl[0]<>$ff) or (infotbl[1]<>$ff) then
begin
{ remember CardBus stuff for later; skip if far bus=0 (i.e. unconfigured) }
if (infotbl[$e] and $7f=2) and (infotbl[$19]<>0) then
begin
cardbus[cardptr+1]:=infotbl[$19];
cardptr:=cardptr+1;
end;
showallinfo;
end;
inc(func);
{ if func 0 = invalid device, don't test for presence of func 1->7 at all. [$e] isn't valid if [0] and [1] aren't!! }
if (func=1) and (infotbl[0]=$ff) and (infotbl[1]=$ff) then func:=8;
{ If not multi-device device, then don't test for func 1-7 as some cards
incorrectly answer back on all 8 function numbers!!! S3 trio64, for example - stupid! }
if (func=1) and (infotbl[$e] and $80=0) then func:=8;
until func=8; {func }
end; {dev }
end; { bus }
{ now scan any CardBus busses that weren't included in the BIOS bus count }
if cardptr>0 then
begin
for cbu:=1 to cardptr do{ scan all cardbus busses }
begin
bus:=cardbus[cbu];
if bus>pci_hibus then{ but only those the BIOS hasn't already had us scan }
begin
for deviceid:=0 to $1f do
begin
func:=0;
repeat
index:=0;
repeat
if usebios then info:=lookup_bios(deviceid,func,bus,index) else info:=lookup_hw(deviceid,func,bus,index);
infotbl[index]:=info;
inc(index);
if index=2 then if (infotbl[0]=$ff) and (infotbl[1]=$ff) then index:=$100;
if index=$40 then if installermode or summary then index:=$100;
until (index=$100);
if (infotbl[0]<>$ff) or (infotbl[1]<>$ff) then showallinfo;
inc(func);
if (func=1) and (infotbl[0]=$ff) and (infotbl[1]=$ff) then func:=8;
if (func=1) and (infotbl[$e] and $80=0) then func:=8;
until func=8;
end;
end;
end;
end;
end;
end.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -