; Set an IDT entry to a callback
%macro SETIDT 2
mov rax, %2
- mov WORD [rdi + %1*16], ax
+ mov WORD [rdi + %1*16], ax
shr rax, 16
- mov WORD [rdi + %1*16 + 6], ax
+ mov WORD [rdi + %1*16 + 6], ax
shr rax, 16
mov DWORD [rdi + %1*16 + 8], eax
; Enable
- mov ax, WORD [rdi + %1*16 + 4]
- or ax, 0x8000
- mov WORD [rdi + %1*16 + 4], ax
+ mov ax, WORD [rdi + %1*16 + 4]
+ or ax, 0x8000
+ mov WORD [rdi + %1*16 + 4], ax
%endmacro
; Install error handlers
mov dx, 0x20
mov al, 0x11
out dx, al ; Init Command
- mov dx, 0x21
+ mov dx, 0x21
mov al, 0xF0
out dx, al ; Offset (Start of IDT Range)
- mov al, 0x04
+ mov al, 0x04
out dx, al ; IRQ connected to Slave (00000100b) = IRQ2
- mov al, 0x01
+ mov al, 0x01
out dx, al ; Set Mode
- mov al, 0x00
+ mov al, 0x00
out dx, al ; Set Mode
mov dx, 0xA0
mov al, 0x11
out dx, al ; Init Command
- mov dx, 0xA1
+ mov dx, 0xA1
mov al, 0xF8
out dx, al ; Offset (Start of IDT Range)
- mov al, 0x02
+ mov al, 0x02
out dx, al ; IRQ Line connected to master
- mov al, 0x01
+ mov al, 0x01
out dx, al ; Set Mode
- mov dl, 0x00
+ mov dl, 0x00
out dx, al ; Set Mode
pop rdx
mov rax, gGDTPtr
mov rcx, gGDT
mov QWORD [rax+2], rcx
- lidt [rax]
+ lgdt [rax]
; Start interrupts
sti
; RDI - IRQ Number
; RSI - Callback
+ ; Check for RDI >= 16
cmp rdi, 16
jb .numOK
xor rax, rax
jmp .ret
.numOK:
- mov rax, rdi
- shr rax, 3+2
+ ; Get handler base into RAX
+ lea rax, [rdi*4]
mov rcx, gaIRQ_Handlers
- add rax, rcx
+ lea rax, [rcx+rax*8]
; Find a free callback slot
%rep NUM_IRQ_CALLBACKS
pop rsi
pop rdi
+ ; Assign and return
mov [rax], rsi
xor rax, rax
[global IrqCommon]
IrqCommon:
PUSH_GPR
+ push gs
+ push fs
- mov rbx, [rsp+16*8] ; Calculate address
- shr rbx, 3+2 ; *8*4
+ mov rbx, [rsp+(16+2)*8] ; Get interrupt number (16 GPRS + 2 SRs)
+; xchg bx, bx ; Bochs Magic break (NOTE: will clear the high-bits of RBX)
+ shl rbx, 2 ; *8*4
mov rax, gaIRQ_Handlers
- add rbx, rax
+ lea rbx, [rax+rbx*8]
; Check all callbacks
+ sub rsp, 8 ; Shadow of argument
%assign i 0
%rep NUM_IRQ_CALLBACKS
; Get callback address
test rax, rax ; Check if it exists
jz .skip.%[i]
; Set RDI to IRQ number
- mov rdi, [rsp+16*8] ; Get IRQ number
+ mov rdi, [rsp+(16+2+1)*8] ; Get IRQ number
call rax ; Call
.skip.%[i]:
add rbx, 8 ; Next!
%assign i i+1
%endrep
+ add rsp, 8
; ACK
+ mov al, 0x20
mov rdi, [rsp+16*8] ; Get IRQ number
cmp rdi, 8
- mov al, 0x20
jb .skipAckSecondary
mov dx, 0x00A0
out dx, al
mov dx, 0x0020
out dx, al
+ pop fs
+ pop gs
POP_GPR
add rsp, 8*2
;xchg bx, bx
[extern Proc_Scheduler]
[global SchedulerIRQ]
+;
+; NOTE: Proc_Scheduler makes assumptions about the stack state when called
+;
SchedulerIRQ:
+ push 0 ; Error code
+ push 0 ; IRQNum
PUSH_GPR
+ push gs
+ push fs
;PUSH_FPU
;PUSH_XMM
;POP_XMM
;POP_FPU
+ pop fs
+ pop gs
POP_GPR
+ add rsp, 2*8 ; Dummy error code and IRQ num
iretq
[section .data]