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
use core::mem::transmute;
use core::ptr::RawPtr;
use cpu::DtReg;
use cpu::exception::Fault;
use cpu::idt::{IdtEntry, IdtReg, INTR_GATE, PRESENT};
use platform::drivers::pic;
use kernel::heap;
pub enum Int {
Fault(Fault)
}
pub struct Table {
reg: &'static IdtReg,
table: *mut IdtEntry,
mask: u16,
}
impl Table {
pub fn new() -> Table {
unsafe {
let table = heap::zero_alloc::<IdtEntry>(256);
let reg = heap::alloc::<IdtReg>(1);
*(reg as *mut IdtReg) = DtReg::new(table, 256);
Table {
reg: transmute(reg),
table: table,
mask: 0xffff
}
}
}
pub unsafe fn enable_maskable(&mut self, irq: uint, isr: unsafe extern "C" fn()) {
*self.table.offset(irq as int) = IdtEntry::new(
isr,
1 << 3,
INTR_GATE | PRESENT
);
self.mask &= !(1u16 << (irq & 0b1111));
pic::mask(self.mask);
}
#[allow(visible_private_types)]
pub unsafe fn set_isr(&mut self, val: Fault, code: bool, handler: unsafe extern "C" fn()) {
*self.table.offset(val as int) = Isr::new(Fault(val), code).idt_entry(handler);
}
pub fn load(&self) {
self.reg.load();
pic::remap();
pic::mask(self.mask);
enable();
}
}
fn enable() {
unsafe {
asm!("sti" :::: "volatile", "intel");
}
}
#[packed]
pub struct Isr {
push_dummy: u8,
push: u8,
value: Int,
jmp: u8,
rel: i32
}
impl Isr {
pub fn new<'a>(val: Int, code: bool) -> &'a mut Isr {
let this: &mut Isr = unsafe { transmute(heap::alloc::<Isr>(1)) };
*this = Isr {
push_dummy: if code { 0x90 } else { 0x50 },
push: 0x6a, value: val,
jmp: 0xe9, rel: -5
};
this
}
pub unsafe fn idt_entry(&mut self, handler: unsafe extern "C" fn()) -> IdtEntry {
self.rel = handler as i32 - (self as *mut Isr).offset(1) as i32;
IdtEntry::new(transmute(self), 1 << 3, INTR_GATE | PRESENT)
}
}