2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
4 * FILE: ntoskrnl/hal/x86/irql.c
5 * PURPOSE: Implements IRQLs
6 * PROGRAMMER: David Welch (welch@cwcom.net)
9 /* INCLUDES *****************************************************************/
11 #include <ddk/ntddk.h>
12 #include <internal/ke.h>
13 #include <internal/ps.h>
14 #include <ntos/minmax.h>
17 #include <internal/debug.h>
19 /* GLOBALS ******************************************************************/
22 #define IRQ_BASE (0x40)
25 * PURPOSE: Current irq level
27 static KIRQL CurrentIrql = HIGH_LEVEL;
31 extern IMPORTED ULONG DpcQueueSize;
33 static ULONG HalpPendingInterruptCount[NR_IRQS];
35 #define DIRQL_TO_IRQ(x) (PROFILE_LEVEL - x)
36 #define IRQ_TO_DIRQL(x) (PROFILE_LEVEL - x)
39 KiInterruptDispatch2 (ULONG Irq, KIRQL old_level);
41 #endif /* LIBCAPTIVE */
43 /* FUNCTIONS ****************************************************************/
45 KIRQL STDCALL KeGetCurrentIrql (VOID)
47 * PURPOSE: Returns the current irq level
48 * RETURNS: The current irq level
56 VOID HalpInitPICs(VOID)
58 memset(HalpPendingInterruptCount, 0, sizeof(HalpPendingInterruptCount));
60 /* Initialization sequence */
61 WRITE_PORT_UCHAR((PUCHAR)0x20, 0x11);
62 WRITE_PORT_UCHAR((PUCHAR)0xa0, 0x11);
63 /* Start of hardware irqs (0x24) */
64 WRITE_PORT_UCHAR((PUCHAR)0x21, 0x40);
65 WRITE_PORT_UCHAR((PUCHAR)0xa1, 0x48);
66 /* 8259-1 is master */
67 WRITE_PORT_UCHAR((PUCHAR)0x21, 0x4);
69 WRITE_PORT_UCHAR((PUCHAR)0xa1, 0x2);
71 WRITE_PORT_UCHAR((PUCHAR)0x21, 0x1);
72 WRITE_PORT_UCHAR((PUCHAR)0xa1, 0x1);
73 /* Enable all interrupts from PICs */
74 WRITE_PORT_UCHAR((PUCHAR)0x21, 0x0);
75 WRITE_PORT_UCHAR((PUCHAR)0xa1, 0x0);
77 /* We can now enable interrupts */
78 __asm__ __volatile__ ("sti\n\t");
82 HalpExecuteIrqs(KIRQL NewIrql)
86 IrqLimit = min(PROFILE_LEVEL - NewIrql, NR_IRQS);
89 * For each irq if there have been any deferred interrupts then now
92 for (i = 0; i < IrqLimit; i++)
94 while (HalpPendingInterruptCount[i] > 0)
97 * For each deferred interrupt execute all the handlers at DIRQL.
99 CurrentIrql = IRQ_TO_DIRQL(i);
100 KiInterruptDispatch2(i, NewIrql);
101 HalpPendingInterruptCount[i]--;
107 HalpLowerIrql(KIRQL NewIrql)
109 if (NewIrql > PROFILE_LEVEL)
111 CurrentIrql = NewIrql;
114 HalpExecuteIrqs(NewIrql);
115 if (NewIrql >= DISPATCH_LEVEL)
117 CurrentIrql = NewIrql;
120 CurrentIrql = DISPATCH_LEVEL;
121 if (DpcQueueSize > 0)
123 KiDispatchInterrupt();
125 if (NewIrql == APC_LEVEL)
127 CurrentIrql = NewIrql;
130 CurrentIrql = APC_LEVEL;
131 if (KeGetCurrentThread() != NULL &&
132 KeGetCurrentThread()->ApcState.KernelApcPending)
134 KiDeliverApc(0, 0, 0);
136 CurrentIrql = PASSIVE_LEVEL;
139 #endif /* LIBCAPTIVE */
141 /**********************************************************************
146 * Restores the irq level on the current processor
149 * NewIrql = Irql to lower to
155 * Uses fastcall convention
158 KfLowerIrql (KIRQL NewIrql)
162 DPRINT("KfLowerIrql(NewIrql %d)\n", NewIrql);
164 if (NewIrql > CurrentIrql)
166 DbgPrint ("(%s:%d) NewIrql %x CurrentIrql %x\n",
167 __FILE__, __LINE__, NewIrql, CurrentIrql);
173 HalpLowerIrql(NewIrql);
174 #else /* LIBCAPTIVE */
175 CurrentIrql = NewIrql;
176 #endif /* LIBCAPTIVE */
180 /**********************************************************************
185 * Restores the irq level on the current processor
188 * NewIrql = Irql to lower to
197 KeLowerIrql (KIRQL NewIrql)
199 KfLowerIrql (NewIrql);
203 /**********************************************************************
208 * Raises the hardware priority (irql)
211 * NewIrql = Irql to raise to
217 * Uses fastcall convention
221 KfRaiseIrql (KIRQL NewIrql)
225 DPRINT("KfRaiseIrql(NewIrql %d)\n", NewIrql);
227 if (NewIrql < CurrentIrql)
229 DbgPrint ("%s:%d CurrentIrql %x NewIrql %x\n",
230 __FILE__,__LINE__,CurrentIrql,NewIrql);
235 OldIrql = CurrentIrql;
236 CurrentIrql = NewIrql;
241 /**********************************************************************
246 * Raises the hardware priority (irql)
249 * NewIrql = Irql to raise to
250 * OldIrql (OUT) = Caller supplied storage for the previous irql
259 KeRaiseIrql (KIRQL NewIrql,
262 *OldIrql = KfRaiseIrql (NewIrql);
267 /**********************************************************************
269 * KeRaiseIrqlToDpcLevel
272 * Raises the hardware priority (irql) to DISPATCH level
285 KeRaiseIrqlToDpcLevel (VOID)
287 return KfRaiseIrql (DISPATCH_LEVEL);
291 /**********************************************************************
293 * KeRaiseIrqlToSynchLevel
296 * Raises the hardware priority (irql) to CLOCK2 level
309 KeRaiseIrqlToSynchLevel (VOID)
311 return KfRaiseIrql (CLOCK2_LEVEL);
316 HalBeginSystemInterrupt (ULONG Vector,
320 if (Vector < IRQ_BASE || Vector > IRQ_BASE + NR_IRQS)
325 /* Send EOI to the PICs */
326 WRITE_PORT_UCHAR((PUCHAR)0x20,0x20);
327 if ((Vector-IRQ_BASE)>=8)
329 WRITE_PORT_UCHAR((PUCHAR)0xa0,0x20);
332 if (CurrentIrql >= Irql)
334 HalpPendingInterruptCount[Vector - IRQ_BASE]++;
337 *OldIrql = CurrentIrql;
344 VOID STDCALL HalEndSystemInterrupt (KIRQL Irql, ULONG Unknown2)
346 * FUNCTION: Finish a system interrupt and restore the specified irq level.
352 BOOLEAN STDCALL HalDisableSystemInterrupt (ULONG Vector,
357 if (Vector < IRQ_BASE || Vector > IRQ_BASE + NR_IRQS)
360 irq = Vector - IRQ_BASE;
363 WRITE_PORT_UCHAR((PUCHAR)0x21,
364 READ_PORT_UCHAR((PUCHAR)0x21)|(1<<irq));
368 WRITE_PORT_UCHAR((PUCHAR)0xa1,
369 READ_PORT_UCHAR((PUCHAR)0xa1)|(1<<(irq-8)));
376 BOOLEAN STDCALL HalEnableSystemInterrupt (ULONG Vector,
382 if (Vector < IRQ_BASE || Vector > IRQ_BASE + NR_IRQS)
385 irq = Vector - IRQ_BASE;
388 WRITE_PORT_UCHAR((PUCHAR)0x21,
389 READ_PORT_UCHAR((PUCHAR)0x21)&(~(1<<irq)));
393 WRITE_PORT_UCHAR((PUCHAR)0xa1,
394 READ_PORT_UCHAR((PUCHAR)0xa1)&(~(1<<(irq-8))));
400 #endif /* LIBCAPTIVE */