diff options
Diffstat (limited to 'src/interrupts.c')
-rw-r--r-- | src/interrupts.c | 41 |
1 files changed, 33 insertions, 8 deletions
diff --git a/src/interrupts.c b/src/interrupts.c index 07a7e55..0c3c72a 100644 --- a/src/interrupts.c +++ b/src/interrupts.c @@ -57,6 +57,20 @@ // OCW2 #define OCW2_EOI 0x20 // non-specific End Of Interrupt +void interrupt_handler_init_void( interrupt_handler_t *handler ) +{ + memset( handler, 0, sizeof( interrupt_handler_t ) ); +} + +void interrupt_handler_init( interrupt_handler_t *handler, uint8_t interrupt_no, struct interrupt_t *interrupt, interrupt_handler_func_t handle ) +{ + memset( handler, 0, sizeof( interrupt_handler_t ) ); + + handler->interrupt_no = interrupt_no; + handler->interrupt = interrupt; + handler->handle = handle; +} + // must be global: when called via assembly code we loose the context // of the interrupt handler structure static interrupt_t *active_interrupt; @@ -64,27 +78,39 @@ static interrupt_t *active_interrupt; void interrupts_init( interrupt_t *interrupt ) { memset( interrupt, 0, sizeof( interrupt_t ) ); + + interrupt_handler_t empty_interrupt_handler; + interrupt_handler_init_void( &empty_interrupt_handler ); for( int i = 0; i < NOF_INTERRUPTS; i++ ) { interrupts_register_interrupt( interrupt, i, GDT_CODE_SEGMENT_SELECTOR, &interrupts_ignore_request, KERNEL_RING, IDT_TYPE_INTERRUPT_GATE, - NULL ); + empty_interrupt_handler ); } // divide-by-zero exception 0x00 + interrupt_handler_t divide_by_zero_interrupt_handler; + interrupt_handler_init( ÷_by_zero_interrupt_handler, 0x00, interrupt, interrupts_exception_division_by_zero ); + interrupts_register_interrupt( interrupt, 0x00, GDT_CODE_SEGMENT_SELECTOR, &interrupts_handle_exception_0x00, KERNEL_RING, IDT_TYPE_INTERRUPT_GATE, - &interrupts_exception_division_by_zero ); + divide_by_zero_interrupt_handler ); // IRQ 0 - PIT - programmable interrupt timer + interrupt_handler_t pit_interrupt_handler; + interrupt_handler_init( &pit_interrupt_handler, IRQ_BASE + 0x00, interrupt, interrupts_interrupt_PIT ); + interrupts_register_interrupt( interrupt, IRQ_BASE + 0x00, GDT_CODE_SEGMENT_SELECTOR, &interrupts_handle_irq_0x00, KERNEL_RING, IDT_TYPE_INTERRUPT_GATE, - &interrupts_interrupt_PIT ); + pit_interrupt_handler ); // IRQ 1 - keyboard + interrupt_handler_t keyboard_interrupt_handler; + interrupt_handler_init( &keyboard_interrupt_handler, IRQ_BASE + 0x01, interrupt, interrupts_interrupt_keyboard ); + interrupts_register_interrupt( interrupt, IRQ_BASE + 0x01, GDT_CODE_SEGMENT_SELECTOR, &interrupts_handle_irq_0x01, KERNEL_RING, IDT_TYPE_INTERRUPT_GATE, - &interrupts_interrupt_keyboard ); + keyboard_interrupt_handler ); port8_init( &interrupt->PIC_master_control, 0x20 ); port8_init( &interrupt->PIC_master_data, 0x21 ); @@ -117,7 +143,7 @@ void interrupts_init( interrupt_t *interrupt ) port8_write( &interrupt->PIC_slave_data, 0 ); // tell CPU where the IDT is - interrupt->idt_pointer.size = 256 * sizeof( interrupt_gate_descriptor_t ) - 1; + interrupt->idt_pointer.size = NOF_INTERRUPTS * sizeof( interrupt_gate_descriptor_t ) - 1; interrupt->idt_pointer.base = (uint32_t)interrupt->descriptor_table; interrupts_load_idt( &interrupt->idt_pointer ); @@ -168,7 +194,6 @@ printf( "Hex number is 0x%X and string is '%s'\n", x, "abaos" ); return esp; } - uint32_t interrupts_handle_static_interrupt( uint8_t interrupt_no, uint32_t esp ) { if( active_interrupt == NULL ) { @@ -182,11 +207,11 @@ uint32_t interrupts_handle_interrupt( interrupt_t *interrupt, uint8_t interrupt_ { interrupt_handler_t handler = interrupt->interrupt_handler[interrupt_no]; - if( handler == NULL ) { + if( handler.handle == NULL ) { kernel_panic( "Unhandled interrupt 0x%X with ESP 0x%X\n", interrupt_no, esp ); } - uint32_t new_esp = handler( interrupt, esp ); + uint32_t new_esp = handler.handle( interrupt, esp ); // send ACK to PIC for hardware interrups if( interrupt_no >= IRQ_BASE && interrupt_no <= IRQ_BASE + 16 ) { |