Mercurial > lcfOS
view cos/kernel/handlers.c @ 298:f7c3d38d0a47
Added reference to read the docs
author | Windel Bouwman |
---|---|
date | Sun, 01 Dec 2013 17:45:22 +0100 |
parents | 24ce177e01e8 |
children |
line wrap: on
line source
#include "kernel.h" // Assembler wrapper prototypes: extern void INT255(void); extern void INT0(void); extern void INT1(void); extern void INT2(void); extern void INT3(void); extern void INT4(void); extern void INT5(void); extern void INT6(void); extern void INT7(void); extern void INT8(void); extern void INT9(void); extern void INT10(void); extern void INT11(void); extern void INT12(void); extern void INT13(void); extern void INT14(void); extern void INT16(void); extern void INT17(void); extern void INT18(void); extern void INT19(void); // Remapped irq assembler wrappers: extern void INT32(void); extern void INT33(void); extern void INT34(void); extern void INT35(void); extern void INT36(void); extern void INT37(void); extern void INT38(void); extern void INT39(void); extern void INT40(void); extern void INT41(void); extern void INT42(void); extern void INT43(void); extern void INT44(void); extern void INT45(void); extern void INT46(void); extern void INT47(void); // THE interrupt descriptor table: IDT_entry *idt = (IDT_entry*)0x5000; volatile idtPointer idtP; void setIDTentry(int num, void (*handler)(), uint16_t selector, uint8_t flags) { // Fill one entry with IDT info: uint64_t offset; // Typecast the function pointer to a number: offset = (uint64_t)handler; // Set offset: idt[num].baseLow = offset & 0xFFFF; idt[num].baseMid = (offset >> 16) & 0xFFFF; idt[num].baseHigh = (offset >> 32) & 0xFFFFFFFF; // Set flags and selector: idt[num].selector = selector; idt[num].flags = flags; // Set reserved fields: idt[num].reserved1 = 0; idt[num].reserved2 = 0; } void setupIDT(void) { int i; // Fill all vectors with the default handler: for (i=0; i<256; i++) { setIDTentry(i, INT255, 0x08, 0x8E); } // Now set other then default handler: setIDTentry(0, INT0, 0x08, 0x8E); setIDTentry(1, INT1, 0x08, 0x8E); setIDTentry(2, INT2, 0x08, 0x8E); setIDTentry(3, INT3, 0x08, 0x8E); setIDTentry(4, INT4, 0x08, 0x8E); setIDTentry(5, INT5, 0x08, 0x8E); setIDTentry(6, INT6, 0x08, 0x8E); setIDTentry(7, INT7, 0x08, 0x8E); setIDTentry(8, INT8, 0x08, 0x8E); setIDTentry(9, INT9, 0x08, 0x8E); setIDTentry(10, INT10, 0x08, 0x8E); setIDTentry(11, INT11, 0x08, 0x8E); setIDTentry(12, INT12, 0x08, 0x8E); setIDTentry(13, INT13, 0x08, 0x8E); setIDTentry(14, INT14, 0x08, 0x8E); //setIDTentry(15, INT15, 0x08, 0x8E); setIDTentry(16, INT16, 0x08, 0x8E); setIDTentry(17, INT17, 0x08, 0x8E); setIDTentry(18, INT18, 0x08, 0x8E); setIDTentry(19, INT19, 0x08, 0x8E); /* reserved interrupts: */ // From int20 - int31 setIDTentry(32, INT32, 0x08, 0x8F); setIDTentry(33, INT33, 0x08, 0x8F); setIDTentry(34, INT34, 0x08, 0x8F); setIDTentry(35, INT35, 0x08, 0x8F); setIDTentry(36, INT36, 0x08, 0x8F); setIDTentry(37, INT37, 0x08, 0x8F); setIDTentry(38, INT38, 0x08, 0x8F); setIDTentry(39, INT39, 0x08, 0x8F); setIDTentry(40, INT40, 0x08, 0x8F); setIDTentry(41, INT41, 0x08, 0x8F); setIDTentry(42, INT42, 0x08, 0x8F); setIDTentry(43, INT43, 0x08, 0x8F); setIDTentry(44, INT44, 0x08, 0x8F); setIDTentry(45, INT45, 0x08, 0x8F); setIDTentry(46, INT46, 0x08, 0x8F); setIDTentry(47, INT47, 0x08, 0x8F); // Set the correct values in the IDT pointer: idtP.base = (uint64_t)idt; idtP.limit = (sizeof(IDT_entry) * 256) - 1; // call load IDT asm function: loadIDT(); PICremap(); asm("sti"); } // PIC functions: void PICremap() { unsigned char maskmaster, maskslave, pic1, pic2; pic1 = 0x20; // remapping location master pic2 = 0x28; maskmaster = inb(0x21); // master cmd=0x20, data=0x21 maskslave = inb(0xA1); // slave command=0xA0, data=0xA1 outb(0x20, 0x20); // end of init outb(0x20, 0x11); // init + ICW1_ICW2 outb(0xA0, 0x11); // init + ICW1_ICW2 outb(0x21, pic1); // ICW2, write offset outb(0xA1, pic2); // ICW2 outb(0x21, 4); // ICW3, write a 4! outb(0xA1, 2); // ICW3, write a 2! outb(0x21, 1); // ICW4, 8086 mode outb(0xA1, 1); // ICW4 outb(0x21, maskmaster); outb(0xA1, maskslave); } /* Function that prints the contents of all registers on the interrupted stack. */ void display_registers(uint64_t *regs) { // Pushed by interrupt handler assembler: printf("rax: %x\n", regs[6]); printf("rbx: %x\n", regs[3]); printf("rcx: %x\n", regs[5]); printf("rdx: %x\n", regs[4]); printf("rsi: %x\n", regs[1]); printf("rdi: %x\n", regs[0]); printf("rbp: %x\n", regs[2]); // Pushed by CPU: printf("rip: %x\n", regs[9]); } void gp_fault(uint64_t *regs) { printf("GP fault\n"); printf("Error code: %x\n", regs[8]); display_registers(regs); panic("No resolution to general protection fault!"); } void page_fault(uint64_t *regs) { printf("Page fault\n"); uint64_t faulting_address; asm volatile("mov %%cr2, %0" : "=r" (faulting_address)); printf("Error code: %x\n", regs[8]); display_registers(regs); printf("Faulting address: %x\n", faulting_address); panic("No resolution to page fault!"); } // Global isr handler: // Hopefully, this function get called with the correct registers. void isr_handler(uint64_t* registers) { uint64_t intnum = registers[7]; // TODO: make a list with handler pointers: if (intnum == 32) { timerDriverUpdate(); } else if (intnum == 33) { keyboardDriverUpdate(); } else if (intnum == 13) { gp_fault(registers); } else if (intnum == 14) { page_fault(registers); } else if (intnum == 39) { printf("Spurious interrupt\n"); } else { printf("Interrupt %d called, registers at: %x\n", registers[7], registers); panic("Paniek! Unhandled interrupt!"); } // TODO: EOI to slave? // TODO: replace this with APIC code? outb(0x20, 0x20); // EOI to master }