Re: Festplattenaktivität feststellen ?
Verfasst: 04.01.2012 12:30
Hier ein schmuckloses (keine Grafik) Code-Beispiel:
Für den "Normal-User" bleibt die 64-Bit-Treiber-Problematik. Die Atsiv.exe wurde seinerzeit z.B. zu etlichen Monitoring-Programmen mitgeliefert
.
Viel Spaß!
Helle
Code: Alles auswählen
;- Festplatten-Aktivität AHCI-SATA-Geräte, 64-Bit-Windows
;- "Helle" Klaus Helbing, 04.01.2012, PB v4.60 (x64)
;- Benötigt WinIo v3.0 und für 64-Bit die Atsiv.exe; es sei denn andere Treiber sind vorhanden
#PROCESSOR_ARCHITECTURE_AMD64 = $9
#SATA_SIG_ATA = $00000101 ;SATA drive = HDD
#SATA_SIG_ATAPI = $EB140101 ;SATAPI drive = CD/DVD (optisches LW)
#SATA_SIG_SEMB = $C33C0101 ;Enclosure management bridge
#SATA_SIG_PM = $96690101 ;Port multiplier
#Class_ID = $01060000 ;Class $01=mass storage device, SubClass $06=serial ATA
;einmaliges Install für 32-Bit; Prinzip, ungetestet
;If OpenLibrary(0, "WinIo32.dll") ;32-Bit-Version laden, Pfad beachten
;Prototype.i ProtoWinIo(Pfad.i, Bool.i)
;Global WIO_InstallWinIoDriver.ProtoWinIo = GetFunction(0, "InstallWinIoDriver")
;Pfad$ = "C:\Codes\PureBasic 4.0\IO\64-Bit\WinIO\PB\" ;Pfad zu WinIo32.sys
;WIO_InstallWinIoDriver(@Pfad$, #False)
;CloseLibrary(0)
;EndIf
OpenWindow(0, 0, 0, 400, 400, "Festplatten-Aktivität AHCI-SATA-Geräte", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
;ermitteln, ob 32- oder 64-Bit-Betriebssystem
SI.SYSTEM_INFO ;Structure System_Info
GetSystemInfo_(@SI)
If SI\wProcessorArchitecture = #PROCESSOR_ARCHITECTURE_AMD64
DLLOK = OpenLibrary(0, "WinIo64.dll") ;64-Bit-Version laden
;----- dies nur für 64-Bit; Pfad beachten (hier Atsiv.exe im selben Verzeichnis wie .pb oder .exe)
RunProgram("Atsiv.exe" ," -u " + "WinIo64.sys", "", #PB_Program_Hide) ;oder auslagern
Delay(250)
RunProgram("Atsiv.exe" ," -f " + "WinIo64.sys", "", #PB_Program_Hide)
Delay(250) ;evtl.anpassen
;-----
Else
DLLOK = OpenLibrary(0, "WinIo32.dll") ;32-Bit-Version laden
EndIf
If DLLOK
Prototype.i ProtoWinIo_0()
Global WIO_InitializeWinIo.ProtoWinIo_0 = GetFunction(0, "InitializeWinIo")
Global WIO_ShutdownWinIo.ProtoWinIo_0 = GetFunction(0, "ShutdownWinIo")
Prototype.i ProtoWinIo_2(physAddr.i, physVal.l)
Global WIO_GetPhysLong.ProtoWinIo_2 = GetFunction(0, "GetPhysLong")
Prototype.i ProtoWinIo_3(Port.w, Value.l, G.b)
Global WIO_SetPortVal.ProtoWinIo_3 = GetFunction(0, "SetPortVal")
Global WIO_GetPortVal.ProtoWinIo_3 = GetFunction(0, "GetPortVal")
WIO_InitializeWinIo()
;- Aufbau Bus-Configuration-Address-Register, Adresse $0CF8:
;- Bit 0-1: Reserviert
;- Bit 2-7: Register-Nummern (DWords) 0-63, $2=Class/SubClass-ID
;- Bit 8-10: Funktions-Nummer 0-7
;- Bit 11-15 Device-Nummer 0-31
;- Bit 16-23 Bus-Nummer 0-255, 0=PCI
;- Bit 24-30 Reserviert
;- Bit 31: Configuration-Address-Register Ein/Aus
;PCI-Bus absuchen nach Class $01=mass storage device, SubClass $06=serial ATA
Port_BCAR.w = $0CF8 ;Bus-Configuration-Address-Register
Port_BCDR.w = $0CFC ;Bus-Configuration-Data-Register
GetValue.l
SetValue.l = $80000000 + %1000 ;Bit 31 setzen sowie Class/SubClass
For i = 0 To 31 ;Device-Nr.
SetValue & $FFFFF8FF ;Funktions-Nr. auf Null setzen
For k = 0 To 7 ;Funktions-Nr.
WIO_SetPortVal(Port_BCAR, SetValue, 4) ;4=Dword-Wert schreiben
WIO_GetPortVal(Port_BCDR, @GetValue, 4) ;Bus-Configuration-Data-Register auslesen
If (GetValue & $FFFF0000) = #Class_ID ;$01060000
SetValue = (SetValue & $FFFFFFF0) + %100100 ;ABAR auslesen (Register-Nummer 9)
WIO_SetPortVal(Port_BCAR, SetValue, 4) ;4=Dword-Wert schreiben
WIO_GetPortVal(Port_BCDR, @GetValue, 4) ;Bus-Configuration-Data-Register auslesen
ABAR = GetValue & $FFFFFFFF ;ABAR=AHCI Base Address
ABAR$ = "AHCI Base Address gefunden an Adresse : $" + Hex(ABAR)
Break 2
EndIf
SetValue + $100
Next
Next
TextGadget(1, 10, 10, 380, 20, ABAR$)
;ermitteln, wieviel AHCI-Ports vorhanden sind
WIO_GetPhysLong(ABAR + $0C, @GetValue) ;$0C=Ports Implemented, jedes gesetzte Bit ist ein SATA-Port (0-31)
Anz_SATA = Len(Bin(GetValue))
Anz_SATA$ = "Anzahl SATA-Ports gefunden : " + Str(Anz_SATA)
TextGadget(2, 10, 30, 380, 20, Anz_SATA$)
;was ist dran an gefundenen Ports?
Signatur = ABAR + $124 ;$124=Signatur Port0
Matrix = 0
k = 1
For i = 1 To Anz_SATA
WIO_GetPhysLong(Signatur, @GetValue)
Typ = GetValue & $FFFFFFFF
Select Typ
Case #SATA_SIG_ATA
Typ$ = "Port " + Str(i - 1) + " ist ein SATA-Drive (HDD)"
Matrix | k
Case #SATA_SIG_ATAPI
Typ$ = "Port " + Str(i - 1) + " ist ein SATAPI-Drive (z.B. optisches LW)"
Case #SATA_SIG_SEMB
Typ$ = "Port " + Str(i - 1) + " ist eine Enclosure Management Bridge)"
Case #SATA_SIG_PM
Typ$ = "Port " + Str(i - 1) + " ist ein Port Multiplier"
Default
Typ$ = "Port " + Str(i - 1) + " ist z.Z. nicht belegt"
EndSelect
TextGadget(2 + i, 10, 30 + (20 * i), 380, 20, Typ$)
Signatur + $80 ;nächster Port
k << 1
Next
If Matrix = 0
MessageRequester("Achtung !", "Keine AHCI-SATA-Platte gefunden !")
End
EndIf
k = i
j = Matrix
For n = i To Anz_SATA + i - 1
If j & 1
TextGadget(2 + k, 10, 50 + (20 * k), 100, 20, "Status Port " + Str(n - i) + " : ")
TextGadget(2 + k + Anz_SATA, 120, 50 + (20 * k), 280, 20, "Ruhe")
k + 1
j >> 1
EndIf
Next
;jetzt die SATA-Platten beobachten
AddWindowTimer(0, 0, 5) ;5 ms, Geschmackssache
Repeat
If Event = #PB_Event_Timer And EventTimer() = 0 ;Aktualisierung und Anzeige ca. alle 0.05 Sekunden
SATA_Activ = ABAR + $134 ;$134=Port0 Device Status auslesen, ist nur eine von mehreren Möglichkeiten
k = i
j = Matrix
For n = i To Anz_SATA + i - 1
If j & 1
WIO_GetPhysLong(SATA_Activ, @GetValue)
If GetValue
SetGadgetText(2 + k + Anz_SATA, "Action") ;kann man natürlich auch grafisch gestalten
Else
SetGadgetText(2 + k + Anz_SATA, "Ruhe")
EndIf
k + 1
j >> 1
EndIf
SATA_Activ + $80 ;nächster Port
Next
EndIf
Event = WaitWindowEvent()
Until Event = #PB_Event_CloseWindow
;WIO_ShutdownWinIo()
CloseLibrary(0)
EndIf

Viel Spaß!
Helle