mirror of
https://github.com/reactos/reactos.git
synced 2024-12-29 10:35:28 +00:00
- Viva la deprecation! Trunk should now boot and the installer should work.
- Basically revert the new HAL/KERNEL IRQ code by putting the old one in, but without the actual pain of svn reverting and losing all the previous code. - The old code goes in ntoskrnl\deprecated, and we only add a comment to the .rbuild file, re-export an old function, and initialize the old code in kernel.c. All the other kernel changes stay in-place to be tested. - Same for hal, basically replace irq.S with irql.c in the .rbuild file, and disable the call to Halpinit1. All the other changes remain. svn path=/trunk/; revision=23707
This commit is contained in:
parent
bb00cadd67
commit
397f1f88d2
9 changed files with 1304 additions and 3 deletions
|
@ -31,7 +31,7 @@
|
|||
<define name="_NTHAL_" />
|
||||
<define name="__USE_W32API" />
|
||||
<file>ipi.c</file>
|
||||
<file>irq.S</file>
|
||||
<file>irql.c</file>
|
||||
<file>processor.c</file>
|
||||
<file>resource.c</file>
|
||||
<file>spinlock.c</file>
|
||||
|
|
|
@ -43,7 +43,7 @@ HalInitSystem (ULONG BootPhase,
|
|||
else if (BootPhase == 1)
|
||||
{
|
||||
/* Initialize the clock interrupt */
|
||||
HalpInitPhase1();
|
||||
//HalpInitPhase1();
|
||||
|
||||
/* Initialize display and make the screen black */
|
||||
HalInitializeDisplay ((PROS_LOADER_PARAMETER_BLOCK)LoaderBlock);
|
||||
|
|
425
reactos/hal/halx86/generic/irql.c
Normal file
425
reactos/hal/halx86/generic/irql.c
Normal file
|
@ -0,0 +1,425 @@
|
|||
/* $Id$
|
||||
*
|
||||
* 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(KeGetPcr()->Irql);
|
||||
}
|
||||
|
||||
VOID NTAPI 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)
|
||||
{
|
||||
KeGetPcr()->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);
|
||||
}
|
||||
KeGetPcr()->Irql--;
|
||||
HalpEndSystemInterrupt(KeGetPcr()->Irql);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
VOID STATIC
|
||||
HalpLowerIrql(KIRQL NewIrql)
|
||||
{
|
||||
if (NewIrql >= PROFILE_LEVEL)
|
||||
{
|
||||
KeGetPcr()->Irql = NewIrql;
|
||||
return;
|
||||
}
|
||||
HalpExecuteIrqs(NewIrql);
|
||||
if (NewIrql >= DISPATCH_LEVEL)
|
||||
{
|
||||
KeGetPcr()->Irql = NewIrql;
|
||||
return;
|
||||
}
|
||||
KeGetPcr()->Irql = DISPATCH_LEVEL;
|
||||
if (((PKIPCR)KeGetPcr())->HalReserved[HAL_DPC_REQUEST])
|
||||
{
|
||||
((PKIPCR)KeGetPcr())->HalReserved[HAL_DPC_REQUEST] = FALSE;
|
||||
KiDispatchInterrupt();
|
||||
}
|
||||
KeGetPcr()->Irql = APC_LEVEL;
|
||||
if (NewIrql == APC_LEVEL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (KeGetCurrentThread() != NULL &&
|
||||
KeGetCurrentThread()->ApcState.KernelApcPending)
|
||||
{
|
||||
KiDeliverApc(KernelMode, NULL, NULL);
|
||||
}
|
||||
KeGetPcr()->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 > KeGetPcr()->Irql)
|
||||
{
|
||||
DbgPrint ("(%s:%d) NewIrql %x CurrentIrql %x\n",
|
||||
__FILE__, __LINE__, NewIrql, KeGetPcr()->Irql);
|
||||
KEBUGCHECK(0);
|
||||
for(;;);
|
||||
}
|
||||
|
||||
HalpLowerIrql(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 < KeGetPcr()->Irql)
|
||||
{
|
||||
DbgPrint ("%s:%d CurrentIrql %x NewIrql %x\n",
|
||||
__FILE__,__LINE__,KeGetPcr()->Irql,NewIrql);
|
||||
KEBUGCHECK (0);
|
||||
for(;;);
|
||||
}
|
||||
|
||||
OldIrql = KeGetPcr()->Irql;
|
||||
KeGetPcr()->Irql = NewIrql;
|
||||
return OldIrql;
|
||||
}
|
||||
|
||||
/**********************************************************************
|
||||
* 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 (KIRQL Irql,
|
||||
ULONG Vector,
|
||||
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 (KeGetPcr()->Irql >= Irql)
|
||||
{
|
||||
HalpPendingInterruptCount[irq]++;
|
||||
return(FALSE);
|
||||
}
|
||||
*OldIrql = KeGetPcr()->Irql;
|
||||
KeGetPcr()->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)KeGetPcr())->HalReserved[HAL_APC_REQUEST] = TRUE;
|
||||
break;
|
||||
|
||||
case DISPATCH_LEVEL:
|
||||
((PKIPCR)KeGetPcr())->HalReserved[HAL_DPC_REQUEST] = TRUE;
|
||||
break;
|
||||
|
||||
default:
|
||||
KEBUGCHECK(0);
|
||||
}
|
||||
}
|
||||
|
||||
/* EOF */
|
780
reactos/ntoskrnl/deprecated/irq.c
Normal file
780
reactos/ntoskrnl/deprecated/irq.c
Normal file
|
@ -0,0 +1,780 @@
|
|||
/* $Id$
|
||||
*
|
||||
* COPYRIGHT: See COPYING in the top level directory
|
||||
* PROJECT: ReactOS kernel
|
||||
* FILE: ntoskrnl/ke/i386/irq.c
|
||||
* PURPOSE: IRQ handling
|
||||
*
|
||||
* PROGRAMMERS: David Welch (welch@mcmail.com)
|
||||
*/
|
||||
|
||||
/*
|
||||
* NOTE: In general the PIC interrupt priority facilities are used to
|
||||
* preserve the NT IRQL semantics, global interrupt disables are only used
|
||||
* to keep the PIC in a consistent state
|
||||
*
|
||||
*/
|
||||
|
||||
/* INCLUDES ****************************************************************/
|
||||
|
||||
#include <ntoskrnl.h>
|
||||
#include <../hal/halx86/include/halirq.h>
|
||||
#include <../hal/halx86/include/mps.h>
|
||||
|
||||
#define NDEBUG
|
||||
#include <internal/debug.h>
|
||||
|
||||
extern KDPC KiExpireTimerDpc;
|
||||
extern ULONG KiMaximumDpcQueueDepth;
|
||||
extern ULONG KiMinimumDpcRate;
|
||||
extern ULONG KiAdjustDpcThreshold;
|
||||
extern ULONG KiIdealDpcRate;
|
||||
extern LONG KiTickOffset;
|
||||
extern ULONG KeMaximumIncrement;
|
||||
extern ULONG KeMinimumIncrement;
|
||||
extern ULONG KeTimeAdjustment;
|
||||
extern BOOLEAN KiClockSetupComplete;
|
||||
|
||||
/* GLOBALS *****************************************************************/
|
||||
|
||||
/* Interrupt handler list */
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
|
||||
#define INT_NAME2(intnum) KiUnexpectedInterrupt##intnum
|
||||
|
||||
#define BUILD_INTERRUPT_HANDLER(intnum) \
|
||||
VOID INT_NAME2(intnum)(VOID);
|
||||
|
||||
#define D(x,y) \
|
||||
BUILD_INTERRUPT_HANDLER(x##y)
|
||||
|
||||
#define D16(x) \
|
||||
D(x,0) D(x,1) D(x,2) D(x,3) \
|
||||
D(x,4) D(x,5) D(x,6) D(x,7) \
|
||||
D(x,8) D(x,9) D(x,A) D(x,B) \
|
||||
D(x,C) D(x,D) D(x,E) D(x,F)
|
||||
|
||||
D16(3) D16(4) D16(5) D16(6)
|
||||
D16(7) D16(8) D16(9) D16(A)
|
||||
D16(B) D16(C) D16(D) D16(E)
|
||||
D16(F)
|
||||
|
||||
#define L(x,y) \
|
||||
(ULONG)& INT_NAME2(x##y)
|
||||
|
||||
#define L16(x) \
|
||||
L(x,0), L(x,1), L(x,2), L(x,3), \
|
||||
L(x,4), L(x,5), L(x,6), L(x,7), \
|
||||
L(x,8), L(x,9), L(x,A), L(x,B), \
|
||||
L(x,C), L(x,D), L(x,E), L(x,F)
|
||||
|
||||
static ULONG irq_handler[ROUND_UP(NR_IRQS, 16)] = {
|
||||
L16(3), L16(4), L16(5), L16(6),
|
||||
L16(7), L16(8), L16(9), L16(A),
|
||||
L16(B), L16(C), L16(D), L16(E)
|
||||
};
|
||||
|
||||
#undef L
|
||||
#undef L16
|
||||
#undef D
|
||||
#undef D16
|
||||
|
||||
#else /* CONFIG_SMP */
|
||||
|
||||
void irq_handler_0(void);
|
||||
void irq_handler_1(void);
|
||||
void irq_handler_2(void);
|
||||
void irq_handler_3(void);
|
||||
void irq_handler_4(void);
|
||||
void irq_handler_5(void);
|
||||
void irq_handler_6(void);
|
||||
void irq_handler_7(void);
|
||||
void irq_handler_8(void);
|
||||
void irq_handler_9(void);
|
||||
void irq_handler_10(void);
|
||||
void irq_handler_11(void);
|
||||
void irq_handler_12(void);
|
||||
void irq_handler_13(void);
|
||||
void irq_handler_14(void);
|
||||
void irq_handler_15(void);
|
||||
|
||||
static unsigned int irq_handler[NR_IRQS]=
|
||||
{
|
||||
(int)&irq_handler_0,
|
||||
(int)&irq_handler_1,
|
||||
(int)&irq_handler_2,
|
||||
(int)&irq_handler_3,
|
||||
(int)&irq_handler_4,
|
||||
(int)&irq_handler_5,
|
||||
(int)&irq_handler_6,
|
||||
(int)&irq_handler_7,
|
||||
(int)&irq_handler_8,
|
||||
(int)&irq_handler_9,
|
||||
(int)&irq_handler_10,
|
||||
(int)&irq_handler_11,
|
||||
(int)&irq_handler_12,
|
||||
(int)&irq_handler_13,
|
||||
(int)&irq_handler_14,
|
||||
(int)&irq_handler_15,
|
||||
};
|
||||
|
||||
#endif /* CONFIG_SMP */
|
||||
|
||||
/*
|
||||
* PURPOSE: Object describing each isr
|
||||
* NOTE: The data in this table is only modified at passsive level but can
|
||||
* be accessed at any irq level.
|
||||
*/
|
||||
|
||||
typedef struct
|
||||
{
|
||||
LIST_ENTRY ListHead;
|
||||
KSPIN_LOCK Lock;
|
||||
ULONG Count;
|
||||
}
|
||||
ISR_TABLE, *PISR_TABLE;
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
static ISR_TABLE IsrTable[NR_IRQS][MAXIMUM_PROCESSORS];
|
||||
#else
|
||||
static ISR_TABLE IsrTable[NR_IRQS][1];
|
||||
#endif
|
||||
|
||||
#define TAG_ISR_LOCK TAG('I', 'S', 'R', 'L')
|
||||
extern IDT_DESCRIPTOR KiIdt[256];
|
||||
|
||||
/* FUNCTIONS ****************************************************************/
|
||||
|
||||
#define PRESENT (0x8000)
|
||||
#define I486_INTERRUPT_GATE (0xe00)
|
||||
|
||||
VOID
|
||||
INIT_FUNCTION
|
||||
NTAPI
|
||||
KeInitInterrupts (VOID)
|
||||
{
|
||||
int i, j;
|
||||
|
||||
|
||||
/*
|
||||
* Setup the IDT entries to point to the interrupt handlers
|
||||
*/
|
||||
for (i=0;i<NR_IRQS;i++)
|
||||
{
|
||||
KiIdt[IRQ_BASE+i].a=(irq_handler[i]&0xffff)+(KGDT_R0_CODE<<16);
|
||||
KiIdt[IRQ_BASE+i].b=(irq_handler[i]&0xffff0000)+PRESENT+
|
||||
I486_INTERRUPT_GATE;
|
||||
#ifdef CONFIG_SMP
|
||||
for (j = 0; j < MAXIMUM_PROCESSORS; j++)
|
||||
#else
|
||||
j = 0;
|
||||
#endif
|
||||
{
|
||||
InitializeListHead(&IsrTable[i][j].ListHead);
|
||||
KeInitializeSpinLock(&IsrTable[i][j].Lock);
|
||||
IsrTable[i][j].Count = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
STATIC VOID
|
||||
KeIRQTrapFrameToTrapFrame(PKIRQ_TRAPFRAME IrqTrapFrame,
|
||||
PKTRAP_FRAME TrapFrame)
|
||||
{
|
||||
TrapFrame->SegGs = (USHORT)IrqTrapFrame->Gs;
|
||||
TrapFrame->SegFs = (USHORT)IrqTrapFrame->Fs;
|
||||
TrapFrame->SegEs = (USHORT)IrqTrapFrame->Es;
|
||||
TrapFrame->SegDs = (USHORT)IrqTrapFrame->Ds;
|
||||
TrapFrame->Eax = IrqTrapFrame->Eax;
|
||||
TrapFrame->Ecx = IrqTrapFrame->Ecx;
|
||||
TrapFrame->Edx = IrqTrapFrame->Edx;
|
||||
TrapFrame->Ebx = IrqTrapFrame->Ebx;
|
||||
TrapFrame->HardwareEsp = IrqTrapFrame->Esp;
|
||||
TrapFrame->Ebp = IrqTrapFrame->Ebp;
|
||||
TrapFrame->Esi = IrqTrapFrame->Esi;
|
||||
TrapFrame->Edi = IrqTrapFrame->Edi;
|
||||
TrapFrame->Eip = IrqTrapFrame->Eip;
|
||||
TrapFrame->SegCs = IrqTrapFrame->Cs;
|
||||
TrapFrame->EFlags = IrqTrapFrame->Eflags;
|
||||
}
|
||||
|
||||
STATIC VOID
|
||||
KeTrapFrameToIRQTrapFrame(PKTRAP_FRAME TrapFrame,
|
||||
PKIRQ_TRAPFRAME IrqTrapFrame)
|
||||
{
|
||||
IrqTrapFrame->Gs = TrapFrame->SegGs;
|
||||
IrqTrapFrame->Fs = TrapFrame->SegFs;
|
||||
IrqTrapFrame->Es = TrapFrame->SegEs;
|
||||
IrqTrapFrame->Ds = TrapFrame->SegDs;
|
||||
IrqTrapFrame->Eax = TrapFrame->Eax;
|
||||
IrqTrapFrame->Ecx = TrapFrame->Ecx;
|
||||
IrqTrapFrame->Edx = TrapFrame->Edx;
|
||||
IrqTrapFrame->Ebx = TrapFrame->Ebx;
|
||||
IrqTrapFrame->Esp = TrapFrame->HardwareEsp;
|
||||
IrqTrapFrame->Ebp = TrapFrame->Ebp;
|
||||
IrqTrapFrame->Esi = TrapFrame->Esi;
|
||||
IrqTrapFrame->Edi = TrapFrame->Edi;
|
||||
IrqTrapFrame->Eip = TrapFrame->Eip;
|
||||
IrqTrapFrame->Cs = TrapFrame->SegCs;
|
||||
IrqTrapFrame->Eflags = TrapFrame->EFlags;
|
||||
}
|
||||
|
||||
/*
|
||||
* NOTE: On Windows this function takes exactly one parameter and EBP is
|
||||
* guaranteed to point to KTRAP_FRAME. The function is used only
|
||||
* by HAL, so there's no point in keeping that prototype.
|
||||
*
|
||||
* @implemented
|
||||
*/
|
||||
VOID
|
||||
STDCALL
|
||||
KeUpdateRunTime(IN PKTRAP_FRAME TrapFrame,
|
||||
IN KIRQL Irql)
|
||||
{
|
||||
PKPRCB Prcb = KeGetCurrentPrcb();
|
||||
PKTHREAD CurrentThread;
|
||||
PKPROCESS CurrentProcess;
|
||||
|
||||
/* Make sure we don't go further if we're in early boot phase. */
|
||||
if (!(Prcb) || !(Prcb->CurrentThread)) return;
|
||||
|
||||
/* Get the current thread and process */
|
||||
CurrentThread = Prcb->CurrentThread;
|
||||
CurrentProcess = CurrentThread->ApcState.Process;
|
||||
|
||||
/* Check if we came from user mode */
|
||||
if (TrapFrame->PreviousPreviousMode != KernelMode)
|
||||
{
|
||||
/* Update user times */
|
||||
CurrentThread->UserTime++;
|
||||
InterlockedIncrement((PLONG)&CurrentProcess->UserTime);
|
||||
Prcb->UserTime++;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Check IRQ */
|
||||
if (Irql > DISPATCH_LEVEL)
|
||||
{
|
||||
/* This was an interrupt */
|
||||
Prcb->InterruptTime++;
|
||||
}
|
||||
else if ((Irql < DISPATCH_LEVEL) || !(Prcb->DpcRoutineActive))
|
||||
{
|
||||
/* This was normal kernel time */
|
||||
CurrentThread->KernelTime++;
|
||||
InterlockedIncrement((PLONG)&CurrentProcess->KernelTime);
|
||||
}
|
||||
else if (Irql == DISPATCH_LEVEL)
|
||||
{
|
||||
/* This was DPC time */
|
||||
Prcb->DpcTime++;
|
||||
}
|
||||
|
||||
/* Update CPU kernel time in all cases */
|
||||
Prcb->KernelTime++;
|
||||
}
|
||||
|
||||
/* Set the last DPC Count and request rate */
|
||||
Prcb->DpcLastCount = Prcb->DpcData[0].DpcCount;
|
||||
Prcb->DpcRequestRate = ((Prcb->DpcData[0].DpcCount - Prcb->DpcLastCount) +
|
||||
Prcb->DpcRequestRate) / 2;
|
||||
|
||||
/* Check if we should request a DPC */
|
||||
if ((Prcb->DpcData[0].DpcQueueDepth) && !(Prcb->DpcRoutineActive))
|
||||
{
|
||||
/* Request one */
|
||||
HalRequestSoftwareInterrupt(DISPATCH_LEVEL);
|
||||
|
||||
/* Update the depth if needed */
|
||||
if ((Prcb->DpcRequestRate < KiIdealDpcRate) &&
|
||||
(Prcb->MaximumDpcQueueDepth > 1))
|
||||
{
|
||||
/* Decrease the maximum depth by one */
|
||||
Prcb->MaximumDpcQueueDepth--;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Decrease the adjustment threshold */
|
||||
if (!(--Prcb->AdjustDpcThreshold))
|
||||
{
|
||||
/* We've hit 0, reset it */
|
||||
Prcb->AdjustDpcThreshold = KiAdjustDpcThreshold;
|
||||
|
||||
/* Check if we've hit queue maximum */
|
||||
if (KiMaximumDpcQueueDepth != Prcb->MaximumDpcQueueDepth)
|
||||
{
|
||||
/* Increase maximum by one */
|
||||
Prcb->MaximumDpcQueueDepth++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* If we're at end of quantum request software interrupt. The rest
|
||||
* is handled in KiDispatchInterrupt.
|
||||
*
|
||||
* NOTE: If one stays at DISPATCH_LEVEL for a long time the DPC routine
|
||||
* which checks for quantum end will not be executed and decrementing
|
||||
* the quantum here can result in overflow. This is not a problem since
|
||||
* we don't care about the quantum value anymore after the QuantumEnd
|
||||
* flag is set.
|
||||
*/
|
||||
if ((CurrentThread->Quantum -= 3) <= 0)
|
||||
{
|
||||
Prcb->QuantumEnd = TRUE;
|
||||
HalRequestSoftwareInterrupt(DISPATCH_LEVEL);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* NOTE: On Windows this function takes exactly zero parameters and EBP is
|
||||
* guaranteed to point to KTRAP_FRAME. Also [esp+0] contains an IRQL.
|
||||
* The function is used only by HAL, so there's no point in keeping
|
||||
* that prototype.
|
||||
*
|
||||
* @implemented
|
||||
*/
|
||||
VOID
|
||||
STDCALL
|
||||
KeUpdateSystemTime(IN PKTRAP_FRAME TrapFrame,
|
||||
IN KIRQL Irql,
|
||||
IN ULONG Increment)
|
||||
{
|
||||
LONG OldOffset;
|
||||
LARGE_INTEGER Time;
|
||||
ASSERT(KeGetCurrentIrql() == PROFILE_LEVEL);
|
||||
if (!KiClockSetupComplete) return;
|
||||
|
||||
/* Update interrupt time */
|
||||
Time.LowPart = SharedUserData->InterruptTime.LowPart;
|
||||
Time.HighPart = SharedUserData->InterruptTime.High1Time;
|
||||
Time.QuadPart += Increment;
|
||||
SharedUserData->InterruptTime.High2Time = Time.u.HighPart;
|
||||
SharedUserData->InterruptTime.LowPart = Time.u.LowPart;
|
||||
SharedUserData->InterruptTime.High1Time = Time.u.HighPart;
|
||||
|
||||
/* Increase the tick offset */
|
||||
KiTickOffset -= Increment;
|
||||
OldOffset = KiTickOffset;
|
||||
|
||||
/* Check if this isn't a tick yet */
|
||||
if (KiTickOffset > 0)
|
||||
{
|
||||
/* Expire timers */
|
||||
KeInsertQueueDpc(&KiExpireTimerDpc, (PVOID)TrapFrame->Eip, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Setup time structure for system time */
|
||||
Time.LowPart = SharedUserData->SystemTime.LowPart;
|
||||
Time.HighPart = SharedUserData->SystemTime.High1Time;
|
||||
Time.QuadPart += KeTimeAdjustment;
|
||||
SharedUserData->SystemTime.High2Time = Time.HighPart;
|
||||
SharedUserData->SystemTime.LowPart = Time.LowPart;
|
||||
SharedUserData->SystemTime.High1Time = Time.HighPart;
|
||||
|
||||
/* Setup time structure for tick time */
|
||||
Time.LowPart = KeTickCount.LowPart;
|
||||
Time.HighPart = KeTickCount.High1Time;
|
||||
Time.QuadPart += 1;
|
||||
KeTickCount.High2Time = Time.HighPart;
|
||||
KeTickCount.LowPart = Time.LowPart;
|
||||
KeTickCount.High1Time = Time.HighPart;
|
||||
SharedUserData->TickCount.High2Time = Time.HighPart;
|
||||
SharedUserData->TickCount.LowPart = Time.LowPart;
|
||||
SharedUserData->TickCount.High1Time = Time.HighPart;
|
||||
|
||||
/* Update tick count in shared user data as well */
|
||||
SharedUserData->TickCountLowDeprecated++;
|
||||
|
||||
/* Queue a DPC that will expire timers */
|
||||
KeInsertQueueDpc(&KiExpireTimerDpc, (PVOID)TrapFrame->Eip, 0);
|
||||
}
|
||||
|
||||
/* Update process and thread times */
|
||||
if (OldOffset <= 0)
|
||||
{
|
||||
/* This was a tick, calculate the next one */
|
||||
KiTickOffset += KeMaximumIncrement;
|
||||
KeUpdateRunTime(TrapFrame, Irql);
|
||||
}
|
||||
}
|
||||
|
||||
VOID STDCALL
|
||||
KiInterruptDispatch2 (ULONG vector, KIRQL old_level)
|
||||
/*
|
||||
* FUNCTION: Calls all the interrupt handlers for a given irq.
|
||||
* ARGUMENTS:
|
||||
* vector - The number of the vector to call handlers for.
|
||||
* old_level - The irql of the processor when the irq took place.
|
||||
* NOTES: Must be called at DIRQL.
|
||||
*/
|
||||
{
|
||||
PKINTERRUPT isr;
|
||||
PLIST_ENTRY current;
|
||||
KIRQL oldlvl;
|
||||
PISR_TABLE CurrentIsr;
|
||||
|
||||
DPRINT("I(0x%.08x, 0x%.08x)\n", vector, old_level);
|
||||
|
||||
/*
|
||||
* Iterate the list until one of the isr tells us its device interrupted
|
||||
*/
|
||||
CurrentIsr = &IsrTable[vector - IRQ_BASE][(ULONG)KeGetCurrentProcessorNumber()];
|
||||
|
||||
KiAcquireSpinLock(&CurrentIsr->Lock);
|
||||
|
||||
CurrentIsr->Count++;
|
||||
current = CurrentIsr->ListHead.Flink;
|
||||
|
||||
while (current != &CurrentIsr->ListHead)
|
||||
{
|
||||
isr = CONTAINING_RECORD(current,KINTERRUPT,InterruptListEntry);
|
||||
oldlvl = KeAcquireInterruptSpinLock(isr);
|
||||
if (isr->ServiceRoutine(isr, isr->ServiceContext))
|
||||
{
|
||||
KeReleaseInterruptSpinLock(isr, oldlvl);
|
||||
break;
|
||||
}
|
||||
KeReleaseInterruptSpinLock(isr, oldlvl);
|
||||
current = current->Flink;
|
||||
}
|
||||
KiReleaseSpinLock(&CurrentIsr->Lock);
|
||||
}
|
||||
|
||||
VOID
|
||||
KiInterruptDispatch3 (ULONG vector, PKIRQ_TRAPFRAME Trapframe)
|
||||
/*
|
||||
* FUNCTION: Calls the irq specific handler for an irq
|
||||
* ARGUMENTS:
|
||||
* irq = IRQ that has interrupted
|
||||
*/
|
||||
{
|
||||
KIRQL old_level;
|
||||
KTRAP_FRAME KernelTrapFrame;
|
||||
PKTHREAD CurrentThread;
|
||||
PKTRAP_FRAME OldTrapFrame=NULL;
|
||||
|
||||
/*
|
||||
* At this point we have interrupts disabled, nothing has been done to
|
||||
* the PIC.
|
||||
*/
|
||||
|
||||
KeGetCurrentPrcb()->InterruptCount++;
|
||||
|
||||
/*
|
||||
* Notify the rest of the kernel of the raised irq level. For the
|
||||
* default HAL this will send an EOI to the PIC and alter the IRQL.
|
||||
*/
|
||||
if (!HalBeginSystemInterrupt (VECTOR2IRQL(vector),
|
||||
vector,
|
||||
&old_level))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Enable interrupts
|
||||
* NOTE: Only higher priority interrupts will get through
|
||||
*/
|
||||
Ke386EnableInterrupts();
|
||||
|
||||
#ifndef CONFIG_SMP
|
||||
if (VECTOR2IRQ(vector) == 0)
|
||||
{
|
||||
KeIRQTrapFrameToTrapFrame(Trapframe, &KernelTrapFrame);
|
||||
KeUpdateSystemTime(&KernelTrapFrame, old_level, 100000);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
/*
|
||||
* Actually call the ISR.
|
||||
*/
|
||||
KiInterruptDispatch2(vector, old_level);
|
||||
}
|
||||
|
||||
/*
|
||||
* End the system interrupt.
|
||||
*/
|
||||
Ke386DisableInterrupts();
|
||||
|
||||
if (old_level==PASSIVE_LEVEL && Trapframe->Cs != KGDT_R0_CODE)
|
||||
{
|
||||
HalEndSystemInterrupt (APC_LEVEL, 0);
|
||||
|
||||
CurrentThread = KeGetCurrentThread();
|
||||
if (CurrentThread!=NULL && CurrentThread->ApcState.UserApcPending)
|
||||
{
|
||||
DPRINT("PID: %d, TID: %d CS %04x/%04x\n",
|
||||
((PETHREAD)CurrentThread)->ThreadsProcess->UniqueProcessId,
|
||||
((PETHREAD)CurrentThread)->Cid.UniqueThread,
|
||||
Trapframe->Cs,
|
||||
CurrentThread->TrapFrame ? CurrentThread->TrapFrame->Cs : 0);
|
||||
if (CurrentThread->TrapFrame == NULL)
|
||||
{
|
||||
OldTrapFrame = CurrentThread->TrapFrame;
|
||||
KeIRQTrapFrameToTrapFrame(Trapframe, &KernelTrapFrame);
|
||||
CurrentThread->TrapFrame = &KernelTrapFrame;
|
||||
}
|
||||
|
||||
Ke386EnableInterrupts();
|
||||
KiDeliverApc(UserMode, NULL, NULL);
|
||||
Ke386DisableInterrupts();
|
||||
|
||||
ASSERT(KeGetCurrentThread() == CurrentThread);
|
||||
if (CurrentThread->TrapFrame == &KernelTrapFrame)
|
||||
{
|
||||
KeTrapFrameToIRQTrapFrame(&KernelTrapFrame, Trapframe);
|
||||
CurrentThread->TrapFrame = OldTrapFrame;
|
||||
}
|
||||
}
|
||||
KeLowerIrql(PASSIVE_LEVEL);
|
||||
}
|
||||
else
|
||||
{
|
||||
HalEndSystemInterrupt (old_level, 0);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static VOID
|
||||
KeDumpIrqList(VOID)
|
||||
{
|
||||
PKINTERRUPT current;
|
||||
PLIST_ENTRY current_entry;
|
||||
LONG i, j;
|
||||
KIRQL oldlvl;
|
||||
BOOLEAN printed;
|
||||
|
||||
for (i=0;i<NR_IRQS;i++)
|
||||
{
|
||||
printed = FALSE;
|
||||
KeRaiseIrql(VECTOR2IRQL(i + IRQ_BASE),&oldlvl);
|
||||
|
||||
for (j=0; j < KeNumberProcessors; j++)
|
||||
{
|
||||
KiAcquireSpinLock(&IsrTable[i][j].Lock);
|
||||
|
||||
current_entry = IsrTable[i][j].ListHead.Flink;
|
||||
current = CONTAINING_RECORD(current_entry,KINTERRUPT,InterruptListEntry);
|
||||
while (current_entry!=&(IsrTable[i][j].ListHead))
|
||||
{
|
||||
if (printed == FALSE)
|
||||
{
|
||||
printed = TRUE;
|
||||
DPRINT("For irq %x:\n",i);
|
||||
}
|
||||
DPRINT(" Isr %x\n",current);
|
||||
current_entry = current_entry->Flink;
|
||||
current = CONTAINING_RECORD(current_entry,KINTERRUPT,InterruptListEntry);
|
||||
}
|
||||
KiReleaseSpinLock(&IsrTable[i][j].Lock);
|
||||
}
|
||||
KeLowerIrql(oldlvl);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* @implemented
|
||||
*/
|
||||
BOOLEAN
|
||||
STDCALL
|
||||
KeConnectInterrupt(PKINTERRUPT InterruptObject)
|
||||
{
|
||||
KIRQL oldlvl,synch_oldlvl;
|
||||
PKINTERRUPT ListHead;
|
||||
ULONG Vector;
|
||||
PISR_TABLE CurrentIsr;
|
||||
BOOLEAN Result;
|
||||
|
||||
DPRINT("KeConnectInterrupt()\n");
|
||||
|
||||
Vector = InterruptObject->Vector;
|
||||
|
||||
if (Vector < IRQ_BASE || Vector >= IRQ_BASE + NR_IRQS)
|
||||
return FALSE;
|
||||
|
||||
Vector -= IRQ_BASE;
|
||||
|
||||
ASSERT (InterruptObject->Number < KeNumberProcessors);
|
||||
|
||||
KeSetSystemAffinityThread(1 << InterruptObject->Number);
|
||||
|
||||
CurrentIsr = &IsrTable[Vector][(ULONG)InterruptObject->Number];
|
||||
|
||||
KeRaiseIrql(VECTOR2IRQL(Vector + IRQ_BASE),&oldlvl);
|
||||
KiAcquireSpinLock(&CurrentIsr->Lock);
|
||||
|
||||
/*
|
||||
* Check if the vector is already in use that we can share it
|
||||
*/
|
||||
if (!IsListEmpty(&CurrentIsr->ListHead))
|
||||
{
|
||||
ListHead = CONTAINING_RECORD(CurrentIsr->ListHead.Flink,KINTERRUPT,InterruptListEntry);
|
||||
if (InterruptObject->ShareVector == FALSE || ListHead->ShareVector==FALSE)
|
||||
{
|
||||
KiReleaseSpinLock(&CurrentIsr->Lock);
|
||||
KeLowerIrql(oldlvl);
|
||||
KeRevertToUserAffinityThread();
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
synch_oldlvl = KeAcquireInterruptSpinLock(InterruptObject);
|
||||
|
||||
DPRINT("%x %x\n",CurrentIsr->ListHead.Flink, CurrentIsr->ListHead.Blink);
|
||||
|
||||
Result = HalEnableSystemInterrupt(Vector + IRQ_BASE, InterruptObject->Irql, InterruptObject->Mode);
|
||||
if (Result)
|
||||
{
|
||||
InsertTailList(&CurrentIsr->ListHead,&InterruptObject->InterruptListEntry);
|
||||
DPRINT("%x %x\n",InterruptObject->InterruptListEntry.Flink, InterruptObject->InterruptListEntry.Blink);
|
||||
}
|
||||
|
||||
InterruptObject->Connected = TRUE;
|
||||
KeReleaseInterruptSpinLock(InterruptObject, synch_oldlvl);
|
||||
|
||||
/*
|
||||
* Release the table spinlock
|
||||
*/
|
||||
KiReleaseSpinLock(&CurrentIsr->Lock);
|
||||
KeLowerIrql(oldlvl);
|
||||
|
||||
KeDumpIrqList();
|
||||
|
||||
KeRevertToUserAffinityThread();
|
||||
|
||||
return Result;
|
||||
}
|
||||
|
||||
/*
|
||||
* @implemented
|
||||
*
|
||||
* FUNCTION: Releases a drivers isr
|
||||
* ARGUMENTS:
|
||||
* InterruptObject = isr to release
|
||||
*/
|
||||
BOOLEAN
|
||||
STDCALL
|
||||
KeDisconnectInterrupt(PKINTERRUPT InterruptObject)
|
||||
{
|
||||
KIRQL oldlvl,synch_oldlvl;
|
||||
PISR_TABLE CurrentIsr;
|
||||
BOOLEAN State;
|
||||
|
||||
DPRINT1("KeDisconnectInterrupt\n");
|
||||
ASSERT (InterruptObject->Number < KeNumberProcessors);
|
||||
|
||||
/* Set the affinity */
|
||||
KeSetSystemAffinityThread(1 << InterruptObject->Number);
|
||||
|
||||
/* Get the ISR Tabe */
|
||||
CurrentIsr = &IsrTable[InterruptObject->Vector - IRQ_BASE]
|
||||
[(ULONG)InterruptObject->Number];
|
||||
|
||||
/* Raise IRQL to required level and lock table */
|
||||
KeRaiseIrql(VECTOR2IRQL(InterruptObject->Vector),&oldlvl);
|
||||
KiAcquireSpinLock(&CurrentIsr->Lock);
|
||||
|
||||
/* Check if it's actually connected */
|
||||
if ((State = InterruptObject->Connected))
|
||||
{
|
||||
/* Lock the Interrupt */
|
||||
synch_oldlvl = KeAcquireInterruptSpinLock(InterruptObject);
|
||||
|
||||
/* Remove this one, and check if all are gone */
|
||||
RemoveEntryList(&InterruptObject->InterruptListEntry);
|
||||
if (IsListEmpty(&CurrentIsr->ListHead))
|
||||
{
|
||||
/* Completely Disable the Interrupt */
|
||||
HalDisableSystemInterrupt(InterruptObject->Vector, InterruptObject->Irql);
|
||||
}
|
||||
|
||||
/* Disconnect it */
|
||||
InterruptObject->Connected = FALSE;
|
||||
|
||||
/* Release the interrupt lock */
|
||||
KeReleaseInterruptSpinLock(InterruptObject, synch_oldlvl);
|
||||
}
|
||||
/* Release the table spinlock */
|
||||
KiReleaseSpinLock(&CurrentIsr->Lock);
|
||||
KeLowerIrql(oldlvl);
|
||||
|
||||
/* Go back to default affinity */
|
||||
KeRevertToUserAffinityThread();
|
||||
|
||||
/* Return Old Interrupt State */
|
||||
return State;
|
||||
}
|
||||
|
||||
/*
|
||||
* @implemented
|
||||
*/
|
||||
VOID
|
||||
STDCALL
|
||||
KeInitializeInterrupt(PKINTERRUPT Interrupt,
|
||||
PKSERVICE_ROUTINE ServiceRoutine,
|
||||
PVOID ServiceContext,
|
||||
PKSPIN_LOCK SpinLock,
|
||||
ULONG Vector,
|
||||
KIRQL Irql,
|
||||
KIRQL SynchronizeIrql,
|
||||
KINTERRUPT_MODE InterruptMode,
|
||||
BOOLEAN ShareVector,
|
||||
CHAR ProcessorNumber,
|
||||
BOOLEAN FloatingSave)
|
||||
{
|
||||
/* Set the Interrupt Header */
|
||||
Interrupt->Type = InterruptObject;
|
||||
Interrupt->Size = sizeof(KINTERRUPT);
|
||||
|
||||
/* Check if we got a spinlock */
|
||||
if (SpinLock)
|
||||
{
|
||||
Interrupt->ActualLock = SpinLock;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* This means we'll be usin the built-in one */
|
||||
KeInitializeSpinLock(&Interrupt->SpinLock);
|
||||
Interrupt->ActualLock = &Interrupt->SpinLock;
|
||||
}
|
||||
|
||||
/* Set the other settings */
|
||||
Interrupt->ServiceRoutine = ServiceRoutine;
|
||||
Interrupt->ServiceContext = ServiceContext;
|
||||
Interrupt->Vector = Vector;
|
||||
Interrupt->Irql = Irql;
|
||||
Interrupt->SynchronizeIrql = SynchronizeIrql;
|
||||
Interrupt->Mode = InterruptMode;
|
||||
Interrupt->ShareVector = ShareVector;
|
||||
Interrupt->Number = ProcessorNumber;
|
||||
Interrupt->FloatingSave = FloatingSave;
|
||||
|
||||
/* Disconnect it at first */
|
||||
Interrupt->Connected = FALSE;
|
||||
}
|
||||
|
||||
VOID KePrintInterruptStatistic(VOID)
|
||||
{
|
||||
LONG i, j;
|
||||
|
||||
for (j = 0; j < KeNumberProcessors; j++)
|
||||
{
|
||||
DPRINT1("CPU%d:\n", j);
|
||||
for (i = 0; i < NR_IRQS; i++)
|
||||
{
|
||||
if (IsrTable[i][j].Count)
|
||||
{
|
||||
DPRINT1(" Irq %x(%d): %d\n", i, VECTOR2IRQ(i + IRQ_BASE), IsrTable[i][j].Count);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* EOF */
|
89
reactos/ntoskrnl/deprecated/irqhand.S
Normal file
89
reactos/ntoskrnl/deprecated/irqhand.S
Normal file
|
@ -0,0 +1,89 @@
|
|||
#include <ndk/asm.h>
|
||||
#include <../hal/halx86/include/halirq.h>
|
||||
|
||||
_KiCommonInterrupt:
|
||||
cld
|
||||
pushl %ds
|
||||
pushl %es
|
||||
pushl %fs
|
||||
pushl %gs
|
||||
pushl $0xceafbeef
|
||||
movl $KGDT_R0_DATA,%eax
|
||||
movl %eax,%ds
|
||||
movl %eax,%es
|
||||
movl %eax,%gs
|
||||
movl $KGDT_R0_PCR,%eax
|
||||
movl %eax,%fs
|
||||
pushl %esp
|
||||
pushl %ebx
|
||||
call _KiInterruptDispatch3
|
||||
addl $0xC, %esp
|
||||
popl %gs
|
||||
popl %fs
|
||||
popl %es
|
||||
popl %ds
|
||||
popa
|
||||
iret
|
||||
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
|
||||
#define BUILD_INTERRUPT_HANDLER(intnum) \
|
||||
.global _KiUnexpectedInterrupt##intnum; \
|
||||
_KiUnexpectedInterrupt##intnum:; \
|
||||
pusha; \
|
||||
movl $0x##intnum, %ebx; \
|
||||
jmp _KiCommonInterrupt;
|
||||
|
||||
/* Interrupt handlers and declarations */
|
||||
|
||||
#define B(x,y) \
|
||||
BUILD_INTERRUPT_HANDLER(x##y)
|
||||
|
||||
#define B16(x) \
|
||||
B(x,0) B(x,1) B(x,2) B(x,3) \
|
||||
B(x,4) B(x,5) B(x,6) B(x,7) \
|
||||
B(x,8) B(x,9) B(x,A) B(x,B) \
|
||||
B(x,C) B(x,D) B(x,E) B(x,F)
|
||||
|
||||
B16(3) B16(4) B16(5) B16(6)
|
||||
B16(7) B16(8) B16(9) B16(A)
|
||||
B16(B) B16(C) B16(D) B16(E)
|
||||
B16(F)
|
||||
|
||||
#undef B
|
||||
#undef B16
|
||||
#undef BUILD_INTERRUPT_HANDLER
|
||||
|
||||
#else /* CONFIG_SMP */
|
||||
|
||||
#define BUILD_INTERRUPT_HANDLER(intnum) \
|
||||
.global _irq_handler_##intnum; \
|
||||
_irq_handler_##intnum:; \
|
||||
pusha; \
|
||||
movl $(##intnum + IRQ_BASE), %ebx; \
|
||||
jmp _KiCommonInterrupt;
|
||||
|
||||
/* Interrupt handlers and declarations */
|
||||
|
||||
#define B(x) \
|
||||
BUILD_INTERRUPT_HANDLER(x)
|
||||
|
||||
B(0) B(1) B(2) B(3)
|
||||
B(4) B(5) B(6) B(7)
|
||||
B(8) B(9) B(10) B(11)
|
||||
B(12) B(13) B(14) B(15)
|
||||
|
||||
#undef B
|
||||
#undef BUILD_INTERRUPT_HANDLER
|
||||
|
||||
#endif /* CONFIG_SMP */
|
||||
|
||||
.intel_syntax noprefix
|
||||
.globl _KiUnexpectedInterrupt@0
|
||||
_KiUnexpectedInterrupt@0:
|
||||
|
||||
/* Bugcheck with invalid interrupt code */
|
||||
push 0x12
|
||||
call _KeBugCheck@4
|
||||
|
|
@ -94,6 +94,7 @@ KiInitializeSystemClock(VOID)
|
|||
SharedUserData->SystemTime.High2Time = SystemBootTime.u.HighPart;
|
||||
SharedUserData->SystemTime.LowPart = SystemBootTime.u.LowPart;
|
||||
SharedUserData->SystemTime.High1Time = SystemBootTime.u.HighPart;
|
||||
KiClockSetupComplete = TRUE;
|
||||
}
|
||||
|
||||
VOID
|
||||
|
|
|
@ -380,6 +380,7 @@ KeInit1(PCHAR CommandLine, PULONG LastKernelAddress)
|
|||
InitializeListHead(&KPCR->PrcbData.WaitListHead);
|
||||
|
||||
KeInitExceptions ();
|
||||
KeInitInterrupts ();
|
||||
|
||||
KeActiveProcessors |= 1 << 0;
|
||||
|
||||
|
|
|
@ -663,6 +663,7 @@ KiCoprocessorError@0
|
|||
KiCheckForKernelApcDelivery@0
|
||||
KiDeliverApc@12
|
||||
KiDispatchInterrupt@0
|
||||
KiInterruptDispatch2@8
|
||||
KiEnableTimerWatchdog
|
||||
KiIpiServiceRoutine@8
|
||||
@KiReleaseSpinLock@4
|
||||
|
|
|
@ -33,7 +33,7 @@
|
|||
<file>exp.c</file>
|
||||
<file>fpu.c</file>
|
||||
<file>gdt.c</file>
|
||||
<file>irq.c</file>
|
||||
<!-- <file>irq.c</file> -->
|
||||
<file>kernel.c</file>
|
||||
<file>ldt.c</file>
|
||||
<file>thread.c</file>
|
||||
|
@ -68,6 +68,10 @@
|
|||
<file>usercall.c</file>
|
||||
<file>wait.c</file>
|
||||
</directory>
|
||||
<directory name="deprecated">
|
||||
<file>irqhand.S</file>
|
||||
<file>irq.c</file>
|
||||
</directory>
|
||||
<directory name="cc">
|
||||
<file>cacheman.c</file>
|
||||
<file>copy.c</file>
|
||||
|
|
Loading…
Reference in a new issue