//----------------------------------------------------------------------------// // GNU GPL OS/K // // // // Desc: Interrupt related functions // // // // // // Copyright © 2018-2019 The OS/K Team // // // // This file is part of OS/K. // // // // OS/K is free software: you can redistribute it and/or modify // // it under the terms of the GNU General Public License as published by // // the Free Software Foundation, either version 3 of the License, or // // any later version. // // // // OS/K is distributed in the hope that it will be useful, // // but WITHOUT ANY WARRANTY//without even the implied warranty of // // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // // GNU General Public License for more details. // // // // You should have received a copy of the GNU General Public License // // along with OS/K. If not, see . // //----------------------------------------------------------------------------// #include #include #include #include #include IdtEntry_t idt[256] = { 0 }; IdtPtr_t idtPtr; IRQList_t irqList = { 0 }; // // Registers an isr with his IRQ to handle driver interrupts // void IdtRegisterIrq(void (*isr)(ISRFrame_t *regs), uchar irq, uchar flags) { uchar n = irqList.n; KalAssert(idt[0].flags!=0); // IDT initialized if ((n == 224)) // IRQs not filled KeStartPanic("[IdtRegisterIrq] Cannot register IRQ %c function %p !", irq, isr ); irqList.entry[n].isr = isr; irqList.entry[n].irq = irq; irqList.entry[n].flags = flags; irqList.n++; } // // Installs the IDT in order to activate the interrupts handling // void IdtSetup(void) { // XXX detect the APIC with cpuid ! EnablePIC(); ushort codeSeg = (ushort)(ulong)BtLoaderInfo.codeSegment; // Set IDT ptr idtPtr.limit = (sizeof(IdtEntry_t) * 256) - 1; idtPtr.base = &idt; // Set IDT Exception Gates IdtSetGate(0, (ulong)isr0, codeSeg, 0x8E); IdtSetGate(1, (ulong)isr1, codeSeg, 0x8E); IdtSetGate(2, (ulong)isr2, codeSeg, 0x8E); IdtSetGate(3, (ulong)isr3, codeSeg, 0x8E); IdtSetGate(4, (ulong)isr4, codeSeg, 0x8E); IdtSetGate(5, (ulong)isr5, codeSeg, 0x8E); IdtSetGate(6, (ulong)isr6, codeSeg, 0x8E); IdtSetGate(7, (ulong)isr7, codeSeg, 0x8E); IdtSetGate(8, (ulong)isr8, codeSeg, 0x8E); IdtSetGate(9, (ulong)isr9, codeSeg, 0x8E); IdtSetGate(10, (ulong)isr10, codeSeg, 0x8E); IdtSetGate(11, (ulong)isr11, codeSeg, 0x8E); IdtSetGate(12, (ulong)isr12, codeSeg, 0x8E); IdtSetGate(13, (ulong)isr13, codeSeg, 0x8E); IdtSetGate(14, (ulong)isr14, codeSeg, 0x8E); IdtSetGate(15, (ulong)isr15, codeSeg, 0x8E); // INTEL RESERVED IdtSetGate(16, (ulong)isr16, codeSeg, 0x8E); IdtSetGate(17, (ulong)isr17, codeSeg, 0x8E); IdtSetGate(18, (ulong)isr18, codeSeg, 0x8E); IdtSetGate(19, (ulong)isr19, codeSeg, 0x8E); IdtSetGate(20, (ulong)isr20, codeSeg, 0x8E); IdtSetGate(21, (ulong)isr21, codeSeg, 0x8E); // INTEL RESERVED IdtSetGate(22, (ulong)isr22, codeSeg, 0x8E); // INTEL RESERVED IdtSetGate(23, (ulong)isr23, codeSeg, 0x8E); // INTEL RESERVED IdtSetGate(24, (ulong)isr24, codeSeg, 0x8E); // INTEL RESERVED IdtSetGate(25, (ulong)isr25, codeSeg, 0x8E); // INTEL RESERVED IdtSetGate(26, (ulong)isr26, codeSeg, 0x8E); // INTEL RESERVED IdtSetGate(27, (ulong)isr27, codeSeg, 0x8E); // INTEL RESERVED IdtSetGate(28, (ulong)isr28, codeSeg, 0x8E); // INTEL RESERVED IdtSetGate(29, (ulong)isr29, codeSeg, 0x8E); // INTEL RESERVED IdtSetGate(30, (ulong)isr30, codeSeg, 0x8E); // INTEL RESERVED IdtSetGate(31, (ulong)isr31, codeSeg, 0x8E); // INTEL RESERVED // Set IDT IRQs Gates IdtSetGate(32, (ulong)isr32, codeSeg, 0x8E); IdtSetGate(33, (ulong)isr33, codeSeg, 0x8E); IdtSetGate(34, (ulong)isr34, codeSeg, 0x8E); IdtSetGate(35, (ulong)isr35, codeSeg, 0x8E); IdtSetGate(36, (ulong)isr36, codeSeg, 0x8E); IdtSetGate(37, (ulong)isr37, codeSeg, 0x8E); IdtSetGate(38, (ulong)isr38, codeSeg, 0x8E); IdtSetGate(39, (ulong)isr39, codeSeg, 0x8E); IdtSetGate(40, (ulong)isr40, codeSeg, 0x8E); IdtSetGate(41, (ulong)isr41, codeSeg, 0x8E); IdtSetGate(42, (ulong)isr42, codeSeg, 0x8E); IdtSetGate(43, (ulong)isr43, codeSeg, 0x8E); IdtSetGate(44, (ulong)isr44, codeSeg, 0x8E); IdtSetGate(45, (ulong)isr45, codeSeg, 0x8E); IdtSetGate(46, (ulong)isr46, codeSeg, 0x8E); IdtSetGate(47, (ulong)isr47, codeSeg, 0x8E); // Load IDT IdtInit(); DebugLog("[IdtSetup] Initialized !\n"); } // // Set an interrupt gate // void IdtSetGate(uchar rank, ulong base, ushort selector, uchar flags) { // Set Base Address idt[rank].baseLow = base & 0xFFFF; idt[rank].baseMid = (base >> 16) & 0xFFFF; idt[rank].baseHigh = (base >> 32) & 0xFFFFFFFF; // Set Selector idt[rank].selector = selector; idt[rank].flags = flags; // Set Reserved Areas to Zero idt[rank].reservedIst = 0; idt[rank].reserved = 0; } // // Enable and initializes the PIC to work correctly // static void EnablePIC(void) { // Set ICW1 - begin init of the PIC IoWriteByteOnPort(0x20, 0x11); IoWriteByteOnPort(0xa0, 0x11); // Set ICW2 (IRQ base offsets) IoWriteByteOnPort(0x21, 0x20); //0x20 is the first free interrupt for IRQ0 IoWriteByteOnPort(0xa1, 0x28); // PIC2 is offseted to 0x28 // Set ICW3 IoWriteByteOnPort(0x21, 0x4); IoWriteByteOnPort(0xa1, 0x2); // Set ICW4 IoWriteByteOnPort(0x21, 0x1); IoWriteByteOnPort(0xa1, 0x1); // Set OCW1 (interrupt masks) IoWriteByteOnPort(0x21, 0xff); IoWriteByteOnPort(0xa1, 0xff); } // // Ends the current interrupt handling // void IoSendEOItoPIC(uchar isr) { if(isr >= 8) IoWriteByteOnPort(0xa0,0x20); IoWriteByteOnPort(0x20,0x20); } void IoEnableNMI(void) { IoWriteByteOnPort(0x70, IoReadByteFromPort(0x70) & 0x7F); } void IoDisableNMI(void) { IoWriteByteOnPort(0x70, IoReadByteFromPort(0x70) | 0x80); } // // The main ISR handler // void IsrHandler(ISRFrame_t *regs) { if ((!regs) || (!regs->rip)) KeStartPanic("[ISR ?] Unknown ISR Exception Abort\n"); if ((regs->intNo >= 21) && (regs->intNo <= 31)) return; // INTEL RESERVED if (regs->intNo == 15) return; // INTEL RESERVED if (regs->intNo < 32) { IdtExceptionHandler(regs); return; } for (int i = 0; i < irqList.n; i++) { if (regs->intNo == irqList.entry[i].irq) { irqList.entry[i].isr(regs); return; } } bprintf(BStdOut, "[ISR 0x%x] %s\n", regs->intNo, "Unknown ISR Exception"); BStdOut->flusher(BStdOut); IoSendEOItoPIC(regs->intNo); /* KeStartPanic("[ISR 0x%x] Unknown ISR Exception Abort\n" */ /* " Error code : 0x%x\n" */ /* " RIP:\t\t%p\n" */ /* " CS:\t\t%p\n" */ /* " RFLAGS:\t%022b\n" */ /* " RSP:\t\t%p\n" */ /* " SS:\t\t%p\n", */ /* regs->intNo, */ /* regs->ErrorCode, */ /* regs->rip, */ /* regs->cs, */ /* regs->rflags, */ /* regs->rsp, */ /* regs->ss */ /* ); */ } // // CPU Exception handler // void IdtExceptionHandler(ISRFrame_t *regs) { int recoverable = 0; char *exceptionMsg = "Unhandled ISR exception"; exceptionMsg = IsrExceptions[regs->intNo]; if (!recoverable) { KeStartPanic("[ISR 0x%x] Irrecoverable Kernel %s\n" " Error code : 0x%x\n" " RIP:\t\t%p\n" " CS:\t\t%p\n" " RFLAGS:\t%022b\n" " RSP:\t\t%p\n" " SS:\t\t%p\n", regs->intNo, exceptionMsg, regs->ErrorCode, regs->rip, regs->cs, regs->rflags, regs->rsp, regs->ss ); } else { bprintf(BStdOut, "[ISR 0x%x] %s\n", regs->intNo, exceptionMsg); BStdOut->flusher(BStdOut); } }