104 lines
2.7 KiB
C
104 lines
2.7 KiB
C
#include <stddef.h>
|
|
#include <stdint.h>
|
|
#include <exec/hal.h>
|
|
#include <exec/task.h>
|
|
#include <exec/irq.h>
|
|
|
|
#pragma pack(push, 1)
|
|
struct Idtr {
|
|
uint16_t limit;
|
|
uintptr_t base;
|
|
};
|
|
|
|
struct IdtEntry {
|
|
uint16_t offset_low;
|
|
uint16_t selector;
|
|
uint8_t zero;
|
|
uint8_t type_attr;
|
|
uint16_t offset_high;
|
|
};
|
|
|
|
struct InitialContext {
|
|
uint32_t eflags; /* PUSHF / POPF */
|
|
uint32_t edi, esi, ebp, esp, ebx, edx, ecx, eax; /* PUSHA / POPA */
|
|
uint32_t eip, final_eip;
|
|
};
|
|
|
|
struct IRQFrame {
|
|
uint32_t irq, eflags, cs, eip;
|
|
};
|
|
#pragma pack(pop)
|
|
|
|
struct Idtr idtr;
|
|
struct IdtEntry idt[256];
|
|
|
|
extern void irq0(void);
|
|
extern void irq1(void);
|
|
extern void irq2(void);
|
|
extern void irq3(void);
|
|
extern void irq4(void);
|
|
extern void irq5(void);
|
|
extern void irq6(void);
|
|
extern void irq7(void);
|
|
extern void irq8(void);
|
|
extern void irq9(void);
|
|
extern void irq10(void);
|
|
extern void irq11(void);
|
|
extern void irq12(void);
|
|
extern void irq13(void);
|
|
extern void irq14(void);
|
|
extern void irq15(void);
|
|
|
|
void IDT32_SetEntry(int vector, uintptr_t handler) {
|
|
idt[vector].offset_low = handler & 0xFFFF;
|
|
idt[vector].selector = 0x08; // Code segment selector
|
|
idt[vector].zero = 0;
|
|
idt[vector].type_attr = 0x8E; // Interrupt gate, present
|
|
idt[vector].offset_high = (handler >> 16) & 0xFFFF;
|
|
}
|
|
|
|
void IDT32_Initialize(void) {
|
|
idtr.base = (uintptr_t)&idt;
|
|
idtr.limit = sizeof(idt) - 1;
|
|
|
|
IDT32_SetEntry(32, (uintptr_t)&irq0);
|
|
IDT32_SetEntry(33, (uintptr_t)&irq1);
|
|
IDT32_SetEntry(34, (uintptr_t)&irq2);
|
|
IDT32_SetEntry(35, (uintptr_t)&irq3);
|
|
IDT32_SetEntry(36, (uintptr_t)&irq4);
|
|
IDT32_SetEntry(37, (uintptr_t)&irq5);
|
|
IDT32_SetEntry(38, (uintptr_t)&irq6);
|
|
IDT32_SetEntry(39, (uintptr_t)&irq7);
|
|
IDT32_SetEntry(40, (uintptr_t)&irq8);
|
|
IDT32_SetEntry(41, (uintptr_t)&irq9);
|
|
IDT32_SetEntry(42, (uintptr_t)&irq10);
|
|
IDT32_SetEntry(43, (uintptr_t)&irq11);
|
|
IDT32_SetEntry(44, (uintptr_t)&irq12);
|
|
IDT32_SetEntry(45, (uintptr_t)&irq13);
|
|
IDT32_SetEntry(45, (uintptr_t)&irq14);
|
|
IDT32_SetEntry(45, (uintptr_t)&irq15);
|
|
|
|
asm("lidt %0" : : "m"(idtr));
|
|
}
|
|
|
|
__attribute__((interrupt))
|
|
void X86_CommonIRQHandler(struct IRQFrame *frame, int irq) {
|
|
if (irq) {
|
|
InterruptDispatch(irq);
|
|
HalAcknowledgeInterrupt(irq);
|
|
} else {
|
|
/* PIT */
|
|
execTicks++;
|
|
HalAcknowledgeInterrupt(irq);
|
|
Yield();
|
|
}
|
|
}
|
|
|
|
void X86_SetupTask(struct Task *task, uintptr_t initial_pc, uintptr_t final_pc) {
|
|
struct InitialContext *ictx;
|
|
task->sp -= sizeof(struct InitialContext);
|
|
ictx = (struct InitialContext *)task->sp;
|
|
ictx->eip = initial_pc;
|
|
ictx->final_eip = final_pc;
|
|
ictx->eflags = 0x202;
|
|
} |