From e611b132f9b8abe35b362e5870b74bce94a1e58e Mon Sep 17 00:00:00 2001 From: Adam Date: Sat, 16 May 2020 20:51:50 -0700 Subject: initial commit --- private/ntos/ndis/ndis40/timerm.c | 1080 +++++++++++++++++++++++++++++++++++++ 1 file changed, 1080 insertions(+) create mode 100644 private/ntos/ndis/ndis40/timerm.c (limited to 'private/ntos/ndis/ndis40/timerm.c') diff --git a/private/ntos/ndis/ndis40/timerm.c b/private/ntos/ndis/ndis40/timerm.c new file mode 100644 index 000000000..20ff1b7e6 --- /dev/null +++ b/private/ntos/ndis/ndis40/timerm.c @@ -0,0 +1,1080 @@ +/*++ + +Copyright (c) 1990-1995 Microsoft Corporation + +Module Name: + + timerm.c + +Abstract: + + NDIS wrapper functions for miniport isr/timer + +Author: + + Sean Selitrennikoff (SeanSe) 05-Oct-93 + +Environment: + + Kernel mode, FSD + +Revision History: + + Jameel Hyder (JameelH) Re-organization 01-Jun-95 +--*/ + +#include +#pragma hdrstop + +// +// Define the module number for debug code. +// +#define MODULE_NUMBER MODULE_TIMERM + +// +// Timers +// +VOID +ndisMTimerDpc( + IN PKDPC Dpc, + IN PVOID Context, + IN PVOID SystemContext1, + IN PVOID SystemContext2 + ) +/*++ + +Routine Description: + + This function services all mini-port timer interrupts. It then calls the + appropriate function that mini-port consumers have registered in the + call to NdisMInitializeTimer. + +Arguments: + + Dpc - Not used. + + Context - A pointer to the NDIS_MINIPORT_TIMER which is bound to this DPC. + + SystemContext1,2 - not used. + +Return Value: + + None. + +--*/ +{ + PNDIS_MINIPORT_TIMER MiniportTimer = (PNDIS_MINIPORT_TIMER)(Context); + PNDIS_TIMER_FUNCTION TimerFunction; + PNDIS_MINIPORT_BLOCK Miniport = MiniportTimer->Miniport; + BOOLEAN LocalLock; + + UNREFERENCED_PARAMETER(Dpc); + UNREFERENCED_PARAMETER(SystemContext1); + UNREFERENCED_PARAMETER(SystemContext2); + + NDIS_ACQUIRE_MINIPORT_SPIN_LOCK_DPC(Miniport); + + do + { + // + // Attempt to acquire the local lock. + // + LOCK_MINIPORT(Miniport, LocalLock); + if (!LocalLock || MINIPORT_TEST_FLAG(Miniport, fMINIPORT_IN_INITIALIZE)) + { + // + // Unlock the miniport in the case of the in-initialize flag. + // + UNLOCK_MINIPORT(Miniport, LocalLock); + + // + // Queue a work item for the timer. + // + NDISM_QUEUE_NEW_WORK_ITEM(Miniport, + NdisWorkItemTimer, + &MiniportTimer->Dpc, + NULL); + + break; + } + + // + // Call Miniport timer function + // + TimerFunction = MiniportTimer->MiniportTimerFunction; + + (*TimerFunction)(NULL, MiniportTimer->MiniportTimerContext, NULL, NULL); + +#if _SEND_PRIORITY + // + // If we are not reseting and not halting then give priority to sends + // at this point. + // + if (!MINIPORT_TEST_FLAG(Miniport, fMINIPORT_RESET_REQUESTED) && + !MINIPORT_TEST_FLAG(Miniport, fMINIPORT_RESET_IN_PROGRESS) && + !MINIPORT_TEST_FLAG(Miniport, fMINIPORT_HALTING)) + { + if (MINIPORT_TEST_FLAG(Miniport, fMINIPORT_FULL_DUPLEX)) + { + ndisMProcessDeferredFullDuplexPrioritySends(Miniport); + } + else + { + ndisMProcessDeferredPrioritySends(Miniport); + } + } + else +#endif + { + NDISM_PROCESS_DEFERRED(Miniport); + } + + UNLOCK_MINIPORT(Miniport, LocalLock); + + } while (FALSE); + + NDIS_RELEASE_MINIPORT_SPIN_LOCK_DPC(Miniport); +} + + +VOID +NdisMInitializeTimer( + IN OUT PNDIS_MINIPORT_TIMER MiniportTimer, + IN NDIS_HANDLE MiniportAdapterHandle, + IN PNDIS_TIMER_FUNCTION TimerFunction, + IN PVOID FunctionContext + ) +/*++ + +Routine Description: + + Sets up an Miniport Timer object, initializing the DPC in the timer to + the function and context. + +Arguments: + + MiniportTimer - the timer object. + MiniportAdapterHandle - pointer to the mini-port block; + TimerFunction - Routine to start. + FunctionContext - Context of TimerFunction. + +Return Value: + + None. + +--*/ +{ + INITIALIZE_TIMER(&(MiniportTimer->Timer)); + + MiniportTimer->Miniport = (PNDIS_MINIPORT_BLOCK)MiniportAdapterHandle; + MiniportTimer->MiniportTimerFunction = TimerFunction; + MiniportTimer->MiniportTimerContext = FunctionContext; + + // + // Initialize our dpc. If Dpc was previously initialized, this will + // reinitialize it. + // + INITIALIZE_DPC(&MiniportTimer->Dpc, + (MiniportTimer->Miniport->Flags & fMINIPORT_IS_CO) ? + (PKDEFERRED_ROUTINE)ndisMCoTimerDpc : + (PKDEFERRED_ROUTINE)ndisMTimerDpc, + (PVOID)MiniportTimer); + + SET_PROCESSOR_DPC(&MiniportTimer->Dpc, + ndisValidProcessors[ndisCurrentProcessor]); +} + + +VOID +NdisMCancelTimer( + IN PNDIS_MINIPORT_TIMER Timer, + OUT PBOOLEAN TimerCancelled + ) +/*++ + +Routine Description: + + Cancels a timer. + +Arguments: + + Timer - The timer to cancel. + + TimerCancelled - TRUE if the timer was canceled, else FALSE. + +Return Value: + + None + +--*/ +{ + *TimerCancelled = CANCEL_TIMER(&((((PNDIS_TIMER)(Timer))->Timer))); +} + + +NDIS_STATUS +NdisMRegisterInterrupt( + OUT PNDIS_MINIPORT_INTERRUPT Interrupt, + IN NDIS_HANDLE MiniportAdapterHandle, + IN UINT InterruptVector, + IN UINT InterruptLevel, + IN BOOLEAN RequestIsr, + IN BOOLEAN SharedInterrupt, + IN NDIS_INTERRUPT_MODE InterruptMode + ) +{ + NDIS_STATUS Status; + + NdisInitializeInterrupt(&Status, + (PNDIS_INTERRUPT)Interrupt, + MiniportAdapterHandle, + NULL, + NULL, + (PNDIS_DEFERRED_PROCESSING)RequestIsr, + InterruptVector, + InterruptLevel, + SharedInterrupt, + InterruptMode); + return Status; +} + + +VOID +NdisMDeregisterInterrupt( + IN PNDIS_MINIPORT_INTERRUPT Interrupt + ) +{ + NdisRemoveInterrupt((PNDIS_INTERRUPT)Interrupt); +} + + +BOOLEAN +NdisMSynchronizeWithInterrupt( + IN PNDIS_MINIPORT_INTERRUPT Interrupt, + IN PVOID SynchronizeFunction, + IN PVOID SynchronizeContext + ) +{ + return (SYNC_WITH_ISR((Interrupt)->InterruptObject, + SynchronizeFunction, + SynchronizeContext)); +} + + + +VOID +ndisMWakeUpDpc( + IN PKDPC Dpc, + IN PVOID Context, + IN PVOID SystemContext1, + IN PVOID SystemContext2 + ) +/*++ + +Routine Description: + + This function services all mini-port. It checks to see if a mini-port is + ever stalled. + +Arguments: + + Dpc - Not used. + + Context - A pointer to the NDIS_TIMER which is bound to this DPC. + + SystemContext1,2 - not used. + +Return Value: + + None. + +--*/ +{ + PNDIS_MINIPORT_BLOCK Miniport = (PNDIS_MINIPORT_BLOCK)(Context); + BOOLEAN Hung = FALSE; + BOOLEAN LocalLock; + PNDIS_MINIPORT_WORK_ITEM WorkItem; + PSINGLE_LIST_ENTRY Link; + + UNREFERENCED_PARAMETER(Dpc); + UNREFERENCED_PARAMETER(SystemContext1); + UNREFERENCED_PARAMETER(SystemContext2); + + NDIS_ACQUIRE_MINIPORT_SPIN_LOCK_DPC(Miniport); + + do + { + // + // If the miniport is halting then do nothing. + // + if (MINIPORT_TEST_FLAG(Miniport, fMINIPORT_HALTING)) + { + break; + } + + // + // Does some other DPC have the miniport lock? + // + LOCK_MINIPORT(Miniport, LocalLock); + if (!LocalLock || + MINIPORT_TEST_FLAG(Miniport, fMINIPORT_RESET_IN_PROGRESS) || + MINIPORT_TEST_FLAG(Miniport, fMINIPORT_RESET_REQUESTED)) + { + // + // Release the local lock in case we are here due to + // a reset in progress. + // + UNLOCK_MINIPORT(Miniport, LocalLock); + + // + // A DPC or timer is already running, assume that + // means things are fine. + // + break; + } + + // + // Call Miniport stall checker. + // + if (Miniport->DriverHandle->MiniportCharacteristics.CheckForHangHandler != NULL) + { + Hung = (Miniport->DriverHandle->MiniportCharacteristics.CheckForHangHandler)( + Miniport->MiniportAdapterContext); + } + + // + // Check the internal wrapper states for the miniport and + // see if we think the miniport should be reset. + // + if (!Hung) do + { + // + // Should we check the request queue? + // + if (!MINIPORT_TEST_FLAG(Miniport, fMINIPORT_IGNORE_REQUEST_QUEUE)) + { + // + // Did a request pend to long? + // + if (Miniport->MiniportRequest != NULL) + { + if (MINIPORT_TEST_FLAG(Miniport, fMINIPORT_REQUEST_TIMEOUT)) + { + Hung = TRUE; + break; + } + else + { + MINIPORT_SET_FLAG(Miniport, fMINIPORT_REQUEST_TIMEOUT); + } + } + } + + // + // Should we ignore the packet queue's? + // + if (!MINIPORT_TEST_FLAG(Miniport, fMINIPORT_IGNORE_PACKET_QUEUE)) + { + // + // Grab the send lock. + // + if (MINIPORT_TEST_FLAG(Miniport, fMINIPORT_FULL_DUPLEX)) + { + NDIS_ACQUIRE_SEND_SPIN_LOCK_DPC(Miniport); + } + + // + // Does the miniport have possession of any packets? + // + if (Miniport->FirstPacket != NULL) + { + // + // Has the packet timed out? + // + if (MINIPORT_TEST_PACKET_FLAG(Miniport->FirstPacket, fPACKET_HAS_TIMED_OUT)) + { + // + // Reset the miniport. + // + Hung = TRUE; + } + else + { + // + // Set the packet flag and wait to see if it is still + // there next time in. + // + MINIPORT_SET_PACKET_FLAG(Miniport->FirstPacket, fPACKET_HAS_TIMED_OUT); + } + } + + // + // Release the send lock. + // + if (MINIPORT_TEST_FLAG(Miniport, fMINIPORT_FULL_DUPLEX)) + { + NDIS_RELEASE_SEND_SPIN_LOCK_DPC(Miniport); + } + + // + // If we are hung then we don't need to check for token ring + // errors. + // + if (Hung) + { + break; + } + } + + // + // Are we ignoring token ring errors? + // + if (!MINIPORT_TEST_FLAG(Miniport, fMINIPORT_IGNORE_TOKEN_RING_ERRORS)) + { + // + // Token Ring reset... + // + if (Miniport->TrResetRing == 1) + { + Hung = TRUE; + break; + } + else if (Miniport->TrResetRing > 1) + { + Miniport->TrResetRing--; + } + } + } while (FALSE); + + // + // If the miniport is hung then queue a workitem to reset it. + // + if (Hung) + { + // + // Queue a reset requested workitem. + // + NDISM_QUEUE_WORK_ITEM(Miniport, NdisWorkItemResetRequested, Miniport, NULL); + } + + // + // Process any changes that have occurred. + // + NDISM_PROCESS_DEFERRED(Miniport); + + UNLOCK_MINIPORT(Miniport, LocalLock); + + } while (FALSE); + + NDIS_RELEASE_MINIPORT_SPIN_LOCK_DPC(Miniport); +} + + +// +// Interrupt stuff +// + + +BOOLEAN +ndisMIsr( + IN PKINTERRUPT KInterrupt, + IN PVOID Context + ) +/*++ + +Routine Description: + + Handles ALL Miniport interrupts, calling the appropriate Miniport ISR and DPC + depending on the context. + +Arguments: + + Interrupt - Interrupt object for the Mac. + + Context - Really a pointer to the interrupt. + +Return Value: + + None. + +--*/ +{ + // + // Get adapter from context. + // + + PNDIS_MINIPORT_INTERRUPT Interrupt = (PNDIS_MINIPORT_INTERRUPT)Context; + PNDIS_MINIPORT_BLOCK Miniport = Interrupt->Miniport; + + BOOLEAN InterruptRecognized; + BOOLEAN QueueDpc; + + do + { + if (MINIPORT_TEST_FLAG(Miniport, fMINIPORT_NORMAL_INTERRUPTS)) + { + // + // Call to disable the interrupt + // + MINIPORT_DISABLE_INTERRUPT(Miniport); + + InterruptRecognized = TRUE; + + goto queue_dpc; + + break; + } + + if (!MINIPORT_TEST_FLAG(Miniport, fMINIPORT_HALTING)) + { + // + // Call MiniportIsr + // + + Interrupt->MiniportIsr( + &InterruptRecognized, + &QueueDpc, + Miniport->MiniportAdapterContext); + + if (QueueDpc) + { +queue_dpc: + Increment((PLONG)&Interrupt->DpcCount, &Interrupt->DpcCountLock); + + if (QUEUE_DPC(&Interrupt->InterruptDpc)) + { + break; + } + + // + // The DPC was already queued, so we have an extra reference (we + // do it this way to ensure that the reference is added *before* + // the DPC is queued). + // + + Decrement((PLONG)&Interrupt->DpcCount, &Interrupt->DpcCountLock); + + if (MINIPORT_TEST_FLAG(Miniport, fMINIPORT_HALTING) && + (Interrupt->DpcCount == 0)) + { + // + // We need to queue a DPC to set the event because we + // can't do it from the ISR. We know that the interrupt + // DPC won't fire because the refcount is 0, so we reuse it. + // + + INITIALIZE_DPC(&Interrupt->InterruptDpc, + ndisLastCountRemovedFunction, + (PVOID)&Interrupt->DpcsCompletedEvent); + + // + // When ndisLastCountRemovedFunction runs it will set + // the event. + // + + QUEUE_DPC(&Interrupt->InterruptDpc); + } + } + + break; + } + + if (!Interrupt->SharedInterrupt && + !Interrupt->IsrRequested && + !MINIPORT_TEST_FLAG(Miniport, fMINIPORT_IN_INITIALIZE)) + { + // + // Call to disable the interrupt + // + ASSERT(Miniport->DisableInterruptHandler != NULL); + + MINIPORT_DISABLE_INTERRUPT(Miniport); + InterruptRecognized = TRUE; + + break; + } + + // + // Call MiniportIsr, but don't queue a DPC. + // + Interrupt->MiniportIsr( + &InterruptRecognized, + &QueueDpc, + Miniport->MiniportAdapterContext); + + } while (FALSE); + + return(InterruptRecognized); +} + + +VOID +ndisMDpc( + IN PVOID SystemSpecific1, + IN PVOID InterruptContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3 + ) +/*++ + +Routine Description: + + Handles ALL Miniport interrupt DPCs, calling the appropriate Miniport DPC + depending on the context. + +Arguments: + + Interrupt - Interrupt object for the Mac. + + Context - Really a pointer to the Interrupt. + +Return Value: + + None. + +--*/ +{ + // + // Get adapter from context. + // + + PNDIS_MINIPORT_INTERRUPT Interrupt = (PNDIS_MINIPORT_INTERRUPT)(InterruptContext); + PNDIS_MINIPORT_BLOCK Miniport = Interrupt->Miniport; + BOOLEAN LocalLock; + + W_HANDLE_INTERRUPT_HANDLER MiniportDpc = Interrupt->MiniportDpc; + + NDIS_ACQUIRE_MINIPORT_SPIN_LOCK_DPC(Miniport); + + do + { + if (MINIPORT_TEST_FLAG(Miniport, fMINIPORT_HALTING)) + { + Decrement((PLONG)&Interrupt->DpcCount, &Interrupt->DpcCountLock); + + if (Interrupt->DpcCount==0) + { + SET_EVENT(&Interrupt->DpcsCompletedEvent); + } + + break; + } + + LOCK_MINIPORT(Miniport, LocalLock); + if (!LocalLock) + { + // + // A DPC is already running, queue this for later. + // + NDISM_QUEUE_WORK_ITEM(Miniport, NdisWorkItemDpc, &Miniport->Dpc, NULL); + Decrement((PLONG)&Interrupt->DpcCount, &Interrupt->DpcCountLock); + + break; + } + + // + // Call MiniportDpc + // + (*MiniportDpc)(Miniport->MiniportAdapterContext); + + Decrement((PLONG)&Interrupt->DpcCount, &Interrupt->DpcCountLock); + + if (!MINIPORT_TEST_FLAG(Miniport, fMINIPORT_HALTING)) + { + // + // Enable interrupts + // + + MINIPORT_SYNC_ENABLE_INTERRUPT(Miniport); + +#if _SEND_PRIORITY + // + // If we are not reseting and not halting then give priority to sends + // at this point. + // + if (!MINIPORT_TEST_FLAG(Miniport, fMINIPORT_RESET_REQUESTED) && + !MINIPORT_TEST_FLAG(Miniport, fMINIPORT_RESET_IN_PROGRESS) && + !MINIPORT_TEST_FLAG(Miniport, fMINIPORT_HALTING)) + { + if (MINIPORT_TEST_FLAG(Miniport, fMINIPORT_FULL_DUPLEX)) + { + ndisMProcessDeferredFullDuplexPrioritySends(Miniport); + } + else + { + ndisMProcessDeferredPrioritySends(Miniport); + } + } + else +#endif + { + NDISM_PROCESS_DEFERRED(Miniport); + } + } + else + { + if (Interrupt->DpcCount == 0) + { + SET_EVENT(&Interrupt->DpcsCompletedEvent); + } + } + + UNLOCK_MINIPORT(Miniport, LocalLock); + + } while (FALSE); + + NDIS_RELEASE_MINIPORT_SPIN_LOCK_DPC(Miniport); +} + + +VOID +ndisMDpcTimer( + IN PVOID SystemSpecific1, + IN PVOID InterruptContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3 + ) +/*++ + +Routine Description: + + Handles a deferred interrupt dpc. + +Arguments: + + Context - Really a pointer to the Miniport block. + +Return Value: + + None. + +--*/ +{ + // + // Get adapter from context. + // + + PNDIS_MINIPORT_BLOCK Miniport = (PNDIS_MINIPORT_BLOCK)(InterruptContext); + BOOLEAN LocalLock; + + W_HANDLE_INTERRUPT_HANDLER MiniportDpc = Miniport->HandleInterruptHandler; + + NDIS_ACQUIRE_MINIPORT_SPIN_LOCK_DPC(Miniport); + + do + { + if (MINIPORT_TEST_FLAG(Miniport, fMINIPORT_IN_INITIALIZE)) + { + break; + } + + LOCK_MINIPORT(Miniport, LocalLock); + if (!LocalLock) + { + // + // A DPC is already running, queue this for later. + // + NDISM_QUEUE_WORK_ITEM(Miniport, NdisWorkItemDpc, &Miniport->Dpc, NULL); + break; + } + + // + // Disable the interrupts. + // + MINIPORT_SYNC_DISABLE_INTERRUPT(Miniport); + + // + // Call MiniportDpc + // + if (MiniportDpc != NULL) + { + (*MiniportDpc)(Miniport->MiniportAdapterContext); + } + + // + // Enable interrupts + // + MINIPORT_SYNC_ENABLE_INTERRUPT(Miniport); + +#if _SEND_PRIORITY + // + // If we are not reseting and not halting then give priority to sends + // at this point. + // + if (!MINIPORT_TEST_FLAG(Miniport, fMINIPORT_RESET_REQUESTED) && + !MINIPORT_TEST_FLAG(Miniport, fMINIPORT_RESET_IN_PROGRESS) && + !MINIPORT_TEST_FLAG(Miniport, fMINIPORT_HALTING)) + { + if (MINIPORT_TEST_FLAG(Miniport, fMINIPORT_FULL_DUPLEX)) + { + ndisMProcessDeferredFullDuplexPrioritySends(Miniport); + } + else + { + ndisMProcessDeferredPrioritySends(Miniport); + } + } + else +#endif + { + NDISM_PROCESS_DEFERRED(Miniport); + } + + UNLOCK_MINIPORT(Miniport, LocalLock); + } while (FALSE); + + NDIS_RELEASE_MINIPORT_SPIN_LOCK_DPC(Miniport); +} + + +VOID +ndisMDeferredTimerDpc( + IN PKDPC Dpc, + IN PVOID Context, + IN PVOID SystemContext1, + IN PVOID SystemContext2 + ) + +/*++ + +Routine Description: + + This is a DPC routine that is queue'd by some of the [full-duplex] routines + in order to get ndisMProcessDeferred[FullDuplex] to run outside of their + context. + +Arguments: + + + +Return Value: + + None. + +--*/ +{ + PNDIS_MINIPORT_BLOCK Miniport = Context; + BOOLEAN LocalLock; + + UNREFERENCED_PARAMETER(Dpc); + UNREFERENCED_PARAMETER(SystemContext1); + UNREFERENCED_PARAMETER(SystemContext2); + + NDIS_ACQUIRE_MINIPORT_SPIN_LOCK_DPC(Miniport); + + LOCK_MINIPORT(Miniport, LocalLock); + if (!LocalLock) + { + // + // Queue this to run later. + // + NDISM_DEFER_PROCESS_DEFERRED(Miniport); + + NDIS_RELEASE_MINIPORT_SPIN_LOCK_DPC(Miniport); + + return; + } + +#if _SEND_PRIORITY + // + // If we are not reseting and not halting then give priority to sends + // at this point. + // + if (!MINIPORT_TEST_FLAG(Miniport, fMINIPORT_RESET_REQUESTED) && + !MINIPORT_TEST_FLAG(Miniport, fMINIPORT_RESET_IN_PROGRESS) && + !MINIPORT_TEST_FLAG(Miniport, fMINIPORT_HALTING)) + { + if (MINIPORT_TEST_FLAG(Miniport, fMINIPORT_FULL_DUPLEX)) + { + ndisMProcessDeferredFullDuplexPrioritySends(Miniport); + } + else + { + ndisMProcessDeferredPrioritySends(Miniport); + } + } + else +#endif + { + NDISM_PROCESS_DEFERRED(Miniport); + } + + UNLOCK_MINIPORT(Miniport, LocalLock); + NDIS_RELEASE_MINIPORT_SPIN_LOCK_DPC(Miniport); +} + + +VOID +ndisMCoDpc( + IN PVOID SystemSpecific1, + IN PVOID InterruptContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3 + ) +/*++ + +Routine Description: + + Handles ALL Miniport interrupt DPCs, calling the appropriate Miniport DPC + depending on the context. + +Arguments: + + Interrupt - Interrupt object for the Mac. + + Context - Really a pointer to the Interrupt. + +Return Value: + + None. + +--*/ +{ + // + // Get adapter from context. + // + + PNDIS_MINIPORT_INTERRUPT Interrupt = (PNDIS_MINIPORT_INTERRUPT)(InterruptContext); + PNDIS_MINIPORT_BLOCK Miniport = Interrupt->Miniport; + BOOLEAN LocalLock; + + W_HANDLE_INTERRUPT_HANDLER MiniportDpc = Interrupt->MiniportDpc; + + if (MINIPORT_TEST_FLAG(Miniport, fMINIPORT_HALTING)) + { + Decrement((PLONG)&Interrupt->DpcCount, &Interrupt->DpcCountLock); + + if (Interrupt->DpcCount==0) + { + SET_EVENT(&Interrupt->DpcsCompletedEvent); + } + } + else + { + // + // Call MiniportDpc + // + (*MiniportDpc)(Miniport->MiniportAdapterContext); + + Decrement((PLONG)&Interrupt->DpcCount, &Interrupt->DpcCountLock); + + if (!MINIPORT_TEST_FLAG(Miniport, fMINIPORT_HALTING)) + { + // + // Enable interrupts + // + + MINIPORT_SYNC_ENABLE_INTERRUPT(Miniport); + } + else + { + if (Interrupt->DpcCount == 0) + { + SET_EVENT(&Interrupt->DpcsCompletedEvent); + } + } + + } +} + + +VOID +ndisMCoDpcTimer( + IN PVOID SystemSpecific1, + IN PVOID InterruptContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3 + ) +/*++ + +Routine Description: + + Handles a deferred interrupt dpc. + +Arguments: + + Context - Really a pointer to the Miniport block. + +Return Value: + + None. + +--*/ +{ + // + // Get adapter from context. + // + + PNDIS_MINIPORT_BLOCK Miniport = (PNDIS_MINIPORT_BLOCK)(InterruptContext); + BOOLEAN LocalLock; + + W_HANDLE_INTERRUPT_HANDLER MiniportDpc = Miniport->HandleInterruptHandler; + + if (!MINIPORT_TEST_FLAG(Miniport, fMINIPORT_IN_INITIALIZE)) + { + // + // Disable the interrupts. + // + MINIPORT_SYNC_DISABLE_INTERRUPT(Miniport); + + // + // Call MiniportDpc + // + if (MiniportDpc != NULL) + { + (*MiniportDpc)(Miniport->MiniportAdapterContext); + } + + // + // Enable interrupts + // + MINIPORT_SYNC_ENABLE_INTERRUPT(Miniport); + + } +} + +VOID +ndisMCoTimerDpc( + IN PKDPC Dpc, + IN PVOID Context, + IN PVOID SystemContext1, + IN PVOID SystemContext2 + ) +/*++ + +Routine Description: + + This function services all mini-port timer interrupts. It then calls the + appropriate function that mini-port consumers have registered in the + call to NdisMInitializeTimer. + +Arguments: + + Dpc - Not used. + + Context - A pointer to the NDIS_MINIPORT_TIMER which is bound to this DPC. + + SystemContext1,2 - not used. + +Return Value: + + None. + +--*/ +{ + PNDIS_MINIPORT_TIMER MiniportTimer = (PNDIS_MINIPORT_TIMER)(Context); + PNDIS_MINIPORT_BLOCK Miniport = MiniportTimer->Miniport; + BOOLEAN LocalLock; + + UNREFERENCED_PARAMETER(Dpc); + UNREFERENCED_PARAMETER(SystemContext1); + UNREFERENCED_PARAMETER(SystemContext2); + + // + // Call Miniport timer function + // + (*MiniportTimer->MiniportTimerFunction)(NULL, MiniportTimer->MiniportTimerContext, NULL, NULL); +} + + + -- cgit v1.2.3