ATA can't find any disk

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.
Post Reply
tommasop
Posts: 8
Joined: Fri Oct 13, 2017 10:03 am

ATA can't find any disk

Post by tommasop »

Hi, i was following the IDE controller tutorial and i encountered a problem. When i read the value of ATA_REG_STATUS i get 0xff and from what i understand that means that there is no hdd in that bus.
I tried with both QEMU and bochs but no hdd is never found. Can someone tell me which option do i have to use to add an hdd to the IDE bus?

To be sure i also add all the devices and the addresses of the channels:

Code: Select all

Device: 0
Vendor ID: 8086
Device ID: 1237
Class ID: 6
SubClass ID: 0
Prog if: 0
Device: 1
Vendor ID: 8086
Device ID: 7000
Class ID: 6
SubClass ID: 1
Prog if: 0
Device: 2
Vendor ID: 8086
Device ID: 7010
Class ID: 1
SubClass ID: 1
Prog if: 80
Device: 3
Vendor ID: 8086
Device ID: 7020
Class ID: c
SubClass ID: 3
Prog if: 0
Device: 4
Vendor ID: 8086
Device ID: 7113
Class ID: 6
SubClass ID: 80
Prog if: 0
PRIMARY_ATA: 
    BASE: f0
    CONTROL: f6
SECONDARY_ATA: 
    BASE: 70
    CONTROL: 76

This is how i get the addresses:

Code: Select all

void getChannelData(struct PCIDevice dev){
    channels[ATA_PRIMARY  ].base  = (dev.BAR[0] & 0xFFFFFFFC) + 0x1F0 * !(dev.BAR[0]);
    channels[ATA_PRIMARY  ].control  = (dev.BAR[1] & 0xFFFFFFFC) + 0x3F6 * !(dev.BAR[1]);
    channels[ATA_SECONDARY].base  = (dev.BAR[2] & 0xFFFFFFFC) + 0x170 * !(dev.BAR[2]);
    channels[ATA_SECONDARY].control  = (dev.BAR[3] & 0xFFFFFFFC) + 0x376 * !(dev.BAR[3]);
    channels[ATA_PRIMARY  ].busmaster = (dev.BAR[4] & 0xFFFFFFFC) + 0; // Bus Master IDE
    channels[ATA_SECONDARY].busmaster = (dev.BAR[4] & 0xFFFFFFFC) + 8; // Bus Master IDE
}
and this is how i read:

Code: Select all

uint8_t read(unsigned char channel, unsigned char reg) {
   unsigned char result;
   if (reg > 0x07 && reg < 0x0C)
      write(channel, ATA_REG_CONTROL, 0x80 | channels[channel].nInt);
   if (reg < 0x08)
      result = inb(channels[channel].base + reg - 0x00);
   else if (reg < 0x0C)
      result = inb(channels[channel].base  + reg - 0x06);
   else if (reg < 0x0E)
      result = inb(channels[channel].control  + reg - 0x0A);
   else if (reg < 0x16)
      result = inb(channels[channel].busmaster + reg - 0x0E);
   if (reg > 0x07 && reg < 0x0C)
      write(channel, ATA_REG_CONTROL, channels[channel].nInt);
   return result;
}

Most of this code is from the tutorial on the wiki, if there is something wrong please tell me.
Thanks to everyone and sorry for my english.
User avatar
BenLunt
Member
Member
Posts: 941
Joined: Sat Nov 22, 2014 6:33 pm
Location: USA
Contact:

Re: ATA can't find any disk

Post by BenLunt »

tommasop wrote:Hi, i was following the IDE controller tutorial and i encountered a problem. When i read the value of ATA_REG_STATUS i get 0xff and from what i understand that means that there is no hdd in that bus.
I tried with both QEMU and bochs but no hdd is never found. Can someone tell me which option do i have to use to add an hdd to the IDE bus?
Correct, if you are reading 0xFF from a byte port I/O register, you most likely have nothing attached to that port.

For QEMU, it is as simple as:

Code: Select all

-drive file=hd.img,format=raw,if=ide,media=disk,index=0
tommasop wrote:To be sure i also add all the devices and the addresses of the channels:

Code: Select all

Device: 4
Vendor ID: 8086
Device ID: 7113
Class ID: 6
SubClass ID: 80
Prog if: 0
PRIMARY_ATA: 
    BASE: f0
    CONTROL: f6
SECONDARY_ATA: 
    BASE: 70
    CONTROL: 76
Where did you get this info? Did you print it yourself? You are missing the high order byte of the BASE and CONTROL values.
tommasop wrote:This is how i get the addresses:

Code: Select all

    channels[ATA_PRIMARY  ].base  = (dev.BAR[0] & 0xFFFFFFFC) + 0x1F0 * !(dev.BAR[0]);
That is a strange way of defaulting to 0x1F0. However, it only works if dev.BAR[0] is guaranteed to be zero if defaulting to 0x1F0. The bottom bits of dev.BAR[0] might still be hard-wired to PORT I/O. If so, and most likely they are, you are getting:

Code: Select all

    channels[ATA_PRIMARY  ].base  = (0x00000001 & 0xFFFFFFFC) + 0x1F0 * !(0x00000001);
which now gives you a base address of

Code: Select all

    channels[ATA_PRIMARY  ].base  = 0 + 0x1F0 * 0;
which is a base address of zero. Probably not what you are anticipating.
tommasop wrote:and this is how i read:

Code: Select all

uint8_t read(unsigned char channel, unsigned char reg) {
   unsigned char result;
   if (reg > 0x07 && reg < 0x0C)
      write(channel, ATA_REG_CONTROL, 0x80 | channels[channel].nInt);
   if (reg < 0x08)
      result = inb(channels[channel].base + reg - 0x00);
   else if (reg < 0x0C)
      result = inb(channels[channel].base  + reg - 0x06);
   else if (reg < 0x0E)
      result = inb(channels[channel].control  + reg - 0x0A);
   else if (reg < 0x16)
      result = inb(channels[channel].busmaster + reg - 0x0E);
   if (reg > 0x07 && reg < 0x0C)
      write(channel, ATA_REG_CONTROL, channels[channel].nInt);
   return result;
}
Without more content, all of that just looks real funny to me.
tommasop wrote:Most of this code is from the tutorial on the wiki, if there is something wrong please tell me.
Thanks to everyone and sorry for my english.
What tutorial are you quoting here? Will you please specify?

- Ben
http://www.fysnet.net/osdesign_book_series.htm
User avatar
qookie
Member
Member
Posts: 72
Joined: Sun Apr 30, 2017 12:16 pm
Libera.chat IRC: qookie
Location: Poland

Re: ATA can't find any disk

Post by qookie »

BenLunt: If I'm not mistaken, he's following PCI IDE Controller, which has both the I/O port calculation formulas that look really similar, and a read function that's almost exactly the same, minus the function name
Working on managarm.
User avatar
BenLunt
Member
Member
Posts: 941
Joined: Sat Nov 22, 2014 6:33 pm
Location: USA
Contact:

Re: ATA can't find any disk

Post by BenLunt »

qookie wrote:BenLunt: If I'm not mistaken, he's following PCI IDE Controller, which has both the I/O port calculation formulas that look really similar, and a read function that's almost exactly the same, minus the function name
Thank you. There are numerous errors on that page and this page shows some of them.

tommasop, I think you need to not rely upon that page's code. The documentation, though I did not read through it thoroughly, seems to be good, but I would suggest you try your own code. In fact, I think I am going to back up to my previous question and ask why you don't simply use the BIOS to read your kernel from the disk? The kernel, then itself, can have an ATA driver that can then read from the disk via this Port I/O technique, which we are willing to help you with.

- Ben
http://www.fysnet.net/osdesign_book_series.htm
tommasop
Posts: 8
Joined: Fri Oct 13, 2017 10:03 am

Re: ATA can't find any disk

Post by tommasop »

Thanks to everyone, the base and control i wrote are the ones that gets calculated with the function getChannelData, i have to rewrite that function. Anyway i'm trying to write my own driver without the bios for learning purpose. I pratically copy-pasted the code from the IDE Controller tutorial because my own code was giving the same result. Now i'm going to try with QEMU and see if it can detect the drive. As for the missing char in the address is an error i've made with the print function :p.
tommasop
Posts: 8
Joined: Fri Oct 13, 2017 10:03 am

Re: ATA can't find any disk

Post by tommasop »

Thanks BenLunt! I tried with the QEMU option you gave and it didn't work but then i checked why the addresses were missing a char and i noticed i declared base and control with unsigned char insted of unsigned short! Now i'm going to rewrite evrything using the hints you gave me, thanks!
Post Reply