2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
4 * FILE: ntoskrnl/hal/x86/mpsirql.c
5 * PURPOSE: Implements IRQLs for multiprocessor systems
6 * PROGRAMMERS: David Welch (welch@cwcom.net)
7 * Casper S. Hornstrup (chorns@users.sourceforge.net)
9 * 12/04/2001 CSH Created
12 /* INCLUDES *****************************************************************/
14 #include <ddk/ntddk.h>
15 #include <internal/ke.h>
16 #include <internal/ps.h>
20 #include <internal/debug.h>
22 /* GLOBALS ******************************************************************/;
24 extern IMPORTED ULONG DpcQueueSize;
26 static VOID KeSetCurrentIrql(KIRQL newlvl);
28 /* FUNCTIONS ****************************************************************/
30 #define IRQL2TPR(irql) (APIC_TPR_MIN + ((irql - DISPATCH_LEVEL - 1) * 8))
32 static VOID HiSetCurrentPriority(
35 //DbgPrint(" P(0x%X)\n", Priority);
36 APICWrite(APIC_TPR, Priority & APIC_TPR_PRI);
40 static VOID HiSwitchIrql(KIRQL OldIrql, ULONG Flags)
42 * FUNCTION: Switches to the current irql
43 * NOTE: Must be called with interrupt disabled
46 PKTHREAD CurrentThread;
49 //DbgPrint("HiSwitchIrql(OldIrql %d)\n", OldIrql);
51 CurrentIrql = KeGetCurrentKPCR()->Irql;
53 if (CurrentIrql >= IPI_LEVEL)
55 /* Block all interrupts */
56 HiSetCurrentPriority(APIC_TPR_MAX);
60 if (CurrentIrql == CLOCK2_LEVEL)
62 HiSetCurrentPriority(APIC_TPR_MAX - 16);
67 if (CurrentIrql > DISPATCH_LEVEL)
69 HiSetCurrentPriority(IRQL2TPR(CurrentIrql));
74 /* Pass all interrupts */
75 HiSetCurrentPriority(0);
77 if (CurrentIrql == DISPATCH_LEVEL)
83 if (CurrentIrql == APC_LEVEL)
85 if (DpcQueueSize > 0 )
87 KeSetCurrentIrql(DISPATCH_LEVEL);
89 KiDispatchInterrupt();
91 KeSetCurrentIrql(PASSIVE_LEVEL);
97 CurrentThread = KeGetCurrentThread();
99 if (CurrentIrql == PASSIVE_LEVEL &&
100 CurrentThread != NULL &&
101 CurrentThread->ApcState.KernelApcPending)
103 KeSetCurrentIrql(APC_LEVEL);
105 KiDeliverApc(0, 0, 0);
107 KeSetCurrentIrql(PASSIVE_LEVEL);
117 KIRQL STDCALL KeGetCurrentIrql (VOID)
119 * PURPOSE: Returns the current irq level
120 * RETURNS: The current irq level
123 return(KeGetCurrentKPCR()->Irql);
127 static VOID KeSetCurrentIrql(KIRQL newlvl)
129 * PURPOSE: Sets the current irq level without taking any action
132 // DPRINT("KeSetCurrentIrql(newlvl %x)\n",newlvl);
134 KeGetCurrentKPCR()->Irql = newlvl;
138 /**********************************************************************
143 * Restores the irq level on the current processor
146 * NewIrql = Irql to lower to
152 * Uses fastcall convention
164 //DbgPrint("KfLowerIrql(NewIrql %d)\n", NewIrql);
167 __asm__ ("\n\tcli\n\t");
169 CurrentIrql = KeGetCurrentKPCR()->Irql;
171 if (NewIrql > CurrentIrql)
173 DbgPrint ("(%s:%d) NewIrql %x CurrentIrql %x\n",
174 __FILE__, __LINE__, NewIrql, CurrentIrql);
179 OldIrql = CurrentIrql;
180 KeGetCurrentKPCR()->Irql = NewIrql;
181 HiSwitchIrql(OldIrql, Flags);
185 /**********************************************************************
190 * Restores the irq level on the current processor
193 * NewIrql = Irql to lower to
207 KfLowerIrql (NewIrql);
211 /**********************************************************************
216 * Raises the hardware priority (irql)
219 * NewIrql = Irql to raise to
225 * Uses fastcall convention
238 //DbgPrint("KfRaiseIrql(NewIrql %d)\n", NewIrql);
241 __asm__ ("\n\tcli\n\t");
243 CurrentIrql = KeGetCurrentKPCR()->Irql;
245 if (NewIrql < CurrentIrql)
247 DbgPrint ("%s:%d CurrentIrql %x NewIrql %x\n",
248 __FILE__,__LINE__,CurrentIrql,NewIrql);
253 OldIrql = CurrentIrql;
254 KeGetCurrentKPCR()->Irql = NewIrql;
256 //DPRINT("NewIrql %x OldIrql %x\n", NewIrql, OldIrql);
257 HiSwitchIrql(OldIrql, Flags);
262 /**********************************************************************
267 * Raises the hardware priority (irql)
270 * NewIrql = Irql to raise to
271 * OldIrql (OUT) = Caller supplied storage for the previous irql
287 *OldIrql = KfRaiseIrql (NewIrql);
291 /**********************************************************************
293 * KeRaiseIrqlToDpcLevel
296 * Raises the hardware priority (irql) to DISPATCH level
310 KeRaiseIrqlToDpcLevel (VOID)
312 return KfRaiseIrql (DISPATCH_LEVEL);
316 /**********************************************************************
318 * KeRaiseIrqlToSynchLevel
321 * Raises the hardware priority (irql) to CLOCK2 level
335 KeRaiseIrqlToSynchLevel (VOID)
337 return KfRaiseIrql (CLOCK2_LEVEL);
341 BOOLEAN STDCALL HalBeginSystemInterrupt (ULONG Vector,
345 DPRINT("Vector (0x%X) Irql (0x%X)\n",
348 if (Vector < FIRST_DEVICE_VECTOR ||
349 Vector > FIRST_DEVICE_VECTOR + NUMBER_DEVICE_VECTORS) {
350 DPRINT("Not a device interrupt\n");
355 * Acknowledge the interrupt
359 *OldIrql = KeGetCurrentIrql();
361 KeSetCurrentIrql(Irql);
367 VOID STDCALL HalEndSystemInterrupt (KIRQL Irql,
370 KeSetCurrentIrql(Irql);
374 BOOLEAN STDCALL HalDisableSystemInterrupt (ULONG Vector,
379 DPRINT("Vector (0x%X)\n", Vector);
381 if (Vector < FIRST_DEVICE_VECTOR ||
382 Vector > FIRST_DEVICE_VECTOR + NUMBER_DEVICE_VECTORS) {
383 DPRINT("Not a device interrupt\n");
387 irq = VECTOR2IRQ(Vector);
389 IOAPICMaskIrq(0, irq);
395 BOOLEAN STDCALL HalEnableSystemInterrupt (ULONG Vector,
401 DPRINT("Vector (0x%X)\n", Vector);
403 if (Vector < FIRST_DEVICE_VECTOR ||
404 Vector > FIRST_DEVICE_VECTOR + NUMBER_DEVICE_VECTORS) {
405 DPRINT("Not a device interrupt\n");
409 irq = VECTOR2IRQ(Vector);
411 IOAPICUnmaskIrq(0, irq);