summaryrefslogtreecommitdiff
path: root/kernel/hal/interrupts.c
diff options
context:
space:
mode:
authorScott Gasch <[email protected]>2016-06-01 19:37:09 -0700
committerScott Gasch <[email protected]>2016-06-01 19:37:09 -0700
commit0a41dae5f406d498b5c9ab1542cb5660e0d982f6 (patch)
tree67ade9fe31cfd0458cc485e95550f7aaf14abdd1 /kernel/hal/interrupts.c
Initial checkin of toy OS project.HEADmaster
Diffstat (limited to 'kernel/hal/interrupts.c')
-rw-r--r--kernel/hal/interrupts.c230
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();
+}
+