TITLE DSIdeInf.asm - VxD retrieves information from IDEs ; created using a modified version of DSIdeInf.asm from ; http://skyscraper.fortunecity.com/virtuosity/452/ ; modified by Scott Kell from DSIdeInf.asm in Jan 2001 ; bug fixed by Grzegorz Lapinski in May 2002 .386P .NOLIST Include Vmm.inc Include VWin32.inc Include Shell.inc .LIST ; ***** EQUATES ***** ; --- Bits --- cBit00 EQU 0000000000000001b cBit02 EQU 0000000000000100b cBit06 EQU 0000000001000000b cBit07 EQU 0000000010000000b ; --- Tests --- cERR EQU cBit00 cBusy EQU cBit07 ; --- Area offsets in buffer --- cDisk0_Exists = 4 cDisk0_RawInfo =12 ; --- GDI commands --- cATA_GDIcmd EQU 0ECh ; GDI command for ATA cATAPI_GDIcmd EQU 0A1h ; GDI command for ATAPI ; **** MACROS ***** ; wPort0 has to be initialized according to IDE WaitWhileBusy MACRO LOCAL LoopWhileBusy LOCAL timeout LOCAL TryAgain LOCAL DriveReady PUSH EBX TryAgain: ; 1000000 is too long ! MOV EBX, 100000 MOV DX, [wPort0] ADD DX, 7 ; DX = Port0 +7 LoopWhileBusy: DEC EBX CMP EBX, 0 JZ timeout IN AL, DX TEST AL, cBusy JNZ LoopWhileBusy POP EBX JMP DriveReady timeout: POP EBX JMP Next_Mos DriveReady: ENDM ; (WaitWhileBusy) ; wPort0 has to be initialized according to IDE ; bDevSelCmd has to be initialized according to MoS SelectDevice MACRO MOV DX, [wPort0] ADD DX, 6 ; DX = Port0 +6 MOV AL, [bDevSelCmd] ; AL = DevSelCmd OUT DX, AL ENDM ; (SelectDevice) ; wPort0 has to be initialized according to IDE ; Parameter 'GDIcmd' is GDI command (ATA or ATAPI) SendGDIcmd MACRO GDIcmd MOV DX, [wPort0] ADD DX, 7 ; DX = Port0 +7 MOV AL, GDIcmd OUT DX, AL ENDM ; (SendGDIcmd) ; ------------------------------- ; --- Device Descriptor Block --- ; ------------------------------- DECLARE_VIRTUAL_DEVICE \ IDE21201, 1, 0, IDE21201_Control,\ UNDEFINED_DEVICE_ID, UNDEFINED_INIT_ORDER ; ---------------------------------------- ; --- Prepare Device Control Procedure --- ; ---------------------------------------- Begin_control_dispatch IDE21201 Control_Dispatch w32_DeviceIoControl, On_DeviceIoControl End_control_dispatch IDE21201 ; ************ ; ** CODE ** ; ************ VxD_LOCKED_CODE_SEG ; === DEVICE CONTROL PROCEDURE === BeginProc On_DeviceIoControl ASSUME ESI:PTR DIOCParams .if [esi].dwIoControlCode==DIOC_Open xor eax,eax .elseif [esi].dwIoControlCode==1 CALL IdesInfo xor eax, eax .endif RET EndProc On_DeviceIoControl ; Meaning of registers: ; ESI: pointer to output buffer ; EDI: pointer to section of 1 disk info, in output buffer ; EBX: IDE (0..3) ; ECX: MasterOrSlave (0..1) ; IDE controllers: ; Range: 0..3 ; Address of IdeExists(n) byte in output buffer ; = ESI + Ide = ESI + EBX ; DISCs: ; Range: 0..7 ; Disk = Ide*2 + MoS = EBX*2 + ECX ; Address of DiskExists(n) byte in output buffer ; = ESI + cDisk0_Exists + Disk ; Address of Disc raw info first byte in output buffer ; = ESI + cDisk0_RawInfo + Disk*512 BeginProc IdesInfo ASSUME ESI:PTR DIOCParams ; --- Preserve registers and flags --- PUSHAD PUSHFD CLI ; clear all interrupts ; --- Initialize ESI as pointer to output buffer --- MOV ESI, [ESI.lpvOutBuffer] ; -------------------------------------- ; --- Process to get the information --- ; -------------------------------------- ; Initialize FOR_Ide counter ; test all 4 IDE controllers MOV EBX, 3 ; EBX = Ide no 3 ; test the first 2 IDE controllers ; MOV EBX, 1 ; EBX = Ide no 3 ; only test the primary IDE controller ; MOV EBX, 0 ; EBX = Ide no 3 FOR_Ide: ; FOR EBX=3 DOWNTO 0 ; --- Initialize wPort0 for this IDE --- MOV DX, [wPorts_table + EBX*2] MOV wPort0, DX ; --- Check if IDE exists --- ;MOV DX, [wPort0] ADD DX, 7 ; DX = Port0 +7 IN AL, DX ;Test0FFh CMP AL, 0FFh JNE Test07Fh JMP NEXT_Ide ; If AL = 0FFh, IDE not present ; -> NEXT_Ide Test07Fh: CMP AL, 07Fh JNE IdeExists JMP NEXT_Ide ; If AL = 07Fh, IDE not present ; -> NEXT_Ide IdeExists: ; --- Set value at the IdeExists area in output buffer --- MOV BYTE PTR [ESI + EBX], 1 ; Ide_Exists = True ; --- Prepare MoS (Master or Slave) loop --- ; Initialize FOR_MoS counter MOV ECX, 1 ; ECX = Slave FOR_MoS: ; FOR MoS=1 DOWNTO 0 ; --- Get bDevSelCmd for this disc --- MOV DL, [bDevSelCmd_table + ECX] ; DL = DevSelCmd MOV bDevSelCmd, DL ; --- Check if Disc exists --- WaitWhileBusy SelectDevice WaitWhileBusy TEST AL, cBit06 ; check the drive ready bit JNZ DiskExists JMP NEXT_MoS ; if drive ready bit not set then next MoS DiskExists: ; Compute Disk (= Ide*2 + MoS = EBX*2 + ECX) MOV EAX, EBX ; EAX = Ide SHL EAX, 1 ; EAX = Ide*2 ADD EAX, ECX ; EAX = Disk ; --- Prepare EDI as pointer ; to the area where info is to be stored -- ; Compute Disk*512 (knowing that 512 = 2 ^9) XCHG AH, AL ; Was: AL = Disk , Now: AH = Disk ; -> EAX = Disk* 2^8 SHL EAX, 1 ; EAX = Disk* 2^9 MOV EDI, ESI ; EDI = @Output buffer ADD EDI, cDisk0_RawInfo ; EDI = @beginning of raw info area in output buffer ADD EDI, EAX ; EDI = @raw info section for this Disc ; ----------------- Retrieve --------- WaitWhileBusy SelectDevice SendGDIcmd cATA_GDIcmd WaitWhileBusy ; check error status MOV DX, [wPort0] ADD DX, 7 ; DX = Port0 +7 IN AL, DX TEST AL, cBit00 JZ RetrieveInfo ; if no error then retrieve info ; ERR=1 -> try ATAPI GDI command WaitWhileBusy SelectDevice SendGDIcmd cATAPI_GDIcmd WaitWhileBusy ; check error status MOV DX, [wPort0] ADD DX, 7 ; DX = Port0 +7 IN AL, DX TEST AL, cBit00 JZ RetrieveInfo ; if no error then retrieve info JMP NEXT_Mos RetrieveInfo: PUSH ECX ; keep MoS value MOV ECX, 256 MOV DX, [wPort0] CLD REP INSW ; Retrieve (finally!) POP ECX ; restore MoS value ; if we've made it this far then we know we have a valid disk ; Compute Disk (= Ide*2 + MoS = EBX*2 + ECX) MOV EAX, EBX ; EAX = Ide SHL EAX, 1 ; EAX = Ide*2 ADD EAX, ECX ; EAX = Disk ; --- Set value at the DiscExists area in output buffer --- MOV BYTE PTR [ESI + cDisk0_Exists + EAX], 1 ; Disk_Exists = True NEXT_Mos: ;LOOP FOR_MoS CMP ECX, 0 JE NEXT_Ide DEC ECX JMP FOR_MoS NEXT_Ide: ;LOOP FOR_Ide CMP EBX, 0 JE Exit_IdeLoop DEC EBX JMP FOR_Ide Exit_IdeLoop: ; --- Restore flags and registers --- STI ; restart the interrupts POPFD POPAD RET EndProc IdesInfo VxD_LOCKED_CODE_ENDS ; ************ ; ** DATA ** ; ************ VxD_LOCKED_DATA_SEG ; --- Tables --- wPorts_table WORD 1F0h, 170h, 1E8h, 168h ; IDE 1 - 4 bDevSelCmd_table BYTE 0A0h, 0B0h ; Master - Slave ; --- Variables --- wPort0 WORD ? ; Port 0 bDevSelCmd BYTE ? VxD_LOCKED_DATA_ENDS END