/*++
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"
#include "tcpip.h"
#include "vjslip.h"
//
// Local function prototypes
//
NDIS_STATUS
NdisWanCreateLinkCB(
OUT PLINKCB *LinkCB
);
VOID
NdisWanInitLinkCB(
IN PLINKCB *LinkCB,
IN PWAN_ADAPTERCB WanAdapterCB,
IN ULONG SendWindow
);
VOID
NdisWanDestroyLinkCB(
IN PLINKCB LinkCB
);
NDIS_STATUS
NdisWanCreateBundleCB(
OUT PBUNDLECB *BundleCB
);
VOID
NdisWanInitBundleCB(
IN PBUNDLECB BundleCB
);
VOID
NdisWanDestroyBundleCB(
IN PBUNDLECB BundleCB
);
NDIS_STATUS
NdisWanCreateProtocolCB(
OUT PPROTOCOLCB *ProtocolCB,
IN USHORT usProtocolType,
IN USHORT usBindingNameLength,
IN PWSTR BindingName,
IN ULONG ulBufferLength,
IN PUCHAR Buffer
);
//VOID
//NdisWanInitProtocolCB(
// IN PPROTOCOLCB ProtocolCB,
// IN ULONG ulBufferLength,
// IN PUCHAR Buffer,
// IN USHORT usProtocolType
// );
VOID
NdisWanDestroyProtocolCB(
IN PPROTOCOLCB ProtocolCB
);
NDIS_STATUS
NdisWanAllocateSendResources(
IN PLINKCB LinkCB,
IN ULONG SendWindow
);
VOID
NdisWanFreeSendResources(
IN PLINKCB LinkCB
);
//
// End local function prototypes
//
NDIS_STATUS
NdisWanCreateAdapterCB(
OUT PADAPTERCB *pAdapterCB,
IN PNDIS_STRING AdapterName
)
/*++
Routine Name:
NdisWanCreateAdapterCB
Routine Description:
This routine creates and initializes an AdapterCB
Arguments:
pAdapterCB - Pointer to a pointer to the AdapterCB that was created
Return Values:
NDIS_STATUS_SUCCESS
NDIS_STATUS_RESOURCES
--*/
{
PADAPTERCB LocalAdapterCB;
ULONG ulAllocationSize, i;
PDEFERRED_DESC FreeDesc;
NdisWanDbgOut(DBG_TRACE, DBG_MEMORY, ("NdisWanCreateAdapterCB: Enter"));
//
// Allocate and zero out the memory block
//
ulAllocationSize = sizeof(ADAPTERCB) + 20*sizeof(DEFERRED_DESC);
NdisWanAllocateMemory(&LocalAdapterCB, ulAllocationSize);
if (LocalAdapterCB == NULL) {
return (NDIS_STATUS_RESOURCES);
}
//
// setup the new control block
//
LocalAdapterCB->ulAllocationSize = ulAllocationSize;
NdisAllocateSpinLock(&LocalAdapterCB->Lock);
#ifdef MINIPORT_NAME
// NdisWanStringToNdisString(&LocalAdapterCB->AdapterName, AdapterName->Buffer);
NdisWanAllocateAdapterName(&LocalAdapterCB->AdapterName, AdapterName);
#endif
//
// Setup free deferred desc list
//
FreeDesc = (PDEFERRED_DESC)((PUCHAR)LocalAdapterCB + sizeof(ADAPTERCB));
for (i = 0; i < 20; i++) {
InsertHeadDeferredQueue(&LocalAdapterCB->FreeDeferredQueue, FreeDesc);
(PUCHAR)FreeDesc += sizeof(DEFERRED_DESC);
}
#if DBG
InitializeListHead(&LocalAdapterCB->DbgNdisPacketList);
#endif
//
// Add to global list
//
InsertTailGlobalList(AdapterCBList, &(LocalAdapterCB->Linkage));
*pAdapterCB = LocalAdapterCB;
NdisWanDbgOut(DBG_TRACE, DBG_MEMORY, ("%ls AdapterCB: 0x%x, Number: %d",
LocalAdapterCB->AdapterName.Buffer, *pAdapterCB, AdapterCBList.ulCount));
NdisWanDbgOut(DBG_TRACE, DBG_MEMORY, ("NdisWanCreateAdapterCB: Exit"));
return (NDIS_STATUS_SUCCESS);
}
VOID
NdisWanDestroyAdapterCB(
IN PADAPTERCB pAdapterCB
)
/*++
Routine Name:
NdisWanDestroyAdapterCB
Routine Description:
This destroys an AdapterCB
Arguments:
pAdapterCB - Pointer to to the AdapterCB that is being destroyed
Return Values:
None
--*/
{
NdisWanDbgOut(DBG_TRACE, DBG_MEMORY, ("NdisWanDestroyAdapterCB: Enter"));
NdisWanDbgOut(DBG_TRACE, DBG_MEMORY, ("AdapterCB: 0x%x", pAdapterCB));
#ifdef MINIPORT_NAME
NdisWanFreeNdisString(&pAdapterCB->AdapterName);
#endif
NdisFreeSpinLock(&pAdapterCB->Lock);
NdisWanFreeMemory(pAdapterCB);
NdisWanDbgOut(DBG_TRACE, DBG_MEMORY, ("NdisWanDestroyAdapterCB: Exit"));
}
NDIS_STATUS
NdisWanCreateWanAdapterCB(
IN PWSTR BindName
)
/*++
Routine Name:
NdisWanCreateWanAdapterCB
Routine Description:
This routine creates and initializes a WanAdapterCB
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:
NDIS_STATUS_SUCCESS
NDIS_STATUS_RESOURCES
--*/
{
PWAN_ADAPTERCB pWanAdapterCB;
ULONG ulAllocationSize;
NdisWanDbgOut(DBG_TRACE, DBG_MEMORY, ("NdisWanCreateWanAdapterCB: Enter"));
NdisWanDbgOut(DBG_TRACE, DBG_MEMORY, ("BindName: %ls", BindName));
//
// Allocate memory for WanAdapterCB
//
ulAllocationSize = sizeof(WAN_ADAPTERCB);
NdisWanAllocateMemory(&pWanAdapterCB, ulAllocationSize);
if (pWanAdapterCB == NULL) {
return (NDIS_STATUS_RESOURCES);
}
//
// Init WanAdapterCB
//
//
// Setup new control block
//
pWanAdapterCB->ulAllocationSize = ulAllocationSize;
NdisWanStringToNdisString(&(pWanAdapterCB->MiniportName), BindName);
NdisAllocateSpinLock(&pWanAdapterCB->Lock);
InitializeListHead(&pWanAdapterCB->FreeLinkCBList);
#if DBG
InitializeListHead(&pWanAdapterCB->DbgWanPacketList);
#endif
//
// Put WanAdapterCB on global list
//
InsertTailGlobalList(WanAdapterCBList, &(pWanAdapterCB->Linkage));
NdisWanDbgOut(DBG_TRACE, DBG_MEMORY, ("WanMiniport %ls WanAdapterCB: 0x%x",
pWanAdapterCB->MiniportName.Buffer, pWanAdapterCB));
NdisWanDbgOut(DBG_TRACE, DBG_MEMORY, ("NdisWanCreateWanAdapterCB: Exit"));
return(NDIS_STATUS_SUCCESS);
}
VOID
NdisWanDestroyWanAdapterCB(
IN PWAN_ADAPTERCB pWanAdapterCB
)
/*++
Routine Name:
NdisWanDestroyWanAdapterCB
Routine Description:
This routine destroys a WanAdapterCB
Arguments:
pWanAdapterCB - Pointer to the WanAdapterCB that is being destroyed
Return Values:
None
--*/
{
NdisWanDbgOut(DBG_TRACE, DBG_MEMORY, ("NdisWanDestroyWanAdapterCB: Enter - WanAdapterCB: 0x%4.4x", pWanAdapterCB));
//
// Free the memory allocated for the NDIS_STRING
//
NdisWanFreeNdisString(&pWanAdapterCB->MiniportName);
NdisFreeSpinLock(&pWanAdapter->Lock);
//
// Free the memory allocated for the control block
//
NdisWanFreeMemory(pWanAdapterCB);
NdisWanDbgOut(DBG_TRACE, DBG_MEMORY, ("NdisWanDestroyWanAdapterCB: Exit"));
}
VOID
NdisWanGetProtocolCB(
OUT PPROTOCOLCB *ProtocolCB,
IN USHORT usProtocolType,
IN USHORT usBindingNameLength,
IN PWSTR BindingName,
IN ULONG ulBufferLength,
IN PUCHAR Buffer
)
/*++
Routine Name:
Routine Description:
Arguments:
Return Values:
--*/
{
*ProtocolCB = NULL;
// NdisAcquireSpinLock(&(FreeProtocolCBList.Lock));
//
// See if there are any ProtocolCB's available on the free list.
// If there are not we will need to allocate one.
//
// if (FreeProtocolCBList.ulCount == 0) {
//
// Create ProtocolCB
//
NdisWanCreateProtocolCB(ProtocolCB,
usProtocolType,
usBindingNameLength,
BindingName,
ulBufferLength,
Buffer);
// } else {
//
// Get the ProtocolCB from the free list
//
// *ProtocolCB = (PPROTOCOLCB)RemoveHeadList(&(FreeProtocolCBList.List));
// FreeProtocolCBList.ulCount--;
// }
// NdisReleaseSpinLock(&(FreeProtocolCBList.Lock));
// if (*ProtocolCB != NULL) {
// NdisWanInitProtocolCB(*ProtocolCB,
// ulBufferLength,
// Buffer,
// usProtocolType);
// }
}
NDIS_STATUS
NdisWanCreateProtocolCB(
OUT PPROTOCOLCB *ProtocolCB,
IN USHORT usProtocolType,
IN USHORT usBindingNameLength,
IN PWSTR BindingName,
IN ULONG ulBufferLength,
IN PUCHAR Buffer
)
/*++
Routine Name:
Routine Description:
Arguments:
Return Values:
NDIS_STATUS_SUCCESS - ProtocolCB was allocated and initialized
NDIS_STATUS_RESOURCES - Error allocating memory for ProtocolCB
--*/
{
PPROTOCOLCB LocalProtocolCB = NULL;
NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
ULONG ulAllocationSize = sizeof(PROTOCOLCB) + ulBufferLength;
PUCHAR AllocatedMemory;
ULONG i;
NdisWanAllocateMemory(&AllocatedMemory, ulAllocationSize);
if (AllocatedMemory != NULL) {
LocalProtocolCB = (PPROTOCOLCB)AllocatedMemory;
LocalProtocolCB->ulAllocationSize = ulAllocationSize;
AllocatedMemory += sizeof(PROTOCOLCB);
LocalProtocolCB->LineUpInfo = AllocatedMemory;
#ifdef BANDWIDTH_ON_DEMAND
//
// Initialize the sample table
//
LocalProtocolCB->SampleTable.ulSampleArraySize = SAMPLE_ARRAY_SIZE;
NdisWanInitWanTime(&LocalProtocolCB->SampleTable.SampleRate, ONE_HUNDRED_MILS);
NdisWanInitWanTime(&LocalProtocolCB->SampleTable.SamplePeriod, ONE_SECOND);
#endif
//
// Copy the bindingname
//
NdisWanStringToNdisString(&LocalProtocolCB->BindingName, BindingName);
//
// Copy over the protocol info
//
LocalProtocolCB->ulLineUpInfoLength = ulBufferLength;
NdisMoveMemory(LocalProtocolCB->LineUpInfo,
Buffer,
ulBufferLength);
//
// Setup the protocol type
//
LocalProtocolCB->usProtocolType = usProtocolType;
//
// Get the PPP protocol value for this protocol type
//
LocalProtocolCB->usPPPProtocolID = GetPPP_ProtocolID(usProtocolType, PROTOCOL_TYPE);
switch (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->LastRecvNonIdleData);
#ifdef BANDWIDTH_ON_DEMAND
LocalProtocolCB->SampleTable.ulFirstIndex =
LocalProtocolCB->SampleTable.ulCurrentIndex = 0;
NdisZeroMemory(&LocalProtocolCB->SampleTable.SampleArray[0],
sizeof(SEND_SAMPLE) * SAMPLE_ARRAY_SIZE);
#endif // end BANDWIDTH_ON_DEMAND
} else {
Status = NDIS_STATUS_RESOURCES;
NdisWanDbgOut(DBG_CRITICAL_ERROR, DBG_MEMORY, ("Error allocating memory for ProtocolCB, ulAllocationSize: %d",
ulAllocationSize));
}
*ProtocolCB = LocalProtocolCB;
return (Status);
}
//VOID
//NdisWanInitProtocolCB(
// IN PPROTOCOLCB ProtocolCB,
// IN ULONG ulBufferLength,
// IN PUCHAR Buffer,
// IN USHORT usProtocolType
// )
///*++
//
//Routine Name:
//
//Routine Description:
//
//Arguments:
//
//Return Values:
//
//--*/
//{
// //
// // Copy over the protocol info
// //
// ProtocolCB->ulLineUpInfoLength = ulBufferLength;
// NdisMoveMemory(ProtocolCB->LineUpInfo,
// Buffer,
// ulBufferLength);
//
// //
// // Setup the protocol type
// //
// ProtocolCB->usProtocolType = usProtocolType;
//
// //
// // Get the PPP protocol value for this protocol type
// //
// ProtocolCB->usPPPProtocolID = GetPPP_ProtocolID(usProtocolType, PROTOCOL_TYPE);
//
// ProtocolCB->SampleTable.ulFirstIndex =
// ProtocolCB->SampleTable.ulCurrentIndex = 0;
// NdisZeroMemory(&ProtocolCB->SampleTable.SampleArray[0],
// sizeof(SEND_SAMPLE) * SAMPLE_ARRAY_SIZE);
//
//}
VOID
NdisWanReturnProtocolCB(
IN PPROTOCOLCB ProtocolCB
)
/*++
Routine Name:
Routine Description:
Arguments:
Return Values:
--*/
{
// NdisAcquireSpinLock(&(FreeProtocolCBList.Lock));
//
// if (FreeProtocolCBList.ulCount > FreeProtocolCBList.ulMaxCount) {
NdisWanDestroyProtocolCB(ProtocolCB);
// } else {
//
// InsertTailGlobalList(FreeProtocolCBList, &(ProtocolCB->Linkage));
//
// FreeProtocolCBList.ulCount++;
//
// }
//
// NdisReleaseSpinLock(&(FreeProtocolCBList.Lock));
}
VOID
NdisWanDestroyProtocolCB(
IN PPROTOCOLCB ProtocolCB
)
/*++
Routine Name:
Routine Description:
Arguments:
Return Values:
--*/
{
ASSERT(ProtocolCB->HeadNdisPacketQueue == NULL);
ASSERT(ProtocolCB->TailNdisPacketQueue == NULL);
if (ProtocolCB->DeviceName.Length != 0) {
NdisWanFreeNdisString(&ProtocolCB->DeviceName);
}
if (ProtocolCB->BindingName.Length != 0) {
NdisWanFreeNdisString(&ProtocolCB->BindingName);
}
NdisWanFreeMemory(ProtocolCB);
}
VOID
NdisWanGetLinkCB(
OUT PLINKCB *LinkCB,
IN PWAN_ADAPTERCB WanAdapterCB,
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:
*LinkCB - Pointer to the location to store the pointer to the LinkCB
WanAdapterCB - Pointer to the WanAdapter control block that this Link is
associated with
Return Values:
None
--*/
{
//
// See if we have any free LinkCB's hanging around
// if not we will allocate one
//
NdisAcquireSpinLock(&(WanAdapterCB->Lock));
if (IsListEmpty(&(WanAdapterCB->FreeLinkCBList))) {
//
// Create LinkCB
//
NdisWanCreateLinkCB(LinkCB);
} else {
//
// Get the LinkCB from the free list
//
*LinkCB = (PLINKCB)RemoveHeadList(&(WanAdapterCB->FreeLinkCBList));
}
NdisReleaseSpinLock(&(WanAdapterCB->Lock));
//
// Set the new link state
//
NdisWanInitLinkCB(LinkCB, WanAdapterCB, SendWindow);
}
NDIS_STATUS
NdisWanCreateLinkCB(
OUT PLINKCB *LinkCB
)
/*++
Routine Name:
Routine Description:
Arguments:
Return Values:
--*/
{
NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
PLINKCB LocalLinkCB = NULL;
ULONG ulAllocationSize, n;
PUCHAR AllocatedMemory = NULL;
//
// Figure out how much we need to allocate
//
ulAllocationSize = sizeof(LINKCB);
//
// Allocate the memory for the LinkCB and it's WAN PACKETS
//
NdisWanAllocateMemory(&AllocatedMemory, ulAllocationSize);
if (AllocatedMemory != NULL) {
//
// Initialize the control block
//
LocalLinkCB = (PLINKCB)AllocatedMemory;
LocalLinkCB->ulAllocationSize = ulAllocationSize;
InitializeListHead(&LocalLinkCB->WanPacketPool);
NdisWanInitializeSyncEvent(&LocalLinkCB->OutstandingFramesEvent);
} else {
Status = NDIS_STATUS_RESOURCES;
NdisWanDbgOut(DBG_CRITICAL_ERROR, DBG_MEMORY, ("Error allocating memory for LinkCB, AllocationSize: %d",
ulAllocationSize));
}
*LinkCB = LocalLinkCB;
return (Status);
}
VOID
NdisWanInitLinkCB(
IN PLINKCB *LinkCB,
IN PWAN_ADAPTERCB WanAdapterCB,
IN ULONG SendWindow
)
/*++
Routine Name:
Routine Description:
Arguments:
Return Values:
--*/
{
PLINKCB LocalLinkCB = *LinkCB;
if (LocalLinkCB == NULL) {
return;
}
LocalLinkCB->hLinkContext = NULL;
LocalLinkCB->ulReferenceCount = 0;
LocalLinkCB->State = LINK_UP;
LocalLinkCB->WanAdapterCB = WanAdapterCB;
LocalLinkCB->OutstandingFrames = 0;
LocalLinkCB->LastRecvSeqNumber = 0;
LocalLinkCB->ulBandwidth = 100;
LocalLinkCB->PacketMemory = NULL;
LocalLinkCB->PacketMemorySize = 0;
LocalLinkCB->RecvFragmentsLost = 0;
NdisZeroMemory(&LocalLinkCB->LinkInfo, sizeof(WAN_LINK_INFO));
LocalLinkCB->LinkInfo.HeaderPadding = WanAdapterCB->WanInfo.HeaderPadding;
LocalLinkCB->LinkInfo.TailPadding = WanAdapterCB->WanInfo.TailPadding;
LocalLinkCB->LinkInfo.SendACCM =
LocalLinkCB->LinkInfo.RecvACCM = WanAdapterCB->WanInfo.DesiredACCM;
NdisZeroMemory(&LocalLinkCB->LinkStats, sizeof(WAN_STATS));
if (NdisWanAllocateSendResources(LocalLinkCB, SendWindow) != NDIS_STATUS_SUCCESS) {
//
// return the linkcb
//
NdisWanReturnLinkCB(LocalLinkCB);
*LinkCB = NULL;
}
}
VOID
NdisWanReturnLinkCB(
PLINKCB LinkCB
)
/*++
Routine Name:
Routine Description:
Arguments:
Return Values:
--*/
{
PWAN_ADAPTERCB WanAdapterCB = LinkCB->WanAdapterCB;
NdisAcquireSpinLock(&(WanAdapterCB->Lock));
//
// Free the wanpacket pool
//
NdisWanFreeSendResources(LinkCB);
InsertTailList(&WanAdapterCB->FreeLinkCBList, &LinkCB->Linkage);
NdisReleaseSpinLock(&(WanAdapterCB->Lock));
}
VOID
NdisWanDestroyLinkCB(
IN PLINKCB LinkCB
)
/*++
Routine Name:
Routine Description:
Arguments:
Return Values:
--*/
{
PWAN_ADAPTERCB WanAdapterCB = LinkCB->WanAdapterCB;
//
// Free the memory allocated for the control block
//
NdisWanFreeMemory(LinkCB);
}
NDIS_STATUS
NdisWanAllocateSendResources(
IN PLINKCB LinkCB,
IN ULONG SendWindow
)
/*++
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
--*/
{
PWAN_ADAPTERCB WanAdapterCB = LinkCB->WanAdapterCB;
ULONG BufferSize, PacketMemorySize, NumberOfPackets, n;
PUCHAR PacketMemory = NULL;
PNDIS_WAN_PACKET WanPacket;
NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
SendWindow = (SendWindow == 0) ?
WanAdapterCB->WanInfo.MaxTransmit : SendWindow;
SendWindow = (SendWindow == 0) ? 1 : SendWindow;
//
// The number of packets that we will create is the send
// window of this WAN Miniport + 1
//
NumberOfPackets = SendWindow + 1;
//
// The size of the buffer that we create is
//
BufferSize = WanAdapterCB->WanInfo.MaxFrameSize +
WanAdapterCB->WanInfo.HeaderPadding +
WanAdapterCB->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 += (WanAdapterCB->WanInfo.MaxFrameSize + 7) / 8;
//
// Make sure that the buffer is dword aligned.
//
BufferSize &= ~(sizeof(PVOID) - 1);
PacketMemorySize = (BufferSize + sizeof(NDIS_WAN_PACKET)) * NumberOfPackets;
//
// Allocate the memory for the wan packet buffer pool
//
NdisAllocateMemory(&PacketMemory,
PacketMemorySize,
WanAdapterCB->WanInfo.MemoryFlags,
WanAdapterCB->WanInfo.HighestAcceptableAddress);
if (PacketMemory != NULL) {
LinkCB->PacketMemory = PacketMemory;
LinkCB->PacketMemorySize = PacketMemorySize;
LinkCB->BufferSize = BufferSize;
for (n = 0; n < NumberOfPackets; n++) {
WanPacket = (PNDIS_WAN_PACKET)PacketMemory;
PacketMemory += sizeof(NDIS_WAN_PACKET);
InsertTailList(&LinkCB->WanPacketPool, &WanPacket->WanPacketQueue);
LinkCB->ulWanPacketCount++;
}
//
// Walk the list of newly created packets and fix up startbuffer and
// endbuffer pointers.
//
for (WanPacket = (PNDIS_WAN_PACKET)LinkCB->WanPacketPool.Flink;
(PVOID)WanPacket != (PVOID)&LinkCB->WanPacketPool;
WanPacket = (PNDIS_WAN_PACKET)WanPacket->WanPacketQueue.Flink) {
//
// Point to the begining of the data.
//
WanPacket->StartBuffer = PacketMemory;
PacketMemory += BufferSize;
//
// The 5 bytes give us a short buffer at the end and will
// keep a WAN Miniport from alignment checking if it uses
// this pointer to 'back copy'
//
WanPacket->EndBuffer = PacketMemory - 5;
}
} else {
Status = NDIS_STATUS_RESOURCES;
NdisWanDbgOut(DBG_CRITICAL_ERROR, DBG_MEMORY, ("Error allocating memory for BufferPool, AllocationSize: %d",
PacketMemorySize));
}
return (Status);
}
VOID
NdisWanFreeSendResources(
IN PLINKCB LinkCB
)
/*++
Routine Name:
NdisWanFreeSendResources
Routine Description:
This routine removes the WanPackets from this linkcb's send list
and free's the memory allocated for these packets. Should be called
at linedown time after all outstanding sends have been accounted for.
Arguments:
LinkCB - Pointer to the linkcb that the resources are being freed from.
Return Values:
None
--*/
{
PNDIS_WAN_PACKET WanPacket;
PUCHAR PacketMemory;
ULONG PacketMemorySize, Flags;
PacketMemory = LinkCB->PacketMemory;
PacketMemorySize = LinkCB->PacketMemorySize;
Flags = LinkCB->WanAdapterCB->WanInfo.MemoryFlags;
//
// Remove the packets from the wan packet pool
//
while (!IsListEmpty(&LinkCB->WanPacketPool)) {
RemoveHeadList(&LinkCB->WanPacketPool);
LinkCB->ulWanPacketCount--;
}
//
// Free the block of memory allocated for this send
//
if (PacketMemory != NULL) {
NdisFreeMemory(PacketMemory, PacketMemorySize, Flags);
}
}
VOID
NdisWanGetBundleCB(
OUT PBUNDLECB *BundleCB
)
/*++
Routine Name:
Routine Description:
Arguments:
Return Values:
--*/
{
NdisAcquireSpinLock(&(FreeBundleCBList.Lock));
//
// See if there are any BundleCB's available on the free list.
// If there are not we will need to allocate one.
//
if (FreeBundleCBList.ulCount == 0) {
//
// Create BundleCB
//
NdisWanCreateBundleCB(BundleCB);
} else {
//
// Get the BundleCB from the free list
//
*BundleCB = (PBUNDLECB)RemoveHeadList(&(FreeBundleCBList.List));
FreeBundleCBList.ulCount--;
}
NdisReleaseSpinLock(&(FreeBundleCBList.Lock));
if (*BundleCB != NULL) {
NdisWanInitBundleCB(*BundleCB);
}
}
NDIS_STATUS
NdisWanCreateBundleCB(
OUT PBUNDLECB *BundleCB
)
/*++
Routine Name:
Routine Description:
Arguments:
Return Values:
--*/
{
NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
PBUNDLECB LocalBundleCB = NULL;
ULONG ulAllocationSize;
PUCHAR AllocatedMemory = NULL;
//
// 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.
//
ulAllocationSize = sizeof(BUNDLECB) +
sizeof(PROTOCOLCB) +
(sizeof(PPROTOCOLCB) * MAX_PROTOCOLS);
NdisWanAllocateMemory(&AllocatedMemory, ulAllocationSize);
if (AllocatedMemory != NULL) {
PWSTR IOName = L"I/O ProtocolCB";
PPROTOCOLCB ProtocolCB;
//
// This is the bundlecb
//
LocalBundleCB = (PBUNDLECB)AllocatedMemory;
LocalBundleCB->ulAllocationSize = ulAllocationSize;
AllocatedMemory += sizeof(BUNDLECB);
//
// This is the memory used for the I/O protocolcb
//
ProtocolCB = (PPROTOCOLCB)AllocatedMemory;
AllocatedMemory += sizeof(PROTOCOLCB);
//
// This is the protocolcb table
//
(PUCHAR)LocalBundleCB->ProtocolCBTable = (PUCHAR)AllocatedMemory;
//
// Initialize the BundleCB
//
NdisAllocateSpinLock(&LocalBundleCB->Lock);
InitializeListHead(&LocalBundleCB->LinkCBList);
InitializeListHead(&LocalBundleCB->SendPacketQueue);
InitializeListHead(&LocalBundleCB->RecvDescPool);
InitializeListHead(&LocalBundleCB->RecvDescAssemblyList);
InitializeListHead(&LocalBundleCB->ProtocolCBList);
NdisWanInitializeSyncEvent(&LocalBundleCB->OutstandingFramesEvent);
NdisWanInitializeSyncEvent(&LocalBundleCB->IndicationEvent);
#ifdef BANDWIDTH_ON_DEMAND
LocalBundleCB->UpperBonDInfo.SampleTable.ulSampleArraySize = SAMPLE_ARRAY_SIZE;
LocalBundleCB->LowerBonDInfo.SampleTable.ulSampleArraySize = SAMPLE_ARRAY_SIZE;
#endif // end of BANDWIDTH_ON_DEMAND
//
// Add the protocolcb to the bundle's table and list
//
ProtocolCB->hProtocolHandle = 0;
ProtocolCB->BundleCB = LocalBundleCB;
ProtocolCB->HeadNdisPacketQueue =
ProtocolCB->TailNdisPacketQueue = NULL;
NdisWanStringToNdisString(&ProtocolCB->DeviceName, IOName);
#ifdef BANDWIDTH_ON_DEMAND
ProtocolCB->SampleTable.ulSampleArraySize = SAMPLE_ARRAY_SIZE;
NdisWanInitWanTime(&ProtocolCB->SampleTable.SampleRate, ONE_HUNDRED_MILS);
NdisWanInitWanTime(&ProtocolCB->SampleTable.SamplePeriod, ONE_SECOND);
#endif
LocalBundleCB->ProtocolCBTable[0] = ProtocolCB;
InsertHeadList(&LocalBundleCB->ProtocolCBList, &ProtocolCB->Linkage);
LocalBundleCB->ulNumberOfRoutes = 1;
} else {
Status = NDIS_STATUS_RESOURCES;
NdisWanDbgOut(DBG_CRITICAL_ERROR, DBG_MEMORY, ("Error allocating memory for BundleCB, AllocationSize: %d",
ulAllocationSize));
}
*BundleCB = LocalBundleCB;
return (Status);
}
VOID
NdisWanInitBundleCB(
PBUNDLECB BundleCB
)
/*++
Routine Name:
Routine Description:
Arguments:
Return Values:
--*/
{
PPROTOCOLCB ProtocolCB = BundleCB->ProtocolCBTable[0];
PRECV_DESC RecvDescHole;
#ifdef BANDWIDTH_ON_DEMAND
PSAMPLE_TABLE SampleTable;
PBOND_INFO BonDInfo;
#endif // end of BANDWIDTH_ON_DEMAND
BundleCB->State = BUNDLE_UP;
NdisZeroMemory(&BundleCB->FramingInfo, sizeof(BUNDLE_FRAME_INFO));
BundleCB->NextLinkToXmit = NULL;
BundleCB->SendingLinks = 0;
BundleCB->SendSeqNumber = 0;
BundleCB->SendSeqMask = 0;
BundleCB->SendSeqTest = 0;
BundleCB->Flags = 0;
NdisZeroMemory(&BundleCB->LineUpInfo, sizeof(BUNDLE_LINE_UP));
BundleCB->LineUpInfo.ulMaximumTotalSize = MAX_TOTAL_SIZE;
//
// Init the recv hole desc
//
BundleCB->RecvSeqMask = 0;
BundleCB->RecvSeqTest = 0;
BundleCB->RecvFragmentsLost = 0;
BundleCB->MinReceivedSeqNumber = 0;
ASSERT(BundleCB->RecvDescAssemblyList.Flink == BundleCB->RecvDescAssemblyList.Blink);
NdisWanGetRecvDesc(BundleCB, &RecvDescHole);
RecvDescHole->SequenceNumber = 0;
RecvDescHole->Flags = 1;
BundleCB->RecvDescHole = RecvDescHole;
InsertHeadList(&BundleCB->RecvDescAssemblyList, &RecvDescHole->Linkage);
NdisWanGetSystemTime(&BundleCB->LastRecvNonIdleData);
ProtocolCB->SendMaskBit = IO_SEND_MASK_BIT;
NdisZeroMemory(&BundleCB->SendVJInfo, sizeof(VJ_INFO));
NdisZeroMemory(&BundleCB->RecvVJInfo, sizeof(VJ_INFO));
NdisZeroMemory(&BundleCB->SendCompInfo, sizeof(COMPRESS_INFO));
NdisZeroMemory(&BundleCB->RecvCompInfo, sizeof(COMPRESS_INFO));
NdisZeroMemory(&BundleCB->SendEncryptInfo,sizeof(ENCRYPTION_INFO));
NdisZeroMemory(&BundleCB->RecvEncryptInfo,sizeof(ENCRYPTION_INFO));
/*
#ifdef ENCRYPT_128BIT
BundleCB->SendEncryptInfo.SessionKeyLength =
BundleCB->RecvEncryptInfo.SessionKeyLength = 16;
BundleCB->SendCompInfo.MSCompType =
BundleCB->RecvCompInfo.MSCompType = NDISWAN_ENCRYPTION |
NDISWAN_40_ENCRYPTION |
NDISWAN_128_ENCRYPTION |
NDISWAN_COMPRESSION;
#else
BundleCB->SendEncryptInfo.SessionKeyLength =
BundleCB->RecvEncryptInfo.SessionKeyLength = 8;
BundleCB->SendCompInfo.MSCompType =
BundleCB->RecvCompInfo.MSCompType = NDISWAN_ENCRYPTION |
NDISWAN_40_ENCRYPTION |
NDISWAN_COMPRESSION;
#endif
*/
BundleCB->SendCompInfo.CompType =
BundleCB->RecvCompInfo.CompType = COMPTYPE_NONE;
ProtocolCB->usProtocolType = PROTOCOL_PRIVATE_IO;
ProtocolCB->usPPPProtocolID = PPP_PROTOCOL_PRIVATE_IO;
BundleCB->SendMask = IO_SEND_MASK_BIT;
#ifdef BANDWIDTH_ON_DEMAND
ProtocolCB->usPriority = 100;
ProtocolCB->ulByteQuota = 0xFFFFFFFF;
ProtocolCB->SampleTable.ulFirstIndex =
ProtocolCB->SampleTable.ulCurrentIndex = 0;
NdisZeroMemory(&ProtocolCB->SampleTable.SampleArray[0],
sizeof(SEND_SAMPLE) * SAMPLE_ARRAY_SIZE);
BonDInfo = &BundleCB->UpperBonDInfo;
BonDInfo->ulBytesThreshold = 0;
BonDInfo->State = BonDIdle;
BonDInfo->usPercentBandwidth = 0xFFFF;
BonDInfo->ulSecondsInSamplePeriod = 0;
NdisWanInitWanTime(&BonDInfo->StartTime, 0);
SampleTable = &BonDInfo->SampleTable;
NdisWanInitWanTime(&SampleTable->SampleRate, 0);
NdisWanInitWanTime(&SampleTable->SamplePeriod, 0);
SampleTable->ulFirstIndex =
SampleTable->ulCurrentIndex =
SampleTable->ulCurrentSampleByteCount = 0;
NdisZeroMemory(&SampleTable->SampleArray[0],
sizeof(SEND_SAMPLE) * SAMPLE_ARRAY_SIZE);
BonDInfo = &BundleCB->LowerBonDInfo;
BonDInfo->ulBytesThreshold = 0;
BonDInfo->State = BonDIdle;
BonDInfo->usPercentBandwidth = 0xFFFF;
BonDInfo->ulSecondsInSamplePeriod = 0;
NdisWanInitWanTime(&BonDInfo->StartTime, 0);
SampleTable = &BonDInfo->SampleTable;
NdisWanInitWanTime(&SampleTable->SampleRate, 0);
NdisWanInitWanTime(&SampleTable->SamplePeriod, 0);
SampleTable->ulFirstIndex =
SampleTable->ulCurrentIndex =
SampleTable->ulCurrentSampleByteCount = 0;
NdisZeroMemory(&SampleTable->SampleArray[0],
sizeof(SEND_SAMPLE) * SAMPLE_ARRAY_SIZE);
#endif // end of BANDWIDTH_ON_DEMAND
BundleCB->ulNameLength = 0;
NdisZeroMemory(&BundleCB->Name, MAX_NAME_LENGTH);
NdisZeroMemory(&BundleCB->BundleStats, sizeof(WAN_STATS));
}
VOID
NdisWanReturnBundleCB(
IN PBUNDLECB BundleCB
)
/*++
Routine Name:
Routine Description:
Arguments:
Return Values:
--*/
{
sl_compress_terminate(&BundleCB->VJCompress);
WanDeallocateCCP(BundleCB);
FlushRecvDescAssemblyList(BundleCB);
FreeRecvDescFreeList(BundleCB);
NdisAcquireSpinLock(&(FreeBundleCBList.Lock));
if (FreeBundleCBList.ulCount >= FreeBundleCBList.ulMaxCount) {
NdisWanDestroyBundleCB(BundleCB);
} else {
InsertTailList(&FreeBundleCBList.List, &(BundleCB->Linkage));
FreeBundleCBList.ulCount++;
}
NdisReleaseSpinLock(&(FreeBundleCBList.Lock));
}
VOID
NdisWanDestroyBundleCB(
IN PBUNDLECB BundleCB
)
/*++
Routine Name:
Routine Description:
Arguments:
Return Values:
--*/
{
PPROTOCOLCB ProtocolCB = BundleCB->ProtocolCBTable[0];
NdisFreeSpinLock(&BundleCB->Lock);
NdisWanFreeNdisString(&ProtocolCB->DeviceName);
NdisWanFreeMemory(BundleCB);
}
NDIS_STATUS
NdisWanCreatePPPProtocolTable(
VOID
)
/*++
Routine Name:
Routine Description:
Arguments:
Return Values:
--*/
{
NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
ULONG ulAllocationSize = 0;
PUCHAR AllocatedMemory;
//
// 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(PPP_PROTOCOL_TABLE) +
(sizeof(USHORT) * MAX_PROTOCOLS) +
(sizeof(USHORT) * MAX_PROTOCOLS);
NdisWanAllocateMemory(&AllocatedMemory, ulAllocationSize);
if (AllocatedMemory == NULL) {
NdisWanDbgOut(DBG_CRITICAL_ERROR, DBG_MEMORY,
("Failed allocating memory for ProtocolLookupTable! TableSize: %d",
ulAllocationSize));
return (NDIS_STATUS_RESOURCES);
}
PPP_ProtocolTable = (PPPP_PROTOCOL_TABLE)AllocatedMemory;
//
// Save the allocation size
//
PPP_ProtocolTable->ulAllocationSize = ulAllocationSize;
//
// Store the array size. This should be read from the registry
//
PPP_ProtocolTable->ulArraySize = MAX_PROTOCOLS;
NdisAllocateSpinLock(&PPP_ProtocolTable->Lock);
//
// Setup the pointer to the ProtocolValue array
//
AllocatedMemory += sizeof(PPP_PROTOCOL_TABLE);
PPP_ProtocolTable->ProtocolID = (PUSHORT)(AllocatedMemory);
//
// Setup the pointer to the PPPProtocolValue array
//
AllocatedMemory += (sizeof(USHORT) * MAX_PROTOCOLS);
PPP_ProtocolTable->PPPProtocolID = (PUSHORT)(AllocatedMemory);
//
// Insert default values for Netbuei, IP, IPX
//
InsertPPP_ProtocolID(PROTOCOL_PRIVATE_IO, PROTOCOL_TYPE);
InsertPPP_ProtocolID(PPP_PROTOCOL_PRIVATE_IO, PPP_TYPE);
InsertPPP_ProtocolID(PROTOCOL_IP, PROTOCOL_TYPE);
InsertPPP_ProtocolID(PPP_PROTOCOL_IP, PPP_TYPE);
InsertPPP_ProtocolID(PROTOCOL_IPX, PROTOCOL_TYPE);
InsertPPP_ProtocolID(PPP_PROTOCOL_IPX, PPP_TYPE);
InsertPPP_ProtocolID(PROTOCOL_NBF, PROTOCOL_TYPE);
InsertPPP_ProtocolID(PPP_PROTOCOL_NBF, PPP_TYPE);
return (Status);
}
VOID
NdisWanDestroyPPPProtocolTable(
VOID
)
/*++
Routine Name:
Routine Description:
Arguments:
Return Values:
--*/
{
NdisFreeSpinLock(&PPP_ProtocolTable->Lock);
NdisWanFreeMemory(PPP_ProtocolTable);
}
NDIS_STATUS
NdisWanCreateConnectionTable(
ULONG TableSize
)
/*++
Routine Name:
Routine Description:
Arguments:
Return Values:
--*/
{
NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
ULONG ulAllocationSize = 0;
PUCHAR AllocatedMemory;
PCONNECTION_TABLE NewTable;
//
// Since we skip the first place in the tables we increase the
// size by one.
//
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) * TableSize) +
(sizeof(PLINKCB) * TableSize);
NdisWanAllocateMemory(&AllocatedMemory, ulAllocationSize);
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;
NdisAllocateSpinLock(&NewTable->Lock);
//
// This is the amount of memory we allocated
//
NewTable->ulAllocationSize = ulAllocationSize;
NewTable->ulArraySize = TableSize;
InitializeListHead(&NewTable->BundleList);
//
// Setup pointer to the linkcb array
//
AllocatedMemory += sizeof(CONNECTION_TABLE);
NewTable->LinkArray = (PLINKCB*)(AllocatedMemory);
//
// Setup the pointer to the bundlecb array
//
AllocatedMemory += (sizeof(PLINKCB) * TableSize);
NewTable->BundleArray = (PBUNDLECB*)(AllocatedMemory);
if (ConnectionTable != NULL) {
//
// We must be growing the table
//
NewTable->ulNumActiveLinks = ConnectionTable->ulNumActiveLinks;
NewTable->ulNumActiveBundles = ConnectionTable->ulNumActiveBundles;
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);
}
NdisWanDestroyConnectionTable();
}
ConnectionTable = NewTable;
return (Status);
}
VOID
NdisWanDestroyConnectionTable(
VOID
)
/*++
Routine Name:
Routine Description:
Arguments:
Return Values:
--*/
{
NdisFreeSpinLock(&ConnectionTable->Lock);
NdisWanFreeMemory(ConnectionTable);
}
VOID
NdisWanGetDeferredDesc(
PADAPTERCB AdapterCB,
PDEFERRED_DESC *RetDesc
)
{
ULONG i;
if (IsDeferredQueueEmpty(&AdapterCB->FreeDeferredQueue)) {
PDEFERRED_DESC DeferredDesc;
NdisWanAllocateMemory(&DeferredDesc, sizeof(DEFERRED_DESC) * 20);
if (DeferredDesc != NULL) {
for (i = 0; i < 20; i++) {
InsertHeadDeferredQueue(&AdapterCB->FreeDeferredQueue, DeferredDesc);
(PUCHAR)DeferredDesc += sizeof(DEFERRED_DESC);
}
}
}
*RetDesc = RemoveHeadDeferredQueue(&AdapterCB->FreeDeferredQueue);
ASSERT(*RetDesc != NULL);
}