Reverted latest changes.
[reactos.git] / reactos / hal / halx86 / mpsirql.c
1 /*
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)
8 * UPDATE HISTORY:
9 * 12/04/2001 CSH Created
10 */
11
12 /* INCLUDES *****************************************************************/
13
14 #include <ddk/ntddk.h>
15 #include <internal/ke.h>
16 #include <internal/ps.h>
17 #include <mps.h>
18
19 #define NDEBUG
20 #include <internal/debug.h>
21
22 /* GLOBALS ******************************************************************/;
23
24 extern IMPORTED ULONG DpcQueueSize;
25
26 static VOID KeSetCurrentIrql(KIRQL newlvl);
27
28 /* FUNCTIONS ****************************************************************/
29
30 #define IRQL2TPR(irql) (APIC_TPR_MIN + ((irql - DISPATCH_LEVEL - 1) * 8))
31
32 static VOID HiSetCurrentPriority(
33 ULONG Priority)
34 {
35 //DbgPrint(" P(0x%X)\n", Priority);
36 APICWrite(APIC_TPR, Priority & APIC_TPR_PRI);
37 }
38
39
40 static VOID HiSwitchIrql(KIRQL OldIrql, ULONG Flags)
41 /*
42 * FUNCTION: Switches to the current irql
43 * NOTE: Must be called with interrupt disabled
44 */
45 {
46 PKTHREAD CurrentThread;
47 KIRQL CurrentIrql;
48
49 //DbgPrint("HiSwitchIrql(OldIrql %d)\n", OldIrql);
50
51 CurrentIrql = KeGetCurrentKPCR()->Irql;
52
53 if (CurrentIrql >= IPI_LEVEL)
54 {
55 /* Block all interrupts */
56 HiSetCurrentPriority(APIC_TPR_MAX);
57 return;
58 }
59
60 if (CurrentIrql == CLOCK2_LEVEL)
61 {
62 HiSetCurrentPriority(APIC_TPR_MAX - 16);
63 popfl(Flags);
64 return;
65 }
66
67 if (CurrentIrql > DISPATCH_LEVEL)
68 {
69 HiSetCurrentPriority(IRQL2TPR(CurrentIrql));
70 popfl(Flags);
71 return;
72 }
73
74 /* Pass all interrupts */
75 HiSetCurrentPriority(0);
76
77 if (CurrentIrql == DISPATCH_LEVEL)
78 {
79 popfl(Flags);
80 return;
81 }
82
83 if (CurrentIrql == APC_LEVEL)
84 {
85 if (DpcQueueSize > 0 )
86 {
87 KeSetCurrentIrql(DISPATCH_LEVEL);
88 __asm__("sti\n\t");
89 KiDispatchInterrupt();
90 __asm__("cli\n\t");
91 KeSetCurrentIrql(PASSIVE_LEVEL);
92 }
93 popfl(Flags);
94 return;
95 }
96
97 CurrentThread = KeGetCurrentThread();
98
99 if (CurrentIrql == PASSIVE_LEVEL &&
100 CurrentThread != NULL &&
101 CurrentThread->ApcState.KernelApcPending)
102 {
103 KeSetCurrentIrql(APC_LEVEL);
104 __asm__("sti\n\t");
105 KiDeliverApc(0, 0, 0);
106 __asm__("cli\n\t");
107 KeSetCurrentIrql(PASSIVE_LEVEL);
108 popfl(Flags);
109 }
110 else
111 {
112 popfl(Flags);
113 }
114 }
115
116
117 KIRQL STDCALL KeGetCurrentIrql (VOID)
118 /*
119 * PURPOSE: Returns the current irq level
120 * RETURNS: The current irq level
121 */
122 {
123 return(KeGetCurrentKPCR()->Irql);
124 }
125
126
127 static VOID KeSetCurrentIrql(KIRQL newlvl)
128 /*
129 * PURPOSE: Sets the current irq level without taking any action
130 */
131 {
132 // DPRINT("KeSetCurrentIrql(newlvl %x)\n",newlvl);
133
134 KeGetCurrentKPCR()->Irql = newlvl;
135 }
136
137
138 /**********************************************************************
139 * NAME EXPORTED
140 * KfLowerIrql
141 *
142 * DESCRIPTION
143 * Restores the irq level on the current processor
144 *
145 * ARGUMENTS
146 * NewIrql = Irql to lower to
147 *
148 * RETURN VALUE
149 * None
150 *
151 * NOTES
152 * Uses fastcall convention
153 */
154
155 VOID FASTCALL
156 KfLowerIrql (
157 KIRQL NewIrql
158 )
159 {
160 KIRQL CurrentIrql;
161 KIRQL OldIrql;
162 ULONG Flags;
163
164 //DbgPrint("KfLowerIrql(NewIrql %d)\n", NewIrql);
165
166 pushfl(Flags);
167 __asm__ ("\n\tcli\n\t");
168
169 CurrentIrql = KeGetCurrentKPCR()->Irql;
170
171 if (NewIrql > CurrentIrql)
172 {
173 DbgPrint ("(%s:%d) NewIrql %x CurrentIrql %x\n",
174 __FILE__, __LINE__, NewIrql, CurrentIrql);
175 KeBugCheck(0);
176 for(;;);
177 }
178
179 OldIrql = CurrentIrql;
180 KeGetCurrentKPCR()->Irql = NewIrql;
181 HiSwitchIrql(OldIrql, Flags);
182 }
183
184
185 /**********************************************************************
186 * NAME EXPORTED
187 * KeLowerIrql
188 *
189 * DESCRIPTION
190 * Restores the irq level on the current processor
191 *
192 * ARGUMENTS
193 * NewIrql = Irql to lower to
194 *
195 * RETURN VALUE
196 * None
197 *
198 * NOTES
199 */
200
201 VOID
202 STDCALL
203 KeLowerIrql (
204 KIRQL NewIrql
205 )
206 {
207 KfLowerIrql (NewIrql);
208 }
209
210
211 /**********************************************************************
212 * NAME EXPORTED
213 * KfRaiseIrql
214 *
215 * DESCRIPTION
216 * Raises the hardware priority (irql)
217 *
218 * ARGUMENTS
219 * NewIrql = Irql to raise to
220 *
221 * RETURN VALUE
222 * previous irq level
223 *
224 * NOTES
225 * Uses fastcall convention
226 */
227
228 KIRQL
229 FASTCALL
230 KfRaiseIrql (
231 KIRQL NewIrql
232 )
233 {
234 KIRQL CurrentIrql;
235 KIRQL OldIrql;
236 ULONG Flags;
237
238 //DbgPrint("KfRaiseIrql(NewIrql %d)\n", NewIrql);
239
240 pushfl(Flags);
241 __asm__ ("\n\tcli\n\t");
242
243 CurrentIrql = KeGetCurrentKPCR()->Irql;
244
245 if (NewIrql < CurrentIrql)
246 {
247 DbgPrint ("%s:%d CurrentIrql %x NewIrql %x\n",
248 __FILE__,__LINE__,CurrentIrql,NewIrql);
249 KeBugCheck (0);
250 for(;;);
251 }
252
253 OldIrql = CurrentIrql;
254 KeGetCurrentKPCR()->Irql = NewIrql;
255
256 //DPRINT("NewIrql %x OldIrql %x\n", NewIrql, OldIrql);
257 HiSwitchIrql(OldIrql, Flags);
258 return OldIrql;
259 }
260
261
262 /**********************************************************************
263 * NAME EXPORTED
264 * KeRaiseIrql
265 *
266 * DESCRIPTION
267 * Raises the hardware priority (irql)
268 *
269 * ARGUMENTS
270 * NewIrql = Irql to raise to
271 * OldIrql (OUT) = Caller supplied storage for the previous irql
272 *
273 * RETURN VALUE
274 * None
275 *
276 * NOTES
277 * Calls KfRaiseIrql
278 */
279
280 VOID
281 STDCALL
282 KeRaiseIrql (
283 KIRQL NewIrql,
284 PKIRQL OldIrql
285 )
286 {
287 *OldIrql = KfRaiseIrql (NewIrql);
288 }
289
290
291 /**********************************************************************
292 * NAME EXPORTED
293 * KeRaiseIrqlToDpcLevel
294 *
295 * DESCRIPTION
296 * Raises the hardware priority (irql) to DISPATCH level
297 *
298 * ARGUMENTS
299 * None
300 *
301 * RETURN VALUE
302 * Previous irq level
303 *
304 * NOTES
305 * Calls KfRaiseIrql
306 */
307
308 KIRQL
309 STDCALL
310 KeRaiseIrqlToDpcLevel (VOID)
311 {
312 return KfRaiseIrql (DISPATCH_LEVEL);
313 }
314
315
316 /**********************************************************************
317 * NAME EXPORTED
318 * KeRaiseIrqlToSynchLevel
319 *
320 * DESCRIPTION
321 * Raises the hardware priority (irql) to CLOCK2 level
322 *
323 * ARGUMENTS
324 * None
325 *
326 * RETURN VALUE
327 * Previous irq level
328 *
329 * NOTES
330 * Calls KfRaiseIrql
331 */
332
333 KIRQL
334 STDCALL
335 KeRaiseIrqlToSynchLevel (VOID)
336 {
337 return KfRaiseIrql (CLOCK2_LEVEL);
338 }
339
340
341 BOOLEAN STDCALL HalBeginSystemInterrupt (ULONG Vector,
342 KIRQL Irql,
343 PKIRQL OldIrql)
344 {
345 DPRINT("Vector (0x%X) Irql (0x%X)\n",
346 Vector, Irql);
347
348 if (Vector < FIRST_DEVICE_VECTOR ||
349 Vector > FIRST_DEVICE_VECTOR + NUMBER_DEVICE_VECTORS) {
350 DPRINT("Not a device interrupt\n");
351 return FALSE;
352 }
353
354 /*
355 * Acknowledge the interrupt
356 */
357 APICSendEOI();
358
359 *OldIrql = KeGetCurrentIrql();
360
361 KeSetCurrentIrql(Irql);
362
363 return TRUE;
364 }
365
366
367 VOID STDCALL HalEndSystemInterrupt (KIRQL Irql,
368 ULONG Unknown2)
369 {
370 KeSetCurrentIrql(Irql);
371 }
372
373
374 BOOLEAN STDCALL HalDisableSystemInterrupt (ULONG Vector,
375 ULONG Unknown2)
376 {
377 ULONG irq;
378
379 DPRINT("Vector (0x%X)\n", Vector);
380
381 if (Vector < FIRST_DEVICE_VECTOR ||
382 Vector > FIRST_DEVICE_VECTOR + NUMBER_DEVICE_VECTORS) {
383 DPRINT("Not a device interrupt\n");
384 return FALSE;
385 }
386
387 irq = VECTOR2IRQ(Vector);
388
389 IOAPICMaskIrq(0, irq);
390
391 return TRUE;
392 }
393
394
395 BOOLEAN STDCALL HalEnableSystemInterrupt (ULONG Vector,
396 ULONG Unknown2,
397 ULONG Unknown3)
398 {
399 ULONG irq;
400
401 DPRINT("Vector (0x%X)\n", Vector);
402
403 if (Vector < FIRST_DEVICE_VECTOR ||
404 Vector > FIRST_DEVICE_VECTOR + NUMBER_DEVICE_VECTORS) {
405 DPRINT("Not a device interrupt\n");
406 return FALSE;
407 }
408
409 irq = VECTOR2IRQ(Vector);
410
411 IOAPICUnmaskIrq(0, irq);
412
413 return TRUE;
414 }
415
416 /* EOF */