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 * 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 Flags
= __readeflags();
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 Flags
= __readeflags();
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
,
322 IN PKTRAP_FRAME TrapFrame
)
324 * FUNCTION: Finish a system interrupt and restore the specified irq level.
328 Flags
= __readeflags();
330 if (Flags
& EFLAGS_INTERRUPT_MASK
)
332 DPRINT1("HalEndSystemInterrupt was called with interrupt's enabled\n");
336 HalpLowerIrql (Irql
, TRUE
);
341 HalDisableSystemInterrupt(UCHAR Vector
,
346 DPRINT ("Vector (0x%X)\n", Vector
);
348 if (Vector
< FIRST_DEVICE_VECTOR
||
349 Vector
>= FIRST_DEVICE_VECTOR
+ NUMBER_DEVICE_VECTORS
)
351 DPRINT1("Not a device interrupt, vector=%x\n", Vector
);
356 irq
= VECTOR2IRQ (Vector
);
364 HalEnableSystemInterrupt (UCHAR Vector
,
366 KINTERRUPT_MODE InterruptMode
)
370 if (Vector
< FIRST_DEVICE_VECTOR
||
371 Vector
>= FIRST_DEVICE_VECTOR
+ NUMBER_DEVICE_VECTORS
)
373 DPRINT("Not a device interrupt\n");
377 /* FIXME: We must check if the requested and the assigned interrupt mode is the same */
379 irq
= VECTOR2IRQ (Vector
);
380 IOAPICUnmaskIrq (irq
);
386 HalRequestSoftwareInterrupt(IN KIRQL Request
)
391 __writefsbyte(FIELD_OFFSET(KIPCR
, HalReserved
[HAL_APC_REQUEST
]), 1);
395 __writefsbyte(FIELD_OFFSET(KIPCR
, HalReserved
[HAL_DPC_REQUEST
]), 1);
404 HalClearSoftwareInterrupt(