; vi:filetype=nasm ts=8 sts=8 sw=8: section .text %define INTR_ASM_ %include "intr.inc" GATE_INTR equ 0600h GATE_TRAP equ 0700h GATE_DEFAULT equ 0800h GATE_PRESENT equ 8000h global init_intr init_intr: call init_pic ; install trap handlers set_trap 0, trap_entry_div set_trap 1, trap_entry_debug set_trap 2, trap_entry_nmi set_trap 3, trap_entry_bp set_trap 4, trap_entry_overflow set_trap 5, trap_entry_bound set_trap 6, trap_entry_ill set_trap 7, trap_entry_nodev set_trap 8, trap_entry_dfault set_trap 9, trap_entry_copseg set_trap 10, trap_entry_tss set_trap 11, trap_entry_segpres set_trap 12, trap_entry_stack set_trap 13, trap_entry_prot set_trap 14, trap_entry_page set_trap 15, trap_entry_reserved set_trap 16, trap_entry_fpu set_trap 17, trap_entry_align set_trap 18, trap_entry_mce set_trap 19, trap_entry_sse ; install dummy interrupt handlers for all IRQ vectors %assign i 0 %rep 8 set_irq_vector i, dummy_intr_pic1 set_irq_vector i+8, dummy_intr_pic2 %assign i i+1 %endrep ret %macro trap_err 2 global trap_entry_%2 trap_entry_%2: push dword %1 jmp trap_entry_common %endmacro %macro trap_noerr 2 global trap_entry_%2 trap_entry_%2: push dword 0 push dword %1 jmp trap_entry_common %endmacro trap_entry_common: pusha ; do exception handling popa add esp, 8 ; remove error code and exception number from stack iret trap_noerr 0, div trap_noerr 1, debug trap_noerr 2, nmi trap_noerr 3, bp trap_noerr 4, overflow trap_noerr 5, bound trap_noerr 6, ill trap_noerr 7, nodev trap_err 8, dfault trap_noerr 9, copseg trap_err 10, tss trap_err 11, segpres trap_err 12, stack trap_err 13, prot trap_err 14, page trap_noerr 15, reserved trap_noerr 16, fpu trap_err 17, align trap_noerr 18, mce trap_noerr 19, sse global set_intr set_intr: push ebp mov ebp, esp push ebx mov ebx, [ebp + 8] mov ax, GATE_TRAP cmp ebx, 32 ; determine if it's an IRQ or an exception (trap) jb .notirq mov ax, GATE_INTR .notirq: lea ebx, [ebx * 8 + idt] ; ebx <- pointer to gate descriptor ; type|dpl goes to the 3rd word of the descriptor (dpl is 0) or ax, (GATE_DEFAULT | GATE_PRESENT) mov [ebx + 4], ax ; address low 16bits go to the first word of the descriptor mov eax, [ebp + 12] mov [ebx], ax ; address high 16bits go to the last word of the descriptor shr eax, 16 mov [ebx + 6], ax ; selector (kcode:1) goes to the second word of the descriptor mov word [ebx + 2], 08h pop ebx pop ebp ret dummy_intr_pic1: pusha end_of_irq 0 popa iret dummy_intr_pic2: pusha end_of_irq 8 popa iret ; PIC initialization command word 1 bits ICW1_ICW4_NEEDED equ 01h ICW1_SINGLE equ 02h ICW1_INTERVAL4 equ 04h ICW1_LEVEL equ 08h ICW1_INIT equ 10h ; PIC initialization command word 4 bits ICW4_8086 equ 01h ICW4_AUTO_EOI equ 02h ICW4_BUF_SLAVE equ 08h ICW4_BUF_MASTER equ 0ch ICW4_SPECIAL equ 10h init_pic: ; send ICW1 saying we'll follow with ICW4 later on mov al, ICW1_INIT | ICW1_ICW4_NEEDED out PIC1_CMD, al out PIC2_CMD, al ; send ICW2 with IRQ remapping mov al, IRQ_OFFSET out PIC1_DATA, al add al, 8 out PIC2_DATA, al ; send ICW3 to setup the master/slave relationship ; ... set bit3 = 3rd interrupt input has a slave mov al, 4 out PIC1_DATA, al ; ... set slave ID to 2 mov al, 2 out PIC2_DATA, al ; send ICW4 to set 8086 mode (no calls generated) mov al, ICW4_8086 out PIC1_DATA, al out PIC2_DATA, al ; done, reset the data port to 0 xor al, al out PIC1_DATA, al out PIC2_DATA, al ret