Disk Geometry

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
Tolga

Disk Geometry

Post by Tolga »

Hi everybody.

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

Thanks for all helps.
blip

Re:Disk Geometry

Post by blip »

For IDE disks, you should use the identify drive command, documents here.
Tolga

Re:Disk Geometry

Post by Tolga »

Hmm. Is there an example code? :-\
blip

Re:Disk Geometry

Post 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.
JAAman

Re:Disk Geometry

Post 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
blip

Re:Disk Geometry

Post 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. :)
blip

Re:Disk Geometry

Post 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.
User avatar
Brendan
Member
Member
Posts: 8561
Joined: Sat Jan 15, 2005 12:00 am
Location: At his keyboard!
Contact:

Re:Disk Geometry

Post 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
For all things; perfection is, and will always remain, impossible to achieve in practice. However; by striving for perfection we create things that are as perfect as practically possible. Let the pursuit of perfection be our guide.
blip

Re:Disk Geometry

Post 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.
Post Reply