diff options
Diffstat (limited to 'src/interrupts.c')
-rw-r--r-- | src/interrupts.c | 38 |
1 files changed, 33 insertions, 5 deletions
diff --git a/src/interrupts.c b/src/interrupts.c index 810f105..59f38b8 100644 --- a/src/interrupts.c +++ b/src/interrupts.c @@ -17,6 +17,16 @@ // types of IDT entries #define IDT_TYPE_INTERRUPT_GATE 0xE +// offset for hardware interrupts +#define IRQ_BASE 0x20 +#define IRQ_BASE_MASTER IRQ_BASE +#define IRQ_BASE_SLAVE IRQ_BASE_MASTER + 8 + +// PIC constants + +#define ICW1_ICW4 0x01 // support a 4th initialization word (ICW4) +#define ICW1_INIT 0x10 // bit indicating initialization of chip + void interrupts_init( interrupt_t *interrupt ) { memset( interrupt, 0, sizeof( interrupt_t ) ); @@ -28,16 +38,34 @@ void interrupts_init( interrupt_t *interrupt ) // divide-by-zero exception 0x00 interrupts_register_interrupt( interrupt, 0x00, GDT_CODE_SEGMENT_SELECTOR, - &interrupts_handle_request_0x00, KERNEL_RING, IDT_TYPE_INTERRUPT_GATE ); + &interrupts_handle_exception_0x00, KERNEL_RING, IDT_TYPE_INTERRUPT_GATE ); - interrupt->idt_pointer.size = 256 * sizeof( interrupt_gate_descriptor_t ) - 1; - interrupt->idt_pointer.base = (uint32_t)interrupt->descriptor_table; - - interrupts_load_idt( &interrupt->idt_pointer ); + // IRQ 0 - PIT - programmable interrupt timer + interrupts_register_interrupt( interrupt, IRQ_BASE + 0x00, GDT_CODE_SEGMENT_SELECTOR, + &interrupts_handle_irq_0x00, KERNEL_RING, IDT_TYPE_INTERRUPT_GATE ); + // IRQ 1 - keyboard + interrupts_register_interrupt( interrupt, IRQ_BASE + 0x00, GDT_CODE_SEGMENT_SELECTOR, + &interrupts_handle_irq_0x00, KERNEL_RING, IDT_TYPE_INTERRUPT_GATE ); + port8_init( &interrupt->PIC_master_control, 0x20 ); port8_init( &interrupt->PIC_master_data, 0x21 ); + port8_init( &interrupt->PIC_slave_control, 0xA0 ); + port8_init( &interrupt->PIC_slave_data, 0xA1 ); + + // initialize hardware management PICs (ICW1) + port8_write( &interrupt->PIC_master_control, ICW1_ICW4 | ICW1_INIT ); + port8_write( &interrupt->PIC_slave_control, ICW1_ICW4 | ICW1_INIT ); + // set IRQ base of both PICS (ICW2) + port8_write( &interrupt->PIC_master_data, IRQ_BASE_MASTER ); + port8_write( &interrupt->PIC_slave_data, IRQ_BASE_SLAVE ); + + // tell CPU where the IDT is + interrupt->idt_pointer.size = 256 * sizeof( interrupt_gate_descriptor_t ) - 1; + interrupt->idt_pointer.base = (uint32_t)interrupt->descriptor_table; + + interrupts_load_idt( &interrupt->idt_pointer ); } void interrupts_register_interrupt( interrupt_t *interrupts, |