rustubs/arch/x86_64/interrupt/
pic_8259.rs

1use crate::arch::x86_64::io_port::*;
2// code from: https://wiki.osdev.org/8259_PIC#Code_Examples
3// data and control ports of PIC1 (master) and PIC2 (slave)
4const IMR1: u16 = 0x21;
5const IMR2: u16 = 0xa1;
6const CTRL1: u16 = 0x20;
7const CTRL2: u16 = 0xa0;
8const PIC_VECTOR_OFFSET: u8 = 0x20;
9
10pub struct PicDeviceInt;
11impl PicDeviceInt {
12	pub const TIMER: u8 = 0;
13	pub const KEYBOARD: u8 = 1;
14}
15
16pub fn init() {
17	// ICW1_ICW4 | ICW1_INIT
18	// start init sequence in cascade mode
19	outb(CTRL1, 0x11);
20	outb(CTRL2, 0x11);
21	// ICW2: MASTER PIC vector offset = 0x20
22	outb(IMR1, PIC_VECTOR_OFFSET);
23	// ICW2: SLAVE PIC vector offset = 0x28
24	outb(IMR2, PIC_VECTOR_OFFSET + 8);
25	// ICW3: tell Master PIC that there is a slave PIC at IRQ2 (0000 0100)
26	outb(IMR1, 0x04);
27	// ICW3: tell Slave PIC its cascade identity (0000 0010)
28	outb(IMR2, 0x02);
29	// ICW4: 8086 mode | auto (normal) EOI
30	outb(IMR1, 0x03);
31	outb(IMR2, 0x03);
32	// set masks
33	outb(IMR1, 0xfb);
34	outb(IMR2, 0xff);
35}
36
37// 8-bit registers IMR1 and IMR2 registers hold interrupt masking bit 0~7 and
38// 8~15; if an interrupt is masked(set 1) on the respective bit, it's disabled
39pub fn allow(interrupt: u8) {
40	if interrupt < 8 {
41		let old = inb(IMR1);
42		outb(IMR1, old & !(1 << interrupt));
43	} else {
44		let old = inb(IMR2);
45		outb(IMR2, old & !(1 << (interrupt - 8)));
46	}
47}
48
49pub fn forbid(interrupt: u8) {
50	if interrupt < 8 {
51		let old = inb(IMR1);
52		outb(IMR1, old | (1 << interrupt));
53	} else {
54		let old = inb(IMR2);
55		outb(IMR2, old | (1 << (interrupt - 8)));
56	}
57}
58
59pub fn is_masked(interrupt: u8) -> bool {
60	if interrupt < 8 {
61		let val = inb(IMR1);
62		val & (interrupt) != 0
63	} else {
64		let val = inb(IMR2);
65		val & (interrupt - 8) != 0
66	}
67}