Page 1 of 1

Disk Geometry

Posted: Mon May 15, 2006 8:54 am
by Tolga
Hi everybody.

How can i detect disk geomerty for Hard Disks? Is there any documents about this?

Thanks for all helps.

Re:Disk Geometry

Posted: Mon May 15, 2006 9:11 am
by blip
For IDE disks, you should use the identify drive command, documents here.

Re:Disk Geometry

Posted: Mon May 15, 2006 10:38 pm
by Tolga
Hmm. Is there an example code? :-\

Re:Disk Geometry

Posted: Tue May 16, 2006 1:01 am
by blip
I don't seem to remember any example code in any of the docs I've read, so I'll improvise with some untested x86 ASM code:

Code: Select all

; In: ES:(E)DI -> buffer for drive ID info
; Out: Buffer filled and (E)DI advanced by 512 bytes
GetIdentifyDriveInfo:
mov dx,1F7h   ; Drive command/status register

.WaitUntilNotBusy:
in al,dx
test al,80h   ; Test busy bit of status
jnz .WaitUntilNotBusy   ; It is normally a good idea to implement timeouts but this is supposed to be a simple example

dec dx  ; Drive head and drive select
mov al,0A0h   ; Select the master drive
out dx,al

inc dx   ; Drive command/status register
mov al,0ECh   ; Identify drive command
out dx,al

.WaitUntilBusy:
in al,dx
test al,80h   ; Test busy bit of status
jz .WaitUntilBusy

.WaitUntilNotBusy2:
in al,dx
test al,80h   ; Test busy bit of status
jnz .WaitUntilNotBusy2

mov cx,256   ; About to transfer 256 words, or 512 bytes
cld   ; Gonna use string instructions

.FillBuffer:

.WaitForMoreData:
in al,dx
test al,08h   ; Test DRQ (Data ReQuest) Bit
jz .WaitForMoreData:

mov dx,1F0h   ; Data register
in ax,dx
xchg ah,al   ; IIRC this is required since the data comes in byte-swapped
stosw
mov dx,1F7h   ; Drive command/status register
dec cx
jnz .FillBuffer

ret
Of course for an OS it would make sense to write this code to take in a base port address of the IDE interface and specify which drive on the interface should be queried. Also as a general rule it's a good idea to disable interrupts when programming hardware.

Re:Disk Geometry

Posted: Tue May 16, 2006 8:17 am
by JAAman
i would, however, recommend using LBA -- especially on newer drives

(iirc)there is no 48bit CHS(48bit LBA is required to use drives larger than 128GB)

on all drives larger than 8GB (and most drives larger than 2GB), the CHS value must be converted into LBA on the drive before it can be used anyway (and internally, you are prob using LBA already anyway -- so why convert it, just to have it converted back)

the only problem with LBA is that (iirc) it isnt supported on ST509 drives -- but then, they dont support the ID command either

Re:Disk Geometry

Posted: Tue May 16, 2006 11:33 am
by blip
I have at least two drives where the ID drive command is supported but LBA is not, they're 42 MB and 212 MB, but yes your code should definitely default to using LBA if possible. If something isn't supported you should see the error bit in the status register set and the abort bit set in the error register. I myself have yet to try 48-bit LBA since so far I don't actually require it to go beyond 128 GB since that's the size of my largest drive. :)

Re:Disk Geometry

Posted: Thu May 18, 2006 4:05 pm
by blip
From the EDI draft thread, figured it fit better here:
Brendan wrote:Also there doesn't seem to be any support for string instructions - "rep insd", "rep outsw", etc. These are used by some devices (e.g. PIO transfers for hard drives that don't support bus mastering/UDMA).
I have at least one machine where using REP INSW/OUTSW is a bad idea for PIO. You're supposed to go into the DRQ poll loop on them or else you get a "stretching" effect where you receive the same word several times before the next is ready (and it repeats) and the sector transfer is incomplete as a result. For example instead of "1 2 3 4" you might get "1 1 2 2 2 3 4 4".

Also I was wrong about the XCHG thing that I put in the example code I think.

Re:Disk Geometry

Posted: Thu May 18, 2006 4:54 pm
by Brendan
Hi,
blip wrote:I have at least one machine where using REP INSW/OUTSW is a bad idea for PIO. You're supposed to go into the DRQ poll loop on them or else you get a "stretching" effect where you receive the same word several times before the next is ready (and it repeats) and the sector transfer is incomplete as a result. For example instead of "1 2 3 4" you might get "1 1 2 2 2 3 4 4".
Actually, there's 5 different PIO modes (numbered "PIO 0" to "PIO 4") and an unofficial "PIO mode 5" that got killed by UDMA before anyone really supported it.

For all PIO modes "rep insw" should work, but for PIO modes 3 and 4 there's meant to be a way to enable 32 bit transfers so that you can use "rep insd" to get the full speed.

I'm thinking if you're getting a repeating pattern then you've got an old drive (e.g. PIO mode 0 and mode 1 only) on a much newer computer, and/or there's something dodgy going on - there's nothing in either the ATA specifications or in Hale Landis's "reference driver" that indicates the need for a DRQ polling loop...


Cheers,

Brendan

Re:Disk Geometry

Posted: Thu May 18, 2006 8:12 pm
by blip
It was an old drive in a "newer" computer but max it was a Pentium I machine with a 212 MB drive originally from a 486 system. Could it hurt in any way to leave in the DRQ loop in normal cases? I don't think it would give any real performance hit especially considering that the physical sector read can take much longer than the actual data fetch over the cable. I haven't done anything with 32-bit PIO transfers so far; when I say PIO I mean programmed input/output in general and include all modes unless otherwise specified.