Detecting the ATA devices

Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
Post Reply
Jim
Member
Member
Posts: 27
Joined: Sun Nov 05, 2006 3:46 am

Detecting the ATA devices

Post by Jim »

Hi

:roll: How do I detect if a ATA device is connected, and which kind is it :?: .
I sow in http://www.osdev.org/osfaq2/index.php/AtapiCdrom
to do like this:

=================================
==
=================================
ataDriveType _tellType(ioAtaController* ctrl)
{
unsigned sc,sn;
sc = inb(ctrl->base + REG_COUNT);
sn = inb(ctrl->base + REG_SECTOR);

if (sc==1 && sn==1) {
unsigned st=inb(ctrl->base + REG_STATUS);
unsigned cl=inb(ctrl->base + REG_CYL_LO);
unsigned ch=inb(ctrl->base + REG_CYL_HI);

/* now let's differentiate ATA, ATAPI, SATA and SATAPI */
if (cl==0x14 && ch==0xEB) return ATADEV_PATAPI;
if (cl==0x69 && ch==0x96) return ATADEV_SATAPI;
if (cl==0 && ch == 0) return ATADEV_PATA;
if (cl==0x3c && ch==0xc3) return ATADEV_SATA;
}

return ATADEV_UNKNOWN;
}

==============================
:roll: :roll: :roll:
But this only works for me in bochs, but not in a real PC, or Microsoft Virtual PC

:roll:
Does any one know a way to do it???
Thanks a lot for any help.
User avatar
kataklinger
Member
Member
Posts: 381
Joined: Fri Nov 04, 2005 12:00 am
Location: Serbia

Post by kataklinger »

You should wait between IO operations, to give IO bus a little rest.

edit #1:
ok, more info:
WAIT FOR READY STATUS FROM CONTROLLER (ALT. STATUS REG.)
BEGIN RESET SIGNAL (ATA ALT CTRL REG)
WAIT FEW ms
END RESET SIGNAL (ATA ALT CTRL REG)
WAIT FEW ms
WAIT FOR READY STATUS FROM CONTROLLER (STATUS REG.)
SELECT ATA CHANNEL
WAIT FEW ms
WIT FOR RESPONSE FROM CONTROLLER (SECTOR REG & SECTRO COUNT REG)
WAIT FOR READY STATUS FROM CONTROLLER (STATUS REG.)
SELECT ATA CHANNEL
WAIT FEW ms

and then run code you have posted.

edit #2:

Download ATA-ATAPI spec. and ther you can find algorithm for detecting ATA devices.
User avatar
smiddy
Member
Member
Posts: 127
Joined: Sun Oct 24, 2004 11:00 pm
Location: In my cube, like a good leming. ;-)

Post by smiddy »

Here's another perspective, perhaps it'll help:

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
durand
Member
Member
Posts: 193
Joined: Wed Dec 21, 2005 12:00 am
Location: South Africa
Contact:

Post by durand »

The best place for ATA and ATAPI code is: http://www.ata-atapi.com/. The code is easy to port to a system.
Toaster
Member
Member
Posts: 25
Joined: Wed Jul 19, 2006 7:11 am
Location: Austria

Post by Toaster »

mhmm there are commands like "Identify Device" and "Execute Device Diagnostic", which have to run on _all_ ATA devices
in the ATA/ATAPI-7 doc it is showed pretty good, look at t13

if you can speak german I recommend you my doc about the ATA Interface http://t0ast3r.t0.ohost.de/sites/tutori ... enuine.pdf

[other docs avl at http://lowlevel.brainsware.org/forum/in ... pic=1602.0 - sorry for the link]

It is an odd way to test registers, better you send the commands and check the return results.

greetings,

Toaster
E-Mail Adresse (= MSN): [email protected]
ICQ: 249-457-459
http://www.viennacomputerproducts.com/
Jim
Member
Member
Posts: 27
Joined: Sun Nov 05, 2006 3:46 am

Detecting ATA/ATAPI/SATA

Post by Jim »

:wink: :wink: :wink: :wink:

From My experience the first thing you need to do for detecting devices, is by getting the information from the BIOS by the enhance disk interface (when you are still in real mode), and with this information try detecting the device, by probing, and by using EXECUTE DEVICE DIAGNOSTIC and IDENTIFY DRIVE

:roll: :roll:
By the way does any one know about SATA specification, and how to read and write sectors etc? :?: :roll: :roll:
:?:
User avatar
JoeKayzA
Member
Member
Posts: 79
Joined: Wed Aug 24, 2005 11:00 pm
Location: Graz/Austria

Re: Detecting ATA/ATAPI/SATA

Post by JoeKayzA »

keller wrote: By the way does any one know about SATA specification, and how to read and write sectors etc? :?: :roll: :roll:
:?:
AFAIK the only "standard" for sata-controllers is intel's AHCI (which is not yet widespread - correct me if I'm wrong), or normal IDE if your controller supports IDE-compatibility mode (like nForce 430's). The communication protocol between controller and drives is IIRC standardized, just google.

cheers Joe
Post Reply