Receiving an interrupt no longer crashes, does seem to cause a general protection fault though (infinite loop time!).
This commit is contained in:
parent
347a5cbff3
commit
04768924e8
@ -18,42 +18,39 @@ type
|
|||||||
int_no, err_code: uint32 # Interrupt number and error code (if applicable)
|
int_no, err_code: uint32 # Interrupt number and error code (if applicable)
|
||||||
eip, cs, eflags, useresp, ss: uint32 # Pushed by the processor automatically.
|
eip, cs, eflags, useresp, ss: uint32 # Pushed by the processor automatically.
|
||||||
|
|
||||||
var
|
const
|
||||||
idt: IDT
|
idtAddress: uint32 = 0x00000000
|
||||||
idtAddr: uint32 = cast[uint32](idt.addr)
|
idt = cast[ptr IDT](idtAddress)
|
||||||
|
|
||||||
{.push stackTrace:off.}
|
|
||||||
proc idtFlush(){.inline,asmNoStackFrame.} =
|
proc idtFlush(){.inline,asmNoStackFrame.} =
|
||||||
asm """
|
asm """
|
||||||
lidt [`idtAddr`]
|
lidtl (0x0)
|
||||||
ret
|
ret
|
||||||
"""
|
"""
|
||||||
{.pop.}
|
|
||||||
|
|
||||||
proc isrHandler(registers: Registers){.exportc.} =
|
proc isrHandler(registers: Registers){.exportc, codegenDecl: "__attribute__((interrupt)) $# $#$#".} =
|
||||||
serial.write("Recieved interrupt:")
|
serial.write("Recieved interrupt handler:")
|
||||||
serial.write(registers.int_no)
|
serial.write(registers.int_no)
|
||||||
serial.write("\L")
|
serial.write("\L")
|
||||||
|
|
||||||
proc isrCommon() =
|
proc isrCommon(){.asmNoStackFrame,exportc.} =
|
||||||
asm """
|
asm """
|
||||||
pusha
|
pusha
|
||||||
movw %ax, %ds
|
mov %ds, %ax
|
||||||
push %eax
|
push %eax
|
||||||
movw $0x10, %ax
|
mov $0x10, %ax
|
||||||
movw %ds, %ax
|
mov %ax, %ds
|
||||||
movw %es, %ax
|
mov %ax, %es
|
||||||
movw %fs, %ax
|
mov %ax, %fs
|
||||||
movw %gs, %ax
|
mov %ax, %gs
|
||||||
call `isrHandler`
|
call `isrHandler`
|
||||||
pop %eax
|
pop %eax
|
||||||
movw %ds, %ax
|
mov %ax, %ds
|
||||||
movw %es, %ax
|
mov %ax, %es
|
||||||
movw %fs, %ax
|
mov %ax, %fs
|
||||||
movw %gs, %ax
|
mov %ax, %gs
|
||||||
popa
|
popa
|
||||||
add $8, %esp
|
add $8, %esp
|
||||||
sti
|
|
||||||
iret
|
iret
|
||||||
"""
|
"""
|
||||||
|
|
||||||
@ -66,12 +63,35 @@ macro generateISR(code: static[uint8], isError: static[bool]): typed =
|
|||||||
nnkFormalParams.newTree(
|
nnkFormalParams.newTree(
|
||||||
newEmptyNode()
|
newEmptyNode()
|
||||||
),
|
),
|
||||||
newEmptyNode(),
|
nnkPragma.newTree(
|
||||||
|
newIdentNode("exportc")
|
||||||
|
),
|
||||||
newEmptyNode(),
|
newEmptyNode(),
|
||||||
nnkStmtList.newTree(
|
nnkStmtList.newTree(
|
||||||
nnkAsmStmt.newTree(
|
nnkAsmStmt.newTree(
|
||||||
newEmptyNode(),
|
newEmptyNode(),
|
||||||
newLit("cli\x0A" & (if isError: "" else: "push 0\x0A") & "push " & $code & "\x0A")
|
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(
|
nnkCall.newTree(
|
||||||
newIdentNode("isrCommon")
|
newIdentNode("isrCommon")
|
||||||
@ -84,17 +104,9 @@ proc idtSetGate(num: uint8, base: uint32, sel: uint16, flags: uint8) =
|
|||||||
idt.entries[num].base_low = uint16(base and 0xFFFF)
|
idt.entries[num].base_low = uint16(base and 0xFFFF)
|
||||||
idt.entries[num].base_high = uint16((base shr 16) and 0xFFFF)
|
idt.entries[num].base_high = uint16((base shr 16) and 0xFFFF)
|
||||||
idt.entries[num].zero = 0
|
idt.entries[num].zero = 0
|
||||||
idt.entries[num].flags = flags
|
idt.entries[num].flags = flags or 0x60
|
||||||
idt.entries[num].kernel_selector = sel
|
idt.entries[num].kernel_selector = sel
|
||||||
|
|
||||||
# Would like to generate these in a loop, but apparently
|
|
||||||
# Error: type mismatch: got <uint8, bool>
|
|
||||||
# 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:
|
static:
|
||||||
generateISR(0, false)
|
generateISR(0, false)
|
||||||
generateISR(1, false)
|
generateISR(1, false)
|
||||||
@ -129,13 +141,15 @@ static:
|
|||||||
generateISR(30, false)
|
generateISR(30, false)
|
||||||
generateISR(31, false)
|
generateISR(31, false)
|
||||||
|
|
||||||
let
|
const
|
||||||
selector: uint16 = 0x08
|
selector: uint16 = 0x08
|
||||||
flags: uint8 = 0x8E
|
flags: uint8 = 0x8E
|
||||||
|
|
||||||
proc idtInstall*() =
|
proc idtInstall*() =
|
||||||
idt.descriptor.limit = uint16(sizeof(IDTEntry) * idt.entries.len) - 1
|
idt.descriptor.limit = uint16(sizeof(idt.entries)) - 1
|
||||||
idt.descriptor.base = cast[uint32](idt.entries.addr)
|
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(0, cast[uint32](isr0), selector, flags)
|
||||||
idtSetGate(1, cast[uint32](isr1), selector, flags)
|
idtSetGate(1, cast[uint32](isr1), selector, flags)
|
||||||
idtSetGate(2, cast[uint32](isr2), selector, flags)
|
idtSetGate(2, cast[uint32](isr2), selector, flags)
|
||||||
@ -168,4 +182,5 @@ proc idtInstall*() =
|
|||||||
idtSetGate(29, cast[uint32](isr29), selector, flags)
|
idtSetGate(29, cast[uint32](isr29), selector, flags)
|
||||||
idtSetGate(30, cast[uint32](isr30), selector, flags)
|
idtSetGate(30, cast[uint32](isr30), selector, flags)
|
||||||
idtSetGate(31, cast[uint32](isr31), selector, flags)
|
idtSetGate(31, cast[uint32](isr31), selector, flags)
|
||||||
|
serial.write("Flushing IDT.\L")
|
||||||
idtFlush()
|
idtFlush()
|
Loading…
Reference in New Issue
Block a user