Implemented irq and isr
This commit is contained in:
parent
aea8d99518
commit
59d7b06117
|
@ -0,0 +1,98 @@
|
|||
#include "i386/irq.h"
|
||||
#include "i386/pic.h"
|
||||
|
||||
#include "i386/idt.h"
|
||||
#include "i386/context.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
/* Extern symbol defined in idt.c */
|
||||
|
||||
extern idt_entry_t idt_entries[256];
|
||||
|
||||
/* External Interrupt Service Routines. */
|
||||
|
||||
extern void irq0();
|
||||
extern void irq1();
|
||||
extern void irq2();
|
||||
extern void irq3();
|
||||
extern void irq4();
|
||||
extern void irq5();
|
||||
extern void irq6();
|
||||
extern void irq7();
|
||||
extern void irq8();
|
||||
extern void irq9();
|
||||
extern void irq10();
|
||||
extern void irq11();
|
||||
extern void irq12();
|
||||
extern void irq13();
|
||||
extern void irq14();
|
||||
extern void irq15();
|
||||
|
||||
/*
|
||||
* irq_init:
|
||||
* ---------
|
||||
*
|
||||
* Remap PIC pins to match the IRQ starting from 32.
|
||||
*
|
||||
*/
|
||||
|
||||
void irq_init(void) {
|
||||
|
||||
pic_remap(IRQ0, IRQ8);
|
||||
|
||||
idt_entries[32] = idt_set_gate( (uint32_t) irq0, 0x08, 0x8E);
|
||||
idt_entries[33] = idt_set_gate( (uint32_t) irq1, 0x08, 0x8E);
|
||||
idt_entries[34] = idt_set_gate( (uint32_t) irq2, 0x08, 0x8E);
|
||||
idt_entries[35] = idt_set_gate( (uint32_t) irq3, 0x08, 0x8E);
|
||||
idt_entries[36] = idt_set_gate( (uint32_t) irq4, 0x08, 0x8E);
|
||||
idt_entries[37] = idt_set_gate( (uint32_t) irq5, 0x08, 0x8E);
|
||||
idt_entries[38] = idt_set_gate( (uint32_t) irq6, 0x08, 0x8E);
|
||||
idt_entries[39] = idt_set_gate( (uint32_t) irq7, 0x08, 0x8E);
|
||||
idt_entries[40] = idt_set_gate( (uint32_t) irq8, 0x08, 0x8E);
|
||||
idt_entries[41] = idt_set_gate( (uint32_t) irq9, 0x08, 0x8E);
|
||||
idt_entries[42] = idt_set_gate( (uint32_t) irq10, 0x08, 0x8E);
|
||||
idt_entries[43] = idt_set_gate( (uint32_t) irq11, 0x08, 0x8E);
|
||||
idt_entries[44] = idt_set_gate( (uint32_t) irq12, 0x08, 0x8E);
|
||||
idt_entries[45] = idt_set_gate( (uint32_t) irq13, 0x08, 0x8E);
|
||||
idt_entries[46] = idt_set_gate( (uint32_t) irq14, 0x08, 0x8E);
|
||||
idt_entries[47] = idt_set_gate( (uint32_t) irq15, 0x08, 0x8E);
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* register_irq:
|
||||
* -------------
|
||||
*
|
||||
* Register a handler in intrpt_handlers array.
|
||||
*
|
||||
*/
|
||||
|
||||
irq_t intrpt_handlers[256];
|
||||
|
||||
void register_irq(uint8_t irq_no, irq_t handler) {
|
||||
|
||||
intrpt_handlers[irq_no] = handler;
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* irq_handler:
|
||||
* ------------
|
||||
*
|
||||
* Using the intrpt number present in context, choose the appropiate handler.
|
||||
* The routine should also send and EOI signal to PIC.
|
||||
*
|
||||
*/
|
||||
|
||||
void irq_handler(context_t context) {
|
||||
|
||||
pic_send_eoi(context.int_no);
|
||||
|
||||
irq_t handler = intrpt_handlers[context.int_no];
|
||||
if (handler)
|
||||
handler(context);
|
||||
else
|
||||
puts("Unhandled interrupt");
|
||||
|
||||
}
|
|
@ -0,0 +1,66 @@
|
|||
.extern irq_handler
|
||||
|
||||
/* Macro that defines an IRQ gate using the irq number and its corresponding IDT index. */
|
||||
|
||||
.macro IRQ _irq_nr, _idt_nr
|
||||
.global irq\_irq_nr
|
||||
irq\_irq_nr:
|
||||
cli
|
||||
push $0x00
|
||||
push $\_idt_nr
|
||||
jmp irq_common_stub
|
||||
.endm
|
||||
|
||||
/* Define the gates. */
|
||||
|
||||
IRQ 0, 32
|
||||
IRQ 1, 33
|
||||
IRQ 2, 34
|
||||
IRQ 3, 35
|
||||
IRQ 4, 36
|
||||
IRQ 5, 37
|
||||
IRQ 6, 38
|
||||
IRQ 7, 39
|
||||
IRQ 8, 40
|
||||
IRQ 9, 41
|
||||
IRQ 10, 42
|
||||
IRQ 11, 43
|
||||
IRQ 12, 44
|
||||
IRQ 13, 45
|
||||
IRQ 14, 46
|
||||
IRQ 15, 47
|
||||
|
||||
/*
|
||||
* Common stub that saves the context on the stack and restores it after
|
||||
* the handler is done
|
||||
*
|
||||
* To see a more comprehensibile layout of the data saved on the stack, please
|
||||
* check context.h
|
||||
*
|
||||
*/
|
||||
|
||||
irq_common_stub:
|
||||
|
||||
pusha
|
||||
|
||||
mov %ds, %ax
|
||||
push %eax
|
||||
|
||||
mov $0x10, %ax
|
||||
mov %ax, %ds
|
||||
mov %ax, %es
|
||||
mov %ax, %fs
|
||||
mov %ax, %gs
|
||||
|
||||
call irq_handler
|
||||
|
||||
pop %ebx
|
||||
mov %bx, %ds
|
||||
mov %bx, %es
|
||||
mov %bx, %fs
|
||||
mov %bx, %gs
|
||||
|
||||
popa
|
||||
add $0x08, %esp
|
||||
sti
|
||||
iret
|
|
@ -0,0 +1,54 @@
|
|||
#include "i386/pic.h"
|
||||
#include "i386/irq.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
/*
|
||||
* pic_remap:
|
||||
* ----------
|
||||
*
|
||||
* Save the state of the data ports. Initialize the PICs, write the vector
|
||||
* offsets, tell the master PIC about the slave and inform the slave about
|
||||
* its identity; and set the PICs in 8086 mode.
|
||||
*
|
||||
*/
|
||||
|
||||
void pic_remap(uint8_t offset1, uint8_t offset2) {
|
||||
|
||||
uint8_t d1, d2;
|
||||
|
||||
d1 = inb(PIC1_DATA);
|
||||
d2 = inb(PIC2_DATA);
|
||||
|
||||
outb(PIC1_COMMAND, ICW1_INIT | ICW1_ICW4);
|
||||
outb(PIC2_COMMAND, ICW1_INIT | ICW1_ICW4);
|
||||
|
||||
outb(PIC1_DATA, offset1);
|
||||
outb(PIC2_DATA, offset2);
|
||||
|
||||
outb(PIC1_DATA, ICW3_SLAVE_IRQ);
|
||||
outb(PIC2_DATA, ICW3_SLAVE_ID);
|
||||
|
||||
outb(PIC1_DATA, ICW4_8086);
|
||||
outb(PIC2_DATA, ICW4_8086);
|
||||
|
||||
outb(PIC1_DATA, d1);
|
||||
outb(PIC2_DATA, d2);
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* pic_send_eoi:
|
||||
* -------------
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
void pic_send_eoi(uint8_t irq) {
|
||||
|
||||
if (irq >= IRQ8)
|
||||
outb(PIC2_COMMAND, PIC_EOI);
|
||||
|
||||
outb(PIC1_COMMAND, PIC_EOI);
|
||||
|
||||
}
|
|
@ -0,0 +1,143 @@
|
|||
#include "i386/isr.h"
|
||||
|
||||
#include "i386/idt.h"
|
||||
#include "i386/context.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
|
||||
/* Extern symbol defined in idt.c */
|
||||
|
||||
extern idt_entry_t idt_entries[256];
|
||||
|
||||
/* External Interrupt Service Routines. */
|
||||
|
||||
extern void isr0();
|
||||
extern void isr1();
|
||||
extern void isr2();
|
||||
extern void isr3();
|
||||
extern void isr4();
|
||||
extern void isr5();
|
||||
extern void isr6();
|
||||
extern void isr7();
|
||||
extern void isr8();
|
||||
extern void isr9();
|
||||
extern void isr10();
|
||||
extern void isr11();
|
||||
extern void isr12();
|
||||
extern void isr13();
|
||||
extern void isr14();
|
||||
extern void isr15();
|
||||
extern void isr16();
|
||||
extern void isr17();
|
||||
extern void isr18();
|
||||
extern void isr19();
|
||||
extern void isr20();
|
||||
extern void isr21();
|
||||
extern void isr22();
|
||||
extern void isr23();
|
||||
extern void isr24();
|
||||
extern void isr25();
|
||||
extern void isr26();
|
||||
extern void isr27();
|
||||
extern void isr28();
|
||||
extern void isr29();
|
||||
extern void isr30();
|
||||
extern void isr31();
|
||||
|
||||
/*
|
||||
* isr_init:
|
||||
* ---------
|
||||
*
|
||||
* Fill the first 32 entries in IDT.
|
||||
*
|
||||
*/
|
||||
|
||||
void isr_init(void) {
|
||||
|
||||
idt_entries[0] = idt_set_gate((uint32_t) isr0, 0x08, 0x8E);
|
||||
idt_entries[1] = idt_set_gate((uint32_t) isr1, 0x08, 0x8E);
|
||||
idt_entries[2] = idt_set_gate((uint32_t) isr2, 0x08, 0x8E);
|
||||
idt_entries[3] = idt_set_gate((uint32_t) isr3, 0x08, 0x8E);
|
||||
idt_entries[4] = idt_set_gate((uint32_t) isr4, 0x08, 0x8E);
|
||||
idt_entries[5] = idt_set_gate((uint32_t) isr5, 0x08, 0x8E);
|
||||
idt_entries[6] = idt_set_gate((uint32_t) isr6, 0x08, 0x8E);
|
||||
idt_entries[7] = idt_set_gate((uint32_t) isr7, 0x08, 0x8E);
|
||||
idt_entries[8] = idt_set_gate((uint32_t) isr8, 0x08, 0x8E);
|
||||
idt_entries[9] = idt_set_gate((uint32_t) isr9, 0x08, 0x8E);
|
||||
idt_entries[10] = idt_set_gate( (uint32_t) isr10, 0x08, 0x8E);
|
||||
idt_entries[11] = idt_set_gate( (uint32_t) isr11, 0x08, 0x8E);
|
||||
idt_entries[12] = idt_set_gate( (uint32_t) isr12, 0x08, 0x8E);
|
||||
idt_entries[13] = idt_set_gate( (uint32_t) isr13, 0x08, 0x8E);
|
||||
idt_entries[14] = idt_set_gate( (uint32_t) isr14, 0x08, 0x8E);
|
||||
idt_entries[15] = idt_set_gate( (uint32_t) isr15, 0x08, 0x8E);
|
||||
idt_entries[16] = idt_set_gate( (uint32_t) isr16, 0x08, 0x8E);
|
||||
idt_entries[17] = idt_set_gate( (uint32_t) isr17, 0x08, 0x8E);
|
||||
idt_entries[18] = idt_set_gate( (uint32_t) isr18, 0x08, 0x8E);
|
||||
idt_entries[19] = idt_set_gate( (uint32_t) isr19, 0x08, 0x8E);
|
||||
idt_entries[20] = idt_set_gate( (uint32_t) isr20, 0x08, 0x8E);
|
||||
idt_entries[21] = idt_set_gate( (uint32_t) isr21, 0x08, 0x8E);
|
||||
idt_entries[22] = idt_set_gate( (uint32_t) isr22, 0x08, 0x8E);
|
||||
idt_entries[23] = idt_set_gate( (uint32_t) isr23, 0x08, 0x8E);
|
||||
idt_entries[24] = idt_set_gate( (uint32_t) isr24, 0x08, 0x8E);
|
||||
idt_entries[25] = idt_set_gate( (uint32_t) isr25, 0x08, 0x8E);
|
||||
idt_entries[26] = idt_set_gate( (uint32_t) isr26, 0x08, 0x8E);
|
||||
idt_entries[27] = idt_set_gate( (uint32_t) isr27, 0x08, 0x8E);
|
||||
idt_entries[28] = idt_set_gate( (uint32_t) isr28, 0x08, 0x8E);
|
||||
idt_entries[29] = idt_set_gate( (uint32_t) isr29, 0x08, 0x8E);
|
||||
idt_entries[30] = idt_set_gate( (uint32_t) isr30, 0x08, 0x8E);
|
||||
idt_entries[31] = idt_set_gate( (uint32_t) isr31, 0x08, 0x8E);
|
||||
|
||||
}
|
||||
|
||||
/* Exception messages for unhandled faults. */
|
||||
|
||||
char *exception_messages[] = {
|
||||
"Division by zero",
|
||||
"Debug",
|
||||
"Non-maskable interrupt",
|
||||
"Breakpoint",
|
||||
"Detected overflow",
|
||||
"Out-of-bounds",
|
||||
"Invalid opcode",
|
||||
"No coprocessor",
|
||||
"Double fault",
|
||||
"Coprocessor segment overrun",
|
||||
"Bad TSS",
|
||||
"Segment not present",
|
||||
"Stack fault",
|
||||
"General protection fault",
|
||||
"Page fault",
|
||||
"Unknown interrupt",
|
||||
"Coprocessor fault",
|
||||
"Alignment check",
|
||||
"Machine check",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved"
|
||||
};
|
||||
|
||||
/* isr_handler:
|
||||
* Handles an incomming request by calling the appropiate handler or printing
|
||||
* an exception message.
|
||||
*
|
||||
* @param context - the context of the caller
|
||||
*
|
||||
*/
|
||||
|
||||
void isr_handler(context_t context) {
|
||||
|
||||
printf("Unhandled exception: %s\n", exception_messages[context.int_no]);
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,89 @@
|
|||
.extern isr_handler
|
||||
|
||||
/* Macros that define the entry point in ISRs with and without an error code. */
|
||||
|
||||
.macro ISR_NO_ERRCODE _isr_nr
|
||||
.global isr\_isr_nr
|
||||
isr\_isr_nr:
|
||||
cli
|
||||
push $0x00
|
||||
push $\_isr_nr
|
||||
jmp isr_common_stub
|
||||
.endm
|
||||
|
||||
.macro ISR_ERRCODE _isr_nr
|
||||
.global isr\_isr_nr
|
||||
isr\_isr_nr:
|
||||
cli
|
||||
push $\_isr_nr
|
||||
jmp isr_common_stub
|
||||
.endm
|
||||
|
||||
/* Expandation of the above mentioned macros. */
|
||||
|
||||
ISR_NO_ERRCODE 0
|
||||
ISR_NO_ERRCODE 1
|
||||
ISR_NO_ERRCODE 2
|
||||
ISR_NO_ERRCODE 3
|
||||
ISR_NO_ERRCODE 4
|
||||
ISR_NO_ERRCODE 5
|
||||
ISR_NO_ERRCODE 6
|
||||
ISR_NO_ERRCODE 7
|
||||
ISR_ERRCODE 8
|
||||
ISR_NO_ERRCODE 9
|
||||
ISR_ERRCODE 10
|
||||
ISR_ERRCODE 11
|
||||
ISR_ERRCODE 12
|
||||
ISR_ERRCODE 13
|
||||
ISR_ERRCODE 14
|
||||
ISR_NO_ERRCODE 15
|
||||
ISR_NO_ERRCODE 16
|
||||
ISR_NO_ERRCODE 17
|
||||
ISR_NO_ERRCODE 18
|
||||
ISR_NO_ERRCODE 19
|
||||
ISR_NO_ERRCODE 20
|
||||
ISR_NO_ERRCODE 21
|
||||
ISR_NO_ERRCODE 22
|
||||
ISR_NO_ERRCODE 23
|
||||
ISR_NO_ERRCODE 24
|
||||
ISR_NO_ERRCODE 25
|
||||
ISR_NO_ERRCODE 26
|
||||
ISR_NO_ERRCODE 27
|
||||
ISR_NO_ERRCODE 28
|
||||
ISR_NO_ERRCODE 29
|
||||
ISR_NO_ERRCODE 30
|
||||
ISR_NO_ERRCODE 31
|
||||
|
||||
/*
|
||||
* Stub for ISRs. It must push the context on the stack and change the PL.
|
||||
* After the isr_handler was called the context will be restored and the
|
||||
* error code and the request number will be cleared from the stack.
|
||||
*
|
||||
*/
|
||||
|
||||
isr_common_stub:
|
||||
|
||||
pusha
|
||||
|
||||
mov %ds, %ax
|
||||
push %eax
|
||||
|
||||
mov $0x10, %ax
|
||||
mov %ax, %ds
|
||||
mov %ax, %es
|
||||
mov %ax, %fs
|
||||
mov %ax, %gs
|
||||
|
||||
call isr_handler
|
||||
|
||||
pop %eax
|
||||
mov %ax, %ds
|
||||
mov %ax, %es
|
||||
mov %ax, %fs
|
||||
mov %ax, %gs
|
||||
|
||||
popa
|
||||
add $0x08, %esp
|
||||
|
||||
sti
|
||||
iret
|
Loading…
Reference in New Issue