Hi
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;
}
==============================
But this only works for me in bochs, but not in a real PC, or Microsoft Virtual PC
Does any one know a way to do it???
Thanks a lot for any help.
Detecting the ATA devices
- kataklinger
- Member
- Posts: 381
- Joined: Fri Nov 04, 2005 12:00 am
- Location: Serbia
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.
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.
- smiddy
- Member
- Posts: 127
- Joined: Sun Oct 24, 2004 11:00 pm
- Location: In my cube, like a good leming. ;-)
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
The best place for ATA and ATAPI code is: http://www.ata-atapi.com/. The code is easy to port to a system.
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
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
Detecting ATA/ATAPI/SATA
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
By the way does any one know about SATA specification, and how to read and write sectors etc?
Re: Detecting ATA/ATAPI/SATA
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.keller wrote: By the way does any one know about SATA specification, and how to read and write sectors etc?
cheers Joe