1+ use crate :: { gdt, print, println} ;
12use lazy_static:: lazy_static;
3+ use pc_keyboard:: { layouts, DecodedKey , HandleControl , Keyboard , ScancodeSet1 } ;
4+ use pic8259:: ChainedPics ;
5+ use spin:: { self , Mutex } ;
26use x86_64:: structures:: idt:: { InterruptDescriptorTable , InterruptStackFrame } ;
37
4- use crate :: println;
8+ // PIC primário
9+ pub const PIC_1_OFFSET : u8 = 32 ;
10+ // PIC secundário
11+ pub const PIC_2_OFFSET : u8 = PIC_1_OFFSET + 8 ;
12+
13+ pub static PICS : spin:: Mutex < ChainedPics > =
14+ spin:: Mutex :: new ( unsafe { ChainedPics :: new ( PIC_1_OFFSET , PIC_2_OFFSET ) } ) ;
15+
16+ #[ derive( Debug , Clone , Copy ) ]
17+ #[ repr( u8 ) ]
18+ pub enum InterruptIndex {
19+ Timer = PIC_1_OFFSET ,
20+ Keyboard ,
21+ }
22+
23+ impl InterruptIndex {
24+ fn as_u8 ( self ) -> u8 {
25+ self as u8
26+ }
27+
28+ fn as_usize ( self ) -> usize {
29+ usize:: from ( self . as_u8 ( ) )
30+ }
31+ }
532
633lazy_static ! {
734 static ref IDT : InterruptDescriptorTable = {
835 let mut idt = InterruptDescriptorTable :: new( ) ;
936 idt. breakpoint. set_handler_fn( breakpoint_handler) ;
37+ unsafe {
38+ idt. double_fault
39+ . set_handler_fn( double_fault_handler)
40+ . set_stack_index( gdt:: DOUBLE_FAULT_IST_INDEX ) ;
41+ }
42+ idt[ InterruptIndex :: Timer . as_usize( ) ] . set_handler_fn( timer_interrupt_handler) ;
43+ idt[ InterruptIndex :: Keyboard . as_usize( ) ] . set_handler_fn( keyboard_interrupt_handler) ;
1044 idt
1145 } ;
1246}
@@ -15,10 +49,59 @@ pub fn init_idt() {
1549 IDT . load ( ) ;
1650}
1751
52+ // as interrupções utilizam um calling convention específico.
1853extern "x86-interrupt" fn breakpoint_handler ( stack_frame : InterruptStackFrame ) {
1954 println ! ( "EXCEPTION: BREAKPOINT\n {:#?}" , stack_frame) ;
2055}
2156
57+ extern "x86-interrupt" fn double_fault_handler (
58+ stack_frame : InterruptStackFrame ,
59+ _error_code : u64 ,
60+ ) -> ! {
61+ panic ! ( "EXCEPTION: DOUBLE FAULT\n {:#?}" , stack_frame) ;
62+ }
63+
64+ extern "x86-interrupt" fn timer_interrupt_handler ( _stack_frame : InterruptStackFrame ) {
65+ print ! ( "." ) ;
66+
67+ unsafe {
68+ PICS . lock ( )
69+ . notify_end_of_interrupt ( InterruptIndex :: Timer . as_u8 ( ) ) ;
70+ }
71+ }
72+
73+ extern "x86-interrupt" fn keyboard_interrupt_handler ( _stack_frame : InterruptStackFrame ) {
74+ use x86_64:: instructions:: port:: Port ;
75+
76+ lazy_static ! {
77+ static ref KEYBOARD : Mutex <Keyboard <layouts:: Us104Key , ScancodeSet1 >> =
78+ Mutex :: new( Keyboard :: new(
79+ ScancodeSet1 :: new( ) ,
80+ layouts:: Us104Key ,
81+ HandleControl :: Ignore
82+ ) ) ;
83+ }
84+
85+ let mut keyboard = KEYBOARD . lock ( ) ;
86+ let mut port = Port :: new ( 0x60 ) ;
87+
88+ let scancode: u8 = unsafe { port. read ( ) } ;
89+
90+ if let Ok ( Some ( key_event) ) = keyboard. add_byte ( scancode) {
91+ if let Some ( key) = keyboard. process_keyevent ( key_event) {
92+ match key {
93+ DecodedKey :: Unicode ( character) => print ! ( "{}" , character) ,
94+ DecodedKey :: RawKey ( key) => print ! ( "{:?}" , key) ,
95+ }
96+ }
97+ }
98+
99+ unsafe {
100+ PICS . lock ( )
101+ . notify_end_of_interrupt ( InterruptIndex :: Keyboard . as_u8 ( ) ) ;
102+ }
103+ }
104+
22105#[ test_case]
23106fn test_breakpoint_exception ( ) {
24107 x86_64:: instructions:: interrupts:: int3 ( ) ;
0 commit comments