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/bitops.h>
13 #include <internal/halio.h>
14 #include <internal/ke.h>
15 #include <internal/ps.h>
18 #include <internal/debug.h>
20 /* GLOBALS ******************************************************************/
22 /* FIXME: this should be in a header file */
24 #define IRQ_BASE (0x40)
27 * PURPOSE: Current irq level
29 static KIRQL CurrentIrql
= HIGH_LEVEL
;
31 extern ULONG DpcQueueSize
;
33 static VOID
KeSetCurrentIrql(KIRQL newlvl
);
35 /* FUNCTIONS ****************************************************************/
37 VOID
HalpInitPICs(VOID
)
39 /* Initialization sequence */
40 WRITE_PORT_UCHAR((PUCHAR
)0x20, 0x11);
41 WRITE_PORT_UCHAR((PUCHAR
)0xa0, 0x11);
42 /* Start of hardware irqs (0x20) */
43 WRITE_PORT_UCHAR((PUCHAR
)0x21, 0x40);
44 WRITE_PORT_UCHAR((PUCHAR
)0xa1, 0x48);
45 /* 8259-1 is master */
46 WRITE_PORT_UCHAR((PUCHAR
)0x21, 0x4);
48 WRITE_PORT_UCHAR((PUCHAR
)0xa1, 0x2);
50 WRITE_PORT_UCHAR((PUCHAR
)0x21, 0x1);
51 WRITE_PORT_UCHAR((PUCHAR
)0xa1, 0x1);
52 /* Mask off all interrupts from PICs */
53 WRITE_PORT_UCHAR((PUCHAR
)0x21, 0xff);
54 WRITE_PORT_UCHAR((PUCHAR
)0xa1, 0xff);
58 static unsigned int HiGetCurrentPICMask(void)
63 mask
= mask
| (inb_p(0xa1)<<8);
69 static unsigned int HiSetCurrentPICMask(unsigned int mask
)
71 outb_p(0x21,mask
& 0xff);
72 outb_p(0xa1,(mask
>> 8) & 0xff);
77 static VOID
HiSwitchIrql(KIRQL oldIrql
)
79 * FUNCTION: Switches to the current irql
80 * NOTE: Must be called with interrupt disabled
84 PKTHREAD CurrentThread
;
86 CurrentThread
= KeGetCurrentThread();
88 if (CurrentIrql
== HIGH_LEVEL
)
90 HiSetCurrentPICMask(0xffff);
93 if (CurrentIrql
> DISPATCH_LEVEL
)
95 unsigned int current_mask
= 0;
97 for (i
=CurrentIrql
; i
>DISPATCH_LEVEL
; i
--)
99 current_mask
= current_mask
| (1 << (HIGH_LEVEL
- i
));
102 HiSetCurrentPICMask(current_mask
);
107 if (CurrentIrql
== DISPATCH_LEVEL
)
109 HiSetCurrentPICMask(0);
114 HiSetCurrentPICMask(0);
115 if (CurrentIrql
== APC_LEVEL
)
117 if (DpcQueueSize
> 0 )
119 KeSetCurrentIrql(DISPATCH_LEVEL
);
121 KiDispatchInterrupt();
123 KeSetCurrentIrql(PASSIVE_LEVEL
);
129 if (CurrentIrql
== PASSIVE_LEVEL
&&
130 CurrentThread
!= NULL
&&
131 CurrentThread
->ApcState
.KernelApcPending
)
133 KeSetCurrentIrql(APC_LEVEL
);
135 KiDeliverApc(0, 0, 0);
137 KeSetCurrentIrql(PASSIVE_LEVEL
);
147 KIRQL STDCALL
KeGetCurrentIrql (VOID
)
149 * PURPOSE: Returns the current irq level
150 * RETURNS: The current irq level
157 static VOID
KeSetCurrentIrql(KIRQL newlvl
)
159 * PURPOSE: Sets the current irq level without taking any action
162 // DPRINT("KeSetCurrentIrql(newlvl %x)\n",newlvl);
163 CurrentIrql
= newlvl
;
167 /**********************************************************************
172 * Restores the irq level on the current processor
175 * NewIrql = Irql to lower to
181 * Uses fastcall convention
194 DPRINT("KfLowerIrql(NewIrql %d)\n", NewIrql
);
196 if (NewIrql
> CurrentIrql
)
198 DbgPrint ("(%s:%d) NewIrql %x CurrentIrql %x\n",
199 __FILE__
, __LINE__
, NewIrql
, CurrentIrql
);
200 KeDumpStackFrames (0, 32);
204 OldIrql
= CurrentIrql
;
205 CurrentIrql
= NewIrql
;
206 HiSwitchIrql(OldIrql
);
210 /**********************************************************************
215 * Restores the irq level on the current processor
218 * NewIrql = Irql to lower to
232 KfLowerIrql (NewIrql
);
236 /**********************************************************************
241 * Raises the hardware priority (irql)
244 * NewIrql = Irql to raise to
250 * Uses fastcall convention
261 DPRINT("KfRaiseIrql(NewIrql %d)\n", NewIrql
);
263 if (NewIrql
< CurrentIrql
)
265 DbgPrint ("%s:%d CurrentIrql %x NewIrql %x\n",
266 __FILE__
,__LINE__
,CurrentIrql
,NewIrql
);
272 OldIrql
= CurrentIrql
;
273 CurrentIrql
= NewIrql
;
275 DPRINT ("NewIrql %x OldIrql %x CurrentIrql %x\n",
276 NewIrql
, OldIrql
, CurrentIrql
);
277 HiSwitchIrql(OldIrql
);
283 /**********************************************************************
288 * Raises the hardware priority (irql)
291 * NewIrql = Irql to raise to
292 * OldIrql (OUT) = Caller supplied storage for the previous irql
308 *OldIrql
= KfRaiseIrql (NewIrql
);
312 /**********************************************************************
314 * KeRaiseIrqlToDpcLevel
317 * Raises the hardware priority (irql) to DISPATCH level
331 KeRaiseIrqlToDpcLevel (VOID
)
333 return KfRaiseIrql (DISPATCH_LEVEL
);
337 /**********************************************************************
339 * KeRaiseIrqlToSynchLevel
342 * Raises the hardware priority (irql) to CLOCK2 level
356 KeRaiseIrqlToSynchLevel (VOID
)
358 // return KfRaiseIrql (CLOCK2_LEVEL);
363 BOOLEAN STDCALL
HalBeginSystemInterrupt (ULONG Vector
,
367 if (Vector
< IRQ_BASE
|| Vector
> IRQ_BASE
+ NR_IRQS
)
370 /* Send EOI to the PICs */
372 if ((Vector
-IRQ_BASE
)>=8)
377 *OldIrql
= KeGetCurrentIrql();
378 if (Vector
-IRQ_BASE
!= 0)
380 DPRINT("old_level %d\n",*OldIrql
);
382 KeSetCurrentIrql(Irql
);
388 VOID STDCALL
HalEndSystemInterrupt (KIRQL Irql
,
391 KeSetCurrentIrql(Irql
);
395 BOOLEAN STDCALL
HalDisableSystemInterrupt (ULONG Vector
,
400 if (Vector
< IRQ_BASE
|| Vector
> IRQ_BASE
+ NR_IRQS
)
403 irq
= Vector
- IRQ_BASE
;
406 outb(0x21,inb(0x21)|(1<<irq
));
410 outb(0xa1,inb(0xa1)|(1<<(irq
-8)));
417 BOOLEAN STDCALL
HalEnableSystemInterrupt (ULONG Vector
,
423 if (Vector
< IRQ_BASE
|| Vector
> IRQ_BASE
+ NR_IRQS
)
426 irq
= Vector
- IRQ_BASE
;
429 outb(0x21,inb(0x21)&(~(1<<irq
)));
433 outb(0xa1,inb(0xa1)&(~(1<<(irq
-8))));