📄 irql.c
字号:
/* $Id: irql.c 21261 2006-03-08 23:26:25Z audit $
*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
* FILE: ntoskrnl/hal/x86/irql.c
* PURPOSE: Implements IRQLs
* PROGRAMMER: David Welch (welch@cwcom.net)
*/
/* INCLUDES *****************************************************************/
#include <hal.h>
#define NDEBUG
#include <debug.h>
/* GLOBALS ******************************************************************/
/*
* FIXME: Use EISA_CONTROL STRUCTURE INSTEAD OF HARD-CODED OFFSETS
*/
typedef union
{
USHORT both;
struct
{
BYTE master;
BYTE slave;
};
}
PIC_MASK;
/*
* PURPOSE: - Mask for HalEnableSystemInterrupt and HalDisableSystemInterrupt
* - At startup enable timer and cascade
*/
#if defined(__GNUC__)
static PIC_MASK pic_mask = {.both = 0xFFFA};
#else
static PIC_MASK pic_mask = { 0xFFFA };
#endif
/*
* PURPOSE: Mask for disabling of acknowledged interrupts
*/
#if defined(__GNUC__)
static PIC_MASK pic_mask_intr = {.both = 0x0000};
#else
static PIC_MASK pic_mask_intr = { 0 };
#endif
static ULONG HalpPendingInterruptCount[NR_IRQS];
#define DIRQL_TO_IRQ(x) (PROFILE_LEVEL - x)
#define IRQ_TO_DIRQL(x) (PROFILE_LEVEL - x)
VOID STDCALL
KiInterruptDispatch2 (ULONG Irq, KIRQL old_level);
/* FUNCTIONS ****************************************************************/
#undef KeGetCurrentIrql
KIRQL STDCALL KeGetCurrentIrql (VOID)
/*
* PURPOSE: Returns the current irq level
* RETURNS: The current irq level
*/
{
return(KeGetCurrentKPCR()->Irql);
}
VOID HalpInitPICs(VOID)
{
memset(HalpPendingInterruptCount, 0, sizeof(HalpPendingInterruptCount));
/* Initialization sequence */
WRITE_PORT_UCHAR((PUCHAR)0x20, 0x11);
WRITE_PORT_UCHAR((PUCHAR)0xa0, 0x11);
/* Start of hardware irqs (0x24) */
WRITE_PORT_UCHAR((PUCHAR)0x21, IRQ_BASE);
WRITE_PORT_UCHAR((PUCHAR)0xa1, IRQ_BASE + 8);
/* 8259-1 is master */
WRITE_PORT_UCHAR((PUCHAR)0x21, 0x4);
/* 8259-2 is slave */
WRITE_PORT_UCHAR((PUCHAR)0xa1, 0x2);
/* 8086 mode */
WRITE_PORT_UCHAR((PUCHAR)0x21, 0x1);
WRITE_PORT_UCHAR((PUCHAR)0xa1, 0x1);
/* Enable interrupts */
WRITE_PORT_UCHAR((PUCHAR)0x21, pic_mask.master);
WRITE_PORT_UCHAR((PUCHAR)0xa1, pic_mask.slave);
/* We can now enable interrupts */
Ki386EnableInterrupts();
}
VOID HalpEndSystemInterrupt(KIRQL Irql)
/*
* FUNCTION: Enable all irqs with higher priority.
*/
{
ULONG flags;
const USHORT mask[] =
{
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x8000, 0xc000, 0xe000, 0xf000,
0xf800, 0xfc00, 0xfe00, 0xff00, 0xff80, 0xffc0, 0xffe0, 0xfff0,
0xfff8, 0xfffc, 0xfffe, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
};
/* Interrupts should be disable while enabling irqs of both pics */
Ki386SaveFlags(flags);
Ki386DisableInterrupts();
pic_mask_intr.both &= mask[Irql];
WRITE_PORT_UCHAR((PUCHAR)0x21, (UCHAR)(pic_mask.master|pic_mask_intr.master));
WRITE_PORT_UCHAR((PUCHAR)0xa1, (UCHAR)(pic_mask.slave|pic_mask_intr.slave));
/* restore flags */
Ki386RestoreFlags(flags);
}
VOID STATIC
HalpExecuteIrqs(KIRQL NewIrql)
{
ULONG IrqLimit, i;
IrqLimit = min(PROFILE_LEVEL - NewIrql, NR_IRQS);
/*
* For each irq if there have been any deferred interrupts then now
* dispatch them.
*/
for (i = 0; i < IrqLimit; i++)
{
if (HalpPendingInterruptCount[i] > 0)
{
KeGetCurrentKPCR()->Irql = (KIRQL)IRQ_TO_DIRQL(i);
while (HalpPendingInterruptCount[i] > 0)
{
/*
* For each deferred interrupt execute all the handlers at DIRQL.
*/
HalpPendingInterruptCount[i]--;
KiInterruptDispatch2(i + IRQ_BASE, NewIrql);
}
KeGetCurrentKPCR()->Irql--;
HalpEndSystemInterrupt(KeGetCurrentKPCR()->Irql);
}
}
}
VOID STATIC
HalpLowerIrql(KIRQL NewIrql)
{
if (NewIrql >= PROFILE_LEVEL)
{
KeGetCurrentKPCR()->Irql = NewIrql;
return;
}
HalpExecuteIrqs(NewIrql);
if (NewIrql >= DISPATCH_LEVEL)
{
KeGetCurrentKPCR()->Irql = NewIrql;
return;
}
KeGetCurrentKPCR()->Irql = DISPATCH_LEVEL;
if (((PKIPCR)KeGetCurrentKPCR())->HalReserved[HAL_DPC_REQUEST])
{
((PKIPCR)KeGetCurrentKPCR())->HalReserved[HAL_DPC_REQUEST] = FALSE;
KiDispatchInterrupt();
}
KeGetCurrentKPCR()->Irql = APC_LEVEL;
if (NewIrql == APC_LEVEL)
{
return;
}
if (KeGetCurrentThread() != NULL &&
KeGetCurrentThread()->ApcState.KernelApcPending)
{
KiDeliverApc(KernelMode, NULL, NULL);
}
KeGetCurrentKPCR()->Irql = PASSIVE_LEVEL;
}
/**********************************************************************
* NAME EXPORTED
* KfLowerIrql
*
* DESCRIPTION
* Restores the irq level on the current processor
*
* ARGUMENTS
* NewIrql = Irql to lower to
*
* RETURN VALUE
* None
*
* NOTES
* Uses fastcall convention
*/
VOID FASTCALL
KfLowerIrql (KIRQL NewIrql)
{
DPRINT("KfLowerIrql(NewIrql %d)\n", NewIrql);
if (NewIrql > KeGetCurrentKPCR()->Irql)
{
DbgPrint ("(%s:%d) NewIrql %x CurrentIrql %x\n",
__FILE__, __LINE__, NewIrql, KeGetCurrentKPCR()->Irql);
KEBUGCHECK(0);
for(;;);
}
HalpLowerIrql(NewIrql);
}
/**********************************************************************
* NAME EXPORTED
* KeLowerIrql
*
* DESCRIPTION
* Restores the irq level on the current processor
*
* ARGUMENTS
* NewIrql = Irql to lower to
*
* RETURN VALUE
* None
*
* NOTES
*/
#undef KeLowerIrql
VOID STDCALL
KeLowerIrql (KIRQL NewIrql)
{
KfLowerIrql (NewIrql);
}
/**********************************************************************
* NAME EXPORTED
* KfRaiseIrql
*
* DESCRIPTION
* Raises the hardware priority (irql)
*
* ARGUMENTS
* NewIrql = Irql to raise to
*
* RETURN VALUE
* previous irq level
*
* NOTES
* Uses fastcall convention
*/
KIRQL FASTCALL
KfRaiseIrql (KIRQL NewIrql)
{
KIRQL OldIrql;
DPRINT("KfRaiseIrql(NewIrql %d)\n", NewIrql);
if (NewIrql < KeGetCurrentKPCR()->Irql)
{
DbgPrint ("%s:%d CurrentIrql %x NewIrql %x\n",
__FILE__,__LINE__,KeGetCurrentKPCR()->Irql,NewIrql);
KEBUGCHECK (0);
for(;;);
}
OldIrql = KeGetCurrentKPCR()->Irql;
KeGetCurrentKPCR()->Irql = NewIrql;
return OldIrql;
}
/**********************************************************************
* NAME EXPORTED
* KeRaiseIrql
*
* DESCRIPTION
* Raises the hardware priority (irql)
*
* ARGUMENTS
* NewIrql = Irql to raise to
* OldIrql (OUT) = Caller supplied storage for the previous irql
*
* RETURN VALUE
* None
*
* NOTES
* Calls KfRaiseIrql
*/
#undef KeRaiseIrql
VOID STDCALL
KeRaiseIrql (KIRQL NewIrql,
PKIRQL OldIrql)
{
*OldIrql = KfRaiseIrql (NewIrql);
}
/**********************************************************************
* NAME EXPORTED
* KeRaiseIrqlToDpcLevel
*
* DESCRIPTION
* Raises the hardware priority (irql) to DISPATCH level
*
* ARGUMENTS
* None
*
* RETURN VALUE
* Previous irq level
*
* NOTES
* Calls KfRaiseIrql
*/
KIRQL STDCALL
KeRaiseIrqlToDpcLevel (VOID)
{
return KfRaiseIrql (DISPATCH_LEVEL);
}
/**********************************************************************
* NAME EXPORTED
* KeRaiseIrqlToSynchLevel
*
* DESCRIPTION
* Raises the hardware priority (irql) to CLOCK2 level
*
* ARGUMENTS
* None
*
* RETURN VALUE
* Previous irq level
*
* NOTES
* Calls KfRaiseIrql
*/
KIRQL STDCALL
KeRaiseIrqlToSynchLevel (VOID)
{
return KfRaiseIrql (CLOCK2_LEVEL);
}
BOOLEAN STDCALL
HalBeginSystemInterrupt (ULONG Vector,
KIRQL Irql,
PKIRQL OldIrql)
{
ULONG irq;
if (Vector < IRQ_BASE || Vector >= IRQ_BASE + NR_IRQS)
{
return(FALSE);
}
irq = Vector - IRQ_BASE;
pic_mask_intr.both |= ((1 << irq) & 0xfffe); // do not disable the timer interrupt
if (irq < 8)
{
WRITE_PORT_UCHAR((PUCHAR)0x21, (UCHAR)(pic_mask.master|pic_mask_intr.master));
WRITE_PORT_UCHAR((PUCHAR)0x20, 0x20);
}
else
{
WRITE_PORT_UCHAR((PUCHAR)0xa1, (UCHAR)(pic_mask.slave|pic_mask_intr.slave));
/* Send EOI to the PICs */
WRITE_PORT_UCHAR((PUCHAR)0x20,0x20);
WRITE_PORT_UCHAR((PUCHAR)0xa0,0x20);
}
if (KeGetCurrentKPCR()->Irql >= Irql)
{
HalpPendingInterruptCount[irq]++;
return(FALSE);
}
*OldIrql = KeGetCurrentKPCR()->Irql;
KeGetCurrentKPCR()->Irql = Irql;
return(TRUE);
}
VOID STDCALL HalEndSystemInterrupt (KIRQL Irql, ULONG Unknown2)
/*
* FUNCTION: Finish a system interrupt and restore the specified irq level.
*/
{
HalpLowerIrql(Irql);
HalpEndSystemInterrupt(Irql);
}
BOOLEAN
STDCALL
HalDisableSystemInterrupt(
ULONG Vector,
KIRQL Irql)
{
ULONG irq;
if (Vector < IRQ_BASE || Vector >= IRQ_BASE + NR_IRQS)
return FALSE;
irq = Vector - IRQ_BASE;
pic_mask.both |= (1 << irq);
if (irq < 8)
{
WRITE_PORT_UCHAR((PUCHAR)0x21, (UCHAR)(pic_mask.master|pic_mask_intr.slave));
}
else
{
WRITE_PORT_UCHAR((PUCHAR)0xa1, (UCHAR)(pic_mask.slave|pic_mask_intr.slave));
}
return TRUE;
}
BOOLEAN
STDCALL
HalEnableSystemInterrupt(
ULONG Vector,
KIRQL Irql,
KINTERRUPT_MODE InterruptMode)
{
ULONG irq;
if (Vector < IRQ_BASE || Vector >= IRQ_BASE + NR_IRQS)
return FALSE;
irq = Vector - IRQ_BASE;
pic_mask.both &= ~(1 << irq);
if (irq < 8)
{
WRITE_PORT_UCHAR((PUCHAR)0x21, (UCHAR)(pic_mask.master|pic_mask_intr.master));
}
else
{
WRITE_PORT_UCHAR((PUCHAR)0xa1, (UCHAR)(pic_mask.slave|pic_mask_intr.slave));
}
return TRUE;
}
VOID FASTCALL
HalRequestSoftwareInterrupt(
IN KIRQL Request)
{
switch (Request)
{
case APC_LEVEL:
((PKIPCR)KeGetCurrentKPCR())->HalReserved[HAL_APC_REQUEST] = TRUE;
break;
case DISPATCH_LEVEL:
((PKIPCR)KeGetCurrentKPCR())->HalReserved[HAL_DPC_REQUEST] = TRUE;
break;
default:
KEBUGCHECK(0);
}
}
/* EOF */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -