From f6dd76b9159245943ccca8a35305140ecd7f63d1 Mon Sep 17 00:00:00 2001 From: Conrad Pankoff Date: Sun, 11 Aug 2019 14:55:53 +1000 Subject: [PATCH] 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. --- Kernel/Devices/PATAChannel.cpp | 16 ++++++++++++---- 1 file 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; }