blob: e37b7809ac84542b3eec64df0f1498e3c3b6b8f1 [file] [edit]
// Copyright 2016 The Fuchsia Authors
// Copyright (c) 2009 Corey Tabaka
// Copyright (c) 2015 Intel Corporation
//
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file or at
// https://opensource.org/licenses/MIT
use crate::arch_rs::x86::x86::outp;
/// Master PIC (PIC1) command and status I/O port.
pub const PIC1_COMMAND: u16 = 0x20;
/// Master PIC (PIC1) data and interrupt mask register I/O port.
pub const PIC1_DATA: u16 = 0x21;
/// Slave PIC (PIC2) command and status I/O port.
pub const PIC2_COMMAND: u16 = 0xA0;
/// Slave PIC (PIC2) data and interrupt mask register I/O port.
pub const PIC2_DATA: u16 = 0xA1;
/// Initialization Command Word 1 (ICW1): Initialization bit (0x10) + ICW4 needed (0x01).
pub const ICW1: u8 = 0x11;
/// Initialization Command Word 3 (ICW3) for Master: Slave controller connected to IRQ2 (bit 2 = 0x04).
pub const ICW3_MASTER: u8 = 0x04;
/// Initialization Command Word 3 (ICW3) for Slave: Slave identification code (IRQ2 = 0x02).
pub const ICW3_SLAVE: u8 = 0x02;
/// Initialization Command Word 4 (ICW4): 8086/88 mode (0x01).
pub const ICW4_8086: u8 = 0x01;
/// Initialization Command Word 4 (ICW4) for Master: 8086/88 mode + special fully nested / buffered mode (0x05).
pub const ICW4_MASTER: u8 = 0x05;
/// Operation Control Word 1 (OCW1): Mask all 8 IRQs on the PIC.
pub const PIC_DISABLE_ALL_IRQS: u8 = 0xFF;
/// Initializes the 8259A PICs and remaps their base interrupt vectors.
///
/// Sends the 4-step Initialization Command Word (ICW) sequence to both the master
/// and slave PICs to remap their interrupt vectors to `pic1` and `pic2` respectively,
/// configure master/slave cascading on IRQ2, set 8086 mode, and mask all IRQs.
pub fn pic_map(pic1: u8, pic2: u8) {
/* send ICW1 */
// SAFETY: Initializing master and slave PICs by writing ICW1 to their command ports.
unsafe {
outp(PIC1_COMMAND, ICW1);
outp(PIC2_COMMAND, ICW1);
}
/* send ICW2 */
// SAFETY: Writing base interrupt vector offsets (ICW2) to master and slave PIC data ports.
unsafe {
outp(PIC1_DATA, pic1); /* remap */
outp(PIC2_DATA, pic2); /* pics */
}
/* send ICW3 */
// SAFETY: Configuring cascade topology (ICW3): master has slave on IRQ2; slave is cascaded to IRQ2.
unsafe {
outp(PIC1_DATA, ICW3_MASTER); /* IRQ2 -> connection to slave */
outp(PIC2_DATA, ICW3_SLAVE);
}
/* send ICW4 */
// SAFETY: Configuring operation modes (ICW4) on master and slave PICs.
unsafe {
outp(PIC1_DATA, ICW4_MASTER);
outp(PIC2_DATA, ICW4_8086);
}
/* disable all IRQs */
// SAFETY: Masking all interrupt lines on both PICs by writing 0xFF to their data registers (OCW1).
unsafe {
outp(PIC1_DATA, PIC_DISABLE_ALL_IRQS);
outp(PIC2_DATA, PIC_DISABLE_ALL_IRQS);
}
}
/// Disables all interrupt lines on both PICs by setting their interrupt masks to 0xFF.
pub fn pic_disable() {
// SAFETY: Writing 0xFF to slave and master PIC data ports to mask all IRQs.
unsafe {
outp(PIC2_DATA, PIC_DISABLE_ALL_IRQS);
outp(PIC1_DATA, PIC_DISABLE_ALL_IRQS);
}
}