//+---------------------------------------------------------------------------- // // File: interrupts.c // // Module: // // Synopsis: // // Created: sgasch 6 Jul 2003 // //+---------------------------------------------------------------------------- #include "kernel.h" #include "hal.h" #include "rtl.h" #include "interrupts.h" IDT_ENTRY g_IDT[NUM_IDT_ENTRIES]; INTERRUPT_HANDLER g_InterruptHandlerTable[NUM_IDT_ENTRIES]; ULONG g_uInterruptsEnabled = 0; void HalEnableInterrupts(void) { g_uInterruptsEnabled++; ASSERT(g_uInterruptsEnabled == 1); __asm__ __volatile__ ( "sti" ); } void HalDisableInterrupts(void) { g_uInterruptsEnabled--; ASSERT(g_uInterruptsEnabled == 0); __asm__ __volatile__ ( "cli" ); } //+---------------------------------------------------------------------------- // // Function: DoNothing // // Synopsis: The default interrupt handler, do nothing // // Arguments: INTERRUPT_STATE *p // // Returns: void // //+---------------------------------------------------------------------------- void HalDoNothing(INTERRUPT_STATE *p) { ; } //+---------------------------------------------------------------------------- // // Function: InterruptSendIrqEoi // // Synopsis: Send Interrupt ReQuest End Of Interrupt to the PIC. // // Arguments: INTERRUPT_STATE *is // // Returns: void // //+---------------------------------------------------------------------------- void HalInterruptSendIrqEoi(INTERRUPT_STATE *is) { ULONG uIrq; BYTE bCommand; BYTE *p = (BYTE *)0x000B8000; *p = '3'; *(p + 1) = ' '; if ((is->uIntNum >= FIRST_EXTERNAL_INT) && (is->uIntNum <= LAST_EXTERNAL_INT)) { uIrq = (is->uIntNum - FIRST_EXTERNAL_INT); ASSERT(uIrq >= 0); ASSERT(uIrq <= 15); bCommand = 0x60 | (uIrq & 0x7); if (uIrq < 8) { // EOI to master PIC out(0x20, bCommand); HalIoDelay(); } else { // EOI to slave PIC and cascade line EOI to master PIC out(0xA0, bCommand); out(0x20, 0x62); HalIoDelay(); } } *p = '4'; *(p + 1) = ' '; } //+---------------------------------------------------------------------------- // // Function: InterruptInitializeGate // // Synopsis: Initializes an interrupt gate with given handler address // and descriptor privilege level. // // Arguments: IDT_ENTRY *pEntry, // void *pPreamble, // ULONG uDpl // // Returns: void // //+---------------------------------------------------------------------------- void HalInterruptInitializeGate(IDT_ENTRY *pEntry, void *pPreamble, ULONG uDpl) { ULONG u = (ULONG)pPreamble; pEntry->i.offsetLow = u & 0xffff; pEntry->i.segmentSelector = (1<<3); pEntry->i.reserved = 0; pEntry->i.signature = 0x70; // == 01110000b pEntry->i.dpl = uDpl; pEntry->i.present = 1; pEntry->i.offsetHigh = u >> 16; } //+---------------------------------------------------------------------------- // // Function: InterruptInstallHandler // // Synopsis: Installs an interrupt handler routine for a given IRQ number // // Arguments: ULONG uInterruptNumber, // INTERRUPT_HANDLER pHandler // // Returns: void // //+---------------------------------------------------------------------------- void HalInterruptInstallHandler(ULONG uInterruptNumber, INTERRUPT_HANDLER pHandler) { ASSERT(uInterruptNumber < ARRAY_LENGTH(g_InterruptHandlerTable)); g_InterruptHandlerTable[uInterruptNumber] = pHandler; } //+---------------------------------------------------------------------------- // // Function: InterruptInitialize // // Synopsis: Initialize the interrupt system // // Arguments: void // // Returns: void // //+---------------------------------------------------------------------------- void HalInitializeInterrupts(void) { ULONG uPreambleEntrySize = (ULONG)&HalInterruptHandlerPreambleAfter; ULONG u; ULONG uDpl; USHORT uLimitAndBase[3]; BYTE *p; // // Determine the size of an interrupt preamble table entry. // uPreambleEntrySize -= (ULONG)&HalInterruptHandlerPreambleBefore; // // Set the base interrupt number for each PIC. See comments in // intsupport.asm. // HalInterruptInitializePICs(); // // Build interrupt descriptor table // for (u = 0, p = &HalInterruptHandlerPreamble; u < ARRAY_LENGTH(g_IDT); u++, p += uPreambleEntrySize) { uDpl = (u == 0x2E) ? USER_PRIVILEGE : KERNEL_PRIVILEGE; HalInterruptInitializeGate(&(g_IDT[u]), p, uDpl); HalInterruptInstallHandler(u, HalDoNothing); } // // Install the IDT // u = (ULONG)&(g_IDT); uLimitAndBase[0] = 8 * NUM_IDT_ENTRIES; uLimitAndBase[1] = (USHORT)(u & 0xffff); uLimitAndBase[2] = (USHORT)(u >> 16); HalInterruptLoadIDTR((void *)uLimitAndBase); // // Install interrupt handlers // HalInterruptInstallHandler(IRQ0, HalTimerInt); HalInterruptInstallHandler(IRQ1, HalKeyboardInt); out(0x21, 0xFC); // turn on keyboard and timer // // Enable interrupts // HalEnableInterrupts(); }