import macros, serial type IDTEntry{.packed.} = object base_low: uint16 kernel_selector: uint16 zero: uint8 flags: uint8 base_high: uint16 IDTPointer{.packed.} = object limit: uint16 base: uint32 IDT{.packed.} = object descriptor: IDTPointer entries: array[0..255, IDTEntry] Registers{.packed.} = object ds: uint32 # Data segment selector edi, esi, ebp, esp, ebx, edx, ecx, eax: uint32 # Pushed by pusha. int_no, err_code: uint32 # Interrupt number and error code (if applicable) eip, cs, eflags, useresp, ss: uint32 # Pushed by the processor automatically. const idtAddress: uint32 = 0x00000000 idt = cast[ptr IDT](idtAddress) proc idtFlush(){.inline,asmNoStackFrame.} = asm """ lidtl (0x0) ret """ proc isrHandler(registers: Registers){.exportc, codegenDecl: "__attribute__((interrupt)) $# $#$#".} = serial.write("Recieved interrupt handler:") serial.write(registers.int_no) serial.write("\L") proc isrCommon(){.asmNoStackFrame,exportc.} = asm """ pusha mov %ds, %ax push %eax mov $0x10, %ax mov %ax, %ds mov %ax, %es mov %ax, %fs mov %ax, %gs call `isrHandler` pop %eax mov %ax, %ds mov %ax, %es mov %ax, %fs mov %ax, %gs popa add $8, %esp iret """ macro generateISR(code: static[uint8], isError: static[bool]): typed = result = nnkStmtList.newTree( nnkProcDef.newTree( newIdentNode("isr" & $code), newEmptyNode(), newEmptyNode(), nnkFormalParams.newTree( newEmptyNode() ), nnkPragma.newTree( newIdentNode("exportc") ), newEmptyNode(), nnkStmtList.newTree( nnkAsmStmt.newTree( newEmptyNode(), newLit((if isError: "" else: "push 0\x0A") & "push " & $code & "\x0A") ), nnkCall.newTree( nnkDotExpr.newTree( newIdentNode("serial"), newIdentNode("write") ), newLit("Recieved interrupt:") ), nnkCall.newTree( nnkDotExpr.newTree( newIdentNode("serial"), newIdentNode("write") ), newLit(code) ), nnkCall.newTree( nnkDotExpr.newTree( newIdentNode("serial"), newIdentNode("write") ), newLit("\x0A") ), nnkCall.newTree( newIdentNode("isrCommon") ) ) ) ) proc idtSetGate(num: uint8, base: uint32, sel: uint16, flags: uint8) = idt.entries[num].base_low = uint16(base and 0xFFFF) idt.entries[num].base_high = uint16((base shr 16) and 0xFFFF) idt.entries[num].zero = 0 idt.entries[num].flags = flags or 0x60 idt.entries[num].kernel_selector = sel static: generateISR(0, false) generateISR(1, false) generateISR(2, false) generateISR(3, false) generateISR(4, false) generateISR(5, false) generateISR(6, false) generateISR(7, false) generateISR(8, true) generateISR(9, false) generateISR(10, true) generateISR(11, true) generateISR(12, true) generateISR(13, true) generateISR(14, true) generateISR(15, false) generateISR(16, false) generateISR(17, false) generateISR(18, false) generateISR(19, false) generateISR(20, false) generateISR(21, false) generateISR(22, false) generateISR(23, false) generateISR(24, false) generateISR(25, false) generateISR(26, false) generateISR(27, false) generateISR(28, false) generateISR(29, false) generateISR(30, false) generateISR(31, false) const selector: uint16 = 0x08 flags: uint8 = 0x8E proc idtInstall*() = idt.descriptor.limit = uint16(sizeof(idt.entries)) - 1 idt.descriptor.base = cast[uint32](idt.entries.addr) for i in 0..idt.entries.len: # Zero IDT memory space idtSetGate(uint8(i),0,0,0) idtSetGate(0, cast[uint32](isr0), selector, flags) idtSetGate(1, cast[uint32](isr1), selector, flags) idtSetGate(2, cast[uint32](isr2), selector, flags) idtSetGate(3, cast[uint32](isr3), selector, flags) idtSetGate(4, cast[uint32](isr4), selector, flags) idtSetGate(5, cast[uint32](isr5), selector, flags) idtSetGate(6, cast[uint32](isr6), selector, flags) idtSetGate(7, cast[uint32](isr7), selector, flags) idtSetGate(8, cast[uint32](isr8), selector, flags) idtSetGate(9, cast[uint32](isr9), selector, flags) idtSetGate(10, cast[uint32](isr10), selector, flags) idtSetGate(11, cast[uint32](isr11), selector, flags) idtSetGate(12, cast[uint32](isr12), selector, flags) idtSetGate(13, cast[uint32](isr13), selector, flags) idtSetGate(14, cast[uint32](isr14), selector, flags) idtSetGate(15, cast[uint32](isr15), selector, flags) idtSetGate(16, cast[uint32](isr16), selector, flags) idtSetGate(17, cast[uint32](isr17), selector, flags) idtSetGate(18, cast[uint32](isr18), selector, flags) idtSetGate(19, cast[uint32](isr19), selector, flags) idtSetGate(20, cast[uint32](isr20), selector, flags) idtSetGate(21, cast[uint32](isr21), selector, flags) idtSetGate(22, cast[uint32](isr22), selector, flags) idtSetGate(23, cast[uint32](isr23), selector, flags) idtSetGate(24, cast[uint32](isr24), selector, flags) idtSetGate(25, cast[uint32](isr25), selector, flags) idtSetGate(26, cast[uint32](isr26), selector, flags) idtSetGate(27, cast[uint32](isr27), selector, flags) idtSetGate(28, cast[uint32](isr28), selector, flags) idtSetGate(29, cast[uint32](isr29), selector, flags) idtSetGate(30, cast[uint32](isr30), selector, flags) idtSetGate(31, cast[uint32](isr31), selector, flags) serial.write("Flushing IDT.\L") idtFlush()