flat assembler
Message board for the users of flat assembler.

Index > OS Construction > ATA and ATAPI devices detection

Author
Thread Post new topic Reply to topic
bogdanontanu



Joined: 07 Jan 2004
Posts: 403
Location: Sol. Earth. Europe. Romania. Bucuresti
bogdanontanu 06 Dec 2004, 03:27
Hi all

I am trying to automatically detect the presence or absence of ATA and ATAPI devices in my OS now.... Unfortunately I have some problems Very Happy

How i do it now:
1) Send ATA Identify on each device
2) IF I get an ABORT error in Command phase
3) THEN --> I try ATA Identify Packed Device

ALL other error means NO DEVICE is present

This procedure works in most cases... Very Happy but not all. Mainly sending a request to an non-existent secondary-slave device when an ATAPI CD-ROM is Secondary Master --> makes the CD-ROM stop answering later on....

I must say that i am testing on 4 very diffrent PC's (new and old) as well as in emulators. (but let us forget about emulators for now...)

All OTHER recomended methods fail miserably on real hardware.. like in:
a) probing ATA ports existence by write/read values into SECTOR_COUNT and SECTOR_NO registers -->sometimes works / sometimes fails

b)Atempting a software reset by setting/reseting SRST bit in Device Control register --> ATAPI devices take this very baddly and refuse to work after this

c)Reading PATA/SATA/PATAPI/SATAPI signature from CYL_LOW and CYL_HIGH registers after a software reset -->almost never works besides PATA Hard disks and even then not exactly as expected : 0x01, 0x01, 0x00, 0xff

So my question is:
===========================
Anybody has any ideea about how to safely detetct the presence of the ATA-IDE devices present in a PC at startup (protected mode) ?

_________________
"Any intelligent fool can make things bigger,
more complex, and more violent.
It takes a touch of genius -- and a lot of courage --
to move in the opposite direction."
Post 06 Dec 2004, 03:27
View user's profile Send private message Visit poster's website Reply with quote
ASHLEY4



Joined: 28 Apr 2004
Posts: 376
Location: UK
ASHLEY4 06 Dec 2004, 17:13
Hi, here is how i do it:
Code:
;=========================================================;; Ata_Atapi16                                    11/12/03 ;;---------------------------------------------------------;; DOS EXTREME OS V0.01                                    ;; by Craig Bamford.                                       ;;                                                         ;; ATA/ATAPI functions.                                    ;;=========================================================; ;----------------------------------------------------; ; GetAtaPiDrive      ; Gets the Ata/Atapi drive info ; ;----------------------------------------------------; ;                                                    ; ;   Input:                                           ; ;          none.                                     ; ;  Output:                                           ; ;          Puts drive info in vals:                  ; ;                                             (100%) ; ;....................................................;GetAtaPiDrive:        mov   byte [Drive_num],0                        ; 0 the variable called " Drive_num ".        mov   byte [command],0xec                       ; Put the hex number for IDENTIFY DRIVE in the var "command".drive_id:        mov   word [port],0x1f0                         ; Try port 1f0 .        mov   byte [drive],0x00                         ; Try master drive 0 (bit 5 should be 0).        call  AtaPi_Id_Drive                            ; Call proc,if no error we have a ata/atapi address.        mov   word [port],0x1f0                         ; Try port 1f0 .        mov   byte [drive],0x10                         ; Try slave drive 1 (bit 5 should be 1,so we put 0x10 bin 10000b) .        call  AtaPi_Id_Drive                            ; Call proc,if no error we have a ata/atapi address.        mov   word [port],0x170                         ; Try port 170 .        mov   byte [drive],0x00                         ; Try master drive 0 (bit 5 should be 0).        call  AtaPi_Id_Drive                            ; Call proc,if no error we have a ata/atapi address.        mov   word [port],0x170                         ; Try port 170 .        mov   byte [drive],0x10                         ; Try slave drive 1 (bit 5 should be 1,so we put 0x10 bin 10000b) .                       call  AtaPi_Id_Drive                            ; Call proc,if no error we have a ata/atapi address.        cmp  byte[command],0xA1                         ; Have we been here before, yes then lets go!        je   Lets_go                               mov  byte[command],0xA1                         ; Put the hex number for ATAPI IDENTIFY DRIVE in the var "command".        jmp  drive_id             Lets_go:                       ret ;----------------------------------------------------; ; AtaPi_Id_Drive                                     ; ;----------------------------------------------------;AtaPi_Id_Drive:                 mov   dx,0x7        add   dx,word [port]        mov   cx,0xffffStatusReg1:                                          in    al,dx        and   al,0x80            jz    WriteCommand1                 loop  StatusReg1                        jmp   DeviceBusy             WriteCommand1:        mov   dx,0x6                 add   dx,word [port]        mov   al,byte [drive]        or    al,0xef        out   dx,al        mov   cx,0xffff        mov   dx,0x7        add   dx,word [port] StatusReg2:                                          in    al,dx        test  al,0x80                   jz    Drdy_check        loop  StatusReg2         jmp   DeviceBusyDrdy_check:        test  al,0x40        jnz   WriteCommand2        cmp   byte[command],0xA1        je    WriteCommand2                    DeviceBusy:        ;stc        ret ;----------------------------------------------------; ;  WriteCommand2                                     ; ;----------------------------------------------------;WriteCommand2:        mov   dx,0x7                   add   dx,word [port]        mov   al,byte [command]              out   dx,al        mov   cx,0xffff        mov   dx,0x7        add   dx,word [port] StatusReg3:         in    al,dx        test  al,0x80        jnz   DrqErrorCheck1        test  al,0x01        jnz   error        test  al,0x08         jnz   Read_data_reg_0        ;stc        ret ;----------------------------------------------------; ; DrqErrorCheck                                      ; ;----------------------------------------------------;DrqErrorCheck1:        push  cx        mov   cx,0xFFFFbusy_delay123:        nop        nop        nop        nop        nop        nop        nop        nop        loop  busy_delay123        pop   cx        loop  StatusReg3error:       ; stc        ret ;----------------------------------------------------; ; Read data reg              (& move it into buffer) ; ;----------------------------------------------------;Read_data_reg_0:                                                          mov   dx,0        add   dx,word [port]        xor   ecx,ecx        mov   cx,0x100        mov   di,Temp_Buffer                Read_data_reg_1:        in    ax,dx                                                                stosw        loop  Read_data_reg_1              ;----------------------------------------------------; ; Label drive C                                      ; ;----------------------------------------------------;        cmp   word[HdPort1],0        jne   ItsAcd_1                mov   dx,word [port]        mov   word[HdPort1],dx        mov   al,byte [drive]        mov   byte[HdDrive1],al        jmp   Byby ItsAcd_1:        cmp   word[CdPort1],0        jne   Byby        mov   dx,word [port]        mov   word[CdPort1],dx        mov   al,byte [drive]        mov   byte[CdDrive1],al Byby:        clc        ret ;----------------------------------------------------; ; Small Delay                                        ; ;----------------------------------------------------;Small_Delay:        push  ecx        mov   ecx,0x0ffffBusyDelay3a:                                          nop        nop        nop        nop        nop        nop        nop        nop        loop  BusyDelay3a        pop   ecx        ret ;----------------------------------------------------; ; Atapi Address                                      ; ;----------------------------------------------------; Atapi_Address:        mov   dx,word[CdPort1]        mov   word[port],dx        mov   al,byte[CdDrive1]        mov   byte[drive],al         ret ;--------------------------------------------------------------- ;                                           Data                                              ;---------------------------------------------------------------;include 'Atapi_info.inc'command:         db 0port:            dw 0drive:           db 0AtapiError       db 0;ATAPIorNot      db 0  Drive_num:       db 0HdDrive1:        db 0HdPort1:         dw 0CdDrive1:        db 0CdPort1:         dw 0Temp_Buffer rw  256    


The only thing i will be changing is adding these
Code:
HdDrive1:        db 0HdPort1:         dw 0HdDrive2:        db 0HdPort2:         dw 0HdDrive3:        db 0HdPort3:         dw 0HdDrive4:        db 0HdPort4:         dw 0CdDrive1:        db 0CdPort1:         dw 0CdDrive2:        db 0CdPort2:         dw 0CdDrive3:        db 0CdPort3:         dw 0CdDrive4:        db 0CdPort4:         dw 0    


And test [command],0xec if it is = i would fill in the HdDrive* & HdPort*, if not i will fill in the CdDrive* & CdPort*.
Please note: i have split my atapi driver up, this bit run on bootup, in realmode, it does no run very well in pmode, the rest of the atapi driver runs fine in pmode ?.

PS: This is a old ver the new is on my other pc.
\\\\||////
(@@)
ASHLEY4.

Batteries not included, Some assembly required.


Last edited by ASHLEY4 on 19 Dec 2004, 02:59; edited 2 times in total
Post 06 Dec 2004, 17:13
View user's profile Send private message Reply with quote
rea



Joined: 14 Nov 2004
Posts: 92
rea 06 Dec 2004, 17:56
I have a question, sorry much offtopic, but I have watched that when more than one code mark is used it is "tabulated" in a rare way that dosent look nice, or is my browser doing extrange things? (Mozilla 1?)
Post 06 Dec 2004, 17:56
View user's profile Send private message Reply with quote
ASHLEY4



Joined: 28 Apr 2004
Posts: 376
Location: UK
ASHLEY4 06 Dec 2004, 21:16
I use Konqueror, but tested it with Mozilla and its fine.

\\\\||////
(@@)
ASHLEY4.

Batteries not included, Some assembly required.
Post 06 Dec 2004, 21:16
View user's profile Send private message Reply with quote
bogdanontanu



Joined: 07 Jan 2004
Posts: 403
Location: Sol. Earth. Europe. Romania. Bucuresti
bogdanontanu 07 Dec 2004, 05:36
I have fixed the problem Smile

Just for your reference guys, the right procedure to detect ATA/ATAPI devices is like this:

1)Reset device
2)Read signature
3)Based on signature send a command:
3a) ATA_Identify_Device command for PATA or SATA Hard Drives
3b) ATA_Identify_Packet_Device for PATAPI or SATAPI CD-ROM/RW

4)If command succeded --> you have a device;
on error the device is not present .

Theoretically Probing the ports after the first reset will also allow you to detect that something is or is not present on the IDE channel. This way you can speed things up by avoiding RESET on an non existing device... However you will need another RESET for existing devices ... after the PROBE or you risk loosing the signature .

Also take care to wait a long time after the RESET before you read the signature.
I have CD-ROMS here that answer very late, and timeouts of under 1s missed the detection.

Also never write to comamnd ports in WORDS or DWORDS ==> this makes controlers go crazy Wink ALWAYS use bytes.


That was all Wink
Post 07 Dec 2004, 05:36
View user's profile Send private message Visit poster's website Reply with quote
ASHLEY4



Joined: 28 Apr 2004
Posts: 376
Location: UK
ASHLEY4 07 Dec 2004, 11:11
YOU MEAN YOU DO THE SAME AS I DO Rolling Eyes , well that was a great tip, it must of tuck you about the same, as reading the above code to work that out.

bogdanontanu wrote:

3)Based on signature send a command:
3a) ATA_Identify_Device command for PATA or SATA Hard Drives
3b) ATA_Identify_Packet_Device for PATAPI or SATAPI CD-ROM/RW


ATA_Identify_Device command = 0xec
ATA_Identify_Packet_Device = 0xa1

\\\\||////
(@@)
ASHLEY4.

Batteries not included, Some assembly required.
Post 07 Dec 2004, 11:11
View user's profile Send private message Reply with quote
Octavio



Joined: 21 Jun 2003
Posts: 366
Location: Spain
Octavio 09 Dec 2004, 20:15
I haven,t done too many tests but this works on all the hardware i have.

1 select device (port+6)
2 read status byte(port+7) if =-1 then there is no disk
if busy to many time then no disk
3 send id command 0ec0h if error then send packet device id command
0a1h if error then no disk.
commands must be send byte by byte dword operations are used only for data transfers.
has someone tested the lba48 or dma modes?
Post 09 Dec 2004, 20:15
View user's profile Send private message Visit poster's website Reply with quote
Display posts from previous:
Post new topic Reply to topic

Jump to:  


< Last Thread | Next Thread >
Forum Rules:
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
You cannot attach files in this forum
You can download files in this forum


Copyright © 1999-2024, Tomasz Grysztar. Also on GitHub, YouTube.

Website powered by rwasa.