fixed the interrupt gate descriptor setup
[ld45_start_nothing] / src / intr.asm
1 ; vi:filetype=nasm ts=8 sts=8 sw=8:
2         section .text
3
4 %define INTR_ASM_
5 %include "intr.inc"
6
7 GATE_INTR equ 0600h
8 GATE_TRAP equ 0700h
9 GATE_DEFAULT equ 0800h
10 GATE_PRESENT equ 8000h
11
12         global init_intr
13 init_intr:
14         call init_pic
15         ; install trap handlers
16         set_trap 0, trap_entry_div
17         set_trap 1, trap_entry_debug
18         set_trap 2, trap_entry_nmi
19         set_trap 3, trap_entry_bp
20         set_trap 4, trap_entry_overflow
21         set_trap 5, trap_entry_bound
22         set_trap 6, trap_entry_ill
23         set_trap 7, trap_entry_nodev
24         set_trap 8, trap_entry_dfault
25         set_trap 9, trap_entry_copseg
26         set_trap 10, trap_entry_tss
27         set_trap 11, trap_entry_segpres
28         set_trap 12, trap_entry_stack
29         set_trap 13, trap_entry_prot
30         set_trap 14, trap_entry_page
31         set_trap 15, trap_entry_reserved
32         set_trap 16, trap_entry_fpu
33         set_trap 17, trap_entry_align
34         set_trap 18, trap_entry_mce
35         set_trap 19, trap_entry_sse
36
37         ; install dummy interrupt handlers for all IRQ vectors
38 %assign i 0
39 %rep 8
40         set_irq_vector i, dummy_intr_pic1
41         set_irq_vector i+8, dummy_intr_pic2
42 %assign i i+1
43 %endrep
44         ret
45
46 %macro trap_err 2
47         global trap_entry_%2
48 trap_entry_%2:
49         push dword %1
50         jmp trap_entry_common
51 %endmacro
52
53 %macro trap_noerr 2
54         global trap_entry_%2
55 trap_entry_%2:
56         push dword 0
57         push dword %1
58         jmp trap_entry_common
59 %endmacro
60
61 trap_entry_common:
62         pusha
63         ; do exception handling
64         popa
65         add esp, 8      ; remove error code and exception number from stack
66         iret
67         
68         trap_noerr 0, div
69         trap_noerr 1, debug
70         trap_noerr 2, nmi
71         trap_noerr 3, bp
72         trap_noerr 4, overflow
73         trap_noerr 5, bound
74         trap_noerr 6, ill
75         trap_noerr 7, nodev
76         trap_err 8, dfault
77         trap_noerr 9, copseg
78         trap_err 10, tss
79         trap_err 11, segpres
80         trap_err 12, stack
81         trap_err 13, prot
82         trap_err 14, page
83         trap_noerr 15, reserved
84         trap_noerr 16, fpu
85         trap_err 17, align
86         trap_noerr 18, mce
87         trap_noerr 19, sse
88
89
90         global set_intr
91 set_intr:
92         push ebp
93         mov ebp, esp
94         push ebx
95
96         mov ebx, [ebp + 8]
97         mov ax, GATE_TRAP
98         cmp ebx, 32     ; determine if it's an IRQ or an exception (trap)
99         jb .notirq
100         mov ax, GATE_INTR
101 .notirq:
102         lea ebx, [ebx * 8 + idt] ; ebx <- pointer to gate descriptor
103         ; type|dpl goes to the 3rd word of the descriptor (dpl is 0)
104         or ax, (GATE_DEFAULT | GATE_PRESENT)
105         mov [ebx + 4], ax
106         ; address low 16bits go to the first word of the descriptor
107         mov eax, [ebp + 12]
108         mov [ebx], ax
109         ; address high 16bits go to the last word of the descriptor
110         shr eax, 16
111         mov [ebx + 6], ax
112         ; selector (kcode:1) goes to the second word of the descriptor
113         mov word [ebx + 2], 08h
114
115         pop ebx
116         pop ebp
117         ret
118
119 dummy_intr_pic1:
120         pusha
121         end_of_irq 0
122         popa
123         iret
124
125 dummy_intr_pic2:
126         pusha
127         end_of_irq 8
128         popa
129         iret
130
131 ; PIC initialization command word 1 bits
132 ICW1_ICW4_NEEDED        equ 01h
133 ICW1_SINGLE             equ 02h
134 ICW1_INTERVAL4          equ 04h
135 ICW1_LEVEL              equ 08h
136 ICW1_INIT               equ 10h
137 ; PIC initialization command word 4 bits
138 ICW4_8086               equ 01h
139 ICW4_AUTO_EOI           equ 02h
140 ICW4_BUF_SLAVE          equ 08h
141 ICW4_BUF_MASTER         equ 0ch
142 ICW4_SPECIAL            equ 10h
143
144 init_pic:
145         ; send ICW1 saying we'll follow with ICW4 later on
146         mov al, ICW1_INIT | ICW1_ICW4_NEEDED
147         out PIC1_CMD, al
148         out PIC2_CMD, al
149         ; send ICW2 with IRQ remapping
150         mov al, IRQ_OFFSET
151         out PIC1_DATA, al
152         add al, 8
153         out PIC2_DATA, al
154         ; send ICW3 to setup the master/slave relationship
155         ; ... set bit3 = 3rd interrupt input has a slave
156         mov al, 4
157         out PIC1_DATA, al
158         ; ... set slave ID to 2
159         mov al, 2
160         out PIC2_DATA, al
161         ; send ICW4 to set 8086 mode (no calls generated)
162         mov al, ICW4_8086
163         out PIC1_DATA, al
164         out PIC2_DATA, al
165         ; done, reset the data port to 0
166         xor al, al
167         out PIC1_DATA, al
168         out PIC2_DATA, al
169         ret