Splited HalEndSystemInterrupt in two functions. HalEndSystemInterrupt,

HalpLowerIrql and HalpExecuteIrqs was called recursively.

svn path=/trunk/; revision=3921
This commit is contained in:
Hartmut Birr 2003-01-02 16:07:49 +00:00
parent e7cbcafe30
commit 4af2b6bcb7

View file

@ -1,4 +1,5 @@
/* /* $Id: irql.c,v 1.8 2003/01/02 16:07:49 hbirr Exp $
*
* COPYRIGHT: See COPYING in the top level directory * COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel * PROJECT: ReactOS kernel
* FILE: ntoskrnl/hal/x86/irql.c * FILE: ntoskrnl/hal/x86/irql.c
@ -26,16 +27,28 @@
*/ */
static KIRQL CurrentIrql = HIGH_LEVEL; static KIRQL CurrentIrql = HIGH_LEVEL;
typedef union
{
USHORT both;
struct
{
BYTE master;
BYTE slave;
}
}
PIC_MASK;
/* /*
* PURPOSE: - Mask for HalEnableSystemInterrupt and HalDisableSystemInterrupt * PURPOSE: - Mask for HalEnableSystemInterrupt and HalDisableSystemInterrupt
* - At startup enable timer and cascade * - At startup enable timer and cascade
*/ */
static USHORT pic_mask = 0xFFFA; static PIC_MASK pic_mask = {.both = 0xFFFA};
/* /*
* PURPOSE: Mask for disabling of acknowledged interrupts * PURPOSE: Mask for disabling of acknowledged interrupts
*/ */
static USHORT pic_mask_intr = 0x0000; static PIC_MASK pic_mask_intr = {.both = 0x0000};
extern IMPORTED ULONG DpcQueueSize; extern IMPORTED ULONG DpcQueueSize;
@ -76,13 +89,35 @@ VOID HalpInitPICs(VOID)
WRITE_PORT_UCHAR((PUCHAR)0x21, 0x1); WRITE_PORT_UCHAR((PUCHAR)0x21, 0x1);
WRITE_PORT_UCHAR((PUCHAR)0xa1, 0x1); WRITE_PORT_UCHAR((PUCHAR)0xa1, 0x1);
/* Enable interrupts */ /* Enable interrupts */
WRITE_PORT_UCHAR((PUCHAR)0x21, pic_mask & 0xFF); WRITE_PORT_UCHAR((PUCHAR)0x21, pic_mask.master);
WRITE_PORT_UCHAR((PUCHAR)0xa1, (pic_mask >> 8) & 0xFF); WRITE_PORT_UCHAR((PUCHAR)0xa1, pic_mask.slave);
/* We can now enable interrupts */ /* We can now enable interrupts */
__asm__ __volatile__ ("sti\n\t"); __asm__ __volatile__ ("sti\n\t");
} }
VOID HalpEndSystemInterrupt(KIRQL Irql)
/*
* FUNCTION: Enable all irqs with higher priority.
*/
{
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 */
__asm__("pushf\n\t");
__asm__("cli\n\t");
pic_mask_intr.both &= mask[Irql];
WRITE_PORT_UCHAR((PUCHAR)0x21, pic_mask.master|pic_mask_intr.master);
WRITE_PORT_UCHAR((PUCHAR)0xa1, pic_mask.slave|pic_mask_intr.slave);
__asm__("popf\n\t");
}
VOID STATIC VOID STATIC
HalpExecuteIrqs(KIRQL NewIrql) HalpExecuteIrqs(KIRQL NewIrql)
{ {
@ -96,26 +131,29 @@ HalpExecuteIrqs(KIRQL NewIrql)
*/ */
for (i = 0; i < IrqLimit; i++) for (i = 0; i < IrqLimit; i++)
{ {
if (HalpPendingInterruptCount[i] > 0)
{
CurrentIrql = IRQ_TO_DIRQL(i);
while (HalpPendingInterruptCount[i] > 0) while (HalpPendingInterruptCount[i] > 0)
{ {
/* /*
* For each deferred interrupt execute all the handlers at DIRQL. * For each deferred interrupt execute all the handlers at DIRQL.
*/ */
CurrentIrql = IRQ_TO_DIRQL(i);
KiInterruptDispatch2(i, NewIrql); KiInterruptDispatch2(i, NewIrql);
HalpPendingInterruptCount[i]--; HalpPendingInterruptCount[i]--;
if (HalpPendingInterruptCount[i] == 0) }
{ CurrentIrql--;
HalEndSystemInterrupt(CurrentIrql, 0); HalpEndSystemInterrupt(CurrentIrql);
}
} }
} }
} }
VOID STATIC VOID STATIC
HalpLowerIrql(KIRQL NewIrql) HalpLowerIrql(KIRQL NewIrql)
{ {
if (NewIrql > PROFILE_LEVEL) if (NewIrql >= PROFILE_LEVEL)
{ {
CurrentIrql = NewIrql; CurrentIrql = NewIrql;
return; return;
@ -131,12 +169,11 @@ HalpLowerIrql(KIRQL NewIrql)
{ {
KiDispatchInterrupt(); KiDispatchInterrupt();
} }
CurrentIrql = APC_LEVEL;
if (NewIrql == APC_LEVEL) if (NewIrql == APC_LEVEL)
{ {
CurrentIrql = NewIrql;
return; return;
} }
CurrentIrql = APC_LEVEL;
if (KeGetCurrentThread() != NULL && if (KeGetCurrentThread() != NULL &&
KeGetCurrentThread()->ApcState.KernelApcPending) KeGetCurrentThread()->ApcState.KernelApcPending)
{ {
@ -325,16 +362,16 @@ HalBeginSystemInterrupt (ULONG Vector,
return(FALSE); return(FALSE);
} }
irq = Vector - IRQ_BASE; irq = Vector - IRQ_BASE;
pic_mask_intr |= (1 << irq); pic_mask_intr.both |= ((1 << irq) & 0xfffe); // do not disable the timer interrupt
if (irq < 8) if (irq < 8)
{ {
WRITE_PORT_UCHAR((PUCHAR)0x21, (pic_mask|pic_mask_intr) & 0xff); WRITE_PORT_UCHAR((PUCHAR)0x21, pic_mask.master|pic_mask_intr.master);
WRITE_PORT_UCHAR((PUCHAR)0x20, 0x20); WRITE_PORT_UCHAR((PUCHAR)0x20, 0x20);
} }
else else
{ {
WRITE_PORT_UCHAR((PUCHAR)0xa1, ((pic_mask|pic_mask_intr) >> 8) & 0xff); WRITE_PORT_UCHAR((PUCHAR)0xa1, pic_mask.slave|pic_mask_intr.slave);
/* Send EOI to the PICs */ /* Send EOI to the PICs */
WRITE_PORT_UCHAR((PUCHAR)0x20,0x20); WRITE_PORT_UCHAR((PUCHAR)0x20,0x20);
WRITE_PORT_UCHAR((PUCHAR)0xa0,0x20); WRITE_PORT_UCHAR((PUCHAR)0xa0,0x20);
@ -357,29 +394,8 @@ VOID STDCALL HalEndSystemInterrupt (KIRQL Irql, ULONG Unknown2)
* FUNCTION: Finish a system interrupt and restore the specified irq level. * FUNCTION: Finish a system interrupt and restore the specified irq level.
*/ */
{ {
ULONG mask;
HalpLowerIrql(Irql); HalpLowerIrql(Irql);
HalpEndSystemInterrupt(Irql);
if (Irql > PROFILE_LEVEL)
{
mask = 0xffff;
}
else if (Irql > PROFILE_LEVEL - NR_IRQS)
{
mask = ~((1 << (PROFILE_LEVEL - Irql + 1)) - 1);
}
else
{
mask = 0;
}
/* Interrupts should be disable while enabling irqs of both pics */
__asm__("pushf\n\t");
__asm__("cli\n\t");
pic_mask_intr &= mask;
WRITE_PORT_UCHAR((PUCHAR)0x21, (pic_mask|pic_mask_intr) & 0xff);
WRITE_PORT_UCHAR((PUCHAR)0xa1, ((pic_mask|pic_mask_intr) >> 8) & 0xff);
__asm__("popf\n\t");
} }
BOOLEAN STDCALL HalDisableSystemInterrupt (ULONG Vector, BOOLEAN STDCALL HalDisableSystemInterrupt (ULONG Vector,
@ -391,14 +407,14 @@ BOOLEAN STDCALL HalDisableSystemInterrupt (ULONG Vector,
return FALSE; return FALSE;
irq = Vector - IRQ_BASE; irq = Vector - IRQ_BASE;
pic_mask |= (1 << irq); pic_mask.both |= (1 << irq);
if (irq < 8) if (irq < 8)
{ {
WRITE_PORT_UCHAR((PUCHAR)0x21, (pic_mask|pic_mask_intr) & 0xff); WRITE_PORT_UCHAR((PUCHAR)0x21, pic_mask.master|pic_mask_intr.slave);
} }
else else
{ {
WRITE_PORT_UCHAR((PUCHAR)0xa1, ((pic_mask|pic_mask_intr) >> 8) & 0xff); WRITE_PORT_UCHAR((PUCHAR)0xa1, pic_mask.slave|pic_mask_intr.slave);
} }
return TRUE; return TRUE;
@ -415,14 +431,14 @@ BOOLEAN STDCALL HalEnableSystemInterrupt (ULONG Vector,
return FALSE; return FALSE;
irq = Vector - IRQ_BASE; irq = Vector - IRQ_BASE;
pic_mask &= ~(1 << irq); pic_mask.both &= ~(1 << irq);
if (irq < 8) if (irq < 8)
{ {
WRITE_PORT_UCHAR((PUCHAR)0x21, (pic_mask|pic_mask_intr) & 0xff); WRITE_PORT_UCHAR((PUCHAR)0x21, pic_mask.master|pic_mask_intr.master);
} }
else else
{ {
WRITE_PORT_UCHAR((PUCHAR)0xa1, ((pic_mask|pic_mask_intr) >> 8) & 0xff); WRITE_PORT_UCHAR((PUCHAR)0xa1, pic_mask.slave|pic_mask_intr.slave);
} }
return TRUE; return TRUE;