windows-nt/Source/XPSP1/NT/net/irda/irsir/queue.c

328 lines
6.5 KiB
C
Raw Permalink Normal View History

2020-09-26 03:20:57 -05:00
#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;
}