diff options
| author | Scott Gasch <[email protected]> | 2016-06-01 19:37:09 -0700 |
|---|---|---|
| committer | Scott Gasch <[email protected]> | 2016-06-01 19:37:09 -0700 |
| commit | 0a41dae5f406d498b5c9ab1542cb5660e0d982f6 (patch) | |
| tree | 67ade9fe31cfd0458cc485e95550f7aaf14abdd1 /kernel/hal/interrupts.c | |
Diffstat (limited to 'kernel/hal/interrupts.c')
| -rw-r--r-- | kernel/hal/interrupts.c | 230 |
1 files changed, 230 insertions, 0 deletions
diff --git a/kernel/hal/interrupts.c b/kernel/hal/interrupts.c new file mode 100644 index 0000000..94f2528 --- /dev/null +++ b/kernel/hal/interrupts.c @@ -0,0 +1,230 @@ +//+---------------------------------------------------------------------------- +// +// 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(); +} + |
