328 lines
6.5 KiB
C
328 lines
6.5 KiB
C
|
|
#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;
|
|
}
|