Page 1 of 1

ATA PIO read only works one half the times

Posted: Thu Jun 28, 2018 6:00 am
by DeezRamChips
Hi :D

I'm making a ext2fs driver and while I was debugging it, I noticed the extended superblock was not loading.
When I looked a little further into it, I noticed my drive_read function was returning only zeros the second time it was run.
But if I tried to run it a third time, then it would work... I tried a few thing and it appears like it works in the following pattern:
1 - Works
2 - Doesn't work
3 - Works
4 - Doesn't work
(and so on)

Code: Select all

int ATAPIO_Class::readBlock(int drive, int numblock, int count, char *buf) {
    uint16_t tmpword;
    int idx;

    if (count == 0) {
        kernel_panic(0x1234, "Null sector count read");
    }

	selectDrive(drive, numblock, count);
	outb(0x1F7, 0x20);

    // Wait for ready signal
    uint8_t status = (inb(0x1F7) & 0x08);
	while (!status) {
        status = (inb(0x1F7) & 0x08);
    }


	for (idx = 0; idx < 256 * count; idx++) {
		tmpword = inw(0x1F0);
		buf[idx * 2] = (uint8_t)tmpword;
		buf[idx * 2 + 1] = (uint8_t)(tmpword >> 8);
	}

	return count;
}
I've even tried adding a 1ms delay just to be sure, but it doesn't change anything
also, reading 5 times like it says on the wiki doesn't change anything either :/
I talked to someone who had also tried making a ATAPIO driver and he said he also had issues
so he switched to AHCI, but I don't want to get into AHCI just yet, seems too complicated just
to test my ext2fs driver...

I'm testing my code on QEMU btw.

Hope someone can figure out what's going on :P

Re: ATA PIO read only works one half the times

Posted: Thu Jun 28, 2018 7:38 am
by iansjack
I may be wrong, but I think you should be checking the status register to see that the controller is not busy before starting the read.

Re: ATA PIO read only works one half the times

Posted: Thu Jun 28, 2018 7:58 am
by DeezRamChips
Well, It's already what i'm doing :?
and if I check it before sending the read command, it hangs :/

Re: ATA PIO read only works one half the times

Posted: Thu Jun 28, 2018 8:06 am
by iansjack
I don't think you are checking it. It's bit 7 in the status register.

Re: ATA PIO read only works one half the times

Posted: Thu Jun 28, 2018 8:21 am
by DeezRamChips
Oh yeah sorry I thought you meant the DRQ bit ^^

changed it and it still gets zeros on second read :/

Code: Select all

Terminal.print("Waiting for drive ready... ");
inb(0x1F7);
inb(0x1F7);
inb(0x1F7);
inb(0x1F7);
uint8_t status = inb(0x1F7);
while ((status & 0x80) && !(status & 0x08)) {
	status = inb(0x1F7);
}
Terminal.println("READY");

selectDrive(drive, numblock, count);

outb(0x1F7, 0x20);

// Wait for ready signal
Terminal.print("Waiting for data... ");
inb(0x1F7);
inb(0x1F7);
inb(0x1F7);
inb(0x1F7);
status = inb(0x1F7);
while ((status & 0x80) && !(status & 0x08)) {
	status = inb(0x1F7);
}
Terminal.println("READING");

for (idx = 0; idx < 256 * count; idx++) {
	tmpword = inw(0x1F0);
	buf[idx * 2] = (uint8_t)tmpword;
	buf[idx * 2 + 1] = (uint8_t)(tmpword >> 8);
}

Re: ATA PIO read only works one half the times

Posted: Fri Jun 29, 2018 7:23 pm
by BrightLight
You can't read the sectors all at once from the data port. You read 256 words (512 bytes, one sector) and then stop there, wait for the BSY bit to clear and the DRQ bit to set again, and then you continue. The actual drive fetches the sectors one by one, and there may be small delays between them, which is why you need to poll the status register in PIO mode.
DeezRamChips wrote:

Code: Select all

Terminal.print("Waiting for drive ready... ");
inb(0x1F7);
inb(0x1F7);
inb(0x1F7);
inb(0x1F7);
uint8_t status = inb(0x1F7);
while ((status & 0x80) && !(status & 0x08)) {
   status = inb(0x1F7);
}
Why is this loop here? Why are you waiting for the DRQ bit before even doing a drive select? It's possible that this code can loop forever, and as a matter of fact, I'm surprised it didn't. Do a drive select, send the LBA and sector count, send the read command, wait for the BSY bit to clear, and then for each sector, wait for the BSY bit and the DRQ bit.

Also if you ever intend on running on real HW, don't assume port numbers.

Re: ATA PIO read only works one half the times

Posted: Sat Jun 30, 2018 12:14 pm
by DeezRamChips
Thanks :D

I can confirm this fixed the issue. I must not have understood the wiki page for that ^^

I moved on to making an AHCI driver though, seems more professional then PIO.

Thanks again :)