00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #include <const.h>
00020
00021 #include <arch/exception.h>
00022 #include <arch/i386.h>
00023 #include <arch/mem.h>
00024 #include <arch/paging.h>
00025
00026 #include <kernel/clock.h>
00027 #include <kernel/console.h>
00028 #include <kernel/floppy.h>
00029 #include <kernel/keyboard.h>
00030 #include <kernel/serial.h>
00031 #include <kernel/speaker.h>
00032 #include <kernel/syscall.h>
00033 #include <kernel/task.h>
00034
00035 #include <net/rtl8139.h>
00036
00037 #include <arch/interrupt.h>
00038
00039
00040 volatile idt_entry_t idt[IDT_DIM];
00041
00042
00043 idt_reg_t idt_ptr;
00044
00045
00046
00047 extern void _irq_00, _irq_01, _irq_02, _irq_03, _irq_04, _irq_05, _irq_06, _irq_07;
00048 extern void _irq_08, _irq_09, _irq_0A, _irq_0B, _irq_0C, _irq_0D, _irq_0E, _irq_0F;
00049 extern void _irq_80;
00050 extern void _irq_unhand;
00051
00052
00053
00054 extern void _exc_00, _exc_01, _exc_02, _exc_03, _exc_04, _exc_05, _exc_06, _exc_07;
00055 extern void _exc_08, _exc_09, _exc_0A, _exc_0B, _exc_0C, _exc_0D, _exc_0E, _exc_0F;
00056 extern void _exc_unhand;
00057
00058
00059
00060 void disable_IRQ(uint8_t IRQ)
00061 {
00062 uint8_t mask;
00063
00064 if (IRQ > 15) return;
00065
00066 if (IRQ < 8)
00067 {
00068
00069 mask = inportb(PORT_INT_MASK_M);
00070 mask |= 1 << IRQ;
00071 outportb(PORT_INT_MASK_M, mask);
00072 }
00073 else
00074 {
00075
00076 mask = inportb(PORT_INT_MASK_S);
00077 mask |= 1 << (IRQ-8);
00078 outportb(PORT_INT_MASK_S, mask);
00079 }
00080 }
00081
00082
00083
00084 void enable_IRQ(uint8_t IRQ)
00085 {
00086 uint8_t mask;
00087
00088 if (IRQ > 15) return;
00089
00090 if (IRQ < 8)
00091 {
00092
00093 mask = inportb(PORT_INT_MASK_M);
00094 mask &= ~(1 << IRQ);
00095 outportb(PORT_INT_MASK_M, mask);
00096 }
00097 else
00098 {
00099
00100 mask = inportb(PORT_INT_MASK_S);
00101 mask &= ~(1 << (IRQ-8));
00102 outportb(PORT_INT_MASK_S, mask);
00103 }
00104 }
00105
00106
00107
00108
00109
00110
00111
00112
00113 void reprogram_PIC()
00114 {
00115
00116 outportb(PORT_8259_M, 0x11);
00117 outportb(PORT_8259_S, 0x11);
00118
00119 outportb(PORT_INT_MASK_M, 0x20);
00120 outportb(PORT_INT_MASK_S, 0x28);
00121
00122 outportb(PORT_INT_MASK_M, 1 << 2);
00123 outportb(PORT_INT_MASK_S, 2);
00124
00125
00126 outportb(PORT_INT_MASK_M, 1);
00127 outportb(PORT_INT_MASK_S, 1);
00128
00129
00130 outportb(PORT_INT_MASK_M, ~(1 << 2));
00131
00132 outportb(PORT_INT_MASK_S, 0xFF);
00133 }
00134
00135
00136 typedef struct irq_desc
00137 {
00138 void *handler;
00139 } irq_desc_t;
00140
00141
00142 static irq_desc_t irq_handler[] =
00143 {
00144 { NULL },
00145 { NULL },
00146 { NULL },
00147 { NULL },
00148 { NULL },
00149 { NULL },
00150 { NULL },
00151 { NULL },
00152
00153 { NULL },
00154 { NULL },
00155 { NULL },
00156 { NULL },
00157 { NULL },
00158 { NULL },
00159 { NULL },
00160 { NULL }
00161 };
00162
00163
00164 #define TOT_IRQ ( sizeof(irq_handler) / sizeof(irq_desc_t) )
00165
00166
00167
00168
00169
00170
00171
00172 void install_irq_handler(uint8_t irq, void *handler)
00173 {
00174 dword IF = GET_IF();
00175
00176 if ( irq > TOT_IRQ )
00177 return;
00178
00179 disable();
00180
00181 irq_handler[irq].handler = handler;
00182 enable_IRQ(irq);
00183
00184 SET_IF(IF);
00185 return;
00186 }
00187
00188
00189
00190 void unhandled_interrupt(uint8_t irq)
00191 {
00192 set_color(LIGHT_RED);
00193 kprintf("\n\rUnhandled IRQ #%03u from task [%s] (%u)!!!", irq, get_pname(), get_pid());
00194 set_color(DEFAULT_COLOR);
00195 beep();
00196
00197
00198 if ( kill(get_pid()) == TRUE )
00199 {
00200 kprintf("\n\rTask [%s] (%u) killed!\n\r",
00201 get_pname(), get_pid()
00202 );
00203 }
00204 else
00205 kprintf("\n\rUnable to kill the task [%s] (%u)", get_pname(), get_pid());
00206 }
00207
00208
00209
00210
00211
00212
00213
00214
00215
00216 void default_handler(irq_context_t *c)
00217 {
00218 if ( c->IRQ < sizeof(irq_handler) )
00219 {
00220
00221
00222 if ( irq_handler[c->IRQ].handler != NULL )
00223 {
00224
00225 int (*p)()=(void *)irq_handler[c->IRQ].handler;
00226 (*p)();
00227 }
00228 else
00229 {
00230
00231 unhandled_interrupt(c->IRQ);
00232 }
00233 }
00234 else
00235 {
00236
00237
00238 switch ( c->IRQ )
00239 {
00240 case MINIRIGHI_INT:
00241 syscall_handler(&(c->eax), &(c->ebp));
00242 break;
00243
00244 default:
00245 unhandled_interrupt(c->IRQ);
00246 break;
00247 }
00248 return;
00249 }
00250
00251 outportb(PORT_8259_M, EOI);
00252 if ( c->IRQ >= 8 )
00253
00254 outportb(PORT_8259_S, EOI);
00255 }
00256
00257
00258
00259
00260
00261
00262
00263
00264
00265 void setup_IDT_entry(byte i, word selector, dword offset, byte attribs, byte paramcnt)
00266 {
00267 dword IF = GET_IF();
00268
00269 disable();
00270
00271 idt[i].offset0_15 = offset & 0xFFFF;
00272 idt[i].offset16_31 = offset >> 16;
00273 idt[i].selector = selector;
00274 idt[i].attribs = attribs;
00275 idt[i].paramcnt = paramcnt;
00276
00277 SET_IF(IF);
00278 }
00279
00280
00281 void install_IDT()
00282 {
00283 unsigned i;
00284
00285
00286 for(i=0x00; i<=0x1F; i++)
00287 setup_IDT_entry(i, KERNEL_CODE, (dword)&_exc_unhand, INT_GATE, 0);
00288
00289
00290 setup_IDT_entry(0x00, KERNEL_CODE, (dword)&_exc_00, INT_GATE, 0);
00291 setup_IDT_entry(0x01, KERNEL_CODE, (dword)&_exc_01, INT_GATE, 0);
00292 setup_IDT_entry(0x02, KERNEL_CODE, (dword)&_exc_02, INT_GATE, 0);
00293 setup_IDT_entry(0x03, KERNEL_CODE, (dword)&_exc_03, INT_GATE, 0);
00294 setup_IDT_entry(0x04, KERNEL_CODE, (dword)&_exc_04, INT_GATE, 0);
00295 setup_IDT_entry(0x05, KERNEL_CODE, (dword)&_exc_05, INT_GATE, 0);
00296 setup_IDT_entry(0x06, KERNEL_CODE, (dword)&_exc_06, INT_GATE, 0);
00297 setup_IDT_entry(0x07, KERNEL_CODE, (dword)&_exc_07, INT_GATE, 0);
00298 setup_IDT_entry(0x08, KERNEL_CODE, (dword)&_exc_08, INT_GATE, 0);
00299 setup_IDT_entry(0x09, KERNEL_CODE, (dword)&_exc_09, INT_GATE, 0);
00300 setup_IDT_entry(0x0A, KERNEL_CODE, (dword)&_exc_0A, INT_GATE, 0);
00301 setup_IDT_entry(0x0B, KERNEL_CODE, (dword)&_exc_0B, INT_GATE, 0);
00302 setup_IDT_entry(0x0C, KERNEL_CODE, (dword)&_exc_0C, INT_GATE, 0);
00303 setup_IDT_entry(0x0D, KERNEL_CODE, (dword)&_exc_0D, INT_GATE, 0);
00304 setup_IDT_entry(0x0E, KERNEL_CODE, (dword)&_exc_0E, INT_GATE, 0);
00305 setup_IDT_entry(0x0F, KERNEL_CODE, (dword)&_exc_0F, INT_GATE, 0);
00306
00307
00308 for(i=0x20; i<=0xFF; i++)
00309 setup_IDT_entry(i, KERNEL_CODE, (dword)&_irq_unhand, INT_GATE, 0);
00310
00311
00312 setup_IDT_entry(0x20, KERNEL_CODE, (dword)&_irq_00, INT_GATE, 0);
00313 setup_IDT_entry(0x21, KERNEL_CODE, (dword)&_irq_01, INT_GATE, 0);
00314 setup_IDT_entry(0x22, KERNEL_CODE, (dword)&_irq_02, INT_GATE, 0);
00315 setup_IDT_entry(0x23, KERNEL_CODE, (dword)&_irq_03, INT_GATE, 0);
00316 setup_IDT_entry(0x24, KERNEL_CODE, (dword)&_irq_04, INT_GATE, 0);
00317 setup_IDT_entry(0x25, KERNEL_CODE, (dword)&_irq_05, INT_GATE, 0);
00318 setup_IDT_entry(0x26, KERNEL_CODE, (dword)&_irq_06, INT_GATE, 0);
00319 setup_IDT_entry(0x27, KERNEL_CODE, (dword)&_irq_07, INT_GATE, 0);
00320 setup_IDT_entry(0x28, KERNEL_CODE, (dword)&_irq_08, INT_GATE, 0);
00321 setup_IDT_entry(0x29, KERNEL_CODE, (dword)&_irq_09, INT_GATE, 0);
00322 setup_IDT_entry(0x2A, KERNEL_CODE, (dword)&_irq_0A, INT_GATE, 0);
00323 setup_IDT_entry(0x2B, KERNEL_CODE, (dword)&_irq_0B, INT_GATE, 0);
00324 setup_IDT_entry(0x2C, KERNEL_CODE, (dword)&_irq_0C, INT_GATE, 0);
00325 setup_IDT_entry(0x2D, KERNEL_CODE, (dword)&_irq_0D, INT_GATE, 0);
00326 setup_IDT_entry(0x2E, KERNEL_CODE, (dword)&_irq_0E, INT_GATE, 0);
00327 setup_IDT_entry(0x2F, KERNEL_CODE, (dword)&_irq_0F, INT_GATE, 0);
00328
00329
00330 setup_IDT_entry(MINIRIGHI_INT, KERNEL_CODE, (dword)&_irq_80, TRAP_GATE | DPL_3, 0);
00331
00332
00333 idt_ptr.limit = (IDT_DIM * sizeof(idt_entry_t) - 1);
00334 * (dword *)idt_ptr.base = ((dword)&idt);
00335
00336
00337 __asm__("lidtl (%0)" : : "r"((dword)&idt_ptr));
00338 }