How to use multiple disks?
How to use multiple disks?
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?
Regards, Bonfra.
Re: How to use multiple disks?
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.
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?
Is there a way to detect all connected drives?pvc wrote:it's the BIOS that decides which physical drive has which id
Regards, Bonfra.
Re: How to use multiple disks?
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?
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?
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 somethingpvc 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.
Regards, Bonfra.
Re: How to use multiple disks?
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?
Following the IDENTIFY command explained here I wrote this code:
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?
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;
}
Regards, Bonfra.
Re: How to use multiple disks?
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.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...
Regards, Bonfra.
Re: How to use multiple disks?
I readed some bits from Ben Lunt book and then write(copyed) this loop to detect all the connected devices:
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.
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.
Regards, Bonfra.
Re: How to use multiple disks?
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.
Assuming your PCI config space read routine is ok.
Re: How to use multiple disks?
I test for any device with class == 1, I've not tested any subclass for now.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.
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
Regards, Bonfra.
Re: How to use multiple disks?
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.
If someone can link some code it could be awesome.
Regards, Bonfra.
-
- Posts: 24
- Joined: Thu Jul 14, 2022 10:46 am
- Libera.chat IRC: json
- Location: Canada
- Contact:
Re: How to use multiple disks?
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?
-
- Member
- Posts: 5562
- Joined: Mon Mar 25, 2013 7:01 pm
Re: How to use multiple disks?
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:After reading this, am I right to conclude that one must go from port to port indiscriminately sending IDENTIFY commands?
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.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 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.)