2011-02-22 17:09:58 +00:00
|
|
|
#include "Tier0/interrupts.h"
|
|
|
|
#include "Tier0/paging.h"
|
|
|
|
#include "Tier0/kstdio.h"
|
|
|
|
#include "Tier0/pic.h"
|
2012-10-29 13:57:48 +00:00
|
|
|
#include "preprocessor_hacks.h"
|
2011-02-22 17:09:58 +00:00
|
|
|
|
2012-04-21 16:55:29 +00:00
|
|
|
struct {
|
|
|
|
// IDT
|
|
|
|
T_IDT_PTR IDTPointer;
|
|
|
|
T_IDT_ENTRY IDTEntries[256];
|
|
|
|
T_ISR_STUB ISRStubs[256];
|
2011-02-22 17:09:58 +00:00
|
|
|
|
2012-05-07 16:53:06 +00:00
|
|
|
} __attribute__((packed)) g_Interrupts;
|
2011-02-22 17:09:58 +00:00
|
|
|
|
2012-05-07 16:53:06 +00:00
|
|
|
void interrupts_lidt(void)
|
|
|
|
{
|
2012-07-20 22:41:03 +00:00
|
|
|
__asm__ __volatile__("movq %0, %%rax; lidt (%%rax)" : : "p"(&g_Interrupts.IDTPointer));
|
2012-05-07 16:53:06 +00:00
|
|
|
}
|
|
|
|
|
2011-02-22 17:09:58 +00:00
|
|
|
u8 interrupts_init_idt(void)
|
|
|
|
{
|
2012-04-21 18:32:02 +00:00
|
|
|
g_Interrupts.IDTPointer.Limit = 256 * 16;
|
2012-05-07 16:53:06 +00:00
|
|
|
g_Interrupts.IDTPointer.Base = (u64)g_Interrupts.IDTEntries;
|
|
|
|
kprintf("[i] Setting up IDT at 0x%x.\n", g_Interrupts.IDTEntries);
|
|
|
|
kprintf("[i] IDT Entry size %i bytes.\n", sizeof(T_IDT_ENTRY));
|
2011-02-22 17:09:58 +00:00
|
|
|
|
|
|
|
// Null those entries!
|
|
|
|
for (u16 i = 0; i < 256; i++)
|
|
|
|
{
|
|
|
|
// Maybe I should access the struct's members...
|
2012-05-07 16:53:06 +00:00
|
|
|
// Or i can just cast that to to u32's and null them.
|
2011-02-22 17:09:58 +00:00
|
|
|
// This will set the Present flag to 0 either way
|
2012-04-21 18:32:02 +00:00
|
|
|
*((u64 *)(&g_Interrupts.IDTEntries[i])) = 0;
|
|
|
|
*(((u64 *)(&g_Interrupts.IDTEntries[i]) + 1)) = 0;
|
2011-02-22 17:09:58 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
2012-05-07 16:53:06 +00:00
|
|
|
void interrupts_create_stub(T_ISR_STUB *Destination, u64 Address)
|
2011-02-22 17:09:58 +00:00
|
|
|
{
|
2012-05-07 16:53:06 +00:00
|
|
|
Destination->Code1 = 0x57565552515350fa;
|
|
|
|
Destination->Code2 = 0x5341524151415041;
|
|
|
|
Destination->Code3 = 0x5741564155415441;
|
|
|
|
Destination->Code4 = 0xb848;
|
2011-02-22 17:09:58 +00:00
|
|
|
Destination->Handler = Address; // Address
|
2012-05-07 16:53:06 +00:00
|
|
|
Destination->Code5 = 0x5d415e415f41d0ff;
|
|
|
|
Destination->Code6 = 0x59415a415b415c41;
|
|
|
|
Destination->Code7 = 0x5b595a5d5e5f5841;
|
|
|
|
Destination->Code8 = 0xcf48fb58;
|
2011-02-22 17:09:58 +00:00
|
|
|
}
|
2012-05-07 16:53:06 +00:00
|
|
|
/*
|
2011-02-22 17:09:58 +00:00
|
|
|
void interrupts_setup_irq(u8 IRQ, void *Handler)
|
|
|
|
{
|
|
|
|
if (g_interrupts_chip != E_INTERRUPTS_CHIP_PIC)
|
|
|
|
{
|
|
|
|
kprintf("[e] Sorry, but I only do PIC-based interrupts for now :(.\n");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
u8 Interrupt = IRQ + PIC_IRQ_START;
|
2011-02-23 03:12:36 +00:00
|
|
|
kprintf("[i] New handler for IRQ %i (Interrupt %i).\n", IRQ, Interrupt);
|
2011-02-22 17:09:58 +00:00
|
|
|
interrupts_setup_isr(Interrupt, Handler, E_INTERRUPTS_RING0);
|
|
|
|
|
|
|
|
// We also need to set the IRQ mask
|
|
|
|
pic_unmask_irq(IRQ);
|
|
|
|
}
|
|
|
|
|
|
|
|
void interrupts_dump_idt_ptr(void)
|
|
|
|
{
|
|
|
|
kprintf("[i] IDT Pointer structure:\n");
|
|
|
|
kprintf(" Base: 0x%x.\n", g_idt_ptr.Base);
|
|
|
|
kprintf(" Limit: 0x%x.\n", g_idt_ptr.Limit);
|
2012-05-07 16:53:06 +00:00
|
|
|
}*/
|
2011-02-22 17:09:58 +00:00
|
|
|
|
|
|
|
void interrupts_dump_idt_entry(u8 Interrupt)
|
|
|
|
{
|
2012-05-07 16:53:06 +00:00
|
|
|
kprintf("[i] IDT Entry for interrupt %x, %x:\n", Interrupt, &g_Interrupts.IDTEntries[Interrupt]);
|
|
|
|
T_IDT_ENTRY Entry = g_Interrupts.IDTEntries[Interrupt];
|
|
|
|
kprintf(" Offset: 0x%x.\n", (u64 )((u64)Entry.OffsetHigh << 32) + ((u64)Entry.OffsetMiddle << 16) + (u64)Entry.OffsetLow);
|
2011-02-22 17:09:58 +00:00
|
|
|
kprintf(" Selector: %u.\n", Entry.Selector);
|
2012-05-07 16:53:06 +00:00
|
|
|
kprintf(" P: %u.\n", Entry.Present);
|
|
|
|
kprintf(" DPL: %u.\n", Entry.DPL);
|
|
|
|
kprintf(" S: %u.\n", Entry.Selector);
|
|
|
|
kprintf(" Gate type: %u.\n", Entry.Type);
|
2011-02-22 17:09:58 +00:00
|
|
|
}
|
|
|
|
|
2011-03-13 14:18:08 +00:00
|
|
|
void interrupts_setup_isr_raw(u8 Interrupt, void *ASMHandler, \
|
|
|
|
T_INTERRUPTS_RING Ring)
|
2011-02-22 17:09:58 +00:00
|
|
|
{
|
2012-05-07 16:53:06 +00:00
|
|
|
u64 uASMHandler = (u64)ASMHandler;
|
|
|
|
g_Interrupts.IDTEntries[Interrupt].OffsetLow = uASMHandler & 0xFFFF;
|
|
|
|
g_Interrupts.IDTEntries[Interrupt].OffsetMiddle = (uASMHandler >> 16) & 0xFFFF;
|
|
|
|
g_Interrupts.IDTEntries[Interrupt].OffsetHigh = uASMHandler >> 32;
|
|
|
|
|
|
|
|
g_Interrupts.IDTEntries[Interrupt].Selector = 0x18;
|
|
|
|
g_Interrupts.IDTEntries[Interrupt].Zero1 = 0;
|
|
|
|
g_Interrupts.IDTEntries[Interrupt].Zero2 = 0;
|
|
|
|
g_Interrupts.IDTEntries[Interrupt].DPL = Ring;
|
|
|
|
g_Interrupts.IDTEntries[Interrupt].Present = 1;
|
|
|
|
g_Interrupts.IDTEntries[Interrupt].Type = 0b1111;
|
2011-02-22 17:09:58 +00:00
|
|
|
}
|
|
|
|
|
2011-03-13 14:18:08 +00:00
|
|
|
void interrupts_setup_isr(u8 Interrupt, void *Handler, \
|
|
|
|
T_INTERRUPTS_RING Ring)
|
|
|
|
{
|
2012-05-07 16:53:06 +00:00
|
|
|
interrupts_create_stub(&g_Interrupts.ISRStubs[Interrupt], (u64)Handler);
|
2011-03-13 14:18:08 +00:00
|
|
|
|
2012-05-07 16:53:06 +00:00
|
|
|
u64 ASMHandler = (u64)&g_Interrupts.ISRStubs[Interrupt];
|
2011-03-13 14:18:08 +00:00
|
|
|
interrupts_setup_isr_raw(Interrupt, (void*)ASMHandler, Ring);
|
|
|
|
}
|
|
|
|
|
2012-05-07 16:53:06 +00:00
|
|
|
/*void interrupts_delete_isr(u8 Interrupt)
|
2011-04-02 14:46:31 +00:00
|
|
|
{
|
|
|
|
*((u32*)&g_idt_entries[Interrupt]) = 0;
|
|
|
|
}
|
2012-05-07 16:53:06 +00:00
|
|
|
*/
|
2012-10-29 13:57:48 +00:00
|
|
|
|
|
|
|
void interrupts_remap_pic(void)
|
|
|
|
{
|
|
|
|
// remap the PIC IRQ's to 0x20-0x27 and 0x28-0x2F
|
|
|
|
|
|
|
|
koutb(0x20, 0x11); // start initialization sequence
|
2012-10-29 17:59:09 +00:00
|
|
|
kio_wait();
|
2012-10-29 13:57:48 +00:00
|
|
|
koutb(0xA0, 0x11); // - " -
|
2012-10-29 17:59:09 +00:00
|
|
|
kio_wait();
|
2012-10-29 13:57:48 +00:00
|
|
|
|
|
|
|
koutb(0x21, 0x20); // master from 0x20
|
2012-10-29 17:59:09 +00:00
|
|
|
kio_wait();
|
2012-10-29 13:57:48 +00:00
|
|
|
koutb(0xA1, 0x28); // slave from 0x28
|
2012-10-29 17:59:09 +00:00
|
|
|
kio_wait();
|
2012-10-29 13:57:48 +00:00
|
|
|
koutb(0x21, 0x04); // slave PIC at IRQ2
|
2012-10-29 17:59:09 +00:00
|
|
|
kio_wait();
|
2012-10-29 13:57:48 +00:00
|
|
|
koutb(0xA1, 0x02); // cascade
|
2012-10-29 17:59:09 +00:00
|
|
|
kio_wait();
|
2012-10-29 13:57:48 +00:00
|
|
|
koutb(0x21, 0x01); // 8086 mode
|
2012-10-29 17:59:09 +00:00
|
|
|
kio_wait();
|
2012-10-29 13:57:48 +00:00
|
|
|
koutb(0xA1, 0x01); // 8086 mode
|
2012-10-29 17:59:09 +00:00
|
|
|
kio_wait();
|
|
|
|
|
|
|
|
// set masks to accept no IRQs
|
|
|
|
koutb(0x21, 0xFF);
|
|
|
|
kio_wait();
|
|
|
|
koutb(0xA1, 0xFF);
|
|
|
|
kio_wait();
|
|
|
|
}
|
|
|
|
|
|
|
|
void interrupts_eoi_pic(u8 IRQ)
|
|
|
|
{
|
|
|
|
if (IRQ > 7)
|
|
|
|
koutb(0xA0, 0x20);
|
2012-10-29 13:57:48 +00:00
|
|
|
|
2012-10-29 17:59:09 +00:00
|
|
|
koutb(0x20, 0x20);
|
2012-10-29 13:57:48 +00:00
|
|
|
}
|
|
|
|
|
2012-10-29 17:59:09 +00:00
|
|
|
#define GENERIC_IRQ_DEF(i) void interrupts_irq##i##_isr(void) { kprintf("[w] OOPS: Unhandled IRQ"#i"\n"); interrupts_eoi_pic(i); }
|
2012-10-29 13:57:48 +00:00
|
|
|
#define GENERIC_IRQ_BIND(i) interrupts_setup_isr(0x20 + i, (void *)interrupts_irq##i##_isr, E_INTERRUPTS_RING0)
|
|
|
|
PPHAX_DO16(GENERIC_IRQ_DEF);
|
|
|
|
|
2011-02-22 17:09:58 +00:00
|
|
|
void interrupts_init_simple(void)
|
|
|
|
{
|
|
|
|
interrupts_init_idt();
|
|
|
|
interrupts_lidt();
|
2012-10-29 13:57:48 +00:00
|
|
|
interrupts_remap_pic();
|
|
|
|
|
|
|
|
// generic IRQ handlers
|
|
|
|
PPHAX_DO16(GENERIC_IRQ_BIND);
|
|
|
|
|
|
|
|
// enable hardware interrupts
|
|
|
|
__asm__ __volatile__("sti;");
|
|
|
|
kprintf("[i] Hardware interrupts enabled.\n");
|
2011-02-22 17:09:58 +00:00
|
|
|
}
|
2012-05-07 16:53:06 +00:00
|
|
|
/*
|
2011-02-23 03:12:36 +00:00
|
|
|
void interrupts_irq_finish(u8 IRQ)
|
2011-02-22 17:09:58 +00:00
|
|
|
{
|
|
|
|
if (g_interrupts_chip == E_INTERRUPTS_CHIP_PIC)
|
|
|
|
pic_eoi(IRQ);
|
|
|
|
}
|
2011-08-27 23:16:17 +00:00
|
|
|
*/
|