summaryrefslogtreecommitdiff
path: root/src/interrupts.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/interrupts.c')
-rw-r--r--src/interrupts.c41
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( &divide_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 ) {