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

685 lines
14 KiB
C

/*++
Copyright (c) 1995-1996 Microsoft Corporation
Module Name:
pxcm.c
Abstract:
This module contains the Call Manager (CM_) entry points listed
in the protocol characteristics table. These entry points are called
by the NDIS wrapper on behalf of requests made by a client.
Author:
Richard Machin (RMachin)
Revision History:
Who When What
-------- -------- ----------------------------------------------
RMachin 10-03-96 created
tonybe 01-23-99 rewrite and cleanup
Notes:
--*/
#include "precomp.h"
#define MODULE_NUMBER MODULE_CM
#define _FILENUMBER 'MCXP'
NDIS_STATUS
PxCmCreateVc(
IN NDIS_HANDLE ProtocolAfContext,
IN NDIS_HANDLE NdisVcHandle,
OUT PNDIS_HANDLE pProtocolVcContext
)
/*++
Routine Description:
We do not allow a client of the proxy to create a Vc ever!
Arguments:
Return Value:
NDIS_STATUS_SUCCESS if everything goes off well right here
NDIS_STATUS_XXXX to indicate any error.
--*/
{
PXDEBUGP(PXD_FATAL, PXM_CM,
("PxCmCreateVc: Should never be called!\n"));
ASSERT(0);
return(NDIS_STATUS_FAILURE);
}
NDIS_STATUS
PxCmDeleteVc(
IN NDIS_HANDLE ProtocolVcContext
)
/*++
Routine Description:
We do not allow a client to delete a vc!
Arguments:
Return Value:
NDIS_STATUS_SUCCESS if everything goes off well right here
NDIS_STATUS_XXXX to indicate any error.
--*/
{
PXDEBUGP(PXD_FATAL, PXM_CM,
("PxCmDeleteVc: Should never be called!\n"));
ASSERT(0);
return(NDIS_STATUS_FAILURE);
}
NDIS_STATUS
PxCmOpenAf(
IN NDIS_HANDLE BindingContext,
IN PCO_ADDRESS_FAMILY AddressFamily,
IN NDIS_HANDLE NdisAfHandle,
OUT PNDIS_HANDLE CallMgrAfContext
)
/*++
Routine Description:
This routine creats an Af context for the client that is opening
our address family. The Af context is threaded up on the adapter
block.
Arguments:
Return Value:
NDIS_STATUS_SUCCESS if everything goes off well right here
NDIS_STATUS_XXXX to indicate any error.
--*/
{
PPX_CM_AF pCmAf;
PPX_ADAPTER pAdapter;
PXDEBUGP(PXD_LOUD, PXM_CM, ("PxCmOpenAf: AF: %x\n",AddressFamily->AddressFamily));
//
// Make sure the address family being opened is ours
//
if(AddressFamily->AddressFamily != CO_ADDRESS_FAMILY_TAPI) {
PXDEBUGP(PXD_ERROR, PXM_CM,
("PxCmOpenAf: not Proxy address family: %x\n",
AddressFamily->AddressFamily));
return(NDIS_STATUS_BAD_VERSION);
}
AdapterFromCmBindContext(BindingContext, pAdapter);
NdisAcquireSpinLock(&pAdapter->Lock);
if (pAdapter->State != PX_ADAPTER_OPEN) {
NdisReleaseSpinLock(&pAdapter->Lock);
return (NDIS_STATUS_CLOSING);
}
NdisReleaseSpinLock(&pAdapter->Lock);
pCmAf =
PxAllocateCmAf(AddressFamily);
if (pCmAf == NULL) {
PXDEBUGP(PXD_ERROR, PXM_CM, ("PXCmOpenAf: AfBlock memory allocation failed!\n"));
return (NDIS_STATUS_RESOURCES);
}
pCmAf->NdisAfHandle = NdisAfHandle;
pCmAf->State = PX_AF_OPENED;
pCmAf->Adapter = pAdapter;
NdisAcquireSpinLock(&pAdapter->Lock);
InsertTailList(&pAdapter->CmAfList, &pCmAf->Linkage);
REF_ADAPTER(pAdapter);
NdisReleaseSpinLock(&pAdapter->Lock);
PXDEBUGP(PXD_LOUD, PXM_CM, ("PxCmOpenAf: CmAf %p, NdisAfHandle is %p\n",
pCmAf,NdisAfHandle));
*CallMgrAfContext = pCmAf;
return(NDIS_STATUS_SUCCESS);
}
NDIS_STATUS
PxCmCloseAf(
IN NDIS_HANDLE CallMgrAfContext
)
/*++
Routine Description:
The client is closing the open of this address family.
Arguments:
Return Value:
NDIS_STATUS_SUCCESS if everything goes off well right here
NDIS_STATUS_XXXX to indicate any error.
--*/
{
PPX_CM_AF pCmAf;
PPX_ADAPTER pAdapter;
pCmAf = (PPX_CM_AF)CallMgrAfContext;
ASSERT(KeGetCurrentIrql() < DISPATCH_LEVEL);
PXDEBUGP(PXD_LOUD, PXM_CM, ("PxCmCloseAf: CmAf %p\n", pCmAf));
//
// There should not be any open saps on this af!
//
ASSERT(IsListEmpty(&pCmAf->CmSapList) == TRUE);
//
// There should not be any active Vc's on this af!
//
ASSERT(IsListEmpty(&pCmAf->VcList) == TRUE);
pAdapter = pCmAf->Adapter;
NdisAcquireSpinLock(&pAdapter->Lock);
RemoveEntryList(&pCmAf->Linkage);
DEREF_ADAPTER_LOCKED(pAdapter);
NdisAcquireSpinLock(&pCmAf->Lock);
pCmAf->State = PX_AF_CLOSED;
pCmAf->Linkage.Flink =
pCmAf->Linkage.Blink = (PLIST_ENTRY)pCmAf;
DEREF_CM_AF_LOCKED(pCmAf);
ASSERT(KeGetCurrentIrql() < DISPATCH_LEVEL);
return (NDIS_STATUS_PENDING);
}
NDIS_STATUS
PxCmRegisterSap(
IN NDIS_HANDLE CallMgrAfContext,
IN PCO_SAP Sap,
IN NDIS_HANDLE NdisSapHandle,
OUT PNDIS_HANDLE CallMgrSapContext
)
/*++
Routine Description:
Arguments:
Return Value:
NDIS_STATUS_SUCCESS if everything goes off well right here
NDIS_STATUS_XXXX to indicate any error.
--*/
{
PPX_CM_AF pCmAf;
PPX_CM_SAP pCmSap;
PPX_ADAPTER pAdapter;
pCmAf = (PPX_CM_AF)CallMgrAfContext;
PXDEBUGP(PXD_LOUD, PXM_CM, ("PxCmRegisterSap: CmAf %p\n", pCmAf));
NdisAcquireSpinLock(&pCmAf->Lock);
if (pCmAf->State != PX_AF_OPENED) {
PXDEBUGP(PXD_WARNING, PXM_CM,
("PxCmRegisterSap: Invalid state %x\n", pCmAf->State));
NdisReleaseSpinLock(&pCmAf->Lock);
return (NDIS_STATUS_FAILURE);
}
pAdapter = pCmAf->Adapter;
NdisReleaseSpinLock(&pCmAf->Lock);
NdisAcquireSpinLock(&pAdapter->Lock);
if (pAdapter->State != PX_ADAPTER_OPEN) {
NdisReleaseSpinLock(&pAdapter->Lock);
return (NDIS_STATUS_CLOSING);
}
NdisReleaseSpinLock(&pAdapter->Lock);
//
// Allocate memory for the Sap
//
pCmSap = PxAllocateCmSap(Sap);
if (pCmSap == NULL) {
PXDEBUGP(PXD_WARNING, PXM_CM,
("PxCmRegisterSap: Error allocating memory for sap %p\n", Sap));
NdisReleaseSpinLock(&pCmAf->Lock);
return (NDIS_STATUS_RESOURCES);
}
NdisAcquireSpinLock(&pCmAf->Lock);
pCmSap->NdisSapHandle = NdisSapHandle;
pCmSap->CmAf = pCmAf;
InsertTailList(&pCmAf->CmSapList, &pCmSap->Linkage);
REF_CM_AF(pCmAf);
NdisReleaseSpinLock(&pCmAf->Lock);
*CallMgrSapContext = pCmSap;
return(STATUS_SUCCESS);
}
NDIS_STATUS
PxCmDeRegisterSap(
IN NDIS_HANDLE CallMgrSapContext
)
/*++
Routine Description:
Arguments:
Return Value:
NDIS_STATUS_SUCCESS if everything goes off well right here
NDIS_STATUS_XXXX to indicate any error.
--*/
{
PPX_CM_SAP pCmSap;
PPX_CM_AF pCmAf;
pCmSap = (PPX_CM_SAP)CallMgrSapContext;
ASSERT(KeGetCurrentIrql() < DISPATCH_LEVEL);
PXDEBUGP(PXD_LOUD, PXM_CM, ("PxCmDeRegisterSap: CmSap %p\n", pCmSap));
pCmAf = pCmSap->CmAf;
InterlockedExchange((PLONG)&pCmSap->State, PX_SAP_CLOSED);
NdisAcquireSpinLock(&pCmAf->Lock);
RemoveEntryList(&pCmSap->Linkage);
DEREF_CM_AF_LOCKED(pCmAf);
PxFreeCmSap(pCmSap);
ASSERT(KeGetCurrentIrql() < DISPATCH_LEVEL);
return(STATUS_SUCCESS);
}
NDIS_STATUS
PxCmMakeCall(
IN NDIS_HANDLE CallMgrVcContext,
IN OUT PCO_CALL_PARAMETERS pCallParameters,
IN NDIS_HANDLE NdisPartyHandle OPTIONAL,
OUT PNDIS_HANDLE pCallMgrPartyContext OPTIONAL
)
/*++
Routine Description:
We do not allow a client to make a call!
Arguments:
Return Value:
NDIS_STATUS_SUCCESS if everything goes off well right here
NDIS_STATUS_XXXX to indicate any error.
--*/
{
ASSERT(0);
return(STATUS_SUCCESS);
}
NDIS_STATUS
PxCmCloseCall(
IN NDIS_HANDLE CallMgrVcContext,
IN NDIS_HANDLE CallMgrPartyContext OPTIONAL,
IN PVOID Buffer OPTIONAL,
IN UINT Size OPTIONAL
)
{
PPX_VC pVc;
PPX_CM_AF pCmAf;
NDIS_STATUS Status;
PXDEBUGP(PXD_LOUD, PXM_CM,
("PxCmCloseCall: VcCtx %x\n", CallMgrVcContext));
GetVcFromCtx(CallMgrVcContext, &pVc);
if (pVc == NULL) {
PXDEBUGP(PXD_WARNING, PXM_CM,
("PxCmCloseCall: Invalid VcCtx %x!\n", CallMgrVcContext));
return (NDIS_STATUS_SUCCESS);
}
NdisAcquireSpinLock(&pVc->Lock);
pVc->HandoffState = PX_VC_HANDOFF_IDLE;
pVc->CloseFlags |= PX_VC_CL_CLOSE_CALL;
NdisReleaseSpinLock(&pVc->Lock);
NdisCmCloseCallComplete(NDIS_STATUS_SUCCESS,
pVc->CmVcHandle,
NULL);
#ifdef CODELETEVC_FIXED
//
// Evidently the CoCreateVc is unbalanced
// when creating a proxy vc. The call to
// NdisCoDeleteVc will fail because the
// Vc is still active.
// Investigate this with ndis guys!!!!!
//
Status =
NdisCoDeleteVc(pVc->CmVcHandle);
if (Status == NDIS_STATUS_SUCCESS) {
pVc->CmVcHandle = NULL;
}
#endif
NdisAcquireSpinLock(&pVc->Lock);
//
// If the Vc is no longer connected then
// we are waiting for this part of the vc
// to go away before we can cleanup the
// vc with the call manager.
//
if (pVc->Flags & PX_VC_CLEANUP_CM) {
ASSERT(pVc->State == PX_VC_DISCONNECTING);
PxCloseCallWithCm(pVc);
}
pCmAf = pVc->CmAf;
//
// Remove the reference applied when the call
// was dispatched to the client. We do not need
// all of the ref code because of the ref applied
// at entry to this function.
//
pVc->RefCount--;
//
// Deref for ref applied at entry when
// validating the vc
//
DEREF_VC_LOCKED(pVc);
DEREF_CM_AF(pCmAf);
return(NDIS_STATUS_PENDING);
}
VOID
PxCmIncomingCallComplete(
IN NDIS_STATUS Status,
IN NDIS_HANDLE CallMgrVcContext,
IN PCO_CALL_PARAMETERS pCallParameters
)
{
PPX_VC pVc;
PXDEBUGP(PXD_LOUD, PXM_CM,
("PxCmIncomingCallComplete: VcCtx %x\n", CallMgrVcContext));
GetVcFromCtx(CallMgrVcContext, &pVc);
if (pVc == NULL) {
PXDEBUGP(PXD_WARNING, PXM_CM,
("PxCmIncomingCallComplete: Invalid VcCtx %x!\n",
CallMgrVcContext));
return;
}
NdisAcquireSpinLock(&pVc->Lock);
PXDEBUGP(PXD_LOUD, PXM_CM,
("PxCmIncomingCallComplete: Vc %p, Status %x\n",
pVc, Status));
PxSignal(&pVc->Block, Status);
//
// remove the ref applied when we mapped
// the vcctx to the vc
//
DEREF_VC_LOCKED(pVc);
}
NDIS_STATUS
PxCmAddParty(
IN NDIS_HANDLE CallMgrVcContext,
IN OUT PCO_CALL_PARAMETERS pCallParameters,
IN NDIS_HANDLE NdisPartyHandle,
OUT PNDIS_HANDLE pCallMgrPartyContext
)
/*++
Routine Description:
We do not allow a client to add a party to a vc!
Arguments:
Return Value:
NDIS_STATUS_SUCCESS if everything goes off well right here
NDIS_STATUS_XXXX to indicate any error.
--*/
{
ASSERT(0);
return(STATUS_SUCCESS);
}
NDIS_STATUS
PxCmDropParty(
IN NDIS_HANDLE CallMgrPartyContext,
IN PVOID Buffer OPTIONAL,
IN UINT Size OPTIONAL
)
/*++
Routine Description:
We do not allow a client to drop a party on a vc!
Arguments:
Return Value:
NDIS_STATUS_SUCCESS if everything goes off well right here
NDIS_STATUS_XXXX to indicate any error.
--*/
{
ASSERT(0);
return(STATUS_SUCCESS);
}
VOID
PxCmActivateVcComplete(
IN NDIS_STATUS Status,
IN NDIS_HANDLE CallMgrVcContext,
IN PCO_CALL_PARAMETERS pCallParameters)
/*++
Routine Description:
The vc has already been activate by the underlying
call manager/miniport!
Arguments:
Return Value:
NDIS_STATUS_SUCCESS if everything goes off well right here
NDIS_STATUS_XXXX to indicate any error.
--*/
{
ASSERT(0);
}
VOID
PxCmDeActivateVcComplete(
IN NDIS_STATUS Status,
IN NDIS_HANDLE CallMgrVcContext
)
/*++
Routine Description:
The vc is never deactivated by our call manager!
Arguments:
Return Value:
NDIS_STATUS_SUCCESS if everything goes off well right here
NDIS_STATUS_XXXX to indicate any error.
--*/
{
ASSERT(0);
}
NDIS_STATUS
PxCmModifyCallQos(
IN NDIS_HANDLE CallMgrVcContext,
IN PCO_CALL_PARAMETERS pCallParameters
)
/*++
Routine Description:
Not sure what to do here right now!
ToDo!!!!!!!!!!
Arguments:
Return Value:
NDIS_STATUS_SUCCESS if everything goes off well right here
NDIS_STATUS_XXXX to indicate any error.
--*/
{
return(STATUS_SUCCESS);
}
NDIS_STATUS
PxCmRequest(
IN NDIS_HANDLE ProtocolAfContext,
IN NDIS_HANDLE ProtocolVcContext OPTIONAL,
IN NDIS_HANDLE ProtocolPartyContext OPTIONAL,
IN OUT PNDIS_REQUEST NdisRequest
)
/*++
Routine Description:
We will handle requests from the clients and pass them down
to the underlying call manager/miniport if needed.
Arguments:
Return Value:
NDIS_STATUS_SUCCESS if everything goes off well right here
NDIS_STATUS_XXXX to indicate any error.
--*/
{
return(STATUS_SUCCESS);
}
VOID
PxCmRequestComplete(
IN NDIS_STATUS Status,
IN NDIS_HANDLE ProtocolAfContext,
IN NDIS_HANDLE ProtocolVcContext, // Optional
IN NDIS_HANDLE ProtocolPartyContext, // Optional
IN PNDIS_REQUEST NdisRequest
)
/*++
Routine Description:
Called by the client upon completion of any requests
that we have passed up to it. If this request needed to
be completed synchronously (status matters) then we will
signal completion and let the calling routine free the
memory. If this could complete asynchronously then we
just free the memory here.
Arguments:
Return Value:
NDIS_STATUS_SUCCESS if everything goes off well right here
NDIS_STATUS_XXXX to indicate any error.
--*/
{
PPX_REQUEST pProxyRequest;
PPX_CM_AF pCmAf;
PPX_VC pVc;
pCmAf = (PPX_CM_AF)ProtocolAfContext;
pVc = (PPX_VC)ProtocolVcContext;
PXDEBUGP(PXD_INFO, PXM_CM, ("PxCmRequestComplete: CmAf %p, Vc %p\n", pCmAf, pVc));
pProxyRequest = CONTAINING_RECORD(NdisRequest, PX_REQUEST, NdisRequest);
if (pProxyRequest->Flags & PX_REQ_ASYNC) {
pProxyRequest->Flags &= ~PX_REQ_ASYNC;
PxFreeMem(pProxyRequest);
DEREF_CM_AF(pCmAf);
} else {
PxSignal(&pProxyRequest->Block, Status);
}
}