Skip to content

Commit

Permalink
pic: struct for chained pic arrangement
Browse files Browse the repository at this point in the history
barzamin committed Oct 22, 2018
1 parent 40e2835 commit 6e7bb1d
Showing 2 changed files with 42 additions and 28 deletions.
68 changes: 41 additions & 27 deletions src/arch/x86_64/device/pic.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
//! Driver for the Programmable Interrupt Controller (Intel 8259A).
use x86_64::instructions::port::Port;
use spin::Mutex;

pub const PRIMARY: Pic = Pic::new(0x20);
pub const SECONDARY: Pic = Pic::new(0xA0);
pub static PICS: Mutex<ChainedPics> = Mutex::new(ChainedPics::new(0x20, 0xA0));

// command constants to send
const PIC_OCW2_EOI: u8 = 0x20;
@@ -12,30 +12,44 @@ const PIC_ICW1_INIT: u8 = 0x10;
const PIC_ICW1_ICW4: u8 = 0x01;
const PIC_ICW4_MODE_8086: u8 = 0x01;

/// Initializes the PIC hardware.
///
/// # Notes
/// This remaps the master PIC to IRQs 0x20..0x28, and the slave to 0x28..0x36.
pub unsafe fn init() {
// ICW1: start initialization, signal that we want the ICW4 phase
PRIMARY.cmd.write(PIC_ICW1_INIT | PIC_ICW1_ICW4);
SECONDARY.cmd.write(PIC_ICW1_INIT | PIC_ICW1_ICW4);

// ICW2: set offsets
PRIMARY.data.write(0x20);
SECONDARY.data.write(0x28);

// ICW3: configure PIC cascading. IRQ 2 [via PC99] is used to chain to the secondary PIC.
PRIMARY.data.write(1 << 2); // the IRQ 2 line is used for cascading
SECONDARY.data.write(2); // the secondary PIC has an ID of 2

// ICW4: put the PICs into 8086 mode (EOIs are required)
PRIMARY.data.write(PIC_ICW4_MODE_8086);
SECONDARY.data.write(PIC_ICW4_MODE_8086);

// initialization done. clear IRQ masks
PRIMARY.set_irq_mask(0);
SECONDARY.set_irq_mask(0);
pub struct ChainedPics {
primary: Pic,
secondary: Pic,
}

impl ChainedPics {
const fn new(primary_port: u16, secondary_port: u16) -> ChainedPics {
ChainedPics {
primary: Pic::new(primary_port),
secondary: Pic::new(secondary_port),
}
}

/// Initializes the PIC hardware.
///
/// # Notes
/// This remaps the primary PIC to IRQs 0x20..0x28, and the secondary PIC to 0x28..0x36.
pub unsafe fn init(&mut self) {
// ICW1: start initialization, signal that we want the ICW4 phase
self.primary.cmd.write(PIC_ICW1_INIT | PIC_ICW1_ICW4);
self.secondary.cmd.write(PIC_ICW1_INIT | PIC_ICW1_ICW4);

// ICW2: set offsets
self.primary.data.write(0x20);
self.secondary.data.write(0x28);

// ICW3: configure PIC cascading. IRQ 2 [via PC99] is used to chain to the secondary PIC.
self.primary.data.write(1 << 2); // the IRQ 2 line is used for cascading
self.secondary.data.write(2); // the secondary PIC has an ID of 2

// ICW4: put the PICs into 8086 mode (EOIs are required)
self.primary.data.write(PIC_ICW4_MODE_8086);
self.secondary.data.write(PIC_ICW4_MODE_8086);

// initialization done. clear IRQ masks
self.primary.set_irq_mask(0);
self.secondary.set_irq_mask(0);
}
}

pub struct Pic {
@@ -44,7 +58,7 @@ pub struct Pic {
}

impl Pic {
pub const fn new(port: u16) -> Pic {
const fn new(port: u16) -> Pic {
Pic {
cmd: Port::new(port),
data: Port::new(port + 1),
2 changes: 1 addition & 1 deletion src/arch/x86_64/mod.rs
Original file line number Diff line number Diff line change
@@ -27,7 +27,7 @@ pub unsafe extern "C" fn _start(multiboot_info_pointer: usize) -> ! {
interrupts::init(&mut mem_ctrl);
info!("int: initialized idt");

pic::init();
pic::PICS.lock().init();
info!("int: initialized pic");

pit::init();

0 comments on commit 6e7bb1d

Please sign in to comment.