/*++ 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" __inline VOID KiLowerIrqlSpecial(KIRQL NewIrql) { __setReg( CV_IA64_SaTPR, (NewIrql << TPR_IRQL_SHIFT)); KeGetPcr()->CurrentIrql = NewIrql; } 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. --*/ { 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); } } #undef KeRaiseIrql VOID KeRaiseIrql ( IN KIRQL NewIrql, OUT PKIRQL OldIrql ) /*++ Routine Description: This function raises the current IRQL to the specified value and returns the previous IRQL. Arguments: NewIrql - Supplies the new IRQL value. OldIrql - Supplies a pointer to the location where the old IRQL is stored. Return Value: None. --*/ { *OldIrql = KfRaiseIrql(NewIrql); }