diff --git a/arch/i386/inter.s b/arch/i386/inter.s new file mode 100644 index 0000000..a7c190f --- /dev/null +++ b/arch/i386/inter.s @@ -0,0 +1,154 @@ + global irq0 + global irq1 + global irq2 + global irq3 + global irq4 + global irq5 + global irq6 + global irq7 + global irq8 + global irq9 + global irq10 + global irq11 + global irq12 + global irq13 + global irq14 + global irq15 + + global load_idt + + global irq0_handler + global irq1_handler + global irq2_handler + global irq3_handler + global irq4_handler + global irq5_handler + global irq6_handler + global irq7_handler + global irq8_handler + global irq9_handler + global irq10_handler + global irq11_handler + global irq12_handler + global irq13_handler + global irq14_handler + global irq15_handler + + extern irq0_handler + extern irq1_handler + extern irq2_handler + extern irq3_handler + extern irq4_handler + extern irq5_handler + extern irq6_handler + extern irq7_handler + extern irq8_handler + extern irq9_handler + extern irq10_handler + extern irq11_handler + extern irq12_handler + extern irq13_handler + extern irq14_handler + extern irq15_handler + +irq0: + pusha + call irq0_handler + popa + iret + +irq1: + pusha + call irq1_handler + popa + iret + +irq2: + pusha + call irq2_handler + popa + iret + +irq3: + pusha + call irq3_handler + popa + iret + +irq4: + pusha + call irq4_handler + popa + iret + +irq5: + pusha + call irq5_handler + popa + iret + +irq6: + pusha + call irq6_handler + popa + iret + +irq7: + pusha + call irq7_handler + popa + iret + +irq8: + pusha + call irq8_handler + popa + iret + +irq9: + pusha + call irq9_handler + popa + iret + +irq10: + pusha + call irq10_handler + popa + iret + +irq11: + pusha + call irq11_handler + popa + iret + +irq12: + pusha + call irq12_handler + popa + iret + +irq13: + pusha + call irq13_handler + popa + iret + +irq14: + pusha + call irq14_handler + popa + iret + +irq15: + pusha + call irq15_handler + popa + iret + +load_idt: + mov 4(%esp), %edx + lidt %edx + sti + ret diff --git a/arch/i386/interrupt.c b/arch/i386/interrupt.c new file mode 100644 index 0000000..c5ffd0c --- /dev/null +++ b/arch/i386/interrupt.c @@ -0,0 +1,273 @@ +#include + +void idt_init(void) { + extern int load_idt(); + extern int irq0(); + extern int irq1(); + extern int irq2(); + extern int irq3(); + extern int irq4(); + extern int irq5(); + extern int irq6(); + extern int irq7(); + extern int irq8(); + extern int irq9(); + extern int irq10(); + extern int irq11(); + extern int irq12(); + extern int irq13(); + extern int irq14(); + extern int irq15(); + + unsigned long irq0_address; + unsigned long irq1_address; + unsigned long irq2_address; + unsigned long irq3_address; + unsigned long irq4_address; + unsigned long irq5_address; + unsigned long irq6_address; + unsigned long irq7_address; + unsigned long irq8_address; + unsigned long irq9_address; + unsigned long irq10_address; + unsigned long irq11_address; + unsigned long irq12_address; + unsigned long irq13_address; + unsigned long irq14_address; + unsigned long irq15_address; + unsigned long idt_address; + unsigned long idt_ptr[2]; + + /* remap PIC */ + outb(0x20, 0x11); + outb(0xA0, 0x11); + outb(0x21, 0x20); + outb(0xA1, 40); + outb(0x21, 0x04); + outb(0xA1, 0x02); + outb(0x21, 0x01); + outb(0xA1, 0x01); + outb(0x21, 0x0); + outb(0xA1, 0x0); + + irq0_address = (unsigned long) irq0; + IDT[32].offset_lowerbits = irq0_address & 0xffff; + IDT[32].selector = 0x08; /* KERNEL_CODE_SEGMENT OFFSET */ + IDT[32].zero = 0; + IDT[32].type_attr = 0x8e; /* INTERRUPT_GATE */ + IDT[32].offset_higherbits = (irq0_address & 0xffff0000) >> 16; + + irq1_address = (unsigned long) irq1; + IDT[33].offset_lowerbits = irq1_address & 0xffff; + IDT[33].selector = 0x08; /* KERNEL_CODE_SEGMENT OFFSET */ + IDT[33].zero = 0; + IDT[33].type_attr = 0x8e; /* INTERRUPT_GATE */ + IDT[33].offset_higherbits = (irq1_address & 0xffff0000) >> 16; + + irq2_address = (unsigned long) irq2; + IDT[34].offset_lowerbits = irq2_address & 0xffff; + IDT[34].selector = 0x08; /* KERNEL_CODE_SEGMENT OFFSET */ + IDT[34].zero = 0; + IDT[34].type_attr = 0x8e; /* INTERRUPT_GATE */ + IDT[34].offset_higherbits = (irq2_address & 0xffff0000) >> 16; + + irq3_address = (unsigned long) irq3; + IDT[35].offset_lowerbits = irq3_address & 0xffff; + IDT[35].selector = 0x08; /* KERNEL_CODE_SEGMENT OFFSET */ + IDT[35].zero = 0; + IDT[35].type_attr = 0x8e; /* INTERRUPT_GATE */ + IDT[35].offset_higherbits = (irq3_address & 0xffff0000) >> 16; + + irq4_address = (unsigned long) irq4; + IDT[36].offset_lowerbits = irq4_address & 0xffff; + IDT[36].selector = 0x08; /* KERNEL_CODE_SEGMENT OFFSET */ + IDT[36].zero = 0; + IDT[36].type_attr = 0x8e; /* INTERRUPT_GATE */ + IDT[36].offset_higherbits = (irq4_address & 0xffff0000) >> 16; + + irq5_address = (unsigned long) irq5; + IDT[37].offset_lowerbits = irq5_address & 0xffff; + IDT[37].selector = 0x08; /* KERNEL_CODE_SEGMENT OFFSET */ + IDT[37].zero = 0; + IDT[37].type_attr = 0x8e; /* INTERRUPT_GATE */ + IDT[37].offset_higherbits = (irq5_address & 0xffff0000) >> 16; + + irq6_address = (unsigned long) irq6; + IDT[38].offset_lowerbits = irq6_address & 0xffff; + IDT[38].selector = 0x08; /* KERNEL_CODE_SEGMENT OFFSET */ + IDT[38].zero = 0; + IDT[38].type_attr = 0x8e; /* INTERRUPT_GATE */ + IDT[38].offset_higherbits = (irq6_address & 0xffff0000) >> 16; + + irq7_address = (unsigned long) irq7; + IDT[39].offset_lowerbits = irq7_address & 0xffff; + IDT[39].selector = 0x08; /* KERNEL_CODE_SEGMENT OFFSET */ + IDT[39].zero = 0; + IDT[39].type_attr = 0x8e; /* INTERRUPT_GATE */ + IDT[39].offset_higherbits = (irq7_address & 0xffff0000) >> 16; + + irq0_address = (unsigned long) irq0; + IDT[40].offset_lowerbits = irq0_address & 0xffff; + IDT[40].selector = 0x08; /* KERNEL_CODE_SEGMENT OFFSET */ + IDT[40].zero = 0; + IDT[40].type_attr = 0x8e; /* INTERRUPT_GATE */ + IDT[40].offset_higherbits = (irq0_address & 0xffff0000) >> 16; + + irq8_address = (unsigned long) irq8; + IDT[41].offset_lowerbits = irq8_address & 0xffff; + IDT[41].selector = 0x08; /* KERNEL_CODE_SEGMENT OFFSET */ + IDT[41].zero = 0; + IDT[41].type_attr = 0x8e; /* INTERRUPT_GATE */ + IDT[41].offset_higherbits = (irq8_address & 0xffff0000) >> 16; + + irq0_address = (unsigned long) irq0; + IDT[42].offset_lowerbits = irq0_address & 0xffff; + IDT[42].selector = 0x08; /* KERNEL_CODE_SEGMENT OFFSET */ + IDT[42].zero = 0; + IDT[42].type_attr = 0x8e; /* INTERRUPT_GATE */ + IDT[42].offset_higherbits = (irq0_address & 0xffff0000) >> 16; + + irq9_address = (unsigned long) irq9; + IDT[43].offset_lowerbits = irq9_address & 0xffff; + IDT[43].selector = 0x08; /* KERNEL_CODE_SEGMENT OFFSET */ + IDT[43].zero = 0; + IDT[43].type_attr = 0x8e; /* INTERRUPT_GATE */ + IDT[43].offset_higherbits = (irq9_address & 0xffff0000) >> 16; + + irq10_address = (unsigned long) irq10; + IDT[44].offset_lowerbits = irq10_address & 0xffff; + IDT[44].selector = 0x08; /* KERNEL_CODE_SEGMENT OFFSET */ + IDT[44].zero = 0; + IDT[44].type_attr = 0x8e; /* INTERRUPT_GATE */ + IDT[44].offset_higherbits = (irq10_address & 0xffff0000) >> 16; + + irq11_address = (unsigned long) irq11; + IDT[45].offset_lowerbits = irq11_address & 0xffff; + IDT[45].selector = 0x08; /* KERNEL_CODE_SEGMENT OFFSET */ + IDT[45].zero = 0; + IDT[45].type_attr = 0x8e; /* INTERRUPT_GATE */ + IDT[45].offset_higherbits = (irq11_address & 0xffff0000) >> 16; + + irq12_address = (unsigned long) irq12; + IDT[46].offset_lowerbits = irq12_address & 0xffff; + IDT[46].selector = 0x08; /* KERNEL_CODE_SEGMENT OFFSET */ + IDT[46].zero = 0; + IDT[46].type_attr = 0x8e; /* INTERRUPT_GATE */ + IDT[46].offset_higherbits = (irq12_address & 0xffff0000) >> 16; + + irq13_address = (unsigned long) irq13; + IDT[47].offset_lowerbits = irq13_address & 0xffff; + IDT[47].selector = 0x08; /* KERNEL_CODE_SEGMENT OFFSET */ + IDT[47].zero = 0; + IDT[47].type_attr = 0x8e; /* INTERRUPT_GATE */ + IDT[47].offset_higherbits = (irq13_address & 0xffff0000) >> 16; + + irq14_address = (unsigned long) irq14; + IDT[48].offset_lowerbits = irq14_address & 0xffff; + IDT[48].selector = 0x08; /* KERNEL_CODE_SEGMENT OFFSET */ + IDT[48].zero = 0; + IDT[48].type_attr = 0x8e; /* INTERRUPT_GATE */ + IDT[48].offset_higherbits = (irq14_address & 0xffff0000) >> 16; + + irq15_address = (unsigned long) irq15; + IDT[49].offset_lowerbits = irq15_address & 0xffff; + IDT[49].selector = 0x08; /* KERNEL_CODE_SEGMENT OFFSET */ + IDT[49].zero = 0; + IDT[49].type_attr = 0x8e; /* INTERRUPT_GATE */ + IDT[49].offset_higherbits = (irq15_address & 0xffff0000) >> 16; + + /* Fill IDT descriptor */ + idt_address = (unsigned long)IDT; + idt_ptr[0] = (sizeof(struct IDT_entry) * 256) + ((idt_address & 0xffff) << 16); + idt_ptr[1] = idt_address >> 16; + + load_idt(idt_ptr); +} + +/* Programmable Interrupt Timer Interrupt */ +void irq0_handler(void) { + outb(0x20, 0x20); /* End of interrupt */ +} + +/* Keyboard Interrupt */ +void irq1_handler(void) { + outb(0x20, 0x20); +} + +/* Cascade. Can probably be ignored. */ +void irq2_handler(void) { + outb(0x20, 0x20); +} + +/* COM2 (Serial Port) */ +void irq3_handler(void) { + outb(0x20, 0x20); +} + +/* COM1 (Serial Port) */ +void irq4_handler(void) { + outb(0x20, 0x20); +} + +/* LPT2 (Parallel Port) */ +void irq5_handler(void) { + outb(0x20, 0x20); +} + +/* Floppy Disk */ +void irq6_handler(void) { + outb(0x20, 0x20); +} + +/* LPT1 (Parallel Port)/Primary PIC Spurious Interrupts */ +void irq7_handler(void) { + outb(0x20, 0x20); /* Don't send this for spurious interrupts */ +} + +/* CMOS RTC */ +void irq8_handler(void) { + outb(0xA0, 0x20); + outb(0x20, 0x20); +} + +/* Peripherals/Legacy SCSI/NIC */ +void irq9_handler(void) { + outb(0xA0, 0x20); + outb(0x20, 0x20); +} + +/* Peripherals/SCSI/NIC */ +void irq10_handler(void) { + outb(0xA0, 0x20); + outb(0x20, 0x20); +} + +/* Peripherals/SCSI/NIC */ +void irq11_handler(void) { + outb(0xA0, 0x20); + outb(0x20, 0x20); +} + +/* PS2 Mouse */ +void irq12_handler(void) { + outb(0xA0, 0x20); + outb(0x20, 0x20); +} + +/* FPU/Coprocessor/Inter-processor */ +void irq13_handler(void) { + outb(0xA0, 0x20); + outb(0x20, 0x20); +} + +/* Primary ATA Hard Drive */ +void irq14_handler(void) { + outb(0xA0, 0x20); + outb(0x20, 0x20); +} + +/* Secondary ATA Hard Drive/Secondary PIC Spurious Interrupt */ +void irq15_handler(void) { + outb(0xA0, 0x20); + outb(0x20, 0x20); +} diff --git a/include/kernel/interrupt.h b/include/kernel/interrupt.h new file mode 100644 index 0000000..781a599 --- /dev/null +++ b/include/kernel/interrupt.h @@ -0,0 +1,16 @@ +#ifndef _KERNEL_INTERRUPT +#define _KERNEL_INTERRUPT + +struct IDT_entry { + unsigned short int offset_lowerbits; + unsigned short int selector; + unsigned char zero; + unsigned char type_attr; + unsigned short int offset_higherbits; +}; + +struct IDT_entry IDT[256]; + +void idt_init(void); + +#endif