windows-nt/Source/XPSP1/NT/net/atm/epvc/sys/client.c
2020-09-26 16:20:57 +08:00

750 lines
18 KiB
C

#include "precomp.h"
#pragma hdrstop
#include "macros.h"
VOID
EpvcCoOpenAfComplete(
IN NDIS_STATUS Status,
IN NDIS_HANDLE ProtocolAfContext,
IN NDIS_HANDLE NdisAfHandle
)
{
ENTER("OpenAdapterComplete", 0x5d75dabd)
PEPVC_I_MINIPORT pMiniport = (PEPVC_I_MINIPORT)ProtocolAfContext;
PTASK_AF pAfTask = (PTASK_AF )pMiniport->af.pAfTask;
RM_DECLARE_STACK_RECORD(sr)
TRACE (TL_T, TM_Cl, (" == EpvcCoOpenAfComplete Context %p Status %x AfHAndle %x",
pMiniport, Status, NdisAfHandle) );
ASSERT (KeGetCurrentIrql() == PASSIVE_LEVEL);
//
// Store the Af Handle
//
if (NDIS_STATUS_SUCCESS == Status)
{
LOCKOBJ (pMiniport, &sr);
pMiniport->af.AfHandle = NdisAfHandle;
//
// Update variables on the miniport structure
// as this task has been given the go ahead
//
MiniportSetFlag (pMiniport, fMP_AddressFamilyOpened);
MiniportClearFlag (pMiniport, fMP_InfoAfClosed);
epvcLinkToExternal(
&pMiniport->Hdr, // pObject
0x5546d299,
(UINT_PTR)pMiniport->af.AfHandle , // Instance1
EPVC_ASSOC_MINIPORT_OPEN_AF, // AssociationID
" Open AF NdisHandle=%p\n",// szFormat
&sr
);
UNLOCKOBJ(pMiniport, &sr);
}
else
{
ASSERT (pMiniport->af.AfHandle == NULL);
pMiniport->af.AfHandle = NULL;
}
pAfTask ->ReturnStatus = Status;
//
// Add an association between
//
RmResumeTask (&pAfTask->TskHdr , 0, &sr);
RM_ASSERT_CLEAR(&sr);
EXIT();
}
VOID
epvcCoCloseAfCompleteWorkItem(
PRM_OBJECT_HEADER pObj,
NDIS_STATUS Status,
PRM_STACK_RECORD pSR
)
/*++
Routine Description:
Resuming the Af task
Arguments:
--*/
{
ENTER("epvcCoCloseAfCompleteWorkItem", 0xf6edfcb8)
PEPVC_I_MINIPORT pMiniport = NULL ;
PTASK_AF pAfTask = NULL;
pMiniport = (PEPVC_I_MINIPORT)pObj ;
LOCKOBJ (pMiniport, pSR);
MiniportSetFlag (pMiniport, fMP_InfoAfClosed);
UNLOCKOBJ (pMiniport, pSR);
pAfTask = (PTASK_AF )pMiniport->af.pAfTask;
if (NDIS_STATUS_SUCCESS==Status )
{
LOCKOBJ (pMiniport, pSR);
epvcUnlinkFromExternal(
&pMiniport->Hdr, // pObject
0x5546d299,
(UINT_PTR)pMiniport->af.AfHandle , // Instance1
EPVC_ASSOC_MINIPORT_OPEN_AF, // AssociationID
pSR
);
pMiniport->af.AfHandle = NULL;
UNLOCKOBJ(pMiniport, pSR);
}
RmResumeTask (&pAfTask->TskHdr , 0, pSR);
EXIT();
return;
}
VOID
EpvcCoCloseAfComplete(
IN NDIS_STATUS Status,
IN NDIS_HANDLE ProtocolAfContext
)
/*++
Routine Description:
Signifies that the AF has been closed.
Resume the Af task - through a workitem
Arguments:
--*/
{
ENTER("EpvcCoCloseAfComplete ", 0x5d75dabd)
PEPVC_I_MINIPORT pMiniport = (PEPVC_I_MINIPORT)ProtocolAfContext;
PTASK_AF pAfTask = (PTASK_AF )pMiniport->af.pAfTask;
RM_DECLARE_STACK_RECORD(sr)
ASSERT (KeGetCurrentIrql() == PASSIVE_LEVEL);
TRACE (TL_T, TM_Cl, (" == EpvcCoCloseAfComplete Context %p Status %x ",
pMiniport, Status) );
//
// Store the Status
//
pAfTask->ReturnStatus = Status;
//
// Queue the WorkItem
//
epvcMiniportQueueWorkItem (
&pMiniport->af.CloseAfWorkItem,
pMiniport,
epvcCoCloseAfCompleteWorkItem,
Status,
&sr
);
EXIT();
RM_ASSERT_CLEAR(&sr);
return;
}
VOID
EpvcCoMakeCallComplete(
IN NDIS_STATUS Status,
IN NDIS_HANDLE ProtocolVcContext,
IN NDIS_HANDLE NdisPartyHandle OPTIONAL,
IN PCO_CALL_PARAMETERS pCallParameters
)
/*++
Routine Description:
This is a notification from Ndis that the Make Call has completed.
We need to pass the Status back to the original thread, so use the Vc
Task as a context
Arguments:
--*/
{
ENTER ("EpvcCoMakeCallComplete", 0x1716ee4b)
PEPVC_I_MINIPORT pMiniport = (PEPVC_I_MINIPORT) ProtocolVcContext;
PTASK_VC pTaskVc = pMiniport->vc.pTaskVc;
RM_DECLARE_STACK_RECORD(SR);
//ASSERT (KeGetCurrentIrql() == PASSIVE_LEVEL);
TRACE (TL_T, TM_Cl, (" == EpvcCoMakeCallComplete Status %x", Status) );
pTaskVc->ReturnStatus = Status;
ASSERT (pCallParameters != NULL);
epvcFreeMemory (pCallParameters ,CALL_PARAMETER_SIZE, 0);
RmResumeTask (&pTaskVc->TskHdr, 0 , &SR);
EXIT();
RM_ASSERT_CLEAR(&SR);
}
VOID
epvcCoCloseCallCompleteWorkItem(
PRM_OBJECT_HEADER pObj,
NDIS_STATUS Status,
PRM_STACK_RECORD pSR
)
{
ENTER ("EpvcCoCloseCallComplete", 0xbd67524a)
PEPVC_I_MINIPORT pMiniport = (PEPVC_I_MINIPORT) pObj;
PTASK_VC pTaskVc = pMiniport->vc.pTaskVc;
ASSERT (KeGetCurrentIrql() == PASSIVE_LEVEL);
TRACE (TL_T, TM_Cl, (" == EpvcCoCloseCallComplete") );
pTaskVc->ReturnStatus = Status;
RmResumeTask (&pTaskVc->TskHdr, 0 , pSR);
RM_ASSERT_CLEAR(pSR);
}
VOID
EpvcCoCloseCallComplete(
IN NDIS_STATUS Status,
IN NDIS_HANDLE ProtocolVcContext,
IN NDIS_HANDLE ProtocolPartyContext OPTIONAL
)
{
ENTER ("EpvcCoCloseCallComplete", 0xbd67524a)
PEPVC_I_MINIPORT pMiniport = (PEPVC_I_MINIPORT) ProtocolVcContext;
RM_DECLARE_STACK_RECORD(SR);
TRACE (TL_T, TM_Cl, (" == EpvcCoCloseCallComplete") );
epvcMiniportQueueWorkItem (&pMiniport->vc.CallVcWorkItem,
pMiniport,
epvcCoCloseCallCompleteWorkItem,
Status,
&SR
);
RM_ASSERT_CLEAR(&SR);
}
NDIS_STATUS
EpvcCoIncomingCall(
IN NDIS_HANDLE ProtocolSapContext,
IN NDIS_HANDLE ProtocolVcContext,
IN OUT PCO_CALL_PARAMETERS CallParameters
)
{
TRACE (TL_T, TM_Cl, (" == EpvcCoIncomingCall") );
return NDIS_STATUS_FAILURE;
}
VOID
EpvcCoCallConnected(
IN NDIS_HANDLE ProtocolVcContext
)
{
TRACE (TL_T, TM_Cl, (" == EpvcCoCallConnected") );
}
VOID
EpvcCoIncomingClose(
IN NDIS_STATUS CloseStatus,
IN NDIS_HANDLE ProtocolVcContext,
IN PVOID CloseData OPTIONAL,
IN UINT Size OPTIONAL
)
{
TRACE (TL_T, TM_Cl, (" == EpvcCoIncomingClose") );
}
//
// CO_CREATE_VC_HANDLER and CO_DELETE_VC_HANDLER are synchronous calls
//
NDIS_STATUS
EpvcClientCreateVc(
IN NDIS_HANDLE ProtocolAfContext,
IN NDIS_HANDLE NdisVcHandle,
OUT PNDIS_HANDLE ProtocolVcContext
)
{
TRACE (TL_T, TM_Cl, (" == EpvcClientCreateVc") );
return NDIS_STATUS_FAILURE;
}
NDIS_STATUS
EpvcClientDeleteVc(
IN NDIS_HANDLE ProtocolVcContext
)
{
TRACE (TL_T, TM_Cl, (" == EpvcClientDeleteVc") );
return NDIS_STATUS_FAILURE;
}
NDIS_STATUS
EpvcCoRequest(
IN NDIS_HANDLE ProtocolAfContext,
IN NDIS_HANDLE ProtocolVcContext OPTIONAL,
IN NDIS_HANDLE ProtocolPartyContext OPTIONAL,
IN OUT PNDIS_REQUEST pNdisRequest
)
/*++
Routine Description:
This routine is called by NDIS when our Call Manager sends us an
NDIS Request. NDIS Requests that are of significance to us are:
- OID_CO_ADDRESS_CHANGE
The set of addresses registered with the switch has changed,
i.e. address registration is complete. We issue an NDIS Request
ourselves to get the list of addresses registered.
- OID_CO_SIGNALING_ENABLED
We ignore this as of now.
TODO: Add code that uses this and the SIGNALING_DISABLED
OIDs to optimize on making calls.
- OID_CO_SIGNALING_DISABLED
We ignore this for now.
- OID_CO_AF_CLOSE
The Call manager wants us to shut down this AF open .
We ignore all other OIDs.
Arguments:
ProtocolAfContext - Our context for the Address Family binding,
which is a pointer to the ATMEPVC Interface.
ProtocolVcContext - Our context for a VC, which is a pointer to
an ATMEPVC VC structure.
ProtocolPartyContext - Our context for a Party. Since we don't do
PMP, this is ignored (must be NULL).
pNdisRequest - Pointer to the NDIS Request.
Return Value:
NDIS_STATUS_SUCCESS if we recognized the OID
NDIS_STATUS_NOT_RECOGNIZED if we didn't.
--*/
{
ENTER("EpvcCoRequest",0xcc5aff85)
PEPVC_I_MINIPORT pMiniport;
NDIS_STATUS Status;
RM_DECLARE_STACK_RECORD (SR)
ASSERT (KeGetCurrentIrql() == PASSIVE_LEVEL);
pMiniport = (PEPVC_I_MINIPORT)ProtocolAfContext;
TRACE (TL_T, TM_Cl, (" ==> EpvcCoRequest") );
//
// Initialize
//
Status = NDIS_STATUS_NOT_RECOGNIZED;
if (pNdisRequest->RequestType == NdisRequestSetInformation)
{
switch (pNdisRequest->DATA.SET_INFORMATION.Oid)
{
case OID_CO_ADDRESS_CHANGE:
TRACE (TL_I, TM_Cl, ("CoRequestHandler: CO_ADDRESS_CHANGE\n"));
//
// The Call Manager says that the list of addresses
// registered on this interface has changed. Get the
// (potentially) new ATM address for this interface.
Status = NDIS_STATUS_SUCCESS;
break;
case OID_CO_SIGNALING_ENABLED:
TRACE (TL_I, TM_Cl, ("CoRequestHandler: CoRequestHandler: CO_SIGNALING_ENABLED\n"));
// ignored for now
Status = NDIS_STATUS_FAILURE;
break;
case OID_CO_SIGNALING_DISABLED:
TRACE (TL_I, TM_Cl, ("CoRequestHandler: CO_SIGNALING_DISABLEDn"));
// Ignored for now
Status = NDIS_STATUS_FAILURE;
break;
case OID_CO_AF_CLOSE:
TRACE (TL_I, TM_Cl, ("CoRequestHandler: CO_AF_CLOSE on MINIPORT %x\n", pMiniport));
Status = epvcProcessOidCloseAf(pMiniport, &SR);
break;
default:
break;
}
}
TRACE (TL_T, TM_Cl, (" <== EpvcCoRequest") );
RM_ASSERT_CLEAR(&SR)
EXIT()
return (Status);
}
VOID
EpvcCoRequestComplete(
IN NDIS_STATUS Status,
IN NDIS_HANDLE ProtocolAfContext OPTIONAL,
IN NDIS_HANDLE ProtocolVcContext OPTIONAL,
IN NDIS_HANDLE ProtocolPartyContext OPTIONAL,
IN PNDIS_REQUEST pRequest
)
{
TRACE (TL_T, TM_Cl, (" == EpvcCoRequest pRequest %x", pRequest) );
}
NDIS_STATUS
epvcPrepareAndSendNdisRequest(
IN PEPVC_ADAPTER pAdapter,
IN PEPVC_NDIS_REQUEST pEpvcNdisRequest,
IN REQUEST_COMPLETION pFunc, // OPTIONAL
IN NDIS_OID Oid,
IN PVOID pBuffer,
IN ULONG BufferLength,
IN NDIS_REQUEST_TYPE RequestType,
IN PEPVC_I_MINIPORT pMiniport, // OPTIONAL
IN BOOLEAN fPendedRequest, // OPTIONAL
IN BOOLEAN fPendedSet, // OPTIONAL
IN PRM_STACK_RECORD pSR
)
/*++
Routine Description:
Send an NDIS Request to query an adapter for information.
If the request pends, block on the EPVC Adapter structure
till it completes.
Arguments:
pAdapter - Points to EPVCAdapter structure
pNdisRequest - Pointer to UNITIALIZED NDIS request structure
pTask - OPTIONAL Task. If NULL, we block until the operation
completes.
PendCode - PendCode to suspend pTask
Oid - OID to be passed in the request
pBuffer - place for value(s)
BufferLength - length of above
pMiniport - Minport associated withe this request - OPTIONAL
fPendedRequest - A request was pended at the miniport - OPTIONAL
fPendedSet - Pended a Set Request - OPTIONAL
Return Value:
The NDIS status of the request.
--*/
{
ENTER("epvcPrepareAndSendNdisRequest",0x1cc515d5)
NDIS_STATUS Status;
PNDIS_REQUEST pNdisRequest = &pEpvcNdisRequest->Request;
TRACE (TL_T, TM_Cl, ("==>epvcSendAdapterNdisRequest pAdapter %x, pRequest %x",
pAdapter, pNdisRequest));
//ASSERT (KeGetCurrentIrql() == PASSIVE_LEVEL);
TRACE (TL_V, TM_Rq, ("Cl Requesting Adapter %x, Oid %x, Buffer %x, Length %x, pFunc %x",
pAdapter,
Oid,
pBuffer,
BufferLength,
pFunc) );
ASSERT (pNdisRequest != NULL);
EPVC_ZEROSTRUCT(pEpvcNdisRequest);
//
// Fill in the NDIS Request structure
//
if (RequestType == NdisRequestQueryInformation)
{
pNdisRequest->RequestType = NdisRequestQueryInformation;
pNdisRequest->DATA.QUERY_INFORMATION.Oid = Oid;
pNdisRequest->DATA.QUERY_INFORMATION.InformationBuffer = pBuffer;
pNdisRequest->DATA.QUERY_INFORMATION.InformationBufferLength = BufferLength;
pNdisRequest->DATA.QUERY_INFORMATION.BytesWritten = 0;
pNdisRequest->DATA.QUERY_INFORMATION.BytesNeeded = BufferLength;
}
else
{
ASSERT(RequestType == NdisRequestSetInformation);
pNdisRequest->RequestType = NdisRequestSetInformation;
pNdisRequest->DATA.SET_INFORMATION.Oid = Oid;
pNdisRequest->DATA.SET_INFORMATION.InformationBuffer = pBuffer;
pNdisRequest->DATA.SET_INFORMATION.InformationBufferLength = BufferLength;
pNdisRequest->DATA.SET_INFORMATION.BytesRead = 0;
pNdisRequest->DATA.SET_INFORMATION.BytesNeeded = BufferLength;
}
ASSERT (pAdapter->bind.BindingHandle != NULL);
//
// If the completion routine is not defined then wait for this request
// to complete.
//
if (pFunc == NULL)
{
// We might potentially wait.
//
ASSERT_PASSIVE();
//
//Insure that we aren't blocking a request that reached our miniport edge
//
ASSERT (pMiniport == NULL);
NdisInitializeEvent(&pEpvcNdisRequest->Event);
NdisRequest(
&Status,
pAdapter->bind.BindingHandle,
pNdisRequest
);
if (PEND(Status))
{
NdisWaitEvent(&pEpvcNdisRequest->Event, 0);
Status = pEpvcNdisRequest->Status;
}
}
else
{
pEpvcNdisRequest->pFunc = pFunc;
pEpvcNdisRequest->pMiniport = pMiniport;
pEpvcNdisRequest->fPendedRequest = fPendedRequest ;
pEpvcNdisRequest->fSet = fPendedSet;
//
// Set up an assoc between the miniport and this request
//
epvcLinkToExternal (&pMiniport->Hdr, // pHdr
0x46591e2d, // LUID
(UINT_PTR)pEpvcNdisRequest, // External entity
EPVC_ASSOC_MINIPORT_REQUEST, // AssocID
"NetWorKAddressRequest %p\n",
pSR
) ;
NdisRequest(
&Status,
pAdapter->bind.BindingHandle,
pNdisRequest
);
if (!PEND(Status))
{
(pFunc) (pEpvcNdisRequest, Status);
// Let this thread complete with a status of pending
Status = NDIS_STATUS_PENDING;
}
}
if (Status == NDIS_STATUS_SUCCESS)
{
TRACE(TL_V, TM_Rq,("Adapter Query - Oid %x", Oid));
DUMPDW (TL_V, TM_Rq, pBuffer, BufferLength);
}
return Status;
}
VOID
epvcCoGenericWorkItem (
IN PNDIS_WORK_ITEM pNdisWorkItem,
IN PVOID Context
)
/*++
Routine Description:
Deref the miniport and invoke the function associated with
the workitem
Arguments:
--*/
{
ENTER ("epvcCoGenericWorkItem ", 0x45b597e8)
PEPVC_WORK_ITEM pEpvcWorkItem = (PEPVC_WORK_ITEM )pNdisWorkItem;
RM_DECLARE_STACK_RECORD (SR);
//
// Deref the miniport or adapter
//
epvcUnlinkFromExternal(
pEpvcWorkItem->pParentObj, // pObject
0x3a70de02,
(UINT_PTR)pNdisWorkItem, // Instance1
EPVC_ASSOC_WORKITEM, // AssociationID
&SR
);
//
// Call the function so that the work is completed
//
(pEpvcWorkItem->pFn) (pEpvcWorkItem->pParentObj, pEpvcWorkItem->ReturnStatus, &SR);
EXIT();
}
VOID
epvcMiniportQueueWorkItem (
IN PEPVC_WORK_ITEM pEpvcWorkItem,
IN PEPVC_I_MINIPORT pMiniport,
IN PEVPC_WORK_ITEM_FUNC pFn,
IN NDIS_STATUS Status,
IN PRM_STACK_RECORD pSR
)
/*++
Routine Description:
Set up the Epvc Work Item with the pfn, Status and , ref the miniport
and then queue the workitem
Arguments:
--*/
{
ENTER("epvcMiniportQueueWorkItem ", 0xc041af99);
//
// Store the contexts
//
pEpvcWorkItem->ReturnStatus = Status;
pEpvcWorkItem->pParentObj = &pMiniport->Hdr;
pEpvcWorkItem->pFn = pFn;
//
// Ref the RM Obj (its a miniport or an adapter)
//
epvcLinkToExternal( &pMiniport->Hdr,
0x62efba09,
(UINT_PTR)&pEpvcWorkItem->WorkItem,
EPVC_ASSOC_WORKITEM,
" WorkItem %p\n",
pSR);
//
// Queue the WorkItem
//
epvcInitializeWorkItem (&pMiniport->Hdr,
&pEpvcWorkItem->WorkItem,
epvcCoGenericWorkItem,
NULL,
pSR);
EXIT()
}