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
);