A hard disk contains a set of registers or ports that are used to communicate to and from the computer. For the end user these ports are normally not significant but when it comes to hard disk firmware programming and direct drive access, knowledge of these ports and how to use them programmatically is very important.
Firstly there are two main modes of port access. Data functions and Non-data functions. The two types are obvious, but for clarity, data functions involve writing and reading data to and from the hard disk. Non-data commands tell the drive to do something or stop doing something. for example, send drive to sleep, wake it up, perform a soft reset, etc. Non data commands are not designed to affect the data on the drive.
The process of working with ports is to load in the values into the registers, then execute the command.
Here is a list of ports available on a modern hard disk.
|Read from register||Write to register||Size|
|1F1||Error register||Feature register||Byte|
|1F2||Sector count register||Byte|
|1F3||Sector number register||Byte|
|1F4||Cylinder low register||Byte|
|1F5||Cylinder high register||Byte|
|1F7||Status register||Command register||Byte|
It is important to differentiate between reading and writing data to reading and writing to registers. When writing to a register you are just loading the register with the value. If the intention is to read data from the drive, you would enter the details about the location of the read, by loading ports 1F2 to 1F6, then load the read command into register 1F7. The drive will then fetch the data and load it into the buffer. You would then load read the data from 1F0.
When reading or writing with drives that support 48 bit LBA values, the process is slightly different. If for example you were making a 48 bit read you would load 1F3 - 1F5 with the first set of values, then again with the second set and finally send the command for the read.