driver/pic: IRQHandlerRaw jumped handler
This commit is contained in:
		| @@ -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 | ||||||
| } | } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -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 | ||||||
| } | } | ||||||
|   | |||||||
| @@ -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); | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user