driver/pic: IRQHandlerRaw jumped handler

This commit is contained in:
Edgaru089 2021-11-07 23:05:29 +08:00
parent 193b29400a
commit 312703104d
3 changed files with 28 additions and 2 deletions

View File

@ -1,6 +1,9 @@
format elf64 format elf64
include 'pic_constants.incS'
extrn irq_pic_IntHandler extrn irq_pic_IntHandler
extrn irq_pic_IRQHandlerRaw
public irq_pic_IntHandler20h public irq_pic_IntHandler20h
public irq_pic_IntHandler21h public irq_pic_IntHandler21h
@ -23,9 +26,25 @@ public irq_pic_IntHandler2fh
section '.text' executable section '.text' executable
macro inth op1 { macro inth op1 {
push rax
mov rax, [irq_pic_IRQHandlerRaw+op1*8]
test rax, rax
jz .noraw
; has raw handler
mov al, PIC_CMD_EOI
if op1 >= 8
out PIC2_COMMAND, al
end if
out PIC1_COMMAND, al
pop rax
jmp qword [irq_pic_IRQHandlerRaw+op1*8]
.noraw:
push rdi push rdi
mov rdi, op1 mov rdi, op1
push rax
push rsi push rsi
push rdx push rdx
push rcx push rcx
@ -41,8 +60,8 @@ macro inth op1 {
pop rcx pop rcx
pop rdx pop rdx
pop rsi pop rsi
pop rax
pop rdi pop rdi
pop rax
iretq iretq
} }

View File

@ -36,6 +36,11 @@ typedef SYSV_ABI void (*irq_pic_IRQHandlerType)();
extern irq_pic_IRQHandlerType irq_pic_IRQHandler[16]; extern irq_pic_IRQHandlerType irq_pic_IRQHandler[16];
extern bool irq_pic_Enabled; extern bool irq_pic_Enabled;
// If IRQHandlerRaw[irq] is not NULL, the function is jumped to (not called).
//
// So the handler should use IRET instead of RET, and save all the registers it uses.
extern void *irq_pic_IRQHandlerRaw[16];
#ifdef __cplusplus #ifdef __cplusplus
} }

View File

@ -10,6 +10,7 @@
irq_pic_IRQHandlerType irq_pic_IRQHandler[16]; irq_pic_IRQHandlerType irq_pic_IRQHandler[16];
void * irq_pic_IRQHandlerRaw[16];
bool irq_pic_Enabled; bool irq_pic_Enabled;
void irq_pic_Init() { void irq_pic_Init() {
@ -34,6 +35,7 @@ void irq_pic_Init() {
outb_wait(PIC2_DATA, 0xff); outb_wait(PIC2_DATA, 0xff);
memset(irq_pic_IRQHandler, 0, sizeof(irq_pic_IRQHandler)); // reset all IRQ handlers memset(irq_pic_IRQHandler, 0, sizeof(irq_pic_IRQHandler)); // reset all IRQ handlers
memset(irq_pic_IRQHandlerRaw, 0, sizeof(irq_pic_IRQHandlerRaw));
// map the IRQ handlers // map the IRQ handlers
interrupt_MapHandler(irq_pic_IntHandler20h, 0x20); interrupt_MapHandler(irq_pic_IntHandler20h, 0x20);