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