From 473a7b6832b9921b3353a6068773139bf6f13671 Mon Sep 17 00:00:00 2001 From: Jeremy Soller <jackpot51@gmail.com> Date: Sat, 11 Feb 2017 21:09:16 -0700 Subject: [PATCH] USe auto-eoi mode, mask off interrupts that happen and allow userspace to clear the mask --- arch/x86_64/src/device/pic.rs | 20 ++++++- arch/x86_64/src/interrupt/irq.rs | 89 +++++++++++++------------------- 2 files changed, 55 insertions(+), 54 deletions(-) diff --git a/arch/x86_64/src/device/pic.rs b/arch/x86_64/src/device/pic.rs index f5b63698..d2ae4b03 100644 --- a/arch/x86_64/src/device/pic.rs +++ b/arch/x86_64/src/device/pic.rs @@ -17,8 +17,8 @@ pub unsafe fn init() { SLAVE.data.write(2); // Set up interrupt mode (1 is manual, 2 is auto EOI) - MASTER.data.write(1); - SLAVE.data.write(1); + MASTER.data.write(2); + SLAVE.data.write(2); // Unmask interrupts MASTER.data.write(0); @@ -45,4 +45,20 @@ impl Pic { pub fn ack(&mut self) { self.cmd.write(0x20); } + + pub fn mask_set(&mut self, irq: u8) { + assert!(irq < 8); + + let mut mask = self.data.read(); + mask |= 1 << irq; + self.data.write(mask); + } + + pub fn mask_clear(&mut self, irq: u8) { + assert!(irq < 8); + + let mut mask = self.data.read(); + mask &= !(1 << irq); + self.data.write(mask); + } } diff --git a/arch/x86_64/src/interrupt/irq.rs b/arch/x86_64/src/interrupt/irq.rs index c6a87334..8e2aa033 100644 --- a/arch/x86_64/src/interrupt/irq.rs +++ b/arch/x86_64/src/interrupt/irq.rs @@ -1,115 +1,100 @@ -use x86::io; - +use device::pic; use device::serial::{COM1, COM2}; use time; -extern { - fn irq_trigger(irq: u8); -} +unsafe fn trigger(irq: u8) { + extern { + fn irq_trigger(irq: u8); + } -#[inline(always)] -unsafe fn master_ack() { - io::outb(0x20, 0x20); -} + if irq < 16 { + if irq >= 8 { + pic::SLAVE.mask_set(irq - 8); + } else { + pic::MASTER.mask_set(irq); + } + } -#[inline(always)] -unsafe fn slave_ack() { - io::outb(0xA0, 0x20); - master_ack(); + irq_trigger(irq); } pub unsafe fn acknowledge(irq: usize) { - if irq >= 8 { - slave_ack(); - } else { - master_ack(); + if irq < 16 { + if irq >= 8 { + pic::SLAVE.mask_clear(irq as u8 - 8); + } else { + pic::MASTER.mask_clear(irq as u8); + } } } interrupt!(pit, { // Saves CPU time by not sending IRQ event irq_trigger(0); - { - const PIT_RATE: u64 = 2250286; - - let mut offset = time::OFFSET.lock(); - let sum = offset.1 + PIT_RATE; - offset.1 = sum % 1000000000; - offset.0 += sum / 1000000000; - } + const PIT_RATE: u64 = 2250286; - master_ack(); + let mut offset = time::OFFSET.lock(); + let sum = offset.1 + PIT_RATE; + offset.1 = sum % 1000000000; + offset.0 += sum / 1000000000; }); interrupt!(keyboard, { - irq_trigger(1); + trigger(1); }); interrupt!(cascade, { - irq_trigger(2); - master_ack(); + // No need to do any operations on cascade }); interrupt!(com2, { - irq_trigger(3); COM2.lock().on_receive(); - master_ack(); }); interrupt!(com1, { - irq_trigger(4); COM1.lock().on_receive(); - master_ack(); }); interrupt!(lpt2, { - irq_trigger(5); - master_ack(); + trigger(5); }); interrupt!(floppy, { - irq_trigger(6); - master_ack(); + trigger(6); }); interrupt!(lpt1, { - irq_trigger(7); - master_ack(); + trigger(7); }); interrupt!(rtc, { - irq_trigger(8); - slave_ack(); + trigger(8); }); interrupt!(pci1, { - irq_trigger(9); - slave_ack(); + trigger(9); }); interrupt!(pci2, { - irq_trigger(10); + trigger(10); }); interrupt!(pci3, { - irq_trigger(11); + trigger(11); }); interrupt!(mouse, { - irq_trigger(12); + trigger(12); }); interrupt!(fpu, { - irq_trigger(13); - slave_ack(); + trigger(13); }); interrupt!(ata1, { - irq_trigger(14); - slave_ack(); + trigger(14); }); interrupt!(ata2, { - irq_trigger(15); - slave_ack(); + trigger(15); }); -- GitLab