Hi everybody.
How can i detect disk geomerty for Hard Disks? Is there any documents about this?
Thanks for all helps.
Disk Geometry
Re:Disk Geometry
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:
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.
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
Re:Disk Geometry
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
(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
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
From the EDI draft thread, figured it fit better here:
Also I was wrong about the XCHG thing that I put in the example code I think.
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".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).
Also I was wrong about the XCHG thing that I put in the example code I think.
Re:Disk Geometry
Hi,
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
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.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".
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.
Re:Disk Geometry
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.