windows-nt/Source/XPSP1/NT/net/rras/ndis/ndproxy/pxcl.c
2020-09-26 16:20:57 +08:00

1131 lines
27 KiB
C

/*++
Copyright (c) 1995-1996 Microsoft Corporation
Module Name:
pxcl.c
Abstract:
The module contains the calls to the proxy client from NDIS.
Author:
Richard Machin (RMachin)
Revision History:
Who When What
-------- -------- ----------------------------------------------
RMachin 10-3-96 created
TonyBe 02-21-99 re-work/re-write
Notes:
--*/
#include "precomp.h"
#define MODULE_NUMBER MODULE_CL
#define _FILENUMBER 'LCXP'
NDIS_STATUS
PxClCreateVc(
IN NDIS_HANDLE ProtocolAfContext,
IN NDIS_HANDLE NdisVcHandle,
OUT PNDIS_HANDLE ProtocolVcContext
)
{
NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
PPX_CL_AF pClAf;
PPX_VC pVc;
PXDEBUGP(PXD_LOUD, PXM_CL,
("PxClCreateVc: ClAf %p\n", ProtocolAfContext));
pClAf = (PPX_CL_AF)ProtocolAfContext;
NdisAcquireSpinLock(&pClAf->Lock);
if (pClAf->State != PX_AF_OPENED) {
PXDEBUGP(PXD_WARNING, PXM_CL,
("PxClCreateVc: Invalid AfState ClAf %p, State %x\n",
pClAf, pClAf->State));
NdisReleaseSpinLock(&pClAf->Lock);
return (NDIS_STATUS_FAILURE);
}
pVc = PxAllocateVc(pClAf);
if (pVc == NULL) {
PXDEBUGP(PXD_WARNING, PXM_CL,
("PxClCreateVc: Error allocating memory\n"));
NdisReleaseSpinLock(&pClAf->Lock);
return (NDIS_STATUS_RESOURCES);
}
pVc->ClVcHandle = NdisVcHandle;
NdisReleaseSpinLock(&pClAf->Lock);
if (!InsertVcInTable(pVc)) {
PXDEBUGP(PXD_WARNING, PXM_CL,
("PxClCreateVc: failed to insert in vc table\n"));
PxFreeVc(pVc);
return (NDIS_STATUS_RESOURCES);
}
*ProtocolVcContext = (NDIS_HANDLE)pVc->hdCall;
PXDEBUGP(PXD_LOUD, PXM_CL,
("PxClCreateVc: Exit\n"));
return(NDIS_STATUS_SUCCESS);
}
NDIS_STATUS
PxClDeleteVc(
IN NDIS_HANDLE ProtocolVcContext
)
{
PPX_VC pVc;
NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
PXDEBUGP(PXD_LOUD, PXM_CL,
("PxClDeleteVc: Enter\n"));
GetVcFromCtx(ProtocolVcContext, &pVc);
if (pVc == NULL) {
PXDEBUGP(PXD_WARNING, PXM_CL,
("PxClDeleteVc: VcCtx invalid %x\n", ProtocolVcContext));
return (NDIS_STATUS_FAILURE);
}
ASSERT(pVc->State == PX_VC_IDLE);
//
// Deref for ref applied when we allocated the Vc.
// We do not need the full deref code as the ref
// applied at entry will keep the vc around.
//
pVc->RefCount--;
//
// Deref for ref applied at entry when
// validating the vc
//
DEREF_VC(pVc);
PXDEBUGP(PXD_LOUD, PXM_CL,
("PxClDeleteVc: Exit, Status %x\n", Status));
return (Status);
}
NDIS_STATUS
PxClRequest(
IN NDIS_HANDLE ProtocolAfContext,
IN NDIS_HANDLE ProtocolVcContext OPTIONAL,
IN NDIS_HANDLE ProtocolPartyContext OPTIONAL,
IN OUT PNDIS_REQUEST NdisRequest
)
/*++
Routine Description:
This is called by an underlying cm/mp to send an ndisrequest to
a client. Since we might be proxying on behalf of multiple clients
we need to broadcast this request on to all clients that have
opened our address family for this adapter. We are interested in
OID_CO_AF_CLOSE so that we can cleanup our open on the Af and
OID_GEN_CO_LINK_SPEED so that we can get changes in linkspeed
on the adapter (and Vc if active).
Arguments:
Return Value:
--*/
{
PPX_CL_AF pClAf;
PPX_CM_AF pCmAf;
PPX_ADAPTER pAdapter;
PPX_VC pVc = NULL;
NDIS_STATUS Status;
NDIS_HANDLE VcHandle;
//
// The Vc returned here could be NULL as this
// request might not be on vc.
//
GetVcFromCtx(ProtocolVcContext, &pVc);
pClAf = (PPX_CL_AF)ProtocolAfContext;
pAdapter = pClAf->Adapter;
PXDEBUGP(PXD_LOUD, PXM_CL,
("PxClRequest: ClAf %p, Vc %p\n", pClAf, pVc));
ASSERT(KeGetCurrentIrql() < DISPATCH_LEVEL);
switch (NdisRequest->DATA.QUERY_INFORMATION.Oid) {
case OID_CO_AF_CLOSE:
{
PPX_TAPI_PROVIDER TapiProvider;
NdisAcquireSpinLock(&pAdapter->Lock);
RemoveEntryList(&pClAf->Linkage);
InsertTailList(&pAdapter->ClAfClosingList, &pClAf->Linkage);
NdisReleaseSpinLock(&pAdapter->Lock);
//
// We need to cleanup and close the open
// on this af. This would include tearing
// down all active calls (Vc's), deregistering
// all saps and closing the af.
//
NdisAcquireSpinLock(&pClAf->Lock);
//
// Mark the Af as closing...
//
pClAf->State = PX_AF_CLOSING;
TapiProvider = pClAf->TapiProvider;
NdisReleaseSpinLock(&pClAf->Lock);
//
// Take all tapi devices associated with
// this address family offline
//
if (TapiProvider != NULL) {
NdisAcquireSpinLock(&TapiProvider->Lock);
MarkProviderOffline(TapiProvider);
NdisReleaseSpinLock(&TapiProvider->Lock);
}
//
// Build list of Vc's that need attention
//
NdisAcquireSpinLock(&pClAf->Lock);
while (!IsListEmpty(&pClAf->VcList)) {
PLIST_ENTRY Entry;
PPX_VC pActiveVc;
Entry = RemoveHeadList(&pClAf->VcList);
InsertHeadList(&pClAf->VcClosingList, Entry);
pActiveVc = CONTAINING_RECORD(Entry, PX_VC, ClAfLinkage);
NdisReleaseSpinLock(&pClAf->Lock);
NdisAcquireSpinLock(&pActiveVc->Lock);
pActiveVc->CloseFlags |= PX_VC_CLOSE_AF;
REF_VC(pActiveVc);
PxVcCleanup(pActiveVc, 0);
DEREF_VC_LOCKED(pActiveVc);
NdisAcquireSpinLock(&pClAf->Lock);
}
//
// Get rid of all of the saps
//
{
PLIST_ENTRY pe;
PPX_CL_SAP pClSap;
pe = pClAf->ClSapList.Flink;
pClSap =
CONTAINING_RECORD(pe, PX_CL_SAP, Linkage);
while ((PVOID)pClSap != (PVOID)&pClAf->ClSapList) {
if (InterlockedCompareExchange((PLONG)&pClSap->State,
PX_SAP_CLOSING,
PX_SAP_OPENED)) {
RemoveEntryList(&pClSap->Linkage);
InsertTailList(&pClAf->ClSapClosingList, &pClSap->Linkage);
NdisReleaseSpinLock(&pClAf->Lock);
ClearSapWithTapiLine(pClSap);
Status = NdisClDeregisterSap(pClSap->NdisSapHandle);
if (Status != NDIS_STATUS_PENDING) {
PxClDeregisterSapComplete(Status, pClSap);
}
NdisAcquireSpinLock(&pClAf->Lock);
pe = pClAf->ClSapList.Flink;
pClSap =
CONTAINING_RECORD(pe, PX_CL_SAP, Linkage);
} else {
pe = pClSap->Linkage.Flink;
pClSap =
CONTAINING_RECORD(pe, PX_CL_SAP, Linkage);
}
}
}
DEREF_CL_AF_LOCKED(pClAf);
//
// Now broadcast this close to all of the clients
// we have using this adapter/af.
//
NdisAcquireSpinLock(&pAdapter->Lock);
while (!IsListEmpty(&pAdapter->CmAfList)) {
PX_REQUEST ProxyRequest;
PPX_REQUEST pProxyRequest = &ProxyRequest;
ULONG Info = 0;
PNDIS_REQUEST NdisRequest;
pCmAf = (PPX_CM_AF)RemoveHeadList(&pAdapter->CmAfList);
InsertTailList(&pAdapter->CmAfClosingList, &pCmAf->Linkage);
NdisReleaseSpinLock(&pAdapter->Lock);
NdisAcquireSpinLock(&pCmAf->Lock);
pCmAf->State = PX_AF_CLOSING;
REF_CM_AF(pCmAf);
NdisReleaseSpinLock(&pCmAf->Lock);
NdisZeroMemory(pProxyRequest, sizeof(PX_REQUEST));
NdisRequest = &pProxyRequest->NdisRequest;
NdisRequest->RequestType =
NdisRequestSetInformation;
NdisRequest->DATA.QUERY_INFORMATION.Oid =
OID_CO_AF_CLOSE;
NdisRequest->DATA.QUERY_INFORMATION.InformationBuffer =
&Info;
NdisRequest->DATA.QUERY_INFORMATION.InformationBufferLength =
sizeof(ULONG);
PxInitBlockStruc(&pProxyRequest->Block);
Status = NdisCoRequest(pAdapter->CmBindingHandle,
pCmAf->NdisAfHandle,
NULL,
NULL,
NdisRequest);
if (Status == NDIS_STATUS_PENDING) {
Status = PxBlock(&pProxyRequest->Block);
}
DEREF_CM_AF(pCmAf);
NdisAcquireSpinLock(&pAdapter->Lock);
}
NdisReleaseSpinLock(&pAdapter->Lock);
}
break;
case OID_GEN_CO_LINK_SPEED:
//
// We need to record the new speed of
// the vc.
//
break;
default:
//
// Just pass it through
//
break;
}
VcHandle = (pVc != NULL) ? pVc->CmVcHandle : NULL;
//
// Now broadcast this request up to all of the Clients
// that have opend our af for this adapter.
//
NdisAcquireSpinLock(&pAdapter->Lock);
pCmAf = (PPX_CM_AF)pAdapter->CmAfList.Flink;
while ((PVOID)pCmAf != (PVOID)&pAdapter->CmAfList) {
PPX_CM_AF NextAf;
PX_REQUEST ProxyRequest;
PPX_REQUEST pProxyRequest = &ProxyRequest;
NextAf =
(PPX_CM_AF)pCmAf->Linkage.Flink;
NdisAcquireSpinLock(&pCmAf->Lock);
if (pCmAf->State != PX_AF_OPENED) {
NdisReleaseSpinLock(&pCmAf->Lock);
pCmAf = NextAf;
continue;
}
REF_CM_AF(pCmAf);
NdisReleaseSpinLock(&pCmAf->Lock);
NdisZeroMemory(pProxyRequest, sizeof(PX_REQUEST));
NdisMoveMemory(&pProxyRequest->NdisRequest, NdisRequest, sizeof(NDIS_REQUEST));
NdisReleaseSpinLock(&pAdapter->Lock);
PxInitBlockStruc(&pProxyRequest->Block);
Status = NdisCoRequest(pAdapter->CmBindingHandle,
pCmAf->NdisAfHandle,
VcHandle,
NULL,
&pProxyRequest->NdisRequest);
if (Status == NDIS_STATUS_PENDING) {
PxBlock(&pProxyRequest->Block);
}
NdisAcquireSpinLock(&pAdapter->Lock);
//
// deref for the ref applied before we
// propagated this request
//
DEREF_CM_AF(pCmAf);
pCmAf = NextAf;
}
NdisReleaseSpinLock(&pAdapter->Lock);
//
// Remove ref applied when we attempted to
// map the vcctx to a vcptr at entry.
//
DEREF_VC(pVc);
ASSERT(KeGetCurrentIrql() < DISPATCH_LEVEL);
return (NDIS_STATUS_SUCCESS);
}
VOID
PxClRequestComplete(
IN NDIS_STATUS Status,
IN NDIS_HANDLE ProtocolAfContext,
IN NDIS_HANDLE ProtocolVcContext, // Optional
IN NDIS_HANDLE ProtocolPartyContext, // Optional
IN PNDIS_REQUEST NdisRequest
)
{
PPX_REQUEST pProxyRequest;
PPX_CL_AF pClAf;
PPX_VC pVc = NULL;
pClAf = (PPX_CL_AF)ProtocolAfContext;
//
// The Vc returned here could be NULL as this
// request might not be on vc.
//
GetVcFromCtx(ProtocolVcContext, &pVc);
PXDEBUGP(PXD_LOUD, PXM_CL,
("PxClRequestComplete: ClAf %p, Vc %p, Oid: %x, Status %x\n",
pClAf, pVc, NdisRequest->DATA.QUERY_INFORMATION.Oid, Status));
pProxyRequest = CONTAINING_RECORD(NdisRequest, PX_REQUEST, NdisRequest);
if (pProxyRequest->Flags & PX_REQ_ASYNC) {
pProxyRequest->Flags &= ~PX_REQ_ASYNC;
PxFreeMem(pProxyRequest);
} else {
PxSignal(&pProxyRequest->Block, Status);
}
//
// Remove ref applied when we attempted to
// map the vcctx to a vcptr at entry.
//
DEREF_VC(pVc);
}
VOID
PxClOpenAfComplete(
IN NDIS_STATUS Status,
IN NDIS_HANDLE ProtocolAfContext,
IN NDIS_HANDLE NdisAfHandle
)
{
PPX_CL_AF pClAf;
pClAf = (PPX_CL_AF)ProtocolAfContext;
PXDEBUGP(PXD_LOUD, PXM_CL,
("PxClOpenAfComplete: ClAf %p, Status %x\n", pClAf, Status));
pClAf->NdisAfHandle = NdisAfHandle;
PxSignal(&pClAf->Block, Status);
}
VOID
PxClCloseAfComplete(
IN NDIS_STATUS Status,
IN NDIS_HANDLE ProtocolAfContext
)
{
PPX_CL_AF pClAf;
PPX_ADAPTER pAdapter;
PPX_TAPI_PROVIDER TapiProvider;
pClAf = (PPX_CL_AF)ProtocolAfContext;
pAdapter = pClAf->Adapter;
PXDEBUGP(PXD_LOUD, PXM_CL,
("PxClCloseAfComplete: ClAf %p, Status %x\n", pClAf, Status));
ASSERT(KeGetCurrentIrql() < DISPATCH_LEVEL);
NdisAcquireSpinLock(&pAdapter->Lock);
RemoveEntryList(&pClAf->Linkage);
DEREF_ADAPTER_LOCKED(pAdapter);
NdisAcquireSpinLock(&pClAf->Lock);
pClAf->State = PX_AF_CLOSED;
TapiProvider = pClAf->TapiProvider;
pClAf->TapiProvider = NULL;
NdisReleaseSpinLock(&pClAf->Lock);
if (TapiProvider != NULL) {
NdisAcquireSpinLock(&TapiProvider->Lock);
MarkProviderOffline(TapiProvider);
NdisReleaseSpinLock(&TapiProvider->Lock);
}
PxFreeClAf(pClAf);
ASSERT(KeGetCurrentIrql() < DISPATCH_LEVEL);
}
VOID
PxClRegisterSapComplete(
IN NDIS_STATUS Status,
IN NDIS_HANDLE ProtocolSapContext,
IN PCO_SAP pSap,
IN NDIS_HANDLE NdisSapHandle
)
{
PPX_CL_SAP pClSap;
PPX_CL_AF pClAf;
PPX_TAPI_LINE TapiLine;
pClSap = (PPX_CL_SAP)ProtocolSapContext;
pClAf = pClSap->ClAf;
TapiLine = pClSap->TapiLine;
PXDEBUGP(PXD_LOUD, PXM_CL,
("PxClRegisterSapComplete: ClSap %p, Status %x\n", pClSap, Status));
if (Status != NDIS_STATUS_SUCCESS) {
InterlockedExchange((PLONG)&pClSap->State, PX_SAP_CLOSED);
NdisAcquireSpinLock(&pClAf->Lock);
RemoveEntryList(&pClSap->Linkage);
DEREF_CL_AF_LOCKED(pClAf);
TapiLine->ClSap = NULL;
PxFreeClSap(pClSap);
return;
}
pClSap->NdisSapHandle = NdisSapHandle;
NdisAcquireSpinLock(&pClAf->Lock);
if (pClAf->State != PX_AF_OPENED) {
//
// the af is no longer open so we to deregister
// this sap
//
NdisReleaseSpinLock(&pClAf->Lock);
InterlockedExchange((PLONG)&pClSap->State, PX_SAP_CLOSING);
Status = NdisClDeregisterSap(pClSap->NdisSapHandle);
if (Status != NDIS_STATUS_PENDING) {
PxClDeregisterSapComplete(Status, pClSap);
}
return;
}
NdisReleaseSpinLock(&pClAf->Lock);
NdisAcquireSpinLock(&TapiLine->Lock);
if (TapiLine->DevStatus->ulNumOpens == 0) {
NdisReleaseSpinLock(&TapiLine->Lock);
//
// There are not any opens on the line so we
// need to deregister the sap
//
InterlockedExchange((PLONG)&pClSap->State, PX_SAP_CLOSING);
Status = NdisClDeregisterSap(pClSap->NdisSapHandle);
if (Status != NDIS_STATUS_PENDING) {
PxClDeregisterSapComplete(Status, pClSap);
}
return;
}
NdisReleaseSpinLock(&TapiLine->Lock);
InterlockedExchange((PLONG)&pClSap->State, PX_SAP_OPENED);
}
VOID
PxClDeregisterSapComplete(
IN NDIS_STATUS Status,
IN NDIS_HANDLE ProtocolSapContext
)
{
PPX_CL_SAP pClSap;
PPX_CL_AF pClAf;
pClSap = (PPX_CL_SAP)ProtocolSapContext;
pClAf = pClSap->ClAf;
PXDEBUGP(PXD_LOUD, PXM_CL,
("PxClDeregisterSapComplete: ClSap %p, Status %x\n", pClSap, Status));
NdisAcquireSpinLock(&pClAf->Lock);
RemoveEntryList(&pClSap->Linkage);
DEREF_CL_AF_LOCKED(pClAf);
InterlockedExchange((PLONG)&pClSap->State, PX_SAP_CLOSED);
PxFreeClSap(pClSap);
}
VOID
PxClMakeCallComplete(
IN NDIS_STATUS Status,
IN NDIS_HANDLE ProtocolVcContext,
IN NDIS_HANDLE ProxyNdisPartyHandle OPTIONAL,
IN PCO_CALL_PARAMETERS pCallParameters
)
{
PPX_VC pVc;
PPX_CL_AF pClAf;
ULONG ulCallState;
ULONG ulCallStateMode;
BOOLEAN TapiStateChange;
PXDEBUGP(PXD_LOUD, PXM_CL,
("PxClMakeCallComplete: VcCtx %x, Status %x\n", ProtocolVcContext, Status));
GetVcFromCtx(ProtocolVcContext, &pVc);
if (pVc == NULL) {
PXDEBUGP(PXD_WARNING, PXM_CL,
("PxClMakeCallComplete: pVc invalid %x\n", ProtocolVcContext));
return;
}
TapiStateChange = TRUE;
NdisAcquireSpinLock(&pVc->Lock);
ASSERT(pVc->Flags & PX_VC_OWNER);
do {
if (pVc->Flags & PX_VC_OUTCALL_ABORTED) {
//
// This call has been aborted while
// in the PROCEEDING state. This means
// that the CloseCallComplete has run
// and did our cleanup so just get
// out.
//
break;
} else if (pVc->Flags & PX_VC_OUTCALL_ABORTING) {
pVc->Flags &= ~PX_VC_OUTCALL_ABORTING;
pVc->Flags |= PX_VC_OUTCALL_ABORTED;
}
ASSERT((pVc->State == PX_VC_DISCONNECTING) ||
(pVc->State == PX_VC_PROCEEDING));
if (Status == NDIS_STATUS_SUCCESS) {
//
// This means that we received a drop from tapi
// while the ClMakeCall was pending.
//
if (pVc->State == PX_VC_DISCONNECTING) {
//
// We need to drop the call with the
// call manager/miniport
//
pVc->Flags &= ~PX_VC_OUTCALL_ABORTED;
PxCloseCallWithCm(pVc);
TapiStateChange = FALSE;
} else {
ulCallState = LINECALLSTATE_CONNECTED;
ulCallStateMode = 0;
pVc->PrevState = pVc->State;
pVc->State = PX_VC_CONNECTED;
}
} else {
ulCallState = LINECALLSTATE_DISCONNECTED;
ulCallStateMode =
PxMapNdisStatusToTapiDisconnectMode(Status, TRUE);
//
// Remove the ref applied before we
// call NdisClMakeCall. We don't need
// to do the full deref code here as the
// ref applied when we mapped the vc will
// keep the vc around!
//
pVc->RefCount--;
pVc->PrevState = pVc->State;
pVc->State = PX_VC_IDLE;
}
if (TapiStateChange == TRUE) {
SendTapiCallState(pVc,
ulCallState,
ulCallStateMode,
pVc->CallInfo->ulMediaMode);
}
if (pVc->Flags & PX_VC_DROP_PENDING){
PxTapiCompleteDropIrps(pVc, Status);
}
} while (FALSE);
//
// Deref for ref applied when mapping the context.
// This releases the Vc lock!
//
DEREF_VC_LOCKED(pVc);
}
VOID
PxClModifyCallQosComplete(
IN NDIS_STATUS Status,
IN NDIS_HANDLE ProtocolVcContext,
IN PCO_CALL_PARAMETERS CallParameters
)
{
}
VOID
PxClCloseCallComplete(
IN NDIS_STATUS Status,
IN NDIS_HANDLE ProtocolVcContext,
IN NDIS_HANDLE ProtocolPartyContext OPTIONAL
)
{
PPX_VC pVc;
PPX_CL_AF pClAf;
PXDEBUGP(PXD_LOUD, PXM_CL,
("PxClCloseCallComplete: VcCtx %x, Status %x\n", ProtocolVcContext, Status));
GetVcFromCtx(ProtocolVcContext, &pVc);
if (pVc == NULL) {
PXDEBUGP(PXD_WARNING, PXM_CL,
("PxClCloseCallComplete: pVc invalid %x\n", ProtocolVcContext));
return;
}
NdisAcquireSpinLock(&pVc->Lock);
do {
//
// The closecall did not take (atm does
// not support receiving a closecall while
// an outgoing call is proceeding). We
// need to get out and cleanup later.
//
if (Status != NDIS_STATUS_SUCCESS) {
pVc->Flags |= PX_VC_CLEANUP_CM;
pVc->CloseFlags |= PX_VC_CM_CLOSE_FAIL;
break;
}
pVc->CloseFlags |= PX_VC_CM_CLOSE_COMP;
if (pVc->Flags & PX_VC_OUTCALL_ABORTED) {
//
// This call has been aborted while
// in the PROCEEDING state. This means
// that the MakeCallComplete has run
// and did our cleanup so just get
// out.
//
break;
} else if (pVc->Flags & PX_VC_OUTCALL_ABORTING) {
pVc->Flags &= ~PX_VC_OUTCALL_ABORTING;
pVc->Flags |= PX_VC_OUTCALL_ABORTED;
} else if (pVc->Flags & PX_VC_INCALL_ABORTING) {
pVc->Flags &= ~PX_VC_INCALL_ABORTING;
pVc->Flags |= PX_VC_INCALL_ABORTED;
}
pVc->PrevState = pVc->State;
pVc->State = PX_VC_IDLE;
pClAf = pVc->ClAf;
SendTapiCallState(pVc,
LINECALLSTATE_DISCONNECTED,
0,
pVc->CallInfo->ulMediaMode);
if (pVc->Flags & PX_VC_DROP_PENDING) {
PxTapiCompleteDropIrps(pVc, Status);
}
//
// Remove the ref applied when this call
// became connected with the call manager
// (NdisClMakeCall/PxClIncomingCall).
// We don't need to do the full deref code
// here as the ref applied when we mapped
// the vc will keep the vc around!
//
pVc->RefCount--;
} while (FALSE);
//
// Deref for ref applied at entry when
// validating the vc
//
DEREF_VC_LOCKED(pVc);
}
VOID
PxClAddPartyComplete(
IN NDIS_STATUS status,
IN NDIS_HANDLE ProtocolPartyContext,
IN NDIS_HANDLE NdisPartyHandle,
IN PCO_CALL_PARAMETERS CallParameters
)
{
ASSERT(0);
}
VOID
PxClDropPartyComplete(
IN NDIS_STATUS status,
IN NDIS_HANDLE ProtocolPartyContext
)
{
ASSERT(0);
}
NDIS_STATUS
PxClIncomingCall(
IN NDIS_HANDLE ProtocolSapContext,
IN NDIS_HANDLE ProtocolVcContext,
IN OUT PCO_CALL_PARAMETERS pCallParams
)
{
PPX_VC pVc;
PPX_CL_SAP pClSap;
PPX_CL_AF pClAf;
NDIS_STATUS Status;
PXDEBUGP(PXD_LOUD, PXM_CL,
("PxClIncomingCall: Sap %p VcCtx %x\n",
ProtocolSapContext, ProtocolVcContext));
pClSap = (PPX_CL_SAP)ProtocolSapContext;
if (pClSap->State != PX_SAP_OPENED) {
PXDEBUGP(PXD_WARNING, PXM_CL,
("PxClIncomingCall: Invalid SapState Sap %p State %x\n",
pClSap, pClSap->State));
return (NDIS_STATUS_FAILURE);
}
pClAf = pClSap->ClAf;
GetVcFromCtx(ProtocolVcContext, &pVc);
if (pVc == NULL) {
PXDEBUGP(PXD_WARNING, PXM_CL,
("PxClIncomingCall: pVc invalid %x\n", ProtocolVcContext));
return (NDIS_STATUS_FAILURE);
}
Status =
(*pClAf->AfGetTapiCallParams)(pVc, pCallParams);
if (Status != NDIS_STATUS_SUCCESS) {
PXDEBUGP(PXD_WARNING, PXM_CL,
("PxClIncomingCall: pVc invalid %x\n", ProtocolVcContext));
return (Status);
}
NdisAcquireSpinLock(&pVc->Lock);
// The algorithim for computing a unique "htCall" is to start
// at the value 1, and perpetually increment by 2. Keeping
// the low bit set will allow the user-mode TAPI component
// we talk to to distinguish between these incoming call handles
// and outgoing call handles, the latter of which will always
// have the low bit zero'd (since they're really pointers to heap).
//
// In <= NT 4.0, valid values used to range between 0x80000000
// and 0xffffffff, as we relied on the fact that user-mode
// addresses always had the low bit zero'd. (Not a valid
// assumption anymore!)
//
pVc->htCall =
InterlockedExchangeAdd((PLONG)&TspCB.htCall, 2);
//
// This ref is applied for the indication to
// tapi of a new call. The ref will be removed
// when tapi closes the call in PxTapiCloseCall.
//
REF_VC(pVc);
//
// This ref is applied for the connection
// between the proxy and the call manager.
// The ref will be removed in either
// PxClCloseCallComplete or PxVcCleanup
// in the case where the offered call is
// dropped by the client.
//
REF_VC(pVc);
SendTapiNewCall(pVc,
pVc->hdCall,
pVc->htCall,
0);
SendTapiCallState(pVc,
LINECALLSTATE_OFFERING,
0,
pVc->CallInfo->ulMediaMode);
pVc->PrevState = pVc->State;
pVc->State = PX_VC_OFFERING;
PxStartIncomingCallTimeout(pVc);
//
// Deref for ref applied at entry when
// validating the vc
//
DEREF_VC_LOCKED(pVc);
return (NDIS_STATUS_PENDING);
}
VOID
PxClIncomingCallQosChange(
IN NDIS_HANDLE ProtocolVcContext,
IN PCO_CALL_PARAMETERS pCallParams
)
{
}
VOID
PxClIncomingCloseCall(
IN NDIS_STATUS CloseStatus,
IN NDIS_HANDLE ProtocolVcContext,
IN PVOID CloseData OPTIONAL,
IN UINT Size OPTIONAL
)
{
PPX_VC pVc;
PPX_CL_AF pClAf;
PXDEBUGP(PXD_LOUD, PXM_CL,
("PxClIncomingCloseCall: VcCtx %x\n", ProtocolVcContext));
GetVcFromCtx(ProtocolVcContext, &pVc);
if (pVc == NULL) {
PXDEBUGP(PXD_WARNING, PXM_CL,
("PxClIncomingCloseCall: pVc invalid %x\n", ProtocolVcContext));
return;
}
NdisAcquireSpinLock(&pVc->Lock);
pVc->CloseFlags |= PX_VC_INCOMING_CLOSE;
PxVcCleanup(pVc, PX_VC_CLEANUP_CM);
//
// remove the ref applied when we
// mapped the ctx to the vc at entry
//
DEREF_VC_LOCKED(pVc);
}
VOID
PxClIncomingDropParty(
IN NDIS_STATUS DropStatus,
IN NDIS_HANDLE ProtocolPartyContext,
IN PVOID CloseData OPTIONAL,
IN UINT Size OPTIONAL
)
{
ASSERT(0);
}
VOID
PxClCallConnected(
IN NDIS_HANDLE ProtocolVcContext
)
{
PPX_VC pVc;
PXDEBUGP(PXD_LOUD, PXM_CL,
("PxClCallConnected: VcCtx %x\n", ProtocolVcContext));
GetVcFromCtx(ProtocolVcContext, &pVc);
if (pVc == NULL) {
PXDEBUGP(PXD_WARNING, PXM_CL,
("PxClCallConnected: pVc invalid %x\n", ProtocolVcContext));
return;
}
NdisAcquireSpinLock(&pVc->Lock);
PXDEBUGP(PXD_LOUD, PXM_CL,
("PxClCallConnected: pVc %p, State %x\n", pVc, pVc->State));
if (pVc->State == PX_VC_CONNECTED) {
SendTapiCallState(pVc,
LINECALLSTATE_CONNECTED,
0,
pVc->CallInfo->ulMediaMode);
}
//
// Deref for ref applied at entry when
// validating the vc
//
DEREF_VC_LOCKED(pVc);
PXDEBUGP(PXD_LOUD, PXM_CL, ("PxClCallConnected: Exit\n"));
}