Code: Select all
GetIDEDrives32:
pusha
mov esi,CDDVDDriveMessage32
mov byte [esi + 13],'1' ; Initialize CD/DVD numbers
mov esi,HardDriveMessage32
mov byte [esi + 11],'1' ; Initialize HDD numbers
mov byte [Command32], 0ECh ; Identify Drive for non ATAPI device
.DriveID:
mov word [Port32],1F0h
mov byte [Drive32],0
call ATAIdentifyDrive32
mov byte [Drive32],10h
call ATAIdentifyDrive32
mov word [Port32],170h
mov byte [Drive32],0
call ATAIdentifyDrive32
mov byte [Drive32],10h
call ATAIdentifyDrive32
cmp byte[Command32],0A1h
je .LetsGo
mov byte[Command32],0A1h ; Change command to ATAPI device identify command
jmp .DriveID
.LetsGo:
popa
ret
ATAIdentifyDrive32:
mov dx,7 ; IDE Command Status Register
add dx,word [Port32] ; Combine with port
mov cx,0FFFFh ; Load CX with number of times to loop
.ReadStatusRegister1:
in al,dx
and al,80h ; Is it busy?
jz .WriteIDECommand1
loop .ReadStatusRegister1 ; Loop until CX is empty or not busy
.DeviceIsBusy:
jmp .Done ; Out of sequence return
.WriteIDECommand1:
mov dx,6 ; Drive and head
add dx,word [Port32]
mov al,byte [Drive32]
or al,0EFh ; Select Drive via Bit 4
out dx,al
mov cx,0FFFFh ; Load CX with number of times to loop
mov dx,7 ; Status register
add dx,word [Port32] ; Combine with port
.ReadStatusRegister2:
in al,dx
test al,80h ; Is it busy?
jz .DriveReadyCheck
loop .ReadStatusRegister2
jmp .DeviceIsBusy
.DriveReadyCheck:
test al,40h ; Is drive ready?
jnz .WriteIDECommand2
cmp byte [Command32],0A1h ; ATAPI IDENTIFY DRIVE Command
je .WriteIDECommand2
; DRDY is not forced for ATAPI
jmp .Done
.WriteIDECommand2:
mov dx,7 ; Command register
add dx,word [Port32] ; Add to the port being written
mov al,byte [Command32] ; Place command to be written in AL
out dx,al ; Write to the port
mov cx,0FFFFh ; Load CX with a number for looping
mov dx,7 ; Status register
add dx,word [Port32] ; Add to port being read
.ReadStatusRegister3:
in al,dx
test al,80h ; Test for Busy
jnz .PassDRQErrorCheck
test al,01h ; Test for an error
jnz .ATAIOError
test al,08h ; DRQ bit
jnz .ReadDataRegister0
.PassDRQErrorCheck:
loop .ReadStatusRegister3
jmp .Done
.ReadDataRegister0:
mov dx,0 ; Data Register
add dx,word [Port32] ; Add to the port value
mov ecx,100h ; 512 bytes to read
mov edi,ParametersBuffer32 ; Save to ParametersBuffer
push es
push ds
pop es
push edi
.ReadDataRegister1:
in ax,dx ; Get a word from the port
stosw ; Store word from AX to DI and increment DI by 2
loop .ReadDataRegister1 ; Loop until done
pop esi ; Restore SI
pop es
mov ecx,20 ; Put 20 into ECX
mov eax,54 ; Put 54 into EAX (Where model number starts)
add esi,eax ; Add EAX to ESI and update ESI
mov edi,ModelNumber32 ; Put the address of ModelNumber into DI
push es
push ds
pop es
.GetModelName:
lodsw ; Load AX with word from SI and increment SI by 2
xchg al,ah ; Ata/Atapi devices SWAP bytes of an ASCII field.
stosw ; Store word from AX to DI and increment DI by 2
loop .GetModelName ; Loop until CX is 0
pop es
mov esi,ParametersBuffer32 ; Update SI with ParametersBuffer address
mov ecx,10 ; Load CX with 10
mov eax,20 ; Put 20 into AX (offset for device serial number)
add esi,eax ; Add AX to SI and update SI
mov edi,SerialNumber32 ; Load DI with the address of SerialNumber
push es
push ds
pop es
.GetSerialNumber:
lodsw ; Load AX with word from SI and increment SI by 2
xchg al,ah ; Ata/Atapi devices SWAP bytes of an ASCII field.
stosw ; Store word from AX to DI and increment DI by 2
loop .GetSerialNumber ; Loop until CX is 0
pop es
mov esi,ParametersBuffer32 ; Update SI with ParametersBuffer address
mov ecx,4 ; Put 4 into CX for loop
mov eax,46 ; Load AX with 46 (offset where Firmware Revision is stored)
add esi,eax ; Add AX to SI and update SI
mov edi,FirmwareRevision32 ; Put the address of FirmwareRevision into DI
push es
push ds
pop es
.GetFirmware:
lodsw ; Load AX with word from SI and increment SI by 2
xchg al,ah ; Ata/Atapi devices SWAP bytes of an ASCII field.
stosw ; Store word from AX to DI and increment DI by 2
loop .GetFirmware ; Loop until CX is 0
pop es
cmp byte [Command32],0ECh ; Is it a hard drive ID
je .HardDriveID
mov esi,CDDVDDriveMessage32
call PrintString32
mov esi,CDDVDDriveMessage32
add esi,13
inc byte [esi]
jmp .ShowInfo
.HardDriveID:
mov esi,HardDriveMessage32
call PrintString32
mov esi,HardDriveMessage32
add esi,11
inc byte [esi]
.ShowInfo:
call PortAndDrive32
mov esi,ModelNumberMessage32
call PrintString32
mov esi,ModelNumber32
call PrintString32
mov esi,SerialNumberMessage32
call PrintString32
mov esi,SerialNumber32
call PrintString32
mov esi,FirmwareMessage32
call PrintString32
mov esi,FirmwareRevision32
call PrintString32
mov esi,SlapOneOn
call PrintString32
jmp .Done
.ATAIOError:
.Done:
ret
PortAndDrive32:
mov esi,PortMessage32
call PrintString32
mov ax,[Port32]
mov cl,10h
call ToHex32
mov esi,HexBuffer32
call PrintString32
mov esi,DriveMessage32
call PrintString32
mov al,[Drive32]
mov cl,8h
call ToHex32
mov esi,HexBuffer32
call PrintString32
ret
Port32 dw 0
Drive32 db 0
Command32 db 0
ParametersBuffer32: TIMES 512 db 0
DeviceBusyMessage32 db ' Device busy!',13,10,0
IDEIOErrorMessage32 db ' IO Error reading device!',0
PortMessage32 db 'Port: ',0
DriveMessage32 db ' Drive: ',0
ModelNumber32: TIMES 41 db 0
ModelNumberMessage32 db ' Model No.: ',0
SerialNumber32: TIMES 21 db 0 ; Buffer for serial number
SerialNumberMessage32 db ' Serial No.: ',0
FirmwareRevision32: TIMES 11 db 0
FirmwareMessage32 db ' Firmware Rev.: ',0
HardDriveMessage32 db 'Hard Drive 1: ',0
CDDVDDriveMessage32 db 'CD/DVD Drive 1: ',0