The general workflow to make a hard disk driver

Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
sunnysideup
Member
Member
Posts: 106
Joined: Sat Feb 08, 2020 11:11 am
Libera.chat IRC: sunnysideup

The general workflow to make a hard disk driver

Post by sunnysideup »

Hello!

I'm doing a bit of OSDev. I have done basic interrupt handling, keyboard drivers, virtual memory management, etc. I also use a FAT12 filesystem as my primary filesystem, mostly because I followed this resource : http://www.brokenthorn.com/Resources/OSDevIndex.html.

I think that the next thing I want is a hard disk driver. The resource that I follow (It was written around 2008) describes a floppy disk controller that is (was?) present in machines. It's 2020 now! Does the floppy disk driver even exist now?? Probably BIOS emulates it? (SMM??)

I think that now, in order to make a disk driver, I need to do something with PCI? SATA?, and it's not some simple controller anymore.

These are just my guesses :) . I'm not sure where I should start reading this from.

This is my target basically: Make something like BIOS int 0x13 in protected mode. Where should I start?

Also, where does PCIe come into the picture? Is ATA related to PCIe in any way? I've discussed that PCIe buses are kind of the primary buses nowadays (Almost all devices connect to them). And the FSB (ISA bus??) has been squashed into the processor SoC? Any good resources/diagrams that might explain the motherboard structure better?

Edit: Alright, I did some research, I got this diagram: https://sabercomlogica.com/wp-content/u ... re-8-1.jpg. Can most of today's motherboards be "logically" considered as this? (I know that the northbridge, etc. has been squashed into the CPU SoC, so physically a motherboard might be way different)
User avatar
iansjack
Member
Member
Posts: 4703
Joined: Sat Mar 31, 2012 3:07 am
Location: Chichester, UK

Re: The general workflow to make a hard disk driver

Post by iansjack »

The good news is that it can be a very simple controller - far simpler than the floppy-disk driver you have looked at. Your best bet is to start with a simple driver using ATA PIO mode, as detailed here: https://wiki.osdev.org/ATA_PIO_Mode

This should work fine on most hardware as long as the controller is set to "IDE" mode in the BIOS. The ports are at fixed addresses, and there is no need to worry about PCI at this stage; you just need to write and read the standard ports. It's much easier than controlling a floppy disk. Later you might want to look at more complicated drivers, using the more advance abilities of PCI cards, but this simple driver should be enough to get you started.

When you get really ambitious you'll be looking at writing a USB driver so that you can access USB-connected storage; but that's a rather more complicated ballgame.
sunnysideup
Member
Member
Posts: 106
Joined: Sat Feb 08, 2020 11:11 am
Libera.chat IRC: sunnysideup

Re: The general workflow to make a hard disk driver

Post by sunnysideup »

So a simple ATA controller is my best bet to get started I'm guessing...
I think later I can move on to DMA accesses from there?
iansjack wrote:This should work fine on most hardware as long as the controller is set to "IDE" mode in the BIOS
What exactly does this do? (If configured to AHCI, will the port numbers vary?) Also, is it fixed after boot? That is, can I change the mode to AHCI mode or something else from the kernel (with no BIOS interference)? Does BIOS emulate this controller, by popping the system into SMM? Sorry for the barrage of questions :oops: :oops: :-# :-#

Yeah this is confusing me too... What is the logical view that I should picture when "thinking" of a motherboard?
sunnysideup wrote: Also, where does PCIe come into the picture? Is ATA related to PCIe in any way? I've discussed that PCIe buses are kind of the primary buses nowadays (Almost all devices connect to them). And the FSB (ISA bus??) has been squashed into the processor SoC? Any good resources/diagrams that might explain the motherboard structure better?

Edit: Alright, I did some research, I got this diagram: https://sabercomlogica.com/wp-content/u ... re-8-1.jpg. Can most of today's motherboards be "logically" considered as this? (I know that the northbridge, etc. has been squashed into the CPU SoC, so physically a motherboard might be way different)
User avatar
iansjack
Member
Member
Posts: 4703
Joined: Sat Mar 31, 2012 3:07 am
Location: Chichester, UK

Re: The general workflow to make a hard disk driver

Post by iansjack »

IDE mode makes the controller act like the standard IDE controller that has been present in PCs for decades. It will use standard ports and is present in just about any PC or emulator that you come across. How it is connected hardware-wise doesn't matter. Just use it as described in the wiki article.

Forget PCI, forget DMA, forget AHCI for the time being.
sunnysideup
Member
Member
Posts: 106
Joined: Sat Feb 08, 2020 11:11 am
Libera.chat IRC: sunnysideup

Re: The general workflow to make a hard disk driver

Post by sunnysideup »

Alright, I'm giving it a read.
Here are a few quick questions:
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.)
Quoted from the wiki ^

So are disk controllers present in the disk drives? Is it the same today?
Current disk controller chips almost always support two ATA buses per chip
Are these the same disk controllers that are present in the disk drives? What does it mean that it supports 2 buses per chip? I thought there should be 2 chips per bus (2 disk drives per bus : master/slave and if each disk has a controller, 2 chips per bus)

Am I going wrong somewhere? Perhaps there's something like the PCI disk controller and that's different from these on disk controllers?
Last edited by sunnysideup on Fri Mar 20, 2020 12:41 am, edited 1 time in total.
User avatar
iansjack
Member
Member
Posts: 4703
Joined: Sat Mar 31, 2012 3:07 am
Location: Chichester, UK

Re: The general workflow to make a hard disk driver

Post by iansjack »

TBH, I don't know, and don't really care, how the hardware is implemented. I'm just interested in the programming interface which lets me read and write disks.
sunnysideup
Member
Member
Posts: 106
Joined: Sat Feb 08, 2020 11:11 am
Libera.chat IRC: sunnysideup

Re: The general workflow to make a hard disk driver

Post by sunnysideup »

Alright sure, that makes sense too...
I'm wondering, what's the difference between writing to port 0x1F7 (Command register for the first bus?)1 and writing to 0x3F7/0x3F6 (These seem to be some sort of 'control' registers. What are they?
User avatar
iansjack
Member
Member
Posts: 4703
Joined: Sat Mar 31, 2012 3:07 am
Location: Chichester, UK

Re: The general workflow to make a hard disk driver

Post by iansjack »

IDE supports two channels, to each of which two drives can be attached. Each of these channels is controlled by a set of 8 registers accessed from ports 0x1F0-7 and 0x3F0-7 respectively. The wiki explains what each register does and how to use them.
sunnysideup
Member
Member
Posts: 106
Joined: Sat Feb 08, 2020 11:11 am
Libera.chat IRC: sunnysideup

Re: The general workflow to make a hard disk driver

Post by sunnysideup »

Well, the wiki says that the second ATA bus is from 0x170-7 :(
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.
I was confused about these device control registers (0x3F6). The wiki doesn't really mention 0x3F0. Maybe I'm missing something?
User avatar
iansjack
Member
Member
Posts: 4703
Joined: Sat Mar 31, 2012 3:07 am
Location: Chichester, UK

Re: The general workflow to make a hard disk driver

Post by iansjack »

You are correct. I misread the wiki (and it's a long time since I wrote any code using this info).

I'd suggest that you just follow the wiki article rather than me trying to relay the information in it to you. For starters just concentrate on one channel and one disk.
sunnysideup
Member
Member
Posts: 106
Joined: Sat Feb 08, 2020 11:11 am
Libera.chat IRC: sunnysideup

Re: The general workflow to make a hard disk driver

Post by sunnysideup »

Alright, I've read the wiki article and here's my attempt to make a very very simple ATA disk driver.

Code: Select all

#include<stdint.h>
#include"dadio.h"
#include"hal.h"

#define STATUS_BSY 0x80
#define STATUS_DRQ 0x08
#define STATUS_DF 0x20
#define STATUS_ERR 0x01

//This is really specific to out OS now, assuming ATA bus 0 master 
//Source - OsDev wiki
void read_sectors_PIO(uint32_t target_address, uint32_t LBA, uint8_t sector_count)
{

	write_port(0x1F6,0xE0 | ((LBA >>24) & 0xF));
	write_port(0x1F2,sector_count);
	write_port(0x1F3, (uint8_t) LBA);
	write_port(0x1F4, (uint8_t)(LBA >> 8));
	write_port(0x1F5, (uint8_t)(LBA >> 16)); 

	//Polling the status port
	uint8_t status = read_port(0x1F7);
	printf("\nStatus byte: ");
	printhex(status);
	while(status & STATUS_BSY)
	{
		status = read_port(0x1F7);
		printf("\nStatus byte: "); //Prints a string on the monitor
		printhex(status); //Prints the hex value of an uint32_t variable
	}

	while(!(status & STATUS_DRQ))
	{
		status = read_port(0x1F7);
	}
	printf("Success");
}
AFAIK I followed the wiki instructions as properly as possible, while still trying to make a 'quick' driver.

However, (status & STATUS_DRQ) is always false (i.e The DRQ bit is never asserted), and I'm stuck in the second while loop. Where have I gone wrong?
User avatar
BenLunt
Member
Member
Posts: 941
Joined: Sat Nov 22, 2014 6:33 pm
Location: USA
Contact:

Re: The general workflow to make a hard disk driver

Post by BenLunt »

Hi,

There is a possibility, though not likely, that you need to reset the controller first. Resetting the controller also has a benefit.

1) Reset the controller by setting the SRST bit in the CONTROL register (secondary set + 2).
2) Ensure that this bit is set for a duration of at least 5 uS before clearing it.
3) Wait a minimum of 2 mS for the controller to come out of reset.
4) Poll the BSY bit. A controller is allowed to have the BSY bit set for up to 30 seconds.
5) Once the BSY bit is clear, wait an additional 5 mS.
6) Now you *must* read the ERROR register. You can disregard the result, but it must be read.
7) Now select the drive you wish to start using.
Please note, after writing to the DEV_HEAD register, you must wait at least 1 mS before you access any of the other registers.

Now for the benefit mentioned above. Reading the COUNT and SECT_NUM registers will give you a type code. This will allow you to find out what type of drive is attached. ATA (magnetic) or ATAPI (optical).

While writing your ATA(PI) driver, take into consideration, port access. For example, your code will need to "select" the drive often. Every time you access the drive, you will need to ensure that the controller is set to that drive. However, selecting the drive takes time, quite a bit of time if you really look at it. One mS is actually a long time if you access the drive quite frequently. If you access the drive 500 times, that is a half of a second total wait time. This is very noticeable when many disk accesses occur. So, how do you get around this? Simply keep a flag indicating what the last selected drive was. If you are selecting the same drive, no need to actually select it. Therefore, there is no 1 mS delay. Simply return. Very noticeable speed-up when you do a lot of disk access.

In my opinion, hardware programming is the most enjoyable part of this hobby of ours. Good luck and have fun.

Ben
- http://www.fysnet.net/media_storage_devices.htm
sunnysideup
Member
Member
Posts: 106
Joined: Sat Feb 08, 2020 11:11 am
Libera.chat IRC: sunnysideup

Re: The general workflow to make a hard disk driver

Post by sunnysideup »

Btw I'm using qemu rn, and it's getting 'stuck' on qemu.
Do I need to do all this initialization on qemu too?
I guess it's advisable, but even for a quick driver?
sunnysideup
Member
Member
Posts: 106
Joined: Sat Feb 08, 2020 11:11 am
Libera.chat IRC: sunnysideup

Re: The general workflow to make a hard disk driver

Post by sunnysideup »

Oh lol, I never sent the command to read the disk at the first place! Damn I'm stupid
User avatar
BenLunt
Member
Member
Posts: 941
Joined: Sat Nov 22, 2014 6:33 pm
Location: USA
Contact:

Re: The general workflow to make a hard disk driver

Post by BenLunt »

sunnysideup wrote:Oh lol, I never sent the command to read the disk at the first place! Damn I'm stupid
I figured it was obvious enough that if you looked it over a little, you would find it :-)

Don't forget to read the STATUS register after every sector or the next sector won't be read.

Ben
Post Reply