irq.c
来自「一个类似windows」· C语言 代码 · 共 586 行 · 第 1/2 页
C
586 行
KeIRQTrapFrameToTrapFrame(Trapframe, &KernelTrapFrame);
KeUpdateSystemTime(&KernelTrapFrame, old_level);
}
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 */
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?