mirror of
https://github.com/reactos/reactos.git
synced 2024-08-23 03:42:40 +00:00
- Cleanup more code in the deprecated IRQ implementation and use the newer implementations oF KeInitializeInterrupt and KeDisconnectInterrupt. Will allow easier debugging oF the HAL IRQ regression with the new, unused implementation.
svn path=/trunk/; revision=24910
This commit is contained in:
parent
54306c43a2
commit
84348d0f29
|
@ -1,87 +1,25 @@
|
|||
/* $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
|
||||
*
|
||||
* PROJECT: ReactOS Kernel
|
||||
* LICENSE: GPL - See COPYING in the top level directory
|
||||
* FILE: ntoskrnl/ke/i386/irq.c
|
||||
* PURPOSE: Manages the Kernel's IRQ support for external drivers,
|
||||
* for the purpopses of connecting, disconnecting and setting
|
||||
* up ISRs for drivers. The backend behind the Io* Interrupt
|
||||
* routines.
|
||||
* PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
|
||||
*/
|
||||
|
||||
/* INCLUDES ****************************************************************/
|
||||
/* INCLUDES ******************************************************************/
|
||||
|
||||
#include <ntoskrnl.h>
|
||||
#define NDEBUG
|
||||
#include <debug.h>
|
||||
|
||||
/* DEPRECATED ****************************************************************/
|
||||
|
||||
#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);
|
||||
|
@ -119,8 +57,6 @@ static unsigned int irq_handler[NR_IRQS]=
|
|||
(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
|
||||
|
@ -135,16 +71,10 @@ typedef struct
|
|||
}
|
||||
ISR_TABLE, *PISR_TABLE;
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
static ISR_TABLE IsrTable[NR_IRQS][MAXIMUM_PROCESSORS];
|
||||
#else
|
||||
static ISR_TABLE IsrTable[NR_IRQS][1];
|
||||
#endif
|
||||
static ISR_TABLE IsrTable[NR_IRQS];
|
||||
|
||||
#define TAG_ISR_LOCK TAG('I', 'S', 'R', 'L')
|
||||
|
||||
/* FUNCTIONS ****************************************************************/
|
||||
|
||||
#define PRESENT (0x8000)
|
||||
#define I486_INTERRUPT_GATE (0xe00)
|
||||
|
||||
|
@ -153,8 +83,7 @@ INIT_FUNCTION
|
|||
NTAPI
|
||||
KeInitInterrupts (VOID)
|
||||
{
|
||||
int i, j;
|
||||
|
||||
int i;
|
||||
|
||||
/*
|
||||
* Setup the IDT entries to point to the interrupt handlers
|
||||
|
@ -164,15 +93,10 @@ KeInitInterrupts (VOID)
|
|||
((IDT_DESCRIPTOR*)&KiIdt[IRQ_BASE+i])->a=(irq_handler[i]&0xffff)+(KGDT_R0_CODE<<16);
|
||||
((IDT_DESCRIPTOR*)&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;
|
||||
InitializeListHead(&IsrTable[i].ListHead);
|
||||
KeInitializeSpinLock(&IsrTable[i].Lock);
|
||||
IsrTable[i].Count = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -192,12 +116,10 @@ KiInterruptDispatch2 (ULONG vector, KIRQL old_level)
|
|||
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()];
|
||||
CurrentIsr = &IsrTable[vector - IRQ_BASE];
|
||||
|
||||
KiAcquireSpinLock(&CurrentIsr->Lock);
|
||||
|
||||
|
@ -234,7 +156,6 @@ KiInterruptDispatch3 (ULONG vector, PKIRQ_TRAPFRAME Trapframe)
|
|||
* At this point we have interrupts disabled, nothing has been done to
|
||||
* the PIC.
|
||||
*/
|
||||
|
||||
KeGetCurrentPrcb()->InterruptCount++;
|
||||
|
||||
/*
|
||||
|
@ -274,11 +195,6 @@ KiInterruptDispatch3 (ULONG vector, PKIRQ_TRAPFRAME Trapframe)
|
|||
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->SegCs : 0);
|
||||
ASSERT (CurrentThread->TrapFrame);
|
||||
|
||||
_enable();
|
||||
|
@ -294,52 +210,192 @@ KiInterruptDispatch3 (ULONG vector, PKIRQ_TRAPFRAME Trapframe)
|
|||
{
|
||||
HalEndSystemInterrupt (old_level, 0);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static VOID
|
||||
KeDumpIrqList(VOID)
|
||||
/* PRIVATE FUNCTIONS *********************************************************/
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
KiGetVectorDispatch(IN ULONG Vector,
|
||||
IN PDISPATCH_INFO Dispatch)
|
||||
{
|
||||
PKINTERRUPT current;
|
||||
PLIST_ENTRY current_entry;
|
||||
LONG i, j;
|
||||
KIRQL oldlvl;
|
||||
BOOLEAN printed;
|
||||
PKINTERRUPT_ROUTINE Handler;
|
||||
ULONG Current;
|
||||
|
||||
for (i=0;i<NR_IRQS;i++)
|
||||
{
|
||||
printed = FALSE;
|
||||
KeRaiseIrql(VECTOR2IRQL(i + IRQ_BASE),&oldlvl);
|
||||
/* Setup the unhandled dispatch */
|
||||
Dispatch->NoDispatch = (PVOID)(((ULONG_PTR)&KiStartUnexpectedRange) +
|
||||
(Vector - PRIMARY_VECTOR_BASE) *
|
||||
KiUnexpectedEntrySize);
|
||||
|
||||
for (j=0; j < KeNumberProcessors; j++)
|
||||
{
|
||||
KiAcquireSpinLock(&IsrTable[i][j].Lock);
|
||||
/* Setup the handlers */
|
||||
Dispatch->InterruptDispatch = KiInterruptDispatch;
|
||||
Dispatch->FloatingDispatch = NULL; // Floating Interrupts are not supported
|
||||
Dispatch->ChainedDispatch = KiChainedDispatch;
|
||||
Dispatch->FlatDispatch = NULL;
|
||||
|
||||
current_entry = IsrTable[i][j].ListHead.Flink;
|
||||
current = CONTAINING_RECORD(current_entry,KINTERRUPT,InterruptListEntry);
|
||||
while (current_entry!=&(IsrTable[i][j].ListHead))
|
||||
/* Get the current handler */
|
||||
Current = ((((PKIPCR)KeGetPcr())->IDT[Vector].ExtendedOffset << 16)
|
||||
& 0xFFFF0000) |
|
||||
(((PKIPCR)KeGetPcr())->IDT[Vector].Offset & 0xFFFF);
|
||||
|
||||
/* Set the interrupt */
|
||||
Dispatch->Interrupt = CONTAINING_RECORD(Current,
|
||||
KINTERRUPT,
|
||||
DispatchCode);
|
||||
|
||||
/* Check what this interrupt is connected to */
|
||||
if ((PKINTERRUPT_ROUTINE)Current == Dispatch->NoDispatch)
|
||||
{
|
||||
if (printed == FALSE)
|
||||
/* Not connected */
|
||||
Dispatch->Type = NoConnect;
|
||||
}
|
||||
else
|
||||
{
|
||||
printed = TRUE;
|
||||
DPRINT("For irq %x:\n",i);
|
||||
/* Get the handler */
|
||||
Handler = Dispatch->Interrupt->DispatchAddress;
|
||||
if (Handler == Dispatch->ChainedDispatch)
|
||||
{
|
||||
/* It's a chained interrupt */
|
||||
Dispatch->Type = ChainConnect;
|
||||
}
|
||||
DPRINT(" Isr %x\n",current);
|
||||
current_entry = current_entry->Flink;
|
||||
current = CONTAINING_RECORD(current_entry,KINTERRUPT,InterruptListEntry);
|
||||
else if ((Handler == Dispatch->InterruptDispatch) ||
|
||||
(Handler == Dispatch->FloatingDispatch))
|
||||
{
|
||||
/* It's unchained */
|
||||
Dispatch->Type = NormalConnect;
|
||||
}
|
||||
KiReleaseSpinLock(&IsrTable[i][j].Lock);
|
||||
else
|
||||
{
|
||||
/* Unknown */
|
||||
Dispatch->Type = UnknownConnect;
|
||||
}
|
||||
KeLowerIrql(oldlvl);
|
||||
}
|
||||
}
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
KiConnectVectorToInterrupt(IN PKINTERRUPT Interrupt,
|
||||
IN CONNECT_TYPE Type)
|
||||
{
|
||||
DISPATCH_INFO Dispatch;
|
||||
PKINTERRUPT_ROUTINE Handler;
|
||||
PULONG Patch = &Interrupt->DispatchCode[0];
|
||||
|
||||
/* Get vector data */
|
||||
KiGetVectorDispatch(Interrupt->Vector, &Dispatch);
|
||||
|
||||
/* Check if we're only disconnecting */
|
||||
if (Type == NoConnect)
|
||||
{
|
||||
/* Set the handler to NoDispatch */
|
||||
Handler = Dispatch.NoDispatch;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Get the right handler */
|
||||
Handler = (Type == NormalConnect) ?
|
||||
Dispatch.InterruptDispatch:
|
||||
Dispatch.ChainedDispatch;
|
||||
ASSERT(Interrupt->FloatingSave == FALSE);
|
||||
|
||||
/* Set the handler */
|
||||
Interrupt->DispatchAddress = Handler;
|
||||
|
||||
/* Jump to the last 4 bytes */
|
||||
Patch = (PULONG)((ULONG_PTR)Patch +
|
||||
((ULONG_PTR)&KiInterruptTemplateDispatch -
|
||||
(ULONG_PTR)KiInterruptTemplate) - 4);
|
||||
|
||||
/* Apply the patch */
|
||||
*Patch = (ULONG)((ULONG_PTR)Handler - ((ULONG_PTR)Patch + 4));
|
||||
|
||||
/* Now set the final handler address */
|
||||
ASSERT(Dispatch.FlatDispatch == NULL);
|
||||
Handler = (PVOID)&Interrupt->DispatchCode;
|
||||
}
|
||||
|
||||
/* Set the pointer in the IDT */
|
||||
((PKIPCR)KeGetPcr())->IDT[Interrupt->Vector].ExtendedOffset =
|
||||
(USHORT)(((ULONG_PTR)Handler >> 16) & 0xFFFF);
|
||||
((PKIPCR)KeGetPcr())->IDT[Interrupt->Vector].Offset =
|
||||
(USHORT)PtrToUlong(Handler);
|
||||
}
|
||||
|
||||
/* PUBLIC FUNCTIONS **********************************************************/
|
||||
|
||||
/*
|
||||
* @implemented
|
||||
*/
|
||||
VOID
|
||||
NTAPI
|
||||
KeInitializeInterrupt(IN PKINTERRUPT Interrupt,
|
||||
IN PKSERVICE_ROUTINE ServiceRoutine,
|
||||
IN PVOID ServiceContext,
|
||||
IN PKSPIN_LOCK SpinLock,
|
||||
IN ULONG Vector,
|
||||
IN KIRQL Irql,
|
||||
IN KIRQL SynchronizeIrql,
|
||||
IN KINTERRUPT_MODE InterruptMode,
|
||||
IN BOOLEAN ShareVector,
|
||||
IN CHAR ProcessorNumber,
|
||||
IN BOOLEAN FloatingSave)
|
||||
{
|
||||
ULONG i;
|
||||
PULONG DispatchCode = &Interrupt->DispatchCode[0], Patch = DispatchCode;
|
||||
|
||||
/* Set the Interrupt Header */
|
||||
Interrupt->Type = InterruptObject;
|
||||
Interrupt->Size = sizeof(KINTERRUPT);
|
||||
|
||||
/* Check if we got a spinlock */
|
||||
if (SpinLock)
|
||||
{
|
||||
/* Use the spinlock given to us */
|
||||
Interrupt->ActualLock = SpinLock;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* This means we'll be using 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;
|
||||
|
||||
/* Loop the template in memory */
|
||||
for (i = 0; i < KINTERRUPT_DISPATCH_CODES; i++)
|
||||
{
|
||||
/* Copy the dispatch code */
|
||||
*DispatchCode++ = KiInterruptTemplate[i];
|
||||
}
|
||||
|
||||
/* Jump to the last 4 bytes */
|
||||
Patch = (PULONG)((ULONG_PTR)Patch +
|
||||
((ULONG_PTR)&KiInterruptTemplateObject -
|
||||
(ULONG_PTR)KiInterruptTemplate) - 4);
|
||||
|
||||
/* Apply the patch */
|
||||
*Patch = PtrToUlong(Interrupt);
|
||||
|
||||
/* Disconnect it at first */
|
||||
Interrupt->Connected = FALSE;
|
||||
}
|
||||
|
||||
/*
|
||||
* @implemented
|
||||
*/
|
||||
BOOLEAN
|
||||
STDCALL
|
||||
KeConnectInterrupt(PKINTERRUPT InterruptObject)
|
||||
NTAPI
|
||||
KeConnectInterrupt(IN PKINTERRUPT InterruptObject)
|
||||
{
|
||||
KIRQL oldlvl,synch_oldlvl;
|
||||
PKINTERRUPT ListHead;
|
||||
|
@ -360,7 +416,7 @@ KeConnectInterrupt(PKINTERRUPT InterruptObject)
|
|||
|
||||
KeSetSystemAffinityThread(1 << InterruptObject->Number);
|
||||
|
||||
CurrentIsr = &IsrTable[Vector][(ULONG)InterruptObject->Number];
|
||||
CurrentIsr = &IsrTable[Vector];
|
||||
|
||||
KeRaiseIrql(VECTOR2IRQL(Vector + IRQ_BASE),&oldlvl);
|
||||
KiAcquireSpinLock(&CurrentIsr->Lock);
|
||||
|
@ -382,13 +438,10 @@ KeConnectInterrupt(PKINTERRUPT InterruptObject)
|
|||
|
||||
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;
|
||||
|
@ -400,8 +453,6 @@ KeConnectInterrupt(PKINTERRUPT InterruptObject)
|
|||
KiReleaseSpinLock(&CurrentIsr->Lock);
|
||||
KeLowerIrql(oldlvl);
|
||||
|
||||
KeDumpIrqList();
|
||||
|
||||
KeRevertToUserAffinityThread();
|
||||
|
||||
return Result;
|
||||
|
@ -409,127 +460,84 @@ KeConnectInterrupt(PKINTERRUPT InterruptObject)
|
|||
|
||||
/*
|
||||
* @implemented
|
||||
*
|
||||
* FUNCTION: Releases a drivers isr
|
||||
* ARGUMENTS:
|
||||
* InterruptObject = isr to release
|
||||
*/
|
||||
BOOLEAN
|
||||
STDCALL
|
||||
KeDisconnectInterrupt(PKINTERRUPT InterruptObject)
|
||||
NTAPI
|
||||
KeDisconnectInterrupt(IN PKINTERRUPT Interrupt)
|
||||
{
|
||||
KIRQL oldlvl,synch_oldlvl;
|
||||
PISR_TABLE CurrentIsr;
|
||||
KIRQL OldIrql, Irql;
|
||||
ULONG Vector;
|
||||
DISPATCH_INFO Dispatch;
|
||||
PKINTERRUPT NextInterrupt;
|
||||
BOOLEAN State;
|
||||
|
||||
DPRINT1("KeDisconnectInterrupt\n");
|
||||
ASSERT (InterruptObject->Number < KeNumberProcessors);
|
||||
|
||||
/* Set the affinity */
|
||||
KeSetSystemAffinityThread(1 << InterruptObject->Number);
|
||||
KeSetSystemAffinityThread(1 << Interrupt->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);
|
||||
/* Lock the dispatcher */
|
||||
OldIrql = KiAcquireDispatcherLock();
|
||||
|
||||
/* Check if it's actually connected */
|
||||
if ((State = InterruptObject->Connected))
|
||||
State = Interrupt->Connected;
|
||||
if (State)
|
||||
{
|
||||
/* Lock the Interrupt */
|
||||
synch_oldlvl = KeAcquireInterruptSpinLock(InterruptObject);
|
||||
/* Get the vector and IRQL */
|
||||
Irql = Interrupt->Irql;
|
||||
Vector = Interrupt->Vector;
|
||||
|
||||
/* Remove this one, and check if all are gone */
|
||||
RemoveEntryList(&InterruptObject->InterruptListEntry);
|
||||
if (IsListEmpty(&CurrentIsr->ListHead))
|
||||
/* Get vector dispatch data */
|
||||
KiGetVectorDispatch(Vector, &Dispatch);
|
||||
|
||||
/* Check if it was chained */
|
||||
if (Dispatch.Type == ChainConnect)
|
||||
{
|
||||
/* Completely Disable the Interrupt */
|
||||
HalDisableSystemInterrupt(InterruptObject->Vector, InterruptObject->Irql);
|
||||
/* Check if the top-level interrupt is being removed */
|
||||
ASSERT(Irql <= SYNCH_LEVEL);
|
||||
if (Interrupt == Dispatch.Interrupt)
|
||||
{
|
||||
/* Get the next one */
|
||||
Dispatch.Interrupt = CONTAINING_RECORD(Dispatch.Interrupt->
|
||||
InterruptListEntry.Flink,
|
||||
KINTERRUPT,
|
||||
InterruptListEntry);
|
||||
|
||||
/* Reconnect it */
|
||||
KiConnectVectorToInterrupt(Dispatch.Interrupt, ChainConnect);
|
||||
}
|
||||
|
||||
/* Disconnect it */
|
||||
InterruptObject->Connected = FALSE;
|
||||
/* Remove it */
|
||||
RemoveEntryList(&Interrupt->InterruptListEntry);
|
||||
|
||||
/* Release the interrupt lock */
|
||||
KeReleaseInterruptSpinLock(InterruptObject, synch_oldlvl);
|
||||
}
|
||||
/* Release the table spinlock */
|
||||
KiReleaseSpinLock(&CurrentIsr->Lock);
|
||||
KeLowerIrql(oldlvl);
|
||||
/* Get the next one */
|
||||
NextInterrupt = CONTAINING_RECORD(Dispatch.Interrupt->
|
||||
InterruptListEntry.Flink,
|
||||
KINTERRUPT,
|
||||
InterruptListEntry);
|
||||
|
||||
/* 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)
|
||||
/* Check if this is the only one left */
|
||||
if (Dispatch.Interrupt == NextInterrupt)
|
||||
{
|
||||
Interrupt->ActualLock = SpinLock;
|
||||
/* Connect it in non-chained mode */
|
||||
KiConnectVectorToInterrupt(Dispatch.Interrupt, NormalConnect);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* This means we'll be usin the built-in one */
|
||||
KeInitializeSpinLock(&Interrupt->SpinLock);
|
||||
Interrupt->ActualLock = &Interrupt->SpinLock;
|
||||
/* Only one left, disable and remove it */
|
||||
HalDisableSystemInterrupt(Interrupt->Vector, Irql);
|
||||
KiConnectVectorToInterrupt(Interrupt, NoConnect);
|
||||
}
|
||||
|
||||
/* 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 */
|
||||
/* Disconnect it */
|
||||
Interrupt->Connected = FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
VOID KePrintInterruptStatistic(VOID)
|
||||
{
|
||||
LONG i, j;
|
||||
/* Unlock the dispatcher and revert affinity */
|
||||
KiReleaseDispatcherLock(OldIrql);
|
||||
KeRevertToUserAffinityThread();
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
/* Return to caller */
|
||||
return State;
|
||||
}
|
||||
|
||||
/* EOF */
|
||||
|
|
Loading…
Reference in a new issue