[SOLVED] ATA: DRQ not cleared after a multiple sectors read

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
User avatar
wichtounet
Member
Member
Posts: 90
Joined: Fri Nov 01, 2013 4:05 pm
Location: Fribourg, Switzerland
Contact:

[SOLVED] ATA: DRQ not cleared after a multiple sectors read

Post by wichtounet »

Hi,

I've a problem making my ATA driver works in Qemu. The problem comes arises when I read multiple sectors at once, 8 in my case. After the 8 * 256 words have been read, the DRQ flag is still set. Normally that should indicate that there are still data, but I don't see how this is possibles since I have read the 8 blocks.

The reads of only 1 blocks succeeds without any problem. Moreover, if, instead of a read of 8 blocks, I read 8 times 1 block, it works perfectly.

In Bochs, everything is working perfectly.

Here is my function to read sectors:

Code: Select all

bool read_write_sectors(ata::drive_descriptor& drive, uint64_t start, uint8_t count, void* data){
    //Select the device
    if(!select_device(drive)){
        return false;
    }

    auto controller = drive.controller;

    uint8_t sc = start & 0xFF;
    uint8_t cl = (start >> 8) & 0xFF;
    uint8_t ch = (start >> 16) & 0xFF;
    uint8_t hd = (start >> 24) & 0x0F;

    //Process the command
    out_byte(controller + ATA_NSECTOR, count);
    out_byte(controller + ATA_SECTOR, sc);
    out_byte(controller + ATA_LCYL, cl);
    out_byte(controller + ATA_HCYL, ch);
    out_byte(controller + ATA_DRV_HEAD, (1 << 6) | (drive.slave << 4) | hd);
    out_byte(controller + ATA_COMMAND, ATA_READ_BLOCK);

    //Wait at least 400ns before reading status register
    sleep_ms(1);

    //Wait at most 30 seconds for BSY flag to be cleared
    if(!wait_for_controller(controller, ATA_STATUS_BSY, 0, 30000)){
        return false;
    }

    //Verify if there are errors
    if(in_byte(controller + ATA_STATUS) & ATA_STATUS_ERR){
        return false;
    }

    //Wait the IRQ to happen
    if(controller == ATA_PRIMARY){
        ata_wait_irq_primary();
    } else {
        ata_wait_irq_secondary();
    }

    //The device can report an error after the IRQ
    if(in_byte(controller + ATA_STATUS) & ATA_STATUS_ERR){
        return false;
    }

    uint16_t* buffer = reinterpret_cast<uint16_t*>(data);

        //Read the disk sectors
        for(uint8_t sector = 0; sector < count; ++sector){
            for(int i = 0; i < 256; ++i){
                *buffer++ = in_word(controller + ATA_DATA);
            }
        }

    return true;
}
(The complete ATA code is available here https://github.com/wichtounet/thor-os/b ... rc/ata.cpp)

Do you something wrong with my function ? Is this a bad idead to read multiple sectors at once ?

Thanks
Last edited by wichtounet on Thu Jan 02, 2014 6:33 am, edited 1 time in total.
Thor Operating System: C++ 64 bits OS: https://github.com/wichtounet/thor-os
Good osdeving!
User avatar
iansjack
Member
Member
Posts: 4711
Joined: Sat Mar 31, 2012 3:07 am
Location: Chichester, UK

Re: ATA: DRQ not cleared after a multiple sectors read in Qe

Post by iansjack »

I believe that you are supposed to poll, or wait for an interrupt, after each sector is read. That makes sense as it may take an appreciable time between sectors (for example if the heads have to move to a new cylinder).
User avatar
wichtounet
Member
Member
Posts: 90
Joined: Fri Nov 01, 2013 4:05 pm
Location: Fribourg, Switzerland
Contact:

Re: ATA: DRQ not cleared after a multiple sectors read in Qe

Post by wichtounet »

iansjack wrote:I believe that you are supposed to poll, or wait for an interrupt, after each sector is read. That makes sense as it may take an appreciable time between sectors (for example if the heads have to move to a new cylinder).
Oh gosh. I was sure than only one IRQ was fired for the whole block, but it is only the case with READ MULTIPLE and WRITE MULTIPLE commands.

I will review my driver to handle this.

Thanks ;)
Thor Operating System: C++ 64 bits OS: https://github.com/wichtounet/thor-os
Good osdeving!
Post Reply