PCI-Bus scannen

Hardware- und Elektronikbasteleien, Ansteuerung von Schnittstellen und Peripherie.
Fragen zu "Consumer"-Problemen kommen in Offtopic.
Benutzeravatar
Helle
Beiträge: 566
Registriert: 11.11.2004 16:13
Wohnort: Magdeburg

PCI-Bus scannen

Beitrag von Helle »

Zufällig habe ich am Wochenende mitbekommen, das TVicPort für nicht-kommerzielle Anwendungen Free-Ware geworden ist. Mit diesem Programm (bzw. der DLL) können Ports gelesen und beschrieben werden, ähnlich inpout32 oder winio, aber praktisch ohne Einschränkungen.
Auf die Schnelle habe ich damit mal ein Progrämmchen zum PCI-Bus scannen geschrieben, alles weitere steht im Code.

Code: Alles auswählen

;- Scannen des PCI-Busses (#0) um Gerät (Device) sowie Hersteller (Vendor) zu ermitteln
;- "Helle" Klaus Helbing, 27.03.2007, PB v4.02
;- Verwendet wird dazu die TVicPort.dll, erhältlich von EnTech, "http://www.entechtaiwan.com/dev/port/index.shtm" 
;- Die DLL ist (Haupt-) Bestandteil des für nicht-kommerzielle Anwendungen freien Programms TVicPort
;- Die Installation ist harmlos, wie bei ähnlichen Programmen auch wird eine DDL nach %WINDIR%\System
;-  und eine SYS nach %WINDIR%\System32\Drivers kopiert
;- Die DLL ist gut dokumentiert und z.B. auch für Parallel-Ports bestens geeignet, dafür sogar mit vielen Extras
;- Auf "http://www.pcidatabase.com" sind Vendor- und Device-Listen frei erhältlich, mit deren 
;-  Hilfe Hersteller und Gerät namentlich zu bestimmen sind. Könnte man auch in´s Programm einbauen!

;- Aufbau Bus-Configuration-Address-Register, Adresse $0CF8:
;- Bit 0-1:   Reserviert
;- Bit 2-7:   Register-Nummer 0-63, für Vendor und Device nur 0 von Interesse
;- Bit 8-10:  Funktions-Nummer 0-7
;- Bit 11-15  Device-Nummer 0-31
;- Bit 16-23  Bus-Nummer 0-255, hier nur 0; 1 wäre z.B. der AGP-Bus  
;- Bit 24-30  Reserviert
;- Bit 31:    Configuration-Address-Register Ein/Aus

If OpenWindow(0, 0, 0, 420, 400, "Geräte und ihre Funktionen am PCI-Bus (Bus-Nr.#0)", #PB_Window_SystemMenu | #PB_Window_ScreenCentered) And CreateGadgetList(WindowID(0))
  ListViewGadget(0, 10, 10, 400, 380)

  If OpenLibrary(0, "TVicPort.dll") = 0
    MessageRequester("TVicPort", "Bibliothek TVicPort.dll konnte nicht geöffnet werden!")
     End  
  EndIf 

  CallFunction(0, "OpenTVicPort")

  If CallFunction(0, "IsDriverOpened")
   Y = $80000000                         ;Bit 31 setzen
     For J = 0 To 31                     ;Device-Nr.
        Y & $FFFFF8FF                    ;Funktions-Nr. auf Null setzen
        For I = 0 To 7                   ;Funktions-Nr.
          CallFunction(0, "WritePortL", $0CF8, Y)
          X = CallFunction(0, "ReadPortL", $0CFC)  ;Bus-Configuration-Data-Register auslesen
            If X <> $FFFFFFFF
              X$ = RSet(Hex(X), 8)
              X1$ = "Device-Nr. = " + Str(J)
              X2$ = "Funktions-Nr. = " + Str(I)
              X3$ = "Vendor = " + Mid(X$, 5, 4)
              X4$ = "Device = " + Mid(X$, 1, 4)
            AddGadgetItem (0, -1, X1$ + " ,  " + X2$ + " :   " + X3$ + " ,  " + X4$)
            EndIf 
          Y + $100
        Next   
     Next

   Else
     MessageRequester("TVicPort", "Driver konnte nicht geladen werden!")
  EndIf

  CallFunction(0, "CloseTVicPort")

  Repeat
  Delay(1)
  Until WindowEvent() = #PB_Event_CloseWindow 

EndIf 

End
Gruss
Helle
Marvin
Beiträge: 497
Registriert: 17.07.2005 14:42
Wohnort: Krikkit

Beitrag von Marvin »

Falls es jemanden interessiert: Bei den Linux-Kernel-Quellen ist irgendwo im PCI-Pfad auch eine große Datei mit vielen Vendor-IDs und Geräte-IDs... (Intel zum Beispiel hat den Vendor $8086)
Benutzeravatar
Helle
Beiträge: 566
Registriert: 11.11.2004 16:13
Wohnort: Magdeburg

Beitrag von Helle »

Da ich es für eine detaillierte Hardware-Bestimmung brauchte, habe ich es mal mit der giveio.sys erledigt (siehe Posts hier). Die benötigte Vendor/Device-Liste kann hier runtergeladen werden: http://www.mdcc-fun.de/k.helbing/Bus-Scannen/ (Zip 89kB).
giveio muss schon installiert sein!

Code: Alles auswählen

;- Bus-Scannen mit giveio.sys
;- "Helle" Klaus Helbing, 17.08.2008, PB 4.20
;- Getestet mit WinXP Prof.
;- Voraussetzung: giveio ist schon installiert

Global Status.l = AllocateMemory(32)   ;Ersatz für eine Struktur, tut´s hier
Global Buffer.l
Global WertL.l
Global ListL.l
Global ListE.l
Global Found.l
Global PortAdresse.w
Global Ch.c
ListeN$ = "   Liste nicht gefunden !"
ListeV$ = "   Vendor nicht gefunden !"
ListeD$ = "   Device nicht gefunden !"

;------------------ DWord lesen
Procedure InL(PortAdresse)
!mov dx,[p.v_PortAdresse]
!in eax,dx
!mov [v_WertL],eax
EndProcedure 
;------------------

;------------------ DWord schreiben
Procedure OutL(PortAdresse, WertL)
!mov dx,[p.v_PortAdresse]
!mov eax,[p.v_WertL]
!out dx,eax
EndProcedure 
;------------------

;------------------ Programm-Anfang
;Test, ob giveio in Registry vorhanden
If RegOpenKeyEx_(#HKEY_LOCAL_MACHINE, "SYSTEM\CurrentControlSet\Services\giveio", 0, #KEY_ALL_ACCESS, @hKey) 
  MessageRequester("Statusmeldung von RegTest", "giveio ist dem System nicht bekannt ! Bitte vorher installieren !")
  End 
EndIf
RegCloseKey_(hKey) 

;giveio vorhanden, jetzt Service-Control-Manager öffnen
hMgr = OpenSCManager_(#Null, #Null, #GENERIC_READ)    ;Handle für Zugriff auf den Dienst-Manager

;Test, ob giveio gestartet ist
hSvc = OpenService_(hMgr, "giveio", #SERVICE_ALL_ACCESS)
QueryServiceStatus_(hSvc, Status)      ;normalerweise ist dafür eine Struktur zu verwenden, aber es wird nur ein Wert benötigt
DriverStart = PeekL(Status+4)
If DriverStart <> 4                    ;4 = schon gestartet
  ;Dienst starten
  StartService_(hSvc, 0, #Null)  
EndIf   

;Device öffnen
hFrei = CreateFile_("\\.\giveio", #GENERIC_READ, 0, #Null, #OPEN_EXISTING, #FILE_ATTRIBUTE_NORMAL, #Null)
If hFrei = #INVALID_HANDLE_VALUE
  MessageRequester("Statusmeldung von Device öffnen", "Kein Portzugriff ! Fehler mit giveio !", 16)
  End 
EndIf
CloseHandle_(hFrei)

FreeMemory(Status)

If OpenWindow(0, 0, 0, 500, 400, "Bus - Scannen", #PB_Window_SystemMenu | #PB_Window_ScreenCentered) And CreateGadgetList(WindowID(0)) 
  ListViewGadget(0, 10, 10, 480, 380) 

  If ReadFile(0, "VenDevList.txt")     ;also im selben Verzeichnis, sonst anpassen
    ListL = Lof(0)
    Buffer = AllocateMemory(ListL)
    ReadData(0, Buffer, ListL)         ;Liste ins RAM kopieren
    CloseFile(0)
  EndIf 

  ListE = Buffer + ListL               ;Ende im Speicher

  Y1 = $80000000                       ;Bit 31 setzen 
  For K1 = 0 To 255                    ;Bus-Nr.
    For J1 = 0 To 31                   ;Device-Nr. 
      Y1 & $FFFFF8FF                   ;Funktions-Nr. auf Null setzen 
      For I1 = 0 To 7                  ;Funktions-Nr. 
        OutL($0CF8, Y1)
        InL($0CFC)                     ;Bus-Configuration-Data-Register auslesen 
        If WertL <> $FFFFFFFF 
          X$ = RSet(Hex(WertL), 8) 
          X0$ = "Bus-Nr. = " + Str(K1)
          X1$ = "Device-Nr. = " + Str(J1) 
          X2$ = "Funktions-Nr. = " + Str(I1) 
          X3$ = "Vendor = " + Mid(X$, 5, 4) 
          X4$ = "Device = " + Mid(X$, 1, 4) 
          AddGadgetItem (0, -1, X0$ + " ,  " + X1$ + " ,  " + X2$ + " :   " + X3$ + " ,  " + X4$) 
    
          If ListL                     ;die Namen von Vendor und Device aus Liste ermitteln
            !mov eax,[v_WertL]         ;AX = Vendor
            !mov ebx,eax
            !mov dl,al
            !and al,0fh
            !add al,30h
            !cmp al,39h
            !jbe @f
            !add al,27h                ;in Liste stehen Kleinbuchstaben! 
            !@@:
            !shl eax,8
            !shr dl,4
            !add dl,30h
            !cmp dl,39h
            !jbe @f
            !add dl,27h
            !@@:
            !mov al,dl

            !shl eax,16

            !mov dl,bh
            !and bh,0fh
            !add bh,30h
            !cmp bh,39h
            !jbe @f
            !add bh,27h
            !@@:
            !shr dl,4
            !add dl,30h
            !cmp dl,39h
            !jbe @f
            !add dl,27h 
            !@@:
            !mov bl,dl

            !mov ax,bx                 ;Vendor fertig

            !mov esi,[v_Buffer]
            !L1:      
            !cmp [esi],eax
            !je L3   
            !L2:
            !inc esi
            !cmp esi,[v_ListE]
            !jb L1
            !mov [v_Found],0           ;Vendor nicht gefunden
            !jmp L4    
            !L3: 
            !cmp byte[esi-1],0ah       ;LF davor?
            !jne L2
            !push esi 
            V$ = "   Vendor = "
            !pop esi
            !add esi,6
            !@@:
            !mov al,[esi]
            !cmp al,0dh
            !je @f
            !mov [v_Ch],al
            !push esi
            V$ + Chr(Ch)
            !pop esi
            !inc esi
            !jmp @b
            !@@:
            !mov [v_Found],esi 
            !L4:  
            If Found                   ;Vendor
              AddGadgetItem (0, -1, V$)
              !mov eax,[v_WertL]       ;jetzt Device ermitteln      
              !shr eax,16              ;AX jetzt Device
              !mov ebx,eax
              !mov dl,al
              !and al,0fh
              !add al,30h
              !cmp al,39h
              !jbe @f
              !add al,27h              ;in Liste stehen Kleinbuchstaben! 
              !@@:
              !shl eax,8
              !shr dl,4
              !add dl,30h
              !cmp dl,39h
              !jbe @f
              !add dl,27h
              !@@:
              !mov al,dl

              !shl eax,16

              !mov dl,bh
              !and bh,0fh
              !add bh,30h
              !cmp bh,39h
              !jbe @f
              !add bh,27h
              !@@:
              !shr dl,4
              !add dl,30h
              !cmp dl,39h
              !jbe @f
              !add dl,27h 
              !@@:
              !mov bl,dl

              !mov ax,bx               ;Device fertig
              
              !mov esi,[v_Found]
              !L11:      
              !cmp [esi],eax
              !je L31   
              !L21:
              !inc esi
              !cmp byte[esi],0ah       ;LF?
              !jne @f        
              !cmp byte[esi+1],9       ;Tab?
              !je @f                   ;es gibt noch Device-Einträge für diesen Vendor  
              !mov [v_Found],0
              !jmp L41                 ;der nächste Eintrag ist ein Vendor
              !@@:
              !cmp esi,[v_ListE]
              !jb L11
              !mov [v_Found],0         ;Device nicht gefunden
              !jmp L41    
              !L31: 
              !cmp byte[esi-1],9       ;Tab davor?
              !jne L21
              !push esi
              D$ = "   Device = "
              !pop esi
              !add esi,6
              !@@:
              !mov al,[esi]
              !cmp al,0dh
              !je @f
              !mov [v_Ch],al
              !push esi               
              D$ + Chr(Ch)
              !pop esi
              !inc esi
              !jmp @b            
              !@@:
              !L41:     
              If Found
                AddGadgetItem (0, -1, D$)
               Else 
                AddGadgetItem (0, -1, ListeD$)   ;Device nicht gefunden
              EndIf
             Else 
              AddGadgetItem (0, -1, ListeV$)     ;Vendor nicht gefunden
            EndIf
           Else
            AddGadgetItem (0, -1, ListeN$)       ;Liste nicht gefunden  
          EndIf      
        EndIf 
        Y1 + $100                      ;Funktions-Nr.   Auch für Bus-Nr.!       
      Next    
    Next 
  Next 

  Repeat 
  Delay(1) 
  Until WindowEvent() = #PB_Event_CloseWindow 
EndIf 

;- Ende
If DriverStart <> 4                    ;war vorher nicht gestartet, also jetzt wieder beenden
  IsEnd = ControlService_(hSvc, #SERVICE_CONTROL_STOP, Status)
  If IsEnd <> 1                        ;1=beendet
    MessageRequester("Statusmeldung von DienstEnd", "giveio konnte nicht beendet werden !")
  EndIf 
EndIf 
                           
CloseServiceHandle_(hSvc)              ;hier erst beenden           
CloseServiceHandle_(hMgr)              
End
Gruß
Helle
Antworten