|
|
/*++
Copyright (c) 1990-1995 Microsoft Corporation
Module Name:
Ndiswan.c
Abstract:
This is the initialization file for the NdisWan driver. This driver is a shim between the protocols, where it conforms to the NDIS 3.1 Miniport interface spec, and the WAN Miniport drivers, where it exports the WAN Extensions for Miniports (it looks like a protocol to the WAN Miniport drivers).
Author:
Tony Bell (TonyBe) June 06, 1995
Environment:
Kernel Mode
Revision History:
TonyBe 06/06/95 Created
--*/
#include "wan.h"
#define __FILE_SIG__ MEMORY_FILESIG
#ifdef ALLOC_PRAGMA
#pragma alloc_text(INIT, NdisWanCreateProtocolInfoTable)
#endif
EXPORT VOID NdisTapiDeregisterProvider( IN NDIS_HANDLE );
//
// Local function prototypes
//
PVOID AllocateWanPacket( IN POOL_TYPE PoolType, IN SIZE_T NumberOfBytes, IN ULONG Tag );
VOID FreeWanPacket( PVOID WanPacket );
//
// End local function prototypes
//
PMINIPORTCB NdisWanAllocateMiniportCB( IN PNDIS_STRING AdapterName ) /*++
Routine Name:
NdisWanAllocateMiniportCB
Routine Description:
This routine creates and initializes an MiniportCB
Arguments:
Return Values:
--*/ { PMINIPORTCB LocalMiniportCB; ULONG ulAllocationSize, i;
NdisWanDbgOut(DBG_TRACE, DBG_MEMORY, ("NdisWanCreateMiniportCB: Enter"));
//
// Allocate and zero out the memory block
//
NdisWanAllocateMemory(&LocalMiniportCB, MINIPORTCB_SIZE, MINIPORTCB_TAG);
if (LocalMiniportCB == NULL) {
return (NULL); }
NdisZeroMemory(LocalMiniportCB, MINIPORTCB_SIZE);
//
// setup the new control block
//
NdisAllocateSpinLock(&LocalMiniportCB->Lock);
#ifdef MINIPORT_NAME
NdisWanAllocateAdapterName(&LocalMiniportCB->AdapterName, AdapterName); #endif
#if DBG
InitializeListHead(&LocalMiniportCB->SendPacketList); InitializeListHead(&LocalMiniportCB->RecvPacketList); #endif
InitializeListHead(&LocalMiniportCB->ProtocolCBList); InitializeListHead(&LocalMiniportCB->AfSapCBList);
NdisWanInitializeSyncEvent(&LocalMiniportCB->HaltEvent); NdisWanClearSyncEvent(&LocalMiniportCB->HaltEvent);
//
// Add to global list
//
InsertTailGlobalList(MiniportCBList, &(LocalMiniportCB->Linkage));
NdisWanDbgOut(DBG_TRACE, DBG_MEMORY, ("%ls MiniportCB: 0x%x, Number: %d", LocalMiniportCB->AdapterName.Buffer, LocalMiniportCB, MiniportCBList.ulCount));
NdisWanDbgOut(DBG_TRACE, DBG_MEMORY, ("NdisWanCreateMiniportCB: Exit"));
return (LocalMiniportCB); }
VOID NdisWanFreeMiniportCB( IN PMINIPORTCB pMiniportCB ) /*++
Routine Name:
NdisWanFreeMiniportCB
Routine Description:
This frees a MiniportCB
Arguments:
pMiniportCB - Pointer to to the MiniportCB that is being destroyed
Return Values:
None
--*/ { PMINIPORTCB mcb; BOOLEAN Found = FALSE;
NdisWanDbgOut(DBG_TRACE, DBG_MEMORY, ("NdisWanFreeMiniportCB: Enter")); NdisWanDbgOut(DBG_TRACE, DBG_MEMORY, ("MiniportCB: 0x%x", pMiniportCB));
#ifdef MINIPORT_NAME
NdisWanFreeNdisString(&pMiniportCB->AdapterName); #endif
NdisFreeSpinLock(&pMiniportCB->Lock);
NdisAcquireSpinLock(&MiniportCBList.Lock);
RemoveEntryList(&pMiniportCB->Linkage);
MiniportCBList.ulCount--;
//
// Walk the miniportcb list and see if this is the only
// instance of this protocol. If it is we need to notify
// user-mode that a protocol has been removed.
//
mcb = (PMINIPORTCB)MiniportCBList.List.Flink;
while ((PVOID)mcb != (PVOID)&MiniportCBList.List) { if (mcb->ProtocolType == pMiniportCB->ProtocolType) { Found = TRUE; break; }
mcb = (PMINIPORTCB)mcb->Linkage.Flink; }
NdisReleaseSpinLock(&MiniportCBList.Lock);
if (Found == FALSE) { PROTOCOL_INFO pinfo;
NdisZeroMemory(&pinfo, sizeof(pinfo)); pinfo.ProtocolType = pMiniportCB->ProtocolType; pinfo.Flags = PROTOCOL_UNBOUND; SetProtocolInfo(&pinfo); }
NdisWanFreeMemory(pMiniportCB);
NdisWanDbgOut(DBG_TRACE, DBG_MEMORY, ("NdisWanFreeMiniportCB: Exit")); }
POPENCB NdisWanAllocateOpenCB( IN PUNICODE_STRING BindName ) /*++
Routine Name:
NdisWanAllocateOpenCB
Routine Description:
This routine creates and initializes a OpenCB
Arguments:
BindName - Pointer to an NDIS_STRING that has the name of the WAN Miniport that will be used in the NdisOpenAdapter call when we bind to the WAN Miniport.
Return Values:
--*/ { POPENCB pOpenCB; ULONG ulAllocationSize; USHORT i;
NdisWanDbgOut(DBG_TRACE, DBG_MEMORY, ("NdisWanCreateOpenCB: Enter")); NdisWanDbgOut(DBG_TRACE, DBG_MEMORY, ("BindName: %ls", BindName));
//
// Allocate memory for OpenCB
//
NdisWanAllocateMemory(&pOpenCB, OPENCB_SIZE, OPENCB_TAG);
if (pOpenCB == NULL) { return (NULL); }
NdisZeroMemory(pOpenCB, OPENCB_SIZE); NdisWanInitializeNotificationEvent(&pOpenCB->InitEvent);
//
// Parse out the GUID for this miniport
//
//
// Setup new control block
//
NdisWanAllocateMemory(&pOpenCB->MiniportName.Buffer, BindName->MaximumLength, NDISSTRING_TAG); pOpenCB->MiniportName.MaximumLength = BindName->MaximumLength; pOpenCB->MiniportName.Length = BindName->Length; RtlCopyUnicodeString(&pOpenCB->MiniportName, BindName);
//
// Go to the end of the string and work back until we find
// the first "{". Now start parsing the string converting
// and copying from WCHAR to CHAR all digits until we hit
// the closing "}".
//
for (i = pOpenCB->MiniportName.Length/sizeof(WCHAR); i > 0; i--) { if (pOpenCB->MiniportName.Buffer[i-1] == (WCHAR)L'{') { break; } }
if (i != 0) { NDIS_STRING Src;
Src.Length = BindName->Length - ((i-1)*sizeof(WCHAR)); Src.MaximumLength = BindName->Length - ((i-1)*sizeof(WCHAR)); Src.Buffer = &BindName->Buffer[i-1];
RtlGUIDFromString(&Src, &pOpenCB->Guid); }
NdisAllocateSpinLock(&pOpenCB->Lock); InitializeListHead(&pOpenCB->AfSapCBList); InitializeListHead(&pOpenCB->AfSapCBClosing); InitializeListHead(&pOpenCB->WanRequestList);
#if DBG
InitializeListHead(&pOpenCB->SendPacketList); #endif
//
// Put OpenCB on global list
//
InsertTailGlobalList(OpenCBList, &(pOpenCB->Linkage));
pOpenCB->RefCount = 1;
NdisWanDbgOut(DBG_TRACE, DBG_MEMORY, ("WanMiniport %ls OpenCB: 0x%x", pOpenCB->MiniportName.Buffer, pOpenCB)); NdisWanDbgOut(DBG_TRACE, DBG_MEMORY, ("NdisWanCreateOpenCB: Exit"));
return(pOpenCB); }
VOID NdisWanFreeOpenCB( IN POPENCB pOpenCB ) /*++
Routine Name:
NdisWanFreeOpenCB
Routine Description:
This routine frees a OpenCB
Arguments:
pOpenCB - Pointer to the OpenCB that is being destroyed
Return Values:
None
--*/ { NdisWanDbgOut(DBG_TRACE, DBG_MEMORY, ("NdisWanFreeOpenCB: Enter - OpenCB: 0x%p", pOpenCB));
if (pOpenCB->Flags & OPEN_LEGACY && pOpenCB->Flags & SEND_RESOURCES) { NdisWanFreeSendResources(pOpenCB); }
//
// Remove from OpenCB global list
//
RemoveEntryGlobalList(OpenCBList, &(pOpenCB->Linkage));
//
// Free the memory allocated for the NDIS_STRING
//
NdisWanFreeNdisString(&pOpenCB->MiniportName);
//
// Free the memory allocated for the control block
//
NdisWanFreeMemory(pOpenCB);
NdisWanDbgOut(DBG_TRACE, DBG_MEMORY, ("NdisWanFreeOpenCB: Exit")); }
PPROTOCOLCB NdisWanAllocateProtocolCB( IN PNDISWAN_ROUTE Route ) /*++
Routine Name:
Routine Description:
Arguments:
Return Values:
--*/ { PPROTOCOLCB LocalProtocolCB; PUCHAR AllocatedMemory; PROTOCOL_INFO ProtocolInfo = {0};
LocalProtocolCB = NdisAllocateFromNPagedLookasideList(&LinkProtoCBList);
if (LocalProtocolCB == NULL) { return(NULL); }
NdisZeroMemory(LocalProtocolCB, PROTOCOLCB_SIZE);
LocalProtocolCB->Signature = PROTOCB_SIG;
if (Route->ulBufferLength > 0) { NdisWanAllocateMemory(&AllocatedMemory, Route->ulBufferLength, PROTOCOLCB_TAG); if (AllocatedMemory == NULL) { NdisFreeToNPagedLookasideList(&LinkProtoCBList, LocalProtocolCB); return (NULL); }
LocalProtocolCB->LineUpInfo = AllocatedMemory; }
//
// Copy the bindingname
//
if (Route->usBindingNameLength != 0) { USHORT usBindingNameLength; WCHAR BindingName[MAX_NAME_LENGTH+1] = {0};
usBindingNameLength = Route->usBindingNameLength;
//
// We will limit the binding name string to 256 wchars
//
if (usBindingNameLength > (MAX_NAME_LENGTH * sizeof(WCHAR))) { usBindingNameLength = MAX_NAME_LENGTH * sizeof(WCHAR); }
NdisMoveMemory((PUCHAR)BindingName, (PUCHAR)Route->BindingName, usBindingNameLength); BindingName[usBindingNameLength/sizeof(WCHAR)] = L'\0';
NdisWanStringToNdisString(&LocalProtocolCB->BindingName, BindingName); }
if (Route->usDeviceNameLength != 0) { USHORT usDeviceNameLength;
usDeviceNameLength = Route->usDeviceNameLength;
//
// We will limit the binding name string to 256 wchars
//
if (usDeviceNameLength > (MAX_NAME_LENGTH * sizeof(WCHAR))) { usDeviceNameLength = (MAX_NAME_LENGTH * sizeof(WCHAR)); }
NdisWanAllocateMemory(&(LocalProtocolCB->InDeviceName.Buffer), usDeviceNameLength, NDISSTRING_TAG);
if (LocalProtocolCB->InDeviceName.Buffer != NULL) {
LocalProtocolCB->InDeviceName.MaximumLength = usDeviceNameLength; LocalProtocolCB->InDeviceName.Length = usDeviceNameLength;
NdisMoveMemory((PUCHAR)LocalProtocolCB->InDeviceName.Buffer, (PUCHAR)Route->DeviceName, usDeviceNameLength); }
}
//
// Copy over the protocol info
//
LocalProtocolCB->ulLineUpInfoLength = Route->ulBufferLength; if (Route->ulBufferLength != 0) { NdisMoveMemory(LocalProtocolCB->LineUpInfo, Route->Buffer, Route->ulBufferLength); } //
// Setup the protocol type
//
LocalProtocolCB->ProtocolType = Route->usProtocolType; //
// Get the PPP protocol value for this protocol type
//
ProtocolInfo.ProtocolType = Route->usProtocolType;
if (GetProtocolInfo(&ProtocolInfo) != TRUE) {
if (LocalProtocolCB->BindingName.Length != 0) { NdisWanFreeNdisString(&LocalProtocolCB->BindingName); }
if (LocalProtocolCB->LineUpInfo != NULL) { NdisWanFreeMemory(LocalProtocolCB->LineUpInfo); }
if (LocalProtocolCB->InDeviceName.Length != 0) { NdisWanFreeMemory(LocalProtocolCB->InDeviceName.Buffer); }
NdisFreeToNPagedLookasideList(&LinkProtoCBList, LocalProtocolCB); return (NULL); }
InitializeListHead(&LocalProtocolCB->VcList); NdisWanInitializeSyncEvent(&LocalProtocolCB->UnrouteEvent);
LocalProtocolCB->PPPProtocolID = ProtocolInfo.PPPId; LocalProtocolCB->MTU = ProtocolInfo.MTU; LocalProtocolCB->TunnelMTU = ProtocolInfo.TunnelMTU; LocalProtocolCB->State = PROTOCOL_ROUTING; LocalProtocolCB->RefCount = 1;
switch (Route->usProtocolType) { case PROTOCOL_IP: LocalProtocolCB->NonIdleDetectFunc = IpIsDataFrame; break; case PROTOCOL_IPX: LocalProtocolCB->NonIdleDetectFunc = IpxIsDataFrame; break; case PROTOCOL_NBF: LocalProtocolCB->NonIdleDetectFunc = NbfIsDataFrame; break; default: LocalProtocolCB->NonIdleDetectFunc = NULL; break; } NdisWanGetSystemTime(&LocalProtocolCB->LastNonIdleData);
return(LocalProtocolCB); }
VOID NdisWanFreeProtocolCB( IN PPROTOCOLCB ProtocolCB ) /*++
Routine Name:
Routine Description:
Arguments:
Return Values:
--*/ {
#if DBG
{ ULONG i;
for (i = 0; i < MAX_MCML; i++) { ASSERT(ProtocolCB->PacketQueue[i].HeadQueue == NULL); ASSERT(ProtocolCB->PacketQueue[i].TailQueue == NULL); }
} #endif
if (ProtocolCB->InDeviceName.Length != 0) { NdisWanFreeMemory(ProtocolCB->InDeviceName.Buffer); }
if (ProtocolCB->OutDeviceName.Length != 0) { NdisWanFreeNdisString(&ProtocolCB->OutDeviceName); }
if (ProtocolCB->BindingName.Length != 0) { NdisWanFreeNdisString(&ProtocolCB->BindingName); }
if (ProtocolCB->LineUpInfo != NULL) { NdisWanFreeMemory(ProtocolCB->LineUpInfo); }
NdisFreeSpinLock(&ProtocolCB->Lock);
NdisFreeToNPagedLookasideList(&LinkProtoCBList, ProtocolCB); }
PLINKCB NdisWanAllocateLinkCB( IN POPENCB OpenCB, IN ULONG SendWindow ) /*++
Routine Name:
NdisWanGetLinkCB
Routine Description:
This function returns a pointer to a LinkCB. The LinkCB is either retrieved from the WanAdapters free list or, if this list is empty, it is allocated.
Arguments:
OpenCB - Pointer to the WanAdapter control block that this Link is associated with
Return Values:
None
--*/ { PLINKCB LocalLinkCB;
//
// Figure out how much we need to allocate
//
LocalLinkCB = NdisAllocateFromNPagedLookasideList(&LinkProtoCBList);
if (LocalLinkCB == NULL) { NdisWanDbgOut(DBG_CRITICAL_ERROR, DBG_MEMORY, ("Error allocating memory for LinkCB"));
return (NULL); }
NdisZeroMemory(LocalLinkCB, LINKCB_SIZE);
//
// Initialize the control block
//
NdisWanInitializeSyncEvent(&LocalLinkCB->OutstandingFramesEvent);
LocalLinkCB->Signature = LINKCB_SIG; LocalLinkCB->hLinkContext = NULL; LocalLinkCB->State = LINK_UP; LocalLinkCB->OpenCB = OpenCB; LocalLinkCB->OutstandingFrames = 0; LocalLinkCB->SendWindowOpen = TRUE; LocalLinkCB->SBandwidth = 100; LocalLinkCB->RBandwidth = 100; LocalLinkCB->SFlowSpec.MaxSduSize = glMaxMTU; LocalLinkCB->RFlowSpec.MaxSduSize = glMRRU;
LocalLinkCB->LinkInfo.HeaderPadding = OpenCB->WanInfo.HeaderPadding; LocalLinkCB->LinkInfo.TailPadding = OpenCB->WanInfo.TailPadding; LocalLinkCB->LinkInfo.SendACCM = LocalLinkCB->LinkInfo.RecvACCM = OpenCB->WanInfo.DesiredACCM; LocalLinkCB->LinkInfo.MaxSendFrameSize = glMaxMTU; LocalLinkCB->LinkInfo.MaxRecvFrameSize = glMRU;
if (OpenCB->Flags & OPEN_LEGACY) { LocalLinkCB->SendHandler = SendOnLegacyLink; } else { LocalLinkCB->SendHandler = SendOnLink; }
if (OpenCB->MediumType == NdisMediumAtm ||
(OpenCB->MediumType == NdisMediumWan && (OpenCB->MediumSubType == NdisWanMediumAtm || OpenCB->MediumSubType == NdisWanMediumPppoe)) ||
(OpenCB->MediumType == NdisMediumCoWan && (OpenCB->MediumSubType == NdisWanMediumAtm || OpenCB->MediumSubType == NdisWanMediumPppoe))) {
LocalLinkCB->RecvHandler = DetectBroadbandFraming;
LocalLinkCB->LinkInfo.SendFramingBits = PPP_FRAMING | PPP_COMPRESS_ADDRESS_CONTROL;
LocalLinkCB->LinkInfo.RecvFramingBits = PPP_FRAMING | PPP_COMPRESS_ADDRESS_CONTROL;
} else {
LocalLinkCB->RecvHandler = DetectFraming; }
LocalLinkCB->SendWindow = (SendWindow == 0 || SendWindow > OpenCB->WanInfo.MaxTransmit) ? OpenCB->WanInfo.MaxTransmit : SendWindow;
if (LocalLinkCB->SendWindow == 0) { LocalLinkCB->SendWindow = 1; }
if (OpenCB->Flags & OPEN_LEGACY) { LocalLinkCB->SendResources = OpenCB->SendResources; } else { LocalLinkCB->SendResources = 1000; }
NdisAllocateSpinLock(&LocalLinkCB->Lock);
LocalLinkCB->RefCount = 1;
REF_OPENCB(OpenCB);
InterlockedIncrement(&OpenCB->ActiveLinkCount);
return (LocalLinkCB); }
VOID NdisWanFreeLinkCB( PLINKCB LinkCB ) /*++
Routine Name:
Routine Description:
Arguments:
Return Values:
--*/ { POPENCB pOpenCB = LinkCB->OpenCB;
ASSERT(LinkCB->OutstandingFrames == 0);
LinkCB->State = LINK_DOWN;
NdisFreeSpinLock(&LocalLinkCB->Lock);
NdisFreeToNPagedLookasideList(&LinkProtoCBList, LinkCB);
InterlockedDecrement(&pOpenCB->ActiveLinkCount);
DEREF_OPENCB(pOpenCB); }
NDIS_STATUS NdisWanAllocateSendResources( POPENCB OpenCB ) /*++
Routine Name:
NdisWanAllocateSendResources
Routine Description:
Allocates all resources (SendDescriptors, WanPackets, ...) required for sending data. Should be called at line up time.
Arguments:
LinkCB - Pointer to the linkcb that the send resources will be attached to. SendWindow - Maximum number of sends that this link can handle
Return Values:
NDIS_STATUS_SUCCESS NDIS_STATUS_RESOURCES
--*/ { ULONG SendWindow; ULONG Endpoints; ULONG NumberOfPackets; ULONG BufferSize; ULONG WanPacketSize; PNDIS_WAN_PACKET WanPacket; NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
do {
//
// We have to have atleast of sendwindow+1 of packets for
// each link on the open. In the case of MCML we need
// this amount for each fragment queue and for the
// single non-fragment queue. So this leaves us with...
//
//
// SendWindow + 1 + (glMaxMTU/glMinFragSize * MAX_MCML) *
// number of links on the open
//
SendWindow = OpenCB->WanInfo.MaxTransmit; Endpoints = OpenCB->WanInfo.Endpoints;
//
// Sendwindow
//
NumberOfPackets = SendWindow;
//
// We keep track of how many fragmenting resources we have
// available for each link
//
NumberOfPackets += ((glMaxMTU/glMinFragSize) * MAX_MCML); OpenCB->SendResources = NumberOfPackets;
//
// Add one for compression data manipulation
//
NumberOfPackets += 1;
//
// multiplied by the # of links on this open
//
NumberOfPackets *= Endpoints;
//
// The size of the buffer that we create is
//
BufferSize = OpenCB->WanInfo.MaxFrameSize + OpenCB->WanInfo.HeaderPadding + OpenCB->WanInfo.TailPadding + 40 + sizeof(PVOID);
//
// We assume compression is always on so we pad out 12%
// incase the compressor expands. I don't know where the
// 12% figure comes from.
//
BufferSize += (OpenCB->WanInfo.MaxFrameSize + 7) / 8;
//
// Make sure that the buffer is dword aligned.
//
BufferSize &= ~((ULONG_PTR)sizeof(PVOID) - 1);
OpenCB->BufferSize = BufferSize;
WanPacketSize = sizeof(DATA_DESC) + sizeof(NDIS_WAN_PACKET) + 3*sizeof(PVOID) + BufferSize;
//
// If this device needs some special memory flags
// we need to allocate memory for it's WanPackets now.
// Otherwise we will intialize a lookaside list and
// retrieve the packets as needed.
if (OpenCB->WanInfo.MemoryFlags == 0) {
NdisInitializeNPagedLookasideList(&OpenCB->WanPacketPool, AllocateWanPacket, FreeWanPacket, 0, WanPacketSize, WANPACKET_TAG, 0);
} else { ULONG PacketMemorySize; PUCHAR PacketMemory; ULONG n;
PacketMemorySize = WanPacketSize * NumberOfPackets;
//
// Allocate the memory for the wan packet buffer pool
//
NdisAllocateMemory(&PacketMemory, PacketMemorySize, OpenCB->WanInfo.MemoryFlags, OpenCB->WanInfo.HighestAcceptableAddress);
if (PacketMemory == NULL) { NdisWanDbgOut(DBG_CRITICAL_ERROR, DBG_MEMORY, ("Error allocating memory for BufferPool, AllocationSize: %d", PacketMemorySize));
Status = NDIS_STATUS_RESOURCES; break; }
OpenCB->PacketMemory = PacketMemory; OpenCB->PacketMemorySize = PacketMemorySize; NdisInitializeSListHead(&OpenCB->WanPacketList);
for (n = 0; n < NumberOfPackets; n++) { PDATA_DESC DataDesc;
//
// Point to the DataDesc
//
DataDesc = (PDATA_DESC)PacketMemory;
PacketMemory = ((PUCHAR)(DataDesc + 1) + sizeof(PVOID));
(ULONG_PTR)PacketMemory &= ~((ULONG_PTR)sizeof(PVOID) - 1);
//
// Point to the WanPacket
//
WanPacket = (PNDIS_WAN_PACKET)PacketMemory;
PacketMemory = ((PUCHAR)(WanPacket + 1) + sizeof(PVOID));
(ULONG_PTR)PacketMemory &= ~((ULONG_PTR)sizeof(PVOID) - 1);
//
// Point to the begining of the data buffer
//
WanPacket->StartBuffer = PacketMemory; WanPacket->EndBuffer = PacketMemory + BufferSize - sizeof(PVOID);
NdisInterlockedPushEntrySList(&OpenCB->WanPacketList, (PSLIST_ENTRY)DataDesc, &OpenCB->Lock);
PacketMemory += BufferSize + sizeof(PVOID); (ULONG_PTR)PacketMemory &= ~((ULONG_PTR)sizeof(PVOID) - 1); } }
} while ( FALSE );
if (Status == NDIS_STATUS_SUCCESS) { OpenCB->Flags |= SEND_RESOURCES; }
return (Status); }
VOID NdisWanFreeSendResources( POPENCB OpenCB ) /*++
Routine Name:
NdisWanFreeSendResources
Routine Description:
This routine removes the WanPackets from this opencb's send list and free's the memory allocated for these packets. Should be called when we are cleaningup an opencb.
Arguments:
OpenCB - Pointer to the opencb that the resources are being freed from.
Return Values:
None
--*/ { PUCHAR PacketMemory; ULONG PacketMemorySize, Flags;
PacketMemory = OpenCB->PacketMemory; PacketMemorySize = OpenCB->PacketMemorySize; Flags = OpenCB->WanInfo.MemoryFlags;
if (OpenCB->WanInfo.MemoryFlags == 0) { NdisDeleteNPagedLookasideList(&OpenCB->WanPacketPool); return; }
//
// Remove the packets from the wan packet pool
//
for (; ;) { PDATA_DESC DataDesc;
DataDesc = (PDATA_DESC) NdisInterlockedPopEntrySList(&OpenCB->WanPacketList, &OpenCB->Lock);
if (DataDesc == NULL) { break; } }
ASSERT(NdisQueryDepthSList(&OpenCB->WanPacketList) == 0);
//
// Free the block of memory allocated for this send
//
if (PacketMemory != NULL) { NdisFreeMemory(OpenCB->PacketMemory, OpenCB->PacketMemorySize, OpenCB->Flags); } }
PBUNDLECB NdisWanAllocateBundleCB( VOID ) /*++
Routine Name:
Routine Description:
Arguments:
Return Values:
--*/ { PBUNDLECB LocalBundleCB = NULL; PWSTR IOName = L"I/O ProtocolCB"; PPROTOCOLCB ProtocolCB; PSAMPLE_TABLE SampleTable; PBOND_INFO BonDInfo; UINT Class; PUCHAR pMem;
//
// Allocation size is the size of the control block plus the size
// of a table of pointers to protocolcb's that might be routed to
// this bundle.
//
pMem = NdisAllocateFromNPagedLookasideList(&BundleCBList);
if (pMem == NULL) { return (NULL); }
NdisZeroMemory(pMem, BUNDLECB_SIZE);
LocalBundleCB = (PBUNDLECB)pMem;
pMem += sizeof(BUNDLECB) + sizeof(PVOID);
//
// This is the memory used for the I/O protocolcb
//
(PUCHAR)ProtocolCB = pMem; (ULONG_PTR)ProtocolCB &= ~((ULONG_PTR)sizeof(PVOID) - 1);
pMem += sizeof(PROTOCOLCB) + sizeof(PVOID);
//
// This is the protocolcb table
//
(PUCHAR)LocalBundleCB->ProtocolCBTable = pMem;
(ULONG_PTR)LocalBundleCB->ProtocolCBTable &= ~((ULONG_PTR)sizeof(PVOID) - 1);
pMem += (MAX_PROTOCOLS * sizeof(PPROTOCOLCB)) + sizeof(PVOID);
//
// Initialize the BundleCB
//
NdisAllocateSpinLock(&LocalBundleCB->Lock); InitializeListHead(&LocalBundleCB->LinkCBList);
for (Class = 0; Class < MAX_MCML; Class++) { PRECV_DESC RecvDescHole; PSEND_FRAG_INFO FragInfo; PBUNDLE_RECV_INFO RecvInfo;
FragInfo = &LocalBundleCB->SendFragInfo[Class]; RecvInfo = &LocalBundleCB->RecvInfo[Class];
InitializeListHead(&FragInfo->FragQueue); FragInfo->MinFragSize = glMinFragSize; FragInfo->MaxFragSize = glMaxFragSize;
InitializeListHead(&RecvInfo->AssemblyList);
//
// Init the recv hole desc
//
RecvDescHole = NdisWanAllocateRecvDesc(0); if (RecvDescHole == NULL) { UINT i;
for (i = 0; i < MAX_MCML; i++) { RecvInfo = &LocalBundleCB->RecvInfo[i];
if (RecvInfo->RecvDescHole != NULL) { NdisWanFreeRecvDesc(RecvInfo->RecvDescHole); } }
NdisFreeToNPagedLookasideList(&BundleCBList, LocalBundleCB);
return (NULL); } RecvDescHole->Flags = MULTILINK_HOLE_FLAG;
RecvInfo->RecvDescHole = RecvDescHole; InsertHeadList(&RecvInfo->AssemblyList, &RecvDescHole->Linkage); RecvInfo->AssemblyCount++; }
InitializeListHead(&LocalBundleCB->ProtocolCBList); NdisWanInitializeSyncEvent(&LocalBundleCB->OutstandingFramesEvent); LocalBundleCB->State = BUNDLE_UP; LocalBundleCB->FramingInfo.MaxRSendFrameSize = glMaxMTU; LocalBundleCB->FramingInfo.MaxRRecvFrameSize = glMRRU; LocalBundleCB->SFlowSpec.MaxSduSize = glMaxMTU; LocalBundleCB->RFlowSpec.MaxSduSize = glMRRU; NdisWanGetSystemTime(&LocalBundleCB->LastNonIdleData); LocalBundleCB->SendCompInfo.CompType = LocalBundleCB->RecvCompInfo.CompType = COMPTYPE_NONE;
//
// Add the protocolcb to the bundle's table and list
//
ProtocolCB->ProtocolType = PROTOCOL_PRIVATE_IO; ProtocolCB->PPPProtocolID = PPP_PROTOCOL_PRIVATE_IO; ProtocolCB->BundleCB = LocalBundleCB; ProtocolCB->State = PROTOCOL_ROUTED; NdisWanStringToNdisString(&ProtocolCB->InDeviceName, IOName); LocalBundleCB->IoProtocolCB = ProtocolCB;
return (LocalBundleCB); }
VOID NdisWanFreeBundleCB( IN PBUNDLECB BundleCB ) /*++
Routine Name:
Routine Description:
Arguments:
Return Values:
--*/ { UINT Class; PPROTOCOLCB IoProtocolCB; PPACKET_QUEUE PacketQueue;
FlushAssemblyLists(BundleCB);
if (BundleCB->Flags & BOND_ENABLED) { RemoveEntryGlobalList(BonDWorkList, &BundleCB->BonDLinkage); }
//
// Free the hole place holders
//
for (Class = 0; Class < MAX_MCML; Class++) { PBUNDLE_RECV_INFO RecvInfo = &BundleCB->RecvInfo[Class];
ASSERT(RecvInfo->RecvDescHole != NULL); NdisWanFreeRecvDesc(RecvInfo->RecvDescHole); RecvInfo->RecvDescHole = NULL; }
#if 0
KeCancelTimer(&BundleCB->BonDTimer); #endif
IoProtocolCB = BundleCB->IoProtocolCB; PacketQueue = &IoProtocolCB->PacketQueue[MAX_MCML];
ASSERT(IsPacketQueueEmpty(PacketQueue));
//
// If we have ppp packets queued we need
// to flush them and free the memory!
//
while (!IsPacketQueueEmpty(PacketQueue)) { PNDIS_PACKET Packet;
Packet = RemoveHeadPacketQueue(PacketQueue)
CompleteNdisPacket(IoProtocolCB->MiniportCB, IoProtocolCB, Packet); }
sl_compress_terminate(&BundleCB->VJCompress);
if (BundleCB->Flags & SEND_CCP_ALLOCATED) {
WanDeallocateCCP(BundleCB, &BundleCB->SendCompInfo, TRUE); BundleCB->Flags &= ~SEND_CCP_ALLOCATED; }
if (BundleCB->Flags & RECV_CCP_ALLOCATED) { WanDeallocateCCP(BundleCB, &BundleCB->RecvCompInfo, FALSE); BundleCB->Flags &= ~RECV_CCP_ALLOCATED; }
if (BundleCB->Flags & SEND_ECP_ALLOCATED) { WanDeallocateECP(BundleCB, &BundleCB->SendCompInfo, &BundleCB->SendCryptoInfo); BundleCB->Flags &= ~SEND_ECP_ALLOCATED; }
if (BundleCB->Flags & RECV_ECP_ALLOCATED) { WanDeallocateECP(BundleCB, &BundleCB->RecvCompInfo, &BundleCB->RecvCryptoInfo); BundleCB->Flags &= ~RECV_ECP_ALLOCATED; }
if (BundleCB->BonDAllocation != NULL) { NdisWanFreeMemory(BundleCB->BonDAllocation); BundleCB->BonDAllocation = NULL; }
BundleCB->State = BUNDLE_DOWN;
NdisFreeSpinLock(&BundleCB->Lock);
NdisWanFreeNdisString(&BundleCB->IoProtocolCB->InDeviceName);
NdisFreeToNPagedLookasideList(&BundleCBList, BundleCB); }
NDIS_STATUS NdisWanCreateProtocolInfoTable( VOID ) /*++
Routine Name:
Routine Description:
Arguments:
Return Values:
--*/ { NDIS_STATUS Status = NDIS_STATUS_SUCCESS; ULONG ulAllocationSize = 0; PUCHAR AllocatedMemory; PROTOCOL_INFO ProtocolInfo;
//
// Allocate ProtocolLookupTable. This table is used to match protocol values
// with their corresponding PPP Protocol values. The table size is set to
// MAX_PROTOCOLS.
//
ulAllocationSize = sizeof(PROTOCOL_INFO_TABLE) + (sizeof(PROTOCOL_INFO) * MAX_PROTOCOLS);
NdisWanAllocateMemory(&AllocatedMemory, ulAllocationSize, PROTOCOLTABLE_TAG);
if (AllocatedMemory == NULL) { NdisWanDbgOut(DBG_CRITICAL_ERROR, DBG_MEMORY, ("Failed allocating memory for ProtocolLookupTable! TableSize: %d", ulAllocationSize));
return (NDIS_STATUS_RESOURCES); }
ProtocolInfoTable = (PPROTOCOL_INFO_TABLE)AllocatedMemory;
//
// Save the allocation size
//
ProtocolInfoTable->ulAllocationSize = ulAllocationSize;
//
// Store the array size. This should be read from the registry
//
ProtocolInfoTable->ulArraySize = MAX_PROTOCOLS;
NdisAllocateSpinLock(&ProtocolInfoTable->Lock);
//
// Setup the pointer to the ProtocolValue array
//
AllocatedMemory += sizeof(PROTOCOL_INFO_TABLE); ProtocolInfoTable->ProtocolInfo = (PPROTOCOL_INFO)(AllocatedMemory);
//
// Insert default values for Netbuei, IP, IPX
//
ProtocolInfo.ProtocolType = PROTOCOL_PRIVATE_IO; ProtocolInfo.PPPId = PPP_PROTOCOL_PRIVATE_IO; ProtocolInfo.MTU = DEFAULT_MTU; ProtocolInfo.TunnelMTU = DEFAULT_MTU; ProtocolInfo.PacketQueueDepth = DEFAULT_PACKETQUEUE_DEPTH; ProtocolInfo.Flags = PROTOCOL_UNBOUND; SetProtocolInfo(&ProtocolInfo);
ProtocolInfo.ProtocolType = PROTOCOL_IP; ProtocolInfo.PPPId = PPP_PROTOCOL_IP; ProtocolInfo.MTU = DEFAULT_MTU; ProtocolInfo.TunnelMTU = DEFAULT_TUNNEL_MTU; ProtocolInfo.PacketQueueDepth = DEFAULT_PACKETQUEUE_DEPTH; ProtocolInfo.Flags = PROTOCOL_UNBOUND; SetProtocolInfo(&ProtocolInfo);
ProtocolInfo.ProtocolType = PROTOCOL_IPX; ProtocolInfo.PPPId = PPP_PROTOCOL_IPX; ProtocolInfo.MTU = DEFAULT_MTU; ProtocolInfo.TunnelMTU = DEFAULT_MTU; ProtocolInfo.PacketQueueDepth = DEFAULT_PACKETQUEUE_DEPTH; ProtocolInfo.Flags = PROTOCOL_UNBOUND; SetProtocolInfo(&ProtocolInfo);
ProtocolInfo.ProtocolType = PROTOCOL_NBF; ProtocolInfo.PPPId = PPP_PROTOCOL_NBF; ProtocolInfo.MTU = DEFAULT_MTU; ProtocolInfo.TunnelMTU = DEFAULT_MTU; ProtocolInfo.PacketQueueDepth = DEFAULT_PACKETQUEUE_DEPTH; ProtocolInfo.Flags = PROTOCOL_UNBOUND; SetProtocolInfo(&ProtocolInfo);
ProtocolInfo.ProtocolType = PROTOCOL_APPLETALK; ProtocolInfo.PPPId = PPP_PROTOCOL_APPLETALK; ProtocolInfo.MTU = DEFAULT_MTU; ProtocolInfo.TunnelMTU = DEFAULT_MTU; ProtocolInfo.PacketQueueDepth = DEFAULT_PACKETQUEUE_DEPTH; ProtocolInfo.Flags = PROTOCOL_UNBOUND; SetProtocolInfo(&ProtocolInfo);
return (Status);
}
VOID NdisWanDestroyProtocolInfoTable( VOID ) /*++
Routine Name:
Routine Description:
Arguments:
Return Values:
--*/ { NdisFreeSpinLock(&ProtocolInfoTable->Lock);
NdisWanFreeMemory(ProtocolInfoTable); }
NDIS_STATUS NdisWanCreateConnectionTable( ULONG TableSize ) /*++
Routine Name:
Routine Description:
Arguments:
Return Values:
--*/ { ULONG ulAllocationSize = 0; ULONG ulArraySize; PUCHAR AllocatedMemory; PCONNECTION_TABLE NewTable;
//
// Since we skip the first place in the tables we increase the
// size by one.
//
ulArraySize = TableSize + 1;
//
// Allocate the Bundle and Link Arrays based on the number of possible connections
// that we have in the system. This should be grown if we get called
// to reinitialize and gain new ports.
//
ulAllocationSize = sizeof(CONNECTION_TABLE) + (sizeof(PBUNDLECB) * ulArraySize) + (sizeof(PLINKCB) * ulArraySize);
NdisWanAllocateMemory(&AllocatedMemory, ulAllocationSize, CONNECTIONTABLE_TAG);
if (AllocatedMemory == NULL) {
NdisWanDbgOut(DBG_CRITICAL_ERROR, DBG_MEMORY, ("Failed allocating memory for ConnectionTable! Size: %d, Links: %d", ulAllocationSize, TableSize));
return (NDIS_STATUS_RESOURCES); }
NewTable = (PCONNECTION_TABLE)AllocatedMemory;
//
// This is the amount of memory we allocated
//
NewTable->ulAllocationSize = ulAllocationSize; NewTable->ulArraySize = TableSize; NewTable->ulNextLink = NewTable->ulNextBundle = 1; InitializeListHead(&NewTable->BundleList); InitializeListHead(&NewTable->LinkList);
//
// Setup pointer to the linkcb array
//
AllocatedMemory += sizeof(CONNECTION_TABLE); NewTable->LinkArray = (PLINKCB*)(AllocatedMemory); //
// Setup the pointer to the bundlecb array
//
AllocatedMemory += (sizeof(PLINKCB) * ulArraySize); NewTable->BundleArray = (PBUNDLECB*)(AllocatedMemory);
if (ConnectionTable != NULL) { PCONNECTION_TABLE FreeTable;
//
// We must be growing the table. This will be
// called with the current connectiontable lock
// held!
//
NewTable->ulNumActiveLinks = ConnectionTable->ulNumActiveLinks; NewTable->ulNumActiveBundles = ConnectionTable->ulNumActiveBundles; NewTable->ulNextLink = ConnectionTable->ulNextLink; NewTable->ulNextBundle = ConnectionTable->ulNextBundle;
NdisMoveMemory((PUCHAR)NewTable->LinkArray, (PUCHAR)ConnectionTable->LinkArray, ConnectionTable->ulArraySize * sizeof(PLINKCB));
NdisMoveMemory((PUCHAR)NewTable->BundleArray, (PUCHAR)ConnectionTable->BundleArray, ConnectionTable->ulArraySize * sizeof(PBUNDLECB));
while (!IsListEmpty(&ConnectionTable->BundleList)) { PBUNDLECB BundleCB;
BundleCB = (PBUNDLECB)RemoveHeadList(&ConnectionTable->BundleList); InsertTailList(&NewTable->BundleList, &BundleCB->Linkage); }
while (!IsListEmpty(&ConnectionTable->LinkList)) { PLIST_ENTRY Entry; PLINKCB LinkCB;
Entry = RemoveHeadList(&ConnectionTable->LinkList); LinkCB = (PLINKCB)CONTAINING_RECORD(Entry, LINKCB, ConnTableLinkage); InsertTailList(&NewTable->LinkList, &LinkCB->ConnTableLinkage);
}
FreeTable = ConnectionTable; ConnectionTable = NewTable;
//
// Destroy the old table
//
NdisWanFreeMemory(FreeTable);
} else { ConnectionTable = NewTable; }
return (NDIS_STATUS_SUCCESS); }
PNDIS_PACKET NdisWanAllocateNdisPacket( ULONG MagicNumber ) { PNDIS_PACKET ReturnPacket = NULL; PPOOL_DESC PoolDesc; NDIS_STATUS Status = NDIS_STATUS_FAILURE; ULONG i; PSINGLE_LIST_ENTRY p = NULL; PNDISWAN_PROTOCOL_RESERVED pres;
NdisAcquireSpinLock(&PacketPoolList.Lock);
//
// Walk the pool desc list and try to allocate a packet
//
PoolDesc = (PPOOL_DESC)PacketPoolList.List.Flink;
while (PoolDesc != (PPOOL_DESC)&PacketPoolList.List) {
p = PopEntryList(&PoolDesc->Head);
if (p != NULL) { break; } PoolDesc = (PPOOL_DESC)PoolDesc->Linkage.Flink; }
if (p == NULL) { //
// We have walked the pool list and did not find any
// free packets on any of the free pools, so allocate
// a new pool and get a packet from it.
//
NdisWanAllocatePriorityMemory(&PoolDesc, sizeof(POOL_DESC), POOLDESC_TAG, NormalPoolPriority);
if (PoolDesc == NULL) { NdisReleaseSpinLock(&PacketPoolList.Lock); return (NULL); }
NdisAllocatePacketPoolEx(&Status, &PoolDesc->PoolHandle, glPacketPoolCount, 0, sizeof(NDISWAN_PROTOCOL_RESERVED));
if (Status != NDIS_STATUS_SUCCESS) { NdisWanFreeMemory(PoolDesc); NdisReleaseSpinLock(&PacketPoolList.Lock); return (NULL); }
for (i = 0; i < glPacketPoolCount; i++) { PNDIS_PACKET np;
NdisAllocatePacket(&Status, &np, PoolDesc->PoolHandle);
ASSERT(np != NULL);
pres = PPROTOCOL_RESERVED_FROM_NDIS(np);
PushEntryList(&PoolDesc->Head, &pres->SLink);
PoolDesc->FreeCount++; }
InsertTailList(&PacketPoolList.List, &PoolDesc->Linkage);
PacketPoolList.TotalDescCount++; PacketPoolList.FreeCount += PoolDesc->FreeCount;
if (PacketPoolList.TotalDescCount > PacketPoolList.MaxDescCount) { PacketPoolList.MaxDescCount = PacketPoolList.TotalDescCount; }
p = PopEntryList(&PoolDesc->Head); }
ASSERT(p != NULL);
pres = CONTAINING_RECORD(p, NDISWAN_PROTOCOL_RESERVED, SLink); ReturnPacket = CONTAINING_RECORD(pres, NDIS_PACKET, ProtocolReserved);
NdisReinitializePacket(ReturnPacket);
PoolDesc->AllocatedCount++; PoolDesc->FreeCount--; ASSERT((PoolDesc->AllocatedCount + PoolDesc->FreeCount) == glPacketPoolCount);
if (PoolDesc->AllocatedCount > PoolDesc->MaxAllocatedCount) {
PoolDesc->MaxAllocatedCount = PoolDesc->AllocatedCount; }
PacketPoolList.AllocatedCount++; PacketPoolList.FreeCount--;
#if DBG
{ PPOOL_DESC pdesc; ULONG FreeCount, AllocatedCount;
pdesc = (PPOOL_DESC)PacketPoolList.List.Flink;
FreeCount = AllocatedCount = 0;
while ((PVOID)pdesc != (PVOID)&PacketPoolList.List) { FreeCount += pdesc->FreeCount; AllocatedCount += pdesc->AllocatedCount; pdesc = (PPOOL_DESC)pdesc->Linkage.Flink; }
if (PacketPoolList.AllocatedCount != AllocatedCount || PacketPoolList.FreeCount != FreeCount){ DbgPrint("NDISWAN: AllocatePacket - PacketPool counts out of sync!\n"); DbgBreakPoint(); }
#if 0
if (PacketPoolList.AllocatedCount > 200) { DbgPrint("NDISWAN: AllocatePacket - Over 200 outstanding packets!\n"); DbgBreakPoint(); } #endif
} #endif
if (PacketPoolList.AllocatedCount > PacketPoolList.MaxAllocatedCount) {
PacketPoolList.MaxAllocatedCount = PacketPoolList.AllocatedCount; } pres->MagicNumber = MagicNumber; pres->PoolDesc = PoolDesc;
NDIS_SET_PACKET_HEADER_SIZE(ReturnPacket, MAC_HEADER_LENGTH);
NDIS_SET_PACKET_STATUS(ReturnPacket, NDIS_STATUS_SUCCESS);
NdisReleaseSpinLock(&PacketPoolList.Lock);
return (ReturnPacket); }
VOID NdisWanFreeNdisPacket( PNDIS_PACKET NdisPacket ) { PNDISWAN_PROTOCOL_RESERVED pres; PPOOL_DESC PoolDesc; PNDIS_BUFFER NdisBuffer; PUCHAR DataBuffer;
pres = PPROTOCOL_RESERVED_FROM_NDIS(NdisPacket);
ASSERT(pres->MagicNumber == MAGIC_INTERNAL_ALLOC || pres->MagicNumber == MAGIC_INTERNAL_IO || pres->MagicNumber == MAGIC_INTERNAL_SEND || pres->MagicNumber == MAGIC_INTERNAL_RECV || pres->MagicNumber == MAGIC_INTERNAL_ALLOC);
PoolDesc = pres->PoolDesc;
NdisAcquireSpinLock(&PacketPoolList.Lock);
#if DBG
{ PPOOL_DESC pdesc;
pdesc = (PPOOL_DESC)PacketPoolList.List.Flink;
while ((PVOID)pdesc != (PVOID)&PacketPoolList.List) {
if (PoolDesc == pdesc) { //
// We found the correct pool
//
break; }
pdesc = (PPOOL_DESC)pdesc->Linkage.Flink; }
if((PVOID)PoolDesc == (PVOID)&PacketPoolList.List){ DbgPrint("NDISWAN: FreePacket PoolDesc %x not on PacketPoolList!\n", PoolDesc); DbgBreakPoint(); } } #endif
PushEntryList(&PoolDesc->Head, &pres->SLink);
PoolDesc->AllocatedCount--; PoolDesc->FreeCount++;
ASSERT((PoolDesc->AllocatedCount + PoolDesc->FreeCount) == glPacketPoolCount);
PacketPoolList.AllocatedCount--; PacketPoolList.FreeCount++;
#if DBG
{ PPOOL_DESC pdesc; ULONG FreeCount, AllocatedCount;
pdesc = (PPOOL_DESC)PacketPoolList.List.Flink;
FreeCount = AllocatedCount = 0;
while ((PVOID)pdesc != (PVOID)&PacketPoolList.List) { FreeCount += pdesc->FreeCount; AllocatedCount += pdesc->AllocatedCount;
pdesc = (PPOOL_DESC)pdesc->Linkage.Flink; }
if (PacketPoolList.AllocatedCount != AllocatedCount || PacketPoolList.FreeCount != FreeCount){ DbgPrint("NDISWAN: FreePacket - PacketPool counts out of sync!\n"); DbgBreakPoint(); } } #endif
//
// If all of the packets have been returned to this pool desc
// and this is not the only pool desc then free it!
//
if (PoolDesc->AllocatedCount == 0 && PacketPoolList.TotalDescCount > 1 && PacketPoolList.FreeCount > PoolDesc->FreeCount) { PSINGLE_LIST_ENTRY p = NULL;
RemoveEntryList(&PoolDesc->Linkage);
PacketPoolList.TotalDescCount--; PacketPoolList.FreeCount -= PoolDesc->FreeCount;
p = PopEntryList(&PoolDesc->Head);
while (p != NULL) { PNDIS_PACKET ReturnPacket;
pres = CONTAINING_RECORD(p, NDISWAN_PROTOCOL_RESERVED, SLink); ReturnPacket = CONTAINING_RECORD(pres, NDIS_PACKET, ProtocolReserved);
NdisFreePacket(ReturnPacket);
p = PopEntryList(&PoolDesc->Head); }
NdisFreePacketPool(PoolDesc->PoolHandle); NdisWanFreeMemory(PoolDesc); }
NdisReleaseSpinLock(&PacketPoolList.Lock); }
PVOID AllocateDataDesc( POOL_TYPE PoolType, SIZE_T NumberOfBytes, ULONG Tag ) /*++
Routine Name:
AllocateDataDesc
Routine Description:
This routine is called by the lookasidelist manager if there are not any descriptors available. It will allocated memory for: DATA_DESC, NDIS_BUFFER, NDIS_PACKET, and a block of memory of size. Arguments:
Return Values:
--*/ { PDATA_DESC DataDesc; PUCHAR DataBuffer; NDIS_STATUS Status;
NdisWanAllocatePriorityMemory(&DataDesc, NumberOfBytes, Tag, NormalPoolPriority);
if (DataDesc == NULL) { NdisWanDbgOut(DBG_CRITICAL_ERROR, DBG_MEMORY, ("AllocateDataDesc failed! Size %d", NumberOfBytes)); return (NULL); }
DataBuffer = ((PUCHAR)(DataDesc + 1) + sizeof(PVOID)); (ULONG_PTR)DataBuffer &= ~((ULONG_PTR)sizeof(PVOID) - 1);
DataDesc->DataBuffer = DataBuffer;
DataDesc->DataBufferLength = (ULONG)(((PUCHAR)DataDesc + NumberOfBytes) - DataBuffer);
// This is not portable to Win95! I need to allocate a buffer
// pool and use a valid handle.
//
NdisAllocateBuffer(&Status, &DataDesc->NdisBuffer, NULL, DataDesc->DataBuffer, DataDesc->DataBufferLength);
if (Status != NDIS_STATUS_SUCCESS) {
NdisWanFreeMemory(DataDesc);
NdisWanDbgOut(DBG_CRITICAL_ERROR, DBG_MEMORY, ("NdisAllocateBuffer failed! DataBufferSize %d", DataDesc->DataBufferLength)); return (NULL); }
DataDesc->NdisPacket = NdisWanAllocateNdisPacket(MAGIC_INTERNAL_ALLOC);
if (DataDesc->NdisPacket == NULL) {
NdisFreeBuffer(DataDesc->NdisBuffer);
NdisWanFreeMemory(DataDesc);
NdisWanDbgOut(DBG_CRITICAL_ERROR, DBG_MEMORY, ("NdisWanAllocateNdisPacket failed! DataBufferSize %d"));
return (NULL); }
NdisChainBufferAtFront(DataDesc->NdisPacket, DataDesc->NdisBuffer);
return(DataDesc); }
VOID FreeDataDesc( PVOID Buffer ) /*++
Routine Name:
Routine Description:
Arguments:
Return Values:
--*/ { PDATA_DESC DataDesc;
DataDesc = (PDATA_DESC)Buffer;
NdisReinitializePacket(DataDesc->NdisPacket);
NdisWanFreeNdisPacket(DataDesc->NdisPacket);
NdisFreeBuffer(DataDesc->NdisBuffer);
NdisWanFreeMemory(Buffer); }
PRECV_DESC NdisWanAllocateRecvDesc( ULONG SizeNeeded ) /*++
Routine Name:
Routine Description:
Arguments:
Return Values:
--*/ { PDATA_DESC DataDesc; PRECV_DESC RecvDesc; ULONG Length; PNPAGED_LOOKASIDE_LIST LookasideList;
if (SizeNeeded > glLargeDataBufferSize) { DbgPrint("NDISWAN: Error Allocating RecvDesc Size %d\n", SizeNeeded); return (NULL); } else if (SizeNeeded > glSmallDataBufferSize) { LookasideList = &LargeDataDescList; } else { LookasideList = &SmallDataDescList; }
DataDesc = NdisAllocateFromNPagedLookasideList(LookasideList);
if (DataDesc == NULL) { return (NULL); }
PPROTOCOL_RESERVED_FROM_NDIS(DataDesc->NdisPacket)->MagicNumber = MAGIC_INTERNAL_RECV;
DataDesc->LookasideList = LookasideList; RecvDesc = &DataDesc->RecvDesc;
NdisZeroMemory(RecvDesc, sizeof(RECV_DESC));
RecvDesc->Signature = RECVDESC_SIG; RecvDesc->DataBuffer = DataDesc->DataBuffer; RecvDesc->NdisBuffer = DataDesc->NdisBuffer; RecvDesc->NdisPacket = DataDesc->NdisPacket;
NdisQueryBuffer(RecvDesc->NdisBuffer, &RecvDesc->StartBuffer, &Length);
RecvDesc->CurrentBuffer = RecvDesc->StartBuffer + MAC_HEADER_LENGTH + PROTOCOL_HEADER_LENGTH;
return (RecvDesc); }
VOID NdisWanFreeRecvDesc( PRECV_DESC RecvDesc ) /*++
Routine Name:
Routine Description:
Arguments:
Return Values:
--*/ { PDATA_DESC DataDesc; PNDIS_BUFFER NdisBuffer; PNDIS_PACKET NdisPacket; PNPAGED_LOOKASIDE_LIST LookasideList;
if (RecvDesc->OriginalPacket != NULL) {
NdisReturnPackets(&RecvDesc->OriginalPacket, 1); RecvDesc->OriginalPacket = NULL; }
DataDesc = CONTAINING_RECORD(RecvDesc, DATA_DESC, RecvDesc);
NdisBuffer = DataDesc->NdisBuffer;
NdisPacket = DataDesc->NdisPacket;
LookasideList = DataDesc->LookasideList;
#if DBG
{ ULONG BufferCount;
NdisQueryPacket(NdisPacket, NULL, &BufferCount, NULL, NULL);
ASSERT(BufferCount == 1); } #endif
NdisAdjustBufferLength(NdisBuffer, DataDesc->DataBufferLength);
NdisRecalculatePacketCounts(NdisPacket);
NDIS_SET_PACKET_HEADER_SIZE(NdisPacket, MAC_HEADER_LENGTH);
NDIS_SET_PACKET_STATUS(NdisPacket, NDIS_STATUS_SUCCESS);
ASSERT(PPROTOCOL_RESERVED_FROM_NDIS(NdisPacket)->MagicNumber == MAGIC_INTERNAL_RECV);
NdisFreeToNPagedLookasideList(LookasideList, DataDesc); }
PSEND_DESC NdisWanAllocateSendDesc( PLINKCB LinkCB, ULONG SizeNeeded ) /*++
Routine Name:
Routine Description:
Arguments:
Return Values:
--*/ { POPENCB OpenCB; PSEND_DESC SendDesc;
//
// Need to determine if this link represents a legacy
// wan miniport or a NDIS 5.0 miniport and get the
// appropriate buffer descriptor.
//
OpenCB = LinkCB->OpenCB;
if (OpenCB->Flags & OPEN_LEGACY) { PDATA_DESC DataDesc; PNDIS_WAN_PACKET WanPacket;
//
// Get a buffer desriptor off of the open block
//
if (OpenCB->WanInfo.MemoryFlags == 0) { PNPAGED_LOOKASIDE_LIST LookasideList;
LookasideList = &OpenCB->WanPacketPool; DataDesc = NdisAllocateFromNPagedLookasideList(LookasideList);
if (DataDesc == NULL) { return(NULL); }
DataDesc->LookasideList = LookasideList;
WanPacket = (PNDIS_WAN_PACKET) ((PUCHAR)(DataDesc + 1) + sizeof(PVOID));
(ULONG_PTR)WanPacket &= ~((ULONG_PTR)sizeof(PVOID) - 1);
//
// Point to the begining of the data.
//
WanPacket->StartBuffer = ((PUCHAR)(WanPacket + 1) + sizeof(PVOID));
(ULONG_PTR)WanPacket->StartBuffer &= ~((ULONG_PTR)sizeof(PVOID) - 1);
WanPacket->EndBuffer = WanPacket->StartBuffer + OpenCB->BufferSize - sizeof(PVOID); } else { DataDesc = (PDATA_DESC) NdisInterlockedPopEntrySList(&OpenCB->WanPacketList, &OpenCB->Lock); if (DataDesc == NULL) { return (NULL); } }
SendDesc = &DataDesc->SendDesc; NdisZeroMemory(SendDesc, sizeof(SEND_DESC));
SendDesc->Signature = SENDESC_SIG; SendDesc->LinkCB = LinkCB; SendDesc->WanPacket = WanPacket;
WanPacket->CurrentBuffer = WanPacket->StartBuffer + OpenCB->WanInfo.HeaderPadding;
SendDesc->StartBuffer = WanPacket->CurrentBuffer;
} else { PDATA_DESC DataDesc; ULONG Length; PNPAGED_LOOKASIDE_LIST LookasideList;
if (SizeNeeded > glLargeDataBufferSize) { DbgPrint("NDISWAN: Error Allocating SendDesc Size %d\n", SizeNeeded); return (NULL); } else if (SizeNeeded > glSmallDataBufferSize) { LookasideList = &LargeDataDescList; } else { LookasideList = &SmallDataDescList; }
DataDesc = NdisAllocateFromNPagedLookasideList(LookasideList);
if (DataDesc == NULL) { return (NULL); }
DataDesc->LookasideList = LookasideList;
PPROTOCOL_RESERVED_FROM_NDIS(DataDesc->NdisPacket)->MagicNumber = MAGIC_INTERNAL_SEND;
SendDesc = &DataDesc->SendDesc; NdisZeroMemory(SendDesc, sizeof(SEND_DESC));
SendDesc->Signature = SENDESC_SIG; SendDesc->LinkCB = LinkCB; SendDesc->NdisPacket = DataDesc->NdisPacket; SendDesc->NdisBuffer = DataDesc->NdisBuffer;
NdisQueryBuffer(SendDesc->NdisBuffer, &SendDesc->StartBuffer, &Length); }
LinkCB->SendResources -= 1; LinkCB->BundleCB->SendResources -= 1;
return (SendDesc); }
VOID NdisWanFreeSendDesc( PSEND_DESC SendDesc ) /*++
Routine Name:
Routine Description:
Arguments:
Return Values:
--*/ { POPENCB OpenCB; PDATA_DESC DataDesc; PLINKCB LinkCB; PNPAGED_LOOKASIDE_LIST LookasideList;
LinkCB = SendDesc->LinkCB;
OpenCB = LinkCB->OpenCB;
DataDesc = CONTAINING_RECORD(SendDesc, DATA_DESC, SendDesc);
LookasideList = DataDesc->LookasideList;
if (OpenCB->Flags & OPEN_LEGACY) {
if (OpenCB->WanInfo.MemoryFlags == 0) {
NdisFreeToNPagedLookasideList(LookasideList, DataDesc);
} else {
NdisInterlockedPushEntrySList(&OpenCB->WanPacketList, (PSLIST_ENTRY)DataDesc, &OpenCB->Lock); }
} else { PNDIS_BUFFER NdisBuffer; PNDIS_PACKET NdisPacket;
NdisBuffer = DataDesc->NdisBuffer;
NdisPacket = DataDesc->NdisPacket;
#if DBG
{ ULONG BufferCount;
NdisQueryPacket(NdisPacket, NULL, &BufferCount, NULL, NULL);
ASSERT(BufferCount == 1); } #endif
NdisAdjustBufferLength(NdisBuffer, DataDesc->DataBufferLength);
NdisRecalculatePacketCounts(NdisPacket);
NDIS_SET_PACKET_HEADER_SIZE(NdisPacket, MAC_HEADER_LENGTH);
NDIS_SET_PACKET_STATUS(NdisPacket, NDIS_STATUS_SUCCESS);
ASSERT(PPROTOCOL_RESERVED_FROM_NDIS(NdisPacket)->MagicNumber == MAGIC_INTERNAL_SEND);
NdisFreeToNPagedLookasideList(LookasideList, DataDesc); }
LinkCB->SendResources += 1; LinkCB->BundleCB->SendResources += 1; }
PCL_AFSAPCB NdisWanAllocateClAfSapCB( POPENCB OpenCB, PCO_ADDRESS_FAMILY AddressFamily ) { PCL_AFSAPCB AfSapCB;
AfSapCB = NdisAllocateFromNPagedLookasideList(&AfSapVcCBList);
if (AfSapCB == NULL) { return (NULL); }
NdisZeroMemory(AfSapCB, sizeof(CL_AFSAPCB));
AfSapCB->Signature = CLAFSAP_SIG; AfSapCB->OpenCB = OpenCB;
AfSapCB->Af.AddressFamily = AddressFamily->AddressFamily; AfSapCB->Af.MajorVersion = AddressFamily->MajorVersion; AfSapCB->Af.MinorVersion = AddressFamily->MinorVersion;
AfSapCB->RefCount = 1; AfSapCB->Flags = AF_OPENING;
return (AfSapCB); }
VOID NdisWanFreeClAfSapCB( PCL_AFSAPCB AfSapCB ) { NdisFreeToNPagedLookasideList(&AfSapVcCBList, AfSapCB); }
PCM_AFSAPCB NdisWanAllocateCmAfSapCB( PMINIPORTCB MiniportCB ) { PCM_AFSAPCB AfSapCB;
AfSapCB = NdisAllocateFromNPagedLookasideList(&AfSapVcCBList);
if (AfSapCB == NULL) { return (NULL); }
NdisZeroMemory(AfSapCB, sizeof(CM_AFSAPCB));
AfSapCB->Signature = CMAFSAP_SIG; AfSapCB->MiniportCB = MiniportCB;
REF_MINIPORTCB(MiniportCB);
NdisAcquireSpinLock(&MiniportCB->Lock);
InsertHeadList(&MiniportCB->AfSapCBList, &AfSapCB->Linkage);
NdisWanInitializeNotificationEvent(&AfSapCB->NotificationEvent);
NdisWanInterlockedInc(&MiniportCB->AfRefCount);
NdisReleaseSpinLock(&MiniportCB->Lock);
return (AfSapCB); }
VOID NdisWanFreeCmAfSapCB( PCM_AFSAPCB AfSapCB ) { PMINIPORTCB MiniportCB = AfSapCB->MiniportCB;
NdisAcquireSpinLock(&MiniportCB->Lock);
NdisWanInterlockedDec(&MiniportCB->AfRefCount);
RemoveEntryList(&AfSapCB->Linkage);
NdisReleaseSpinLock(&MiniportCB->Lock);
DEREF_MINIPORTCB(MiniportCB);
NdisFreeToNPagedLookasideList(&AfSapVcCBList, AfSapCB); }
PCM_VCCB NdisWanAllocateCmVcCB( PCM_AFSAPCB AfSapCB, NDIS_HANDLE NdisVcHandle ) { PCM_VCCB CmVcCB;
CmVcCB = NdisAllocateFromNPagedLookasideList(&AfSapVcCBList);
if (CmVcCB == NULL) { return (NULL); }
NdisZeroMemory(CmVcCB, sizeof(CM_VCCB));
CmVcCB->AfSapCB = AfSapCB; CmVcCB->Signature = CMVC_SIG; CmVcCB->NdisVcHandle = NdisVcHandle;
return (CmVcCB); }
VOID NdisWanFreeCmVcCB( PCM_VCCB CmVcCB ) { NdisFreeToNPagedLookasideList(&AfSapVcCBList, CmVcCB); }
NDIS_STATUS AllocateIoNdisPacket( ULONG SizeNeeded, PNDIS_PACKET *NdisPacket, PNDIS_BUFFER *NdisBuffer, PUCHAR *DataBuffer ) /*++
Routine Name: AllocateIoNdisPacket Routine Description:
This routine will alocate a packet used to send a PPP control packet over a wan endpoint. The routine is written with the assumption that there will only ever be a single NDIS_BUFFER attached to the packet. This buffer is attached immediately to the front of the packet. Before calling a miniport the NDIS_BUFFER must have it's length adjusted and the packet must recalculate all counts.
Arguments:
Return Values:
--*/ { PDATA_DESC DataDesc; ULONG Length; PNPAGED_LOOKASIDE_LIST LookasideList;
if (SizeNeeded > glLargeDataBufferSize) {
DbgPrint("NDISWAN: Error Allocating IoNdisPacket Size %d\n", SizeNeeded); return (NDIS_STATUS_FAILURE); } else if (SizeNeeded > glSmallDataBufferSize) { LookasideList = &LargeDataDescList; } else { LookasideList = &SmallDataDescList; }
DataDesc = NdisAllocateFromNPagedLookasideList(LookasideList);
if (DataDesc == NULL) { return (NDIS_STATUS_RESOURCES); }
DataDesc->LookasideList = LookasideList;
*NdisPacket = DataDesc->NdisPacket;
PPROTOCOL_RESERVED_FROM_NDIS(DataDesc->NdisPacket)->MagicNumber = MAGIC_INTERNAL_IO;
PPROTOCOL_RESERVED_FROM_NDIS(DataDesc->NdisPacket)->DataDesc = DataDesc;
*NdisBuffer = DataDesc->NdisBuffer;
NdisQueryBuffer(DataDesc->NdisBuffer, &DataDesc->DataBuffer, &Length); *DataBuffer = DataDesc->DataBuffer;
return (NDIS_STATUS_SUCCESS); }
VOID FreeIoNdisPacket( PNDIS_PACKET NdisPacket ) /*++
Routine Name:
FreeIoNdisPacket Routine Description:
This routine will free a packet used to send a PPP control packet over a wan endpoint. The routine is written with the assumption that there will only ever be a single NDIS_BUFFER attached to the packet. This buffer does not have to be explicitly removed from the packet here as a pointer to it is stored in the DATA_DESC itself and will be freed when the DATA_DESC is freed.
Arguments:
Return Values:
--*/ { PDATA_DESC DataDesc; PNDIS_BUFFER NdisBuffer; PNPAGED_LOOKASIDE_LIST LookasideList;
DataDesc = PPROTOCOL_RESERVED_FROM_NDIS(NdisPacket)->DataDesc;
ASSERT(PPROTOCOL_RESERVED_FROM_NDIS(NdisPacket)->MagicNumber == MAGIC_INTERNAL_IO);
LookasideList = DataDesc->LookasideList;
NdisAdjustBufferLength(DataDesc->NdisBuffer, DataDesc->DataBufferLength);
NdisRecalculatePacketCounts(NdisPacket);
NDIS_SET_PACKET_HEADER_SIZE(NdisPacket, MAC_HEADER_LENGTH);
NDIS_SET_PACKET_STATUS(NdisPacket, NDIS_STATUS_SUCCESS);
NdisFreeToNPagedLookasideList(LookasideList, DataDesc); }
PVOID AllocateWanPacket( IN POOL_TYPE PoolType, IN SIZE_T NumberOfBytes, IN ULONG Tag ) { PVOID pMem;
NdisWanAllocatePriorityMemory(&pMem, NumberOfBytes, Tag, NormalPoolPriority);
return(pMem); }
VOID FreeWanPacket( PVOID WanPacket ) { NdisWanFreeMemory(WanPacket); }
|