diff --git a/kernel/src/arch/x86_64/disk/ATA.cpp b/kernel/src/arch/x86_64/disk/ATA.cpp index 680bf4a8..b4b1aca8 100644 --- a/kernel/src/arch/x86_64/disk/ATA.cpp +++ b/kernel/src/arch/x86_64/disk/ATA.cpp @@ -5,6 +5,11 @@ SharedPtr g_controller; +static void irq_handler(Registers* regs, void* ctx) +{ + ((ATA::Channel*)ctx)->irq_handler(regs); +} + namespace ATA { Result Controller::scan() @@ -85,6 +90,22 @@ namespace ATA m_current_drive = drive; } + void Channel::irq_handler(Registers*) + { + // FIXME: Read the Busmaster register to make sure the IRQ is for this channel. + + // FIXME: Also read it in case there was a DMA read error. + + m_thread->wake_up(); + } + + void Channel::wait_for_irq() + { + m_thread = Scheduler::current(); + + kernel_wait_for_event(); + } + bool Channel::initialize() { int offset = m_channel_index ? 2 : 0; @@ -113,6 +134,14 @@ namespace ATA else m_interrupt_line = m_channel_index ? 15 : 14; + bool ok = CPU::register_interrupt(m_interrupt_line, ::irq_handler, this); + if (!ok) + { + kerrorln("ata: Failed to register IRQ handler for ATA channel %d (IRQ %d)", m_channel_index, + m_interrupt_line); + return false; + } + for (u8 drive = 0; drive < 2; drive++) { ScopedKMutexLock<100> lock(m_lock); diff --git a/kernel/src/arch/x86_64/disk/ATA.h b/kernel/src/arch/x86_64/disk/ATA.h index 39ab2d21..18766f91 100644 --- a/kernel/src/arch/x86_64/disk/ATA.h +++ b/kernel/src/arch/x86_64/disk/ATA.h @@ -52,6 +52,9 @@ namespace ATA void delay_400ns(); + void wait_for_irq(); + void irq_handler(Registers*); + void select(u8 drive); bool initialize(); @@ -65,6 +68,8 @@ namespace ATA KMutex<100> m_lock {}; + Thread* m_thread; + u16 m_io_base; u16 m_control_base;