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))));