d5052482d14e2f972c8cfee7823d72ffabe5231e
[reactos.git] / reactos / ntoskrnl / hal / x86 / irql.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
4 * FILE: ntoskrnl/hal/x86/irql.c
5 * PURPOSE: Implements IRQLs
6 * PROGRAMMER: David Welch (welch@cwcom.net)
7 */
8
9 /* INCLUDES *****************************************************************/
10
11 #include <ddk/ntddk.h>
12 #include <internal/bitops.h>
13 #include <internal/halio.h>
14 #include <internal/ke.h>
15 #include <internal/ps.h>
16
17 #define NDEBUG
18 #include <internal/debug.h>
19
20 /* GLOBALS ******************************************************************/
21
22 /*
23 * PURPOSE: Current irq level
24 */
25 static KIRQL CurrentIrql = HIGH_LEVEL;
26
27 extern ULONG DpcQueueSize;
28
29 /* FUNCTIONS ****************************************************************/
30
31 #if 0
32 static unsigned int HiGetCurrentPICMask(void)
33 {
34 unsigned int mask;
35
36 mask = inb_p(0x21);
37 mask = mask | (inb_p(0xa1)<<8);
38
39 return mask;
40 }
41 #endif
42
43 static unsigned int HiSetCurrentPICMask(unsigned int mask)
44 {
45 outb_p(0x21,mask & 0xff);
46 outb_p(0xa1,(mask >> 8) & 0xff);
47
48 return mask;
49 }
50
51 static VOID HiSwitchIrql(KIRQL oldIrql)
52 /*
53 * FUNCTION: Switches to the current irql
54 * NOTE: Must be called with interrupt disabled
55 */
56 {
57 unsigned int i;
58 PKTHREAD CurrentThread;
59
60 CurrentThread = KeGetCurrentThread();
61
62 if (CurrentIrql == HIGH_LEVEL)
63 {
64 HiSetCurrentPICMask(0xffff);
65 return;
66 }
67 if (CurrentIrql > DISPATCH_LEVEL)
68 {
69 unsigned int current_mask = 0;
70
71 for (i=(CurrentIrql-DISPATCH_LEVEL);i>DISPATCH_LEVEL;i--)
72 {
73 set_bit(NR_DEVICE_SPECIFIC_LEVELS - i,&current_mask);
74 }
75
76 HiSetCurrentPICMask(current_mask);
77 __asm__("sti\n\t");
78 return;
79 }
80
81 if (CurrentIrql == DISPATCH_LEVEL)
82 {
83 HiSetCurrentPICMask(0);
84 __asm__("sti\n\t");
85 return;
86 }
87
88 HiSetCurrentPICMask(0);
89 if (CurrentIrql == APC_LEVEL)
90 {
91 if (DpcQueueSize > 0 )
92 {
93 KeSetCurrentIrql(DISPATCH_LEVEL);
94 __asm__("sti\n\t");
95 KeDrainDpcQueue();
96 __asm__("cli\n\t");
97 KeSetCurrentIrql(PASSIVE_LEVEL);
98 }
99 __asm__("sti\n\t");
100 return;
101 }
102
103 if (CurrentIrql == PASSIVE_LEVEL &&
104 CurrentThread != NULL &&
105 CurrentThread->ApcState.KernelApcPending)
106 {
107 KeSetCurrentIrql(APC_LEVEL);
108 __asm__("sti\n\t");
109 KeCallApcsThread();
110 __asm__("cli\n\t");
111 KeSetCurrentIrql(PASSIVE_LEVEL);
112 __asm__("sti\n\t");
113 }
114 else
115 {
116 __asm__("sti\n\t");
117 }
118 }
119
120
121 VOID KeSetCurrentIrql(KIRQL newlvl)
122 /*
123 * PURPOSE: Sets the current irq level without taking any action
124 */
125 {
126 // DPRINT("KeSetCurrentIrql(newlvl %x)\n",newlvl);
127 CurrentIrql = newlvl;
128 }
129
130
131 KIRQL STDCALL KeGetCurrentIrql (VOID)
132 /*
133 * PURPOSE: Returns the current irq level
134 * RETURNS: The current irq level
135 */
136 {
137 return(CurrentIrql);
138 }
139
140
141 /**********************************************************************
142 * NAME EXPORTED
143 * KfLowerIrql
144 *
145 * DESCRIPTION
146 * Restores the irq level on the current processor
147 *
148 * ARGUMENTS
149 * NewIrql = Irql to lower to
150 *
151 * RETURN VALUE
152 * None
153 *
154 * NOTES
155 * Uses fastcall convention
156 */
157
158 VOID
159 FASTCALL
160 KfLowerIrql (
161 KIRQL NewIrql
162 )
163 {
164 KIRQL OldIrql;
165
166 __asm__("cli\n\t");
167
168 DPRINT("KfLowerIrql(NewIrql %d)\n", NewIrql);
169
170 if (NewIrql > CurrentIrql)
171 {
172 DbgPrint ("(%s:%d) NewIrql %x CurrentIrql %x\n",
173 __FILE__, __LINE__, NewIrql, CurrentIrql);
174 KeDumpStackFrames (0, 32);
175 for(;;);
176 }
177
178 OldIrql = CurrentIrql;
179 CurrentIrql = NewIrql;
180 HiSwitchIrql(OldIrql);
181 }
182
183
184 /**********************************************************************
185 * NAME EXPORTED
186 * KeLowerIrql
187 *
188 * DESCRIPTION
189 * Restores the irq level on the current processor
190 *
191 * ARGUMENTS
192 * NewIrql = Irql to lower to
193 *
194 * RETURN VALUE
195 * None
196 *
197 * NOTES
198 */
199
200 VOID
201 STDCALL
202 KeLowerIrql (
203 KIRQL NewIrql
204 )
205 {
206 KfLowerIrql (NewIrql);
207 }
208
209
210 /**********************************************************************
211 * NAME EXPORTED
212 * KfRaiseIrql
213 *
214 * DESCRIPTION
215 * Raises the hardware priority (irql)
216 *
217 * ARGUMENTS
218 * NewIrql = Irql to raise to
219 *
220 * RETURN VALUE
221 * previous irq level
222 *
223 * NOTES
224 * Uses fastcall convention
225 */
226
227 KIRQL
228 FASTCALL
229 KfRaiseIrql (
230 KIRQL NewIrql
231 )
232 {
233 KIRQL OldIrql;
234
235 DPRINT("KfRaiseIrql(NewIrql %d)\n", NewIrql);
236
237 if (NewIrql < CurrentIrql)
238 {
239 DbgPrint ("%s:%d CurrentIrql %x NewIrql %x\n",
240 __FILE__,__LINE__,CurrentIrql,NewIrql);
241 KeBugCheck (0);
242 for(;;);
243 }
244
245 __asm__("cli\n\t");
246 OldIrql = CurrentIrql;
247 CurrentIrql = NewIrql;
248
249 DPRINT ("NewIrql %x OldIrql %x CurrentIrql %x\n",
250 NewIrql, OldIrql, CurrentIrql);
251 HiSwitchIrql(OldIrql);
252
253 return OldIrql;
254 }
255
256
257 /**********************************************************************
258 * NAME EXPORTED
259 * KeRaiseIrql
260 *
261 * DESCRIPTION
262 * Raises the hardware priority (irql)
263 *
264 * ARGUMENTS
265 * NewIrql = Irql to raise to
266 * OldIrql (OUT) = Caller supplied storage for the previous irql
267 *
268 * RETURN VALUE
269 * None
270 *
271 * NOTES
272 * Calls KfRaiseIrql
273 */
274
275 VOID
276 STDCALL
277 KeRaiseIrql (
278 KIRQL NewIrql,
279 PKIRQL OldIrql
280 )
281 {
282 *OldIrql = KfRaiseIrql (NewIrql);
283 }
284
285 /* EOF */