200 lines
2.9 KiB
C
200 lines
2.9 KiB
C
/*++
|
||
|
||
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);
|
||
}
|
||
}
|
||
|