windows-nt/Source/XPSP1/NT/net/atm/samples/atmsmpl/driver/callmgr.c
2020-09-26 16:20:57 +08:00

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"));
}