|
|
#include "irsir.h"
#pragma alloc_text(PAGE,InitializePacketQueue)
VOID InitializePacketQueue( PPACKET_QUEUE PacketQueue, PVOID Context, PACKET_STARTER StarterRoutine )
{
NdisZeroMemory(PacketQueue,sizeof(*PacketQueue));
NdisAllocateSpinLock(&PacketQueue->Lock);
PacketQueue->Context=Context;
PacketQueue->Starter=StarterRoutine;
PacketQueue->Active=TRUE;
KeInitializeEvent(&PacketQueue->InactiveEvent,NotificationEvent,FALSE);
return;
}
VOID QueuePacket( PPACKET_QUEUE PacketQueue, PNDIS_PACKET Packet )
{
NDIS_STATUS Status; PPACKET_RESERVED_BLOCK Reserved=(PPACKET_RESERVED_BLOCK)&Packet->MiniportReservedEx[0];
NdisAcquireSpinLock(&PacketQueue->Lock);
if ((PacketQueue->CurrentPacket == NULL) && PacketQueue->Active && (PacketQueue->HeadOfList == NULL)) { //
// not currently handling a packet and the queu is active and there are not other packets
// queued, so handle it now
//
PacketQueue->CurrentPacket=Packet;
NdisReleaseSpinLock(&PacketQueue->Lock);
(*PacketQueue->Starter)( PacketQueue->Context, Packet );
return;
}
//
// need to queue the packet
//
Reserved->Next=NULL;
if (PacketQueue->HeadOfList == NULL) { //
// the list is empty
//
PacketQueue->HeadOfList=Packet;
} else {
Reserved=(PPACKET_RESERVED_BLOCK)&PacketQueue->TailOfList->MiniportReservedEx[0];
Reserved->Next=Packet; }
PacketQueue->TailOfList=Packet;
NdisReleaseSpinLock(&PacketQueue->Lock);
return;
}
VOID StartNextPacket( PPACKET_QUEUE PacketQueue )
{
NdisAcquireSpinLock(&PacketQueue->Lock);
ASSERT(PacketQueue->CurrentPacket != NULL);
//
// done with this one
//
PacketQueue->CurrentPacket=NULL;
if (!PacketQueue->InStartNext) { //
// not already in this function
//
PacketQueue->InStartNext=TRUE;
while ((PacketQueue->CurrentPacket == NULL) && PacketQueue->Active && (PacketQueue->HeadOfList != NULL)) { //
// there is a packet queued
//
PNDIS_PACKET Packet; PPACKET_RESERVED_BLOCK Reserved;
//
// get the first packet on the list
//
Packet=PacketQueue->HeadOfList;
//
// Get a pointer to miniport reserved area
//
Reserved=(PPACKET_RESERVED_BLOCK)&Packet->MiniportReservedEx[0];
//
// move to the next one in the list
//
PacketQueue->HeadOfList=Reserved->Next;
#if DBG
Reserved->Next=NULL;
if (PacketQueue->HeadOfList == NULL) {
PacketQueue->TailOfList=NULL; } #endif
//
// now the current one
//
PacketQueue->CurrentPacket=Packet;
NdisReleaseSpinLock(&PacketQueue->Lock);
//
// start the processing
//
(*PacketQueue->Starter)( PacketQueue->Context, Packet );
NdisAcquireSpinLock(&PacketQueue->Lock);
}
if (!PacketQueue->Active && (PacketQueue->CurrentPacket == NULL)) { //
// the queue has been paused and we don't have a current packet, signal the event
//
KeSetEvent( &PacketQueue->InactiveEvent, IO_NO_INCREMENT, FALSE ); }
PacketQueue->InStartNext=FALSE; }
NdisReleaseSpinLock(&PacketQueue->Lock);
return;
}
VOID PausePacketProcessing( PPACKET_QUEUE PacketQueue, BOOLEAN WaitForInactive )
{
BOOLEAN CurrentlyActive=FALSE;
NdisAcquireSpinLock(&PacketQueue->Lock);
PacketQueue->Active=FALSE;
if (PacketQueue->CurrentPacket != NULL) { //
// there is a packet currently being processed
//
CurrentlyActive=TRUE;
KeClearEvent(&PacketQueue->InactiveEvent);
}
NdisReleaseSpinLock(&PacketQueue->Lock);
if (WaitForInactive && CurrentlyActive) { //
// the caller wants use to wait for the queue to inactive, and it was active when
// theis was called
//
KeWaitForSingleObject( &PacketQueue->InactiveEvent, Executive, KernelMode, FALSE, NULL );
}
return;
}
VOID ActivatePacketProcessing( PPACKET_QUEUE PacketQueue )
{
NdisAcquireSpinLock(&PacketQueue->Lock);
PacketQueue->Active=TRUE;
if ((PacketQueue->CurrentPacket == NULL) && (PacketQueue->HeadOfList != NULL)) { //
// there is a packet queued
//
PNDIS_PACKET Packet; PPACKET_RESERVED_BLOCK Reserved;
Packet=PacketQueue->HeadOfList;
//
// get a pointer to the reserved area
//
Reserved=(PPACKET_RESERVED_BLOCK)&Packet->MiniportReservedEx[0];
PacketQueue->HeadOfList=Reserved->Next;
//
// now the current one
//
PacketQueue->CurrentPacket=Packet;
NdisReleaseSpinLock(&PacketQueue->Lock);
//
// start the processing
//
(*PacketQueue->Starter)( PacketQueue->Context, Packet );
NdisAcquireSpinLock(&PacketQueue->Lock);
}
NdisReleaseSpinLock(&PacketQueue->Lock);
return;
}
VOID FlushQueuedPackets( PPACKET_QUEUE PacketQueue, NDIS_HANDLE WrapperHandle )
{ //
// dispose of all of the queue packets, don't touch the current one though
//
NdisAcquireSpinLock(&PacketQueue->Lock);
while (PacketQueue->HeadOfList != NULL) { //
// there is a packet queued
//
PNDIS_PACKET Packet; PPACKET_RESERVED_BLOCK Reserved;
Packet=PacketQueue->HeadOfList;
Reserved=(PPACKET_RESERVED_BLOCK)&Packet->MiniportReservedEx[0];
PacketQueue->HeadOfList=Reserved->Next;
NdisReleaseSpinLock(&PacketQueue->Lock);
//
// start the processing
//
NdisMSendComplete( WrapperHandle, Packet, NDIS_STATUS_REQUEST_ABORTED );
NdisAcquireSpinLock(&PacketQueue->Lock);
}
NdisReleaseSpinLock(&PacketQueue->Lock);
return; }
|