|
|
/*++
Copyright (c) 1990-1997 Microsoft Corporation
Module Name:
cm.c
Abstract:
This file contains the functions that implement the ndiswan NDIS 5.0 call manager interface. These functions are used by the ndiswan miniport and NDIS 5.0 clients.
Author:
Tony Bell (TonyBe) January 9, 1997
Environment:
Kernel Mode
Revision History:
TonyBe 01/09/97 Created
--*/
#include "wan.h"
#include "traffic.h"
#include "ntddtc.h"
#define __FILE_SIG__ CM_FILESIG
NDIS_STATUS CmCreateVc( IN NDIS_HANDLE ProtocolAfContext, IN NDIS_HANDLE NdisVcHandle, OUT PNDIS_HANDLE ProtocolVcContext ) { PCM_AFSAPCB AfSapCB = (PCM_AFSAPCB)ProtocolAfContext; PCM_VCCB CmVcCB;
NdisWanDbgOut(DBG_TRACE, DBG_CM, ("CmCreateVc: Enter"));
CmVcCB = NdisWanAllocateCmVcCB(AfSapCB, NdisVcHandle);
if (CmVcCB == NULL) { return (NDIS_STATUS_RESOURCES); }
*ProtocolVcContext = CmVcCB;
NdisWanDbgOut(DBG_TRACE, DBG_CM, ("CmCreateVc: Exit"));
return (NDIS_STATUS_SUCCESS); }
NDIS_STATUS CmDeleteVc( IN NDIS_HANDLE ProtocolVcContext ) { PCM_VCCB CmVcCB;
NdisWanDbgOut(DBG_TRACE, DBG_CM, ("CmDeleteVc: Enter"));
CmVcCB = (PCM_VCCB)ProtocolVcContext;
ASSERT(CmVcCB->RefCount == 0);
NdisWanFreeCmVcCB(CmVcCB);
NdisWanDbgOut(DBG_TRACE, DBG_CM, ("CmDeleteVc: Exit"));
return (NDIS_STATUS_SUCCESS); }
NDIS_STATUS CmOpenAf( IN NDIS_HANDLE CallMgrBindingContext, IN PCO_ADDRESS_FAMILY AddressFamily, IN NDIS_HANDLE NdisAfHandle, OUT PNDIS_HANDLE CallMgrAfContext ) { PMINIPORTCB MiniportCB = (PMINIPORTCB)CallMgrBindingContext; PCM_AFSAPCB AfSapCB;
NdisWanDbgOut(DBG_TRACE, DBG_CM, ("CmOpenAf: Enter"));
if (AddressFamily->AddressFamily != CO_ADDRESS_FAMILY_PPP) { return (NDIS_STATUS_FAILURE); }
AfSapCB = NdisWanAllocateCmAfSapCB(MiniportCB);
if (AfSapCB == NULL) { return (NDIS_STATUS_RESOURCES); }
*CallMgrAfContext = (NDIS_HANDLE)AfSapCB;
NdisWanDbgOut(DBG_TRACE, DBG_CM, ("CmOpenAf: Exit"));
return(NDIS_STATUS_SUCCESS); }
NDIS_STATUS CmCloseAf( IN NDIS_HANDLE CallMgrAfContext ) { PCM_AFSAPCB AfSapCB = (PCM_AFSAPCB)CallMgrAfContext;
NdisWanDbgOut(DBG_TRACE, DBG_CM, ("CmCloseAf: Enter"));
NdisWanFreeCmAfSapCB(AfSapCB);
NdisWanDbgOut(DBG_TRACE, DBG_CM, ("CmCloseAf: Exit"));
return(NDIS_STATUS_SUCCESS); }
NDIS_STATUS CmRegisterSap( IN NDIS_HANDLE CallMgrAfContext, IN PCO_SAP Sap, IN NDIS_HANDLE NdisSapHandle, OUT PNDIS_HANDLE CallMgrSapContext ) { PMINIPORTCB MiniportCB = (PMINIPORTCB)CallMgrAfContext;
NdisWanDbgOut(DBG_TRACE, DBG_CM, ("CmRegisterSap: Enter SapType %d", Sap->SapType));
*CallMgrSapContext = CallMgrAfContext;
NdisWanDbgOut(DBG_TRACE, DBG_CM, ("CmRegisterSap: Exit"));
return(NDIS_STATUS_SUCCESS); }
NDIS_STATUS CmDeregisterSap( IN NDIS_HANDLE CallMgrSapContext ) { PCM_AFSAPCB AfSapCB = (PCM_AFSAPCB)CallMgrSapContext;
NdisWanDbgOut(DBG_TRACE, DBG_CM, ("CmDeregisterSap: Enter"));
NdisWanDbgOut(DBG_TRACE, DBG_CM, ("CmDeregisterSap: Exit")); return(NDIS_STATUS_SUCCESS); }
NDIS_STATUS CmMakeCall( IN NDIS_HANDLE CallMgrVcContext, IN OUT PCO_CALL_PARAMETERS CallParameters, IN NDIS_HANDLE NdisPartyHandle OPTIONAL, OUT PNDIS_HANDLE CallMgrPartyContext OPTIONAL ) { PBUNDLECB BundleCB; PPROTOCOLCB ProtocolCB; PCM_VCCB CmVcCB; PCO_CALL_MANAGER_PARAMETERS CallMgrParams; PCO_MEDIA_PARAMETERS MediaParams; PCO_SPECIFIC_PARAMETERS SpecificParams; LPQOS_WAN_MEDIA QosMedia; LPQOS_OBJECT_HDR QoSObject; LONG ParamsLength; NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
NdisWanDbgOut(DBG_TRACE, DBG_CM, ("CmMakeCall: Enter"));
CmVcCB = (PCM_VCCB)CallMgrVcContext;
CallMgrParams = CallParameters->CallMgrParameters;
MediaParams = CallParameters->MediaParameters;
SpecificParams = &MediaParams->MediaSpecific;
if (SpecificParams->ParamType != PARAM_TYPE_GQOS_INFO) { NdisWanDbgOut(DBG_CRITICAL_ERROR, DBG_CM, ("CmMakeCall: Not a QOS Vc! ParamType %x", SpecificParams->ParamType)); return (NDIS_STATUS_FAILURE); }
QosMedia = (LPQOS_WAN_MEDIA)SpecificParams->Parameters;
//
// Need to check the flowspec for bandwidth
//
do { ULONG_PTR BIndex, PIndex;
//
// Get the protocolcb
//
GetNdisWanIndices(QosMedia->LinkId, BIndex, PIndex);
if (!IsBundleValid((NDIS_HANDLE)BIndex, TRUE, &BundleCB)) {
Status = NDIS_STATUS_FAILURE; break; }
AcquireBundleLock(BundleCB);
PROTOCOLCB_FROM_PROTOCOLH(BundleCB, ProtocolCB, PIndex);
if (ProtocolCB == NULL || ProtocolCB == (PVOID)RESERVED_PROTOCOLCB || ProtocolCB->State != PROTOCOL_ROUTED) { ReleaseBundleLock(BundleCB); Status = NDIS_STATUS_FAILURE; break; }
//
// If we don't have multilink or if we have encryption then we can not
// do isslow
//
if (!(BundleCB->FramingInfo.SendFramingBits & PPP_MULTILINK_FRAMING) || (BundleCB->SendFlags & DO_ENCRYPTION)) { CmVcCB->FlowClass = 0; } else {
if (QosMedia->ISSLOW == 1) { CmVcCB->FlowClass = MAX_MCML; BundleCB->Flags |= QOS_ENABLED; } else { CmVcCB->FlowClass = 0; } }
#ifdef USE_QOS_WORKER
NdisInitializeWorkItem(&BundleCB->QoSWorkItem, QoSSendFragments, BundleCB); #endif
SetBundleFlags(BundleCB);
NdisWanDbgOut(DBG_INFO, DBG_CM, ("MakeCall Vc/Protocol %p/%p %d/%d", CmVcCB, ProtocolCB, CmVcCB->State, ProtocolCB->State));
NdisWanDbgOut(DBG_INFO, DBG_CM, ("Setting FlowClass %x Isslow %d", CmVcCB->FlowClass, QosMedia->ISSLOW));
REF_CMVCCB(CmVcCB);
CmVcCB->ProtocolCB = ProtocolCB;
InsertTailList(&ProtocolCB->VcList, &CmVcCB->Linkage);
REF_PROTOCOLCB(ProtocolCB);
ReleaseBundleLock(BundleCB);
InterlockedExchange((PLONG)&CmVcCB->State, CMVC_ACTIVE);
NdisMCmActivateVc(CmVcCB->NdisVcHandle, CallParameters);
} while (FALSE);
//
// Deref for ref applied in IsBundleValid
//
DEREF_BUNDLECB(BundleCB);
NdisWanDbgOut(DBG_TRACE, DBG_CM, ("CmMakeCall: Exit"));
return(Status); }
NDIS_STATUS CmCloseCall( IN NDIS_HANDLE CallMgrVcContext, IN NDIS_HANDLE CallMgrPartyContext OPTIONAL, IN PVOID CloseData OPTIONAL, IN UINT Size OPTIONAL ) { PPROTOCOLCB ProtocolCB; PBUNDLECB BundleCB; PCM_VCCB CmVcCB; BOOLEAN DisableQoS = TRUE;
NdisWanDbgOut(DBG_TRACE, DBG_CM, ("CmCloseCall: Enter"));
CmVcCB = (PCM_VCCB)CallMgrVcContext;
ProtocolCB = CmVcCB->ProtocolCB;
BundleCB = ProtocolCB->BundleCB;
AcquireBundleLock(BundleCB);
if (CmVcCB->State != CMVC_CLOSE_DISPATCHED) { RemoveEntryList(&CmVcCB->Linkage); }
//
// Walk the Vc list and see if there are any
// ISSLOW Vc's. If there are not then disable QOS
//
{ PCM_VCCB _vc;
_vc = (PCM_VCCB)ProtocolCB->VcList.Flink;
while ((PVOID)_vc != (PVOID)&ProtocolCB->VcList) { if (_vc->FlowClass == MAX_MCML) { DisableQoS = FALSE; break; } _vc = (PCM_VCCB)_vc->Linkage.Flink; } }
NdisWanDbgOut(DBG_INFO, DBG_CM, ("CloseCall Vc/Protocol %p/%p %d/%d", CmVcCB, ProtocolCB, CmVcCB->State, ProtocolCB->State));
InterlockedExchange((PLONG)&CmVcCB->State, CMVC_CLOSING);
DEREF_CMVCCB(CmVcCB);
DEREF_PROTOCOLCB(ProtocolCB);
if (DisableQoS && BundleCB != NULL) {
BundleCB->Flags &= ~QOS_ENABLED; }
ReleaseBundleLock(BundleCB);
NdisWanDbgOut(DBG_TRACE, DBG_CM, ("CmCloseCall: Exit"));
return(NDIS_STATUS_PENDING); }
NDIS_STATUS CmModifyCallQoS( IN NDIS_HANDLE CallMgrVcContext, IN PCO_CALL_PARAMETERS CallParameters ) { PCM_VCCB CmVcCB; PCO_CALL_MANAGER_PARAMETERS CallMgrParams; PCO_MEDIA_PARAMETERS MediaParams; PCO_SPECIFIC_PARAMETERS SpecificParams; LPQOS_WAN_MEDIA QosMedia; LPQOS_OBJECT_HDR QoSObject; PBUNDLECB BundleCB; PPROTOCOLCB ProtocolCB;
NdisWanDbgOut(DBG_TRACE, DBG_CM, ("CmModifyCallQos: Enter"));
CmVcCB = (PCM_VCCB)CallMgrVcContext;
CallMgrParams = CallParameters->CallMgrParameters;
MediaParams = CallParameters->MediaParameters;
SpecificParams = &MediaParams->MediaSpecific;
if (SpecificParams->ParamType != PARAM_TYPE_GQOS_INFO) { NdisWanDbgOut(DBG_CRITICAL_ERROR, DBG_CM, ("CmMakeCall: Not a QOS Vc! ParamType %x", SpecificParams->ParamType)); return (NDIS_STATUS_SUCCESS); }
QosMedia = (LPQOS_WAN_MEDIA)SpecificParams->Parameters;
ProtocolCB = CmVcCB->ProtocolCB;
if (ProtocolCB == NULL) { return (NDIS_STATUS_SUCCESS); }
BundleCB = ProtocolCB->BundleCB;
if (BundleCB == NULL) { return (NDIS_STATUS_SUCCESS); }
AcquireBundleLock(BundleCB);
//
// If we don't have multilink or if we have encryption then we can not
// do isslow
//
if (!(BundleCB->FramingInfo.SendFramingBits & PPP_MULTILINK_FRAMING) || (BundleCB->SendFlags & DO_ENCRYPTION)) { CmVcCB->FlowClass = 0; } else {
if (QosMedia->ISSLOW == 1) { CmVcCB->FlowClass = MAX_MCML; BundleCB->Flags |= QOS_ENABLED; } else { CmVcCB->FlowClass = 0; // Walk the Vc list and see if there are any
// ISSLOW Vc's. If there are not then disable QOS
{ PCM_VCCB _vc; BOOLEAN DisableQoS = TRUE; _vc = (PCM_VCCB)ProtocolCB->VcList.Flink; while ((PVOID)_vc != (PVOID)&ProtocolCB->VcList) { if (_vc->FlowClass == MAX_MCML) { DisableQoS = FALSE; break; } _vc = (PCM_VCCB)_vc->Linkage.Flink; } if (DisableQoS) { BundleCB->Flags &= ~QOS_ENABLED; } } } } SetBundleFlags(BundleCB);
ReleaseBundleLock(BundleCB);
NdisWanDbgOut(DBG_DEATH, DBG_CM, ("Updating FlowClass %x for Vc/Protocol %p/%p, Isslow %d", CmVcCB->FlowClass, CmVcCB, CmVcCB->ProtocolCB, QosMedia->ISSLOW));
NdisWanDbgOut(DBG_TRACE, DBG_CM, ("CmModifyCallQos: Exit")); return(NDIS_STATUS_SUCCESS); }
VOID CmIncomingCallComplete( IN NDIS_STATUS Status, IN NDIS_HANDLE CallMgrVcContext, IN PCO_CALL_PARAMETERS CallParameters ) { NdisWanDbgOut(DBG_TRACE, DBG_CM, ("CmIncomingCallComplete: Enter"));
NdisWanDbgOut(DBG_TRACE, DBG_CM, ("CmIncomingCallComplete: Exit")); }
VOID CmActivateVcComplete( IN NDIS_STATUS Status, IN NDIS_HANDLE CallMgrVcContext, IN PCO_CALL_PARAMETERS CallParameters ) { NdisWanDbgOut(DBG_TRACE, DBG_CM, ("CmActivateVcComplete: Enter"));
NdisWanDbgOut(DBG_TRACE, DBG_CM, ("CmActivateVcComplete: Exit")); }
VOID CmDeactivateVcComplete( IN NDIS_STATUS Status, IN NDIS_HANDLE CallMgrVcContext ) { NdisWanDbgOut(DBG_TRACE, DBG_CM, ("CmDeactivateVcComplete: Enter"));
NdisWanDbgOut(DBG_TRACE, DBG_CM, ("CmDeactivateVcComplete: Exit")); }
NDIS_STATUS CmRequest( IN NDIS_HANDLE ProtocolAfContext, IN NDIS_HANDLE ProtocolVcContext OPTIONAL, IN NDIS_HANDLE ProtocolPartyContext OPTIONAL, IN OUT PNDIS_REQUEST NdisRequest ) { NDIS_STATUS Status; NdisWanDbgOut(DBG_TRACE, DBG_CM, ("CmRequest: Enter"));
Status = NdisWanCoOidProc((PMINIPORTCB)ProtocolAfContext, (PCM_VCCB)ProtocolVcContext, NdisRequest);
NdisWanDbgOut(DBG_TRACE, DBG_CM, ("CmRequest: Exit Status: 0x%x", Status)); return(Status); }
|