reorganize source
[com32] / src / kern / intr_s.asm
diff --git a/src/kern/intr_s.asm b/src/kern/intr_s.asm
new file mode 100644 (file)
index 0000000..58c31f6
--- /dev/null
@@ -0,0 +1,161 @@
+; pcboot - bootable PC demo/game kernel
+; Copyright (C) 2018-2023  John Tsiombikas <nuclear@member.fsf.org>
+; 
+; This program is free software: you can redistribute it and/or modify
+; it under the terms of the GNU General Public License as published by
+; the Free Software Foundation, either version 3 of the License, or
+; (at your option) any later version.
+; 
+; This program is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY, without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+; GNU General Public License for more details.
+; 
+; You should have received a copy of the GNU General Public License
+; along with this program.  If not, see <https://www.gnu.org/licenses/>.
+
+       section .data
+       align 4
+       dw 0
+idtr_desc:
+lim:   dw 0
+addr:  dd 0
+
+       section .text
+; void set_idt(uint32_t addr, uint16_t limit)
+       global set_idt
+set_idt:
+       mov eax, [esp + 4]
+       mov [addr], eax
+       mov ax, [esp + 8]
+       mov [lim], ax
+       lidt [idtr_desc]
+       ret
+
+; int get_intr_flag()
+       global get_intr_flag
+get_intr_flag:
+       pushf
+       pop eax
+       ; bit 9 of eflags is IF
+       shr eax, 9
+       and eax, 1
+       ret
+
+; void set_intr_flag(int onoff)
+       global set_intr_flag
+set_intr_flag:
+       cmp dword [esp + 4], 0
+       jz .off
+       sti
+       ret
+.off:  cli
+       ret
+
+; interrupt entry with error code macro
+; this macro generates an interrupt entry point for the
+; exceptions which include error codes in the stack frame
+%macro ientry_err 2
+       global intr_entry_%2
+intr_entry_%2:
+       push dword %1
+       jmp intr_entry_common
+%endmacro
+
+; interrupt entry without error code macro
+; this macro generates an interrupt entry point for the interrupts
+; and exceptions which do not include error codes in the stack frame
+; it pushes a dummy error code (0), to make the stack frame identical
+%macro ientry_noerr 2
+       global intr_entry_%2
+intr_entry_%2:
+       push dword 0
+       push dword %1
+       jmp intr_entry_common
+%endmacro
+
+; common code used by all entry points. calls dispatch_intr()
+; defined in intr.c
+       extern dispatch_intr
+intr_entry_common:
+       ; save general purpose registers
+       pusha
+       call dispatch_intr
+intr_ret_local:
+       ; restore general purpose registers
+       popa
+       ; remove error code and intr num from stack
+       add esp, 8
+       iret
+
+; special case for the timer interrupt, to avoid all the overhead of
+; going through the C interrupt dispatcher 250 times each second
+;      extern nticks
+;      global intr_entry_fast_timer
+;intr_entry_fast_timer:
+;      inc dword [nticks]
+;      ; signal end of interrupt
+;      push eax
+;      mov al, 20h
+;      out 20h, al
+;      pop eax
+;      iret
+
+; special case for IRQ 7 and IRQ 15, to catch spurious interrupts
+PIC1_CMD equ 0x20
+PIC2_CMD equ 0xa0
+OCW2_EOI equ 0x20
+OCW3_ISR equ 0x0b
+
+       global irq7_entry_check_spurious
+irq7_entry_check_spurious:
+       push eax
+       mov al, OCW3_ISR
+       out PIC1_CMD, al
+       in al, PIC1_CMD
+       and al, 80h
+       pop eax
+       jnz intr_entry_irq7
+       iret
+
+       global irq15_entry_check_spurious
+irq15_entry_check_spurious:
+       push eax
+       mov al, OCW3_ISR
+       out PIC2_CMD, al
+       in al, PIC2_CMD
+       and al, 80h
+       jnz .legit
+       ; it was spurious, send EOI to master PIC and iret
+       mov al, OCW2_EOI
+       out PIC1_CMD, al
+       pop eax
+       iret
+.legit:        pop eax
+       jmp intr_entry_irq15
+
+
+; XXX not necessary for now, just leaving it in in case it's useful
+; down the road.
+;
+; intr_ret is called by context_switch to return from the kernel
+; to userspace. The argument is a properly formed intr_frame
+; structure with the saved context of the new task.
+;
+; First thing to do is remove the return address pointing back
+; to context_switch, which then leaves us with a proper interrupt
+; stack frame, so we can jump right in the middle of the regular
+; interrupt return code above.
+       global intr_ret
+intr_ret:
+       add esp, $4
+       jmp intr_ret_local
+
+; by including interrupts.h with ASM defined, the macros above
+; are expanded to generate all required interrupt entry points
+%define INTR_ENTRY_EC(n, name)         ientry_err n, name
+%define INTR_ENTRY_NOEC(n, name)       ientry_noerr n, name
+
+%include 'intrtab.h'
+
+; vi:set ts=8 sts=8 sw=8 ft=nasm: