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