2518 lines
60 KiB
C
2518 lines
60 KiB
C
/*++
|
|
|
|
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;
|
|
NdisWanCopyUnicodeString(&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);
|
|
|
|
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;
|
|
|
|
RtlCopyMemory((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,
|
|
(PSINGLE_LIST_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,
|
|
(PSINGLE_LIST_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);
|
|
}
|