+[section .text]
+Desctab_Init:
+ ; Install IRQ Handlers
+ ret
+
+; int IRQ_AddHandler(int IRQ, void (*Handler)(int IRQ))
+; Return Values:
+; 0 on Success
+; -1 on an invalid IRQ Number
+; -2 when no slots are avaliable
+[global IRQ_AddHandler]
+IRQ_AddHandler:
+ ; RDI - IRQ Number
+ ; RSI - Callback
+
+ cmp rdi, 16
+ jb .numOK
+ xor rax, rax
+ dec rax
+ jmp .ret
+.numOK:
+
+ mov rax, rdi
+ shr rax, 3+2
+ mov rcx, gaIRQ_Handlers
+ add rax, rcx
+
+ ; Find a free callback slot
+ %rep NUM_IRQ_CALLBACKS
+ mov rdx, [rax]
+ test rdx, rdx
+ jz .assign
+ add rax, 8
+ %endrep
+ ; None found, return -2
+ xor rax, rax
+ dec rax
+ dec rax
+ jmp .ret
+
+ ; Assign the IRQ Callback
+.assign:
+ mov [rax], rsi
+ xor rax, rax
+
+.ret:
+ ret
+
+%macro DEFERR 1
+Isr%1:
+ push 0
+ push %1
+ jmp ErrorCommon
+%endmacro
+%macro DEFERRNO 1
+Isr%1:
+ push %1
+ jmp ErrorCommon
+%endmacro
+
+%macro DEFIRQ 1
+Irq%1:
+ push 0
+ push %1
+ jmp IrqCommon
+%endmacro
+
+IrqCommon:
+ PUSH_GPR
+
+ mov rbx, [rsp+16*8] ; Calculate address
+ shr rbx, 3+2 ; *8*4
+ mov rax, gaIRQ_Handlers
+ add rbx, rax
+
+ %assign i 0
+ %rep NUM_IRQ_CALLBACKS
+ mov rax, [rbx]
+ test rax, rax
+ mov rdi, [rsp+16*8] ; Get IRQ number
+ jz .skip.%[i]
+ call rax ; 2 Bytes (Op and Mod/RM)
+.skip.%[i]:
+ add rbx, 8
+ %assign i i+1
+ %endrep
+
+ mov rdi, [rsp+16*8] ; Get IRQ number
+ cmp rdi, 8
+ mov al, 0x20
+ jb .skipAckSecondary
+ mov dx, 0x00A0
+ out dx, al
+.skipAckSecondary:
+ mov dx, 0x0020
+ out dx, al
+
+ POP_GPR
+ add rsp, 16
+ iret
+