summaryrefslogtreecommitdiff
path: root/irq.asm
blob: 89392201eadee845adc48aab951efc702a03579d (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
section .text
global idt_entry
global PIC_sendEOI
global idt_init
extern interrupt_handler

extern inb
extern outb

struc idt_entry
    .base_low:  resw 1
    .selector:  resw 1
    .zero:      resb 1
    .flags:     resb 1
    .base_high: resw 1
endstruc

%macro no_error_code_interrupt_handler 1
global interrupt_handler_%1:
interrupt_handler_%1:
    push dword 0
    push dword %1
    jmp common_interrupt_handler
%endmacro

%macro error_code_interrupt_handler 1
global interrupt_handler_%1
interrupt_handler_%1:
    push dword %1
    jmp common_interrupt_handler
%endmacro

%macro idt_set_gate 2
    ; Assign values to IDT entry at interrupt (ecx)
    ; with the offset of the interrupt handler (edx)
    mov edx, %2
    mov [idt + %1 * 8 + idt_entry.base_low], dx
    mov word [idt + %1 * 8 + idt_entry.selector], 0x8
    mov byte [idt + %1 * 8 + idt_entry.zero], 0x0
    mov byte [idt + %1 * 8 + idt_entry.flags], 0x8e
    shr edx, 16
    mov word [idt + %1 * 8 + idt_entry.base_high], dx
%endmacro

common_interrupt_handler:
    pushad
    call interrupt_handler
    popad
    add esp, 8
    iret

no_error_code_interrupt_handler 0
no_error_code_interrupt_handler 1
no_error_code_interrupt_handler 2
no_error_code_interrupt_handler 3
no_error_code_interrupt_handler 4
no_error_code_interrupt_handler 5
no_error_code_interrupt_handler 6
no_error_code_interrupt_handler 7
error_code_interrupt_handler 8
no_error_code_interrupt_handler 9
error_code_interrupt_handler 10
error_code_interrupt_handler 11
error_code_interrupt_handler 12
error_code_interrupt_handler 13
error_code_interrupt_handler 14
no_error_code_interrupt_handler 15
no_error_code_interrupt_handler 16
no_error_code_interrupt_handler 17
no_error_code_interrupt_handler 18
no_error_code_interrupt_handler 19
no_error_code_interrupt_handler 20
no_error_code_interrupt_handler 21
no_error_code_interrupt_handler 22
no_error_code_interrupt_handler 23
no_error_code_interrupt_handler 24
no_error_code_interrupt_handler 25
no_error_code_interrupt_handler 26
no_error_code_interrupt_handler 27
no_error_code_interrupt_handler 28
no_error_code_interrupt_handler 29
no_error_code_interrupt_handler 30
no_error_code_interrupt_handler 31
; 32 unused
no_error_code_interrupt_handler 33


PIC_sendEOI:
    ret

PIC_remap:
    ;arguments:
    ;offset1 - vector offset for master PIC
    ;          vectors on the master become offset1..offset1+7
    ;offset2 - same for slave PIC: offset2..offset2+7

    push ebp
    mov ebp, esp

    sub ebp, 8

    push PIC1_DATA
    call inb
    mov [ebp - 4], al           ; save PIC1 mask

    push PIC2_DATA
    call inb
    mov [ebp - 8], al           ; save PIC2 mask

    push ICW1_INIT+ICW1_ICW4    ; initialization sequence (cascade)
    push PIC1_COMMAND
    call outb

    push ICW1_INIT+ICW1_ICW4    ; initialization sequence (cascade)
    push PIC2_COMMAND
    call outb

    push word [ebp + 8]         ; ICW2: Master PIC vector offset
    push PIC1_DATA
    call outb

    push word [ebp + 12]        ; ICW2: Save PIC vector offset
    push PIC2_DATA
    call outb

    push 0x4                    ; ICW3: tell Master PIC there is a slave PIC at IRQ2 (0000 0100)
    push PIC1_DATA
    call outb

    push 2                      ; ICW3: tell Slave PIC its cacade identity (0000 0010)
    push PIC2_DATA
    call outb

    push ICW4_8086
    push PIC1_DATA
    call outb

    push ICW4_8086
    push PIC2_DATA
    call outb

    push word [ebp - 4]
    push PIC1_DATA
    call outb

    push word [ebp - 8]
    push PIC2_DATA
    call outb

    add ebp, 8
    leave
    ret

idt_init:
    push ebp
    mov ebp, esp

    mov al, 0x0                             ; idt's initial value
    mov ecx, idt_entry_size * 256 - 1       ; Size of: idt
    mov edi, idt                            ; pointer to: idt
    cld                                     ; clear direction flag
    rep stosb                               ; fill array with zeros


    idt_set_gate 33, interrupt_handler_33   ; implement INT 21

    mov ebx, idt_entry_size * 256 - 1       ; size of: idt - 1
    mov eax, idt                            ; pointer to: idt

    mov [idt_ptr], ebx                      ; describe ITDR limit
    mov [idt_ptr + 2], eax                  ; describe ITDR offset

    push idt_ptr
    call idt_load                           ; load IDTR register

    leave
    ret



idt_load:
    push ebp
    mov ebp, esp

    mov edx, [esp + 8]
    lidt [edx]

    leave
    ret


section .data
%include 'constants.asm'

section .bss
align 4

idt_ptr:
    resw 1
    resd 1

idt:
    resb idt_entry_size * 256