2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
4 * FILE: hal/halx86/mp/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 NTAPI
KeGetCurrentIrql (VOID
)
26 * PURPOSE: Returns the current irq level
27 * RETURNS: The current irq level
33 Flags
= __readeflags();
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 Flags
= __readeflags();
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 Flags
= __readeflags();
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 * Raises the hardware priority (irql)
155 * NewIrql = Irql to raise to
161 * Uses fastcall convention
165 KfRaiseIrql (KIRQL NewIrql
)
170 Flags
= __readeflags();
173 OldIrql
= KeGetCurrentIrql ();
175 if (NewIrql
< OldIrql
)
177 DPRINT1 ("CurrentIrql %x NewIrql %x\n", KeGetCurrentIrql (), NewIrql
);
182 if (NewIrql
> DISPATCH_LEVEL
)
184 APICWrite (APIC_TPR
, IRQL2TPR(NewIrql
) & APIC_TPR_PRI
);
186 KeSetCurrentIrql (NewIrql
);
187 if (Flags
& EFLAGS_INTERRUPT_MASK
)
195 /**********************************************************************
197 * KeRaiseIrqlToDpcLevel
200 * Raises the hardware priority (irql) to DISPATCH level
213 KeRaiseIrqlToDpcLevel (VOID
)
215 return KfRaiseIrql (DISPATCH_LEVEL
);
219 /**********************************************************************
221 * KeRaiseIrqlToSynchLevel
224 * Raises the hardware priority (irql) to CLOCK2 level
237 KeRaiseIrqlToSynchLevel (VOID
)
239 return KfRaiseIrql (CLOCK2_LEVEL
);
244 HalBeginSystemInterrupt (KIRQL Irql
,
249 DPRINT("Vector (0x%X) Irql (0x%X)\n", Vector
, Irql
);
251 if (KeGetCurrentIrql () >= Irql
)
253 DPRINT1("current irql %d, new irql %d\n", KeGetCurrentIrql(), Irql
);
257 Flags
= __readeflags();
258 if (Flags
& EFLAGS_INTERRUPT_MASK
)
260 DPRINT1("HalBeginSystemInterrupt was called with interrupt's enabled\n");
263 APICWrite (APIC_TPR
, IRQL2TPR (Irql
) & APIC_TPR_PRI
);
264 *OldIrql
= KeGetCurrentIrql ();
265 KeSetCurrentIrql (Irql
);
271 HalEndSystemInterrupt (KIRQL Irql
,
272 IN PKTRAP_FRAME TrapFrame
)
274 * FUNCTION: Finish a system interrupt and restore the specified irq level.
278 Flags
= __readeflags();
280 if (Flags
& EFLAGS_INTERRUPT_MASK
)
282 DPRINT1("HalEndSystemInterrupt was called with interrupt's enabled\n");
286 HalpLowerIrql (Irql
, TRUE
);
291 HalDisableSystemInterrupt(UCHAR Vector
,
296 DPRINT ("Vector (0x%X)\n", Vector
);
298 if (Vector
< FIRST_DEVICE_VECTOR
||
299 Vector
>= FIRST_DEVICE_VECTOR
+ NUMBER_DEVICE_VECTORS
)
301 DPRINT1("Not a device interrupt, vector=%x\n", Vector
);
306 irq
= VECTOR2IRQ (Vector
);
314 HalEnableSystemInterrupt (UCHAR Vector
,
316 KINTERRUPT_MODE InterruptMode
)
320 if (Vector
< FIRST_DEVICE_VECTOR
||
321 Vector
>= FIRST_DEVICE_VECTOR
+ NUMBER_DEVICE_VECTORS
)
323 DPRINT("Not a device interrupt\n");
327 /* FIXME: We must check if the requested and the assigned interrupt mode is the same */
329 irq
= VECTOR2IRQ (Vector
);
330 IOAPICUnmaskIrq (irq
);
336 HalRequestSoftwareInterrupt(IN KIRQL Request
)
341 __writefsbyte(FIELD_OFFSET(KIPCR
, HalReserved
[HAL_APC_REQUEST
]), 1);
345 __writefsbyte(FIELD_OFFSET(KIPCR
, HalReserved
[HAL_DPC_REQUEST
]), 1);
354 HalClearSoftwareInterrupt(