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>
24 #include <internal/debug.h>
26 /* GLOBALS ******************************************************************/;
29 /* FUNCTIONS ****************************************************************/
31 KIRQL STDCALL
KeGetCurrentIrql (VOID
)
33 * PURPOSE: Returns the current irq level
34 * RETURNS: The current irq level
40 Ki386SaveFlags(Flags
);
41 Ki386DisableInterrupts();
43 irql
= Ki386ReadFsByte(offsetof(KPCR
, Irql
));
44 if (irql
> HIGH_LEVEL
)
46 DPRINT1 ("CurrentIrql %x\n", irql
);
49 if (Flags
& X86_EFLAGS_IF
)
51 Ki386EnableInterrupts();
57 VOID
KeSetCurrentIrql (KIRQL NewIrql
)
59 * PURPOSE: Sets the current irq level without taking any action
63 if (NewIrql
> HIGH_LEVEL
)
65 DPRINT1 ("NewIrql %x\n", NewIrql
);
68 Ki386SaveFlags(Flags
);
69 Ki386DisableInterrupts();
70 Ki386WriteFsByte(offsetof(KPCR
, Irql
), NewIrql
);
71 if (Flags
& X86_EFLAGS_IF
)
73 Ki386EnableInterrupts();
78 HalpLowerIrql(KIRQL NewIrql
, BOOL FromHalEndSystemInterrupt
)
81 if (NewIrql
>= DISPATCH_LEVEL
)
83 KeSetCurrentIrql (NewIrql
);
84 APICWrite(APIC_TPR
, IRQL2TPR (NewIrql
) & APIC_TPR_PRI
);
87 Ki386SaveFlags(Flags
);
88 if (KeGetCurrentIrql() > APC_LEVEL
)
90 KeSetCurrentIrql (DISPATCH_LEVEL
);
91 APICWrite(APIC_TPR
, IRQL2TPR (DISPATCH_LEVEL
) & APIC_TPR_PRI
);
92 if (FromHalEndSystemInterrupt
|| Ki386ReadFsByte(offsetof(KPCR
, HalReserved
[HAL_DPC_REQUEST
])))
94 Ki386WriteFsByte(offsetof(KPCR
, HalReserved
[HAL_DPC_REQUEST
]), 0);
95 Ki386EnableInterrupts();
96 KiDispatchInterrupt();
97 if (!(Flags
& X86_EFLAGS_IF
))
99 Ki386DisableInterrupts();
102 KeSetCurrentIrql (APC_LEVEL
);
104 if (NewIrql
== APC_LEVEL
)
108 if (KeGetCurrentThread () != NULL
&&
109 KeGetCurrentThread ()->ApcState
.KernelApcPending
)
111 Ki386EnableInterrupts();
112 KiDeliverApc(KernelMode
, NULL
, NULL
);
113 if (!(Flags
& X86_EFLAGS_IF
))
115 Ki386DisableInterrupts();
118 KeSetCurrentIrql (PASSIVE_LEVEL
);
122 /**********************************************************************
127 * Restores the irq level on the current processor
130 * NewIrql = Irql to lower to
136 * Uses fastcall convention
139 KfLowerIrql (KIRQL NewIrql
)
141 KIRQL oldIrql
= KeGetCurrentIrql();
142 if (NewIrql
> oldIrql
)
144 DPRINT1 ("NewIrql %x CurrentIrql %x\n", NewIrql
, oldIrql
);
147 HalpLowerIrql (NewIrql
, FALSE
);
151 /**********************************************************************
156 * Restores the irq level on the current processor
159 * NewIrql = Irql to lower to
168 KeLowerIrql (KIRQL NewIrql
)
170 KfLowerIrql (NewIrql
);
174 /**********************************************************************
179 * Raises the hardware priority (irql)
182 * NewIrql = Irql to raise to
188 * Uses fastcall convention
192 KfRaiseIrql (KIRQL NewIrql
)
197 Ki386SaveFlags(Flags
);
198 Ki386DisableInterrupts();
200 OldIrql
= KeGetCurrentIrql ();
202 if (NewIrql
< OldIrql
)
204 DPRINT1 ("CurrentIrql %x NewIrql %x\n", KeGetCurrentIrql (), NewIrql
);
209 if (NewIrql
> DISPATCH_LEVEL
)
211 APICWrite (APIC_TPR
, IRQL2TPR(NewIrql
) & APIC_TPR_PRI
);
213 KeSetCurrentIrql (NewIrql
);
214 if (Flags
& X86_EFLAGS_IF
)
216 Ki386EnableInterrupts();
223 /**********************************************************************
228 * Raises the hardware priority (irql)
231 * NewIrql = Irql to raise to
232 * OldIrql (OUT) = Caller supplied storage for the previous irql
241 KeRaiseIrql (KIRQL NewIrql
,
244 *OldIrql
= KfRaiseIrql (NewIrql
);
248 /**********************************************************************
250 * KeRaiseIrqlToDpcLevel
253 * Raises the hardware priority (irql) to DISPATCH level
266 KeRaiseIrqlToDpcLevel (VOID
)
268 return KfRaiseIrql (DISPATCH_LEVEL
);
272 /**********************************************************************
274 * KeRaiseIrqlToSynchLevel
277 * Raises the hardware priority (irql) to CLOCK2 level
290 KeRaiseIrqlToSynchLevel (VOID
)
292 return KfRaiseIrql (CLOCK2_LEVEL
);
297 HalBeginSystemInterrupt (ULONG Vector
,
302 DPRINT("Vector (0x%X) Irql (0x%X)\n", Vector
, Irql
);
304 if (KeGetCurrentIrql () >= Irql
)
306 DPRINT1("current irql %d, new irql %d\n", KeGetCurrentIrql(), Irql
);
310 Ki386SaveFlags(Flags
);
311 if (Flags
& X86_EFLAGS_IF
)
313 DPRINT1("HalBeginSystemInterrupt was called with interrupt's enabled\n");
316 APICWrite (APIC_TPR
, IRQL2TPR (Irql
) & APIC_TPR_PRI
);
317 *OldIrql
= KeGetCurrentIrql ();
318 KeSetCurrentIrql (Irql
);
324 HalEndSystemInterrupt (KIRQL Irql
,
327 * FUNCTION: Finish a system interrupt and restore the specified irq level.
331 Ki386SaveFlags(Flags
);
333 if (Flags
& X86_EFLAGS_IF
)
335 DPRINT1("HalEndSystemInterrupt was called with interrupt's enabled\n");
339 HalpLowerIrql (Irql
, TRUE
);
343 HalDisableSystemInterrupt (ULONG Vector
,
348 DPRINT ("Vector (0x%X)\n", Vector
);
350 if (Vector
< FIRST_DEVICE_VECTOR
||
351 Vector
>= FIRST_DEVICE_VECTOR
+ NUMBER_DEVICE_VECTORS
)
353 DPRINT1("Not a device interrupt, vector=%x\n", Vector
);
357 irq
= VECTOR2IRQ (Vector
);
365 HalEnableSystemInterrupt (ULONG Vector
,
367 KINTERRUPT_MODE InterruptMode
)
371 if (Vector
< FIRST_DEVICE_VECTOR
||
372 Vector
>= FIRST_DEVICE_VECTOR
+ NUMBER_DEVICE_VECTORS
)
374 DPRINT("Not a device interrupt\n");
378 /* FIXME: We must check if the requested and the assigned interrupt mode is the same */
380 irq
= VECTOR2IRQ (Vector
);
381 IOAPICUnmaskIrq (irq
);
387 HalRequestSoftwareInterrupt(IN KIRQL Request
)
392 Ki386WriteFsByte(offsetof(KPCR
, HalReserved
[HAL_APC_REQUEST
]), 1);
396 Ki386WriteFsByte(offsetof(KPCR
, HalReserved
[HAL_DPC_REQUEST
]), 1);