Code: Select all
#include "icxxabi.h"
#include "Video.h"
#include "Disk.h"
#include "PageManager.h"
#include "MemoryManager.h"
#include "HeapIndexItem.h"
#include "PCIConfigHeaderManager.h"
#include "new.h"
#include "E1000.h"
#include "rtl8139.h"
/*
* Interrupt Descriptor Structure
*/
#define IDT_SIZE 256
#define MAIN_FILE
#include "globals.h"
char exception_messages[32][64] =
{
"Division By Zero",
"Debug",
"Non Maskable Interrupt",
"Breakpoint Exception",
"Into Detected Overflow Exception",
"Out of Bounds Exception",
"Invalid Opcode Exception",
"No Coprocessor Exception",
"Double Fault Exception",
"Coprocessor Segment Overrun Exception",
"Bad TSS Exception",
"Segment Not Present Exception",
"Stack Fault Exception",
"General Protection Fault Exception",
"Page Fault Exception",
"Unknown Interrupt Exception",
"Coprocessor Fault Exception",
"Alignment Check Exception (486+)",
"Machine Check Exception (Pentium/586+)",
"Reserved Exceptions",
"Reserved Exceptions",
"Reserved Exceptions",
"Reserved Exceptions",
"Reserved Exceptions",
"Reserved Exceptions",
"Reserved Exceptions",
"Reserved Exceptions",
"Reserved Exceptions",
"Reserved Exceptions",
"Reserved Exceptions",
"Reserved Exceptions",
"Reserved Exceptions"
};
char kbdus[128] =
{
0, 27, '1', '2', '3', '4', '5', '6', '7', '8', /* 9 */
'9', '0', '-', '=', '\b', /* Backspace */
'\t', /* Tab */
'q', 'w', 'e', 'r', /* 19 */
't', 'y', 'u', 'i', 'o', 'p', '[', ']', '\n', /* Enter key */
0, /* 29 - Control */
'a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';', /* 39 */
'\'', '`', 0, /* Left shift */
'\\', 'z', 'x', 'c', 'v', 'b', 'n', /* 49 */
'm', ',', '.', '/', 0, /* Right shift */
'*',
0, /* Alt */
' ', /* Space bar */
0, /* Caps lock */
0, /* 59 - F1 key ... > */
0, 0, 0, 0, 0, 0, 0, 0,
0, /* < ... F10 */
0, /* 69 - Num lock*/
0, /* Scroll Lock */
0, /* Home key */
0, /* Up Arrow */
0, /* Page Up */
'-',
0, /* Left Arrow */
0,
0, /* Right Arrow */
'+',
0, /* 79 - End key*/
0, /* Down Arrow */
0, /* Page Down */
0, /* Insert Key */
0, /* Delete Key */
0, 0, 0,
0, /* F11 Key */
0, /* F12 Key */
0, /* All other keys are undefined */
};
/*
* Prototypes
*/
void idtStart(void);
void idtSet(uint8_t, uint64_t, uint16_t, uint8_t);
static void gdt_set_gate(uint32_t num, uint32_t base, uint32_t limit, uint8_t access, uint8_t gran);
static void init_gdt();
#if defined(__cplusplus)
extern "C" /* Use C linkage for kernel_main. */
#else
extern
#endif
void isrHandler(struct registers *);
#if defined(__cplusplus)
extern "C" /* Use C linkage for kernel_main. */
#else
extern
#endif
void gdtInit(uint64_t p);
#if defined(__cplusplus)
extern "C" /* Use C linkage for kernel_main. */
#else
extern
#endif
void idtInit();
#if defined(__cplusplus)
extern "C"
#else
extern
#endif
void isr0();
#if defined(__cplusplus)
extern "C"
#else
extern
#endif
void isr1();
#if defined(__cplusplus)
extern "C"
#else
extern
#endif
void isr2();
#if defined(__cplusplus)
extern "C"
#else
extern
#endif
void isr3();
#if defined(__cplusplus)
extern "C"
#else
extern
#endif
void isr4();
#if defined(__cplusplus)
extern "C"
#else
extern
#endif
void isr5();
#if defined(__cplusplus)
extern "C"
#else
extern
#endif
void isr6();
#if defined(__cplusplus)
extern "C"
#else
extern
#endif
void isr7();
#if defined(__cplusplus)
extern "C"
#else
extern
#endif
void isr8();
#if defined(__cplusplus)
extern "C"
#else
extern
#endif
void isr9();
#if defined(__cplusplus)
extern "C"
#else
extern
#endif
void isr10();
#if defined(__cplusplus)
extern "C"
#else
extern
#endif
void isr11();
#if defined(__cplusplus)
extern "C"
#else
extern
#endif
void isr12();
#if defined(__cplusplus)
extern "C"
#else
extern
#endif
void isr13();
#if defined(__cplusplus)
extern "C"
#else
extern
#endif
void isr14();
#if defined(__cplusplus)
extern "C"
#else
extern
#endif
void isr15();
#if defined(__cplusplus)
extern "C"
#else
extern
#endif
void isr16();
#if defined(__cplusplus)
extern "C"
#else
extern
#endif
void isr17();
#if defined(__cplusplus)
extern "C"
#else
extern
#endif
void isr18();
#if defined(__cplusplus)
extern "C"
#else
extern
#endif
void isr19();
#if defined(__cplusplus)
extern "C"
#else
extern
#endif
void isr20();
#if defined(__cplusplus)
extern "C"
#else
extern
#endif
void isr21();
#if defined(__cplusplus)
extern "C"
#else
extern
#endif
void isr22();
#if defined(__cplusplus)
extern "C"
#else
extern
#endif
void isr23();
#if defined(__cplusplus)
extern "C"
#else
extern
#endif
void isr24();
#if defined(__cplusplus)
extern "C"
#else
extern
#endif
void isr25();
#if defined(__cplusplus)
extern "C"
#else
extern
#endif
void isr26();
#if defined(__cplusplus)
extern "C"
#else
extern
#endif
void isr27();
#if defined(__cplusplus)
extern "C"
#else
extern
#endif
void isr28();
#if defined(__cplusplus)
extern "C"
#else
extern
#endif
void isr29();
#if defined(__cplusplus)
extern "C"
#else
extern
#endif
void isr30();
#if defined(__cplusplus)
extern "C"
#endif
void isr31();
#if defined(__cplusplus)
extern "C"
#endif
void irq0 ();
#if defined(__cplusplus)
extern "C"
#endif
void irq1 ();
#if defined(__cplusplus)
extern "C"
#endif
void irq2 ();
#if defined(__cplusplus)
extern "C"
#endif
void irq3 ();
#if defined(__cplusplus)
extern "C"
#endif
void irq4 ();
#if defined(__cplusplus)
extern "C"
#endif
void irq5 ();
#if defined(__cplusplus)
extern "C"
#endif
void irq6 ();
#if defined(__cplusplus)
extern "C"
#endif
void irq7 ();
#if defined(__cplusplus)
extern "C"
#endif
void irq8 ();
#if defined(__cplusplus)
extern "C"
#endif
void irq9 ();
#if defined(__cplusplus)
extern "C"
#endif
void irq10();
#if defined(__cplusplus)
extern "C"
#endif
void irq11();
#if defined(__cplusplus)
extern "C"
#endif
void irq12();
#if defined(__cplusplus)
extern "C"
#endif
void irq13();
#if defined(__cplusplus)
extern "C"
#endif
void irq14();
#if defined(__cplusplus)
extern "C"
#endif
void irq15();
/* Setup Table and Pointer */
idtEntry idt[IDT_SIZE];
idtPointer idtP;
void IRQ_set_mask(unsigned char IRQline) {
uint16_t port;
uint8_t value;
if(IRQline < 8) {
port = PIC1_DATA;
} else {
port = PIC2_DATA;
IRQline -= 8;
}
value = Ports::inportb(port) | (1 << IRQline);
Ports::outportb(port, value);
}
void IRQ_clear_mask(unsigned char IRQline) {
uint16_t port;
uint8_t value;
if(IRQline < 8) {
port = PIC1_DATA;
} else {
port = PIC2_DATA;
IRQline -= 8;
}
value = Ports::inportb(port) & ~(1 << IRQline);
Ports::outportb(port, value);
}
void register_interrupt_handler(uint8_t n, isr_t handler)
{
interrupt_handlers[n] = handler;
if ( n >= IRQ0)
IRQ_clear_mask(n-IRQ0);
}
void idtStart(void) {
/* Set IDT Pointer */
idtP.limit = (sizeof(idtEntry) * IDT_SIZE) - 1;
idtP.base = (uint64_t)&idt;
/* Clear Memory for IDT's */
Utils::memset((uint8_t *)&idt, 0, sizeof(idtEntry) * IDT_SIZE);
Utils::memset((uint8_t *)&interrupt_handlers, 0, sizeof(isr_t)*256);
Ports::outportb(0x20, 0x11);
Ports::outportb(0xA0, 0x11);
Ports::outportb(0x21, 0x20);
Ports::outportb(0xA1, 0x28);
Ports::outportb(0x21, 0x04);
Ports::outportb(0xA1, 0x02);
Ports::outportb(0x21, 0x01);
Ports::outportb(0xA1, 0x01);
Ports::outportb(0x21, 0x0);
Ports::outportb(0xA1, 0x0);
for ( unsigned char c = 0 ; c < 16 ; c++)
IRQ_set_mask(c);
/* Set IDT Gates */
idtSet(0, (uint64_t)isr0, 0x08, 0x8E);
idtSet(1, (uint64_t)isr1, 0x08, 0x8E);
idtSet(2, (uint64_t)isr2, 0x08, 0x8E);
idtSet(3, (uint64_t)isr3, 0x08, 0x8E);
idtSet(4, (uint64_t)isr4, 0x08, 0x8E);
idtSet(5, (uint64_t)isr5, 0x08, 0x8E);
idtSet(6, (uint64_t)isr6, 0x08, 0x8E);
idtSet(7, (uint64_t)isr7, 0x08, 0x8E);
idtSet(8, (uint64_t)isr8, 0x08, 0x8E);
idtSet(9, (uint64_t)isr9, 0x08, 0x8E);
idtSet(10, (uint64_t)isr10, 0x08, 0x8E);
idtSet(11, (uint64_t)isr11, 0x08, 0x8E);
idtSet(12, (uint64_t)isr12, 0x08, 0x8E);
idtSet(13, (uint64_t)isr13, 0x08, 0x8E);
idtSet(14, (uint64_t)isr14, 0x08, 0x8E);
idtSet(15, (uint64_t)isr15, 0x08, 0x8E);
idtSet(16, (uint64_t)isr16, 0x08, 0x8E);
idtSet(17, (uint64_t)isr17, 0x08, 0x8E);
idtSet(18, (uint64_t)isr18, 0x08, 0x8E);
idtSet(19, (uint64_t)isr19, 0x08, 0x8E);
idtSet(20, (uint64_t)isr20, 0x08, 0x8E);
idtSet(21, (uint64_t)isr21, 0x08, 0x8E);
idtSet(22, (uint64_t)isr22, 0x08, 0x8E);
idtSet(23, (uint64_t)isr23, 0x08, 0x8E);
idtSet(24, (uint64_t)isr24, 0x08, 0x8E);
idtSet(25, (uint64_t)isr25, 0x08, 0x8E);
idtSet(26, (uint64_t)isr26, 0x08, 0x8E);
idtSet(27, (uint64_t)isr27, 0x08, 0x8E);
idtSet(28, (uint64_t)isr28, 0x08, 0x8E);
idtSet(29, (uint64_t)isr29, 0x08, 0x8E);
idtSet(30, (uint64_t)isr30, 0x08, 0x8E);
idtSet(31, (uint64_t)isr31, 0x08, 0x8E);
idtSet(32, (uint64_t)irq0, 0x08, 0x8E);
idtSet(33, (uint64_t)irq1, 0x08, 0x8E);
idtSet(34, (uint64_t)irq2, 0x08, 0x8E);
idtSet(35, (uint64_t)irq3, 0x08, 0x8E);
idtSet(36, (uint64_t)irq4, 0x08, 0x8E);
idtSet(37, (uint64_t)irq5, 0x08, 0x8E);
idtSet(38, (uint64_t)irq6, 0x08, 0x8E);
idtSet(39, (uint64_t)irq7, 0x08, 0x8E);
idtSet(40, (uint64_t)irq8, 0x08, 0x8E);
idtSet(41, (uint64_t)irq9, 0x08, 0x8E);
idtSet(42, (uint64_t)irq10, 0x08, 0x8E);
idtSet(43, (uint64_t)irq11, 0x08, 0x8E);
idtSet(44, (uint64_t)irq12, 0x08, 0x8E);
idtSet(45, (uint64_t)irq13, 0x08, 0x8E);
idtSet(46, (uint64_t)irq14, 0x08, 0x8E);
idtSet(47, (uint64_t)irq15, 0x08, 0x8E);
/* Load IDT Table */
idtInit();
}
void idtSet(uint8_t number, uint64_t base, uint16_t selector, uint8_t flags) {
/* Set Base Address */
idt[number].baseLow = base & 0xFFFF;
idt[number].baseMid = (base >> 16) & 0xFFFF;
idt[number].baseHigh = (base >> 32) & 0xFFFFFFFF;
/* Set Selector */
idt[number].selector = selector;
idt[number].flags = flags;
/* Set Reserved Areas to Zero */
idt[number].reservedIst = 0;
idt[number].reserved = 0;
}
#if defined(__cplusplus)
extern "C" /* Use C linkage for kernel_main. */
#endif
void isrHandler(struct registers * regs) {
// Video video;
if ( regs->intNo == 14)
{
video.setPosition(10,10);
uint64_t faulting_address;
asm volatile("mov %%cr2, %0" : "=r" (faulting_address));
// The error code gives us details of what happened.
int present = !(regs->errCode & 0x1); // Page not present
int rw = regs->errCode & 0x2; // Write operation?
int us = regs->errCode & 0x4; // Processor was in user-mode?
int reserved = regs->errCode & 0x8; // Overwritten CPU-reserved bits of page entry?
int id = regs->errCode & 0x10; // Caused by an instruction fetch?
video.putString("Page fault! ( ",COLOR_BLUE,COLOR_WHITE);
video.putHexa(regs->errCode,COLOR_BLUE,COLOR_WHITE);
video.putString(", ",COLOR_BLUE,COLOR_WHITE);
if (present) {video.putString("present ",COLOR_BLUE,COLOR_WHITE);}
if (rw) {video.putString("read-only ",COLOR_BLUE,COLOR_WHITE);}
if (us) {video.putString("user-mode ",COLOR_BLUE,COLOR_WHITE);}
if (id) {video.putString("Inst. fetch ",COLOR_BLUE,COLOR_WHITE);}
if (reserved) {video.putString("reserved ",COLOR_BLUE,COLOR_WHITE);}
video.putString(") at 0x",COLOR_BLUE,COLOR_WHITE);
video.putHexa(faulting_address,COLOR_BLUE,COLOR_WHITE);
video.putString("\n",COLOR_BLUE,COLOR_WHITE);
}
else
{
// This is where the GPF Message get displayed
video.setPosition(10,10);
video.putString("Error Code: ",COLOR_BLUE,COLOR_WHITE);
video.putHexa(regs->errCode,COLOR_BLUE,COLOR_WHITE);
video.putString("\n",COLOR_BLUE,COLOR_WHITE);
}
return;
}
#if defined(__cplusplus)
extern "C" /* Use C linkage for kernel_main. */
#endif
void irq_handler(registers * regs)
{
if ( regs->intNo == 42)
{
uint8_t oldx = video.getPositionX();
uint8_t oldy = video.getPositionY();
video.setPosition(45,2);
video.putString("I am here 1",COLOR_BLUE,COLOR_WHITE);
video.setPosition(oldx,oldy);
}
else if (interrupt_handlers[regs->intNo] == 0)
{
uint8_t oldx = video.getPositionX();
uint8_t oldy = video.getPositionY();
video.setPosition(45,3);
video.putString("Got Interrupt",COLOR_BLUE,COLOR_WHITE);
video.putDecimal(regs->intNo,COLOR_BLUE,COLOR_WHITE);
video.setPosition(oldx,oldy);
}
if (interrupt_handlers[regs->intNo] != 0)
{
isr_t handler = interrupt_handlers[regs->intNo];
handler(regs);
}
// Send an EOI (end of interrupt) signal to the PICs.
// If this interrupt involved the slave.
if (regs->intNo >= 40)
{
// Send reset signal to slave.
Ports::outportb(PIC2_COMMAND, 0x20);
}
// Send reset signal to master. (As well as slave, if necessary).
Ports::outportb(PIC1_COMMAND, 0x20);
if ( regs->intNo == 42)
{
uint8_t oldx = video.getPositionX();
uint8_t oldy = video.getPositionY();
video.setPosition(45,2);
video.putString("I am here 2",COLOR_BLUE,COLOR_WHITE);
video.setPosition(oldx,oldy);
}
}
static void timer_callback(registers * regs)
{
tick++;
// Video video;
video.setPosition(50,12);
if ( regs->intNo == 32)
{
video.putString("Tick: ",COLOR_BLUE,COLOR_WHITE);
video.putDecimal(tick,COLOR_BLUE,COLOR_WHITE);
video.putString("\n",COLOR_BLUE,COLOR_WHITE);
}
}
static void keyboard_callback(struct registers * regs)
{
unsigned char status = Ports::inportb(0x64);
unsigned char sc = Ports::inportb(0x60);
// Video video;
if ( sc&0x80)
{
}
else
{
video.setPosition(40,15);
video.putString("IRQ: ",COLOR_BLUE,COLOR_WHITE);
video.putHexa(regs->intNo,COLOR_BLUE,COLOR_WHITE);
video.putString(", Status: ",COLOR_BLUE,COLOR_WHITE);
video.putHexa(status,COLOR_BLUE,COLOR_WHITE);
video.putString("\n",COLOR_BLUE,COLOR_WHITE);
video.setPosition(40,16);
char mychar = kbdus[sc];
video.putString("Got Character: ",COLOR_BLUE,COLOR_WHITE);
video.putCharacter((char)mychar,COLOR_BLUE,COLOR_WHITE);
video.putString("\n",COLOR_BLUE,COLOR_WHITE);
}
}
void init_timer(uint32_t frequency)
{
// Firstly, register our timer callback.
register_interrupt_handler(IRQ0, &timer_callback);
register_interrupt_handler(IRQ1, &keyboard_callback);
// The value we send to the PIT is the value to divide it's input clock
// (1193180 Hz) by, to get our required frequency. Important to note is
// that the divisor must be small enough to fit into 16-bits.
uint32_t divisor = 1193180 / frequency;
// Send the command byte.
Ports::outportb(0x43, 0x34);
// Divisor has to be sent byte-wise, so split here into upper/lower bytes.
uint8_t l = (uint8_t)(divisor & 0xFF);
uint8_t h = (uint8_t)( (divisor>>8) & 0xFF );
// Send the frequency divisor.
Ports::outportb(0x40, l);
Ports::outportb(0x40, h);
}
unsigned int createMask(unsigned a, unsigned b)
{
unsigned r = 0;
for (unsigned i=a; i<=b; i++)
r |= 1 << i;
return r;
}
#if defined(__cplusplus)
extern "C" /* Use C linkage for kernel_main. */
#endif
void kernel_main()
{
video.initialize();
video.clearScreen(COLOR_BLACK);
idtStart();
init_timer(50);
asm volatile ("sti");
}