643369a552eec0ffcd6ef5cb4117704d9e16ddb8
[reactos.git] / hal / halx86 / mp / i386 / mpsirql.c
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(KIPCR, HalReserved[HAL_DPC_REQUEST]));
88 if (FromHalEndSystemInterrupt || DpcRequested)
89 {
90 __writefsbyte(FIELD_OFFSET(KIPCR, 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 UCHAR 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(UCHAR 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 (UCHAR 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(KIPCR, HalReserved[HAL_APC_REQUEST]), 1);
342 break;
343
344 case DISPATCH_LEVEL:
345 __writefsbyte(FIELD_OFFSET(KIPCR, 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 }