1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
use crate::arch::x86_64::kernel::idt;
use crate::arch::x86_64::kernel::irq::ExceptionStackFrame;
use crate::x86::io::*;
const PIC1_COMMAND_PORT: u16 = 0x20;
const PIC1_DATA_PORT: u16 = 0x21;
const PIC2_COMMAND_PORT: u16 = 0xA0;
const PIC2_DATA_PORT: u16 = 0xA1;
pub const PIC1_INTERRUPT_OFFSET: u8 = 32;
const PIC2_INTERRUPT_OFFSET: u8 = 40;
const SPURIOUS_IRQ_NUMBER: u8 = 7;
const PIC_EOI_COMMAND: u8 = 0x20;
pub fn eoi(int_no: u8) {
unsafe {
if int_no >= 40 {
outb(PIC2_COMMAND_PORT, PIC_EOI_COMMAND);
}
outb(PIC1_COMMAND_PORT, PIC_EOI_COMMAND);
}
}
pub fn init() {
idt::set_gate(
PIC1_INTERRUPT_OFFSET + SPURIOUS_IRQ_NUMBER,
spurious_interrupt_on_master as usize,
0,
);
idt::set_gate(
PIC2_INTERRUPT_OFFSET + SPURIOUS_IRQ_NUMBER,
spurious_interrupt_on_slave as usize,
0,
);
unsafe {
outb(PIC1_COMMAND_PORT, 0x11);
outb(PIC2_COMMAND_PORT, 0x11);
outb(PIC1_DATA_PORT, PIC1_INTERRUPT_OFFSET);
outb(PIC2_DATA_PORT, PIC2_INTERRUPT_OFFSET);
outb(PIC1_DATA_PORT, 0x04);
outb(PIC2_DATA_PORT, 0x02);
outb(PIC1_DATA_PORT, 0x01);
outb(PIC2_DATA_PORT, 0x01);
outb(PIC1_DATA_PORT, 0xFF);
outb(PIC2_DATA_PORT, 0xFF);
}
}
extern "x86-interrupt" fn spurious_interrupt_on_master(_stack_frame: &mut ExceptionStackFrame) {
debug!("Spurious Interrupt on Master PIC (IRQ7)");
}
extern "x86-interrupt" fn spurious_interrupt_on_slave(_stack_frame: &mut ExceptionStackFrame) {
debug!("Spurious Interrupt on Slave PIC (IRQ15)");
unsafe {
outb(PIC1_COMMAND_PORT, PIC_EOI_COMMAND);
}
}
fn edit_mask(int_no: u8, insert: bool) {
let port = if int_no >= 40 {
PIC2_DATA_PORT
} else {
PIC1_DATA_PORT
};
let offset = if int_no >= 40 { 40 } else { 32 };
unsafe {
let mask = inb(port);
if insert {
outb(port, mask | 1 << (int_no - offset));
} else {
outb(port, mask & !(1 << (int_no - offset)));
}
}
}
pub fn mask(int_no: u8) {
edit_mask(int_no, true);
}
pub fn unmask(int_no: u8) {
edit_mask(int_no, false);
}