Page 1 of 2

How to use multiple disks?

Posted: Fri Dec 25, 2020 12:40 pm
by Bonfra
When the bootloader is loaded, the bios sets DL as the drive number. For example, if booting happens from an HDD the value of DL will be 0x80 which is universal for all HDD as far as I've understood. In the kernel, I'm implementing an interface to access files on the disk and I thought about reading other disks other than the boot one. I found this source in the wiki (I use the LBA one) which allows me to read sectors from the bootdrive as HDD. It works and I'm developing the filesystem driver and the VFS. But how can I access other disks? In my case, I burn the image in a USB and boot it from a real PC with its own hard drive. How can I access it?

Re: How to use multiple disks?

Posted: Fri Dec 25, 2020 2:00 pm
by pvc
Value 0x80 represents first drive, value 0x81 represents second, 0x82 third, etc.
These values are, of course, only valid for int 0x13 BIOS calls.
And it's the BIOS that decides which physical drive has which id. I am not sure if drive ids can be non-consecutive numbers or not.

Re: How to use multiple disks?

Posted: Fri Dec 25, 2020 2:17 pm
by Bonfra
pvc wrote:it's the BIOS that decides which physical drive has which id
Is there a way to detect all connected drives?

Re: How to use multiple disks?

Posted: Fri Dec 25, 2020 2:22 pm
by iansjack
As explained here: https://wiki.osdev.org/ATA_PIO_Mode#Det ... ialization , you can use the ATA IDENTIFY command on each port to determine whether a drive is attached.

Re: How to use multiple disks?

Posted: Fri Dec 25, 2020 2:22 pm
by pvc
I am not exactly sure, but I think, your best bet would be probing consecutive ids with IDENTIFY command and see if it succeeds or fails.

Re: How to use multiple disks?

Posted: Fri Dec 25, 2020 2:34 pm
by Bonfra
pvc wrote:I am not exactly sure, but I think, your best bet would be probing consecutive ids with IDENTIFY command and see if it succeeds or fails.
This is more of a bootloader solution. I'd like to achieve this in the kernel, I'm reading @iansjack solution of the ATA identify command. It looks a bit scary but seems right. I'll let you know if I understand something

Re: How to use multiple disks?

Posted: Fri Dec 25, 2020 3:50 pm
by nexos
To access a USB stick, you must write a USB host controller driver. Then you must write a driver for mass storage devices. USB is very difficult, however...

Re: How to use multiple disks?

Posted: Fri Dec 25, 2020 4:08 pm
by Bonfra
Following the IDENTIFY command explained here I wrote this code:

Code: Select all

int ata_identify(uint16_t drive)
{
    // Select master drive
    outportb(ATA_DRIVE_SELECT, ATA_MASTER);

    // Clear parameters
    outportb(ATA_SECTORS_COUNT, 0);
    outportb(ATA_LBA_LO, 0);
    outportb(ATA_LBA_MID, 0);
    outportb(ATA_LBA_HI, 0);

    // Identify command
    outportb(ATA_COMMAND_IO, ATA_IDENTIFY_COMMAND);
    uint8_t status = inportb(ATA_STATUS_PORT);

    if(status == ATA_NO_DEVICE)
        return ATA_NO_DEVICE;
}
The explanation continued but I stopped writing when I noticed that I didn't use the drive parameter. Is the wiki not describeing how to detect a specific drive or is me not reading correctly?

Re: How to use multiple disks?

Posted: Fri Dec 25, 2020 4:10 pm
by Bonfra
nexos wrote:To access a USB stick, you must write a USB host controller driver. Then you must write a driver for mass storage devices. USB is very difficult, however...
The USB is booted with some sort of HDD emulation or something, anyway using the example from the wiki I managed to read the sectors from the USB stick.

Re: How to use multiple disks?

Posted: Sun Dec 27, 2020 7:25 am
by Bonfra
I readed some bits from Ben Lunt book and then write(copyed) this loop to detect all the connected devices:

Code: Select all

    size_t current_device = 0;
    for(int bus = 0; bus < PCI_MAX_BUS; bus++)
        for(int dev = 0; dev < PCI_MAX_DEVICE; dev++)
            for(int func = 0; func < PCI_MAX_FUNCTION; func++)
                if(pci_read_word(bus, dev, func, 0) != UINT16_MAX)
                {
                    pci_device_t data;
                    uint32_t* dataptr = (uint32_t*)&data;

                    // read in the 256 bytes (64 dwords)
                    for(int i = 0; i < 64; i++)
                        dataptr[i] = pci_read_dword(bus, dev, func, i << 2);

                    devices[current_device++] = data;
                }

Then I filter the devices taking only the ones with class = 1, so the ATA devices.
It's strange how when I boot the os on real hardware there seems to be any ATA device connected. I tried on multiple machines but all returns me zero ATA devices. Instead in QEMU, I get back at least one device. How is that possible? There must be an ATA controller.

Re: How to use multiple disks?

Posted: Sun Dec 27, 2020 8:05 am
by pvc
Do your test machines have real parallel IDE interface? Or are they SATA only? For SATA, they may use either IDE controller or AHCI controller. For IDE controllers you should look for PCI devices with class == 1 and subclass == 1. For AHCI controllers, it's class == 1 and subclass == 6.
Assuming your PCI config space read routine is ok.

Re: How to use multiple disks?

Posted: Sun Dec 27, 2020 11:27 am
by Bonfra
pvc wrote:Do your test machines have real parallel IDE interface? Or are they SATA only? For SATA, they may use either IDE controller or AHCI controller. For IDE controllers you should look for PCI devices with class == 1 and subclass == 1. For AHCI controllers, it's class == 1 and subclass == 6.
I test for any device with class == 1, I've not tested any subclass for now.

Edit:
I noticed that I accidentally deleted a digit from the device count, I wrote 3 instead of 32, so it couldn't work. Now it works and found the devices. Let's see how It goes from now on.

Now I should use the detected device in some way that I yet don't know but I'm sure it's explained in this awesome book. I'll link it here for future readers:
http://www.fysnet.net/media_storage_devices.htm

Re: How to use multiple disks?

Posted: Sun Dec 27, 2020 5:43 pm
by Bonfra
Can someone link me some actual working code that manages the pci and the ata so that I can better learn? I can find some articles here and there but they are all very confusing. I searched on the wiki and on GitHub I can find only some bits not related to each other. Nothing complete or well explained.
If someone can link some code it could be awesome.

Re: How to use multiple disks?

Posted: Sun Jan 29, 2023 7:03 pm
by jaihsonk
After reading this, am I right to conclude that one must go from port to port indiscriminately sending IDENTIFY commands? And will whatever device connected (if there is one) will send a 16 bit number to identify what kind of device is attached?

Re: How to use multiple disks?

Posted: Sun Jan 29, 2023 7:18 pm
by Octocontrabass
jaihsonk wrote:After reading this, am I right to conclude that one must go from port to port indiscriminately sending IDENTIFY commands?
You can discriminate a little bit. There are certain combinations of status and error register values that will tell you for certain that no drive is connected.
jaihsonk wrote:And will whatever device connected (if there is one) will send a 16 bit number to identify what kind of device is attached?
If a hard drive is connected, it will reply with 512 bytes of data the same way it would if you used the READ command to read one sector. Those 512 bytes of data will tell you just about everything you need to know about the drive.

If something else is connected, it will abort the command and fill the command block registers with a signature to tell you that you should use IDENTIFY PACKET DEVICE instead.

If nothing is connected, nothing will happen. (On really old PCs, you might see bus capacitance when reading the nonexistent drive's registers.)