diff --git a/arch/x86_64/src/device/pic.rs b/arch/x86_64/src/device/pic.rs
index f5b636987e90f6ddd03727060c92eb65becf9cf8..d2ae4b032940eaef327674cb036161c426abaed4 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 c6a87334cff2dc969e533ec204513b4e2437fd20..8e2aa0337baa14271929dc7daab4d26ab1668e37 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);
 });