home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: SysTools / SysTools.zip / pci040vk.zip / pci.pas < prev    next >
Pascal/Delphi Source File  |  2000-07-28  |  55KB  |  2,133 lines

  1. (*&Use32+*)
  2. (*&Delphi-*)
  3. (*&AlignCode+*)
  4. (*&AlignData+*)
  5. (*&AlignRec-*)
  6. (*&Optimize+*)
  7. Program PCI;
  8.  
  9. {$G+}
  10. {$R+}
  11. {$S+}
  12. {$I+}
  13.  
  14.  
  15. uses
  16.   (*$IFDEF VirtualPascal*)
  17.     VpSysLow,VpUtils,
  18.     (*$IFDEF DPMI32*)
  19.     DPMI32,DPMI32df,
  20.     (*$ENDIF*)
  21.     (*$IFDEF OS2*)
  22.     Os2Base,Os2Def,
  23.     (*$ENDIF*)
  24.   (*$ELSE*)
  25.     newdelay,
  26.   (*$ENDIF*)
  27.   Dos,Crt;
  28.  
  29.  
  30. {$I classes.pas}
  31.  
  32.  
  33. {
  34.   This code is Written by Craig Hart in 1996-2000. It is released as freeware;
  35.   please use and modify at will. No gurarantees are made or implied.
  36.  
  37.  
  38.   Please read the accompaning documentation PCI.DOC for all the info
  39.   relating to this program!
  40. }
  41.  
  42.  
  43. const
  44.   revision      : string[5-1+2]='0.40vk'; (* 0.40ß *)
  45.  
  46. (*$IFDEF VirtualPascal*)
  47. type
  48.   PWord=^smallword;
  49. (*$ELSE*)
  50. type
  51.   smallword=word;
  52. (*$ENDIF*)
  53.  
  54.  
  55. var
  56.   wrlncount,
  57.   PCIverhi,
  58.   PCIverlo,
  59.   PCIchar,
  60.   PCI_hibus,
  61.   errcode,
  62.   deviceid,
  63.   func,
  64.   info,
  65.   nn,
  66.   pp,
  67.   lb,
  68.   bus,
  69.   sum,
  70.   disp,
  71.   cap_ptr       : byte;
  72.  
  73.   showhelp,
  74.   businfo,
  75.   tableok,
  76.   dorouting,
  77.   dopcirouting,
  78.   userev,
  79.   summary,
  80.   bogusid,
  81.   genssid,
  82.   dumpregs,
  83.   usebios,
  84.   failed,
  85.   first         : boolean;
  86.  
  87.  
  88.   irqmap        : array[0..15] of byte;
  89.  
  90.   conmap,
  91.   len,
  92.   addr,
  93.   index,
  94.   i,
  95.   j,
  96.   l,
  97.   v             : word;
  98.  
  99.   f             : text;
  100.  
  101.   revchk,
  102.   oemidnum,
  103.   oemidstr,
  104.   cmdstr,
  105.   vstr,
  106.   cmpstr        : string;
  107.  
  108.  
  109.   infotbl       : array[0..$ff] of byte;
  110.  
  111.   irqbuff       : array[0..1023] of byte;
  112.  
  113.  
  114.   pcidevs_txt   : string;
  115.   pcidevs_path  : string;
  116.  
  117.  
  118.   linecounter   :word;
  119.  
  120.   org_output_FlushFunc  : pointer;
  121.  
  122.  
  123. (*$IFDEF VirtualPascal*)
  124. procedure pagefilter1(var t:text);(*$Saves ALL*)
  125.   var
  126.      z:word;
  127.   begin
  128.     with TextRec(t) do
  129.       for z:=1 to BufPos do
  130.         if BufPtr^[z]=#10 then
  131.           Inc(linecounter);
  132.   end;
  133.  
  134. procedure pagefilter2;(*$Saves ALL*)
  135.   begin
  136.     if linecounter>=Hi(WindMax) then
  137.       begin
  138.         SysReadKey;
  139.         linecounter:=0;
  140.       end;
  141.   end;
  142.  
  143. procedure page_output_FlushFunc;assembler;(*$Uses None*)(*$Frame-*)
  144.   asm
  145.     push ebx
  146.     call pagefilter1
  147.     push ebx
  148.     call [org_output_FlushFunc]
  149.     call pagefilter2
  150.     ret 4
  151.   end;
  152.  
  153. (*$ELSE*) (* BP *)
  154.  
  155. procedure pagefilter1(var t:text);assembler;
  156.   asm
  157.     push ax
  158.       push di
  159.         push es
  160.           push cx
  161.  
  162.             les di,[t]
  163.             mov cx,es:[di+TextRec.BufPos]
  164.             les di,es:[di+TextRec.BufPtr]
  165.             cld
  166.             mov al,10
  167.   @sl:
  168.             jcxz @ret
  169.             dec cx
  170.             scasb
  171.             jne @sl
  172.             inc linecounter
  173.             jmp @sl
  174.   @ret:
  175.           pop cx
  176.         pop es
  177.       pop di
  178.     pop ax
  179.   end;
  180.  
  181. procedure pagefilter2;assembler;
  182.   asm
  183.     push ax
  184.       mov ax,WindMax
  185.       shr ax,8
  186.       cmp linecounter,ax
  187.       jb @ret
  188.  
  189.       sub ax,ax
  190.       int $16
  191.  
  192.       mov linecounter,0
  193.   @ret:
  194.     pop ax
  195.   end;
  196.  
  197. procedure page_output_FlushFunc;assembler;
  198.   asm
  199.     push es
  200.     push bx
  201.     call pagefilter1
  202.     push es
  203.     push bx
  204.     call [org_output_FlushFunc]
  205.     call pagefilter2
  206.     retf 4
  207.   end;
  208. (*$ENDIF*)
  209.  
  210. function cvtb(b:byte) : byte;
  211. begin
  212.   if b>9 then cvtb:=b+Ord('A')-10 else cvtb:=b+Ord('0');
  213. end;
  214.  
  215. function wrhexb(byt:byte): string;
  216. begin
  217.  wrhexb:=Chr(cvtb(byt and $0f));
  218. end;
  219.  
  220. function wrhex(byt:byte) : string;
  221. begin
  222.   wrhex:=Chr(cvtb((byt and $f0) shr 4))+Chr(cvtb(byt and $0f));
  223. end;
  224.  
  225. function wrhexw(wor:word): string;
  226. begin
  227.   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));
  228. end;
  229.  
  230.  
  231. (* Make the PCI configuration status register printout pretty *)
  232. (* Input = the string to be output *)
  233.  
  234. Procedure printstatus (s : string);
  235. Begin
  236.   if not first then if (Length(s)+WhereX)>78 then
  237.   begin
  238.     WriteLn(',');
  239.     Write('   ');
  240.   end else Write(', ');
  241.   Write(s);
  242.   first:=false;
  243. End;
  244.  
  245.  
  246. (*$IFDEF VirtualPascal*)
  247. function IORedirected : boolean ;
  248.   begin
  249.     IORedirected:=not VPUtils.IsFileHandleConsole(SysFileStdOut);
  250.   end;
  251. (*$ELSE*)
  252. function IORedirected : boolean ; Assembler;
  253. asm
  254.   push ds
  255.   mov ax,prefixseg
  256.   mov ds,ax
  257.   xor bx,bx
  258.   les bx,[bx + $34]
  259.   mov al,es:[bx]
  260.   mov ah,es:[bx +1]
  261.   pop ds
  262.   cmp al,ah
  263.   mov al,true
  264.   jne @exit
  265.  
  266.   mov al,false
  267.  
  268.  @exit:
  269. end;
  270. (*$ENDIF*)
  271.  
  272.  
  273. (*$IFDEF OS2*)
  274. var
  275.   biosf000:array[0..$ffff] of byte;
  276.  
  277. procedure os2_read_bios;
  278.  
  279.   var
  280.     hand,
  281.     action,
  282.     rc                  :longint;
  283.  
  284.     ParmRec1:
  285.       record            // Input parameter record
  286.         phys32          :longint;
  287.         laenge          :smallword;
  288.       end;
  289.  
  290.     ParmRec2:
  291.       record
  292.         sel             :smallword;
  293.       end;
  294.  
  295.     ParmLen             : ULong;  // Parameter length in bytes
  296.     DataLen             : ULong;  // Data length in bytes
  297.     Data1:
  298.       record
  299.         sel             :smallword;
  300.       end;
  301.  
  302.   begin
  303.     FillChar(biosf000,SizeOf(biosf000),0);
  304.  
  305.     if DosOpen('SCREEN$',hand,action,0,0,1,$40,nil)<>0 then
  306.       exit;
  307.  
  308.     ParmLen:=SizeOf(ParmRec1);
  309.  
  310.     with ParmRec1 do
  311.       begin
  312.         phys32:=$000f0000;
  313.         laenge:=0;
  314.       end;
  315.  
  316.     datalen:=SizeOf(data1);
  317.     rc:=DosDevIOCtl(
  318.             hand,                       // Handle to device
  319.             IOCTL_SCR_AND_PTRDRAW,      // Category of request
  320.             SCR_ALLOCLDT,               // Function being requested
  321.             @ParmRec1,                  // Input/Output parameter list
  322.             ParmLen,                    // Maximum output parameter size
  323.             @ParmLen,                   // Input:  size of parameter list
  324.                                         // Output: size of parameters returned
  325.             @Data1,                     // Input/Output data area
  326.             Datalen,                    // Maximum output data size
  327.             @DataLen);                  // Input:  size of input data area
  328.     if rc=0 then
  329.       begin
  330.  
  331.         asm (*$SAVES NONE*)
  332.           push gs
  333.  
  334.             sub esi,esi
  335.             mov gs,data1.sel
  336.  
  337.             mov edi,offset biosf000
  338.             mov ecx,$10000
  339.             cld
  340.           @l1:
  341.             mov al,gs:[esi]
  342.             inc esi
  343.             stosb
  344.             loop @l1
  345.  
  346.           pop gs
  347.         end;
  348.  
  349.         ParmLen:=SizeOf(ParmRec2);
  350.  
  351.         with ParmRec2 do
  352.           begin
  353.             sel:=data1.sel;
  354.           end;
  355.  
  356.         DataLen:=0;
  357.         rc:=DosDevIOCtl(
  358.                 hand,                           // Handle to device
  359.                 IOCTL_SCR_AND_PTRDRAW,          // Category of request
  360.                 SCR_DEALLOCLDT,                 // Function being requested
  361.                 @ParmRec2,                      // Input/Output parameter list
  362.                 ParmLen,                        // Maximum output parameter size
  363.                 @ParmLen,                       // Input:  size of parameter list
  364.                                                 // Output: size of parameters returned
  365.                 nil,                            // Input/Output data area
  366.                 Datalen,                        // Maximum output data size
  367.                 @DataLen);                      // Input:  size of input data area
  368.  
  369.       end;
  370.  
  371.     DosClose(hand);
  372.   end;
  373.  
  374. (*$ENDIF*)
  375.  
  376. function Mem_F000(const i:word):byte;
  377.   begin
  378.     (*$IFDEF VirtualPascal*)
  379.  
  380.       (*$IFDEF DPMI32*)
  381.       Mem_F000:=Mem[$f0000+i];
  382.       (*$ENDIF*)
  383.  
  384.       (*$IFDEF OS2*)
  385.       Mem_F000:=biosf000[i];
  386.       (*$ENDIF*)
  387.  
  388.  
  389.     (*$ELSE*)
  390.     Mem_F000:=Mem[$f000:i];
  391.     (*$ENDIF*)
  392.   end;
  393.  
  394. function MemW_F000(const i:word):word;
  395.   begin
  396.     (*$IFDEF VirtualPascal*)
  397.  
  398.       (*$IFDEF DPMI32*)
  399.       MemW_F000:=MemW[$f0000+i];
  400.       (*$ENDIF*)
  401.  
  402.       (*$IFDEF OS2*)
  403.       MemW_F000:=PWord(@biosf000[i])^;
  404.       (*$ENDIF*)
  405.  
  406.  
  407.     (*$ELSE*)
  408.     MemW_F000:=MemW[$f000:i];
  409.     (*$ENDIF*)
  410.   end;
  411.  
  412. function MemL_F000(const i:word):longint;
  413.   begin
  414.     (*$IFDEF VirtualPascal*)
  415.  
  416.       (*$IFDEF DPMI32*)
  417.       MemL_F000:=MemL[$f0000+i];
  418.       (*$ENDIF*)
  419.  
  420.       (*$IFDEF OS2*)
  421.       MemL_F000:=PLongint(@biosf000[i])^;
  422.       (*$ENDIF*)
  423.  
  424.  
  425.     (*$ELSE*)
  426.     MemL_F000:=MemL[$f000:i];
  427.     (*$ENDIF*)
  428.   end;
  429.  
  430. (*$IFDEF OS2*)
  431. var
  432.   oemhlp_handle :longint;
  433.  
  434. procedure open_oemhlp;
  435.   begin
  436.     if SysFileOpen('OEMHLP$',open_access_readonly+open_share_denynone,oemhlp_handle)<>0 then
  437.        oemhlp_handle:=-1;
  438.   end;
  439.  
  440. procedure close_oemhlp;
  441.   begin
  442.     SysFileClose(oemhlp_handle);
  443.   end;
  444. (*$ENDIF*)
  445.  
  446. (*$IFDEF VirtualPascal*)
  447.  
  448.   (*$IFDEF OS2*)
  449.   function lookup_bios(deviceid,func,bus:byte;index:word) : byte;
  450.  
  451.     var
  452.       para              :
  453.         packed record
  454.           subfuction    :byte;
  455.           busnumber     :byte;
  456.           devfuncnumber :byte;
  457.           configregister:byte;
  458.           size          :byte;
  459.         end;
  460.  
  461.       data              :
  462.         packed record
  463.           returncode    :byte;
  464.           data          :longint;
  465.         end;
  466.  
  467.       para_len,data_len :longint;
  468.  
  469.  
  470.     begin
  471.       with para do
  472.         begin
  473.           subfuction:=3; (* read configuartion byte ($1a/$b108) *)
  474.           busnumber:=bus;
  475.           devfuncnumber:=deviceid shl 3+func;
  476.           configregister:=index;
  477.           size:=SizeOf(byte);
  478.         end;
  479.       para_len:=SizeOf(para);
  480.  
  481.       with data do
  482.         begin
  483.           returncode:=0;
  484.           data:=0;
  485.         end;
  486.       data_len:=SizeOf(data);
  487.  
  488.       errcode:=
  489.         DosDevIoCtl(
  490.           oemhlp_handle,
  491.           $80,              (* oemhlp/testcfg/.. *)
  492.           $0b,              (* PCI *)
  493.           @para,SizeOf(para),@para_len,
  494.           @data,SizeOf(data),@data_len);
  495.  
  496.       if errcode=$00 then
  497.         begin
  498.           failed:=false;
  499.           lookup_bios:=Lo(data.data);
  500.         end;
  501.     end;
  502.  
  503.   procedure pci_present_test;
  504.     var
  505.       para              :
  506.         packed record
  507.           subfuction    :byte;
  508.         end;
  509.  
  510.       data              :
  511.         packed record
  512.           returncode    :byte;
  513.           hardwaremech  :byte;
  514.           majorver      :byte;
  515.           minorver      :byte;
  516.           lastbus       :byte;
  517.         end;
  518.  
  519.       para_len,data_len :longint;
  520.  
  521.  
  522.     begin
  523.       with para do
  524.         begin
  525.           subfuction:=0; (* read configuartion byte ($1a/$b101) *)
  526.         end;
  527.       para_len:=SizeOf(para);
  528.  
  529.       FillChar(data,SizeOf(data),0);
  530.       data_len:=SizeOf(data);
  531.  
  532.       errcode:=
  533.         DosDevIoCtl(
  534.           oemhlp_handle,
  535.           $80,              (* oemhlp/testcfg/.. *)
  536.           $0b,              (* PCI *)
  537.           @para,SizeOf(para),@para_len,
  538.           @data,SizeOf(data),@data_len);
  539.  
  540.       if errcode=$00 then
  541.         with data do
  542.           begin
  543.             PCIchar:=hardwaremech;
  544.             PCI_hibus:=lastbus;
  545.             PCIverlo:=minorver;
  546.             PCIverhi:=majorver;
  547.             failed:=false;
  548.           end;
  549.     end;
  550.  
  551.  
  552.   procedure load_irqbuff;
  553.     begin
  554.       (* failed:=true; *)
  555.     end;
  556.  
  557.   (*$ENDIF OS2*)
  558.  
  559.   (*$IFDEF DPMI32*)
  560.   function lookup_bios(deviceid,func,bus:byte;index:word) : byte;assembler;
  561.     (*$Uses EBX,ECX,EDX,EDI*)(*$Frame-*)
  562.     asm
  563.       mov ax,$b108
  564.       mov bl,deviceid
  565.       shl bl,3
  566.       add bl,func
  567.       mov bh,bus
  568.       mov edi,index
  569.       int $1a
  570.       jc @exit
  571.  
  572.       mov failed,false
  573.     @exit:
  574.       mov errcode,ah
  575.       mov al,cl
  576.     end;
  577.  
  578.  
  579.   procedure pci_present_test;assembler;
  580.     (*$Uses ALL*)(*$Frame-*)
  581.     asm
  582.       mov ax,$b101
  583.       int $1a
  584.       jc @exit
  585.  
  586.       cmp dx,$4350
  587.       jne @exit
  588.  
  589.       mov PCIchar,al
  590.       mov PCI_hibus,cl
  591.       mov PCIverlo,bl
  592.       mov PCIverhi,bh
  593.       mov failed,false
  594.  
  595.     @exit:
  596.     end;
  597.  
  598.   procedure load_irqbuff;
  599.     var
  600.       irq16     :smallword;
  601.       r         :real_mode_call_structure_typ;
  602.     begin
  603.       if GetDosMem(irq16,SizeOf(irqbuff))<>0 then Exit;
  604.       FillChar(Mem[irq16 shl 4],SizeOf(irqbuff),0);
  605.  
  606.       MemW[irq16 shl 4+0]:=SizeOf(irqbuff)-6;
  607.       MemW[irq16 shl 4+2]:=6;
  608.       MemW[irq16 shl 4+4]:=irq16;
  609.  
  610.       with r do
  611.         begin
  612.           init_register(r);
  613.           ax_:=$b10e;
  614.           bx_:=$0000;
  615.           ds_:=$f000;
  616.           es_:=irq16;
  617.           edi_:=0;
  618.  
  619.           intr_realmode(r,$1a);
  620.           Move(Ptr(irq16 shl 4)^,irqbuff,SizeOf(irqbuff));
  621.           len:=MemW[es_ shl 4+edi_];
  622.           freedosmem(irq16);
  623.  
  624.           if ah_<>0 then Exit;
  625.  
  626.           conmap:=bx_;
  627.           failed:=false;
  628.  
  629.         end;
  630.     end;
  631.   (*$ENDIF DPMI32*)
  632.  
  633.   function lookup_hw(deviceid,func,bus:byte;index:word) : byte;assembler;
  634.     (*$Uses ECX*)(*$Frame+*)
  635.     asm
  636.       mov ah,$80
  637.       mov al,bus
  638.       shl eax,16
  639.       mov al,byte ptr[index]
  640.       and al,$fc
  641.       mov ah,deviceid
  642.       shl ah,3
  643.       add ah,func
  644.  
  645.       push eax
  646.       push $0cf8
  647.       call _Out32
  648.  
  649.       mov ecx,index
  650.       and ecx,3
  651.       shl ecx,3 (* *8  *)
  652.  
  653.       push $0cfc
  654.       call _In32
  655.       shr eax,cl
  656.       mov cl,al
  657.       mov failed,false
  658.  
  659.       push 0
  660.       push $0cf8
  661.       call _Out32
  662.  
  663.       mov al,cl
  664.     end;
  665.  
  666.  
  667. (*$ELSE*) (* BP 7.0 *)
  668. function lookup_bios(deviceid,func,bus:byte;index:word) : byte;
  669.  
  670. var inf:byte;
  671.  
  672. begin
  673.   asm
  674.     mov ax,$b108
  675.     mov bl,deviceid
  676.     shl bl,3
  677.     add bl,func
  678.     mov bh,bus
  679.     mov di,index
  680.     int $1a
  681.     jc @exit
  682.  
  683.     mov failed,false
  684.     mov inf,cl
  685.   @exit:
  686.     mov errcode,ah
  687.   end;
  688.   lookup_bios:=inf;
  689. end;
  690.  
  691.  
  692. function lookup_hw(deviceid,func,bus:byte;index:word) : byte;
  693. var inf:byte;
  694.  
  695. begin
  696.   asm
  697.     mov ax,$8000
  698.     mov al,bus
  699.     db $66;shl ax,16
  700.  
  701.     mov ax,index
  702.     and ax,00fch
  703.     mov ah,deviceid
  704.     shl ah,3
  705.     add ah,func
  706.  
  707.     mov dx,0cf8h
  708.     db $66;out dx,ax
  709.  
  710.     mov ax,index
  711.     and ax,3
  712.     mov bl,8
  713.     mul bl
  714.     mov cx,ax
  715.  
  716.     mov dx,0cfch
  717.     db $66;in ax,dx
  718.     db $66;shr ax,cl
  719.     mov inf,al
  720.     mov failed,false
  721.  
  722.  
  723.     db $66;xor ax,ax
  724.     mov dx,0cf8h
  725.     db $66;out dx,ax
  726.  
  727.   end;
  728.   lookup_hw:=inf;
  729. end;
  730.  
  731. procedure pci_present_test;assembler;
  732.   asm
  733.     mov ax,$b101
  734.     int $1a
  735.     jc @exit
  736.  
  737.     cmp dx,$4350
  738.     jne @exit
  739.  
  740.     mov PCIchar,al
  741.     mov PCI_hibus,cl
  742.     mov PCIverlo,bl
  743.     mov PCIverhi,bh
  744.     mov failed,false
  745.  
  746.   @exit:
  747.   end;
  748.  
  749. procedure load_irqbuff;assembler;
  750.   const
  751.     irq_buf_size=SizeOf(irqbuff)-2-4;
  752.   asm
  753.     push ds
  754.  
  755.     mov bx,0
  756.     mov ax,seg irqbuff
  757.     mov es,ax
  758.     mov di,offset irqbuff
  759.     mov word ptr es:[di+0],irq_buf_size
  760.     lea ax,[di+6]
  761.     mov es:[di+2],ax
  762.     mov es:[di+4],es
  763.  
  764.     mov ax,0f000h
  765.     mov ds,ax
  766.     mov ax,0b10eh
  767.  
  768.     int $1a
  769.     pop ds
  770.  
  771.     mov cx,word ptr es:[di]
  772.  
  773.     cmp ah,0
  774.     jne @exit
  775.  
  776.  
  777.     mov conmap,bx
  778.     mov len,cx
  779.     mov failed,false
  780.  
  781.   @exit:
  782.   end;
  783. (*$ENDIF*)
  784.  
  785.  
  786. (*$IFDEF VirtualPascal*)
  787. var
  788.   pcidevs_txt_buffer    :PChar;
  789.   pcidevs_txt_end       :PChar;
  790.   pcidevs_txt_position  :PChar;
  791. (*$ENDIF*)
  792.  
  793. procedure Assign2(var f:text;const filename:string);
  794.   (*$IFDEF VirtualPascal*)
  795.   var
  796.     f2                  :file;
  797.     f2s                 :longint;
  798.  
  799.   begin
  800.     pcidevs_txt_buffer  :=nil;
  801.     pcidevs_txt_end     :=nil;
  802.     pcidevs_txt_position:=nil;
  803.  
  804.     Assign(f2,filename);
  805.     (*$I-*)
  806.     Reset(f2,1);
  807.     (*$I+*)
  808.     if InOutRes<>0 then Exit;
  809.  
  810.     f2s:=FileSize(f2);
  811.     GetMem(pcidevs_txt_buffer,f2s+2);
  812.     pcidevs_txt_buffer[f2s  ]:=#$0d;
  813.     pcidevs_txt_buffer[f2s+1]:=#$0a;
  814.     BlockRead(f2,pcidevs_txt_buffer[0],f2s);
  815.     Close(f2);
  816.  
  817.     pcidevs_txt_end     :=@pcidevs_txt_buffer[f2s];
  818.     pcidevs_txt_position:=pcidevs_txt_buffer;
  819.   end;
  820.   (*$ELSE*)
  821.   begin
  822.     Assign(f,filename);
  823.   end;
  824.   (*$ENDIF*)
  825.  
  826. procedure Reset2(var f:text);
  827.   (*$IFDEF VirtualPascal*)
  828.   begin
  829.     pcidevs_txt_position:=pcidevs_txt_buffer;
  830.   end;
  831.   (*$ELSE*)
  832.   begin
  833.     Reset(f);
  834.   end;
  835.   (*$ENDIF*)
  836.  
  837.  
  838. procedure ReadLn2(var f:text;var zk:string);
  839.   (*$IFDEF VirtualPascal*)
  840.   begin
  841.     zk:='';
  842.     repeat
  843.       case pcidevs_txt_position[0] of
  844.         ^Z,
  845.         #$0d:
  846.           Inc(pcidevs_txt_position);
  847.         #$0a:
  848.           begin
  849.             Inc(pcidevs_txt_position);
  850.             Exit;
  851.           end;
  852.       else
  853.         zk:=zk+pcidevs_txt_position[0];
  854.         Inc(pcidevs_txt_position);
  855.       end;
  856.     until false;
  857.   end;
  858.   (*$ELSE*)
  859.   begin
  860.     ReadLn(f,zk);
  861.   end;
  862.   (*$ENDIF*)
  863.  
  864.  
  865. function Eof2(var f:text):boolean;
  866.   (*$IFDEF VirtualPascal*)
  867.   begin
  868.     Eof2:=(pcidevs_txt_position=pcidevs_txt_end);
  869.   end;
  870.   (*$ELSE*)
  871.   begin
  872.     Eof2:=Eof(f);
  873.   end;
  874.   (*$ENDIF*)
  875.  
  876.  
  877. procedure Close2(var f:text);
  878.   (*$IFDEF VirtualPascal*)
  879.   begin
  880.   end;
  881.   (*$ELSE*)
  882.   begin
  883.     Close(f);
  884.   end;
  885.   (*$ENDIF*)
  886.  
  887.  
  888.  
  889. procedure listmap(va:word;dispst:string);
  890. var
  891.   comma  : byte;
  892.   failed : boolean;
  893.   l,
  894.   j      : word;
  895.  
  896. begin
  897.   failed:=true;
  898.   Write(dispst);
  899.   comma:=0;
  900.   for l:=0 to 15 do if (va and (1 shl l))>0 then Inc(comma);
  901.  
  902.   l:=1;
  903.   j:=0;
  904.   repeat
  905.     if (va and l)=l then
  906.     begin
  907.       Write(j);
  908.       if comma>1 then Write(',') else Write(' ');
  909.       Dec(comma);
  910.       failed:=false;
  911.     end;
  912.     l:=l shl 1;
  913.     Inc(j);
  914.   until j=16;
  915.   if failed then WriteLn('None') else WriteLn;
  916. end;
  917.  
  918.  
  919. procedure lookupven(silent:boolean);
  920. begin
  921.   Reset2(f);
  922.   failed:=true;
  923.   repeat
  924.     ReadLn2(f,vstr);
  925.     if (vstr[1]='V') and (Copy(vstr,3,4)=cmpstr) then
  926.     begin
  927.       TextColor(14);
  928.       if not silent then Write(Copy(vstr,8,Length(vstr)));
  929.       TextColor(7);
  930.       failed:=false;
  931.     end;
  932.   until Eof2(f) or not failed;
  933.   if failed then
  934.   begin
  935.     TextColor(12);
  936.     if not silent then Write('Unknown');
  937.     TextColor(7);
  938.   end;
  939. end;
  940.  
  941. procedure lookupdev;
  942. begin
  943.   failed:=true;
  944.   if not Eof2(f) then
  945.   begin
  946.     repeat
  947.       ReadLn2(f,vstr);
  948.       if (vstr[1]='D') and (Copy(vstr,3,4)=cmpstr) then
  949.       begin
  950.         if not Eof2(f) then ReadLn2(f,revchk);
  951.         if revchk[1]='R' then
  952.         begin
  953.           repeat
  954.             if wrhex(infotbl[8])=Copy(revchk,3,2) then vstr:='xxxxxxx'+Copy(revchk,6,Length(revchk));
  955.             if not Eof2(f) then ReadLn2(f,revchk);
  956.           until revchk[1]<>'R';
  957.         end;
  958.         TextColor(14);
  959.         Write(Copy(vstr,8,Length(vstr)));
  960.         failed:=false;
  961.         TextColor(7);
  962.       end;
  963.     until Eof2(f) or not failed or (vstr[1]='V');
  964.   end;
  965.   if failed then
  966.   begin
  967.     TextColor(12);
  968.     Write('Unknown');
  969.     TextColor(7);
  970.   end;
  971. end;
  972.  
  973.  
  974. begin
  975.   (*$IFDEF OS2*)
  976.   open_oemhlp;
  977.   os2_read_bios;
  978.   (*$ENDIF*)
  979.  
  980.   showhelp:=false;
  981.   businfo:=false;
  982.   dorouting:=true;
  983.   dopcirouting:=false;
  984.   dumpregs:=false;
  985.   usebios:=true;
  986.   summary:=false;
  987.  
  988. { the following hack permits MS-DOS display output redirection to work }
  989.   if ioredirected then
  990.     begin
  991.       WriteLn('Craig Hart''s PCI+AGP bus sniffer, version ',revision,', freeware made in 1996-2000.');
  992.       Assign(output,'');
  993.       Rewrite(output);
  994.     end
  995.   else
  996.     begin
  997.        ClrScr;
  998.        linecounter:=0;
  999.        { insert page filter }
  1000.        with TextRec(Output) do
  1001.          begin
  1002.            org_output_FlushFunc:=FlushFunc;
  1003.            FlushFunc:=@page_output_FlushFunc;
  1004.          end;
  1005.     end;
  1006.  
  1007.  
  1008.  
  1009.   for i:=0 to 15 do irqmap[i]:=0;
  1010.   failed:=true;
  1011.  
  1012.   { calculate datafile searchpath: exefile path,... }
  1013.   pcidevs_path:=ParamStr(0);
  1014.   while (not (pcidevs_path[Length(pcidevs_path)] in ['\','/'])) and (pcidevs_path<>'') do
  1015.     Dec(pcidevs_path[0]);
  1016.  
  1017.   pcidevs_path:=pcidevs_path+';'+GetEnv('PATH')+';'+GetEnv('DPATH');
  1018.  
  1019.   pcidevs_txt:=FSearch('pcidevs.txt',pcidevs_path);
  1020.  
  1021.   {$i-}
  1022.   if pcidevs_txt<>'' then
  1023.     begin
  1024.       Assign2(f,pcidevs_txt);
  1025.       Reset2(f);
  1026.     end;
  1027.  
  1028.   if (IOResult<>0) or (pcidevs_txt='') then
  1029.   begin
  1030.     WriteLn('PCI Halted:');
  1031.     WriteLn;
  1032.     WriteLn('Sorry, I cannot locate my PCIDEVS.TXT datafile!!!');
  1033.     Halt(10);
  1034.   end;
  1035.   Close2(f);
  1036.   {$i+}
  1037.  
  1038.  
  1039.  
  1040.   if ParamCount>0 then
  1041.   begin
  1042.     for i:=1 to ParamCount do
  1043.     begin
  1044.       cmdstr:=ParamStr(i);
  1045.       for j:=1 to Length(cmdstr) do cmdstr[j]:=UpCase(cmdstr[j]);
  1046.       if (Length(cmdstr)=Length('-?')) and (cmdstr[1] in ['+','-','/']) then
  1047.         case cmdstr[2] of
  1048.           'H':usebios:=false;
  1049.           'D':dumpregs:=true;
  1050.           'S':summary:=true;
  1051.           'T':dorouting:=false;
  1052.           'P':dopcirouting:=true;
  1053.           'B':businfo:=true;
  1054.         else
  1055.               showhelp:=true;
  1056.         end
  1057.       else
  1058.         showhelp:=true;
  1059.  
  1060.       if showhelp then
  1061.       begin
  1062.         TextMode(Co80);
  1063.         linecounter:=0;
  1064.         WriteLn(' Help for PCI  (Version ',revision,')');
  1065.         TextColor(8);
  1066.         WriteLn('───────────────────────────────');
  1067.         TextColor(7);
  1068.         WriteLn;
  1069.         WriteLn('Usage: PCI [-H] [-D] [-S] [-T] [-B] [-P] [-?]   [] indicates optional parameter');
  1070.         WriteLn;
  1071.         WriteLn;
  1072.         WriteLn('-H : Use direct hardware access (instead of the BIOS) to retrieve PCI Info');
  1073.         WriteLn('     May be required for accurate reporting on Intel 430FX chipset+Award BIOS');
  1074.         WriteLn('-D : Do a hex-dump of each device''s configuration space');
  1075.         WriteLn('-S : Create a brief, summary report only; only devices and IRQs listed');
  1076.         WriteLn('-T : Disable test ROM IRQ Routing Table function');
  1077.         WriteLn('-B : Enable display of Bus, Device & Function info');
  1078.         WriteLn('-P : Enable display of PCI slot routing data');
  1079.         WriteLn('-? : Displays this help screen!');
  1080.         WriteLn;
  1081.         WriteLn;
  1082.         WriteLn('PCI Supports generating reports to a file or printer using MS-DOS pipes; i.e.');
  1083.         WriteLn;
  1084.         WriteLn('      PCI -D > REPORT.TXT             PCI > LPT1:           PCI | MORE');
  1085.         WriteLn;
  1086.         WriteLn('PCI is written by Craig Hart, and is released as freeware, with no restictions');
  1087.         Write('on use or copying. Visit ');
  1088.         TextColor(11);
  1089.         Write('http://members.hyperlink.net.au/~chart ');
  1090.         TextColor(7);
  1091.         WriteLn('for updates to');
  1092.         WriteLn('the program and the PCI Database file PCIDEVS.TXT');
  1093.         Halt(10);
  1094.       end;
  1095.     end;
  1096.   end;
  1097.  
  1098.  
  1099.   if test8086<2 then
  1100.   begin
  1101.     WriteLn('PCI Halted:');
  1102.     WriteLn;
  1103.     WriteLn('PC Must be at least a 386 to possibly have a PCI or AGP bus!');
  1104.     Halt(1);
  1105.   end;
  1106.  
  1107. { Look for PCI BIOS }
  1108.   pci_present_test;
  1109.  
  1110.  
  1111.  
  1112.   if failed then
  1113.   begin
  1114.     WriteLn('PCI Halted:');
  1115.     WriteLn;
  1116.     WriteLn('No PCI BIOS was detected! (NB: This always fails under Windows NT!)');
  1117.     Halt(2);
  1118.   end;
  1119.  
  1120.  
  1121. { OK, we have PCI... do our stuff.. }
  1122.  
  1123.  
  1124.   begin
  1125.     if not ioredirected then TextMode(Co80+Font8x8);
  1126.     linecounter:=0;
  1127.     WriteLn(' Craig Hart''s PCI+AGP bus sniffer, version ',revision,', freeware made in 1996-2000.');
  1128.     WriteLn;
  1129.     Write('PCI BIOS Version ',PCIverhi,'.',wrhex(PCIverlo),' found!');
  1130.  
  1131.     if summary then WriteLn('                                  (Summary Report)') else WriteLn;
  1132.  
  1133.     WriteLn;
  1134.     WriteLn('Number of PCI Busses : ',PCI_hibus+1);
  1135.     Write('PCI Characteristics  : ');
  1136.     if PCIchar and 1=1 then Write('Config Mechanism 1 ') else usebios:=true; { must use BIOS if no cfg mech 1 supported }
  1137.     if PCIchar and 2=2 then Write('Config Mechanism 2 ');
  1138.     if PCIchar and 16=16 then Write('Special Cycle Mechanism 1 ');
  1139.     if PCIchar and 32=32 then Write('Special Cycle Mechanism 2 ');
  1140.     WriteLn;
  1141.     WriteLn;
  1142.     Write('Searching for PCI Devices using ');
  1143.     if usebios then WriteLn('the System BIOS') else WriteLn('Configuration Mechanism 1');
  1144.     WriteLn;
  1145.  
  1146.     for bus:=0 to pci_hibus do          { fix bugs for 440LX chipset, 2 PCI busesAGP=1 bus! }
  1147.     begin
  1148.     for deviceid:=0 to $1f do
  1149.     begin
  1150.       for func:=0 to 7 do
  1151.       begin
  1152.         index:=0;
  1153.         repeat
  1154.           if usebios then info:=lookup_bios(deviceid,func,bus,index) else info:=lookup_hw(deviceid,func,bus,index);
  1155.           infotbl[index]:=info;
  1156.           Inc(index);
  1157. { don't try to read cfg-space of non-existant devices: hangs some chipsets!}
  1158.           if index=2 then if (infotbl[0]=$ff) and (infotbl[1]=$ff) then index:=$100;
  1159.         until index=$100;
  1160.  
  1161.  
  1162.  
  1163.         if (infotbl[0]<>$ff) or (infotbl[1]<>$ff) then
  1164.         begin
  1165.           if businfo then
  1166.           begin
  1167.             Write(' PCI Bus ');
  1168.             TextColor(11);
  1169.             Write(bus);
  1170.             TextColor(7);
  1171.             Write(', Device Number ');
  1172.             TextColor(11);
  1173.             Write(deviceid);
  1174.             TextColor(7);
  1175.             Write(', Device Function ');
  1176.             TextColor(11);
  1177.             WriteLn(func);
  1178.             TextColor(7);
  1179.           end;
  1180.  
  1181.           Write(' Vendor ',wrhexw(infotbl[1] shl 8+infotbl[0]),'h ');
  1182.           cmpstr:=wrhexw(infotbl[1] shl 8+infotbl[0]);
  1183.           lookupven(false);
  1184.           WriteLn;
  1185.  
  1186.  
  1187.           Write(' Device ',wrhexw(infotbl[3] shl 8+infotbl[2]),'h ');
  1188.           cmpstr:=wrhexw(infotbl[3] shl 8+infotbl[2]);
  1189.           lookupdev;
  1190.           WriteLn;
  1191.  
  1192.  
  1193.           if not summary then
  1194.           begin
  1195.             Write(' Command ',wrhexw(infotbl[5] shl 8+infotbl[4]),'h');
  1196.             if infotbl[5] shl 8+infotbl[4] > 0 then
  1197.             begin
  1198.               first:=true;
  1199.               Write(' (');
  1200.               if infotbl[4] and 1=1 then printstatus('I/O Access');
  1201.               if infotbl[4] and 2=2 then printstatus('Memory Access');
  1202.               if infotbl[4] and 4=4 then printstatus('BusMaster');
  1203.               if infotbl[4] and 8=8 then printstatus('Special Cycles');
  1204.               if infotbl[4] and 16=16 then printstatus('MemWrite+Invalidate');
  1205.               if infotbl[4] and 32=32 then printstatus('VGA Palette Snoop');
  1206.               if infotbl[4] and 64=64 then printstatus('Parity Error Response');
  1207.               if infotbl[4] and 128=128 then printstatus('Wait Cycles');
  1208.  
  1209.               if infotbl[5] and 1=1 then printstatus('System Errors');
  1210.               if infotbl[5] and 2=2 then printstatus('Back-To-Back Transactions');
  1211.  
  1212.               Write(')');
  1213.             end;
  1214.             WriteLn;
  1215.  
  1216.  
  1217.             Write(' Status ',wrhexw(infotbl[7] shl 8+infotbl[6]),'h');
  1218.             if (infotbl[6]<>0) or (infotbl[7]<>0) then
  1219.             begin
  1220.               first:=true;
  1221.               Write(' (');
  1222.               if infotbl[6] and 16=16 then printstatus('Has Capabilities List');
  1223.               if infotbl[6] and 32=32 then printstatus('Supports 66MHz');
  1224.               if infotbl[6] and 64=64 then printstatus('Has UDF');
  1225.               if infotbl[6] and 128=128 then printstatus('Supports Back-To-Back Trans.');
  1226.  
  1227.               if infotbl[7] and 1=1 then printstatus('Data parity Error Detected');
  1228.               if infotbl[7] and 8=8 then printstatus('Signalled Target Abort');
  1229.               if infotbl[7] and 16=16 then printstatus('Received Target Abort');
  1230.               if infotbl[7] and 32=32 then printstatus('Received Master Abort');
  1231.               if infotbl[7] and 64=64 then printstatus('Signalled System Error');
  1232.               if infotbl[7] and 128=128 then printstatus('Detected Parity Error');
  1233.  
  1234.               case ((infotbl[7] and 6) shr 1) of
  1235.                 0 : printstatus('Fast Timing');
  1236.                 1 : printstatus('Medium Timing');
  1237.                 2 : printstatus('Slow Timing');
  1238.                 3 : printstatus('Unknown Timing');
  1239.               end;
  1240.               Write(')');
  1241.  
  1242.             end;
  1243.             WriteLn;
  1244.  
  1245.             Write(' Revision ',wrhex(infotbl[8]),'h');
  1246.             Write(', Header Type ',wrhex(infotbl[$e]),'h');
  1247.             WriteLn(', Bus Latency ',wrhex(infotbl[$d]),'h');
  1248.  
  1249.  
  1250.             Write(' Self test ',wrhex(infotbl[$f]),'h (Self test ');
  1251.             if infotbl[$f] and $80=0 then Write('not ');
  1252.             Write('supported');
  1253.  
  1254.  
  1255.             if infotbl[$f] and $80=$80 then
  1256.             begin
  1257.               Write(': Completion code ',wrhexb(infotbl[$f] and $f),'h - ');
  1258.               if infotbl[$f] and $f=0 then
  1259.               begin
  1260.                 TextColor(10);
  1261.                 Write('OK');
  1262.                 TextColor(7);
  1263.               end else
  1264.               begin
  1265.                 TextColor(12);
  1266.                 Write('Failed!!');
  1267.                 TextColor(7);
  1268.               end;
  1269.             end;
  1270.  
  1271.  
  1272.  
  1273.             WriteLn(')');
  1274.  
  1275.  
  1276.             if infotbl[$c]<>0 then WriteLn(' Cache line size ',infotbl[$c]*4,' Bytes (',infotbl[$c],' DWords)');
  1277.  
  1278.  
  1279.             Write(' PCI Class ');
  1280.             for i:=0 to high_class_name do
  1281.             if infotbl[$b]=i then
  1282.             begin
  1283.               TextColor(14);
  1284.               Write(PCI_class_names[i]);
  1285.               TextColor(7);
  1286.             end;
  1287.  
  1288.             Write(' Subclass ');
  1289.             for i:=0 to high_class_array do
  1290.             if (infotbl[$b] shl 8 + infotbl[$a])=PCI_class_array[i].class then
  1291.             begin
  1292.               TextColor(14);
  1293.               Write(PCI_class_array[i].name);
  1294.               TextColor(7);
  1295.             end;
  1296.  
  1297.             Write(' Interface ');
  1298.             WriteLn(wrhex(infotbl[9]),'h');
  1299.  
  1300.           end;
  1301.  
  1302.  
  1303.  
  1304.           if not summary then
  1305.           begin
  1306. { look for generic PCI IDE controller & decode it's info, if present }
  1307.            if (infotbl[$b]=01) and (infotbl[$a]=01) then
  1308.            begin
  1309.              WriteLn(' PCI EIDE Controller Features :');
  1310.              Write('  BusMaster EIDE is ');
  1311.              if infotbl[$9] and $80=0 then
  1312.              begin
  1313.                TextColor(12);
  1314.                Write('NOT ');
  1315.                TextColor(7);
  1316.              end;
  1317.              WriteLn('supported');
  1318.  
  1319.              Write('  Primary   Channel is ');
  1320.              if infotbl[$9] and 1=0 then
  1321.              begin
  1322.                WriteLn('at I/O Port 01F0h and IRQ 14');
  1323.                Inc(irqmap[14]);
  1324.              end else WriteLn('in native mode at Addresses 0 & 1');
  1325.              Write('  Secondary Channel is ');
  1326.              if infotbl[$9] and 4=0 then
  1327.              begin
  1328.                WriteLn('at I/O Port 0170h and IRQ 15');
  1329.                Inc(irqmap[15]);
  1330.              end else WriteLn('in native mode at Addresses 2 & 3');
  1331.            end;
  1332.  
  1333.            end else
  1334.            begin
  1335. { summary mode: pick up IRQs only }
  1336.              if (infotbl[$b]=01) and (infotbl[$a]=01) then
  1337.              begin
  1338.                if infotbl[$9] and 1=0 then Inc(irqmap[14]);
  1339.                if infotbl[$9] and 4=0 then Inc(irqmap[15]);
  1340.              end;
  1341.            end;
  1342.  
  1343.  
  1344.  
  1345.  
  1346. { if type 0 table & if Subsystem ID exists, display and scan file for match }
  1347.            if infotbl[$e] and $7f=0 then
  1348.            if (infotbl[$2c]<>0) or (infotbl[$2d]<>0) or (infotbl[$2e]<>0) or (infotbl[$2f]<>0) then
  1349.            begin
  1350.  
  1351. { subsystem ID }
  1352.  
  1353.              Write(' Subsystem ID ',wrhexw(infotbl[$2f] shl 8+infotbl[$2e]));
  1354.              Write(wrhexw(infotbl[$2d] shl 8+infotbl[$2c]),'h');
  1355.              cmpstr:=wrhexw(infotbl[$2f] shl 8+infotbl[$2e])+wrhexw(infotbl[$2d] shl 8+infotbl[$2c]);
  1356.  
  1357.  
  1358.              genssid:=false;
  1359.              if (infotbl[$2c]=infotbl[0])
  1360.              and (infotbl[$2d]=infotbl[1])
  1361.              and (infotbl[$2e]=infotbl[2])
  1362.              and (infotbl[$2f]=infotbl[3]) then genssid:=true;
  1363.  
  1364.              oemidnum:='';
  1365.              oemidstr:='';
  1366.              bogusid:=false;
  1367.  
  1368.  
  1369.              failed:=true;
  1370.              userev:=true;
  1371.              if not Eof2(f) then
  1372.              begin
  1373.                repeat
  1374. {!!}             if userev then vstr:=revchk else ReadLn2(f,vstr);
  1375.                  userev:=false;
  1376.  
  1377.  
  1378. { OEM Vendor ID }
  1379.                  if vstr[1]='O' then
  1380.                  begin
  1381.                    if Copy(vstr,3,4)=Copy(cmpstr,5,4) then
  1382.                    begin
  1383.                      oemidstr:=Copy(vstr,8,Length(vstr)); { closest match }
  1384.                      oemidnum:=Copy(vstr,3,4); { matching vendor name }
  1385.                    end;
  1386.                  end;
  1387.  
  1388.  
  1389.                  if vstr[1]='S' then
  1390.                  begin
  1391.                    if Copy(vstr,3,4)=Copy(cmpstr,1,4) then
  1392.                    begin
  1393.                      if oemidnum<>'' then
  1394.                      begin
  1395.                        oemidstr:=Copy(vstr,8,Length(vstr));
  1396.                        begin
  1397.                          TextColor(14);
  1398.                          Write(' ',oemidstr);
  1399.                          if genssid then
  1400.                          begin
  1401.                            TextColor(11);
  1402.                            WriteLn(' (Generic ID)')
  1403.                          end else WriteLn;
  1404.                          failed:=false;
  1405.                          TextColor(7);
  1406.                        end;
  1407.                      end;
  1408.                    end;
  1409.                  end;
  1410.  
  1411.  
  1412.  
  1413.  
  1414.  
  1415.  
  1416.  
  1417. { Oddball 8 digit entry }
  1418.                  if (vstr[1]='X') and (Copy(vstr,3,8)=cmpstr) then
  1419.                  begin
  1420.                    oemidnum:=Copy(vstr,7,4); { matching vendor name }
  1421.                    bogusid:=true;
  1422.                    TextColor(14);
  1423.                    Write(' ',Copy(vstr,12,Length(vstr)));
  1424.                    if genssid then
  1425.                    begin
  1426.                      TextColor(11);
  1427.                      WriteLn(' (Generic ID)')
  1428.                    end else WriteLn;
  1429.                    failed:=false;
  1430.                    TextColor(7);
  1431.                  end;
  1432.  
  1433.  
  1434.  
  1435.                until Eof2(f) or not failed or ((vstr[1]<>'O') and (vstr[1]<>'X') and (vstr[1]<>'S'));
  1436.              end;
  1437.  
  1438.  
  1439.  
  1440.  
  1441.  
  1442.  
  1443.              if failed then
  1444.              begin
  1445.                if oemidstr<>'' then
  1446.                begin
  1447.                  TextColor(14);
  1448.                  Write(' ',oemidstr);
  1449.                  TextColor(15);
  1450.                  Write(' (Guess Only!)');
  1451.                  TextColor(7);
  1452.                end else
  1453.                begin
  1454.                  TextColor(12);
  1455.                  Write(' Unknown');
  1456.                end;
  1457.  
  1458.                if genssid then
  1459.                begin
  1460.                  TextColor(11);
  1461.                  WriteLn(' (Generic ID)')
  1462.                end else WriteLn;
  1463.                TextColor(7);
  1464.              end;
  1465.  
  1466.  
  1467. { subsystem vendor }
  1468.              Write(' Subsystem Vendor ',wrhexw(infotbl[$2d] shl 8+infotbl[$2c]),'h');
  1469.  
  1470.              if bogusid then
  1471.              begin
  1472.                TextColor(15);
  1473.                WriteLn(' Known Bad Subsystem ID - no Vendor ID readable');
  1474.                TextColor(7);
  1475.              end else
  1476.              begin
  1477.                if oemidnum<>'' then cmpstr:=oemidnum
  1478.                else cmpstr:=wrhexw(infotbl[$2d] shl 8+infotbl[$2c]);
  1479.                Close2(f);                { get back to start of file, as the}
  1480.                Reset2(f);                { subsys vendor may be higher up...!}
  1481.                failed:=true;
  1482.                if not Eof2(f) then
  1483.                begin
  1484.                  repeat
  1485.                    ReadLn2(f,vstr);
  1486.                    if (vstr[1]='V') and (Copy(vstr,3,4)=cmpstr) then
  1487.                    begin
  1488.                      TextColor(14);
  1489.                      WriteLn(' ',Copy(vstr,8,Length(vstr)));
  1490.                      failed:=false;
  1491.                      TextColor(7);
  1492.                    end;
  1493.                  until Eof2(f) or not failed;
  1494.                end;
  1495.                if failed then
  1496.                begin
  1497.                  TextColor(12);
  1498.                  WriteLn(' Unknown');
  1499.                  TextColor(7);
  1500.                end;
  1501.              end;
  1502.            end;
  1503.  
  1504.  
  1505. { always }
  1506.            Close2(f);
  1507.  
  1508.  
  1509.  
  1510.            if not summary then
  1511.            begin
  1512.  
  1513. { type 0 header = 5 entries, type 1 = 2, type 2 = skip }
  1514.            pp:=0;
  1515.            if infotbl[$e] and $7f=0 then pp:=5;
  1516.            if infotbl[$e] and $7f=1 then pp:=1;
  1517.  
  1518.  
  1519.            if pp>0 then for nn:=0 to pp do
  1520.            begin
  1521.              if infotbl[$10+(nn*4)]+infotbl[$11+(nn*4)]+
  1522.                infotbl[$12+(nn*4)]+infotbl[$13+(nn*4)]<>0 then
  1523.              begin
  1524.                Write(' Address ',nn,' is a');
  1525.                if infotbl[$10+(nn*4)] and 1=1 then
  1526.                begin
  1527.                  Write('n I/O Port : ');
  1528.                  addr:=infotbl[$13+(nn*4)] shl 8 + infotbl[$12+(nn*4)];
  1529.                  Write(wrhexw(addr));
  1530.                  addr:=infotbl[$11+(nn*4)] shl 8 + (infotbl[$10+(nn*4)] and $fc);
  1531.                  Write(wrhexw(addr),'h');
  1532.                end else
  1533.                begin
  1534.                  Write(' Memory Address');
  1535.                  if infotbl[$10+(nn*4)] and 6=0 then Write(' (anywhere in 0-4Gb');
  1536.                  if infotbl[$10+(nn*4)] and 6=2 then Write(' (below 1Mb');
  1537.                  if infotbl[$10+(nn*4)] and 6=4 then Write(' (anywhere in 64-bit space');
  1538.                  if infotbl[$10+(nn*4)] and 6=6 then Write(' (reserved');
  1539.                  if infotbl[$10+(nn*4)] and 8=8 then Write(', Prefetchable) : ') else Write(') : ');
  1540.                  addr:=infotbl[$13+(nn*4)] shl 8 + infotbl[$12+(nn*4)];
  1541.                  Write(wrhexw(addr));
  1542.                  addr:=infotbl[$11+(nn*4)] shl 8 + (infotbl[$10+(nn*4)] and $f0);
  1543.                  Write(wrhexw(addr)+'h');
  1544.                end;
  1545.                WriteLn;
  1546.              end;
  1547.            end;
  1548.  
  1549.  
  1550.            end;
  1551.  
  1552.  
  1553. { all header types - list IRQ, if present }
  1554.            if (infotbl[$3c]<16) and (infotbl[$3c]>0) then
  1555.            begin
  1556.              Write(' System IRQ ',infotbl[$3c],', INT# ');
  1557.              if infotbl[$3d]=0 then Write('-') else Write(Chr(infotbl[$3d]+64));
  1558.              WriteLn;
  1559.              Inc(irqmap[infotbl[$3c]]);
  1560.            end;
  1561.  
  1562.  
  1563.  
  1564.  
  1565.            if not summary then
  1566.            begin
  1567.  
  1568.  
  1569.  
  1570. { type 0,1 header - List ExpROM, if present }
  1571.            if (infotbl[$e] and $7f=0) or (infotbl[$e] and $7f=1) then
  1572.            begin
  1573.              if infotbl[$e] and $7f=0 then lb:=$30;
  1574.              if infotbl[$e] and $7f=1 then lb:=$38;
  1575.              if (infotbl[lb+3]<>0) or (infotbl[lb+2]<>0) or (infotbl[lb+1] and $f8<>0) then
  1576.              begin
  1577.                Write(' Expansion ROM at ',wrhexw(infotbl[lb+3] shl 8+infotbl[lb+2]));
  1578.                Write(wrhex(infotbl[lb+1] and $f8),'00h is ');
  1579.                if infotbl[lb] and 1=1 then WriteLn('enabled') else WriteLn('disabled');
  1580.              end;
  1581.            end;
  1582.  
  1583.            end;
  1584.  
  1585.  
  1586.  
  1587. { type 1 header only - List bus numbers etc }
  1588.  
  1589.            if not summary then
  1590.            begin
  1591.  
  1592.  
  1593.  
  1594.            if infotbl[$e] and $7f=1 then
  1595.            begin
  1596.              Write(' Primary bus number ',infotbl[$18],', Secondary bus number ',infotbl[$19]);
  1597.              WriteLn(', Subordinate bus number ',infotbl[$1a]);
  1598.  
  1599.              Write(' Secondary bus latency ',wrhex(infotbl[$1b]),'h');
  1600.              WriteLn(', Secondary bus status ',wrhex(infotbl[$1f]),wrhex(infotbl[$1e]),'h');
  1601.  
  1602.              first:=true;
  1603.              Write(' Secondary bus controls : ');
  1604.              if infotbl[$3e] and 1=1 then printstatus('parity detection');
  1605.              if infotbl[$3e] and 4=4 then printstatus('ISA mapping');
  1606.              if infotbl[$3e] and 8=8 then printstatus('VGA mapping');
  1607.              if infotbl[$3e] and 32=32 then printstatus('master abort mode');
  1608.              if infotbl[$3e] and 128=128 then printstatus('back-to-back transactions');
  1609.              WriteLn;
  1610.  
  1611.  
  1612. { I/O ports range accessable beyond bridge }
  1613.              if (infotbl[$1c]<>0) or (infotbl[$1d]<>0) then
  1614.              begin
  1615.                Write(' I/O Port range accessable beyond bridge : ');
  1616.                if infotbl[$1c] and $f=0 then Write(wrhexb(infotbl[$1c] shr 4),'000h to ') else
  1617.                  Write(wrhex(infotbl[$31]),wrhex(infotbl[$30]),wrhexb(infotbl[$1c] shr 4),'000h to ');
  1618.                if infotbl[$1d] and $f=0 then WriteLn(wrhexb(infotbl[$1d] shr 4),'FFFh') else
  1619.                  WriteLn(wrhex(infotbl[$33]),wrhex(infotbl[$32]),wrhexb(infotbl[$1d] shr 4),'FFFh');
  1620.              end;
  1621.  
  1622.  
  1623.  
  1624.            end;
  1625.            end;
  1626.  
  1627.  
  1628.  
  1629. { type 2 header only - List bus numbers etc }
  1630.  
  1631.            if not summary then
  1632.            begin
  1633.              if infotbl[$e] and $7f=2 then
  1634.              begin
  1635.                Write(' PCI bus number ',infotbl[$18],', CardBus bus number ',infotbl[$19]);
  1636.                WriteLn(', Subordinate bus number ',infotbl[$1a]);
  1637.                WriteLn(' CardBus latency ',wrhex(infotbl[$1b]),'h');
  1638.              end;
  1639.            end;
  1640.  
  1641.  
  1642.  
  1643.  
  1644.  
  1645.            if not summary then
  1646.            begin
  1647.  
  1648.  
  1649.  
  1650.  
  1651.  
  1652. { explore the capabilities list, if present
  1653.   (should ony be in type 0 or 2 headers???
  1654.   - not according to DEC 21150 pci bridge!)
  1655. }
  1656.  
  1657.            if infotbl[6] and $10=$10 then
  1658.            begin
  1659.              WriteLn(' Capabilities List Information :');
  1660. {type 0}     if infotbl[$e] and $7f=0 then cap_ptr:=infotbl[$34];
  1661. {type 1}     if infotbl[$e] and $7f=1 then cap_ptr:=infotbl[$34];
  1662. {type 2}     if infotbl[$e] and $7f=2 then cap_ptr:=infotbl[$14];
  1663.              repeat
  1664.                case infotbl[cap_ptr] of
  1665.  
  1666.                  01 : begin
  1667.                         WriteLn('  Power Management Capabilities');
  1668. {                        WriteLn('  PM Capabilities : ',wrhexw(infotbl[cap_ptr+3] shl 8 + infotbl[cap_ptr+2]),'h');}
  1669. {                        WriteLn('  PM Status : ',wrhexw(infotbl[cap_ptr+5] shl 8 + infotbl[cap_ptr+4]),'h');}
  1670. {                        WriteLn('  PM Bridge Extensions : ',wrhex(infotbl[cap_ptr+6]),'h');}
  1671. {                        WriteLn('  PM Data Register : ',wrhex(infotbl[cap_ptr+7]),'h');}
  1672.                         if infotbl[cap_ptr+3] and 4=4 then WriteLn('    Supports Power state D2');
  1673.                         if infotbl[cap_ptr+3] and 2=2 then WriteLn('    Supports Power state D1');
  1674.                         if infotbl[cap_ptr+3] and 1=0 then WriteLn('    Supports reduced clock speed (when idle)');
  1675.                         Write('    Current power state : D');
  1676.                         case infotbl[cap_ptr+4] and 3 of
  1677.                           0 : WriteLn('0');
  1678.                           1 : WriteLn('1');
  1679.                           2 : WriteLn('2');
  1680.                           3 : WriteLn('3');
  1681.                         end;
  1682.                       end;
  1683.  
  1684.  
  1685.                  02 : begin
  1686.                         Write('  AGP Capabilities, Version ');
  1687.                         WriteLn(infotbl[cap_ptr+2] shr 4,'.',infotbl[cap_ptr+2] and $0f);
  1688.  
  1689.                         { Status register }
  1690.  
  1691.                         Write('    AGP Speed(s) Supported : ');
  1692.                         if infotbl[cap_ptr+4] and 1=1 then Write('1x ');
  1693.                         if infotbl[cap_ptr+4] and 2=2 then Write('2x ');
  1694.                         if infotbl[cap_ptr+4] and 4=4 then Write('4x ');
  1695.                         if infotbl[cap_ptr+4] and 7=0 then
  1696.                         begin
  1697.                           TextColor(12);
  1698.                           Write('None!!');
  1699.                           TextColor(11);
  1700.                           Write(' (Assume Only 1x Support)');
  1701.                           TextColor(7);
  1702.                         end;
  1703.                         WriteLn;
  1704.  
  1705.                         Write('    FW Transfers Supported : ');
  1706.                         if infotbl[cap_ptr+4] and $10=$10 then WriteLn('Yes') else WriteLn('No');
  1707.  
  1708.                         Write('    >4Gb Address Space Supported : ');
  1709.                         if infotbl[cap_ptr+4] and $20=$20 then WriteLn('Yes') else WriteLn('No');
  1710.  
  1711.                         Write('    Sideband Addressing Supported : ');
  1712.                         if infotbl[cap_ptr+5] and 2=2 then WriteLn('Yes') else WriteLn('No');
  1713.  
  1714.                         Write('    Maximum Command Queue Length : ',infotbl[cap_ptr+7]+1,' byte');
  1715.                         if infotbl[cap_ptr+7]=0 then WriteLn else WriteLn('s');
  1716.  
  1717.  
  1718.                         { Command register }
  1719.  
  1720.                         Write('    AGP Speed Selected : ');
  1721.                         if infotbl[cap_ptr+8] and 1=1 then Write('1x ');
  1722.                         if infotbl[cap_ptr+8] and 2=2 then Write('2x ');
  1723.                         if infotbl[cap_ptr+8] and 4=4 then Write('4x ');
  1724.                         if infotbl[cap_ptr+8] and 7=0 then Write('None Selected');
  1725.                         WriteLn;
  1726.  
  1727.                         Write('    FW Transfers Enabled : ');
  1728.                         if infotbl[cap_ptr+8] and $10=$10 then WriteLn('Yes') else WriteLn('No');
  1729.  
  1730.                         Write('    >4Gb Address Space Enabled : ');
  1731.                         if infotbl[cap_ptr+8] and $20=$20 then WriteLn('Yes') else WriteLn('No');
  1732.  
  1733.                         Write('    AGP Enabled : ');
  1734.                         if infotbl[cap_ptr+9] and 1=1 then WriteLn('Yes') else WriteLn('No');
  1735.  
  1736.                         Write('    Sideband Addressing Enabled : ');
  1737.                         if infotbl[cap_ptr+9] and 2=2 then WriteLn('Yes') else WriteLn('No');
  1738.  
  1739.                         Write('    Current Command Queue Length : ',infotbl[cap_ptr+11]+1,' byte');
  1740.                         if infotbl[cap_ptr+11]=0 then WriteLn else WriteLn('s');
  1741.                       end;
  1742.  
  1743.  
  1744.  
  1745.                  05 : begin
  1746.                         WriteLn('  Message Signalled Interrupt Capability');
  1747.                         Write('    MSI is ');
  1748.                         if infotbl[cap_ptr+2] and 1=1 then WriteLn('enabled') else WriteLn('disabled');
  1749.                       end;
  1750.  
  1751.  
  1752.  
  1753.                  else WriteLn('  Unknown Capability (Code ',wrhex(infotbl[cap_ptr]),'h)!!');
  1754.                end;
  1755.                cap_ptr:=infotbl[cap_ptr+1];
  1756.              until cap_ptr=0;
  1757.            end;
  1758.  
  1759.  
  1760.            end;
  1761.  
  1762.  
  1763. { do a hex-dump, if requested }
  1764.            if dumpregs then
  1765.            begin
  1766.              WriteLn;
  1767.              WriteLn(' Hex-Dump of device configuration space follows:');
  1768.              Write('  0000  ');
  1769.              for i:=0 to $ff do
  1770.              begin
  1771.                if (i>0) and (i mod 16=0) then
  1772.                begin
  1773.                  Write('   ');
  1774.                  for j:=i-16 to i-1 do if Ord(infotbl[j])<32 then Write('.') else Write(Chr(infotbl[j]));
  1775.                  WriteLn;
  1776.                  Write('  ',wrhexw(i),'  ');
  1777.                end;
  1778.                Write(wrhex(infotbl[i]),' ');
  1779.              end;
  1780.              Write('   ');
  1781.              for j:=240 to 255 do if Ord(infotbl[j])<32 then Write('.') else Write(Chr(infotbl[j]));
  1782.              WriteLn;
  1783.            end;
  1784.  
  1785.  
  1786.  
  1787.  
  1788.  
  1789.  
  1790.  
  1791.  
  1792.            WriteLn;             { space between devices }
  1793.  
  1794.  
  1795.  
  1796. { If not multi-device device, then don't test for func 1-7 as some cards
  1797. incorrectly answer back on all 8 function numbers!!! S3 trio64, for example - stupid!  }
  1798.  
  1799.            if (func=0) and (infotbl[$e] and $80=0) then func:=7;
  1800.          end;
  1801.        end;
  1802.       end;
  1803.     end;
  1804.  
  1805.  
  1806.  
  1807.  
  1808.  
  1809.  
  1810.  
  1811.  
  1812.  
  1813.  
  1814.  
  1815.  
  1816.  
  1817.  
  1818.  
  1819.  
  1820.  
  1821.  
  1822.  
  1823.  
  1824.  
  1825.  
  1826.  
  1827.  
  1828.  
  1829.  
  1830.  
  1831.  
  1832.  
  1833.  
  1834.  
  1835.  
  1836. {
  1837.   The following is an experiment with "Get IRQ Routing Info" BIOS function:
  1838.   the avid coder is free to un-comment the code and try it out: I couldn't
  1839.   make much sense out of the information returned myself!
  1840. }
  1841.  
  1842.  
  1843.  
  1844.      if dopcirouting then
  1845.     begin
  1846.  
  1847.  
  1848.       WriteLn;
  1849.       WriteLn('PCI slot IRQ mapping information');
  1850.  
  1851.       failed:=true;
  1852.       FillChar(irqbuff,SizeOf(irqbuff),$00);
  1853.       load_irqbuff;
  1854.  
  1855.       if not failed then
  1856.       begin
  1857.         TextColor(10);
  1858.         WriteLn(' PCI slot mapping information read successfully');
  1859.         TextColor(7);
  1860.         WriteLn;
  1861.  
  1862. { hex-dump table }
  1863.         if dumpregs then
  1864.         begin
  1865.           WriteLn('Hex-Dump of IRQ Routing table : ');
  1866.           WriteLn;
  1867.           {
  1868.           Write('  0000  ');
  1869.           for i:=0 to 1023 do
  1870.           begin
  1871.             if (i>0) and (i mod 16=0) then
  1872.             begin
  1873.               Write('   ');
  1874.               for j:=i-16 to i-1 do if Ord(irqbuff[j])<32 then Write('.') else Write(Chr(irqbuff[j]));
  1875.               WriteLn;
  1876.               Write('  ',wrhexw(i),'  ');
  1877.             end;
  1878.             Write(wrhex(irqbuff[i]),' ');
  1879.           end;
  1880.           Write('   ');
  1881.           for j:=1024-16 to 1024-1 do if Ord( irqbuff[j])<32 then Write('.') else Write(Chr(irqbuff[j]));
  1882.           WriteLn;
  1883.           WriteLn;
  1884.           }
  1885.           for i:=0 to (len-1) shr 4 do
  1886.             begin
  1887.               Write('  ',wrhexw(i shl 4),'  ');
  1888.  
  1889.               for j:=0 to 15 do
  1890.                 Write(wrhex(irqbuff[6+i shl 4+j]),' ');
  1891.  
  1892.               Write('   ');
  1893.  
  1894.               for j:=0 to 15 do
  1895.                 if Ord( irqbuff[6+i shl 4+j])<32 then
  1896.                   Write('.')
  1897.                 else
  1898.                   Write(Chr(irqbuff[6+i shl 4+j]));
  1899.  
  1900.               WriteLn('   ');
  1901.             end;
  1902.         end;
  1903.  
  1904.  
  1905. {}
  1906.         WriteLn(' PCI slot IRQ availability listing');
  1907.         WriteLn;
  1908.         for i:=0 to (len shr 4)-1 do
  1909.         begin
  1910.           WriteLn('  PCI Bus ',irqbuff[6+(i*16)],', Device ',irqbuff[6+1+(i*16)] shr 3,', Slot ',wrhex(irqbuff[6+14+(i*16)]));
  1911.           listmap(irqbuff[6+ 4+(i*16)] shl 8 + irqbuff[6+ 3+(i*16)],'   INTA# can be connected to IRQs ');
  1912.           listmap(irqbuff[6+ 7+(i*16)] shl 8 + irqbuff[6+ 6+(i*16)],'   INTB# can be connected to IRQs ');
  1913.           listmap(irqbuff[6+10+(i*16)] shl 8 + irqbuff[6+ 9+(i*16)],'   INTC# can be connected to IRQs ');
  1914.           listmap(irqbuff[6+13+(i*16)] shl 8 + irqbuff[6+12+(i*16)],'   INTD# can be connected to IRQs ');
  1915.           WriteLn;
  1916.         end;
  1917.         WriteLn;
  1918.  
  1919.  
  1920. {}
  1921.         WriteLn(' PCI slot INTx to IRQ-router mappings');
  1922.         WriteLn;
  1923.         WriteLn('  SLOT BUS DEV  INTA INTB INTC INTD');
  1924.         for i:=0 to (len shr 4)-1 do
  1925.         begin
  1926.           Write('   ',wrhex(irqbuff[6+14+(i*16)]),'  ',irqbuff[6+0+(i*16)]:2,'  ',irqbuff[6+1+(i*16)] shr 3:2);
  1927.           Write('    ',wrhex(irqbuff[6+2+(i*16)]),'   ',wrhex(irqbuff[6+5+(i*16)]),'   ',
  1928.             wrhex(irqbuff[6+8+(i*16)]),'   ',wrhex(irqbuff[6+11+(i*16)]),'  ');
  1929.  
  1930.           if usebios then
  1931.           begin
  1932.             infotbl[0]:=lookup_bios(irqbuff[6+1+(i*16)] shr 3,0,irqbuff[6+0+(i*16)],0);
  1933.             infotbl[1]:=lookup_bios(irqbuff[6+1+(i*16)] shr 3,0,irqbuff[6+0+(i*16)],1);
  1934.             infotbl[2]:=lookup_bios(irqbuff[6+1+(i*16)] shr 3,0,irqbuff[6+0+(i*16)],2);
  1935.             infotbl[3]:=lookup_bios(irqbuff[6+1+(i*16)] shr 3,0,irqbuff[6+0+(i*16)],3);
  1936.             infotbl[4]:=lookup_bios(irqbuff[6+1+(i*16)] shr 3,0,irqbuff[6+0+(i*16)],4);
  1937.             infotbl[5]:=lookup_bios(irqbuff[6+1+(i*16)] shr 3,0,irqbuff[6+0+(i*16)],5);
  1938.             infotbl[6]:=lookup_bios(irqbuff[6+1+(i*16)] shr 3,0,irqbuff[6+0+(i*16)],6);
  1939.             infotbl[7]:=lookup_bios(irqbuff[6+1+(i*16)] shr 3,0,irqbuff[6+0+(i*16)],7);
  1940.           end else
  1941.           begin
  1942.             infotbl[0]:=lookup_hw(irqbuff[6+1+(i*16)] shr 3,0,irqbuff[6+0+(i*16)],0);
  1943.             infotbl[1]:=lookup_hw(irqbuff[6+1+(i*16)] shr 3,0,irqbuff[6+0+(i*16)],1);
  1944.             infotbl[2]:=lookup_hw(irqbuff[6+1+(i*16)] shr 3,0,irqbuff[6+0+(i*16)],2);
  1945.             infotbl[3]:=lookup_hw(irqbuff[6+1+(i*16)] shr 3,0,irqbuff[6+0+(i*16)],3);
  1946.             infotbl[4]:=lookup_hw(irqbuff[6+1+(i*16)] shr 3,0,irqbuff[6+0+(i*16)],4);
  1947.             infotbl[5]:=lookup_hw(irqbuff[6+1+(i*16)] shr 3,0,irqbuff[6+0+(i*16)],5);
  1948.             infotbl[6]:=lookup_hw(irqbuff[6+1+(i*16)] shr 3,0,irqbuff[6+0+(i*16)],6);
  1949.             infotbl[7]:=lookup_hw(irqbuff[6+1+(i*16)] shr 3,0,irqbuff[6+0+(i*16)],7);
  1950.           end;
  1951.  
  1952.           cmpstr:=wrhexw(infotbl[1] shl 8+infotbl[0]);
  1953.           if cmpstr<>'FFFF' then
  1954.           begin
  1955.             lookupven(true);
  1956.             cmpstr:=wrhexw(infotbl[3] shl 8+infotbl[2]);
  1957.             lookupdev;
  1958.           end else Write('No Device Detected');
  1959.  
  1960.  
  1961.  
  1962.  
  1963.           WriteLn;
  1964.         end;
  1965.         WriteLn;
  1966.  
  1967.  
  1968. {}
  1969.         listmap(conmap,' IRQ''s dedicated to PCI : ');
  1970.  
  1971.       end else
  1972.       begin
  1973.         TextColor(12);
  1974.         WriteLn(' Unable to read slot mapping information from PCI BIOS!');
  1975.         TextColor(7);
  1976.       end;
  1977.       WriteLn;
  1978.     end;
  1979.  
  1980.  
  1981.  
  1982.  
  1983.  
  1984.  
  1985.  
  1986.  
  1987.  
  1988.  
  1989.  
  1990.  
  1991.  
  1992.  
  1993.  
  1994.  
  1995.  
  1996.  
  1997.  
  1998.  
  1999.  
  2000.  
  2001.  
  2002.  
  2003. { BIOS IRQ Routing table tests }
  2004.  
  2005.     if dorouting then
  2006.     begin
  2007.       WriteLn('ROM PCI IRQ routing table Windows 9x Compatibility Tests....');
  2008.  
  2009.  
  2010. { Find table }
  2011.       i:=0;
  2012.       failed:=true;
  2013.       repeat
  2014.         if MemL_F000(i)=$52495024 then (* $PIR *)
  2015.           failed:=false
  2016.         else
  2017.           Inc(i,16);
  2018.       until (i>$ffef) or not failed;
  2019.  
  2020.  
  2021. { check table }
  2022.       if not failed then
  2023.       begin
  2024.  
  2025.         tableok:=true;
  2026.  
  2027.         WriteLn(' ROM IRQ routing table found at F000h:',wrhexw(i),'h');
  2028.         Write(' Table Version ',Mem_F000(i+5),'.',Mem_F000(i+4));
  2029.         if (Mem_F000(i+5)=1) and (Mem_F000(i+4)=0) then WriteLn(' - OK') else
  2030.         begin
  2031.           TextColor(12);
  2032.           WriteLn('Invalid Version!');
  2033.           TextColor(7);
  2034.           tableok:=false;
  2035.         end;
  2036.  
  2037.         Write(' Table size ',MemW_F000(i+6),' bytes - ');
  2038.         if (MemW_F000(i+6)<33) or (MemW_F000(i+6) mod 16<>0) then
  2039.         begin
  2040.           TextColor(12);
  2041.           WriteLn('Invalid Size!');
  2042.           TextColor(7);
  2043.           tableok:=false;
  2044.         end else WriteLn('OK');
  2045.  
  2046.  
  2047.  
  2048.         Write(' Table Checksum ',wrhex(Mem_F000(i+31)),'h - ');
  2049.         {$R-}  {Range checking off as sum is DELIBERATELY meant to overfow }
  2050.         sum:=0;
  2051.         for l:=0 to MemW_F000(i+6)-1 do
  2052.         begin
  2053.           sum:=sum+Mem_F000(i+l);
  2054.         end;
  2055.         {$R+}
  2056.         if sum=0 then WriteLn('OK') else
  2057.         begin
  2058.           TextColor(12);
  2059.           WriteLn('Failed!');
  2060.           TextColor(7);
  2061.           tableok:=false;
  2062.         end;
  2063.  
  2064.  
  2065.         listmap(MemW_F000(i+10),' IRQ''s dedicated to PCI : ');
  2066.  
  2067.  
  2068.         if tableok then
  2069.         begin
  2070.           TextColor(10);
  2071.           WriteLn(' The ROM PCI IRQ routing table appears to be OK.');
  2072.           TextColor(7);
  2073.         end else
  2074.         begin
  2075.           TextColor(12);
  2076.           WriteLn(' The ROM PCI IRQ routing table appears to be faulty!!');
  2077.           TextColor(7);
  2078.         end;
  2079.  
  2080.       end else
  2081.       begin
  2082.         TextColor(12);
  2083.         WriteLn('No ROM PCI IRQ routing table found!!!');
  2084.         TextColor(7);
  2085.       end;
  2086.     end;
  2087.  
  2088.  
  2089.  
  2090.  
  2091.  
  2092. { final summarial IRQ info }
  2093.  
  2094.     WriteLn;
  2095.  
  2096.     Write('IRQ Summary: ');
  2097.     failed:=true;
  2098.     disp:=0;
  2099.     for i:=0 to 15 do if irqmap[i]>0 then Inc(disp); { count IRQs}
  2100.     for i:=0 to 15 do if irqmap[i]>0 then
  2101.     begin
  2102.       if failed then
  2103.       begin
  2104.         if disp=1 then Write('IRQ ') else Write('IRQs ');
  2105.       end else Write(',');
  2106.       Write(i);
  2107.       failed:=false;
  2108.     end;
  2109.     if failed then WriteLn('No IRQ''s are used by PCI Devices!') else
  2110.     begin
  2111.       if disp=1 then Write(' is') else Write(' are');
  2112.       WriteLn(' used by PCI devices');
  2113.     end;
  2114.  
  2115.     Write('Shared IRQs: ');
  2116.     failed:=true;
  2117.     for i:=0 to 15 do if irqmap[i]>1 then
  2118.     begin
  2119.       if not failed then Write('             ');
  2120.       WriteLn('IRQ ',i,' is shared by ',irqmap[i],' PCI Devices');
  2121.       failed:=false;
  2122.     end;
  2123.     if failed then WriteLn('There are no shared PCI IRQs');
  2124.  
  2125.  
  2126.  
  2127.   end;
  2128.   (*$IFDEF OS2*)
  2129.   close_oemhlp;
  2130.   (*$ENDIF*)
  2131. end.
  2132.  
  2133.