-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathinterrupts.C
executable file
·165 lines (127 loc) · 5.1 KB
/
interrupts.C
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
/*
File: interrupts.C
Author: R. Bettati
Department of Computer Science
Texas A&M University
Date : 09/03/05
*/
/*--------------------------------------------------------------------------*/
/* DEFINES */
/*--------------------------------------------------------------------------*/
#define IRQ_TABLE_SIZE 16
#define IRQ_BASE 32
/*--------------------------------------------------------------------------*/
/* INCLUDES */
/*--------------------------------------------------------------------------*/
#include "assert.H"
#include "utils.H"
#include "console.H"
#include "idt.H"
#include "irq.H"
#include "exceptions.H"
#include "interrupts.H"
/*--------------------------------------------------------------------------*/
/* EXTERNS */
/*--------------------------------------------------------------------------*/
/* The low-level functions (defined in file 'irq_low.s') that handle the
16 PIC-generated interrupts.
These functions are actually merely stubs that put the error code and
the exception code on the stack and then call a low-level function, which
in turn calls the interrupt dispatcher.
Yes, there are more efficient ways to handle exceptions, but they require more
code replication.
*/
extern "C" void irq0();
extern "C" void irq1();
extern "C" void irq2();
extern "C" void irq3();
extern "C" void irq4();
extern "C" void irq5();
extern "C" void irq6();
extern "C" void irq7();
extern "C" void irq8();
extern "C" void irq9();
extern "C" void irq10();
extern "C" void irq11();
extern "C" void irq12();
extern "C" void irq13();
extern "C" void irq14();
extern "C" void irq15();
/*--------------------------------------------------------------------------*/
/* LOCAL VARIABLES */
/*--------------------------------------------------------------------------*/
static ExceptionHandler handler_table[IRQ_TABLE_SIZE];
/*--------------------------------------------------------------------------*/
/* LOCAL FUNCTIONS */
/*--------------------------------------------------------------------------*/
static BOOLEAN generated_by_slave_PIC(unsigned int int_no) {
return int_no > 7;
}
/*--------------------------------------------------------------------------*/
/* EXPORTED INTERRUPT DISPATCHER FUNCTIONS */
/*--------------------------------------------------------------------------*/
void init_interrupt_dispatcher() {
/* -- INITIALIZE LOW-LEVEL EXCEPTOIN HANDLERS */
/* Add any new ISRs to the IDT here using IDT::set_gate */
IDT::set_gate( 0+ IRQ_BASE, (unsigned) irq0, 0x08, 0x8E);
IDT::set_gate( 1+ IRQ_BASE, (unsigned) irq1, 0x08, 0x8E);
IDT::set_gate( 2+ IRQ_BASE, (unsigned) irq2, 0x08, 0x8E);
IDT::set_gate( 3+ IRQ_BASE, (unsigned) irq3, 0x08, 0x8E);
IDT::set_gate( 4+ IRQ_BASE, (unsigned) irq4, 0x08, 0x8E);
IDT::set_gate( 5+ IRQ_BASE, (unsigned) irq5, 0x08, 0x8E);
IDT::set_gate( 6+ IRQ_BASE, (unsigned) irq6, 0x08, 0x8E);
IDT::set_gate( 7+ IRQ_BASE, (unsigned) irq7, 0x08, 0x8E);
IDT::set_gate( 8+ IRQ_BASE, (unsigned) irq8, 0x08, 0x8E);
IDT::set_gate( 9+ IRQ_BASE, (unsigned) irq9, 0x08, 0x8E);
IDT::set_gate(10+ IRQ_BASE, (unsigned)irq10, 0x08, 0x8E);
IDT::set_gate(11+ IRQ_BASE, (unsigned)irq11, 0x08, 0x8E);
IDT::set_gate(12+ IRQ_BASE, (unsigned)irq12, 0x08, 0x8E);
IDT::set_gate(13+ IRQ_BASE, (unsigned)irq13, 0x08, 0x8E);
IDT::set_gate(14+ IRQ_BASE, (unsigned)irq14, 0x08, 0x8E);
IDT::set_gate(15+ IRQ_BASE, (unsigned)irq15, 0x08, 0x8E);
/* -- INITIALIZE THE HIGH-LEVEL EXCEPTION HANDLER */
int i;
for(i = 0; i < IRQ_TABLE_SIZE; i++) {
handler_table[i] = NULL;
}
}
void dispatch_interrupt(REGS * _r) {
/* -- INTERRUPT NUMBER */
unsigned int int_no = _r->int_no - IRQ_BASE;
//Console::puts("INTERRUPT DISPATCHER: int_no = ");
//Console::putui(int_no);
//Console::puts("\n");
assert((int_no >= 0) && (int_no < IRQ_TABLE_SIZE));
/* -- HAS A HANDLER BEEN REGISTERED FOR THIS INTERRUPT NO? */
InterruptHandler handler = handler_table[int_no];
if (!handler) {
/* --- NO DEFAULT HANDLER HAS BEEN REGISTERED. SIMPLY RETURN AN ERROR. */
Console::puts("INTERRUPT NO: ");
Console::puti(int_no);
Console::puts("\n");
Console::puts("NO DEFAULT INTERRUPT HANDLER REGISTERED\n");
// abort();
}
else {
/* -- HANDLE THE INTERRUPT */
handler(_r);
}
/* This is an interrupt that was raised by the interrupt controller. We need
to send and end-of-interrupt (EOI) signal to the controller after the
interrupt has been handled. */
/* Check if the interrupt was generated by the slave interrupt controller.
If so, send an End-of-Interrupt (EOI) message to the slave controller. */
if (generated_by_slave_PIC(int_no)) {
outportb(0xA0, 0x20);
}
/* Send an EOI message to the master interrupt controller. */
outportb(0x20, 0x20);
}
void register_interrupt_handler(unsigned int _irq_code,
ExceptionHandler _handler) {
assert(_irq_code >= 0 && _irq_code < IRQ_TABLE_SIZE);
handler_table[_irq_code] = _handler;
Console::puts("Installed interrupt handler at IRQ ");
Console::putui(_irq_code);
Console::puts("\n");
}