From d6318f2cc67f6bf3734d82784b13d73b94d76897 Mon Sep 17 00:00:00 2001 From: Liav A Date: Wed, 15 Apr 2020 15:46:36 +0300 Subject: [PATCH] Kernel: Ensure that we receive IRQs in PIO mode when IOAPIC is enabled The IOAPIC manual states that "Interrupt Mask-R/W. When this bit is 1, the interrupt signal is masked. Edge-sensitive interrupts signaled on a masked interrupt pin are ignored." - Therefore we have to ensure that we disable interrupts globally with cli(), but also to ensure that we invoke enable_irq() before sending the hardware command that generates an IRQ almost immediately. --- Kernel/Devices/PATAChannel.cpp | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/Kernel/Devices/PATAChannel.cpp b/Kernel/Devices/PATAChannel.cpp index a00fec92114..8fbf4f2dad0 100644 --- a/Kernel/Devices/PATAChannel.cpp +++ b/Kernel/Devices/PATAChannel.cpp @@ -183,6 +183,8 @@ void PATAChannel::wait_for_irq() void PATAChannel::handle_irq(const RegisterState&) { + // FIXME: We might get random interrupts due to malfunctioning hardware, so we should check that we actually requested something to happen. + u8 status = m_io_base.offset(ATA_REG_STATUS).in(); if (status & ATA_SR_ERR) { print_ide_status(status); @@ -443,6 +445,7 @@ bool PATAChannel::ata_read_sectors(u32 lba, u16 count, u8* outbuf, bool slave_re break; } + prepare_for_irq(); m_io_base.offset(ATA_REG_COMMAND).out(ATA_CMD_READ_PIO); for (int i = 0; i < count; i++) { @@ -458,10 +461,15 @@ bool PATAChannel::ata_read_sectors(u32 lba, u16 count, u8* outbuf, bool slave_re #ifdef PATA_DEBUG dbg() << "PATAChannel: Retrieving 512 bytes (part " << i << ") (status=" << String::format("%b", status) << "), outbuf=(" << buffer << ")..."; #endif + prepare_for_irq(); + for (int i = 0; i < 256; i++) { buffer[i] = IO::in16(m_io_base.offset(ATA_REG_DATA).get()); } } + + sti(); + disable_irq(); return true; } @@ -507,12 +515,11 @@ bool PATAChannel::ata_write_sectors(u32 start_sector, u16 count, const u8* inbuf #ifdef PATA_DEBUG dbg() << "PATAChannel: Writing 512 bytes (part " << i << ") (status=" << String::format("%b", status) << "), inbuf=(" << (inbuf + (512 * i)) << ")..."; #endif - + prepare_for_irq(); auto* buffer = (u16*)(const_cast(inbuf) + i * 512); for (int i = 0; i < 256; i++) { IO::out16(m_io_base.offset(ATA_REG_DATA).get(), buffer[i]); } - prepare_for_irq(); wait_for_irq(); status = m_io_base.offset(ATA_REG_STATUS).in(); ASSERT(!(status & ATA_SR_BSY));