hardware 0.0.9

A no_std bare-metal hardware abstraction layer — all port I/O, memory and swap allocations are guarded at runtime. Do not consider this dependency stable before x.1.x
Documentation
use crate::arch::x86_64::io::{inb, outb};
use crate::interrupt::IrqController;
use core::sync::atomic::{AtomicU16, Ordering};

pub struct Pic8259;

impl Default for Pic8259 {
    fn default() -> Self {
        Self::new()
    }
}

impl Pic8259 {
    pub const fn new() -> Self {
        Pic8259
    }

    pub fn read_mask(&self) -> u16 {
        let a = unsafe { inb(0x21) } as u16;
        let b = unsafe { inb(0xA1) } as u16;
        (b << 8) | a
    }

    fn write_mask(&self, mask: u16) {
        unsafe {
            outb(0x21, (mask & 0xff) as u8);
        }
        unsafe {
            outb(0xA1, ((mask >> 8) & 0xff) as u8);
        }
    }
}

static PIC_MASK: AtomicU16 = AtomicU16::new(0xffff);

impl IrqController for Pic8259 {
    fn init(&self) -> bool {
        unsafe {
            outb(0x20, 0x11);
            outb(0xA0, 0x11);
            outb(0x21, 0x20);
            outb(0xA1, 0x28);
            outb(0x21, 0x04);
            outb(0xA1, 0x02);
            outb(0x21, 0x01);
            outb(0xA1, 0x01);
            outb(0x21, 0xff);
            outb(0xA1, 0xff);
        }
        PIC_MASK.store(0xffff, Ordering::Release);
        true
    }

    fn enable_irq(&self, irq: u8) {
        let mut mask = PIC_MASK.load(Ordering::Acquire);
        mask &= !(1u16 << (irq as u16));
        PIC_MASK.store(mask, Ordering::Release);
        self.write_mask(mask);
    }

    fn disable_irq(&self, irq: u8) {
        let mut mask = PIC_MASK.load(Ordering::Acquire);
        mask |= 1u16 << (irq as u16);
        PIC_MASK.store(mask, Ordering::Release);
        self.write_mask(mask);
    }

    fn eoi(&self, irq: u8) {
        let cmd: u8 = 0x20;
        unsafe {
            outb(0x20, cmd);
        }
        if irq >= 8 {
            unsafe {
                outb(0xA0, cmd);
            }
        }
    }
}