diff options
Diffstat (limited to 'src/int/pic.c')
| -rw-r--r-- | src/int/pic.c | 115 |
1 files changed, 115 insertions, 0 deletions
diff --git a/src/int/pic.c b/src/int/pic.c new file mode 100644 index 0000000..472e50c --- /dev/null +++ b/src/int/pic.c @@ -0,0 +1,115 @@ +#include "pic.h" +#include "utils/asm.h" +#include "utils/mem.h" +#include "utils/syscall.h" + +struct IDT_REGISTER IDTR={ + 200*8, + 0x0 +}; + +/// Bridge between IDT and functions call +asm ( +".macro SAVE_REGS \n\t" + "pushal \n\t" + "push %ds \n\t" + "push %es \n\t" + "push %fs \n\t" + "push %gs \n\t" + "push %ebx \n\t" + "mov $0x10,%bx \n\t" + "mov %bx,%ds \n\t" + "pop %ebx \n\t" +".endm \n\t" +".macro RESTORE_REGS \n\t" + "pop %gs \n\t" + "pop %fs \n\t" + "pop %es \n\t" + "pop %ds \n\t" + "popal \n\t" +".endm \n\t" +"PIC_IRQ_DEFAULT: \n\t" + "SAVE_REGS \n\t" + "movb $0x20, %al \n\t" + "outb %al, $0x20 \n\t" + "RESTORE_REGS \n\t" + "iret \n\t" +"PIC_IRQ_PRINT: \n\t" + "SAVE_REGS \n\t" + "call _8042_keypress \n\t" + "movb $0x20, %al \n\t" + "outb %al, $0x20 \n\t" + "RESTORE_REGS \n\t" + "iret \n\t" +"PIC_IRQ_CLOCK: \n\t" + "SAVE_REGS \n\t" + "call clock \n\t" + "movb $0x20, %al \n\t" + "outb %al, $0x20 \n\t" + "RESTORE_REGS \n\t" + "iret \n\t" +"PIC_IRQ_SYSCALL: \n\t" + "SAVE_REGS \n\t" + "call syscall \n\t" + "movb $0x20, %al \n\t" + "outb %al, $0x20 \n\t" + "RESTORE_REGS \n\t" + "iret \n\t" +"INT_PAGE_FAULT: \n\t" + "SAVE_REGS \n\t" + "call page_fault \n\t" + "hlt \n\t" + "movb $0x20, %al \n\t" + "outb %al, $0x20 \n\t" + "RESTORE_REGS \n\t" + "iret \n\t" +); + +extern u32 PIC_IRQ_DEFAULT,PIC_IRQ_PRINT,PIC_IRQ_CLOCK, PIC_IRQ_SYSCALL,INT_PAGE_FAULT; + +void pic_enable_interrupt(){ + // Map first default 32 entries + for(int i=0;i<200;i++){ + pic_add_idt_entry((IDT_ENTRY){0x08,(u32)&PIC_IRQ_DEFAULT,IDT_INT_GATE},i); + if(i==14) + pic_add_idt_entry((IDT_ENTRY){0x08,(u32)&INT_PAGE_FAULT,IDT_INT_GATE},i); + if(i==32) + pic_add_idt_entry((IDT_ENTRY){0x08,(u32)&PIC_IRQ_CLOCK,IDT_INT_GATE},i); + if(i==33) + pic_add_idt_entry((IDT_ENTRY){0x08,(u32)&PIC_IRQ_PRINT,IDT_INT_GATE},i); + if(i==48) + pic_add_idt_entry((IDT_ENTRY){0x08,(u32)&PIC_IRQ_SYSCALL,IDT_TRAP_GATE},i); + } + + // 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,0x70); // 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 + + // OCW: Masking + outbj(0x21,0b11111100); + + + asm("lidtl (IDTR)"); + asm("sti"); +} + +void pic_add_idt_entry(IDT_ENTRY entry, int id){ + 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+(id*8)),8); +} |
