The general workflow to make a hard disk driver
-
- Member
- Posts: 106
- Joined: Sat Feb 08, 2020 11:11 am
- Libera.chat IRC: sunnysideup
The general workflow to make a hard disk driver
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)
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)
Re: The general workflow to make a hard disk driver
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.
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.
-
- 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
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?
Yeah this is confusing me too... What is the logical view that I should picture when "thinking" of a motherboard?
I think later I can move on to DMA accesses from there?
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 questionsiansjack wrote:This should work fine on most hardware as long as the controller is set to "IDE" mode in the BIOS
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)
Re: The general workflow to make a hard disk driver
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.
Forget PCI, forget DMA, forget AHCI for the time being.
-
- 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
Alright, I'm giving it a read.
Here are a few quick questions:
So are disk controllers present in the disk drives? Is it the same today?
Am I going wrong somewhere? Perhaps there's something like the PCI disk controller and that's different from these on disk controllers?
Here are a few quick questions:
Quoted from the wiki ^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.)
So are disk controllers present in the disk drives? Is it the same today?
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)Current disk controller chips almost always support two ATA buses per chip
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.
Re: The general workflow to make a hard disk driver
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.
-
- 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
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?
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?
Re: The general workflow to make a hard disk driver
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.
-
- 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
Well, the wiki says that the second ATA bus is from 0x170-7
I was confused about these device control registers (0x3F6). The wiki doesn't really mention 0x3F0. Maybe I'm missing something?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.
Re: The general workflow to make a hard disk driver
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.
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.
-
- 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
Alright, I've read the wiki article and here's my attempt to make a very very simple ATA disk driver.
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?
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");
}
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?
Re: The general workflow to make a hard disk driver
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
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
-
- 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
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?
Do I need to do all this initialization on qemu too?
I guess it's advisable, but even for a quick driver?
-
- 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
Oh lol, I never sent the command to read the disk at the first place! Damn I'm stupid
Re: The general workflow to make a hard disk driver
I figured it was obvious enough that if you looked it over a little, you would find it :-)sunnysideup wrote:Oh lol, I never sent the command to read the disk at the first place! Damn I'm stupid
Don't forget to read the STATUS register after every sector or the next sector won't be read.
Ben