61 lines
1.6 KiB
C
61 lines
1.6 KiB
C
#include "pic.h"
|
|
#include "asm.h"
|
|
#include "mem.h"
|
|
|
|
struct IDT_REGISTER IDTR={
|
|
100*8,
|
|
0x0
|
|
};
|
|
|
|
/// 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<100;i++){
|
|
pic_add_idt_entry((IDT_ENTRY){0x08,(u32)&PIC_IRQ_DEFAULT,IDT_TYPE_1},i);
|
|
if(i==32)
|
|
pic_add_idt_entry((IDT_ENTRY){0x08,(u32)&PIC_IRQ_PRINT,IDT_TYPE_1},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
|
|
|
|
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);
|
|
}
|