Skip to content

Commit

Permalink
Kernel: Fix PATA reads without DMA
Browse files Browse the repository at this point in the history
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 f6dd76b
Showing 1 changed file with 12 additions and 4 deletions.
16 changes: 12 additions & 4 deletions Kernel/Devices/PATAChannel.cpp
Expand Up @@ -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;
}

Expand Down

0 comments on commit f6dd76b

Please sign in to comment.