ATA PIO Mode: Difference between revisions

[unchecked revision][unchecked revision]
Content deleted Content added
Creature (talk | contribs)
Replaced a couple of pre tags with wikitables.
More forceful rewording about ATA IDENTIFY
Line 56:
===Floating Bus===
 
The disk that was selected last (by the BIOS, during boot) is supposed to maintain control of the electrical values on each IDE bus. If there is no disk connected to the bus at all, then the electrical values on the bus will all go "high" (to +5 volts). A computer will read this as an 0xFF byte -- this is a condition called a "floating" bus. This is an excellent way to find out if there are no drives on a bus. <b>'''Before sending any data to the IO ports,</b>''' read the Regular Status byte. The value 0xFF is an illegal status value, and indicates that the bus has no drives. The reason to read the port before writing anything is that the act of writing can easily cause the voltages of the wires to go screwy for a millisecond (since there may be nothing attached to the wires to control the voltages!), and mess up any attempt to measure "float".
 
Measuring "float" is a shortcut for detecting that drives do not exist. Reading a non-0xFF value is not completely definitive. The definitive test for detecting drives is the [[#IDENTIFY command]].
 
===Detecting Controller IO Ports===
Line 72 ⟶ 74:
===IDENTIFY command===
 
To use the IDENTIFY command, select a target drive by sending 0xA0 for the master drive, or 0xB0 for the slave, to the "drive select" IO port. On the Primary bus, this would be port 0x1F6. AThen 400nsset delaythe isSectorcount, aLBAlo, goodLBAmid, ideaand LBAhi IO ports to 0 (port 0x1F2 to 0x1F5). Then send the IDENTIFY command (0xEC) to the Command IO port (0x1F7).
Then read the Status port (0x1F7) again. If the value read is 0, the drive does not exist. For any other value: poll the Status port (0x1F7) until bit 7 (BSY, value = 0x80) clears. Because of some ATAPI drives that do not follow spec, at this point you need to check the LBAmid and LBAhi ports (0x1F4 and 0x1F5) to see if they are non-zero. If so, the drive is not ATA, and you should stop polling. Otherwise, continue polling one of the Status ports until bit 3 (DRQ, value = 8) sets --, or until bit 0 (ERR, value = 1) sets.
 
At that point, if ERR is clear, the data is ready to read from the Data port (0x1F0). Read 256 words, and store them.
 
===="Command Aborted"====
 
ATAPI or SATA devices willare supposed to respond to an ATA IDENTIFY command by immediately reporting an error in the Status Register, rather than setting BSY, then DRQ, then sending 256 words of PIO data. These devices will also write specific values to the IO ports, that can be read. Seeing ATAPI specific values on those ports after thisan sort of "abort"IDENTIFY is definitive proof that the device is ATAPI -- on the Primary bus, IO port 0x1F4 will read as 0x14, and IO port 0x1F5 will read as 0xEB. If a normal ATA drive should ever happen to abort an IDENTIFY command, the values in those two ports will be 0. A SATA device will report 0x3c, and 0xc3 instead. See below for a code example.
 
'''However''', at least a few real ATAPI drives do not set the ERR flag after aborting an ATA IDENTIFY command. So do not depend completely on the ERR flag after an IDENTIFY.
Make sure to note that this means it is important to check the ERR bit (bit 0, value = 1) in the Regular or Alternate Status register, before trying to read the 256 words of PIO data.
 
====Interesting information returned by IDENTIFY====
Line 95 ⟶ 98:
 
* Words 100 through 103 taken as a QWORD contain the total number of 48 bit addressable sectors on the drive. (Probably also proof that LBA48 is supported.)
 
===Conformant?===
All by all, it seems that a lot of ATA drives handle operations differently, as ~, one of our members, found out (see [http://forum.osdev.org/viewtopic.php?f=1&t=20690&hilit=ATA+Detection the forums]). The floating bus 0xFF value, for example, isn't always the value you would expect it to be. Different hard drives may also report different values for the Cylinder Low and Cylinder High values which you usually check when an error was returned in status byte after attempting to execute the IDENTIFY (0xEC) command.
 
One could also try to ignore whether the ATA IDENTIFY command returns an error or not, and simply immediately continue with reading the Cylinder Low and High values. As said above, they should both be 0x00 for standard PATA devices. Sadly, it seems that hardware (and sometimes Bochs) can return different values for these registers. Sometimes it may help to try and 'flush' a couple of registers, e.g.:
 
<source lang="c">
// 'base' is e.g. 0x01F0.
outb(base + 2, 0x00); // Sector count
outb(base + 3, 0x00); // Sector number
outb(base + 4, 0x00); // Cylinder low
outb(base + 5, 0x00); // Cylinder high
</source>
 
Do this preferably just before you execute the IDENTIFY (0xEC) command. This will cause some hardware (and apparently, Bochs) to suddenly return proper values when you read the Cylinder Low and Cylinder High values later.
 
==Addressing Modes==
Line 142 ⟶ 130:
|-
| 3
| Sector Number / LBAlo
| This is CHS / LBA28 / LBA48 specific.
|-
| 4
| Cylinder Low / LBAmid
| Partial Disk Sector address.
|-
| 5
| Cylinder High / LBAhi
| Partial Disk Sector address.
|-