diff options
author | Conrad Pankoff <deoxxa@fknsrs.biz> | 2019-08-11 14:55:53 +1000 |
---|---|---|
committer | Andreas Kling <awesomekling@gmail.com> | 2019-08-11 08:25:11 +0200 |
commit | f6dd76b9159245943ccca8a35305140ecd7f63d1 (patch) | |
tree | 2c7b85b9a5951f1023cf376213332232003b1c31 | |
parent | d1a7316799d9f49ed42ccc57514c06e464f2ceeb (diff) | |
download | serenity-f6dd76b9159245943ccca8a35305140ecd7f63d1.zip |
Kernel: Fix PATA reads without DMA
Apparently we need to poll the drive for its status after each sector we
read if we're not doing DMA. Previously we only did it at the start,
which resulted in every sector after the first in a batch having 12 bytes
of garbage on the end. This manifested as silent read corruption.
-rw-r--r-- | Kernel/Devices/PATAChannel.cpp | 16 |
1 files changed, 12 insertions, 4 deletions
diff --git a/Kernel/Devices/PATAChannel.cpp b/Kernel/Devices/PATAChannel.cpp index ece7e0619a..db3d025c53 100644 --- a/Kernel/Devices/PATAChannel.cpp +++ b/Kernel/Devices/PATAChannel.cpp @@ -443,13 +443,21 @@ bool PATAChannel::ata_read_sectors(u32 start_sector, u16 count, u8* outbuf, bool if (m_device_error) return false; - u8 status = IO::in8(m_io_base + ATA_REG_STATUS); - ASSERT(status & ATA_SR_DRQ); + for (int i = 0; i < count; i++) { + wait_400ns(m_io_base); + + while (IO::in8(m_io_base + ATA_REG_STATUS) & ATA_SR_BSY) + ; + + u8 status = IO::in8(m_io_base + ATA_REG_STATUS); + ASSERT(status & ATA_SR_DRQ); #ifdef PATA_DEBUG - kprintf("Retrieving %u bytes (status=%b), outbuf=%p...\n", count * 512, status, outbuf); + kprintf("PATAChannel: Retrieving 512 bytes (part %d) (status=%b), outbuf=%p...\n", i, status, outbuf + (512 * i)); #endif - IO::repeated_in16(m_io_base + ATA_REG_DATA, outbuf, count * 256); + IO::repeated_in16(m_io_base + ATA_REG_DATA, outbuf + (512 * i), 256); + } + return true; } |