/*++ 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); } }