/*******************************************************************************/ /* COS2000 - Compatible Operating System - LGPL v3 - Hordé Nicolas */ /* */ #include "interrupts.h" #include "types.h" #include "asm.h" #include "memory.h" #include "video.h" #include "gdt.h" #include "system.h" #include "debug.h" #include "process.h" #include "handlers.h" #define IDT_SIZE 256 /* nombre de descripteurs */ /* registre idt */ static struct idtr idtreg; /* table de IDT */ static idtdes idt[IDT_SIZE]; static u32 retry_address; extern wrapper_exception0; extern wrapper_exception1; extern wrapper_exception2; extern wrapper_exception3; extern wrapper_exception4; extern wrapper_exception5; extern wrapper_exception6; extern wrapper_exception7; extern wrapper_exception8; extern wrapper_exception9; extern wrapper_exception10; extern wrapper_exception11; extern wrapper_exception12; extern wrapper_exception13; extern wrapper_exception14; extern wrapper_exception15; extern wrapper_exception16; extern wrapper_exception17; extern wrapper_exception18; extern wrapper_interruption; /******************************************************************************/ /* Initialise la reprise après erreur */ void initretry(u32 address) { retry_address = address; } /******************************************************************************/ /* Récupère l'adresse de reprise après erreur */ u32 getinitretry(void) { return retry_address; } /******************************************************************************/ /* Initialise le controleur d'interruption 8259A */ void initpic(void) { /* MASTER */ /* Initialisation de ICW1 */ outb(PIC1_CMD, ICW1_INIT + ICW1_ICW4); nop(); /* Initialisation de ICW2 - vecteur de depart = 32 */ outb(PIC1_DATA, 0x20); nop(); /* Initialisation de ICW3 */ outb(PIC1_DATA, 0x04); nop(); /* Initialisation de ICW4 */ outb(PIC1_DATA, ICW4_8086); nop(); /* masquage des interruptions */ outb(PIC1_DATA, 0xFF); nop(); /* SLAVE */ /* Initialisation de ICW1 */ outb(PIC2_CMD, ICW1_INIT + ICW1_ICW4); nop(); /* Initialisation de ICW2 - vecteur de depart = 96 */ outb(PIC2_DATA, 0x60); nop(); /* Initialisation de ICW3 */ outb(PIC2_DATA, 0x02); nop(); /* Initialisation de ICW4 */ outb(PIC2_DATA, ICW4_8086); nop(); /* masquage des interruptions */ outb(PIC2_DATA, 0xFF); nop(); /* Demasquage des irqs sauf clavier outb(PIC1_DATA,0xFD); nop(); */ } /******************************************************************************/ /* Active une IRQ */ void enableirq(u8 irq) { u16 port; cli(); port = (((irq & 0x08) << 4) + PIC1_DATA); outb(port, inb(port) & ~(1 << (irq & 7))); sti(); } /******************************************************************************/ /* Désactive une IRQ */ void disableirq(u8 irq) { u16 port; cli(); port = (((irq & 0x08) << 4) + PIC1_DATA); outb(port, inb(port) | (1 << (irq & 7))); sti(); } /******************************************************************************/ /* Créé un descripteur pour l'IDT */ void makeidtdes(u32 offset, u16 select, u16 type, idtdes * desc) { desc->offset0_15 = (offset & 0xffff); desc->select = select; desc->type = type; desc->offset16_31 = (offset & 0xffff0000) >> 16; return; } /******************************************************************************/ /* Change une entrée dans l'IDT */ void setidt(u32 offset, u16 select, u16 type, u16 index) { cli(); idtdes *desc; desc = idtreg.base; desc[index].offset0_15 = (offset & 0xffff); desc[index].select = select; desc[index].type = type; desc[index].offset16_31 = (offset & 0xffff0000) >> 16; sti(); } /******************************************************************************/ /* Met une entrée dans l'IDT */ void putidt(u32 offset, u16 select, u16 type, u16 index) { idtdes temp; makeidtdes(offset, select, type, &temp); idt[index] = temp; } /******************************************************************************/ /* Initialise une IDT */ void initidt(void) { u16 i; putidt((u32) &wrapper_exception0, SEL_KERNEL_CODE, ENTRY_PRESENT | ENTRY_RING0 | INTGATE, 0); putidt((u32) &wrapper_exception1, SEL_KERNEL_CODE, ENTRY_PRESENT | ENTRY_RING0 | INTGATE, 1); putidt((u32) &wrapper_exception2, SEL_KERNEL_CODE, ENTRY_PRESENT | ENTRY_RING0 | INTGATE, 2); putidt((u32) &wrapper_exception3, SEL_KERNEL_CODE, ENTRY_PRESENT | ENTRY_RING0 | INTGATE, 3); putidt((u32) &wrapper_exception4, SEL_KERNEL_CODE, ENTRY_PRESENT | ENTRY_RING0 | INTGATE, 4); putidt((u32) &wrapper_exception5, SEL_KERNEL_CODE, ENTRY_PRESENT | ENTRY_RING0 | INTGATE, 5); putidt((u32) &wrapper_exception6, SEL_KERNEL_CODE, ENTRY_PRESENT | ENTRY_RING0 | INTGATE, 6); putidt((u32) &wrapper_exception7, SEL_KERNEL_CODE, ENTRY_PRESENT | ENTRY_RING0 | INTGATE, 7); putidt((u32) &wrapper_exception8, SEL_KERNEL_CODE, ENTRY_PRESENT | ENTRY_RING0 | INTGATE, 8); putidt((u32) &wrapper_exception9, SEL_KERNEL_CODE, ENTRY_PRESENT | ENTRY_RING0 | INTGATE, 9); putidt((u32) &wrapper_exception10, SEL_KERNEL_CODE, ENTRY_PRESENT | ENTRY_RING0 | INTGATE, 10); putidt((u32) &wrapper_exception11, SEL_KERNEL_CODE, ENTRY_PRESENT | ENTRY_RING0 | INTGATE, 11); putidt((u32) &wrapper_exception12, SEL_KERNEL_CODE, ENTRY_PRESENT | ENTRY_RING0 | INTGATE, 12); putidt((u32) &wrapper_exception13, SEL_KERNEL_CODE, ENTRY_PRESENT | ENTRY_RING0 | INTGATE, 13); putidt((u32) &wrapper_exception14, SEL_KERNEL_CODE, ENTRY_PRESENT | ENTRY_RING0 | INTGATE, 14); putidt((u32) &wrapper_exception15, SEL_KERNEL_CODE, ENTRY_PRESENT | ENTRY_RING0 | INTGATE, 15); putidt((u32) &wrapper_exception16, SEL_KERNEL_CODE, ENTRY_PRESENT | ENTRY_RING0 | INTGATE, 16); putidt((u32) &wrapper_exception17, SEL_KERNEL_CODE, ENTRY_PRESENT | ENTRY_RING0 | INTGATE, 17); putidt((u32) &wrapper_exception18, SEL_KERNEL_CODE, ENTRY_PRESENT | ENTRY_RING0 | INTGATE, 18); for (i = 19; i < 32; i++) { putidt((u32) &wrapper_interruption, SEL_KERNEL_CODE, ENTRY_PRESENT | ENTRY_RING3 | TRAPGATE, i); } putidt((u32) irq0, SEL_KERNEL_CODE, ENTRY_PRESENT | ENTRY_RING0 | INTGATE, 32); putidt((u32) irq1, SEL_KERNEL_CODE, ENTRY_PRESENT | ENTRY_RING0 | INTGATE, 33); putidt((u32) irq2, SEL_KERNEL_CODE, ENTRY_PRESENT | ENTRY_RING0 | INTGATE, 34); putidt((u32) irq3, SEL_KERNEL_CODE, ENTRY_PRESENT | ENTRY_RING0 | INTGATE, 35); putidt((u32) irq4, SEL_KERNEL_CODE, ENTRY_PRESENT | ENTRY_RING0 | INTGATE, 36); putidt((u32) irq5, SEL_KERNEL_CODE, ENTRY_PRESENT | ENTRY_RING0 | INTGATE, 37); putidt((u32) irq6, SEL_KERNEL_CODE, ENTRY_PRESENT | ENTRY_RING0 | INTGATE, 38); putidt((u32) irq7, SEL_KERNEL_CODE, ENTRY_PRESENT | ENTRY_RING0 | INTGATE, 39); for (i = 40; i < 96; i++) { putidt((u32) &wrapper_interruption, SEL_KERNEL_CODE, ENTRY_PRESENT | ENTRY_RING3 | TRAPGATE, i); } putidt((u32) irq8, SEL_KERNEL_CODE, ENTRY_PRESENT | ENTRY_RING0 | INTGATE, 96); putidt((u32) irq9, SEL_KERNEL_CODE, ENTRY_PRESENT | ENTRY_RING0 | INTGATE, 97); putidt((u32) irq10, SEL_KERNEL_CODE, ENTRY_PRESENT | ENTRY_RING0 | INTGATE, 98); putidt((u32) irq11, SEL_KERNEL_CODE, ENTRY_PRESENT | ENTRY_RING0 | INTGATE, 99); putidt((u32) irq12, SEL_KERNEL_CODE, ENTRY_PRESENT | ENTRY_RING0 | INTGATE, 100); putidt((u32) irq13, SEL_KERNEL_CODE, ENTRY_PRESENT | ENTRY_RING0 | INTGATE, 101); putidt((u32) irq14, SEL_KERNEL_CODE, ENTRY_PRESENT | ENTRY_RING0 | INTGATE, 102); putidt((u32) irq15, SEL_KERNEL_CODE, ENTRY_PRESENT | ENTRY_RING0 | INTGATE, 103); for (i = 104; i < IDT_SIZE; i++) { putidt((u32) &wrapper_interruption, SEL_KERNEL_CODE, ENTRY_PRESENT | ENTRY_RING0 | TRAPGATE, i); } /* initialise le registre idt */ idtreg.limite = IDT_SIZE * sizeof(idtdes); idtreg.base = IDT_ADDR; /* recopie de la IDT a son adresse */ memcpy(&idt, (u8 *) idtreg.base, idtreg.limite, 1); /* chargement du registre IDTR */ lidt(idtreg); } /******************************************************************************/ /* 8253/8254 PIT (Programmable Interval Timer) Timer ajustable */ void inittimer(void) { u32 divisor = TIMER_FREQ / HZ; outb(TIMER_MODE, RATE_GENERATOR); outb(TIMER0, (u8) divisor); outb(TIMER0, (u8) (divisor >> 8)); } /*******************************************************************************/