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;
}
Do you something wrong with my function ? Is this a bad idead to read multiple sectors at once ?
Thanks