2 * This is the device-driver interface to the interrupt system.
3 * Copyright (c) 2001,2003 David H. Hovemeyer <daveho@cs.umd.edu>
6 * This is free software. You are permitted to use,
7 * redistribute, and modify it as specified in the file "COPYING".
10 #include <geekos/kassert.h>
11 #include <geekos/idt.h>
12 #include <geekos/io.h>
13 #include <geekos/irq.h>
15 #include <geekos/debug.h>
17 /* ----------------------------------------------------------------------
18 * Private functions and data
19 * ---------------------------------------------------------------------- */
23 * This should be kept up to date with setup.asm
24 * (which does the initial programming of the PICs).
26 static ushort_t s_irqMask = 0xfffb;
29 * Get the master and slave parts of an IRQ mask.
31 #define MASTER(mask) ((mask) & 0xff)
32 #define SLAVE(mask) (((mask)>>8) & 0xff)
35 /* ----------------------------------------------------------------------
37 * ---------------------------------------------------------------------- */
40 * Install a handler for given IRQ.
41 * Note that we don't unmask the IRQ.
43 void Install_IRQ(int irq, Interrupt_Handler handler)
45 Install_Interrupt_Handler(irq + FIRST_EXTERNAL_INT, handler);
49 * Get current IRQ mask. Each bit position represents
50 * one of the 16 IRQ lines.
52 ushort_t Get_IRQ_Mask(void)
60 void Set_IRQ_Mask(ushort_t mask)
62 uchar_t oldMask, newMask;
64 oldMask = MASTER(s_irqMask);
65 newMask = MASTER(mask);
66 if (newMask != oldMask) {
67 Out_Byte(0x21, newMask);
70 oldMask = SLAVE(s_irqMask);
71 newMask = SLAVE(mask);
72 if (newMask != oldMask) {
73 Out_Byte(0xA1, newMask);
82 void Enable_IRQ(int irq)
84 bool iflag = Begin_Int_Atomic();
86 KASSERT(irq >= 0 && irq < 16);
87 ushort_t mask = Get_IRQ_Mask();
91 End_Int_Atomic(iflag);
97 void Disable_IRQ(int irq)
99 bool iflag = Begin_Int_Atomic();
101 KASSERT(irq >= 0 && irq < 16);
102 ushort_t mask = Get_IRQ_Mask();
106 End_Int_Atomic(iflag);
110 * Called by an IRQ handler to begin the interrupt.
113 void Begin_IRQ(struct Interrupt_State* state)
115 // SerialPrint("Begin_IRQ for interrupt 0x%x\n",state->intNum);
119 * Called by an IRQ handler to end the interrupt.
120 * Sends an EOI command to the appropriate PIC(s).
122 void End_IRQ(struct Interrupt_State* state)
124 int irq = state->intNum - FIRST_EXTERNAL_INT;
129 void End_IRQ_num(int irq) {
130 uchar_t command = 0x60 | (irq & 0x7);
133 /* Specific EOI to master PIC */
134 Out_Byte(0x20, command);
137 /* Specific EOI to slave PIC, then to master (cascade line) */
138 Out_Byte(0xA0, command);
139 Out_Byte(0x20, 0x62);