windows-nt/Source/XPSP1/NT/base/ntos/ke/ia64/intsupc.c

200 lines
2.9 KiB
C
Raw Permalink Normal View History

2020-09-26 03:20:57 -05:00
/*++
Copyright (c) 1993 Microsoft Corporation
Copyright (c) 1998 Intel Corporation
Module Name:
intsupc.c
Abstract:
This module implements ruotines for interrupt support.
Author:
Bernard Lint 5-May-1998
Environment:
Kernel mode only.
Revision History:
--*/
#include "ki.h"
VOID
KiLowerIrqlSpecial(KIRQL);
VOID
KiDispatchSoftwareInterrupt (
KIRQL Irql
)
/*++
Routine Description:
Dispatch pending software interrupt
Arguments:
Irql (a0) - Software interrupt to dispatch
Return Value:
None.
Notes:
Interrupts disabled on entry/return.
The function is only called by KiCheckForSoftwareInterrupt that passes an
Irql value of APC_LEVEL or DISPATCH_LEVEL.
--*/
{
PKPRCB Prcb = KeGetCurrentPrcb();
KiLowerIrqlSpecial(Irql); // set IRQL
if (Irql == APC_LEVEL) {
PCR->ApcInterrupt = 0;
_enable();
//
// Dispatch APC Interrupt via direct call to KiDeliverApc
//
KiDeliverApc(KernelMode,NULL,NULL);
_disable();
} else {
PCR->DispatchInterrupt = 0;
_enable();
//
// Dispatch DPC Interrupt
//
KiDispatchInterrupt();
_disable();
}
}
VOID
KiCheckForSoftwareInterrupt (
KIRQL RequestIrql
)
/*++
Routine Description:
Check for and dispatch pending software interrupts
Arguments:
Irql (a0) - New, lower IRQL
Return Value:
None.
Notes:
Caller must check IRQL has dropped below s/w IRQL level
--*/
{
BOOLEAN InterruptState;
InterruptState = KeDisableInterrupts();
if (RequestIrql == APC_LEVEL) {
//
// Dispatch only DPC requests
//
while (PCR->DispatchInterrupt) {
KiDispatchSoftwareInterrupt(DISPATCH_LEVEL);
}
} else {
//
// Dispatch either APC or DPC
//
while (PCR->SoftwareInterruptPending) {
KIRQL Irql;
if (PCR->DispatchInterrupt) {
Irql = DISPATCH_LEVEL;
} else {
Irql = APC_LEVEL;
}
KiDispatchSoftwareInterrupt(Irql);
}
}
//
// Lower IRQL to the requested level, restore interrupts and
// return.
//
KiLowerIrqlSpecial(RequestIrql);
KeEnableInterrupts(InterruptState);
}
VOID
KiRequestSoftwareInterrupt (
KIRQL RequestIrql
)
/*++
Routine Description:
This function requests a software interrupt at the specified IRQL
level.
Arguments:
RequestIrql (a0) - Supplies the request IRQL value.
Return Value:
None.
--*/
{
KIRQL Irql;
#if DEBUG
if ((RequestIrql < APC_LEVEL) || (RequestIrql > DISPATCH_LEVEL))
KeBugCheckEx(INVALID_SOFTWARE_INTERRUPT, RequestIrql, 0, 0, 0);
#endif
((PUCHAR)&PCR->SoftwareInterruptPending)[RequestIrql-APC_LEVEL] = 1;
Irql = KeGetCurrentIrql();
if (Irql < RequestIrql) {
KeLowerIrql (Irql);
}
}