1219 lines
30 KiB
C
1219 lines
30 KiB
C
/*++
|
|
|
|
Copyright (c) 1990-1998 Microsoft Corporation, All Rights Reserved.
|
|
|
|
Module Name:
|
|
|
|
callmgr.c
|
|
|
|
Abstract:
|
|
|
|
This module contains the interface of the driver with the Call Manager.
|
|
|
|
Author:
|
|
|
|
Anil Francis Thomas (10/98)
|
|
|
|
Environment:
|
|
|
|
Kernel
|
|
|
|
Revision History:
|
|
|
|
--*/
|
|
#include "precomp.h"
|
|
#pragma hdrstop
|
|
|
|
|
|
#define MODULE_ID MODULE_CALLMGR
|
|
|
|
VOID
|
|
AtmSmCoAfRegisterNotify(
|
|
IN NDIS_HANDLE ProtocolBindingContext,
|
|
IN PCO_ADDRESS_FAMILY pAddressFamily
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine is called by NDIS when a Call manager registers its support
|
|
for an Address Family over an adapter. If this is the Address Family we
|
|
are interested in (UNI 3.1), then we register our SAP on this adapter.
|
|
|
|
Arguments:
|
|
|
|
ProtocolBindingContext - our context passed in NdisOpenAdapter, which is
|
|
a pointer to our Adapter structure.
|
|
pAddressFamily - points to a structure describing the
|
|
Address Family registered by a Call Manager.
|
|
|
|
Return Value:
|
|
|
|
None
|
|
|
|
--*/
|
|
{
|
|
PATMSM_ADAPTER pAdapt = (PATMSM_ADAPTER)
|
|
ProtocolBindingContext;
|
|
NDIS_STATUS Status;
|
|
NDIS_CLIENT_CHARACTERISTICS Chars;
|
|
|
|
TraceIn(AtmSmCoAfRegisterNotify);
|
|
|
|
if(!AtmSmReferenceAdapter(pAdapt))
|
|
return;
|
|
|
|
if ((pAddressFamily->AddressFamily == CO_ADDRESS_FAMILY_Q2931) &&
|
|
(pAddressFamily->MajorVersion == 3) &&
|
|
(pAddressFamily->MinorVersion == 1) &&
|
|
(pAdapt->NdisAfHandle == NULL))
|
|
{
|
|
DbgInfo(("AfNotify: Adapter %X\n", pAdapt));
|
|
|
|
//
|
|
// We successfully opened the adapter. Now open the address-family
|
|
//
|
|
pAdapt->AddrFamily.AddressFamily = CO_ADDRESS_FAMILY_Q2931;
|
|
pAdapt->AddrFamily.MajorVersion = 3;
|
|
pAdapt->AddrFamily.MinorVersion = 1;
|
|
|
|
NdisZeroMemory(&Chars, sizeof(NDIS_CLIENT_CHARACTERISTICS));
|
|
Chars.MajorVersion = 5;
|
|
Chars.MinorVersion = 0;
|
|
Chars.ClCreateVcHandler = AtmSmCreateVc;
|
|
Chars.ClDeleteVcHandler = AtmSmDeleteVc;
|
|
Chars.ClRequestHandler = AtmSmCoRequest;
|
|
Chars.ClRequestCompleteHandler = AtmSmCoRequestComplete;
|
|
Chars.ClOpenAfCompleteHandler = AtmSmOpenAfComplete;
|
|
Chars.ClCloseAfCompleteHandler = AtmSmCloseAfComplete;
|
|
Chars.ClRegisterSapCompleteHandler = AtmSmRegisterSapComplete;
|
|
Chars.ClDeregisterSapCompleteHandler = AtmSmDeregisterSapComplete;
|
|
Chars.ClMakeCallCompleteHandler = AtmSmMakeCallComplete;
|
|
Chars.ClModifyCallQoSCompleteHandler = NULL;
|
|
Chars.ClCloseCallCompleteHandler = AtmSmCloseCallComplete;
|
|
Chars.ClAddPartyCompleteHandler = AtmSmAddPartyComplete;
|
|
Chars.ClDropPartyCompleteHandler = AtmSmDropPartyComplete;
|
|
Chars.ClIncomingCallHandler = AtmSmIncomingCall;
|
|
Chars.ClIncomingCallQoSChangeHandler = AtmSmIncomingCallQoSChange;
|
|
Chars.ClIncomingCloseCallHandler = AtmSmIncomingCloseCall;
|
|
Chars.ClIncomingDropPartyHandler = AtmSmIncomingDropParty;
|
|
Chars.ClCallConnectedHandler = AtmSmCallConnected;
|
|
|
|
Status = NdisClOpenAddressFamily(pAdapt->NdisBindingHandle,
|
|
&pAdapt->AddrFamily,
|
|
pAdapt, // Use this as the Af context
|
|
&Chars,
|
|
sizeof(NDIS_CLIENT_CHARACTERISTICS),
|
|
&pAdapt->NdisAfHandle);
|
|
if (NDIS_STATUS_PENDING != Status)
|
|
{
|
|
AtmSmOpenAfComplete(Status, pAdapt, pAdapt->NdisAfHandle);
|
|
}
|
|
|
|
} else {
|
|
|
|
// Not UNI3.1, hence remove the reference we added above
|
|
AtmSmDereferenceAdapter(pAdapt);
|
|
}
|
|
|
|
TraceOut(AtmSmCoAfRegisterNotify);
|
|
}
|
|
|
|
|
|
VOID
|
|
AtmSmOpenAfComplete(
|
|
IN NDIS_STATUS Status,
|
|
IN NDIS_HANDLE ProtocolAfContext,
|
|
IN NDIS_HANDLE NdisAfHandle
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Completion processing for the OpenAf call.
|
|
|
|
Arguments:
|
|
|
|
Status Status of OpenAf
|
|
ProtocolAfContext Pointer to the pAdapt
|
|
NdisAfHandle Ndis Handle to refer to this Af
|
|
|
|
Return Value:
|
|
|
|
|
|
--*/
|
|
{
|
|
PATMSM_ADAPTER pAdapt= (PATMSM_ADAPTER)ProtocolAfContext;
|
|
|
|
TraceIn(AtmSmOpenAfComplete);
|
|
|
|
if (NDIS_STATUS_SUCCESS == Status){
|
|
|
|
pAdapt->NdisAfHandle = NdisAfHandle;
|
|
|
|
pAdapt->ulFlags |= ADAPT_AF_OPENED;
|
|
|
|
//
|
|
// Now register our SAP on this interface
|
|
//
|
|
Status = AtmSmRegisterSap(pAdapt);
|
|
|
|
} else {
|
|
|
|
DbgErr(("Opening of Address Family Failed! Status - 0x%X\n", Status));
|
|
}
|
|
|
|
if ((Status != NDIS_STATUS_SUCCESS) &&
|
|
(Status != NDIS_STATUS_PENDING)){
|
|
|
|
//
|
|
// Close Address family (This results in a dereference)
|
|
//
|
|
Status = NdisClCloseAddressFamily(pAdapt->NdisAfHandle);
|
|
if (NDIS_STATUS_PENDING != Status){
|
|
|
|
AtmSmCloseAfComplete(Status, pAdapt);
|
|
}
|
|
|
|
//
|
|
// Close Adapter (This results in a dereference)
|
|
//
|
|
NdisCloseAdapter(&Status, pAdapt->NdisBindingHandle);
|
|
if (NDIS_STATUS_PENDING != Status){
|
|
|
|
AtmSmCloseAdapterComplete(pAdapt, Status);
|
|
}
|
|
|
|
// if synchronous - by now the adapter structure wll be freed
|
|
}
|
|
|
|
TraceOut(AtmSmOpenAfComplete);
|
|
}
|
|
|
|
|
|
NDIS_STATUS
|
|
AtmSmRegisterSap(
|
|
IN PATMSM_ADAPTER pAdapt
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
Register the Sap for receiving incoming calls.
|
|
|
|
Arguments:
|
|
|
|
Return Value:
|
|
|
|
--*/
|
|
{
|
|
ULONG ulSize;
|
|
NDIS_STATUS Status;
|
|
PATM_SAP pAtmSap;
|
|
PATM_ADDRESS pAtmAddress;
|
|
|
|
TraceIn(AtmSmRegisterSap);
|
|
|
|
do
|
|
{
|
|
//
|
|
// Allocate memory for registering the SAP, if doing it for the
|
|
// first time.
|
|
//
|
|
ulSize = sizeof(CO_SAP) + sizeof(ATM_SAP) + sizeof(ATM_ADDRESS);
|
|
|
|
if (NULL == pAdapt->pSap){
|
|
|
|
AtmSmAllocMem(&pAdapt->pSap, PCO_SAP, ulSize);
|
|
|
|
}
|
|
|
|
if (NULL == pAdapt->pSap){
|
|
|
|
Status = NDIS_STATUS_RESOURCES;
|
|
DbgErr(("Failed to allocate memory for Sap\n"));
|
|
break;
|
|
}
|
|
|
|
NdisZeroMemory(pAdapt->pSap, ulSize);
|
|
|
|
pAdapt->pSap->SapType = SAP_TYPE_NSAP;
|
|
pAdapt->pSap->SapLength = sizeof(ATM_SAP) + sizeof(ATM_ADDRESS);
|
|
|
|
pAtmSap = (PATM_SAP)pAdapt->pSap->Sap;
|
|
pAtmAddress = (PATM_ADDRESS)(pAtmSap->Addresses);
|
|
|
|
//
|
|
// Fill in the ATM SAP with default values
|
|
//
|
|
NdisMoveMemory(&pAtmSap->Blli, &AtmSmDefaultBlli, sizeof(ATM_BLLI_IE));
|
|
NdisMoveMemory(&pAtmSap->Bhli, &AtmSmDefaultBhli, sizeof(ATM_BHLI_IE));
|
|
|
|
//
|
|
// ATM Address to "listen" on: Wild card everything except the SEL.
|
|
//
|
|
pAtmSap->NumberOfAddresses = 1;
|
|
pAtmAddress->AddressType = SAP_FIELD_ANY_AESA_REST;
|
|
pAtmAddress->NumberOfDigits = ATM_ADDRESS_LENGTH;
|
|
pAtmAddress->Address[ATM_ADDRESS_LENGTH-1] = pAdapt->SelByte;
|
|
|
|
Status = NdisClRegisterSap(pAdapt->NdisAfHandle,
|
|
pAdapt,
|
|
pAdapt->pSap,
|
|
&pAdapt->NdisSapHandle);
|
|
|
|
if (Status != NDIS_STATUS_PENDING){
|
|
|
|
AtmSmRegisterSapComplete(Status,
|
|
pAdapt,
|
|
pAdapt->pSap,
|
|
pAdapt->NdisSapHandle);
|
|
}
|
|
} while (FALSE);
|
|
|
|
if ((Status != NDIS_STATUS_SUCCESS) &&
|
|
(Status != NDIS_STATUS_PENDING)){
|
|
|
|
DbgErr(("Registering Sap Failed! Status - 0x%X\n", Status));
|
|
|
|
// cleanup done after return
|
|
}
|
|
|
|
TraceOut(AtmSmRegisterSap);
|
|
|
|
return Status;
|
|
}
|
|
|
|
|
|
|
|
VOID
|
|
AtmSmRegisterSapComplete(
|
|
IN NDIS_STATUS Status,
|
|
IN NDIS_HANDLE ProtocolSapContext,
|
|
IN PCO_SAP pSap,
|
|
IN NDIS_HANDLE NdisSapHandle
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
Called by NDIS or us when the Sap registration completes.
|
|
|
|
Arguments:
|
|
|
|
|
|
Return Value:
|
|
|
|
|
|
--*/
|
|
{
|
|
PATMSM_ADAPTER pAdapt = (PATMSM_ADAPTER)ProtocolSapContext;
|
|
|
|
TraceIn(AtmSmRegisterSapComplete);
|
|
|
|
ASSERT (pSap == pAdapt->pSap);
|
|
|
|
if (NDIS_STATUS_SUCCESS != Status){
|
|
|
|
DbgErr(("RegisterSapComplete failed (%x): Adapter %x\n",
|
|
Status, pAdapt));
|
|
AtmSmFreeMem(pAdapt->pSap);
|
|
pAdapt->pSap = NULL;
|
|
|
|
} else {
|
|
|
|
ACQUIRE_ADAPTER_GEN_LOCK(pAdapt);
|
|
|
|
pAdapt->NdisSapHandle = NdisSapHandle;
|
|
pAdapt->ulFlags |= ADAPT_SAP_REGISTERED;
|
|
|
|
RELEASE_ADAPTER_GEN_LOCK(pAdapt);
|
|
|
|
}
|
|
|
|
TraceOut(AtmSmRegisterSapComplete);
|
|
}
|
|
|
|
|
|
VOID
|
|
AtmSmDeregisterSapComplete(
|
|
IN NDIS_STATUS Status,
|
|
IN NDIS_HANDLE ProtocolSapContext
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
Called by NDIS or us when the Sap Deregistration completes.
|
|
|
|
Arguments:
|
|
|
|
|
|
Return Value:
|
|
|
|
|
|
--*/
|
|
{
|
|
PATMSM_ADAPTER pAdapt = (PATMSM_ADAPTER)ProtocolSapContext;
|
|
|
|
TraceIn(AtmSmDeregisterSapComplete);
|
|
|
|
pAdapt->ulFlags &= ~ADAPT_SAP_REGISTERED;
|
|
|
|
pAdapt->NdisSapHandle = NULL;
|
|
|
|
AtmSmFreeMem(pAdapt->pSap);
|
|
|
|
pAdapt->pSap = NULL;
|
|
|
|
TraceOut(AtmSmDeregisterSapComplete);
|
|
}
|
|
|
|
|
|
VOID
|
|
AtmSmCloseAfComplete(
|
|
IN NDIS_STATUS Status,
|
|
IN NDIS_HANDLE ProtocolAfContext
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
Called by NDIS or us when closing of AF completes.
|
|
|
|
Arguments:
|
|
|
|
|
|
Return Value:
|
|
|
|
|
|
--*/
|
|
{
|
|
PATMSM_ADAPTER pAdapt = (PATMSM_ADAPTER)ProtocolAfContext;
|
|
|
|
pAdapt->ulFlags &= ~ADAPT_AF_OPENED;
|
|
|
|
pAdapt->NdisAfHandle = NULL;
|
|
|
|
DbgInfo(("CloseAfComplete: pAdapt %x, Flags %x, Ref %x\n",
|
|
pAdapt, pAdapt->ulFlags, pAdapt->ulRefCount));
|
|
|
|
//
|
|
// Nothing much to do except dereference the pAdapt
|
|
//
|
|
AtmSmDereferenceAdapter(pAdapt);
|
|
}
|
|
|
|
|
|
NDIS_STATUS
|
|
AtmSmCreateVc(
|
|
IN NDIS_HANDLE ProtocolAfContext,
|
|
IN NDIS_HANDLE NdisVcHandle,
|
|
OUT PNDIS_HANDLE ProtocolVcContext
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Entry point called by NDIS when the Call Manager wants to create
|
|
a new endpoint (VC). We allocate a new VC structure, and return
|
|
a pointer to it as our VC context.
|
|
|
|
Arguments:
|
|
|
|
ProtocolAfContext - Actually a pointer to the ATMSM adapter structure
|
|
NdisVcHandle - Handle for this VC for all future references
|
|
ProtocolVcContext - Place where we (protocol) return our context for the VC
|
|
|
|
Return Value:
|
|
|
|
NDIS_STATUS_SUCCESS if we could create a VC
|
|
NDIS_STATUS_RESOURCES otherwise
|
|
--*/
|
|
{
|
|
PATMSM_ADAPTER pAdapt = (PATMSM_ADAPTER)ProtocolAfContext;
|
|
PATMSM_VC pVc;
|
|
NDIS_STATUS Status;
|
|
|
|
DbgInfo(("CreateVc: NdisVcHandle %x, Adapt - %x\n", NdisVcHandle, pAdapt));
|
|
|
|
*ProtocolVcContext = NULL;
|
|
|
|
|
|
Status = AtmSmAllocVc(pAdapt, &pVc, VC_TYPE_INCOMING, NdisVcHandle);
|
|
|
|
if(NDIS_STATUS_SUCCESS == Status){
|
|
|
|
*ProtocolVcContext = pVc;
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
|
|
NDIS_STATUS
|
|
AtmSmDeleteVc(
|
|
IN NDIS_HANDLE ProtocolVcContext
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Our Delete VC handler. This VC would have been allocated as a result
|
|
of a previous entry into our CreateVcHandler, and possibly used for
|
|
an incoming call.
|
|
|
|
We dereference the VC here.
|
|
|
|
Arguments:
|
|
|
|
ProtocolVcContext - pointer to our VC structure
|
|
|
|
Return Value:
|
|
|
|
NDIS_STATUS_SUCCESS always
|
|
|
|
--*/
|
|
{
|
|
PATMSM_VC pVc = (PATMSM_VC)ProtocolVcContext;
|
|
|
|
DbgInfo(("DeleteVc: For Vc %lx\n", pVc));
|
|
|
|
pVc->NdisVcHandle = NULL;
|
|
AtmSmDereferenceVc(pVc);
|
|
|
|
return NDIS_STATUS_SUCCESS;
|
|
}
|
|
|
|
|
|
NDIS_STATUS
|
|
AtmSmIncomingCall(
|
|
IN NDIS_HANDLE ProtocolSapContext,
|
|
IN NDIS_HANDLE ProtocolVcContext,
|
|
IN OUT PCO_CALL_PARAMETERS CallParameters
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Handler for incoming call. We accept the call unless we are shutting down
|
|
and then do the actual processing when the call processing completes.
|
|
|
|
Arguments:
|
|
|
|
ProtocolSapContext Pointer to the pAdapt
|
|
ProtocolVcContext Pointer to the Vc
|
|
CallParameters Call Parameters
|
|
|
|
Return Value:
|
|
|
|
|
|
--*/
|
|
{
|
|
PATMSM_ADAPTER pAdapt = (PATMSM_ADAPTER)ProtocolSapContext;
|
|
PATMSM_VC pVc = (PATMSM_VC)ProtocolVcContext;
|
|
Q2931_CALLMGR_PARAMETERS UNALIGNED * CallMgrSpecific;
|
|
|
|
ASSERT (pVc->pAdapt == pAdapt);
|
|
|
|
DbgInfo(("AtmSmIncomingCall: On Vc %lx\n", pVc));
|
|
|
|
//
|
|
// Mark the Vc to indicate the call processing is underway
|
|
//
|
|
ACQUIRE_ADAPTER_GEN_LOCK(pAdapt);
|
|
|
|
ASSERT ((pVc->ulFlags & (ATMSM_VC_ACTIVE | ATMSM_VC_CALLPROCESSING)) == 0);
|
|
|
|
ATMSM_SET_VC_STATE(pVc, ATMSM_VC_CALLPROCESSING);
|
|
|
|
RELEASE_ADAPTER_GEN_LOCK(pAdapt);
|
|
|
|
//
|
|
// Get the remote atm address from the call-parameters
|
|
//
|
|
CallMgrSpecific = (PQ2931_CALLMGR_PARAMETERS)&CallParameters->
|
|
CallMgrParameters->CallMgrSpecific.Parameters[0];
|
|
|
|
pVc->HwAddr.Address = CallMgrSpecific->CallingParty;
|
|
|
|
//
|
|
// Get the max size of packets we can send on this VC, from the
|
|
// AAL5 parameters. Limit it to the size our miniport can support.
|
|
//
|
|
pVc->MaxSendSize = pAdapt->MaxPacketSize; // default
|
|
|
|
if (CallMgrSpecific->InfoElementCount > 0) {
|
|
|
|
Q2931_IE UNALIGNED * pIe;
|
|
AAL5_PARAMETERS UNALIGNED * pAal5;
|
|
ULONG IeCount;
|
|
|
|
pIe = (PQ2931_IE)CallMgrSpecific->InfoElements;
|
|
for (IeCount = CallMgrSpecific->InfoElementCount;
|
|
IeCount != 0;
|
|
IeCount--) {
|
|
|
|
if (pIe->IEType == IE_AALParameters) {
|
|
|
|
pAal5 = &(((PAAL_PARAMETERS_IE)pIe->IE)->
|
|
AALSpecificParameters.AAL5Parameters);
|
|
//
|
|
// Make sure we don't send more than what the caller can handle.
|
|
//
|
|
if (pAal5->ForwardMaxCPCSSDUSize < pVc->MaxSendSize) {
|
|
|
|
pVc->MaxSendSize = pAal5->ForwardMaxCPCSSDUSize;
|
|
}
|
|
|
|
//
|
|
// Make sure the caller doesn't send more than what our
|
|
// miniport can handle.
|
|
//
|
|
if (pAal5->BackwardMaxCPCSSDUSize > pAdapt->MaxPacketSize) {
|
|
|
|
pAal5->BackwardMaxCPCSSDUSize = pAdapt->MaxPacketSize;
|
|
}
|
|
break;
|
|
}
|
|
pIe = (PQ2931_IE)((PUCHAR)pIe + pIe->IELength);
|
|
}
|
|
}
|
|
|
|
|
|
return NDIS_STATUS_SUCCESS;
|
|
}
|
|
|
|
|
|
VOID
|
|
AtmSmCallConnected(
|
|
IN NDIS_HANDLE ProtocolVcContext
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Last hand-shake in the incoming call path. Move the Vc to the list of
|
|
active calls.
|
|
|
|
Arguments:
|
|
|
|
ProtocolVcContext Pointer to VC
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
{
|
|
PATMSM_VC pVc = (PATMSM_VC)ProtocolVcContext;
|
|
PATMSM_ADAPTER pAdapt = pVc->pAdapt;
|
|
|
|
DbgInfo(("AtmSmCallConnected: On pVc %x pAdapt %x\n", pVc, pAdapt));
|
|
|
|
pAdapt = pVc->pAdapt;
|
|
|
|
// now we add a reference to the VC
|
|
AtmSmReferenceVc(pVc);
|
|
|
|
ACQUIRE_ADAPTER_GEN_LOCK(pAdapt);
|
|
|
|
ASSERT(ATMSM_GET_VC_STATE(pVc) != ATMSM_VC_ACTIVE);
|
|
|
|
ASSERT(ATMSM_GET_VC_STATE(pVc) == ATMSM_VC_CALLPROCESSING);
|
|
|
|
ATMSM_SET_VC_STATE(pVc, ATMSM_VC_ACTIVE);
|
|
|
|
// remove the Vc from the inactive list
|
|
RemoveEntryList(&pVc->List);
|
|
|
|
// insert the vc into the active list
|
|
InsertHeadList(&pAdapt->ActiveVcHead, &pVc->List);
|
|
|
|
RELEASE_ADAPTER_GEN_LOCK(pAdapt);
|
|
|
|
}
|
|
|
|
|
|
VOID
|
|
AtmSmMakeCallComplete(
|
|
IN NDIS_STATUS Status,
|
|
IN NDIS_HANDLE ProtocolVcContext,
|
|
IN NDIS_HANDLE NdisPartyHandle OPTIONAL,
|
|
IN PCO_CALL_PARAMETERS CallParameters
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Handle completion of an earlier call to NdisClMakeCall. If the call has
|
|
succeeded and if this is a point to multipoint call, initiate Addparty on
|
|
the rest of the addresses. If it is not multipoint, then send any packets
|
|
pending on the call.
|
|
|
|
Arguments:
|
|
|
|
Status Result of NdisClMakeCall
|
|
ProtocolVcContext Pointer to P-P or PMP Vc
|
|
NdisPartyHandle If successful, the handle for this party
|
|
CallParameters Pointer to Call parameters
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
{
|
|
PATMSM_VC pVc = (PATMSM_VC)ProtocolVcContext;
|
|
PATMSM_ADAPTER pAdapt = (PATMSM_ADAPTER)pVc->pAdapt;
|
|
PATMSM_PMP_MEMBER pMember;
|
|
BOOLEAN bLockReleased = FALSE;
|
|
|
|
|
|
DbgInfo(("MakeCallComplete: Status %x, pVc %x, VC flag %x\n",
|
|
Status, pVc, pVc->ulFlags));
|
|
|
|
// Free the call parameters
|
|
AtmSmFreeMem(CallParameters);
|
|
|
|
//
|
|
// If this is a point to point connection and we succeeded in connecting
|
|
// then send the packets pending on the VC.
|
|
//
|
|
if(VC_TYPE_PMP_OUTGOING != pVc->VcType){
|
|
|
|
PIRP pIrp;
|
|
|
|
|
|
if(NDIS_STATUS_SUCCESS == Status){
|
|
// successfully connected the P-P call, send any pending packets
|
|
|
|
ACQUIRE_ADAPTER_GEN_LOCK(pAdapt);
|
|
|
|
ATMSM_SET_VC_STATE(pVc, ATMSM_VC_ACTIVE);
|
|
|
|
DbgInfo(("PP VC 0x%x successfully connected to destination\n",
|
|
pVc));
|
|
|
|
// now complete IRP that started this connect call
|
|
pIrp = pVc->pConnectIrp;
|
|
pVc->pConnectIrp = NULL;
|
|
|
|
ASSERT(pIrp);
|
|
|
|
// remove the Vc from the inactive list
|
|
RemoveEntryList(&pVc->List);
|
|
|
|
// insert the vc into the active list
|
|
InsertHeadList(&pAdapt->ActiveVcHead, &pVc->List);
|
|
|
|
RELEASE_ADAPTER_GEN_LOCK(pAdapt);
|
|
|
|
if(pIrp){
|
|
|
|
pIrp->IoStatus.Status = STATUS_SUCCESS;
|
|
|
|
// now set the connect context
|
|
*(PHANDLE)(pIrp->AssociatedIrp.SystemBuffer) = (HANDLE)pVc;
|
|
pIrp->IoStatus.Information = sizeof(HANDLE);
|
|
|
|
IoCompleteRequest(pIrp, IO_NETWORK_INCREMENT);
|
|
}
|
|
|
|
AtmSmSendQueuedPacketsOnVc(pVc);
|
|
|
|
} else {
|
|
|
|
// failed to connect the call.
|
|
|
|
// now complete IRP that started this connect call
|
|
PIRP pIrp = pVc->pConnectIrp;
|
|
pVc->pConnectIrp = NULL;
|
|
|
|
ASSERT(pIrp);
|
|
|
|
if(pIrp){
|
|
|
|
pIrp->IoStatus.Status = Status;
|
|
|
|
pIrp->IoStatus.Information = 0;
|
|
|
|
IoCompleteRequest(pIrp, IO_NETWORK_INCREMENT);
|
|
}
|
|
|
|
DbgInfo(("PP VC 0x%x failed to connect to destination - Status - "
|
|
"0x%x\n", pVc, Status));
|
|
|
|
// Cleanup the VC - remove the reference added at create
|
|
AtmSmDereferenceVc(pVc);
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
//
|
|
// This is the completion of the first Make call on a PMP. If the first
|
|
// has succeeded, we add the rest. If the first one failed, we remove it
|
|
// and try to make a call on another one.
|
|
//
|
|
|
|
ACQUIRE_ADAPTER_GEN_LOCK(pAdapt);
|
|
|
|
//
|
|
// Get the member we were trying to connect to.
|
|
//
|
|
for (pMember = pVc->pPMPMembers; pMember; pMember = pMember->pNext)
|
|
if(ATMSM_GET_MEMBER_STATE(pMember) == ATMSM_MEMBER_CONNECTING)
|
|
break;
|
|
|
|
ASSERT(NULL != pMember);
|
|
|
|
pVc->ulNumConnectingMembers--;
|
|
|
|
if (NDIS_STATUS_SUCCESS == Status){
|
|
|
|
ASSERT(NULL != NdisPartyHandle);
|
|
|
|
ATMSM_SET_MEMBER_STATE(pMember, ATMSM_MEMBER_CONNECTED);
|
|
|
|
pMember->NdisPartyHandle = NdisPartyHandle;
|
|
|
|
pVc->ulNumActiveMembers++;
|
|
|
|
//
|
|
// check if the member was invalidated during the call setup
|
|
// if so, remove this guy
|
|
//
|
|
if(ATMSM_IS_MEMBER_INVALID(pMember)){
|
|
|
|
RELEASE_ADAPTER_GEN_LOCK(pAdapt);
|
|
bLockReleased = TRUE;
|
|
|
|
// This member was invalidated, now drop him off
|
|
AtmSmDropMemberFromVc(pVc, pMember);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
DbgWarn(("MakeCall error %x, pMember %x to addr:", Status, pMember));
|
|
|
|
DumpATMAddress(ATMSMD_ERR, "", &pMember->HwAddr.Address);
|
|
|
|
RELEASE_ADAPTER_GEN_LOCK(pAdapt);
|
|
bLockReleased = TRUE;
|
|
|
|
//
|
|
// Connection failed. Delete this member from our list of members.
|
|
//
|
|
DeleteMemberInfoFromVc(pVc, pMember);
|
|
}
|
|
|
|
if(!bLockReleased) {
|
|
|
|
RELEASE_ADAPTER_GEN_LOCK(pAdapt);
|
|
}
|
|
|
|
//
|
|
// Add anymore members remaining
|
|
//
|
|
AtmSmConnectToPMPDestinations(pVc);
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
VOID
|
|
AtmSmIncomingCloseCall(
|
|
IN NDIS_STATUS CloseStatus,
|
|
IN NDIS_HANDLE ProtocolVcContext,
|
|
IN PVOID CloseData OPTIONAL,
|
|
IN UINT Size OPTIONAL
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Indication of an incoming close call from the network. If this
|
|
is not an outgoing PMP VC, then we mark the VC as inactive, and
|
|
move it to the Inactive VC list. If this is on PMP Vc,
|
|
there must be only one party on the PMP connection. We update
|
|
that member's state.
|
|
|
|
In any case, we call NdisClCloseCall to complete the handshake.
|
|
|
|
Arguments:
|
|
|
|
CloseStatus Status of Close
|
|
ProtocolVcContext Pointer to VC
|
|
CloseData Optional Close data (IGNORED)
|
|
Size Size of Optional Close Data (OPTIONAL)
|
|
|
|
Return Value:
|
|
|
|
None
|
|
|
|
--*/
|
|
{
|
|
PATMSM_VC pVc = (PATMSM_VC)ProtocolVcContext;
|
|
PATMSM_ADAPTER pAdapt = pVc->pAdapt;
|
|
NDIS_HANDLE NdisVcHandle = pVc->NdisVcHandle;
|
|
NDIS_HANDLE NdisPartyHandle;
|
|
PATMSM_PMP_MEMBER pMember;
|
|
NDIS_STATUS Status;
|
|
|
|
|
|
if (VC_TYPE_PMP_OUTGOING != pVc->VcType){
|
|
|
|
|
|
DbgInfo(("AtmSmIncomingCloseCall: On Vc 0x%x\n",
|
|
ProtocolVcContext));
|
|
|
|
ACQUIRE_ADAPTER_GEN_LOCK(pAdapt);
|
|
|
|
ASSERT (ATMSM_GET_VC_STATE(pVc) != ATMSM_VC_CLOSING);
|
|
|
|
NdisPartyHandle = NULL;
|
|
|
|
|
|
ATMSM_SET_VC_STATE(pVc, ATMSM_VC_CLOSING);
|
|
|
|
|
|
ASSERT(pVc->HwAddr.SubAddress == NULL);
|
|
|
|
RemoveEntryList(&pVc->List);
|
|
InsertHeadList(&pAdapt->InactiveVcHead, &pVc->List);
|
|
|
|
RELEASE_ADAPTER_GEN_LOCK(pAdapt);
|
|
|
|
pMember = NULL;
|
|
|
|
Status = NdisClCloseCall(NdisVcHandle, NdisPartyHandle, NULL, 0);
|
|
|
|
DbgInfo(("NdisCloseCall Status - 0x%X Vc - 0x%X\n", Status, pVc));
|
|
|
|
if (Status != NDIS_STATUS_PENDING){
|
|
|
|
AtmSmCloseCallComplete(Status, pVc, (NDIS_HANDLE)pMember);
|
|
}
|
|
|
|
} else {
|
|
|
|
//
|
|
// May be the net has gone bad
|
|
//
|
|
DbgInfo(("PMP IncomingCloseCall: On Vc %x\n", ProtocolVcContext));
|
|
|
|
AtmSmDisconnectVc(pVc);
|
|
}
|
|
}
|
|
|
|
|
|
VOID
|
|
AtmSmCloseCallComplete(
|
|
IN NDIS_STATUS Status,
|
|
IN NDIS_HANDLE ProtocolVcContext,
|
|
IN NDIS_HANDLE ProtocolPartyContext OPTIONAL
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This is called to complete our call to NdisClCloseCall. If the VC
|
|
is other than outgoing PMP, we update its state and dereference it
|
|
|
|
If this is an outgoing PMP, we delete the last member
|
|
|
|
Arguments:
|
|
|
|
Status Status of NdisClCloseCall
|
|
ProtocolVcContext Pointer to our VC structure
|
|
ProtocolPartyContext If the VC is PMP Vc, this is a pointer
|
|
to the Member that was disconnected.
|
|
|
|
Return Value:
|
|
|
|
None
|
|
|
|
--*/
|
|
{
|
|
PATMSM_VC pVc = (PATMSM_VC)ProtocolVcContext;
|
|
PATMSM_ADAPTER pAdapt = pVc->pAdapt;
|
|
BOOLEAN bStopping;
|
|
|
|
DbgInfo(("AtmSmCloseCallComplete: On Vc %lx\n", pVc));
|
|
|
|
ASSERT(Status == NDIS_STATUS_SUCCESS);
|
|
|
|
switch(pVc->VcType){
|
|
|
|
case VC_TYPE_INCOMING:
|
|
case VC_TYPE_PP_OUTGOING:
|
|
|
|
// Both incoming call and outgoing PP calls
|
|
|
|
ACQUIRE_ADAPTER_GEN_LOCK(pAdapt);
|
|
|
|
ASSERT (ATMSM_GET_VC_STATE(pVc) == ATMSM_VC_CLOSING);
|
|
|
|
ATMSM_SET_VC_STATE(pVc, ATMSM_VC_CLOSED);
|
|
|
|
RELEASE_ADAPTER_GEN_LOCK(pAdapt);
|
|
|
|
// Now dereference the VC
|
|
AtmSmDereferenceVc(pVc);
|
|
|
|
break;
|
|
|
|
|
|
case VC_TYPE_PMP_OUTGOING: {
|
|
|
|
// Outgoing PMP
|
|
|
|
ACQUIRE_ADAPTER_GEN_LOCK(pAdapt);
|
|
|
|
pVc->ulNumDroppingMembers--;
|
|
|
|
ATMSM_SET_VC_STATE(pVc, ATMSM_VC_CLOSED);
|
|
|
|
ASSERT(1 == pVc->ulNumTotalMembers);
|
|
ASSERT((0 == pVc->ulNumActiveMembers) &&
|
|
(0 == pVc->ulNumConnectingMembers) &&
|
|
(0 == pVc->ulNumDroppingMembers));
|
|
|
|
RELEASE_ADAPTER_GEN_LOCK(pAdapt);
|
|
|
|
if(DeleteMemberInfoFromVc(pVc,
|
|
(PATMSM_PMP_MEMBER)ProtocolPartyContext)){
|
|
|
|
}
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
ASSERT(FALSE);
|
|
|
|
}
|
|
}
|
|
|
|
|
|
VOID
|
|
AtmSmAddPartyComplete(
|
|
IN NDIS_STATUS Status,
|
|
IN NDIS_HANDLE ProtocolPartyContext,
|
|
IN NDIS_HANDLE NdisPartyHandle,
|
|
IN PCO_CALL_PARAMETERS CallParameters
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Completion of NdisClAddParty to add a new party to PMP Vc.
|
|
If successful, update the member's state. Otherwise, delete it.
|
|
|
|
Arguments:
|
|
|
|
Status Status of AddParty
|
|
ProtocolPartyContext Pointer to Member being added
|
|
NdisPartyHandle Valid if AddParty successful
|
|
CallParameters Pointer to AddParty call parameters
|
|
|
|
Return Value:
|
|
|
|
None
|
|
|
|
--*/
|
|
{
|
|
PATMSM_PMP_MEMBER pMember = (PATMSM_PMP_MEMBER)ProtocolPartyContext;
|
|
PATMSM_VC pVc = (PATMSM_VC)pMember->pVc;
|
|
PATMSM_ADAPTER pAdapt = (PATMSM_ADAPTER)pVc->pAdapt;
|
|
BOOLEAN bLockReleased = FALSE;
|
|
|
|
// Free the memory for CallParameters
|
|
AtmSmFreeMem(CallParameters);
|
|
|
|
DbgLoud(("AddPartyComplete: Status %x, pMember %x, NdisPartyHandle %x\n",
|
|
Status, pMember, NdisPartyHandle));
|
|
|
|
ACQUIRE_ADAPTER_GEN_LOCK(pAdapt);
|
|
|
|
pVc->ulNumConnectingMembers--;
|
|
|
|
if (NDIS_STATUS_SUCCESS == Status){
|
|
|
|
ATMSM_SET_MEMBER_STATE(pMember, ATMSM_MEMBER_CONNECTED);
|
|
|
|
ASSERT(NdisPartyHandle);
|
|
|
|
pMember->NdisPartyHandle = NdisPartyHandle;
|
|
|
|
pVc->ulNumActiveMembers++;
|
|
|
|
//
|
|
// check if the member was invalidated during the call setup
|
|
// if so, remove this guy
|
|
//
|
|
if(ATMSM_IS_MEMBER_INVALID(pMember)){
|
|
|
|
RELEASE_ADAPTER_GEN_LOCK(pAdapt);
|
|
bLockReleased = TRUE;
|
|
|
|
// This member was invalidated, now drop him off
|
|
AtmSmDropMemberFromVc(pVc, pMember);
|
|
}
|
|
|
|
} else {
|
|
|
|
DbgWarn(("MakeCall error %x, pMember %x to addr:", Status, pMember));
|
|
|
|
DumpATMAddress(ATMSMD_ERR, "", &pMember->HwAddr.Address);
|
|
|
|
RELEASE_ADAPTER_GEN_LOCK(pAdapt);
|
|
bLockReleased = TRUE;
|
|
|
|
//
|
|
// Connection failed. Delete this member from our list of members.
|
|
//
|
|
DeleteMemberInfoFromVc(pVc,
|
|
(PATMSM_PMP_MEMBER)ProtocolPartyContext);
|
|
|
|
}
|
|
|
|
if(!bLockReleased) {
|
|
|
|
RELEASE_ADAPTER_GEN_LOCK(pAdapt);
|
|
}
|
|
|
|
//
|
|
// Add anymore members remaining
|
|
//
|
|
AtmSmConnectToPMPDestinations(pVc);
|
|
|
|
}
|
|
|
|
|
|
VOID
|
|
AtmSmDropPartyComplete(
|
|
IN NDIS_STATUS Status,
|
|
IN NDIS_HANDLE ProtocolPartyContext
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This is called to signify completion of a previous NdisClDropParty,
|
|
to drop a member off a PMP Vc. Delete the member.
|
|
|
|
Arguments:
|
|
|
|
Status Status of DropParty
|
|
ProtocolPartyContext Pointer to Member being dropped
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
{
|
|
PATMSM_PMP_MEMBER pMember = (PATMSM_PMP_MEMBER)ProtocolPartyContext;
|
|
PATMSM_VC pVc = (PATMSM_VC)pMember->pVc;
|
|
PATMSM_ADAPTER pAdapt = (PATMSM_ADAPTER)pVc->pAdapt;
|
|
BOOLEAN IsVcClosing;
|
|
|
|
DbgInfo(("DropPartyComplete: Vc - %x Member - %x\n", pVc, pMember));
|
|
|
|
ASSERT(Status == NDIS_STATUS_SUCCESS);
|
|
|
|
ACQUIRE_ADAPTER_GEN_LOCK(pAdapt);
|
|
|
|
pVc->ulNumDroppingMembers--;
|
|
|
|
IsVcClosing = ((ATMSM_GET_VC_STATE(pVc) == ATMSM_VC_NEED_CLOSING) &&
|
|
(pVc->ulNumActiveMembers == 1) &&
|
|
((pVc->ulNumDroppingMembers + pVc->ulNumConnectingMembers)
|
|
== 0));
|
|
RELEASE_ADAPTER_GEN_LOCK(pAdapt);
|
|
|
|
//
|
|
// Delete this member info structure
|
|
//
|
|
DeleteMemberInfoFromVc(pVc, pMember);
|
|
|
|
//
|
|
// If this VC is closing remove the last member in it
|
|
// (This member will issue a close call).
|
|
//
|
|
if(IsVcClosing){
|
|
|
|
ASSERT(1 == pVc->ulNumTotalMembers);
|
|
|
|
AtmSmDropMemberFromVc(pVc, pVc->pPMPMembers);
|
|
}
|
|
}
|
|
|
|
|
|
VOID
|
|
AtmSmIncomingDropParty(
|
|
IN NDIS_STATUS DropStatus,
|
|
IN NDIS_HANDLE ProtocolPartyContext,
|
|
IN PVOID CloseData OPTIONAL,
|
|
IN UINT Size OPTIONAL
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Indication that a Member has dropped off the PMP Vc
|
|
We complete this handshake by calling NdisClDropParty.
|
|
|
|
Arguments:
|
|
|
|
DropStatus Status
|
|
ProtocolPartyContext Pointer to Member
|
|
CloseData Optional Close data (IGNORED)
|
|
Size Size of Optional Close Data (OPTIONAL)
|
|
|
|
Return Value:
|
|
|
|
None
|
|
|
|
--*/
|
|
{
|
|
PATMSM_PMP_MEMBER pMember = (PATMSM_PMP_MEMBER)ProtocolPartyContext;
|
|
PATMSM_VC pVc = (PATMSM_VC)pMember->pVc;
|
|
|
|
ASSERT(DropStatus == NDIS_STATUS_SUCCESS);
|
|
|
|
ASSERT(ATMSM_GET_MEMBER_STATE(pMember) == ATMSM_MEMBER_CONNECTED);
|
|
|
|
DbgInfo(("IncomingDropParty: pVc %x, pMember %x, Addr: ",
|
|
pVc, pMember));
|
|
|
|
DumpATMAddress(ATMSMD_INFO, "", &pMember->HwAddr.Address);
|
|
|
|
|
|
AtmSmDropMemberFromVc(pVc, pMember);
|
|
}
|
|
|
|
|
|
|
|
VOID
|
|
AtmSmIncomingCallQoSChange(
|
|
IN NDIS_HANDLE ProtocolVcContext,
|
|
IN PCO_CALL_PARAMETERS CallParameters
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
|
|
Arguments:
|
|
|
|
|
|
Return Value:
|
|
|
|
|
|
--*/
|
|
{
|
|
DbgWarn(("QoSChange: Ignored\n"));
|
|
}
|
|
|
|
|