From ec014db9fa3f6b5b7ad3491c20f2c2a65c56a7a6 Mon Sep 17 00:00:00 2001 From: Andreas Baumann Date: Thu, 1 Jun 2017 19:14:44 +0200 Subject: introducted a interrupt handler object --- doc/LINKS.TODO | 1 + src/Makefile | 4 ++-- src/interrupts.c | 41 +++++++++++++++++++++++++++++++++-------- src/interrupts.h | 11 ++++++++++- src/stage1_functions.asm | 2 +- 5 files changed, 47 insertions(+), 12 deletions(-) diff --git a/doc/LINKS.TODO b/doc/LINKS.TODO index a7b3f15..df6471d 100644 --- a/doc/LINKS.TODO +++ b/doc/LINKS.TODO @@ -39,4 +39,5 @@ http://prettyos.de PIC: http://www.brokenthorn.com/Resources/OSDevPic.html +http://wiki.osdev.org/8259_PIC diff --git a/src/Makefile b/src/Makefile index 3e89a74..9c6a931 100644 --- a/src/Makefile +++ b/src/Makefile @@ -13,10 +13,10 @@ all: image.bin kernel.sym # + M * 512 (M is currently 7) = 3144 for kernel.bin # + 1 * 512 = 512 for magic.bin # (M + N + 1 is the number of sectors to be read in stage 2, as stage 1 -# loads only the first sector, so adapt NOF_LOAD_SECTORS to 19) +# loads only the first sector, so adapt NOF_LOAD_SECTORS to 20) image.bin: boot.bin kernel.bin magic.bin cat boot.bin kernel.bin > image.tmp - truncate -s 9728 image.tmp + truncate -s 10240 image.tmp cat image.tmp magic.bin > image.bin boot.bin: boot.asm boot_gdt.asm stage1_functions.asm stage2_functions.asm stage2_switch_mode.asm stage2_a20.asm 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 ) { diff --git a/src/interrupts.h b/src/interrupts.h index 0cdb6cc..82f95f4 100644 --- a/src/interrupts.h +++ b/src/interrupts.h @@ -43,7 +43,16 @@ typedef struct { struct interrupt_t; -typedef uint32_t (*interrupt_handler_t)( struct interrupt_t *interrupt, uint32_t esp ); +typedef uint32_t (*interrupt_handler_func_t)( struct interrupt_t *interrupt, uint32_t esp ); + +typedef struct interrupt_handler_t { + uint8_t interrupt_no; + struct interrupt_t *interrupt; + interrupt_handler_func_t handle; +} interrupt_handler_t; + +void interrupt_handler_init_void( interrupt_handler_t *handler ); +void interrupt_handler_init( interrupt_handler_t *handler, uint8_t interrupt_no, struct interrupt_t *interrupt, interrupt_handler_func_t handle ); typedef struct interrupt_t { interrupt_descriptor_table_pointer_t idt_pointer; diff --git a/src/stage1_functions.asm b/src/stage1_functions.asm index c2e1bcd..8953b9c 100644 --- a/src/stage1_functions.asm +++ b/src/stage1_functions.asm @@ -2,7 +2,7 @@ ; 3 * 512 for bootloader stage2 and the kernel code ; (note: the first sector gets loaded by the BIOS, so ; subtract 1 here!) -NOF_LOAD_SECTORS equ 19 +NOF_LOAD_SECTORS equ 20 ; IN bx: begin of memory area to dump ; IN ax: number of words to dump -- cgit v1.2.3-54-g00ecf