#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; }