xref: /reactos/hal/halx86/mp/mpsirql.c (revision d2aeaba5)
1 /*
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)
8  * UPDATE HISTORY:
9  *     12/04/2001  CSH  Created
10  */
11 
12 /* INCLUDES *****************************************************************/
13 
14 #include <hal.h>
15 #define NDEBUG
16 #include <debug.h>
17 
18 /* GLOBALS ******************************************************************/
19 
20 
21 /* FUNCTIONS ****************************************************************/
22 
23 #undef KeGetCurrentIrql
24 KIRQL NTAPI KeGetCurrentIrql (VOID)
25 /*
26  * PURPOSE: Returns the current irq level
27  * RETURNS: The current irq level
28  */
29 {
30   KIRQL irql;
31   ULONG Flags;
32 
33   Flags = __readeflags();
34   _disable();
35 
36   irql = __readfsbyte(FIELD_OFFSET(KPCR, Irql));
37   if (irql > HIGH_LEVEL)
38     {
39       DPRINT1 ("CurrentIrql %x\n", irql);
40       ASSERT(FALSE);
41     }
42   if (Flags & EFLAGS_INTERRUPT_MASK)
43     {
44       _enable();
45     }
46   return irql;
47 }
48 
49 
50 #undef KeSetCurrentIrql
51 VOID KeSetCurrentIrql (KIRQL NewIrql)
52 /*
53  * PURPOSE: Sets the current irq level without taking any action
54  */
55 {
56   ULONG Flags;
57   if (NewIrql > HIGH_LEVEL)
58   {
59     DPRINT1 ("NewIrql %x\n", NewIrql);
60     ASSERT(FALSE);
61   }
62   Flags = __readeflags();
63   _disable();
64   __writefsbyte(FIELD_OFFSET(KPCR, Irql), NewIrql);
65   if (Flags & EFLAGS_INTERRUPT_MASK)
66     {
67       _enable();
68     }
69 }
70 
71 VOID
72 HalpLowerIrql(KIRQL NewIrql, BOOLEAN FromHalEndSystemInterrupt)
73 {
74   ULONG Flags;
75   UCHAR DpcRequested;
76   if (NewIrql >= DISPATCH_LEVEL)
77     {
78       KeSetCurrentIrql (NewIrql);
79       APICWrite(APIC_TPR, IRQL2TPR (NewIrql) & APIC_TPR_PRI);
80       return;
81     }
82   Flags = __readeflags();
83   if (KeGetCurrentIrql() > APC_LEVEL)
84     {
85       KeSetCurrentIrql (DISPATCH_LEVEL);
86       APICWrite(APIC_TPR, IRQL2TPR (DISPATCH_LEVEL) & APIC_TPR_PRI);
87       DpcRequested = __readfsbyte(FIELD_OFFSET(KPCR, HalReserved[HAL_DPC_REQUEST]));
88       if (FromHalEndSystemInterrupt || DpcRequested)
89         {
90           __writefsbyte(FIELD_OFFSET(KPCR, HalReserved[HAL_DPC_REQUEST]), 0);
91           _enable();
92           KiDispatchInterrupt();
93           if (!(Flags & EFLAGS_INTERRUPT_MASK))
94             {
95               _disable();
96             }
97 	}
98       KeSetCurrentIrql (APC_LEVEL);
99     }
100   if (NewIrql == APC_LEVEL)
101     {
102       return;
103     }
104   if (KeGetCurrentThread () != NULL &&
105       KeGetCurrentThread ()->ApcState.KernelApcPending)
106     {
107       _enable();
108       KiDeliverApc(KernelMode, NULL, NULL);
109       if (!(Flags & EFLAGS_INTERRUPT_MASK))
110         {
111           _disable();
112         }
113     }
114   KeSetCurrentIrql (PASSIVE_LEVEL);
115 }
116 
117 
118 /**********************************************************************
119  * NAME							EXPORTED
120  *	KfLowerIrql
121  *
122  * DESCRIPTION
123  *	Restores the irq level on the current processor
124  *
125  * ARGUMENTS
126  *	NewIrql = Irql to lower to
127  *
128  * RETURN VALUE
129  *	None
130  *
131  * NOTES
132  *	Uses fastcall convention
133  */
134 VOID FASTCALL
135 KfLowerIrql (KIRQL	NewIrql)
136 {
137   KIRQL oldIrql = KeGetCurrentIrql();
138   if (NewIrql > oldIrql)
139     {
140       DPRINT1 ("NewIrql %x CurrentIrql %x\n", NewIrql, oldIrql);
141       ASSERT(FALSE);
142     }
143   HalpLowerIrql (NewIrql, FALSE);
144 }
145 
146 
147 /**********************************************************************
148  * NAME							EXPORTED
149  *	KfRaiseIrql
150  *
151  * DESCRIPTION
152  *	Raises the hardware priority (irql)
153  *
154  * ARGUMENTS
155  *	NewIrql = Irql to raise to
156  *
157  * RETURN VALUE
158  *	previous irq level
159  *
160  * NOTES
161  *	Uses fastcall convention
162  */
163 
164 KIRQL FASTCALL
165 KfRaiseIrql (KIRQL	NewIrql)
166 {
167   KIRQL OldIrql;
168   ULONG Flags;
169 
170   Flags = __readeflags();
171   _disable();
172 
173   OldIrql = KeGetCurrentIrql ();
174 
175   if (NewIrql < OldIrql)
176     {
177       DPRINT1 ("CurrentIrql %x NewIrql %x\n", KeGetCurrentIrql (), NewIrql);
178       ASSERT(FALSE);
179     }
180 
181 
182   if (NewIrql > DISPATCH_LEVEL)
183     {
184       APICWrite (APIC_TPR, IRQL2TPR(NewIrql) & APIC_TPR_PRI);
185     }
186   KeSetCurrentIrql (NewIrql);
187   if (Flags & EFLAGS_INTERRUPT_MASK)
188     {
189       _enable();
190     }
191 
192   return OldIrql;
193 }
194 
195 /**********************************************************************
196  * NAME							EXPORTED
197  *	KeRaiseIrqlToDpcLevel
198  *
199  * DESCRIPTION
200  *	Raises the hardware priority (irql) to DISPATCH level
201  *
202  * ARGUMENTS
203  *	None
204  *
205  * RETURN VALUE
206  *	Previous irq level
207  *
208  * NOTES
209  *	Calls KfRaiseIrql
210  */
211 
212 KIRQL NTAPI
213 KeRaiseIrqlToDpcLevel (VOID)
214 {
215   return KfRaiseIrql (DISPATCH_LEVEL);
216 }
217 
218 
219 /**********************************************************************
220  * NAME							EXPORTED
221  *	KeRaiseIrqlToSynchLevel
222  *
223  * DESCRIPTION
224  *	Raises the hardware priority (irql) to CLOCK2 level
225  *
226  * ARGUMENTS
227  *	None
228  *
229  * RETURN VALUE
230  *	Previous irq level
231  *
232  * NOTES
233  *	Calls KfRaiseIrql
234  */
235 
236 KIRQL NTAPI
237 KeRaiseIrqlToSynchLevel (VOID)
238 {
239   return KfRaiseIrql (CLOCK2_LEVEL);
240 }
241 
242 
243 BOOLEAN NTAPI
244 HalBeginSystemInterrupt (KIRQL Irql,
245 			 ULONG Vector,
246 			 PKIRQL OldIrql)
247 {
248   ULONG Flags;
249   DPRINT("Vector (0x%X)  Irql (0x%X)\n", Vector, Irql);
250 
251   if (KeGetCurrentIrql () >= Irql)
252   {
253     DPRINT1("current irql %d, new irql %d\n", KeGetCurrentIrql(), Irql);
254     ASSERT(FALSE);
255   }
256 
257   Flags = __readeflags();
258   if (Flags & EFLAGS_INTERRUPT_MASK)
259   {
260      DPRINT1("HalBeginSystemInterrupt was called with interrupt's enabled\n");
261      ASSERT(FALSE);
262   }
263   APICWrite (APIC_TPR, IRQL2TPR (Irql) & APIC_TPR_PRI);
264   *OldIrql = KeGetCurrentIrql ();
265   KeSetCurrentIrql (Irql);
266   return(TRUE);
267 }
268 
269 
270 VOID NTAPI
271 HalEndSystemInterrupt (KIRQL Irql,
272                        IN PKTRAP_FRAME TrapFrame)
273 /*
274  * FUNCTION: Finish a system interrupt and restore the specified irq level.
275  */
276 {
277   ULONG Flags;
278   Flags = __readeflags();
279 
280   if (Flags & EFLAGS_INTERRUPT_MASK)
281   {
282      DPRINT1("HalEndSystemInterrupt was called with interrupt's enabled\n");
283      ASSERT(FALSE);
284   }
285   APICSendEOI();
286   HalpLowerIrql (Irql, TRUE);
287 }
288 
289 VOID
290 NTAPI
291 HalDisableSystemInterrupt(ULONG Vector,
292 			  KIRQL Irql)
293 {
294   ULONG irq;
295 
296   DPRINT ("Vector (0x%X)\n", Vector);
297 
298   if (Vector < FIRST_DEVICE_VECTOR ||
299       Vector >= FIRST_DEVICE_VECTOR + NUMBER_DEVICE_VECTORS)
300   {
301     DPRINT1("Not a device interrupt, vector=%x\n", Vector);
302     ASSERT(FALSE);
303     return;
304   }
305 
306   irq = VECTOR2IRQ (Vector);
307   IOAPICMaskIrq (irq);
308 
309   return;
310 }
311 
312 
313 BOOLEAN NTAPI
314 HalEnableSystemInterrupt (ULONG Vector,
315 			  KIRQL Irql,
316 			  KINTERRUPT_MODE InterruptMode)
317 {
318   ULONG irq;
319 
320   if (Vector < FIRST_DEVICE_VECTOR ||
321       Vector >= FIRST_DEVICE_VECTOR + NUMBER_DEVICE_VECTORS)
322   {
323     DPRINT("Not a device interrupt\n");
324     return FALSE;
325   }
326 
327   /* FIXME: We must check if the requested and the assigned interrupt mode is the same */
328 
329   irq = VECTOR2IRQ (Vector);
330   IOAPICUnmaskIrq (irq);
331 
332   return TRUE;
333 }
334 
335 VOID FASTCALL
336 HalRequestSoftwareInterrupt(IN KIRQL Request)
337 {
338   switch (Request)
339   {
340     case APC_LEVEL:
341       __writefsbyte(FIELD_OFFSET(KPCR, HalReserved[HAL_APC_REQUEST]), 1);
342       break;
343 
344     case DISPATCH_LEVEL:
345       __writefsbyte(FIELD_OFFSET(KPCR, HalReserved[HAL_DPC_REQUEST]), 1);
346       break;
347 
348     default:
349       ASSERT(FALSE);
350   }
351 }
352 
353 VOID FASTCALL
354 HalClearSoftwareInterrupt(
355   IN KIRQL Request)
356 {
357   UNIMPLEMENTED;
358 }
359