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. var idt: IDT idtAddr: uint32 = cast[uint32](idt.addr) {.push stackTrace:off.} proc idtFlush(){.inline,asmNoStackFrame.} = asm """ lidt [`idtAddr`] ret """ {.pop.} proc isrHandler(registers: Registers){.exportc.} = serial.write("Recieved interrupt:") serial.write(registers.int_no) serial.write("\L") proc isrCommon() = asm """ pusha movw %ax, %ds push %eax movw $0x10, %ax movw %ds, %ax movw %es, %ax movw %fs, %ax movw %gs, %ax call `isrHandler` pop %eax movw %ds, %ax movw %es, %ax movw %fs, %ax movw %gs, %ax popa add $8, %esp sti iret """ macro generateISR(code: static[uint8], isError: static[bool]): typed = result = nnkStmtList.newTree( nnkProcDef.newTree( newIdentNode("isr" & $code), newEmptyNode(), newEmptyNode(), nnkFormalParams.newTree( newEmptyNode() ), newEmptyNode(), newEmptyNode(), nnkStmtList.newTree( nnkAsmStmt.newTree( newEmptyNode(), newLit("cli\x0A" & (if isError: "" else: "push 0\x0A") & "push " & $code & "\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 idt.entries[num].kernel_selector = sel # Would like to generate these in a loop, but apparently # Error: type mismatch: got # but expected one of: # macro generateISR(code: static[uint8]; isError: static[bool]): typed # first type mismatch at position: 1 # required type: static[uint8] # but expression 'uint8(i)' is of type: uint8 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) let selector: uint16 = 0x08 flags: uint8 = 0x8E proc idtInstall*() = idt.descriptor.limit = uint16(sizeof(IDTEntry) * idt.entries.len) - 1 idt.descriptor.base = cast[uint32](idt.entries.addr) 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) idtFlush()