1572 lines
35 KiB
C
1572 lines
35 KiB
C
/*++
|
|
|
|
Copyright (c) 1990-1998 Microsoft Corporation, All Rights Reserved.
|
|
|
|
Module Name:
|
|
|
|
misc.c
|
|
|
|
Abstract:
|
|
|
|
This module contains several miscellaneous routines like, ReferenceVC
|
|
dereferenceVC etc.
|
|
|
|
|
|
Author:
|
|
|
|
Anil Francis Thomas (10/98)
|
|
|
|
Environment:
|
|
|
|
Kernel
|
|
|
|
Revision History:
|
|
DChen 092499 Remove try/except block in VerifyRecvOpenContext
|
|
|
|
--*/
|
|
#include "precomp.h"
|
|
#pragma hdrstop
|
|
|
|
|
|
#define MODULE_ID MODULE_MISC
|
|
|
|
|
|
NDIS_STATUS AtmSmAllocVc(
|
|
IN PATMSM_ADAPTER pAdapt,
|
|
OUT PATMSM_VC *ppVc,
|
|
IN ULONG VcType,
|
|
IN NDIS_HANDLE NdisVcHandle
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
This routine is used to create a VC structure and link to an adapter
|
|
|
|
Arguments:
|
|
pAdapt - Adapter structure
|
|
ppVc - pointer to a pointer of Vc
|
|
VcType - Type of VC to allocate (incoming, pmp outgoing etc)
|
|
|
|
Return Value:
|
|
|
|
NDIS_STATUS_SUCCESS if we could create a VC
|
|
NDIS_STATUS_RESOURCES no resources
|
|
NDIS_STATUS_CLOSING if we couldn't reference the adapter
|
|
--*/
|
|
{
|
|
PATMSM_VC pVc;
|
|
NDIS_STATUS Status;
|
|
|
|
*ppVc = NULL;
|
|
|
|
//
|
|
// Add a reference to the adapter for the VC (see if the adapter
|
|
// is closing)
|
|
//
|
|
if(!AtmSmReferenceAdapter(pAdapt))
|
|
return NDIS_STATUS_CLOSING;
|
|
|
|
//
|
|
// Allocate a Vc, initialize it and link it into the Adapter
|
|
//
|
|
|
|
AtmSmAllocMem(&pVc, PATMSM_VC, sizeof(ATMSM_VC));
|
|
|
|
if(NULL != pVc)
|
|
{
|
|
|
|
NdisZeroMemory(pVc, sizeof(ATMSM_VC));
|
|
|
|
pVc->ulSignature = atmsm_vc_signature;
|
|
|
|
pVc->NdisVcHandle = NdisVcHandle;
|
|
pVc->pAdapt = pAdapt;
|
|
pVc->ulRefCount = 1; // Dereferenced when DeleteVc is called.
|
|
pVc->VcType = VcType;
|
|
|
|
pVc->MaxSendSize = pAdapt->MaxPacketSize; // default
|
|
|
|
ATMSM_SET_VC_STATE(pVc, ATMSM_VC_IDLE);
|
|
|
|
ACQUIRE_ADAPTER_GEN_LOCK(pAdapt);
|
|
|
|
InsertHeadList(&pAdapt->InactiveVcHead, &pVc->List);
|
|
|
|
RELEASE_ADAPTER_GEN_LOCK(pAdapt);
|
|
|
|
Status = NDIS_STATUS_SUCCESS;
|
|
|
|
DbgInfo(("CreateVc: Created Vc %x\n", pVc));
|
|
|
|
}
|
|
else
|
|
{
|
|
|
|
// Not enough resources, hence remove the reference we added above
|
|
AtmSmDereferenceAdapter(pAdapt);
|
|
|
|
Status = NDIS_STATUS_RESOURCES;
|
|
|
|
DbgErr(("CreateVc: Failed - No resources\n"));
|
|
}
|
|
|
|
*ppVc = pVc;
|
|
|
|
return Status;
|
|
}
|
|
|
|
BOOLEAN AtmSmReferenceVc(
|
|
IN PATMSM_VC pVc
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Reference the VC.
|
|
|
|
Arguments:
|
|
|
|
pVc Pointer to the VC.
|
|
|
|
Return Value:
|
|
|
|
TRUE Referenced
|
|
FALSE Interface is closing, cannot reference.
|
|
|
|
--*/
|
|
{
|
|
PATMSM_ADAPTER pAdapt = pVc->pAdapt;
|
|
BOOLEAN rc = FALSE;
|
|
|
|
DbgInfo(("AtmSmReferenceVc - VC - 0x%X\n", pVc));
|
|
|
|
ACQUIRE_ADAPTER_GEN_LOCK(pAdapt);
|
|
|
|
if(ATMSM_GET_VC_STATE(pVc) != ATMSM_VC_CLOSING)
|
|
{
|
|
pVc->ulRefCount ++;
|
|
rc = TRUE;
|
|
}
|
|
|
|
RELEASE_ADAPTER_GEN_LOCK(pAdapt);
|
|
|
|
return rc;
|
|
}
|
|
|
|
ULONG AtmSmDereferenceVc(
|
|
IN PATMSM_VC pVc
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Dereference the VC. This could result in the VC to be deallocated.
|
|
|
|
Arguments:
|
|
|
|
pVc Pointer to the VC.
|
|
|
|
Return Value:
|
|
|
|
Reference count
|
|
|
|
--*/
|
|
{
|
|
PATMSM_ADAPTER pAdapt = pVc->pAdapt;
|
|
ULONG ulRet;
|
|
|
|
TraceIn(AtmSmDereferenceVc);
|
|
|
|
DbgInfo(("AtmSmDereferenceVc - VC - 0x%X\n", pVc));
|
|
|
|
ASSERT(pVc->ulRefCount > 0);
|
|
|
|
ACQUIRE_ADAPTER_GEN_LOCK(pAdapt);
|
|
|
|
ulRet = --pVc->ulRefCount;
|
|
|
|
if(0 == pVc->ulRefCount)
|
|
{
|
|
|
|
PIRP pIrp;
|
|
ULONG VcType = pVc->VcType;
|
|
NDIS_HANDLE NdisVcHandle = pVc->NdisVcHandle;
|
|
|
|
|
|
ASSERT (ATMSM_GET_VC_STATE(pVc) != ATMSM_VC_ACTIVE);
|
|
|
|
ASSERT (0 == pVc->ulNumTotalMembers);
|
|
|
|
// cleanup a connectIrp if it exists
|
|
pIrp = pVc->pConnectIrp;
|
|
pVc->pConnectIrp = NULL;
|
|
|
|
if(pIrp)
|
|
{
|
|
|
|
pIrp->IoStatus.Status = STATUS_UNSUCCESSFUL;
|
|
|
|
pIrp->IoStatus.Information = 0;
|
|
|
|
IoCompleteRequest(pIrp, IO_NETWORK_INCREMENT);
|
|
}
|
|
|
|
// Remove any send packets pending on the Vc
|
|
while(pVc->pSendPktNext)
|
|
{
|
|
|
|
PPROTO_RSVD pPRsvd;
|
|
PNDIS_PACKET pPacket;
|
|
|
|
pPacket = pVc->pSendPktNext;
|
|
|
|
pPRsvd = GET_PROTO_RSVD(pPacket);
|
|
|
|
pVc->pSendPktNext = pPRsvd->pPktNext;
|
|
|
|
// this is the last packet
|
|
if(pVc->pSendLastPkt == pPacket)
|
|
pVc->pSendLastPkt = NULL;
|
|
|
|
pVc->ulSendPktsCount--;
|
|
|
|
RELEASE_ADAPTER_GEN_LOCK(pAdapt);
|
|
|
|
AtmSmCoSendComplete(NDIS_STATUS_CLOSING, (NDIS_HANDLE)pVc, pPacket);
|
|
|
|
ACQUIRE_ADAPTER_GEN_LOCK(pAdapt);
|
|
}
|
|
|
|
|
|
RemoveEntryList(&pVc->List);
|
|
|
|
// this is important - since memory is not cleared
|
|
pVc->ulSignature = atmsm_dead_vc_signature;
|
|
pVc->pAdapt = NULL;
|
|
|
|
AtmSmFreeMem(pVc);
|
|
|
|
// Release the lock on the adapter
|
|
RELEASE_ADAPTER_GEN_LOCK(pAdapt);
|
|
|
|
if(((VC_TYPE_PP_OUTGOING == VcType) ||
|
|
(VC_TYPE_PMP_OUTGOING == VcType)) &&
|
|
NdisVcHandle != NULL)
|
|
{
|
|
|
|
(VOID)NdisCoDeleteVc(NdisVcHandle);
|
|
}
|
|
|
|
// dereference the adapter (to remove the VC reference)
|
|
// should be done after releasing the lock
|
|
AtmSmDereferenceAdapter(pAdapt);
|
|
|
|
}
|
|
else
|
|
{
|
|
|
|
// Release the lock on the adapter
|
|
RELEASE_ADAPTER_GEN_LOCK(pAdapt);
|
|
}
|
|
|
|
TraceOut(AtmSmDereferenceVc);
|
|
|
|
return ulRet;
|
|
}
|
|
|
|
BOOLEAN DeleteMemberInfoFromVc(
|
|
IN PATMSM_VC pVc,
|
|
IN PATMSM_PMP_MEMBER pMemberToRemove
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
The specified member structure is removed from the VC and the
|
|
structure is freed.
|
|
|
|
Arguments:
|
|
pVc Pointer to the VC.
|
|
|
|
Return Value:
|
|
TRUE - if removed
|
|
FALSE - otherwise
|
|
|
|
--*/
|
|
{
|
|
PATMSM_ADAPTER pAdapt = pVc->pAdapt;
|
|
PATMSM_PMP_MEMBER pMember;
|
|
PATMSM_PMP_MEMBER pPrevMember = NULL;
|
|
|
|
TraceIn(DeleteMemberInfoFromVc);
|
|
|
|
ACQUIRE_ADAPTER_GEN_LOCK(pAdapt);
|
|
|
|
for(pMember = pVc->pPMPMembers; pMember;
|
|
pPrevMember = pMember, pMember = pMember->pNext)
|
|
if(pMember == pMemberToRemove)
|
|
break;
|
|
|
|
ASSERT(pMember);
|
|
|
|
if(!pMember)
|
|
{
|
|
|
|
RELEASE_ADAPTER_GEN_LOCK(pAdapt);
|
|
return FALSE;
|
|
}
|
|
|
|
if(!pPrevMember)
|
|
{
|
|
|
|
pVc->pPMPMembers = pMember->pNext;
|
|
|
|
}
|
|
else
|
|
{
|
|
|
|
pPrevMember->pNext = pMember->pNext;
|
|
}
|
|
|
|
AtmSmFreeMem(pMember);
|
|
|
|
pVc->ulNumTotalMembers--;
|
|
|
|
RELEASE_ADAPTER_GEN_LOCK(pAdapt);
|
|
|
|
|
|
// Now dereference the VC
|
|
AtmSmDereferenceVc(pVc);
|
|
|
|
TraceOut(DeleteMemberInfoFromVc);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
VOID AtmSmDisconnectVc(
|
|
IN PATMSM_VC pVc
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
This routine can be used to disconnect a P-P VC or disconnect
|
|
all members of a PMP Vc
|
|
|
|
Arguments:
|
|
pVc - Pointer to the VC.
|
|
|
|
Return Value:
|
|
NONE
|
|
|
|
--*/
|
|
{
|
|
NDIS_STATUS Status;
|
|
PATMSM_ADAPTER pAdapt = pVc->pAdapt;
|
|
|
|
TraceIn(AtmSmDisconnectVc);
|
|
|
|
ACQUIRE_ADAPTER_GEN_LOCK(pAdapt);
|
|
|
|
if(VC_TYPE_PMP_OUTGOING != pVc->VcType)
|
|
{
|
|
|
|
//
|
|
// This is a PP VC
|
|
//
|
|
if((ATMSM_GET_VC_STATE(pVc) == ATMSM_VC_SETUP_IN_PROGRESS) ||
|
|
(ATMSM_GET_VC_STATE(pVc) == ATMSM_VC_ACTIVE))
|
|
{
|
|
|
|
ATMSM_SET_VC_STATE(pVc, ATMSM_VC_CLOSING);
|
|
|
|
RELEASE_ADAPTER_GEN_LOCK(pAdapt);
|
|
|
|
Status = NdisClCloseCall(
|
|
pVc->NdisVcHandle,
|
|
NULL, // No party Handle
|
|
NULL, // No Buffer
|
|
0 // Size of above
|
|
);
|
|
|
|
if(NDIS_STATUS_PENDING != Status)
|
|
{
|
|
|
|
AtmSmCloseCallComplete(
|
|
Status,
|
|
(NDIS_HANDLE)pVc,
|
|
(NDIS_HANDLE)NULL
|
|
);
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
|
|
if(ATMSM_GET_VC_STATE(pVc) == ATMSM_VC_IDLE)
|
|
{
|
|
|
|
RELEASE_ADAPTER_GEN_LOCK(pAdapt);
|
|
|
|
// remove the reference added to the VC while creating
|
|
AtmSmDereferenceVc(pVc);
|
|
}
|
|
else
|
|
{
|
|
|
|
RELEASE_ADAPTER_GEN_LOCK(pAdapt);
|
|
|
|
}
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
|
|
PATMSM_PMP_MEMBER pMember;
|
|
|
|
// this is a PMP VC
|
|
|
|
//
|
|
// Find a member that we haven't tried drop on.
|
|
//
|
|
while(TRUE)
|
|
{
|
|
|
|
for(pMember = pVc->pPMPMembers; pMember != NULL;
|
|
pMember = pMember->pNext)
|
|
{
|
|
|
|
if(0 == (pMember->ulFlags & ATMSM_MEMBER_DROP_TRIED))
|
|
{
|
|
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
if(!pMember) // we are done with all members
|
|
break;
|
|
|
|
RELEASE_ADAPTER_GEN_LOCK(pAdapt);
|
|
|
|
AtmSmDropMemberFromVc(pVc, pMember);
|
|
|
|
ACQUIRE_ADAPTER_GEN_LOCK(pAdapt);
|
|
}
|
|
|
|
RELEASE_ADAPTER_GEN_LOCK(pAdapt);
|
|
|
|
// remove the reference added to the VC while creating
|
|
AtmSmDereferenceVc(pVc);
|
|
}
|
|
|
|
TraceOut(AtmSmDisconnectVc);
|
|
}
|
|
|
|
VOID AtmSmDropMemberFromVc(
|
|
IN PATMSM_VC pVc,
|
|
IN PATMSM_PMP_MEMBER pMemberToDrop
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
This is used to drop a member from a PMP VC. This could be
|
|
called as a result of incoming Drop request, or we are
|
|
initiating a drop request.
|
|
|
|
Handle all cases
|
|
(a) Not connected to PMP Vc
|
|
(b) Connection being setup (MakeCall or AddParty in progress)
|
|
(c) Connected to PMP Vc
|
|
|
|
Arguments:
|
|
pVc - Pointer to the VC.
|
|
pMemberToDrop - pointer to a member that is being dropped
|
|
|
|
Return Value:
|
|
NONE
|
|
|
|
--*/
|
|
{
|
|
PATMSM_ADAPTER pAdapt = (PATMSM_ADAPTER)pVc->pAdapt;
|
|
BOOLEAN bLockReleased = FALSE;
|
|
NDIS_STATUS Status;
|
|
NDIS_HANDLE NdisVcHandle;
|
|
NDIS_HANDLE NdisPartyHandle;
|
|
|
|
TraceIn(AtmSmDropMemberFromVc);
|
|
|
|
DbgInfo(("pAdapt %x, pVc %x pMember %x, ConnSt %x, PartyHandle %x\n",
|
|
pAdapt, pVc, pMemberToDrop, ATMSM_GET_MEMBER_STATE(pMemberToDrop),
|
|
pMemberToDrop->NdisPartyHandle));
|
|
|
|
ACQUIRE_ADAPTER_GEN_LOCK(pAdapt);
|
|
|
|
pMemberToDrop->ulFlags |= ATMSM_MEMBER_DROP_TRIED;
|
|
|
|
switch(ATMSM_GET_MEMBER_STATE(pMemberToDrop))
|
|
{
|
|
|
|
case ATMSM_MEMBER_CONNECTED:
|
|
|
|
NdisPartyHandle = pMemberToDrop->NdisPartyHandle;
|
|
|
|
ASSERT(NdisPartyHandle != NULL);
|
|
|
|
if((pVc->ulNumActiveMembers + pVc->ulNumConnectingMembers)
|
|
> 1)
|
|
{
|
|
|
|
//
|
|
// This is not the last member in connected or connecting
|
|
// state. Hence use DropParty.
|
|
//
|
|
|
|
ATMSM_SET_MEMBER_STATE(pMemberToDrop, ATMSM_MEMBER_CLOSING);
|
|
|
|
pVc->ulNumActiveMembers--;
|
|
pVc->ulNumDroppingMembers++;
|
|
|
|
RELEASE_ADAPTER_GEN_LOCK(pAdapt);
|
|
bLockReleased = TRUE;
|
|
|
|
Status = NdisClDropParty(
|
|
NdisPartyHandle,
|
|
NULL,
|
|
0
|
|
);
|
|
|
|
if(NDIS_STATUS_PENDING != Status)
|
|
{
|
|
|
|
AtmSmDropPartyComplete(
|
|
Status,
|
|
(NDIS_HANDLE)pMemberToDrop
|
|
);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
|
|
//
|
|
// This is the last active party. Check if any DropParty()'s are
|
|
// yet to finish.
|
|
//
|
|
if(0 != pVc->ulNumDroppingMembers)
|
|
{
|
|
//
|
|
// This member will have to wait till all DropParty()s are
|
|
// complete. Mark the ClusterControlVc so that we send
|
|
// a CloseCall() when all DropParty()s are done.
|
|
//
|
|
ATMSM_SET_VC_STATE(pVc, ATMSM_VC_NEED_CLOSING);
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Last active party, and no DropParty pending.
|
|
//
|
|
NdisVcHandle = pVc->NdisVcHandle;
|
|
|
|
|
|
ATMSM_SET_VC_STATE(pVc, ATMSM_VC_CLOSING);
|
|
ATMSM_SET_MEMBER_STATE(pMemberToDrop, ATMSM_MEMBER_CLOSING);
|
|
|
|
pVc->ulNumActiveMembers--;
|
|
pVc->ulNumDroppingMembers++;
|
|
|
|
RELEASE_ADAPTER_GEN_LOCK(pAdapt);
|
|
bLockReleased = TRUE;
|
|
|
|
Status = NdisClCloseCall(
|
|
NdisVcHandle,
|
|
NdisPartyHandle,
|
|
NULL,
|
|
0
|
|
);
|
|
|
|
if(NDIS_STATUS_PENDING != Status)
|
|
{
|
|
|
|
AtmSmCloseCallComplete(
|
|
Status,
|
|
(NDIS_HANDLE)pVc,
|
|
(NDIS_HANDLE)pMemberToDrop
|
|
);
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
|
|
case ATMSM_MEMBER_CONNECTING:
|
|
//
|
|
// Mark it so that we'll delete it when the AddParty/MakeCall
|
|
// completes.
|
|
//
|
|
pMemberToDrop->ulFlags |= ATMSM_MEMBER_INVALID;
|
|
break;
|
|
|
|
case ATMSM_MEMBER_CLOSING:
|
|
NOTHING;
|
|
break;
|
|
|
|
case ATMSM_MEMBER_IDLE:
|
|
//
|
|
// No connection. Just unlink this from the IntF and free it.
|
|
//
|
|
|
|
RELEASE_ADAPTER_GEN_LOCK(pAdapt);
|
|
bLockReleased = TRUE;
|
|
|
|
DeleteMemberInfoFromVc(pVc, pMemberToDrop);
|
|
break;
|
|
|
|
default:
|
|
ASSERT(FALSE);
|
|
break;
|
|
}
|
|
|
|
if(!bLockReleased)
|
|
{
|
|
|
|
RELEASE_ADAPTER_GEN_LOCK(pAdapt);
|
|
}
|
|
|
|
TraceOut(AtmSmDropMemberFromVc);
|
|
}
|
|
|
|
PCO_CALL_PARAMETERS AtmSmPrepareCallParameters(
|
|
IN PATMSM_ADAPTER pAdapt,
|
|
IN PHW_ADDR pHwAddr,
|
|
IN BOOLEAN IsMakeCall,
|
|
IN BOOLEAN IsMultipointVC
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Allocate and fill in call parameters for use in a MakeCall
|
|
|
|
Arguments:
|
|
|
|
pAdapt - Ptr to Adapter
|
|
pHwAddr - Points to the Called ATM address and subaddress
|
|
IsMakeCall - MakeCall or AddParty
|
|
|
|
Return Value:
|
|
|
|
Allocated Call Parameter
|
|
|
|
--*/
|
|
{
|
|
PATMSM_FLOW_SPEC pFlowSpec;
|
|
PCO_CALL_PARAMETERS pCallParameters;
|
|
PCO_CALL_MANAGER_PARAMETERS pCallMgrParameters;
|
|
|
|
PQ2931_CALLMGR_PARAMETERS pAtmCallMgrParameters;
|
|
|
|
//
|
|
// All Info Elements that we need to fill:
|
|
//
|
|
Q2931_IE UNALIGNED * pIe;
|
|
AAL_PARAMETERS_IE UNALIGNED * pAalIe;
|
|
ATM_TRAFFIC_DESCRIPTOR_IE UNALIGNED * pTrafficDescriptor;
|
|
ATM_BROADBAND_BEARER_CAPABILITY_IE UNALIGNED * pBbc;
|
|
ATM_BLLI_IE UNALIGNED * pBlli;
|
|
ATM_QOS_CLASS_IE UNALIGNED * pQos;
|
|
|
|
ULONG RequestSize;
|
|
|
|
RequestSize = sizeof(CO_CALL_PARAMETERS) +
|
|
sizeof(CO_CALL_MANAGER_PARAMETERS) +
|
|
sizeof(Q2931_CALLMGR_PARAMETERS) +
|
|
(IsMakeCall? ATMSM_MAKE_CALL_IE_SPACE :
|
|
ATMSM_ADD_PARTY_IE_SPACE);
|
|
|
|
AtmSmAllocMem(&pCallParameters, PCO_CALL_PARAMETERS, RequestSize);
|
|
|
|
if(NULL == pCallParameters)
|
|
{
|
|
|
|
return(pCallParameters);
|
|
}
|
|
|
|
pFlowSpec = &(pAdapt->VCFlowSpec);
|
|
|
|
//
|
|
// Zero out everything
|
|
//
|
|
NdisZeroMemory((PUCHAR)pCallParameters, RequestSize);
|
|
|
|
//
|
|
// Distribute space amongst the various structures
|
|
//
|
|
pCallMgrParameters = (PCO_CALL_MANAGER_PARAMETERS)
|
|
((PUCHAR)pCallParameters +
|
|
sizeof(CO_CALL_PARAMETERS));
|
|
|
|
|
|
//
|
|
// Set pointers to link the above structures together
|
|
//
|
|
pCallParameters->CallMgrParameters = pCallMgrParameters;
|
|
pCallParameters->MediaParameters = (PCO_MEDIA_PARAMETERS)NULL;
|
|
|
|
|
|
pCallMgrParameters->CallMgrSpecific.ParamType = 0;
|
|
pCallMgrParameters->CallMgrSpecific.Length =
|
|
sizeof(Q2931_CALLMGR_PARAMETERS) +
|
|
(IsMakeCall? ATMSM_MAKE_CALL_IE_SPACE :
|
|
ATMSM_ADD_PARTY_IE_SPACE);
|
|
|
|
pAtmCallMgrParameters = (PQ2931_CALLMGR_PARAMETERS)
|
|
pCallMgrParameters->CallMgrSpecific.Parameters;
|
|
|
|
if(IsMultipointVC)
|
|
pCallParameters->Flags |= MULTIPOINT_VC;
|
|
|
|
//
|
|
// Call Manager generic flow parameters:
|
|
//
|
|
pCallMgrParameters->Transmit.TokenRate = (pFlowSpec->SendBandwidth);
|
|
pCallMgrParameters->Transmit.TokenBucketSize = (pFlowSpec->SendMaxSize);
|
|
pCallMgrParameters->Transmit.MaxSduSize = pFlowSpec->SendMaxSize;
|
|
pCallMgrParameters->Transmit.PeakBandwidth = (pFlowSpec->SendBandwidth);
|
|
pCallMgrParameters->Transmit.ServiceType = pFlowSpec->ServiceType;
|
|
|
|
//
|
|
// We are setting up unidirectional calls, so receive side values are 0's.
|
|
// Note: for PMP it should be 0 in all cases
|
|
//
|
|
pCallMgrParameters->Receive.ServiceType = pFlowSpec->ServiceType;
|
|
|
|
//
|
|
// Q2931 Call Manager Parameters:
|
|
//
|
|
|
|
//
|
|
// Called address:
|
|
//
|
|
//
|
|
pAtmCallMgrParameters->CalledParty = pHwAddr->Address;
|
|
|
|
// NOTE: Add Called Subaddress IE for E164.
|
|
|
|
//
|
|
// Calling address:
|
|
//
|
|
pAtmCallMgrParameters->CallingParty = pAdapt->ConfiguredAddress;
|
|
|
|
//
|
|
// RFC 1755 (Sec 5) says that the following IEs MUST be present in the
|
|
// SETUP message, so fill them all.
|
|
//
|
|
// AAL Parameters
|
|
// Traffic Descriptor (MakeCall only)
|
|
// Broadband Bearer Capability (MakeCall only)
|
|
// Broadband Low Layer Info
|
|
// QoS (MakeCall only)
|
|
//
|
|
|
|
//
|
|
// Initialize the Info Element list
|
|
//
|
|
pAtmCallMgrParameters->InfoElementCount = 0;
|
|
pIe = (PQ2931_IE)(pAtmCallMgrParameters->InfoElements);
|
|
|
|
|
|
//
|
|
// AAL Parameters:
|
|
//
|
|
|
|
{
|
|
UNALIGNED AAL5_PARAMETERS *pAal5;
|
|
|
|
pIe->IEType = IE_AALParameters;
|
|
pIe->IELength = SIZEOF_Q2931_IE + SIZEOF_AAL_PARAMETERS_IE;
|
|
pAalIe = (PAAL_PARAMETERS_IE)pIe->IE;
|
|
pAalIe->AALType = AAL_TYPE_AAL5;
|
|
pAal5 = &(pAalIe->AALSpecificParameters.AAL5Parameters);
|
|
pAal5->ForwardMaxCPCSSDUSize = pFlowSpec->SendMaxSize;
|
|
pAal5->BackwardMaxCPCSSDUSize = pFlowSpec->ReceiveMaxSize;
|
|
}
|
|
|
|
pAtmCallMgrParameters->InfoElementCount++;
|
|
pIe = (PQ2931_IE)((PUCHAR)pIe + pIe->IELength);
|
|
|
|
|
|
//
|
|
// Traffic Descriptor:
|
|
//
|
|
|
|
if(IsMakeCall)
|
|
{
|
|
|
|
pIe->IEType = IE_TrafficDescriptor;
|
|
pIe->IELength = SIZEOF_Q2931_IE + SIZEOF_ATM_TRAFFIC_DESCR_IE;
|
|
pTrafficDescriptor = (PATM_TRAFFIC_DESCRIPTOR_IE)pIe->IE;
|
|
|
|
if(SERVICETYPE_BESTEFFORT == pFlowSpec->ServiceType)
|
|
{
|
|
|
|
pTrafficDescriptor->ForwardTD.PeakCellRateCLP01 =
|
|
BYTES_TO_CELLS(pFlowSpec->SendBandwidth);
|
|
pTrafficDescriptor->BestEffort = TRUE;
|
|
|
|
}
|
|
else
|
|
{
|
|
|
|
// Predictive/Guaranteed service
|
|
// (we map this to CBR, see BBC below)
|
|
|
|
pTrafficDescriptor->ForwardTD.PeakCellRateCLP01 =
|
|
BYTES_TO_CELLS(pFlowSpec->SendBandwidth);
|
|
pTrafficDescriptor->BestEffort = FALSE;
|
|
}
|
|
|
|
pAtmCallMgrParameters->InfoElementCount++;
|
|
pIe = (PQ2931_IE)((PUCHAR)pIe + pIe->IELength);
|
|
}
|
|
|
|
//
|
|
// Broadband Bearer Capability
|
|
//
|
|
|
|
if(IsMakeCall)
|
|
{
|
|
|
|
pIe->IEType = IE_BroadbandBearerCapability;
|
|
pIe->IELength = SIZEOF_Q2931_IE + SIZEOF_ATM_BBC_IE;
|
|
pBbc = (PATM_BROADBAND_BEARER_CAPABILITY_IE)pIe->IE;
|
|
|
|
pBbc->BearerClass = BCOB_X;
|
|
pBbc->UserPlaneConnectionConfig = UP_P2P;
|
|
if(SERVICETYPE_BESTEFFORT == pFlowSpec->ServiceType)
|
|
{
|
|
|
|
pBbc->TrafficType = TT_NOIND;
|
|
pBbc->TimingRequirements = TR_NOIND;
|
|
pBbc->ClippingSusceptability = CLIP_NOT;
|
|
|
|
}
|
|
else
|
|
{
|
|
|
|
pBbc->TrafficType = TT_CBR;
|
|
pBbc->TimingRequirements = TR_END_TO_END;
|
|
pBbc->ClippingSusceptability = CLIP_SUS;
|
|
}
|
|
|
|
pAtmCallMgrParameters->InfoElementCount++;
|
|
pIe = (PQ2931_IE)((PUCHAR)pIe + pIe->IELength);
|
|
}
|
|
|
|
//
|
|
// Broadband Lower Layer Information
|
|
//
|
|
|
|
pIe->IEType = IE_BLLI;
|
|
pIe->IELength = SIZEOF_Q2931_IE + SIZEOF_ATM_BLLI_IE;
|
|
pBlli = (PATM_BLLI_IE)pIe->IE;
|
|
NdisMoveMemory((PUCHAR)pBlli,
|
|
(PUCHAR)&AtmSmDefaultBlli,
|
|
sizeof(ATM_BLLI_IE));
|
|
|
|
pAtmCallMgrParameters->InfoElementCount++;
|
|
pIe = (PQ2931_IE)((PUCHAR)pIe + pIe->IELength);
|
|
|
|
//
|
|
// QoS
|
|
//
|
|
|
|
if(IsMakeCall)
|
|
{
|
|
|
|
pIe->IEType = IE_QOSClass;
|
|
pIe->IELength = SIZEOF_Q2931_IE + SIZEOF_ATM_QOS_IE;
|
|
pQos = (PATM_QOS_CLASS_IE)pIe->IE;
|
|
if(SERVICETYPE_BESTEFFORT == pFlowSpec->ServiceType)
|
|
{
|
|
pQos->QOSClassForward = pQos->QOSClassBackward = 0;
|
|
|
|
}
|
|
else
|
|
{
|
|
|
|
pQos->QOSClassForward = pQos->QOSClassBackward = 1;
|
|
}
|
|
|
|
pAtmCallMgrParameters->InfoElementCount++;
|
|
pIe = (PQ2931_IE)((PUCHAR)pIe + pIe->IELength);
|
|
}
|
|
|
|
return(pCallParameters);
|
|
}
|
|
|
|
NTSTATUS VerifyRecvOpenContext(
|
|
PATMSM_ADAPTER pAdapt
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
This routine is used to verify that an open context passed is valid
|
|
|
|
Note: we add a reference on the adapter
|
|
|
|
Arguments:
|
|
|
|
Return Value:
|
|
|
|
--*/
|
|
{
|
|
NTSTATUS Status = STATUS_SUCCESS;
|
|
|
|
PATMSM_ADAPTER pAdapter;
|
|
ULONG ulNum = 0;
|
|
|
|
if(pAdapt == NULL)
|
|
{
|
|
return STATUS_UNSUCCESSFUL;
|
|
}
|
|
|
|
ACQUIRE_GLOBAL_LOCK();
|
|
|
|
// walk the adapter list to see if this adapter exists
|
|
for(pAdapter = AtmSmGlobal.pAdapterList; pAdapter &&
|
|
ulNum < AtmSmGlobal.ulAdapterCount;
|
|
pAdapter = pAdapter->pAdapterNext)
|
|
{
|
|
if(pAdapt == pAdapter)
|
|
break;
|
|
}
|
|
|
|
if(pAdapter == NULL || ulNum == AtmSmGlobal.ulAdapterCount)
|
|
{
|
|
RELEASE_GLOBAL_LOCK();
|
|
return STATUS_UNSUCCESSFUL;
|
|
}
|
|
|
|
if(atmsm_adapter_signature != pAdapt->ulSignature)
|
|
Status = STATUS_INVALID_PARAMETER;
|
|
else
|
|
{
|
|
if(AtmSmReferenceAdapter(pAdapt))
|
|
{
|
|
if(FALSE == pAdapt->fAdapterOpenedForRecv)
|
|
{
|
|
Status = STATUS_INVALID_PARAMETER;
|
|
|
|
// remove the reference
|
|
AtmSmDereferenceAdapter(pAdapt);
|
|
}
|
|
}
|
|
else
|
|
Status = STATUS_UNSUCCESSFUL;
|
|
}
|
|
|
|
RELEASE_GLOBAL_LOCK();
|
|
|
|
return Status;
|
|
}
|
|
|
|
NTSTATUS VerifyConnectContext(
|
|
PATMSM_VC pVc
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
This routine is used to verify that a connect context passed is valid
|
|
|
|
Note: we add a reference on the VC
|
|
|
|
Arguments:
|
|
|
|
Return Value:
|
|
|
|
--*/
|
|
{
|
|
NTSTATUS Status = STATUS_SUCCESS;
|
|
|
|
try
|
|
{
|
|
|
|
if((atmsm_vc_signature != pVc->ulSignature) ||
|
|
(NULL == pVc->pAdapt))
|
|
Status = STATUS_INVALID_PARAMETER;
|
|
else
|
|
{
|
|
|
|
if(!AtmSmReferenceVc(pVc))
|
|
Status = STATUS_UNSUCCESSFUL;
|
|
else
|
|
{
|
|
|
|
PATMSM_ADAPTER pAdapt = pVc->pAdapt;
|
|
|
|
if(atmsm_adapter_signature != pAdapt->ulSignature)
|
|
{
|
|
Status = STATUS_INVALID_PARAMETER;
|
|
|
|
// remove the VC reference
|
|
AtmSmDereferenceVc(pVc);
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
}except(EXCEPTION_EXECUTE_HANDLER)
|
|
{
|
|
|
|
Status = GetExceptionCode();
|
|
DbgErr(("VerifyConnectContext: CC 0x%x exception - 0x%x\n",
|
|
pVc, Status));
|
|
return Status;
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
UINT CopyPacketToIrp(
|
|
PIRP pIrp,
|
|
PNDIS_PACKET pPkt
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
This routine is used to copy the connects of a packet into the user supplied
|
|
buffer.
|
|
|
|
Arguments:
|
|
|
|
Return Value:
|
|
|
|
--*/
|
|
{
|
|
PNDIS_BUFFER pPktBuffer;
|
|
PVOID pPktBufferVA, pDstBufferVA;
|
|
UINT uiBufSize, uiTotalLen, uiMdlSizeLeft;
|
|
UINT uiCopySize, uiTotalBytesCopied;
|
|
|
|
NdisGetFirstBufferFromPacketSafe(pPkt,
|
|
&pPktBuffer,
|
|
&pPktBufferVA,
|
|
&uiBufSize,
|
|
&uiTotalLen,
|
|
NormalPagePriority);
|
|
|
|
if (pPktBufferVA == NULL)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
ASSERT(pPktBuffer && (0 != uiBufSize));
|
|
|
|
uiTotalBytesCopied = 0;
|
|
|
|
uiMdlSizeLeft = MmGetMdlByteCount(pIrp->MdlAddress);
|
|
|
|
pDstBufferVA = MmGetSystemAddressForMdlSafe(pIrp->MdlAddress, NormalPagePriority);
|
|
if(pDstBufferVA != NULL && uiMdlSizeLeft != 0)
|
|
{
|
|
while(pPktBuffer)
|
|
{
|
|
uiCopySize = (uiMdlSizeLeft < uiBufSize) ? uiMdlSizeLeft :uiBufSize;
|
|
|
|
// copy the data
|
|
NdisMoveMemory(pDstBufferVA, pPktBufferVA, uiCopySize);
|
|
|
|
pDstBufferVA = (PVOID) ((PCHAR)pDstBufferVA + uiCopySize);
|
|
uiTotalBytesCopied += uiCopySize;
|
|
|
|
uiMdlSizeLeft -= uiCopySize;
|
|
|
|
if(uiMdlSizeLeft <= 0)
|
|
break;
|
|
|
|
// get the next buffer
|
|
NdisGetNextBuffer(pPktBuffer, &pPktBuffer);
|
|
|
|
// get details of the new buffer
|
|
if(pPktBuffer)
|
|
{
|
|
NdisQueryBufferSafe(pPktBuffer, &pPktBufferVA, &uiBufSize, NormalPagePriority);
|
|
if(pPktBufferVA == NULL)
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
return uiTotalBytesCopied;
|
|
}
|
|
|
|
VOID AtmSmRecvReturnTimerFunction (
|
|
IN PVOID SystemSpecific1,
|
|
IN PVOID FunctionContext,
|
|
IN PVOID SystemSpecific2,
|
|
IN PVOID SystemSpecific3
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This timer function, checks to see there are any buffered packets that has
|
|
been around for a while. If so it gives the packet back to the miniport
|
|
driver.
|
|
It queues itself back if there are anymore packets in the queue
|
|
|
|
We use NdisGetSystemUpTime, since that is all the resolution we want
|
|
|
|
Arguments:
|
|
|
|
SystemSpecific1 - Not used
|
|
FunctionContext - Adapter
|
|
SystemSpecific2 - Not used
|
|
SystemSpecific3 - Not used
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
{
|
|
PATMSM_ADAPTER pAdapt = (PATMSM_ADAPTER)FunctionContext;
|
|
ULONG ulTime;
|
|
BOOLEAN bShouldQueueTimerAgain = FALSE;
|
|
|
|
ACQUIRE_ADAPTER_GEN_LOCK(pAdapt);
|
|
|
|
pAdapt->fRecvTimerQueued = FALSE;
|
|
|
|
NdisGetSystemUpTime(&ulTime);
|
|
|
|
|
|
// check if any packets have been sitting around for long
|
|
// if so, return them
|
|
|
|
while(pAdapt->pRecvPktNext)
|
|
{
|
|
|
|
PPROTO_RSVD pPRsvd;
|
|
PNDIS_PACKET pPkt;
|
|
|
|
pPkt = pAdapt->pRecvPktNext;
|
|
pPRsvd = GET_PROTO_RSVD(pPkt);
|
|
|
|
if((ulTime - pPRsvd->ulTime) >= RECV_BUFFERING_TIME)
|
|
{
|
|
|
|
pAdapt->pRecvPktNext = pPRsvd->pPktNext;
|
|
|
|
if(pAdapt->pRecvLastPkt == pPkt)
|
|
pAdapt->pRecvLastPkt = NULL;
|
|
|
|
DbgVeryLoud(("Returning a packet that was buffered too long\n"));
|
|
|
|
pAdapt->ulRecvPktsCount--;
|
|
|
|
// release the recv queue lock
|
|
RELEASE_ADAPTER_GEN_LOCK(pAdapt);
|
|
|
|
// return the packet to the miniport
|
|
NdisReturnPackets(&pPkt, 1);
|
|
|
|
ACQUIRE_ADAPTER_GEN_LOCK(pAdapt);
|
|
|
|
}
|
|
else
|
|
{
|
|
|
|
// time hasn't expired for this packet
|
|
ulTime = RECV_BUFFERING_TIME - (ulTime - pPRsvd->ulTime);
|
|
|
|
bShouldQueueTimerAgain = TRUE;
|
|
|
|
break;
|
|
}
|
|
}
|
|
|
|
if(bShouldQueueTimerAgain)
|
|
{
|
|
|
|
SET_ADAPTER_RECV_TIMER(pAdapt, ulTime);
|
|
}
|
|
|
|
RELEASE_ADAPTER_GEN_LOCK(pAdapt);
|
|
|
|
return;
|
|
}
|
|
|
|
VOID AtmSmConnectToPMPDestinations(
|
|
IN PATMSM_VC pVc
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This will make a call to the destination in PMP case. It will MakeCall
|
|
to the first member. Subsequent destinations are added using AddParty.
|
|
|
|
Arguments:
|
|
|
|
pVc - Ptr to a PMP Vc
|
|
|
|
Return Value:
|
|
|
|
None
|
|
|
|
--*/
|
|
{
|
|
PATMSM_ADAPTER pAdapt = (PATMSM_ADAPTER)pVc->pAdapt;
|
|
BOOLEAN bLockReleased = FALSE;
|
|
PCO_CALL_PARAMETERS pCallParameters;
|
|
NDIS_HANDLE ProtocolVcContext;
|
|
NDIS_HANDLE ProtocolPartyContext;
|
|
NDIS_STATUS Status;
|
|
PATMSM_PMP_MEMBER pMember;
|
|
|
|
TraceIn(AtmSmConnectToPMPDestinations);
|
|
|
|
ASSERT(VC_TYPE_PMP_OUTGOING == pVc->VcType);
|
|
|
|
ACQUIRE_ADAPTER_GEN_LOCK(pAdapt);
|
|
|
|
do
|
|
{ // break off loop
|
|
|
|
// First find any member addresses that is not yet connected
|
|
for(pMember = pVc->pPMPMembers; pMember; pMember = pMember->pNext)
|
|
if(ATMSM_GET_MEMBER_STATE(pMember) == ATMSM_MEMBER_IDLE)
|
|
break;
|
|
|
|
// if there are no - more members to be connected then get out
|
|
if(!pMember)
|
|
{
|
|
break;
|
|
}
|
|
|
|
ProtocolVcContext = (NDIS_HANDLE)pVc;
|
|
ProtocolPartyContext = (NDIS_HANDLE)pMember;
|
|
|
|
//
|
|
// First see if we have connected 1 or more members
|
|
//
|
|
if(0 == pVc->ulNumActiveMembers)
|
|
{
|
|
// No one is connected yet, so do a MakeCall
|
|
|
|
ASSERT(ATMSM_GET_VC_STATE(pVc) != ATMSM_VC_ACTIVE);
|
|
|
|
if(NULL == pVc->NdisVcHandle)
|
|
{
|
|
|
|
Status = NdisCoCreateVc(
|
|
pAdapt->NdisBindingHandle,
|
|
pAdapt->NdisAfHandle,
|
|
(NDIS_HANDLE)pVc,
|
|
&pVc->NdisVcHandle
|
|
);
|
|
|
|
if(NDIS_STATUS_SUCCESS != Status)
|
|
{
|
|
|
|
break;
|
|
}
|
|
|
|
DbgVeryLoud(("AddMembers: Created VC, VC %x, NdisVcHandle %x\n",
|
|
pVc, pVc->NdisVcHandle));
|
|
}
|
|
|
|
ASSERT(NULL != pVc->NdisVcHandle);
|
|
|
|
pCallParameters = AtmSmPrepareCallParameters(pAdapt,
|
|
&pMember->HwAddr,
|
|
TRUE,
|
|
TRUE);
|
|
if(pCallParameters == (PCO_CALL_PARAMETERS)NULL)
|
|
{
|
|
|
|
Status = NdisCoDeleteVc(pVc->NdisVcHandle);
|
|
ASSERT(NDIS_STATUS_SUCCESS == Status);
|
|
|
|
pVc->NdisVcHandle = NULL;
|
|
Status = NDIS_STATUS_RESOURCES;
|
|
|
|
break;
|
|
}
|
|
|
|
ATMSM_SET_VC_STATE(pVc, ATMSM_VC_SETUP_IN_PROGRESS);
|
|
|
|
ATMSM_SET_MEMBER_STATE(pMember, ATMSM_MEMBER_CONNECTING);
|
|
|
|
pVc->ulNumConnectingMembers++;
|
|
|
|
RELEASE_ADAPTER_GEN_LOCK(pAdapt);
|
|
bLockReleased = TRUE;
|
|
|
|
Status = NdisClMakeCall(
|
|
pVc->NdisVcHandle,
|
|
pCallParameters,
|
|
ProtocolPartyContext,
|
|
&pMember->NdisPartyHandle
|
|
);
|
|
|
|
if(NDIS_STATUS_PENDING != Status)
|
|
{
|
|
|
|
AtmSmMakeCallComplete(
|
|
Status,
|
|
ProtocolVcContext,
|
|
pMember->NdisPartyHandle,
|
|
pCallParameters
|
|
);
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
// we have atleast one connected member, add the rest using AddParty
|
|
|
|
ASSERT(NULL != pVc->NdisVcHandle);
|
|
|
|
pCallParameters = AtmSmPrepareCallParameters(pAdapt,
|
|
&pMember->HwAddr,
|
|
FALSE,
|
|
TRUE);
|
|
if(pCallParameters == (PCO_CALL_PARAMETERS)NULL)
|
|
{
|
|
|
|
Status = NDIS_STATUS_RESOURCES;
|
|
break;
|
|
}
|
|
|
|
|
|
ATMSM_SET_VC_STATE(pVc, ATMSM_VC_ADDING_PARTIES);
|
|
|
|
ATMSM_SET_MEMBER_STATE(pMember, ATMSM_MEMBER_CONNECTING);
|
|
|
|
pVc->ulNumConnectingMembers++;
|
|
|
|
RELEASE_ADAPTER_GEN_LOCK(pAdapt);
|
|
bLockReleased = TRUE;
|
|
|
|
Status = NdisClAddParty(
|
|
pVc->NdisVcHandle,
|
|
ProtocolPartyContext,
|
|
pCallParameters,
|
|
&pMember->NdisPartyHandle
|
|
);
|
|
|
|
if(NDIS_STATUS_PENDING != Status)
|
|
{
|
|
|
|
AtmSmAddPartyComplete(
|
|
Status,
|
|
ProtocolPartyContext,
|
|
pMember->NdisPartyHandle,
|
|
pCallParameters
|
|
);
|
|
}
|
|
|
|
}
|
|
|
|
}while(FALSE);
|
|
|
|
if(!bLockReleased)
|
|
{
|
|
|
|
RELEASE_ADAPTER_GEN_LOCK(pAdapt);
|
|
}
|
|
|
|
|
|
if(pVc->ulNumActiveMembers &&
|
|
(pVc->ulNumActiveMembers == pVc->ulNumTotalMembers))
|
|
{
|
|
|
|
PIRP pIrp;
|
|
|
|
//
|
|
// 1 or more members are connected, send any packets pending on the VC.
|
|
//
|
|
ACQUIRE_ADAPTER_GEN_LOCK(pAdapt);
|
|
|
|
DbgInfo(("PMP VC 0x%x connected - %u members\n", pVc,
|
|
pVc->ulNumActiveMembers));
|
|
|
|
ATMSM_SET_VC_STATE(pVc, ATMSM_VC_ACTIVE);
|
|
|
|
// 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
|
|
{
|
|
|
|
if(0 == pVc->ulNumTotalMembers)
|
|
{
|
|
|
|
// now complete IRP that started this connect call
|
|
PIRP pIrp = pVc->pConnectIrp;
|
|
|
|
pVc->pConnectIrp = NULL;
|
|
|
|
ASSERT(pIrp);
|
|
|
|
if(pIrp)
|
|
{
|
|
|
|
pIrp->IoStatus.Status = STATUS_UNSUCCESSFUL;
|
|
|
|
pIrp->IoStatus.Information = 0;
|
|
|
|
IoCompleteRequest(pIrp, IO_NETWORK_INCREMENT);
|
|
}
|
|
|
|
DbgInfo(("PMP VC 0x%x failed to connect any members\n", pVc));
|
|
|
|
// Cleanup the VC - remove the reference added at create
|
|
AtmSmDereferenceVc(pVc);
|
|
}
|
|
}
|
|
|
|
TraceOut(AtmSmConnectToPMPDestinations);
|
|
}
|
|
|
|
VOID AtmSmConnectPPVC(
|
|
IN PATMSM_VC pVc
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This will make a call to the destination in PP case. It will MakeCall
|
|
to the destination.
|
|
|
|
Arguments:
|
|
|
|
pVc - Ptr to a PP Vc
|
|
|
|
Return Value:
|
|
|
|
None
|
|
|
|
--*/
|
|
{
|
|
PATMSM_ADAPTER pAdapt = (PATMSM_ADAPTER)pVc->pAdapt;
|
|
BOOLEAN bLockReleased = FALSE;
|
|
PCO_CALL_PARAMETERS pCallParameters;
|
|
NDIS_HANDLE ProtocolVcContext;
|
|
NDIS_STATUS Status;
|
|
|
|
TraceIn(AtmSmConnectPPVC);
|
|
|
|
ASSERT(VC_TYPE_PP_OUTGOING == pVc->VcType);
|
|
|
|
ACQUIRE_ADAPTER_GEN_LOCK(pAdapt);
|
|
|
|
do
|
|
{ // break off loop
|
|
|
|
ProtocolVcContext = (NDIS_HANDLE)pVc;
|
|
|
|
ASSERT(ATMSM_GET_VC_STATE(pVc) != ATMSM_VC_ACTIVE);
|
|
|
|
ASSERT(NULL == pVc->NdisVcHandle);
|
|
|
|
if(NULL == pVc->NdisVcHandle)
|
|
{
|
|
|
|
Status = NdisCoCreateVc(
|
|
pAdapt->NdisBindingHandle,
|
|
pAdapt->NdisAfHandle,
|
|
(NDIS_HANDLE)pVc,
|
|
&pVc->NdisVcHandle
|
|
);
|
|
|
|
if(NDIS_STATUS_SUCCESS != Status)
|
|
{
|
|
|
|
break;
|
|
}
|
|
|
|
DbgVeryLoud(("Connect: Created VC, VC %x, NdisVcHandle %x\n",
|
|
pVc, pVc->NdisVcHandle));
|
|
}
|
|
|
|
ASSERT(NULL != pVc->NdisVcHandle);
|
|
|
|
pCallParameters = AtmSmPrepareCallParameters(pAdapt,
|
|
&pVc->HwAddr,
|
|
TRUE,
|
|
FALSE);
|
|
if(pCallParameters == (PCO_CALL_PARAMETERS)NULL)
|
|
{
|
|
|
|
Status = NdisCoDeleteVc(pVc->NdisVcHandle);
|
|
pVc->NdisVcHandle = NULL;
|
|
|
|
Status = NDIS_STATUS_RESOURCES;
|
|
break;
|
|
}
|
|
|
|
ATMSM_SET_VC_STATE(pVc, ATMSM_VC_SETUP_IN_PROGRESS);
|
|
|
|
RELEASE_ADAPTER_GEN_LOCK(pAdapt);
|
|
bLockReleased = TRUE;
|
|
|
|
Status = NdisClMakeCall(
|
|
pVc->NdisVcHandle,
|
|
pCallParameters,
|
|
NULL,
|
|
NULL
|
|
);
|
|
|
|
if(NDIS_STATUS_PENDING != Status)
|
|
{
|
|
|
|
AtmSmMakeCallComplete(
|
|
Status,
|
|
ProtocolVcContext,
|
|
NULL,
|
|
pCallParameters
|
|
);
|
|
}
|
|
|
|
}while(FALSE);
|
|
|
|
if(!bLockReleased)
|
|
{
|
|
|
|
RELEASE_ADAPTER_GEN_LOCK(pAdapt);
|
|
}
|
|
|
|
|
|
TraceOut(AtmSmConnectPPVC);
|
|
}
|
|
|
|
|