IDE DMA
Posted: Tue May 26, 2015 3:37 am
Hi,
Maybe "ATA DMA" would be a better subject, I don't know.
I was using ATA PIO for a long time but it is really slow (e.g. copying wav-files), so I decided to try to implement DMA.
I have read :
http://wiki.osdev.org/ATA/ATAPI_using_DMA
http://forum.osdev.org/viewtopic.php?f=1&t=24394
and several documents, including the Intel IDE Controller specification which says that bit3 should be set to 1 in the BusMasterCmd-register if we want to WRITE, but it seems that the osdev-wiki-page is correct because if bit3 is set then it means READ.
Reading sectors from winchester with DMA works well for me. The interrupt always gets fired(once after 64Kb buffer, I have one entry in the PRDT) in case of READ (no matter if I read 1, 128 or 69631 consecutive sectors). I tested it on real HW (Dell D820).
The problem is that if I WRITE, the interrupt doesn't get fired if sectorcount is smaller than 128 (as if bit7 of low-byte of sectorcount would matter). So, if I try to write 140 sectors with DMA, then I should get two interrupts, because I have just one entry in the PRDT(i.e. 64Kb dma-buffer) and I call WRITE in a loop. Unfortunately I get only the first interrupt (with sectorcnt=128 (128*512 ==> 64Kb)) and the second one doesn't come (with sectorcnt=12).
This occurs on D820.
With Bochs it works, because the two interrupts get fired, in case of 140 sectors.
Note that the contents of the buffer gets written to disk correctly on real HW, even if the interrupt doesn't get fired.
In other words, If I WRITE just one sector, then there is no interrupt, there will be a timeout, but the data is written to disk.
I could check if the sectorcnt is smaller than 128, and have a 1ms delay instead of a "timeout waiting for the interrupt".
Knowing that Bochs always sends the interrupt, there must be a better solution.
Maybe "ATA DMA" would be a better subject, I don't know.
I was using ATA PIO for a long time but it is really slow (e.g. copying wav-files), so I decided to try to implement DMA.
I have read :
http://wiki.osdev.org/ATA/ATAPI_using_DMA
http://forum.osdev.org/viewtopic.php?f=1&t=24394
and several documents, including the Intel IDE Controller specification which says that bit3 should be set to 1 in the BusMasterCmd-register if we want to WRITE, but it seems that the osdev-wiki-page is correct because if bit3 is set then it means READ.
Reading sectors from winchester with DMA works well for me. The interrupt always gets fired(once after 64Kb buffer, I have one entry in the PRDT) in case of READ (no matter if I read 1, 128 or 69631 consecutive sectors). I tested it on real HW (Dell D820).
The problem is that if I WRITE, the interrupt doesn't get fired if sectorcount is smaller than 128 (as if bit7 of low-byte of sectorcount would matter). So, if I try to write 140 sectors with DMA, then I should get two interrupts, because I have just one entry in the PRDT(i.e. 64Kb dma-buffer) and I call WRITE in a loop. Unfortunately I get only the first interrupt (with sectorcnt=128 (128*512 ==> 64Kb)) and the second one doesn't come (with sectorcnt=12).
This occurs on D820.
With Bochs it works, because the two interrupts get fired, in case of 140 sectors.
Note that the contents of the buffer gets written to disk correctly on real HW, even if the interrupt doesn't get fired.
In other words, If I WRITE just one sector, then there is no interrupt, there will be a timeout, but the data is written to disk.
I could check if the sectorcnt is smaller than 128, and have a 1ms delay instead of a "timeout waiting for the interrupt".
Knowing that Bochs always sends the interrupt, there must be a better solution.