ATA PIO Mode: Difference between revisions

m
Bot: Replace deprecated source tag with syntaxhighlight
[unchecked revision][unchecked revision]
(→‎Registers: Added Drive Address Register)
m (Bot: Replace deprecated source tag with syntaxhighlight)
 
(19 intermediate revisions by 9 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.
 
 
Line 18 ⟶ 20:
==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 37:
 
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 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 122:
 
* uint16_t 100 through 103 taken as a uint64_t contain the total number of 48 bit addressable sectors on the drive. (Probably also proof that LBA48 is supported.)
 
 
 
==Addressing Modes==
Line 139 ⟶ 137:
===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 through 0x1F7 (the "I/O" portsport base), through 0x1F7 and 0x3F6 (the "Control" port base). Thethrough values0x3F7. in this table are relative toFor the so-calledsecondary I/Obus, portthey baseare address.usually So0x170 athrough port0x177 offsetand of0x376 1through actually means 0x1F0 + 1 = 0x1F10x377. ThisSome issystems donemay becausehave thenon-standard baseport addresslocations may vary depending onfor the hardware.ATA Alsobusses, somein ofwhich thesecase I/Oit portsmay mapbe helpful to differentconsult registersthe basedsection on whetherPCI theyto aredetermine beinghow readto fromretrieve orport writtenaddresses to.for Seevarious thedevices tablein below for usagethe detailssystem.
 
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 port
! Direction
! Function
Line 207:
| W
| Command Register
| Used to send ATA commands to the device.
| 8-bit / 8-bit
|-
Line 216:
{| {{wikitable}}
|-
! Port Offset from
"Control" portbase
! Direction
! Function
Line 231:
| 0
| W
| CommandDevice Control Register
| Used to sendreset ATAthe commandsbus toor theenable/disable deviceinterrupts.
| 8-bit / 8-bit
|-
Line 288:
 
 
====Drive / Head Register (I/O base + 6)====
 
{| {{wikitable}}
Line 319:
 
 
====Status Register (I/O base + 7)====
 
{| {{wikitable}}
Line 364:
 
 
====Alternate Status Register (Control base + 0)====
 
Reading the Device Control Register port gets you the value of the Alternate Status Register, instead.
Line 371:
 
 
====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.
Line 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
Line 416:
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)====
 
 
====Drive Address Register====
 
{| {{wikitable}}
Line 595 ⟶ 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.
 
 
 
==ATA Commands==
 
And finally, a list of many ATA commands.
 
{| {{wikitable}}
|-
! Command
! Description
|-
| 1x
| Recalibrate
|-
| 20
| Read sectors with retry
|-
| 21
| Read sectors without retry
|-
| 22
| Read long with retry
|-
| 23
| Read long without retry
|-
| 30
| Write sectors with retry
|-
| 31
| Write sectors without retry
|-
| 32
| Write long with retry
|-
| 33
| Write long without retry
|-
| 3C
| Write verify
|-
| 40
| Read verify sectors with retry
|-
| 41
| Read verify sectors without retry
|-
| 50
| Format track
|-
| 7X
| Seek
|-
| 8x
| Vendor unique
|-
| 90
| Execute drive diagnostics
|-
| 91 or E0
| Initialize drive parameters
|-
| 94 or E1
| Standby immediate
|-
| 95 or E2
| Idle immediate
|-
| 96 or E3
| Standby
|-
| 97 or E4
| Idle
|-
| 98 or E5
| Check power mode
|-
| 99 or E6
| Set sleep mode
|-
| 9A
| Vendor unique
|-
| C0 - C3
| Vendor unique
|-
| C4
| Read multiple
|-
| C5
| Write multiple
|-
| C6
| Set multiple mode
|-
| C8
| Read DMA with retry
|-
| C9
| Read DMA without retry
|-
| CA
| Write DMA with retry
|-
| CB
| Write DMA with retry
|-
| E4
| Read buffer
|-
| E8
| Write buffer
|-
| E9
| Write same
|-
| EC
| Identify drive
|-
| EF
| Set features
|-
| F0 - F4
| EATA standard
|-
| F5 - FF
| Vendor unique
|-
|}
 
 
Line 733 ⟶ 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 753 ⟶ 621:
return ATADEV_UNKNOWN;
}
</syntaxhighlight>
</source>
 
 
Line 761 ⟶ 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 1,038 ⟶ 906:
pop eax
ret
</syntaxhighlight>
</source>
 
 
Line 1,049 ⟶ 917:
==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 1,065 ⟶ 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.
* An exmaple 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.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.]