aboutsummaryrefslogtreecommitdiff
path: root/src/utils/pic.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/utils/pic.c')
-rw-r--r--src/utils/pic.c65
1 files changed, 65 insertions, 0 deletions
diff --git a/src/utils/pic.c b/src/utils/pic.c
new file mode 100644
index 0000000..f77eb70
--- /dev/null
+++ b/src/utils/pic.c
@@ -0,0 +1,65 @@
+#include "pic.h"
+#include "asm.h"
+#include "mem.h"
+
+struct IDT_REGISTER IDTR={
+ 90*8,
+ 0
+};
+
+/// Bridge between IDT and functions call
+asm (
+"PIC_IRQ_DEFAULT:"
+ "movb $0x20, %al \n\t"
+ "outb %al, $0x20 \n\t"
+ "iret \n\t"
+"PIC_IRQ_PRINT: \n\t"
+ "call _8042_keypress \n\t"
+ "movb $0x20, %al \n\t"
+ "outb %al, $0x20 \n\t"
+ "iret \n\t"
+);
+
+extern u32 PIC_IRQ_DEFAULT,PIC_IRQ_PRINT;
+
+
+void pic_enable_interrupt(){
+ // Map first default 32 entries
+ for(int i=0;i<90;i++){
+ pic_add_idt_entry((IDT_ENTRY){0x08,(u32)&PIC_IRQ_DEFAULT,IDT_TYPE_1});
+ if(i==32)
+ pic_add_idt_entry((IDT_ENTRY){0x08,(u32)&PIC_IRQ_PRINT,IDT_TYPE_1});
+ }
+
+ // Now configure 8952A
+
+ // ICW1: Initialisation
+ outbj(0x20,0x11); // Master
+ outbj(0xA0,0x11); // Slave
+
+ // ICW2: Map IRQ index to entry into the IDT
+ outbj(0x21,0x20); // Start interrupt at offset 0x20 in IDT (index 32)
+ outbj(0xA1,0x50); // Start interrupt at offset 0x50 in IDT (index 80)
+
+ // ICW3: Indicate the connection between master and slave
+ outbj(0x21,0x02); // Slave connected to pin 2
+ outbj(0xA1,0x01); // Indicate pin id to the slave (2-1)
+
+ // ICW4: Operating mode
+ outbj(0x21,0x01); // Default operating mode
+ outbj(0xA1,0x01); // Default operating mode
+
+ asm("lidtl (IDTR)");
+ asm("sti");
+
+}
+
+void pic_add_idt_entry(IDT_ENTRY entry){
+ static int cur_offset=0;
+ int descriptor[2];
+ descriptor[0]=entry.offset & 0xFFFF | entry.segment << 16;
+ descriptor[1]=entry.type & 0xFFFF | entry.offset & 0xFFFF0000;
+
+ memcpy((void*)descriptor, (void *)(IDTR.base+cur_offset),8);
+ cur_offset+=8;
+} \ No newline at end of file