PsInitProcessManagment(): Hack-fake process name "System"
[reactos.git] / hal / halx86 / 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/ke.h>
13 #include <internal/ps.h>
14 #include <ntos/minmax.h>
15
16 #define NDEBUG
17 #include <internal/debug.h>
18
19 /* GLOBALS ******************************************************************/
20
21 #define NR_IRQS         (16)
22 #define IRQ_BASE        (0x40)
23
24 /*
25  * PURPOSE: Current irq level
26  */
27 static KIRQL CurrentIrql = HIGH_LEVEL;
28
29 #ifndef LIBCAPTIVE
30
31 extern IMPORTED ULONG DpcQueueSize;
32
33 static ULONG HalpPendingInterruptCount[NR_IRQS];
34
35 #define DIRQL_TO_IRQ(x)  (PROFILE_LEVEL - x)
36 #define IRQ_TO_DIRQL(x)  (PROFILE_LEVEL - x)
37
38 VOID STDCALL
39 KiInterruptDispatch2 (ULONG Irq, KIRQL old_level);
40
41 #endif /* LIBCAPTIVE */
42
43 /* FUNCTIONS ****************************************************************/
44
45 KIRQL STDCALL KeGetCurrentIrql (VOID)
46 /*
47  * PURPOSE: Returns the current irq level
48  * RETURNS: The current irq level
49  */
50 {
51   return(CurrentIrql);
52 }
53
54 #ifndef LIBCAPTIVE
55
56 VOID HalpInitPICs(VOID)
57 {
58   memset(HalpPendingInterruptCount, 0, sizeof(HalpPendingInterruptCount));
59
60   /* Initialization sequence */
61   WRITE_PORT_UCHAR((PUCHAR)0x20, 0x11);
62   WRITE_PORT_UCHAR((PUCHAR)0xa0, 0x11);
63   /* Start of hardware irqs (0x24) */
64   WRITE_PORT_UCHAR((PUCHAR)0x21, 0x40);
65   WRITE_PORT_UCHAR((PUCHAR)0xa1, 0x48);
66   /* 8259-1 is master */
67   WRITE_PORT_UCHAR((PUCHAR)0x21, 0x4);
68   /* 8259-2 is slave */
69   WRITE_PORT_UCHAR((PUCHAR)0xa1, 0x2);
70   /* 8086 mode */
71   WRITE_PORT_UCHAR((PUCHAR)0x21, 0x1);
72   WRITE_PORT_UCHAR((PUCHAR)0xa1, 0x1);   
73   /* Enable all interrupts from PICs */
74   WRITE_PORT_UCHAR((PUCHAR)0x21, 0x0);
75   WRITE_PORT_UCHAR((PUCHAR)0xa1, 0x0);
76   
77   /* We can now enable interrupts */
78   __asm__ __volatile__ ("sti\n\t");
79 }
80
81 VOID STATIC
82 HalpExecuteIrqs(KIRQL NewIrql)
83 {
84   ULONG IrqLimit, i;
85   
86   IrqLimit = min(PROFILE_LEVEL - NewIrql, NR_IRQS);
87
88   /*
89    * For each irq if there have been any deferred interrupts then now
90    * dispatch them.
91    */
92   for (i = 0; i < IrqLimit; i++)
93     {
94       while (HalpPendingInterruptCount[i] > 0)
95         {
96           /*
97            * For each deferred interrupt execute all the handlers at DIRQL.
98            */
99           CurrentIrql = IRQ_TO_DIRQL(i);
100           KiInterruptDispatch2(i, NewIrql);
101           HalpPendingInterruptCount[i]--;
102         }
103     }
104 }
105
106 VOID STATIC
107 HalpLowerIrql(KIRQL NewIrql)
108 {
109   if (NewIrql > PROFILE_LEVEL)
110     {
111       CurrentIrql = NewIrql;
112       return;
113     }
114   HalpExecuteIrqs(NewIrql);
115   if (NewIrql >= DISPATCH_LEVEL)
116     {
117       CurrentIrql = NewIrql;
118       return;
119     }
120   CurrentIrql = DISPATCH_LEVEL;
121   if (DpcQueueSize > 0)
122     {
123       KiDispatchInterrupt();
124     }
125   if (NewIrql == APC_LEVEL)
126     {
127       CurrentIrql = NewIrql;
128       return;
129     }
130   CurrentIrql = APC_LEVEL;
131   if (KeGetCurrentThread() != NULL && 
132       KeGetCurrentThread()->ApcState.KernelApcPending)
133     {
134       KiDeliverApc(0, 0, 0);
135     }
136   CurrentIrql = PASSIVE_LEVEL;
137 }
138
139 #endif /* LIBCAPTIVE */
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 VOID FASTCALL
158 KfLowerIrql (KIRQL      NewIrql)
159 {
160   KIRQL OldIrql;
161   
162   DPRINT("KfLowerIrql(NewIrql %d)\n", NewIrql);
163   
164   if (NewIrql > CurrentIrql)
165     {
166       DbgPrint ("(%s:%d) NewIrql %x CurrentIrql %x\n",
167                 __FILE__, __LINE__, NewIrql, CurrentIrql);
168       KeBugCheck(0);
169       for(;;);
170     }
171   
172 #ifndef LIBCAPTIVE
173   HalpLowerIrql(NewIrql);
174 #else /* LIBCAPTIVE */
175   CurrentIrql = NewIrql;
176 #endif /* LIBCAPTIVE */
177 }
178
179
180 /**********************************************************************
181  * NAME                                                 EXPORTED
182  *      KeLowerIrql
183  *
184  * DESCRIPTION
185  *      Restores the irq level on the current processor
186  *
187  * ARGUMENTS
188  *      NewIrql = Irql to lower to
189  *
190  * RETURN VALUE
191  *      None
192  *
193  * NOTES
194  */
195
196 VOID STDCALL
197 KeLowerIrql (KIRQL NewIrql)
198 {
199   KfLowerIrql (NewIrql);
200 }
201
202
203 /**********************************************************************
204  * NAME                                                 EXPORTED
205  *      KfRaiseIrql
206  *
207  * DESCRIPTION
208  *      Raises the hardware priority (irql)
209  *
210  * ARGUMENTS
211  *      NewIrql = Irql to raise to
212  *
213  * RETURN VALUE
214  *      previous irq level
215  *
216  * NOTES
217  *      Uses fastcall convention
218  */
219
220 KIRQL FASTCALL
221 KfRaiseIrql (KIRQL      NewIrql)
222 {
223   KIRQL OldIrql;
224   
225   DPRINT("KfRaiseIrql(NewIrql %d)\n", NewIrql);
226   
227   if (NewIrql < CurrentIrql)
228     {
229       DbgPrint ("%s:%d CurrentIrql %x NewIrql %x\n",
230                 __FILE__,__LINE__,CurrentIrql,NewIrql);
231       KeBugCheck (0);
232       for(;;);
233     }
234   
235   OldIrql = CurrentIrql;
236   CurrentIrql = NewIrql;
237   return OldIrql;
238 }
239
240
241 /**********************************************************************
242  * NAME                                                 EXPORTED
243  *      KeRaiseIrql
244  *
245  * DESCRIPTION
246  *      Raises the hardware priority (irql)
247  *
248  * ARGUMENTS
249  *      NewIrql = Irql to raise to
250  *      OldIrql (OUT) = Caller supplied storage for the previous irql
251  *
252  * RETURN VALUE
253  *      None
254  *
255  * NOTES
256  *      Calls KfRaiseIrql
257  */
258 VOID STDCALL
259 KeRaiseIrql (KIRQL      NewIrql,
260              PKIRQL     OldIrql)
261 {
262   *OldIrql = KfRaiseIrql (NewIrql);
263 }
264
265 #ifndef LIBCAPTIVE
266
267 /**********************************************************************
268  * NAME                                                 EXPORTED
269  *      KeRaiseIrqlToDpcLevel
270  *
271  * DESCRIPTION
272  *      Raises the hardware priority (irql) to DISPATCH level
273  *
274  * ARGUMENTS
275  *      None
276  *
277  * RETURN VALUE
278  *      Previous irq level
279  *
280  * NOTES
281  *      Calls KfRaiseIrql
282  */
283
284 KIRQL STDCALL
285 KeRaiseIrqlToDpcLevel (VOID)
286 {
287   return KfRaiseIrql (DISPATCH_LEVEL);
288 }
289
290
291 /**********************************************************************
292  * NAME                                                 EXPORTED
293  *      KeRaiseIrqlToSynchLevel
294  *
295  * DESCRIPTION
296  *      Raises the hardware priority (irql) to CLOCK2 level
297  *
298  * ARGUMENTS
299  *      None
300  *
301  * RETURN VALUE
302  *      Previous irq level
303  *
304  * NOTES
305  *      Calls KfRaiseIrql
306  */
307
308 KIRQL STDCALL
309 KeRaiseIrqlToSynchLevel (VOID)
310 {
311   return KfRaiseIrql (CLOCK2_LEVEL);
312 }
313
314
315 BOOLEAN STDCALL 
316 HalBeginSystemInterrupt (ULONG Vector,
317                          KIRQL Irql,
318                          PKIRQL OldIrql)
319 {
320   if (Vector < IRQ_BASE || Vector > IRQ_BASE + NR_IRQS)
321     {
322       return(FALSE);
323     }
324   
325   /* Send EOI to the PICs */
326   WRITE_PORT_UCHAR((PUCHAR)0x20,0x20);
327   if ((Vector-IRQ_BASE)>=8)
328     {
329       WRITE_PORT_UCHAR((PUCHAR)0xa0,0x20);
330     }
331   
332   if (CurrentIrql >= Irql)
333     {
334       HalpPendingInterruptCount[Vector - IRQ_BASE]++;
335       return(FALSE);
336     }
337   *OldIrql = CurrentIrql;
338   CurrentIrql = Irql;
339
340   return(TRUE);
341 }
342
343
344 VOID STDCALL HalEndSystemInterrupt (KIRQL Irql, ULONG Unknown2)
345 /*
346  * FUNCTION: Finish a system interrupt and restore the specified irq level.
347  */
348 {
349   HalpLowerIrql(Irql);
350 }
351
352 BOOLEAN STDCALL HalDisableSystemInterrupt (ULONG Vector,
353                                            ULONG Unknown2)
354 {
355   ULONG irq;
356   
357   if (Vector < IRQ_BASE || Vector > IRQ_BASE + NR_IRQS)
358     return FALSE;
359
360   irq = Vector - IRQ_BASE;
361   if (irq < 8)
362      {
363        WRITE_PORT_UCHAR((PUCHAR)0x21, 
364                         READ_PORT_UCHAR((PUCHAR)0x21)|(1<<irq));
365      }
366   else
367     {
368       WRITE_PORT_UCHAR((PUCHAR)0xa1, 
369                        READ_PORT_UCHAR((PUCHAR)0xa1)|(1<<(irq-8)));
370     }
371   
372   return TRUE;
373 }
374
375
376 BOOLEAN STDCALL HalEnableSystemInterrupt (ULONG Vector,
377                                           ULONG Unknown2,
378                                           ULONG Unknown3)
379 {
380   ULONG irq;
381
382   if (Vector < IRQ_BASE || Vector > IRQ_BASE + NR_IRQS)
383     return FALSE;
384
385   irq = Vector - IRQ_BASE;
386   if (irq < 8)
387     {
388       WRITE_PORT_UCHAR((PUCHAR)0x21, 
389                        READ_PORT_UCHAR((PUCHAR)0x21)&(~(1<<irq)));
390     }
391   else
392      {
393        WRITE_PORT_UCHAR((PUCHAR)0xa1, 
394                         READ_PORT_UCHAR((PUCHAR)0xa1)&(~(1<<(irq-8))));
395      }
396
397   return TRUE;
398 }
399
400 #endif /* LIBCAPTIVE */
401
402 /* EOF */