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)
9 /* INCLUDES *****************************************************************/
11 #include <ddk/ntddk.h>
12 #include <internal/ke.h>
13 #include <internal/ps.h>
14 #include <ntos/minmax.h>
17 #include <internal/debug.h>
19 /* GLOBALS ******************************************************************/
22 #define IRQ_BASE (0x40)
25 * PURPOSE: Current irq level
27 static KIRQL CurrentIrql = HIGH_LEVEL;
29 extern IMPORTED ULONG DpcQueueSize;
31 static ULONG HalpPendingInterruptCount[NR_IRQS];
33 #define DIRQL_TO_IRQ(x) (PROFILE_LEVEL - x)
34 #define IRQ_TO_DIRQL(x) (PROFILE_LEVEL - x)
37 KiInterruptDispatch2 (ULONG Irq, KIRQL old_level);
39 /* FUNCTIONS ****************************************************************/
41 KIRQL STDCALL KeGetCurrentIrql (VOID)
43 * PURPOSE: Returns the current irq level
44 * RETURNS: The current irq level
50 VOID HalpInitPICs(VOID)
52 memset(HalpPendingInterruptCount, 0, sizeof(HalpPendingInterruptCount));
54 /* Initialization sequence */
55 WRITE_PORT_UCHAR((PUCHAR)0x20, 0x11);
56 WRITE_PORT_UCHAR((PUCHAR)0xa0, 0x11);
57 /* Start of hardware irqs (0x24) */
58 WRITE_PORT_UCHAR((PUCHAR)0x21, 0x40);
59 WRITE_PORT_UCHAR((PUCHAR)0xa1, 0x48);
60 /* 8259-1 is master */
61 WRITE_PORT_UCHAR((PUCHAR)0x21, 0x4);
63 WRITE_PORT_UCHAR((PUCHAR)0xa1, 0x2);
65 WRITE_PORT_UCHAR((PUCHAR)0x21, 0x1);
66 WRITE_PORT_UCHAR((PUCHAR)0xa1, 0x1);
67 /* Enable all interrupts from PICs */
68 WRITE_PORT_UCHAR((PUCHAR)0x21, 0x0);
69 WRITE_PORT_UCHAR((PUCHAR)0xa1, 0x0);
71 /* We can now enable interrupts */
72 __asm__ __volatile__ ("sti\n\t");
76 HalpExecuteIrqs(KIRQL NewIrql)
80 IrqLimit = min(PROFILE_LEVEL - NewIrql, NR_IRQS);
83 * For each irq if there have been any deferred interrupts then now
86 for (i = 0; i < IrqLimit; i++)
88 while (HalpPendingInterruptCount[i] > 0)
91 * For each deferred interrupt execute all the handlers at DIRQL.
93 CurrentIrql = IRQ_TO_DIRQL(i);
94 KiInterruptDispatch2(i, NewIrql);
95 HalpPendingInterruptCount[i]--;
101 HalpLowerIrql(KIRQL NewIrql)
103 if (NewIrql > PROFILE_LEVEL)
105 CurrentIrql = NewIrql;
108 HalpExecuteIrqs(NewIrql);
109 if (NewIrql >= DISPATCH_LEVEL)
111 CurrentIrql = NewIrql;
114 CurrentIrql = DISPATCH_LEVEL;
115 if (DpcQueueSize > 0)
117 KiDispatchInterrupt();
119 if (NewIrql == APC_LEVEL)
121 CurrentIrql = NewIrql;
124 CurrentIrql = APC_LEVEL;
125 if (KeGetCurrentThread() != NULL &&
126 KeGetCurrentThread()->ApcState.KernelApcPending)
128 KiDeliverApc(0, 0, 0);
130 CurrentIrql = PASSIVE_LEVEL;
133 /**********************************************************************
138 * Restores the irq level on the current processor
141 * NewIrql = Irql to lower to
147 * Uses fastcall convention
150 KfLowerIrql (KIRQL NewIrql)
154 DPRINT("KfLowerIrql(NewIrql %d)\n", NewIrql);
156 if (NewIrql > CurrentIrql)
158 DbgPrint ("(%s:%d) NewIrql %x CurrentIrql %x\n",
159 __FILE__, __LINE__, NewIrql, CurrentIrql);
164 HalpLowerIrql(NewIrql);
168 /**********************************************************************
173 * Restores the irq level on the current processor
176 * NewIrql = Irql to lower to
185 KeLowerIrql (KIRQL NewIrql)
187 KfLowerIrql (NewIrql);
191 /**********************************************************************
196 * Raises the hardware priority (irql)
199 * NewIrql = Irql to raise to
205 * Uses fastcall convention
209 KfRaiseIrql (KIRQL NewIrql)
213 DPRINT("KfRaiseIrql(NewIrql %d)\n", NewIrql);
215 if (NewIrql < CurrentIrql)
217 DbgPrint ("%s:%d CurrentIrql %x NewIrql %x\n",
218 __FILE__,__LINE__,CurrentIrql,NewIrql);
223 OldIrql = CurrentIrql;
224 CurrentIrql = NewIrql;
229 /**********************************************************************
234 * Raises the hardware priority (irql)
237 * NewIrql = Irql to raise to
238 * OldIrql (OUT) = Caller supplied storage for the previous irql
247 KeRaiseIrql (KIRQL NewIrql,
250 *OldIrql = KfRaiseIrql (NewIrql);
254 /**********************************************************************
256 * KeRaiseIrqlToDpcLevel
259 * Raises the hardware priority (irql) to DISPATCH level
272 KeRaiseIrqlToDpcLevel (VOID)
274 return KfRaiseIrql (DISPATCH_LEVEL);
278 /**********************************************************************
280 * KeRaiseIrqlToSynchLevel
283 * Raises the hardware priority (irql) to CLOCK2 level
296 KeRaiseIrqlToSynchLevel (VOID)
298 return KfRaiseIrql (CLOCK2_LEVEL);
303 HalBeginSystemInterrupt (ULONG Vector,
307 if (Vector < IRQ_BASE || Vector > IRQ_BASE + NR_IRQS)
312 /* Send EOI to the PICs */
313 WRITE_PORT_UCHAR((PUCHAR)0x20,0x20);
314 if ((Vector-IRQ_BASE)>=8)
316 WRITE_PORT_UCHAR((PUCHAR)0xa0,0x20);
319 if (CurrentIrql >= Irql)
321 HalpPendingInterruptCount[Vector - IRQ_BASE]++;
324 *OldIrql = CurrentIrql;
331 VOID STDCALL HalEndSystemInterrupt (KIRQL Irql, ULONG Unknown2)
333 * FUNCTION: Finish a system interrupt and restore the specified irq level.
339 BOOLEAN STDCALL HalDisableSystemInterrupt (ULONG Vector,
344 if (Vector < IRQ_BASE || Vector > IRQ_BASE + NR_IRQS)
347 irq = Vector - IRQ_BASE;
350 WRITE_PORT_UCHAR((PUCHAR)0x21,
351 READ_PORT_UCHAR((PUCHAR)0x21)|(1<<irq));
355 WRITE_PORT_UCHAR((PUCHAR)0xa1,
356 READ_PORT_UCHAR((PUCHAR)0xa1)|(1<<(irq-8)));
363 BOOLEAN STDCALL HalEnableSystemInterrupt (ULONG Vector,
369 if (Vector < IRQ_BASE || Vector > IRQ_BASE + NR_IRQS)
372 irq = Vector - IRQ_BASE;
375 WRITE_PORT_UCHAR((PUCHAR)0x21,
376 READ_PORT_UCHAR((PUCHAR)0x21)&(~(1<<irq)));
380 WRITE_PORT_UCHAR((PUCHAR)0xa1,
381 READ_PORT_UCHAR((PUCHAR)0xa1)&(~(1<<(irq-8))));