ATA PIO Mode: Difference between revisions

m
Bot: Replace deprecated source tag with syntaxhighlight
[unchecked revision][unchecked revision]
m (Fixing/clarify "80 conductor cable detection")
m (Bot: Replace deprecated source tag with syntaxhighlight)
 
(30 intermediate revisions by 12 users not shown)
Line 1:
According to the ATA specs, PIO mode must always be supported by all ATA-compliant drives as the default data transfer mechanism.
 
PIO mode uses a tremendous amount of CPU resources, because every byte of data transferred between the disk and the CPU must be sent through the CPU's [[Inline Assembly/Examples#I\O access|IO port bus]] (not the memory). On some CPUs, PIO mode can still achieve actual transfer speeds of 16MB per sec, but no other processes on the machine will get any CPU time.
 
However, when a computer is just beginning to boot, there are no other processes. So PIO mode is an excellent and simple interface to utilize during bootup until the system goes into multitasking mode.
 
Please note that this article deals with what are now styled PATA hard disks, as opposed to SATA hard disks.
 
 
However, when a computer is just beginning to boot there are no other processes. So PIO mode is an excellent and simple interface to utilize during bootup, until the system goes into multitasking mode.
 
==Hardware==
Line 11 ⟶ 15:
What the original IDE specification did was to detach the disk controller boards from the motherboard, and stick one controller onto each disk drive, permanently. When the CPU accessed a disk IO port, there was a chip that shorted the CPU's IO bus pins directly onto the IDE cable -- so the CPU could directly access the drive's controller board. The data transfer mechanism between the CPU and the controller board remained the same, and is now called PIO mode.
(Nowadays, the disk controller chips just copy the electrical signals between the IO port bus and the IDE cable, until the drive goes into some other mode than PIO.)
 
 
 
==Master/Slave Drives==
 
There is only one wire dedicated to selecting which drive on each bus is active. It is either electrically "high" or "low", which means that there can never be more than two devices operational on any ATA bus. They are called the master and the slave devices, for no particular reason. TheirThe terms 'master' and 'slave' have largely been abandoned as they inaccurately portray the master drive as having some kind of superiority over the slave drive, or that the latter is dependent on the master. However, these terms will be used in this document. The functionality of the master and slave drives is almost completely identical. There is a special IO port bit that allows a driver to select either drive as the target drive for each command byte.
 
==Primary/Secondary Bus==
 
Current disk controller chips almost always support two ATA buses per chip. There is a standardized set of IO ports to control the disks on the buses. The first two buses are called the Primary and Secondary ATA bus, and are almost always controlled by IO ports 0x1F0 through 0x1F7, and 0x170 through 0x177, respectively (unless you change it). The associated Device Control Registers/Alternate Status ports are IO ports 0x3F6, and 0x376, respectively. The standard IRQ for the Primary bus is IRQ14, and IRQ15 for the Secondary bus.
 
If the next two buses exist, they are normally controlled by IO ports 0x1E8 through 0x1EF, and 0x168 through 0x16F, respectively. The associated Device Control Registers/Alternate Status ports are IO ports 0x3E6, and 0x366.
Line 25 ⟶ 31:
 
When the system boots, according to the specs, the PCI disk controller is supposed to be in "Legacy/Compatibility" mode. This means it is supposed to use the standardized IO port settings. You may have no real choice but to rely on that fact.
 
 
 
==400ns delays==
 
The method suggested in the ATA specs for sending ATA commands tells you to check the BSY and DRQ bits before trying to send a command. This means that you need to read a Status Register (Alternate Status is a good choice) <i>for the proper drive</i> before sending the next command. Which means that you need to select the correct device <i>first</i>, before you can read that status (and then send all the other values to the other IO ports).
Which means that a drive select may always happen <i>just before</i> a status read. This is bad. Many drives require a little time to respond to a "select", and push their status onto the bus. The suggestion is to read the Status register <b>FIVEFIFTEEN TIMES</b>, and only pay attention to the value returned by the last one -- after selecting a new master or slave device. The point being that you can assume an IO port read takes approximatelyat 100nsleast 30ns, so doing the first fourfourteen creates a 400ns420ns delay -- which allows the drive time to push the correct voltages onto the bus.
 
Reading IO ports to create delays wastes a lot of CPU cycles. So, it is actually smarter to have your driver remember the last value sent to each Drive Select IO port, to avoid doing unneeded drive selections, if the value did not change. If you do not send a drive select, then you only have to read the Status Register <b>once</b>.
Line 36 ⟶ 44:
 
There is a similar problem after writing the Command Register, with the ERR/DF bits. They are two slightly different kinds of errors that can terminate a command. BSY and DRQ will be cleared, but ERR or DF remain set <i>until just after you write a new command to the Command Register</i>. If you are using polling (see below), you should account for the fact that your first four reads of the Status Register, after sending your command byte, may have the ERR or DF bits still set accidentally. (If you are using IRQs, the Status will always be correct by the time the IRQ is serviced.)
 
 
 
==Cache Flush==
 
On some drives it is necessary to "manually" flush the hardware write cache after every write command. This is done by sending the 0xE7 command to the Command Register (then waiting for BSY to clear). If a driver does not do this, then subsequent write commands can fail invisibly, or "temporary bad sectors" can be created on your disk.
 
 
 
==Bad Sectors==
Line 51 ⟶ 63:
 
As said above, there are also "temporary bad sectors". When you read them you will get a hardware error, just like for a permanently bad sector. If you write to that sector, however, the write will work perfectly and the sector will turn back into a good sector. Temporary bad sectors can happen as a result of unflushed write caches, power spikes, or power failures.
 
 
 
==Detection and Initialization==
Line 59 ⟶ 73:
 
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===
 
Detecting controller IO ports is probably a waste of time. During boot, the IO ports assigned to the ATA bus are supposed to be located at standardized addresses. If they are not there, your only chance of finding them is to enumerate the disk controllers on the PCI bus. Alternately, if the ports <i>are</i> at the standard addresses, then "detecting" them gains you nothing. However, you will see controller detection code around, and it is a good thing to be able to recognize it, and know what it is for. If you suspect you know the location of a set of ATA controller IO ports, and there is at least one drive attached to that bus, then you can "detect" those IO ports. ATA controller IO ports are mostly read/write ports. This means that if you write a value to (for example) the "SectorCount" IO port, then you are supposed to be able to read the same value back again, to see what it is set to. This read/write function is performed by the master drive on the bus, unless the slave drive both exists and is selected. One caveat is that if you write a value to a "non-existent" IO port, you may be able to read that value back off the bus, if you read it immediately. So, generally, the way ATA IO port detection software works is to write a byte to one suspected ATA IO port, write a different byte to a different ATA IO port, then read back and verify the two values written to the two ports. If both bytes verify, then the IO ports are read/write ports, and they can be presumed to be ATA controller IO ports. On the Primary bus, ports 0x1F2 through 0x1F5 should all be read/write.
 
 
 
===Standard and Non-standard Detection===
Line 71 ⟶ 89:
 
The other method is to use the Execute Device Diagnostics command (0x90). It supposedly sets bits in the Error Register (0x1F1 on the Primary bus) to show the existence of master and slave devices on the bus.
 
 
 
===IDENTIFY command===
Line 78 ⟶ 98:
 
At that point, if ERR is clear, the data is ready to read from the Data port (0x1F0). Read 256 16-bit values, and store them.
 
 
 
===="Command Aborted"====
Line 84 ⟶ 106:
 
'''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.
 
 
 
====Interesting information returned by IDENTIFY====
Line 91 ⟶ 115:
* uint16_t 83: Bit 10 is set if the drive supports LBA48 mode.
 
* uint16_t 88: The bits in the low byte tell you the supported UDMA modes, the upper byte tells you which UDMA mode is active. If the active mode is not the highest supported mode, you may want to figure out why. ''Notes: The returned uint16_t should look like this in binary: 0000001 00000001. Each bit corresponds to a single mode. E.g. if the decimal number is 257, that means that only UDMA mode 1 is supported and running (the binary number above) if the binary number is 515, the binary looks like this, 00000010 00000011, that means that UDMA modes 1 and 2 are supported, and 2 is running. This is true for every mode. If it does not look like that, e.g 00000001 00000011, as stated above, you may want to find out why. The formula for finding out the decimal number is 257 * 2 ^ position + 2 ^position - 1.''
 
* uint16_t 93 from a master drive on the bus: Bit 11 is supposed to be set if the drive detects an 80 conductor cable. ''Notes: if the bit is set then 80 conductor cable is present and UDMA modes > 2 can be used; if bit is clear then there may or may not be an 80 conductor cable and UDMA modes > 2 shouldn't be used but might work fine. Because this bit is "master device only", if there is a slave device and no master there is no way information about cable type (and would have to assume UDMA modes > 2 can't be used).''
Line 102 ⟶ 126:
 
Currently there are three addressing modes to select particular sectors to read or write on a disk. They are 28 bit LBA, 48 bit LBA, and CHS. CHS mode is obsolete, but is discussed quickly below. The number of bits in the LBA modes refer to the number of significant bits in the sector "address", called an LBA. In 28 bit mode, LBAs from 0 to 0x0FFFFFFF are legal. This gives a total of 256M sectors, or 128GB of addressable space. So 28 bit LBA mode is also obsolete for many current drives. However, 28 bit PIO mode is faster than 48 bit addressing, so it may be a better choice for drives or partitions that do not violate the maximum LBA value limitation.
 
 
 
===Absolute/Relative LBA===
 
All the ATA commands that use LBA addressing require "absolute" LBAs (ie. the sector offset from the very beginning of the disk -- completely ignoring [[Partition Table|partition]] boundaries). At first glance, it might seem most efficient to store the LBA values in this same format in your OS. However, this is not the case. It is always necessary to validate the LBAs that are passed into your driver, as truly belonging to the partition that is being accessed. It ends up being smartest to use partition-relative LBA addressing in your code, because you then never need to test if the LBA being accessed is "off the front" of your current partition. So you only need to do half as many tests. This makes up for the fact that you need to add the absolute LBA of the beginning of the current partition to every "relative" LBA value passed to the driver. At the same time, doing this can give you access to one additional LBA address bit. (See the [[#ATA Driver|"33 bit LBA" driver]] code below.)
 
 
 
===Registers===
 
An ATA bus typically has 9ten I/O ports thatwhich control its behavior. For the primary bus, these I/O ports are usually 0x1F0 (the "I/O" port base) through 0x1F7, and 0x3F6 (see the directions"Control" belowport forbase) usagethrough details)0x3F7. TheFor valuesthe insecondary thisbus, tablethey are relativeusually to0x170 thethrough so-called0x177 I/Oand port0x376 basethrough address0x377. SoSome asystems may have non-standard port valuelocations offor 1the actuallyATA meansbusses, 0x1F0in +which 1case =it 0x1F1.may Thisbe ishelpful doneto becauseconsult the basesection addresson mayPCI varyto dependingdetermine onhow to retrieve port addresses for various devices in the hardwaresystem.
 
The values in these tables are relative to the so-called port base; a port offset of 1 from the I/O port base actually refers to port 0x1F1 (0x1F0 + 1 = 0x1F1). This is done because the base port may vary depending on the hardware in any given system. Also, some of these I/O ports map to different registers based on whether they are being read from or written to.
 
{| {{wikitable}}
|-
! Port Offset from
"I/O" base
! Direction
! Function
! Description
! Param. size LBA28/LBA48
|-
| 0
| R/W
| Data Port
| Data Register
| Read/Write PIO '''data''' bytes on this port.
| Read/Write PIO '''data''' bytes
| 16-bit / 16-bit
|-
| 1
| R
| Features / Error Information
| Error Register
| Usually used for ATAPI devices.
| Used to retrieve any error generated by the last ATA command executed.
| 8-bit / 16-bit
|-
| 1
| W
| Features Register
| Used to control command specific interface features.
| 8-bit / 16-bit
|-
| 2
| R/W
| Sector Count
| Sector Count Register
| Number of sectors to read/write (0 is a special value).
| 8-bit / 16-bit
|-
| 3
| R/W
| Sector Number / LBAlo
| Sector Number Register (LBAlo)
| This is CHS / LBA28 / LBA48 specific.
| 8-bit / 16-bit
|-
| 4
| R/W
| Cylinder Low / LBAmid
| Cylinder Low Register / (LBAmid)
| Partial Disk Sector address.
| 8-bit / 16-bit
|-
| 5
| R/W
| Cylinder High / LBAhi
| Cylinder High Register / (LBAhi)
| Partial Disk Sector address.
| 8-bit / 16-bit
|-
| 6
| R/W
| Drive / Head Port
| Drive / Head Register
| Used to select a drive and/or head. May supports extra address/flag bits.
| Used to select a drive and/or head. Supports extra address/flag bits.
| 8-bit / 8-bit
|-
| 7
| R
| Command port / Regular Status port
| Status Register
| Used to send commands or read the current status.
| Used to read the current status.
| 8-bit / 8-bit
|-
| 7
| W
| Command Register
| Used to send ATA commands to the device.
| 8-bit / 8-bit
|-
|}
 
====Status Byte====
 
 
In the following table you will find the layout of the so-called Status Byte.
{| {{wikitable}}
|-
! Offset from
"Control" base
! Direction
! Function
! Description
! Param. size LBA28/LBA48
|-
| 0
| R
| Alternate Status Register
| A duplicate of the Status Register which does not affect interrupts.
| 8-bit / 8-bit
|-
| 0
| W
| Device Control Register
| Used to reset the bus or enable/disable interrupts.
| 8-bit / 8-bit
|-
| 1
| R
| Drive Address Register
| Provides drive select and head select information.
| 8-bit / 8-bit
|-
|}
 
 
 
====Error Register====
 
{| {{wikitable}}
|-
! Bit
! Abbreviation
! Function
|-
| 0
| AMNF
| Address mark not found.
|-
| 1
| TKZNF
| Track zero not found.
|-
| 2
| ABRT
| Aborted command.
|-
| 3
| MCR
| Media change request.
|-
| 4
| IDNF
| ID not found.
|-
| 5
| MC
| Media changed.
|-
| 6
| UNC
| Uncorrectable data error.
|-
| 7
| BBK
| Bad Block detected.
|}
 
 
 
====Drive / Head Register (I/O base + 6)====
 
{| {{wikitable}}
|-
! Bit
! Abbreviation
! Function
|-
| 0 - 3
|
| In CHS addressing, bits 0 to 3 of the head. In LBA addressing, bits 24 to 27 of the block number.
|-
| 4
| DRV
| Selects the drive number.
|-
| 5
| 1
| Always set.
|-
| 6
| LBA
| Uses CHS addressing if clear or LBA addressing if set.
|-
| 7
| 1
| Always set.
|}
 
 
 
====Status Register (I/O base + 7)====
 
{| {{wikitable}}
Line 164 ⟶ 330:
| ERR
| Indicates an error occurred. Send a new command to clear it (or nuke it with a Software Reset).
|-
| 1
| IDX
| Index. Always set to zero.
|-
| 2
| CORR
| Corrected data. Always set to zero.
|-
| 3
Line 186 ⟶ 360:
|}
 
Technically, when BSY is set, the other bits in the Status byte are meaningless. It is also generally a Bad Idea to test the "Seek Complete" (DSC) bit, because it has been deprecated and reusedreplaced forby anotherthe purposenewer SRV bit.
 
====Device Control Register / Alternate Status====
 
 
There is an additional IO port that changes the behavior of each ATA bus, called the Device Control Register (on the Primary bus, port 0x3F6). Each ATA bus has its own Control Register.
====Alternate Status Register (Control base + 0)====
You cannot read the Control Register. Reading the port gets you the value of the Alternate Status Register, instead.
 
Reading the Device Control Register port gets you the value of the Alternate Status Register, instead.
The value of Alternate Status is always the same as the Regular Status port (0x1F7 on the Primary bus), but reading the Alternate Status port does not affect interrupts. (See Preempting IRQs, below).
 
 
=====Control Register bit definitions:=====
 
====Device Control Register (Control base + 0)====
 
There is an additional IO port that changes the behavior of each ATA bus, called the Device Control Register (on the Primary bus, port 0x3F6). Each ATA bus has its own Control Register.
 
{| {{wikitable}}
Line 201 ⟶ 380:
! Abbreviation
! Function
|-
| 0
| n/a
| Always set to zero.
|-
| 1
Line 208 ⟶ 391:
| 2
| SRST
| Set, then clear (after 5us), this to do a "Software Reset" on all ATA drives on a bus, if one is misbehaving.
|-
| 3
| n/a
| Reserved.
|-
| 4
| n/a
| Reserved.
|-
| 5
| n/a
| Reserved.
|-
| 6
| n/a
| Reserved.
|-
| 7
Line 216 ⟶ 415:
 
All other bits are reserved and should always be clear. In general, you will want to leave HOB, SRST, and nIEN cleared. Set each Device Control Register to 0 once, during boot.
 
====Drive Address Register (Control base + 1)====
 
{| {{wikitable}}
|-
! Bit
! Abbreviation
! Function
|-
| 0
| DS0
| Drive 0 select. Clears when drive 0 selected.
|-
| 1
| DS1
| Drive 1 select. Clears when drive 1 selected.
|-
| 2 - 5
| HS0 - HS3
| One's compliment representation of the currently selected head.
|-
| 6
| WTG
| Write gate; goes low while writing to the drive is in progress.
|-
| 7
| n/a
| Reserved for compatibility with floppy drive controllers which may use this bit.
|}
 
==Resetting a drive / Software Reset==
 
For non-ATAPI drives, the only method a driver has of resetting a drive after a major error is to do a "software reset" on the bus. Set bit 2 (SRST, value = 4) in the proper Control Register for the bus. This will reset <b>both</b> ATA devices on the bus. Then, you have to clear that bit again, yourself. The master drive on the bus is automatically selected. ATAPI drives set values on their LBA_LOW and LBA_HIGH IO ports, but are not supposed to reset or even terminate their current command.
 
 
 
==IRQs==
 
Note: When a command terminates with an error, it does <b>not</b> generate an IRQ. It is smart to check the Alternate Status Register a few times per second to see if the ERR bit has set. Otherwise, you will not know until your command times out.
 
 
 
===Handling an IRQ===
Line 242 ⟶ 474:
 
Note: if you are still in singletasking mode, and polling the Regular Status Register in PIO mode only, then the only thing the IRQ handler needs to do is send EOI to the PICs. You may even want to set the Control Register's nIEN bit, to try to shut off disk IRQs completely.
 
 
 
===Polling the Status vs. IRQs===
Line 254 ⟶ 488:
<b>How to poll</b> (waiting for the drive to be ready to transfer data):
Read the Regular Status port until bit 7 (BSY, value = 0x80) clears, and bit 3 (DRQ, value = 8) sets -- or until bit 0 (ERR, value = 1) or bit 5 (DF, value = 0x20) sets. If neither error bit is set, the device is ready right then.
 
 
 
===Preempting/Preventing IRQs from firing:===
Line 260 ⟶ 496:
A much more complete way to prevent ATA IRQs from happening is to set the nIEN bit in the Control Register of a particular <i>selected drive</i>. This should prevent the drive on the bus from sending any IRQs at all, until you clear the bit again. <b>However, it may not always work!</b> Several programmers have reported problems making nIEN work.
Drives only respond to <i>newly written values</i> of nIEN when they are the selected drive on the bus. That is, if a drive is selected, and you set nIEN, then select the other drive with the Drive Select Register, then clear nIEN -- then the first drive should "remember" forever that it was told not to send IRQs -- until you select it again, and write a 0 to the nIEN bit in the Control Register.
 
 
 
===Read/Write Multiple===
Line 266 ⟶ 504:
 
<b>NOTE:</b> Overall, PIO mode is a slow transfer method. Under real working conditions, almost any drive should be controlled by a DMA driver, and should not be using PIO. Trying to speed up PIO mode by preempting IRQs (or any other method) is mostly a waste of time and effort. ATA drives that are 400MB or smaller may not support Multiword DMA mode 0, however. If you want to support drives that size, then perhaps a <i>little</i> effort spent on PIO mode drivers is worthwhile.
 
 
 
==x86 Directions==
Line 293 ⟶ 533:
===Writing 28 bit LBA===
To write sectors in 28 bit PIO mode, send command "WRITE SECTORS" (0x30) to the Command port. Do <b>not</b> use <b>REP</b> OUTSW to transfer data. There must be a tiny delay between each OUTSW output uint16_t. A jmp $+2 size of delay. Make sure to do a Cache Flush (ATA command 0xE7) after each write command completes.
 
 
 
===48 bit PIO===
Reading sectors using 48 bit PIO is very similar to the 28 bit method:
 
(Notes: A sector count of 0 means 65536 sectors = 32MB. Try not to send bytes to the same IO port twice in a row. Doing so is <b>much</b> slower than doing two outb() commands to <b>different</b> IO ports. The important thing is that the high byte of the sector count, features and LBA bytes 4, 5, & 6 go to their respective ports <b>before the low bytes</b>.)
 
Assume you have a sectorcount uint16_t and a 6 byte LBA value. Mentally number the LBA bytes as 1 to 6, from low to high.
Line 319 ⟶ 561:
 
After the command byte is sent, transfer each sector of data in exactly the same way as for a 28 bit PIO Read/Write command.
 
 
 
==CHS mode==
Line 349 ⟶ 593:
 
Note on the "magic bits" sent to port 0x1f6: Bit 6 (value = 0x40) is the LBA bit. This must be clear for CHS transfers, as said above. Bits 7 and 5 are obsolete for <b>current</b> ATA drives, but must be set for backwards compatibility with very old (ATA1) drives.
 
 
 
==x86 Code Examples==
Line 355 ⟶ 601:
(Using a Software Reset -- adapted from PypeClicker)
 
<sourcesyntaxhighlight lang="c">
/* on Primary bus: ctrl->base =0x1F0, ctrl->dev_ctl =0x3F6. REG_CYL_LO=4, REG_CYL_HI=5, REG_DEVSEL=6 */
int detect_devtype (int slavebit, struct DEVICE *ctrl)
Line 375 ⟶ 621:
return ATADEV_UNKNOWN;
}
</syntaxhighlight>
</source>
 
 
 
===ATA Driver===
Line 381 ⟶ 629:
(Note: the following routines should all include some form of OS-specific timeout.)
 
<sourcesyntaxhighlight lang="asm">
; do a singletasking PIO ATA read
; inputs: ebx = # of sectors to read, edi -> dest buffer, esi -> driverdata struct, ebp = 4b LBA
Line 658 ⟶ 906:
pop eax
ret
</syntaxhighlight>
</source>
 
 
 
==Comments==
ATA Execute Drive Diagnostic command (0x90) may not work right in Bochs.
 
 
 
==See Also==
===Wiki Pages===
* [[ATA Command Matrix|ATA Command Matrix]]
* [[MBR_(x86)|Master Boot Record (x86)]]
* [[Partition_Table|Partition Table (x86)]]
* [[PCI IDE Controller|IDE Controller]]
 
===Threads===
*[http://www.osdev.org/phpBB2/viewtopic.php?t=12268 How to w/r harddisk in pmode? (ASM Code from Dex)]
*[http://www.osdev.org/phpBB2/viewtopic.php?t=15314 ATA PIO code library (ASM code from XCHG)]
*[httphttps://forum.osdev.org/viewtopic.php?f=1&t=33152&p=167798285620#p167798p285620 IDEproblem Tutorialwith reading and writing to hard disc (C code fromfor reading/writing with ''mostafazizo''PIO28)]
 
===External Links===
Line 677 ⟶ 931:
* http://www.ata-atapi.com -- Public Domain C driver sourcecode, including SATA, Busmatering DMA, ATAPI -- not perfect, but good.
* [http://hddguru.com/content/en/documentation/ HDD Guru] -- The actual ATA specs from the first one that was released in 1994 to the 8th one in 2006.
* An example of [http://msdn.microsoft.com/en-us/library/windows/hardware/ff559006(v=vs.85).aspx the structure of the data returned by the IDENTIFY Command] (in case you wanted to know what most of the fields were for).
* [http://www.ranish.com/part/primer.htm Partitioning Primer] -- A .HTM file containing some information about partitioning.
* [http://www.fysnet.net/media_storage_devices.htm A book] written by somebody on the forum about ATA and SATA.
* [https://github.com/omarrx024/xos/blob/master/kernel/blkdev/ata.asm ATA PIO driver in assembly.]
 
[[Category:ATA]]