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 *****************************************************************/
18 /* GLOBALS ******************************************************************/;
21 /* FUNCTIONS ****************************************************************/
23 #undef KeGetCurrentIrql
24 KIRQL STDCALL
KeGetCurrentIrql (VOID
)
26 * PURPOSE: Returns the current irq level
27 * RETURNS: The current irq level
33 Ke386SaveFlags(Flags
);
36 irql
= __readfsbyte(FIELD_OFFSET(KPCR
, Irql
));
37 if (irql
> HIGH_LEVEL
)
39 DPRINT1 ("CurrentIrql %x\n", irql
);
42 if (Flags
& EFLAGS_INTERRUPT_MASK
)
50 #undef KeSetCurrentIrql
51 VOID
KeSetCurrentIrql (KIRQL NewIrql
)
53 * PURPOSE: Sets the current irq level without taking any action
57 if (NewIrql
> HIGH_LEVEL
)
59 DPRINT1 ("NewIrql %x\n", NewIrql
);
62 Ke386SaveFlags(Flags
);
64 __writefsbyte(FIELD_OFFSET(KPCR
, Irql
), NewIrql
);
65 if (Flags
& EFLAGS_INTERRUPT_MASK
)
72 HalpLowerIrql(KIRQL NewIrql
, BOOLEAN FromHalEndSystemInterrupt
)
76 if (NewIrql
>= DISPATCH_LEVEL
)
78 KeSetCurrentIrql (NewIrql
);
79 APICWrite(APIC_TPR
, IRQL2TPR (NewIrql
) & APIC_TPR_PRI
);
82 Ke386SaveFlags(Flags
);
83 if (KeGetCurrentIrql() > APC_LEVEL
)
85 KeSetCurrentIrql (DISPATCH_LEVEL
);
86 APICWrite(APIC_TPR
, IRQL2TPR (DISPATCH_LEVEL
) & APIC_TPR_PRI
);
87 DpcRequested
= __readfsbyte(FIELD_OFFSET(KIPCR
, HalReserved
[HAL_DPC_REQUEST
]));
88 if (FromHalEndSystemInterrupt
|| DpcRequested
)
90 __writefsbyte(FIELD_OFFSET(KIPCR
, HalReserved
[HAL_DPC_REQUEST
]), 0);
92 KiDispatchInterrupt();
93 if (!(Flags
& EFLAGS_INTERRUPT_MASK
))
98 KeSetCurrentIrql (APC_LEVEL
);
100 if (NewIrql
== APC_LEVEL
)
104 if (KeGetCurrentThread () != NULL
&&
105 KeGetCurrentThread ()->ApcState
.KernelApcPending
)
108 KiDeliverApc(KernelMode
, NULL
, NULL
);
109 if (!(Flags
& EFLAGS_INTERRUPT_MASK
))
114 KeSetCurrentIrql (PASSIVE_LEVEL
);
118 /**********************************************************************
123 * Restores the irq level on the current processor
126 * NewIrql = Irql to lower to
132 * Uses fastcall convention
135 KfLowerIrql (KIRQL NewIrql
)
137 KIRQL oldIrql
= KeGetCurrentIrql();
138 if (NewIrql
> oldIrql
)
140 DPRINT1 ("NewIrql %x CurrentIrql %x\n", NewIrql
, oldIrql
);
143 HalpLowerIrql (NewIrql
, FALSE
);
147 /**********************************************************************
152 * Restores the irq level on the current processor
155 * NewIrql = Irql to lower to
164 KeLowerIrql (KIRQL NewIrql
)
166 KfLowerIrql (NewIrql
);
170 /**********************************************************************
175 * Raises the hardware priority (irql)
178 * NewIrql = Irql to raise to
184 * Uses fastcall convention
188 KfRaiseIrql (KIRQL NewIrql
)
193 Ke386SaveFlags(Flags
);
196 OldIrql
= KeGetCurrentIrql ();
198 if (NewIrql
< OldIrql
)
200 DPRINT1 ("CurrentIrql %x NewIrql %x\n", KeGetCurrentIrql (), NewIrql
);
205 if (NewIrql
> DISPATCH_LEVEL
)
207 APICWrite (APIC_TPR
, IRQL2TPR(NewIrql
) & APIC_TPR_PRI
);
209 KeSetCurrentIrql (NewIrql
);
210 if (Flags
& EFLAGS_INTERRUPT_MASK
)
219 /**********************************************************************
224 * Raises the hardware priority (irql)
227 * NewIrql = Irql to raise to
228 * OldIrql (OUT) = Caller supplied storage for the previous irql
238 KeRaiseIrql (KIRQL NewIrql
,
241 *OldIrql
= KfRaiseIrql (NewIrql
);
245 /**********************************************************************
247 * KeRaiseIrqlToDpcLevel
250 * Raises the hardware priority (irql) to DISPATCH level
263 KeRaiseIrqlToDpcLevel (VOID
)
265 return KfRaiseIrql (DISPATCH_LEVEL
);
269 /**********************************************************************
271 * KeRaiseIrqlToSynchLevel
274 * Raises the hardware priority (irql) to CLOCK2 level
287 KeRaiseIrqlToSynchLevel (VOID
)
289 return KfRaiseIrql (CLOCK2_LEVEL
);
294 HalBeginSystemInterrupt (KIRQL Irql
,
299 DPRINT("Vector (0x%X) Irql (0x%X)\n", Vector
, Irql
);
301 if (KeGetCurrentIrql () >= Irql
)
303 DPRINT1("current irql %d, new irql %d\n", KeGetCurrentIrql(), Irql
);
307 Ke386SaveFlags(Flags
);
308 if (Flags
& EFLAGS_INTERRUPT_MASK
)
310 DPRINT1("HalBeginSystemInterrupt was called with interrupt's enabled\n");
313 APICWrite (APIC_TPR
, IRQL2TPR (Irql
) & APIC_TPR_PRI
);
314 *OldIrql
= KeGetCurrentIrql ();
315 KeSetCurrentIrql (Irql
);
321 HalEndSystemInterrupt (KIRQL Irql
,
324 * FUNCTION: Finish a system interrupt and restore the specified irq level.
328 Ke386SaveFlags(Flags
);
330 if (Flags
& EFLAGS_INTERRUPT_MASK
)
332 DPRINT1("HalEndSystemInterrupt was called with interrupt's enabled\n");
336 HalpLowerIrql (Irql
, TRUE
);
340 HalDisableSystemInterrupt (ULONG Vector
,
345 DPRINT ("Vector (0x%X)\n", Vector
);
347 if (Vector
< FIRST_DEVICE_VECTOR
||
348 Vector
>= FIRST_DEVICE_VECTOR
+ NUMBER_DEVICE_VECTORS
)
350 DPRINT1("Not a device interrupt, vector=%x\n", Vector
);
354 irq
= VECTOR2IRQ (Vector
);
362 HalEnableSystemInterrupt (ULONG Vector
,
364 KINTERRUPT_MODE InterruptMode
)
368 if (Vector
< FIRST_DEVICE_VECTOR
||
369 Vector
>= FIRST_DEVICE_VECTOR
+ NUMBER_DEVICE_VECTORS
)
371 DPRINT("Not a device interrupt\n");
375 /* FIXME: We must check if the requested and the assigned interrupt mode is the same */
377 irq
= VECTOR2IRQ (Vector
);
378 IOAPICUnmaskIrq (irq
);
384 HalRequestSoftwareInterrupt(IN KIRQL Request
)
389 __writefsbyte(FIELD_OFFSET(KIPCR
, HalReserved
[HAL_APC_REQUEST
]), 1);
393 __writefsbyte(FIELD_OFFSET(KIPCR
, HalReserved
[HAL_DPC_REQUEST
]), 1);
402 HalClearSoftwareInterrupt(