178 lines
5.4 KiB
Nim
178 lines
5.4 KiB
Nim
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(
|
|
nnkCall.newTree(
|
|
nnkDotExpr.newTree(
|
|
newIdentNode("serial"),
|
|
newIdentNode("write")
|
|
),
|
|
newLit("Recieved interrupt:")
|
|
),
|
|
nnkCall.newTree(
|
|
nnkDotExpr.newTree(
|
|
newIdentNode("serial"),
|
|
newIdentNode("writeLine")
|
|
),
|
|
newLit(code)
|
|
),
|
|
nnkAsmStmt.newTree(
|
|
newEmptyNode(),
|
|
newLit((if isError: "" else: "push 0\x0A") & "push " & $code & "\x0A")
|
|
)
|
|
)
|
|
)
|
|
)
|
|
|
|
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.writeLine("Flushing IDT.")
|
|
idtFlush() |