Implemented irq and isr

This commit is contained in:
lucic71 2022-06-28 19:40:51 +03:00
parent aea8d99518
commit 59d7b06117
5 changed files with 450 additions and 0 deletions

View File

@ -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");
}

View File

@ -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

View File

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

143
kernel/arch/i386/isr/isr.c Normal file
View File

@ -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]);
}

View File

@ -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