# How do computers really communicate with hard-drives on x86_64?

All of us have saved a file on our computers using a programming language. If I look down through the layers of abstraction, I usually get stuck at a kernel-level call or a C-call like fwrite(); But even at this already deep level things like filesystems and location of storage are hidden from us. For example, one cannot tell on which drive a file is stored when the partition uses more than one drive, nor do you need to care which file-system is used.

This leads me to an extensive set of questions:

Imagine you are a creator of an OS running on x86_64. You have not yet created an abstraction for working with external devices. Somebody now plugs in a device using a USB - Port.

1. Does this interrupt the processor or does this change a flag the OS can read? How would you make sure a routine is set up which will start communicating with the device once plugged in?

2. After this routine is set up, which protocols are you using to communicate with the device? Does it matter that the device is plugged in via USB, or would other ports work the same? If it does matter, how does the program know? (x86: Which assembly instructions are achieving communication with any device?)

3. You have now figured out that the device is indeed a hard-drive. Is communicating with every hard-drive the same? You would now like to - only for the matter of further questions - do the following: If this device contains another OS (OS-signature in boot section), start the other OS (reading), if however, the disk does not contain another OS you would like to inject your data to the disk at byte disk_size/2. (Writing) How would you accomplish that? (Protocol?, Assembly - Instruction?) EDIT: In my mind, a UEFI is also a tiny little OS. The boot section - in my mind - correct me if I am wrong - is a part of a hard drive where Bios or UEFI is searching the actual OS. So any OS could start another OS...

Kind regards!

Disclaimer: I am not asking for assembly code, I am asking for the mechanism in general. However, examples given in x86_64 are welcomed.

• Related question: cs.stackexchange.com/questions/80962/… – Pseudonym Mar 27 '20 at 1:25
• I'm not sure what you're referring to in the 3rd question. "Contains another OS" - what do you mean by that? Are you assuming the device is running its own code and its own OS? What does that have to do with a boot section, or starting that OS? I'm lost. – D.W. Mar 27 '20 at 1:44
• In my mind, a UEFI is also a tiny little OS. The boot section - in my mind - correct me if I am wrong - is a part of a hard drive where Bios or UEFI is searching the actual OS... – TVSuchty Mar 27 '20 at 7:34
• @TVSuchty I think you have multiple assumptions there that are not quite right. We prefer that you ask only one question per post. When you have multiple questions, it is better to ask them separately. Answering all three of those questions and also cleaning up the misconceptions seems like a lot to explain in an answer. – D.W. Mar 27 '20 at 8:20
• Today's (largeish, higher-end) hard disk drives run their own operating system (to handle e.g. forwarding broken sectors --no, they are impossible to avoid--, complex cacheing mechanisms, readahead/writebehind, and other goodies needed for performance). Some nutcase installed Linux on one of them. – vonbrand Mar 27 '20 at 17:37

The processor has a control bus which allows it to tell the motherboard it wants to write somewhere else than RAM. When the processor sets a certain line on the control bus, it can write data to a port instead of RAM.

The processor can send data to certain ports which, by convention, are used to talk to hardware. The Hard-Drives have controllers which will answer to certain values on their respective conventional ports. These will be called commands. SATA drives which are the most common types today use certain ports for bilateral communication between processor and hard-drive.

An example is PIO mode that all SATA compliant drives must respect. In PIO mode (https://wiki.osdev.org/ATA_PIO_Mode), the port 0x1f7 is used to send commands to the drive. It will then output its data onto a certain port that the processor will read to fetch the data.

As to USB, it is similar. The USB controller (xhci today see https://wiki.osdev.org/XHCI and https://wiki.osdev.org/Universal_Serial_Bus#USB_2.0_Host_Controllers) is actually polling its own USB port to determine if a device is plugged in at some point. This provides the plug and play functionalities.

When you do a read/write operation you use IO ports again just like before but these ports are mapped to RAM addresses creating RAM holes known as the PCI hole. To determine the memory mapped ports locations you need to parse the ACPI tables which are built by the BIOS during initialisation of the system. The ACPI tables have conventional locations in RAM that the OS can look for. Once the OS finds these tables it needs to interpret language known as AML to determine what devices are connected on the computer and where (at what RAM address) to find the ports/registers to communicate with these devices.

Other hardware then hard-drives (keyboard/mouse) work with interrupts and ports which is another complex subject.

PS: Developping your own x86-64 operating system is not that unrealistic. Osdev.org can help on that path. If you have some time and go step by step you will learn a lot.