Skip to content
Permalink
Browse files

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.
  • Loading branch information...
deoxxa authored and awesomekling committed Aug 11, 2019
1 parent d1a7316 commit f6dd76b9159245943ccca8a35305140ecd7f63d1
Showing with 12 additions and 4 deletions.
  1. +12 −4 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;
}

0 comments on commit f6dd76b

Please sign in to comment.
You can’t perform that action at this time.