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>
17 #include <ntos/minmax.h>
25 #include <internal/debug.h>
27 /* GLOBALS ******************************************************************/;
30 /* FUNCTIONS ****************************************************************/
32 KIRQL STDCALL
KeGetCurrentIrql (VOID
)
34 * PURPOSE: Returns the current irq level
35 * RETURNS: The current irq level
41 Ki386SaveFlags(Flags
);
42 Ki386DisableInterrupts();
44 irql
= Ki386ReadFsByte(offsetof(KPCR
, Irql
));
45 if (irql
> HIGH_LEVEL
)
47 DPRINT1 ("CurrentIrql %x\n", irql
);
50 if (Flags
& X86_EFLAGS_IF
)
52 Ki386EnableInterrupts();
58 VOID
KeSetCurrentIrql (KIRQL NewIrql
)
60 * PURPOSE: Sets the current irq level without taking any action
64 if (NewIrql
> HIGH_LEVEL
)
66 DPRINT1 ("NewIrql %x\n", NewIrql
);
69 Ki386SaveFlags(Flags
);
70 Ki386DisableInterrupts();
71 Ki386WriteFsByte(offsetof(KPCR
, Irql
), NewIrql
);
72 if (Flags
& X86_EFLAGS_IF
)
74 Ki386EnableInterrupts();
79 HalpLowerIrql(KIRQL NewIrql
, BOOL FromHalEndSystemInterrupt
)
82 if (NewIrql
>= DISPATCH_LEVEL
)
84 KeSetCurrentIrql (NewIrql
);
85 APICWrite(APIC_TPR
, IRQL2TPR (NewIrql
) & APIC_TPR_PRI
);
88 Ki386SaveFlags(Flags
);
89 if (KeGetCurrentIrql() > APC_LEVEL
)
91 KeSetCurrentIrql (DISPATCH_LEVEL
);
92 APICWrite(APIC_TPR
, IRQL2TPR (DISPATCH_LEVEL
) & APIC_TPR_PRI
);
93 if (FromHalEndSystemInterrupt
|| Ki386ReadFsByte(offsetof(KPCR
, HalReserved
[HAL_DPC_REQUEST
])))
95 Ki386WriteFsByte(offsetof(KPCR
, HalReserved
[HAL_DPC_REQUEST
]), 0);
96 Ki386EnableInterrupts();
97 KiDispatchInterrupt();
98 if (!(Flags
& X86_EFLAGS_IF
))
100 Ki386DisableInterrupts();
103 KeSetCurrentIrql (APC_LEVEL
);
105 if (NewIrql
== APC_LEVEL
)
109 if (KeGetCurrentThread () != NULL
&&
110 KeGetCurrentThread ()->ApcState
.KernelApcPending
)
112 Ki386EnableInterrupts();
113 KiDeliverApc(KernelMode
, NULL
, NULL
);
114 if (!(Flags
& X86_EFLAGS_IF
))
116 Ki386DisableInterrupts();
119 KeSetCurrentIrql (PASSIVE_LEVEL
);
123 /**********************************************************************
128 * Restores the irq level on the current processor
131 * NewIrql = Irql to lower to
137 * Uses fastcall convention
140 KfLowerIrql (KIRQL NewIrql
)
142 KIRQL oldIrql
= KeGetCurrentIrql();
143 if (NewIrql
> oldIrql
)
145 DPRINT1 ("NewIrql %x CurrentIrql %x\n", NewIrql
, oldIrql
);
148 HalpLowerIrql (NewIrql
, FALSE
);
152 /**********************************************************************
157 * Restores the irq level on the current processor
160 * NewIrql = Irql to lower to
169 KeLowerIrql (KIRQL NewIrql
)
171 KfLowerIrql (NewIrql
);
175 /**********************************************************************
180 * Raises the hardware priority (irql)
183 * NewIrql = Irql to raise to
189 * Uses fastcall convention
193 KfRaiseIrql (KIRQL NewIrql
)
198 Ki386SaveFlags(Flags
);
199 Ki386DisableInterrupts();
201 OldIrql
= KeGetCurrentIrql ();
203 if (NewIrql
< OldIrql
)
205 DPRINT1 ("CurrentIrql %x NewIrql %x\n", KeGetCurrentIrql (), NewIrql
);
210 if (NewIrql
> DISPATCH_LEVEL
)
212 APICWrite (APIC_TPR
, IRQL2TPR(NewIrql
) & APIC_TPR_PRI
);
214 KeSetCurrentIrql (NewIrql
);
215 if (Flags
& X86_EFLAGS_IF
)
217 Ki386EnableInterrupts();
224 /**********************************************************************
229 * Raises the hardware priority (irql)
232 * NewIrql = Irql to raise to
233 * OldIrql (OUT) = Caller supplied storage for the previous irql
242 KeRaiseIrql (KIRQL NewIrql
,
245 *OldIrql
= KfRaiseIrql (NewIrql
);
249 /**********************************************************************
251 * KeRaiseIrqlToDpcLevel
254 * Raises the hardware priority (irql) to DISPATCH level
267 KeRaiseIrqlToDpcLevel (VOID
)
269 return KfRaiseIrql (DISPATCH_LEVEL
);
273 /**********************************************************************
275 * KeRaiseIrqlToSynchLevel
278 * Raises the hardware priority (irql) to CLOCK2 level
291 KeRaiseIrqlToSynchLevel (VOID
)
293 return KfRaiseIrql (CLOCK2_LEVEL
);
298 HalBeginSystemInterrupt (ULONG Vector
,
303 DPRINT("Vector (0x%X) Irql (0x%X)\n", Vector
, Irql
);
305 if (KeGetCurrentIrql () >= Irql
)
307 DPRINT1("current irql %d, new irql %d\n", KeGetCurrentIrql(), Irql
);
311 Ki386SaveFlags(Flags
);
312 if (Flags
& X86_EFLAGS_IF
)
314 DPRINT1("HalBeginSystemInterrupt was called with interrupt's enabled\n");
317 APICWrite (APIC_TPR
, IRQL2TPR (Irql
) & APIC_TPR_PRI
);
318 *OldIrql
= KeGetCurrentIrql ();
319 KeSetCurrentIrql (Irql
);
325 HalEndSystemInterrupt (KIRQL Irql
,
328 * FUNCTION: Finish a system interrupt and restore the specified irq level.
332 Ki386SaveFlags(Flags
);
334 if (Flags
& X86_EFLAGS_IF
)
336 DPRINT1("HalEndSystemInterrupt was called with interrupt's enabled\n");
340 HalpLowerIrql (Irql
, TRUE
);
344 HalDisableSystemInterrupt (ULONG Vector
,
349 DPRINT ("Vector (0x%X)\n", Vector
);
351 if (Vector
< FIRST_DEVICE_VECTOR
||
352 Vector
>= FIRST_DEVICE_VECTOR
+ NUMBER_DEVICE_VECTORS
)
354 DPRINT1("Not a device interrupt, vector=%x\n", Vector
);
358 irq
= VECTOR2IRQ (Vector
);
366 HalEnableSystemInterrupt (ULONG Vector
,
368 KINTERRUPT_MODE InterruptMode
)
372 if (Vector
< FIRST_DEVICE_VECTOR
||
373 Vector
>= FIRST_DEVICE_VECTOR
+ NUMBER_DEVICE_VECTORS
)
375 DPRINT("Not a device interrupt\n");
379 /* FIXME: We must check if the requested and the assigned interrupt mode is the same */
381 irq
= VECTOR2IRQ (Vector
);
382 IOAPICUnmaskIrq (irq
);
388 HalRequestSoftwareInterrupt(IN KIRQL Request
)
393 Ki386WriteFsByte(offsetof(KPCR
, HalReserved
[HAL_APC_REQUEST
]), 1);
397 Ki386WriteFsByte(offsetof(KPCR
, HalReserved
[HAL_DPC_REQUEST
]), 1);