windows-nt/Source/XPSP1/NT/net/rndis/rndismp/comini.c
2020-09-26 16:20:57 +08:00

1872 lines
72 KiB
C

/***************************************************************************
Copyright (c) 1999 Microsoft Corporation
Module Name:
COMINI.C
Abstract:
CO-NDIS Miniport driver entry points for the Remote NDIS miniport.
Environment:
kernel mode only
Notes:
THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR
PURPOSE.
Copyright (c) 1999 Microsoft Corporation. All Rights Reserved.
Revision History:
12/16/99: Created
Author:
ArvindM
****************************************************************************/
#include "precomp.h"
/****************************************************************************/
/* RndismpCoCreateVc */
/****************************************************************************/
/* */
/* Routine Description: */
/* */
/* Entry point to create a VC. We allocate a local VC structure, and send */
/* off a CreateVc message to the device. */
/* */
/* Arguments: */
/* */
/* MiniportAdapterContext - pointer to our adapter structure */
/* NdisVcHandle - the NDIS wrapper's handle for this VC */
/* pMiniportVcContext - place to return our context for this VC */
/* */
/* Return: */
/* */
/* NDIS_STATUS */
/* */
/****************************************************************************/
NDIS_STATUS
RndismpCoCreateVc(IN NDIS_HANDLE MiniportAdapterContext,
IN NDIS_HANDLE NdisVcHandle,
OUT PNDIS_HANDLE pMiniportVcContext)
{
PRNDISMP_ADAPTER pAdapter;
PRNDISMP_VC pVc;
PRNDISMP_MESSAGE_FRAME pMsgFrame;
NDIS_STATUS Status;
ULONG RefCount = 0;
pVc = NULL;
// get adapter context
pAdapter = PRNDISMP_ADAPTER_FROM_CONTEXT_HANDLE(MiniportAdapterContext);
do
{
if (pAdapter->Halting)
{
Status = NDIS_STATUS_NOT_ACCEPTED;
break;
}
pVc = AllocateVc(pAdapter);
if (pVc == NULL)
{
Status = NDIS_STATUS_RESOURCES;
break;
}
RNDISMP_REF_VC(pVc); // Creation ref
//
// Prepare a CreateVc message to send to the device.
//
pMsgFrame = BuildRndisMessageCoMiniport(pAdapter,
pVc,
REMOTE_CONDIS_MP_CREATE_VC_MSG,
NULL);
if (pMsgFrame == NULL)
{
Status = NDIS_STATUS_RESOURCES;
break;
}
pVc->VcState = RNDISMP_VC_CREATING;
RNDISMP_REF_VC(pVc); // Pending CreateVc response
RNDISMP_SEND_TO_MICROPORT(pAdapter, pMsgFrame, TRUE, CompleteSendCoCreateVc);
}
while (FALSE);
//
// Clean up if failure.
//
if (Status != NDIS_STATUS_SUCCESS)
{
if (pVc != NULL)
{
RNDISMP_DEREF_VC(pVc, &RefCount); // Creation ref
ASSERT(RefCount == 0); // the Vc should be dealloc'ed above.
}
}
return (Status);
}
/****************************************************************************/
/* CompleteSendCoCreateVc */
/****************************************************************************/
/* */
/* Routine Description: */
/* */
/* Callback routine called when microport completes sending a CreateVc */
/* message to the device. */
/* */
/* Arguments: */
/* */
/* pMsgFrame - Pointer to message frame */
/* SendStatus - status of the microport send. */
/* */
/* Return: */
/* */
/* VOID */
/* */
/****************************************************************************/
VOID
CompleteSendCoCreateVc(IN PRNDISMP_MESSAGE_FRAME pMsgFrame,
IN NDIS_STATUS SendStatus)
{
PRNDISMP_VC pVc;
PRNDISMP_ADAPTER pAdapter;
PRNDISMP_MESSAGE_FRAME pTmpMsgFrame;
ULONG RefCount = 0;
if (SendStatus == NDIS_STATUS_SUCCESS)
{
//
// The message was sent successfully. Do nothing until
// we get a response from the device.
//
}
else
{
pVc = pMsgFrame->pVc;
pAdapter = pVc->pAdapter;
TRACE1(("CompleteSendCoCreateVc: VC %x, Adapter %x, fail status %x\n",
pVc, pAdapter, SendStatus));
//
// Failed to send it to the device. Remove this message from
// the pending list and free it.
//
RNDISMP_LOOKUP_PENDING_MESSAGE(pTmpMsgFrame, pAdapter, pMsgFrame->RequestId);
ASSERT(pMsgFrame == pTmpMsgFrame);
DereferenceMsgFrame(pMsgFrame);
HandleCoCreateVcFailure(pVc, SendStatus);
}
} // CompleteSendCoCreateVc
/****************************************************************************/
/* HandleCoCreateVcFailure */
/****************************************************************************/
/* */
/* Routine Description: */
/* */
/* Utility routine to handle failure of a CreateVc, either due to a local */
/* microport send failure, or via explicit rejection by the device. */
/* */
/* Arguments: */
/* */
/* pVc - Pointer to VC on which this failure has occurred */
/* Status - NDIS status associated with this failure */
/* */
/* Return: */
/* */
/* VOID */
/* */
/****************************************************************************/
VOID
HandleCoCreateVcFailure(IN PRNDISMP_VC pVc,
IN NDIS_STATUS Status)
{
NDIS_HANDLE NdisVcHandle;
BOOLEAN bFailActivateVc = FALSE;
PCO_CALL_PARAMETERS pCallParameters;
ULONG RefCount = 0;
RNDISMP_ACQUIRE_VC_LOCK(pVc);
NdisVcHandle = pVc->NdisVcHandle;
switch (pVc->VcState)
{
case RNDISMP_VC_CREATING:
pVc->VcState = RNDISMP_VC_CREATE_FAILURE;
break;
case RNDISMP_VC_CREATING_DELETE_PENDING:
pVc->VcState = RNDISMP_VC_ALLOCATED;
break;
case RNDISMP_VC_CREATING_ACTIVATE_PENDING:
bFailActivateVc = TRUE;
pCallParameters = pVc->pCallParameters;
pVc->VcState = RNDISMP_VC_CREATE_FAILURE;
break;
default:
ASSERT(FALSE);
break;
}
RNDISMP_DEREF_VC_LOCKED(pVc, &RefCount); // Pending CreateVc response
if (RefCount != 0)
{
RNDISMP_RELEASE_VC_LOCK(pVc);
}
if (bFailActivateVc)
{
NdisMCoActivateVcComplete(Status,
NdisVcHandle,
pCallParameters);
}
} // HandleCoCreateVcFailure
/****************************************************************************/
/* RndismpCoDeleteVc */
/****************************************************************************/
/* */
/* Routine Description: */
/* */
/* Entry point to delete a VC. We send a DeleteVc message to the device. */
/* */
/* Arguments: */
/* */
/* MiniportVcContext - pointer to our VC structure */
/* */
/* Return: */
/* */
/* NDIS_STATUS */
/* */
/****************************************************************************/
NDIS_STATUS
RndismpCoDeleteVc(IN NDIS_HANDLE MiniportVcContext)
{
PRNDISMP_VC pVc;
NDIS_STATUS Status;
pVc = PRNDISMP_VC_FROM_CONTEXT_HANDLE(MiniportVcContext);
Status = StartVcDeletion(pVc);
return (Status);
} // RndismpCoDeleteVc
/****************************************************************************/
/* StartVcDeletion */
/****************************************************************************/
/* */
/* Routine Description: */
/* */
/* Initiate a DeleteVc operation on the specified VC. */
/* */
/* Arguments: */
/* */
/* pVc - Pointer to VC structure */
/* */
/* Return: */
/* */
/* NDIS_STATUS */
/* */
/****************************************************************************/
NDIS_STATUS
StartVcDeletion(IN PRNDISMP_VC pVc)
{
PRNDISMP_ADAPTER pAdapter;
PRNDISMP_MESSAGE_FRAME pMsgFrame;
NDIS_STATUS Status;
ULONG RefCount = 0;
BOOLEAN bSendDeleteVc;
pAdapter = pVc->pAdapter;
bSendDeleteVc = FALSE;
pMsgFrame = NULL;
do
{
//
// Prepare a DeleteVc message to send to the device.
//
pMsgFrame = BuildRndisMessageCoMiniport(pAdapter,
pVc,
REMOTE_CONDIS_MP_DELETE_VC_MSG,
NULL);
Status = NDIS_STATUS_SUCCESS;
TRACE2(("StartVcDeletion: VC %x, state %d, Msg %x\n", pVc, pVc->VcState, pMsgFrame));
RNDISMP_ACQUIRE_VC_LOCK(pVc);
switch (pVc->VcState)
{
case RNDISMP_VC_CREATED:
if (pMsgFrame != NULL)
{
pVc->VcState = RNDISMP_VC_DELETING;
bSendDeleteVc = TRUE;
}
else
{
Status = NDIS_STATUS_RESOURCES;
bSendDeleteVc = FALSE;
}
break;
case RNDISMP_VC_CREATING:
bSendDeleteVc = FALSE;
pVc->VcState = RNDISMP_VC_CREATING_DELETE_PENDING;
break;
case RNDISMP_VC_CREATE_FAILURE:
bSendDeleteVc = FALSE;
pVc->VcState = RNDISMP_VC_ALLOCATED;
break;
default:
bSendDeleteVc = FALSE;
Status = NDIS_STATUS_NOT_ACCEPTED;
break;
}
RNDISMP_RELEASE_VC_LOCK(pVc);
if (Status != NDIS_STATUS_SUCCESS)
{
break;
}
if (bSendDeleteVc)
{
ASSERT(pMsgFrame != NULL);
RNDISMP_REF_VC(pVc); // pending DeleteVc message
RNDISMP_SEND_TO_MICROPORT(pAdapter, pMsgFrame, TRUE, CompleteSendCoDeleteVc);
}
RNDISMP_DEREF_VC(pVc, &RefCount); // successful DeleteVc
}
while (FALSE);
if (!bSendDeleteVc)
{
if (pMsgFrame != NULL)
{
DereferenceMsgFrame(pMsgFrame);
}
}
return (Status);
} // StartVcDeletion
/****************************************************************************/
/* CompleteSendCoDeleteVc */
/****************************************************************************/
/* */
/* Routine Description: */
/* */
/* Callback routine called when microport completes sending a DeleteVc */
/* message to the device. */
/* */
/* Arguments: */
/* */
/* pMsgFrame - Pointer to message frame */
/* SendStatus - status of the microport send. */
/* */
/* Return: */
/* */
/* VOID */
/* */
/****************************************************************************/
VOID
CompleteSendCoDeleteVc(IN PRNDISMP_MESSAGE_FRAME pMsgFrame,
IN NDIS_STATUS SendStatus)
{
PRNDISMP_VC pVc;
PRNDISMP_ADAPTER pAdapter;
PRNDISMP_MESSAGE_FRAME pTmpMsgFrame;
if (SendStatus == NDIS_STATUS_SUCCESS)
{
//
// The message was sent successfully. Do nothing until
// we get a response from the device.
//
}
else
{
pVc = pMsgFrame->pVc;
pAdapter = pVc->pAdapter;
TRACE1(("CompleteSendCoDeleteVc: VC %x, Adapter %x, fail status %x\n",
pVc, pAdapter, SendStatus));
//
// Failed to send it to the device. Remove this message from
// the pending list and free it.
//
RNDISMP_LOOKUP_PENDING_MESSAGE(pTmpMsgFrame, pAdapter, pMsgFrame->RequestId);
ASSERT(pMsgFrame == pTmpMsgFrame);
DereferenceMsgFrame(pMsgFrame);
//
// Take care of the VC now.
//
HandleCoDeleteVcFailure(pVc, SendStatus);
}
} // CompleteSendCoDeleteVc
/****************************************************************************/
/* HandleCoDeleteVcFailure */
/****************************************************************************/
/* */
/* Routine Description: */
/* */
/* Utility routine to handle failure of a DeleteVc, either due to a local */
/* microport send failure, or via explicit rejection by the device. */
/* */
/* Arguments: */
/* */
/* pVc - Pointer to VC on which this failure has occurred */
/* Status - NDIS status associated with this failure */
/* */
/* Return: */
/* */
/* VOID */
/* */
/****************************************************************************/
VOID
HandleCoDeleteVcFailure(IN PRNDISMP_VC pVc,
IN NDIS_STATUS Status)
{
ULONG RefCount = 0;
RNDISMP_ACQUIRE_VC_LOCK(pVc);
switch (pVc->VcState)
{
case RNDISMP_VC_DELETING:
pVc->VcState = RNDISMP_VC_DELETE_FAIL;
break;
default:
ASSERT(FALSE);
break;
}
RNDISMP_DEREF_VC_LOCKED(pVc, &RefCount); // Pending DeleteVc response
if (RefCount != 0)
{
RNDISMP_RELEASE_VC_LOCK(pVc);
}
} // HandleCoDeleteVcFailure
/****************************************************************************/
/* RndismpCoActivateVc */
/****************************************************************************/
/* */
/* Routine Description: */
/* */
/* Entry point to activate a VC. We send an ActivateVc message to the */
/* device. */
/* */
/* Arguments: */
/* */
/* MiniportVcContext - pointer to our VC structure */
/* pCallParameters - CONDIS parameters for the VC */
/* */
/* Return: */
/* */
/* NDIS_STATUS */
/* */
/****************************************************************************/
NDIS_STATUS
RndismpCoActivateVc(IN NDIS_HANDLE MiniportVcContext,
IN PCO_CALL_PARAMETERS pCallParameters)
{
PRNDISMP_VC pVc;
NDIS_STATUS Status;
pVc = PRNDISMP_VC_FROM_CONTEXT_HANDLE(MiniportVcContext);
pVc->pCallParameters = pCallParameters;
Status = StartVcActivation(pVc);
return (Status);
} // RndismpCoActivateVc
/****************************************************************************/
/* StartVcActivation */
/****************************************************************************/
/* */
/* Routine Description: */
/* */
/* Start an Activate-VC operation on the specified VC. */
/* */
/* Arguments: */
/* */
/* pVc - Pointer to VC structure */
/* */
/* Return: */
/* */
/* NDIS_STATUS */
/* */
/****************************************************************************/
NDIS_STATUS
StartVcActivation(IN PRNDISMP_VC pVc)
{
NDIS_STATUS Status;
PRNDISMP_MESSAGE_FRAME pMsgFrame;
PRNDISMP_ADAPTER pAdapter;
BOOLEAN bSendActivateVc;
NDIS_HANDLE NdisVcHandle;
PCO_CALL_PARAMETERS pCallParameters;
Status = NDIS_STATUS_PENDING;
bSendActivateVc = FALSE;
NdisVcHandle = pVc->NdisVcHandle;
pCallParameters = pVc->pCallParameters;
pAdapter = pVc->pAdapter;
do
{
//
// Prepare an ActivateVc message to send to the device.
//
pMsgFrame = BuildRndisMessageCoMiniport(pAdapter,
pVc,
REMOTE_CONDIS_MP_ACTIVATE_VC_MSG,
pCallParameters);
RNDISMP_ACQUIRE_VC_LOCK(pVc);
switch (pVc->VcState)
{
case RNDISMP_VC_CREATING:
pVc->VcState = RNDISMP_VC_CREATING_ACTIVATE_PENDING;
break;
case RNDISMP_VC_CREATED:
if (pMsgFrame != NULL)
{
pVc->VcState = RNDISMP_VC_ACTIVATING;
bSendActivateVc = TRUE;
}
else
{
TRACE1(("StartVcAct: VC %x, failed to build msg!\n", pVc));
Status = NDIS_STATUS_RESOURCES;
}
break;
default:
TRACE1(("StartVcAct: VC %x in invalid state %d\n", pVc, pVc->VcState));
Status = NDIS_STATUS_NOT_ACCEPTED;
break;
}
RNDISMP_RELEASE_VC_LOCK(pVc);
if (Status != NDIS_STATUS_PENDING)
{
break;
}
if (bSendActivateVc)
{
ASSERT(pMsgFrame != NULL);
RNDISMP_REF_VC(pVc); // pending ActivateVc message
RNDISMP_SEND_TO_MICROPORT(pAdapter, pMsgFrame, TRUE, CompleteSendCoActivateVc);
}
}
while (FALSE);
if (!bSendActivateVc)
{
if (pMsgFrame != NULL)
{
DereferenceMsgFrame(pMsgFrame);
}
}
if (Status != NDIS_STATUS_PENDING)
{
NdisMCoActivateVcComplete(
Status,
NdisVcHandle,
pCallParameters);
Status = NDIS_STATUS_PENDING;
}
return (Status);
} // StartVcActivation
/****************************************************************************/
/* CompleteSendCoActivateVc */
/****************************************************************************/
/* */
/* Routine Description: */
/* */
/* Callback routine to handle send-completion of an Activate VC message. */
/* */
/* Arguments: */
/* */
/* pMsgFrame - Pointer to message frame */
/* SendStatus - status of the microport send. */
/* */
/* Return: */
/* */
/* VOID */
/* */
/****************************************************************************/
VOID
CompleteSendCoActivateVc(IN PRNDISMP_MESSAGE_FRAME pMsgFrame,
IN NDIS_STATUS SendStatus)
{
PRNDISMP_VC pVc;
PRNDISMP_ADAPTER pAdapter;
PRNDISMP_MESSAGE_FRAME pTmpMsgFrame;
PCO_CALL_PARAMETERS pCallParameters;
ULONG RefCount = 0;
NDIS_HANDLE NdisVcHandle;
if (SendStatus == NDIS_STATUS_SUCCESS)
{
//
// The message was sent successfully. Do nothing until
// we get a response from the device.
//
}
else
{
pVc = pMsgFrame->pVc;
pAdapter = pVc->pAdapter;
TRACE1(("CompleteSendCoActivateVc: VC %x, Adapter %x, fail status %x\n",
pVc, pAdapter, SendStatus));
ASSERT(SendStatus != NDIS_STATUS_PENDING);
//
// Failed to send it to the device. Remove this message from
// the pending list and free it.
//
RNDISMP_LOOKUP_PENDING_MESSAGE(pTmpMsgFrame, pAdapter, pMsgFrame->RequestId);
ASSERT(pMsgFrame == pTmpMsgFrame);
DereferenceMsgFrame(pMsgFrame);
//
// Take care of the VC now.
//
RNDISMP_ACQUIRE_VC_LOCK(pVc);
NdisVcHandle = pVc->NdisVcHandle;
pCallParameters = pVc->pCallParameters;
pVc->VcState = RNDISMP_VC_CREATED;
RNDISMP_DEREF_VC_LOCKED(pVc, &RefCount); // pending ActivateVc
if (RefCount != 0)
{
RNDISMP_RELEASE_VC_LOCK(pVc);
}
NdisMCoActivateVcComplete(
SendStatus,
NdisVcHandle,
pCallParameters);
}
} // CompleteSendCoActivateVc
/****************************************************************************/
/* RndismpCoDeactivateVc */
/****************************************************************************/
/* */
/* Routine Description: */
/* */
/* Entry point to de-activate a VC. We send an DeactivateVc message to the */
/* device. */
/* */
/* Arguments: */
/* */
/* MiniportVcContext - pointer to our VC structure */
/* */
/* Return: */
/* */
/* NDIS_STATUS */
/* */
/****************************************************************************/
NDIS_STATUS
RndismpCoDeactivateVc(IN NDIS_HANDLE MiniportVcContext)
{
PRNDISMP_VC pVc;
PRNDISMP_ADAPTER pAdapter;
PRNDISMP_MESSAGE_FRAME pMsgFrame;
NDIS_STATUS Status;
NDIS_HANDLE NdisVcHandle;
BOOLEAN bVcLockAcquired = FALSE;
BOOLEAN bSendDeactivateVc = FALSE;
pMsgFrame = NULL;
pVc = PRNDISMP_VC_FROM_CONTEXT_HANDLE(MiniportVcContext);
pAdapter = pVc->pAdapter;
Status = NDIS_STATUS_PENDING;
do
{
//
// Prepare a DeactivateVc message to send to the device.
//
pMsgFrame = BuildRndisMessageCoMiniport(pAdapter,
pVc,
REMOTE_CONDIS_MP_DEACTIVATE_VC_MSG,
NULL);
bVcLockAcquired = TRUE;
RNDISMP_ACQUIRE_VC_LOCK(pVc);
NdisVcHandle = pVc->NdisVcHandle;
if (pVc->VcState != RNDISMP_VC_ACTIVATED)
{
Status = NDIS_STATUS_NOT_ACCEPTED;
break;
}
switch (pVc->VcState)
{
case RNDISMP_VC_ACTIVATED:
if (pMsgFrame != NULL)
{
bSendDeactivateVc = TRUE;
pVc->VcState = RNDISMP_VC_DEACTIVATING;
}
else
{
bSendDeactivateVc = FALSE;
Status = NDIS_STATUS_RESOURCES;
}
break;
default:
bSendDeactivateVc = FALSE;
break;
}
if (bSendDeactivateVc)
{
RNDISMP_REF_VC(pVc); // pending Deactivate VC
RNDISMP_SEND_TO_MICROPORT(pAdapter, pMsgFrame, TRUE, CompleteSendCoDeactivateVc);
}
}
while (FALSE);
if (!bSendDeactivateVc)
{
if (pMsgFrame != NULL)
{
DereferenceMsgFrame(pMsgFrame);
}
}
if (Status != NDIS_STATUS_PENDING)
{
ASSERT(Status != NDIS_STATUS_SUCCESS);
NdisMCoDeactivateVcComplete(
Status,
NdisVcHandle);
Status = NDIS_STATUS_PENDING;
}
return (Status);
}
/****************************************************************************/
/* CompleteSendCoDeactivateVc */
/****************************************************************************/
/* */
/* Routine Description: */
/* */
/* Callback routine to handle send-completion of a deactivate VC message. */
/* */
/* Arguments: */
/* */
/* pMsgFrame - Pointer to message frame */
/* SendStatus - status of the microport send. */
/* */
/* Return: */
/* */
/* VOID */
/* */
/****************************************************************************/
VOID
CompleteSendCoDeactivateVc(IN PRNDISMP_MESSAGE_FRAME pMsgFrame,
IN NDIS_STATUS SendStatus)
{
PRNDISMP_VC pVc;
PRNDISMP_ADAPTER pAdapter;
PRNDISMP_MESSAGE_FRAME pTmpMsgFrame;
PCO_CALL_PARAMETERS pCallParameters;
ULONG RefCount = 0;
NDIS_HANDLE NdisVcHandle;
if (SendStatus == NDIS_STATUS_SUCCESS)
{
//
// The message was sent successfully. Do nothing until
// we get a response from the device.
//
}
else
{
pVc = pMsgFrame->pVc;
pAdapter = pVc->pAdapter;
TRACE1(("CompleteSendCoDeactivateVc: VC %x, Adapter %x, fail status %x\n",
pVc, pAdapter, SendStatus));
ASSERT(SendStatus != NDIS_STATUS_PENDING);
//
// Failed to send it to the device. Remove this message from
// the pending list and free it.
//
RNDISMP_LOOKUP_PENDING_MESSAGE(pTmpMsgFrame, pAdapter, pMsgFrame->RequestId);
ASSERT(pMsgFrame == pTmpMsgFrame);
DereferenceMsgFrame(pMsgFrame);
//
// Take care of the VC now.
//
RNDISMP_ACQUIRE_VC_LOCK(pVc);
NdisVcHandle = pVc->NdisVcHandle;
pCallParameters = pVc->pCallParameters;
pVc->VcState = RNDISMP_VC_ACTIVATED;
RNDISMP_DEREF_VC_LOCKED(pVc, &RefCount); // pending DeactivateVc
if (RefCount != 0)
{
RNDISMP_RELEASE_VC_LOCK(pVc);
}
NdisMCoDeactivateVcComplete(
SendStatus,
NdisVcHandle);
}
} // CompleteSendCoDeactivateVc
/****************************************************************************/
/* RndismpCoRequest */
/****************************************************************************/
/* */
/* Routine Description: */
/* */
/* Entry point to handle a CO-request. We send a MiniportCoRequest message */
/* to the device. */
/* */
/* Arguments: */
/* */
/* MiniportAdapterContext - pointer to our adapter structure */
/* MiniportVcContext - pointer to our VC structure */
/* pRequest - Pointer to NDIS request */
/* */
/* Return: */
/* */
/* NDIS_STATUS */
/* */
/****************************************************************************/
NDIS_STATUS
RndismpCoRequest(IN NDIS_HANDLE MiniportAdapterContext,
IN NDIS_HANDLE MiniportVcContext,
IN OUT PNDIS_REQUEST pRequest)
{
PRNDISMP_ADAPTER pAdapter;
PRNDISMP_VC pVc;
NDIS_STATUS Status;
NDIS_OID Oid;
pAdapter = PRNDISMP_ADAPTER_FROM_CONTEXT_HANDLE(MiniportAdapterContext);
pVc = PRNDISMP_VC_FROM_CONTEXT_HANDLE(MiniportVcContext);
switch (pRequest->RequestType)
{
case NdisRequestQueryInformation:
case NdisRequestQueryStatistics:
Oid = pRequest->DATA.QUERY_INFORMATION.Oid;
TRACE2(("CoReq: Adapter %x, Req %x, QueryInfo/Stat (%d) Oid %x\n",
pAdapter, pRequest, pRequest->RequestType, Oid));
Status = ProcessQueryInformation(pAdapter,
pVc,
pRequest,
Oid,
pRequest->DATA.QUERY_INFORMATION.InformationBuffer,
pRequest->DATA.QUERY_INFORMATION.InformationBufferLength,
&pRequest->DATA.QUERY_INFORMATION.BytesWritten,
&pRequest->DATA.QUERY_INFORMATION.BytesNeeded);
break;
case NdisRequestSetInformation:
Oid = pRequest->DATA.SET_INFORMATION.Oid;
TRACE1(("CoReq: Adapter %x, Req %x, SetInfo Oid %x\n",
pAdapter, pRequest, Oid));
Status = ProcessSetInformation(pAdapter,
pVc,
pRequest,
Oid,
pRequest->DATA.SET_INFORMATION.InformationBuffer,
pRequest->DATA.SET_INFORMATION.InformationBufferLength,
&pRequest->DATA.SET_INFORMATION.BytesRead,
&pRequest->DATA.SET_INFORMATION.BytesNeeded);
break;
default:
TRACE1(("CoReq: Unsupported request type %d\n",
pRequest->RequestType));
Status = NDIS_STATUS_NOT_SUPPORTED;
break;
}
return (Status);
}
/****************************************************************************/
/* RndismpCoSendPackets */
/****************************************************************************/
/* */
/* Routine Description: */
/* */
/* Entry point to send one or more packets on a VC. */
/* */
/* Arguments: */
/* */
/* MiniportVcContext - pointer to our VC structure */
/* PacketArray - Array of packet pointers */
/* NumberOfPackets - number of packets in array above */
/* */
/* Return: */
/* */
/* VOID */
/* */
/****************************************************************************/
VOID
RndismpCoSendPackets(IN NDIS_HANDLE MiniportVcContext,
IN PNDIS_PACKET * PacketArray,
IN UINT NumberOfPackets)
{
PRNDISMP_VC pVc;
UINT i;
pVc = PRNDISMP_VC_FROM_CONTEXT_HANDLE(MiniportVcContext);
RNDISMP_ACQUIRE_VC_LOCK(pVc);
pVc->RefCount += NumberOfPackets;
if (pVc->VcState == RNDISMP_VC_ACTIVATED)
{
RNDISMP_RELEASE_VC_LOCK(pVc);
DoMultipleSend(pVc->pAdapter,
pVc,
PacketArray,
NumberOfPackets);
}
else
{
RNDISMP_RELEASE_VC_LOCK(pVc);
for (i = 0; i < NumberOfPackets; i++)
{
CompleteSendDataOnVc(pVc, PacketArray[i], NDIS_STATUS_VC_NOT_ACTIVATED);
}
}
} // RndismpCoSendPackets
/****************************************************************************/
/* ReceiveCreateVcComplete */
/****************************************************************************/
/* */
/* Routine Description: */
/* */
/* Process a CONDIS CreateVcComplete message from the device */
/* */
/* Arguments: */
/* */
/* pAdapter - pointer to our Adapter structure */
/* pMessage - pointer to RNDIS message */
/* pMdl - pointer to MDL received from microport */
/* TotalLength - length of complete message */
/* MicroportMessageContext - context for message from micorport */
/* ReceiveStatus - used by microport to indicate it is low on resource */
/* bMessageCopied - is this a copy of the original message? */
/* */
/* Return: */
/* */
/* BOOLEAN - should the message be returned to the microport? */
/* */
/****************************************************************************/
BOOLEAN
ReceiveCreateVcComplete(IN PRNDISMP_ADAPTER pAdapter,
IN PRNDIS_MESSAGE pMessage,
IN PMDL pMdl,
IN ULONG TotalLength,
IN NDIS_HANDLE MicroportMessageContext,
IN NDIS_STATUS ReceiveStatus,
IN BOOLEAN bMessageCopied)
{
BOOLEAN bDiscardPkt = TRUE;
PRNDISMP_VC pVc;
PRNDISMP_MESSAGE_FRAME pCreateVcMsgFrame;
PRCONDIS_MP_CREATE_VC_COMPLETE pCreateVcComp;
RNDISMP_VC_STATE VcState;
BOOLEAN bVcLockAcquired = FALSE;
ULONG RefCount = 0;
NDIS_STATUS Status;
pVc = NULL;
do
{
pCreateVcComp = RNDIS_MESSAGE_PTR_TO_MESSAGE_PTR(pMessage);
//
// TBD - Validate lengths?
//
//
// Check the request Id.
//
RNDISMP_LOOKUP_PENDING_MESSAGE(pCreateVcMsgFrame, pAdapter, pCreateVcComp->RequestId);
if (pCreateVcMsgFrame == NULL)
{
TRACE1(("CreateVcComp: Adapter %x, Invalid ReqId %d!\n",
pAdapter, pCreateVcComp->RequestId));
break;
}
pVc = pCreateVcMsgFrame->pVc;
Status = pCreateVcComp->Status;
DereferenceMsgFrame(pCreateVcMsgFrame);
if (Status != NDIS_STATUS_SUCCESS)
{
HandleCoCreateVcFailure(pVc, Status);
break;
}
bVcLockAcquired = TRUE;
RNDISMP_ACQUIRE_VC_LOCK(pVc);
RNDISMP_DEREF_VC_LOCKED(pVc, &RefCount); // pending CreateVc
if (RefCount == 0)
{
bVcLockAcquired = FALSE;
break;
}
pVc->DeviceVcContext = pCreateVcComp->DeviceVcHandle;
VcState = pVc->VcState;
switch (VcState)
{
case RNDISMP_VC_CREATING:
pVc->VcState = RNDISMP_VC_CREATED;
break;
case RNDISMP_VC_CREATING_ACTIVATE_PENDING:
pVc->VcState = RNDISMP_VC_CREATED;
RNDISMP_RELEASE_VC_LOCK(pVc);
bVcLockAcquired = FALSE;
Status = StartVcActivation(pVc);
ASSERT(Status == NDIS_STATUS_PENDING);
break;
case RNDISMP_VC_CREATING_DELETE_PENDING:
pVc->VcState = RNDISMP_VC_CREATED;
RNDISMP_RELEASE_VC_LOCK(pVc);
bVcLockAcquired = FALSE;
Status = StartVcDeletion(pVc);
break;
default:
TRACE1(("CreateVcComp: VC %x, wrong state %d\n",
pVc, VcState));
break;
}
}
while (FALSE);
if (bVcLockAcquired)
{
RNDISMP_RELEASE_VC_LOCK(pVc);
}
return (bDiscardPkt);
}
/****************************************************************************/
/* ReceiveActivateVcComplete */
/****************************************************************************/
/* */
/* Routine Description: */
/* */
/* Process a CONDIS ActivateVcComplete message from the device */
/* */
/* Arguments: */
/* */
/* pAdapter - pointer to our Adapter structure */
/* pMessage - pointer to RNDIS message */
/* pMdl - pointer to MDL received from microport */
/* TotalLength - length of complete message */
/* MicroportMessageContext - context for message from micorport */
/* ReceiveStatus - used by microport to indicate it is low on resource */
/* bMessageCopied - is this a copy of the original message? */
/* */
/* Return: */
/* */
/* BOOLEAN - should the message be returned to the microport? */
/* */
/****************************************************************************/
BOOLEAN
ReceiveActivateVcComplete(IN PRNDISMP_ADAPTER pAdapter,
IN PRNDIS_MESSAGE pMessage,
IN PMDL pMdl,
IN ULONG TotalLength,
IN NDIS_HANDLE MicroportMessageContext,
IN NDIS_STATUS ReceiveStatus,
IN BOOLEAN bMessageCopied)
{
BOOLEAN bDiscardPkt = TRUE;
PRNDISMP_VC pVc;
PRNDISMP_MESSAGE_FRAME pActVcMsgFrame;
PRCONDIS_MP_ACTIVATE_VC_COMPLETE pActVcComp;
BOOLEAN bVcLockAcquired = FALSE;
ULONG RefCount = 0;
NDIS_STATUS Status;
NDIS_HANDLE NdisVcHandle;
PCO_CALL_PARAMETERS pCallParameters;
pVc = NULL;
do
{
pActVcComp = RNDIS_MESSAGE_PTR_TO_MESSAGE_PTR(pMessage);
//
// TBD - Validate lengths?
//
//
// Check the request Id.
//
RNDISMP_LOOKUP_PENDING_MESSAGE(pActVcMsgFrame, pAdapter, pActVcComp->RequestId);
if (pActVcMsgFrame == NULL)
{
TRACE1(("ActVcComp: Adapter %x, Invalid ReqId %d!\n",
pAdapter, pActVcComp->RequestId));
break;
}
pVc = pActVcMsgFrame->pVc;
DereferenceMsgFrame(pActVcMsgFrame);
bVcLockAcquired = TRUE;
RNDISMP_ACQUIRE_VC_LOCK(pVc);
RNDISMP_DEREF_VC_LOCKED(pVc, &RefCount); // pending ActivateVc
if (RefCount == 0)
{
bVcLockAcquired = FALSE;
break;
}
if (pVc->VcState != RNDISMP_VC_ACTIVATING)
{
TRACE1(("ActVcComp: Adapter %x, VC %x: invalid state %d\n",
pAdapter, pVc, pVc->VcState));
break;
}
Status = pActVcComp->Status;
if (Status == NDIS_STATUS_SUCCESS)
{
pVc->VcState = RNDISMP_VC_ACTIVATED;
}
else
{
pVc->VcState = RNDISMP_VC_CREATED;
}
NdisVcHandle = pVc->NdisVcHandle;
pCallParameters = pVc->pCallParameters;
RNDISMP_RELEASE_VC_LOCK(pVc);
bVcLockAcquired = FALSE;
NdisMCoActivateVcComplete(
pActVcComp->Status,
NdisVcHandle,
pCallParameters);
}
while (FALSE);
if (bVcLockAcquired)
{
RNDISMP_RELEASE_VC_LOCK(pVc);
}
return (bDiscardPkt);
}
/****************************************************************************/
/* ReceiveDeleteVcComplete */
/****************************************************************************/
/* */
/* Routine Description: */
/* */
/* Process a CONDIS DeleteVcComplete message from the device */
/* */
/* Arguments: */
/* */
/* pAdapter - pointer to our Adapter structure */
/* pMessage - pointer to RNDIS message */
/* pMdl - pointer to MDL received from microport */
/* TotalLength - length of complete message */
/* MicroportMessageContext - context for message from micorport */
/* ReceiveStatus - used by microport to indicate it is low on resource */
/* bMessageCopied - is this a copy of the original message? */
/* */
/* Return: */
/* */
/* BOOLEAN - should the message be returned to the microport? */
/* */
/****************************************************************************/
BOOLEAN
ReceiveDeleteVcComplete(IN PRNDISMP_ADAPTER pAdapter,
IN PRNDIS_MESSAGE pMessage,
IN PMDL pMdl,
IN ULONG TotalLength,
IN NDIS_HANDLE MicroportMessageContext,
IN NDIS_STATUS ReceiveStatus,
IN BOOLEAN bMessageCopied)
{
BOOLEAN bDiscardPkt = TRUE;
PRNDISMP_VC pVc;
PRCONDIS_MP_DELETE_VC_COMPLETE pDeleteVcComp;
PRNDISMP_MESSAGE_FRAME pDeleteVcMsgFrame;
RNDISMP_VC_STATE VcState;
BOOLEAN bVcLockAcquired = FALSE;
ULONG RefCount = 0;
NDIS_STATUS Status;
pVc = NULL;
do
{
pDeleteVcComp = RNDIS_MESSAGE_PTR_TO_MESSAGE_PTR(pMessage);
//
// TBD - Validate lengths?
//
//
// Check the request Id.
//
RNDISMP_LOOKUP_PENDING_MESSAGE(pDeleteVcMsgFrame, pAdapter, pDeleteVcComp->RequestId);
if (pDeleteVcMsgFrame == NULL)
{
TRACE1(("DeleteVcComp: Adapter %x, Invalid ReqId %d!\n",
pAdapter, pDeleteVcComp->RequestId));
break;
}
pVc = pDeleteVcMsgFrame->pVc;
Status = pDeleteVcComp->Status;
DereferenceMsgFrame(pDeleteVcMsgFrame);
if (Status != NDIS_STATUS_SUCCESS)
{
HandleCoDeleteVcFailure(pVc, Status);
break;
}
bVcLockAcquired = TRUE;
RNDISMP_ACQUIRE_VC_LOCK(pVc);
RNDISMP_DEREF_VC_LOCKED(pVc, &RefCount); // pending DeleteVc
if (RefCount == 0)
{
bVcLockAcquired = FALSE;
break;
}
if (pVc->VcState != RNDISMP_VC_DELETING)
{
TRACE1(("DeleteVcComp: Adapter %x, VC %x: invalid state %d\n",
pAdapter, pVc, pVc->VcState));
break;
}
pVc->VcState = RNDISMP_VC_ALLOCATED;
RNDISMP_DEREF_VC(pVc, &RefCount); // remove create ref
if (RefCount == 0)
{
bVcLockAcquired = FALSE;
}
}
while (FALSE);
if (bVcLockAcquired)
{
RNDISMP_RELEASE_VC_LOCK(pVc);
}
return (bDiscardPkt);
}
/****************************************************************************/
/* ReceiveDeactivateVcComplete */
/****************************************************************************/
/* */
/* Routine Description: */
/* */
/* Process a CONDIS DeActivateVcComplete message from the device */
/* */
/* Arguments: */
/* */
/* pAdapter - pointer to our Adapter structure */
/* pMessage - pointer to RNDIS message */
/* pMdl - pointer to MDL received from microport */
/* TotalLength - length of complete message */
/* MicroportMessageContext - context for message from micorport */
/* ReceiveStatus - used by microport to indicate it is low on resource */
/* bMessageCopied - is this a copy of the original message? */
/* */
/* Return: */
/* */
/* BOOLEAN - should the message be returned to the microport? */
/* */
/****************************************************************************/
BOOLEAN
ReceiveDeactivateVcComplete(IN PRNDISMP_ADAPTER pAdapter,
IN PRNDIS_MESSAGE pMessage,
IN PMDL pMdl,
IN ULONG TotalLength,
IN NDIS_HANDLE MicroportMessageContext,
IN NDIS_STATUS ReceiveStatus,
IN BOOLEAN bMessageCopied)
{
BOOLEAN bDiscardPkt = TRUE;
PRNDISMP_VC pVc;
RNDISMP_VC_STATE VcState;
PRNDISMP_MESSAGE_FRAME pDeactivateVcMsgFrame;
PRCONDIS_MP_DEACTIVATE_VC_COMPLETE pDeactivateVcComp;
BOOLEAN bVcLockAcquired = FALSE;
BOOLEAN bAddTempRef = FALSE;
ULONG RefCount = 0;
NDIS_STATUS Status;
pVc = NULL;
do
{
pDeactivateVcComp = RNDIS_MESSAGE_PTR_TO_MESSAGE_PTR(pMessage);
//
// TBD - Validate lengths?
//
//
// Check the request Id.
//
RNDISMP_LOOKUP_PENDING_MESSAGE(pDeactivateVcMsgFrame, pAdapter, pDeactivateVcComp->RequestId);
if (pDeactivateVcMsgFrame == NULL)
{
TRACE1(("DeactivateVcComp: Adapter %x, Invalid ReqId %d!\n",
pAdapter, pDeactivateVcComp->RequestId));
break;
}
pVc = pDeactivateVcMsgFrame->pVc;
DereferenceMsgFrame(pDeactivateVcMsgFrame);
bVcLockAcquired = TRUE;
RNDISMP_ACQUIRE_VC_LOCK(pVc);
RNDISMP_DEREF_VC_LOCKED(pVc, &RefCount); // pending DeactivateVc
if (RefCount == 0)
{
bVcLockAcquired = FALSE;
break;
}
if (pVc->VcState != RNDISMP_VC_DEACTIVATING)
{
TRACE1(("DeactVcComp: Adapter %x, VC %x: invalid state %d\n",
pAdapter, pVc, pVc->VcState));
ASSERT(FALSE);
break;
}
if (pDeactivateVcComp->Status == NDIS_STATUS_SUCCESS)
{
pVc->VcState = RNDISMP_VC_DEACTIVATED;
//
// We add a temp ref on the VC to help complete deactivate-VC
// from a common place (see bAddTempRef below).
//
RNDISMP_REF_VC(pVc); // temp ref, deactivate vc complete OK
bAddTempRef = TRUE;
}
else
{
pVc->VcState = RNDISMP_VC_ACTIVATED;
}
RNDISMP_RELEASE_VC_LOCK(pVc);
bVcLockAcquired = FALSE;
if (bAddTempRef)
{
//
// The following deref will check and call NDIS'
// deactivate vc complete API if we don't have any
// outstanding sends or receives on this VC.
//
RNDISMP_DEREF_VC(pVc, &RefCount); // temp ref
}
}
while (FALSE);
if (bVcLockAcquired)
{
RNDISMP_RELEASE_VC_LOCK(pVc);
}
return (bDiscardPkt);
}
/****************************************************************************/
/* BuildRndisMessageCoMiniport */
/****************************************************************************/
/* */
/* Routine Description: */
/* */
/* Allocate resources for message and frame and build an RNDIS message */
/* for sending to a remote CONDIS Miniport device. */
/* */
/* Arguments: */
/* */
/* pAdapter - Pointer to adapter structure */
/* pVc - Pointer to VC structure */
/* NdisMessageType - RNDIS message type */
/* pCallParameters - optional pointer to call parameters, applicable to */
/* certain message types. */
/* */
/* Return: */
/* */
/* PRNDISMP_MESSAGE_FRAME */
/* */
/****************************************************************************/
PRNDISMP_MESSAGE_FRAME
BuildRndisMessageCoMiniport(IN PRNDISMP_ADAPTER pAdapter,
IN PRNDISMP_VC pVc,
IN UINT NdisMessageType,
IN PCO_CALL_PARAMETERS pCallParameters OPTIONAL)
{
PRNDIS_MESSAGE pMessage;
UINT MessageSize;
PRNDISMP_MESSAGE_FRAME pMsgFrame;
switch (NdisMessageType)
{
case REMOTE_CONDIS_MP_CREATE_VC_MSG:
{
PRCONDIS_MP_CREATE_VC pCreateVc;
MessageSize = RNDIS_MESSAGE_SIZE(RCONDIS_MP_CREATE_VC);
pMsgFrame = AllocateMessageAndFrame(pAdapter, MessageSize);
if (pMsgFrame == NULL)
{
break;
}
pMessage = RNDISMP_GET_MSG_FROM_FRAME(pMsgFrame);
pMessage->NdisMessageType = NdisMessageType;
pMsgFrame->NdisMessageType = NdisMessageType;
pCreateVc = &pMessage->Message.CoMiniportCreateVc;
pCreateVc->RequestId = pMsgFrame->RequestId;
pCreateVc->NdisVcHandle = pVc->VcId;
break;
}
case REMOTE_CONDIS_MP_DELETE_VC_MSG:
{
PRCONDIS_MP_DELETE_VC pDeleteVc;
MessageSize = RNDIS_MESSAGE_SIZE(RCONDIS_MP_DELETE_VC);
pMsgFrame = AllocateMessageAndFrame(pAdapter, MessageSize);
if (pMsgFrame == NULL)
{
break;
}
pMessage = RNDISMP_GET_MSG_FROM_FRAME(pMsgFrame);
pMessage->NdisMessageType = NdisMessageType;
pMsgFrame->NdisMessageType = NdisMessageType;
pDeleteVc = &pMessage->Message.CoMiniportDeleteVc;
pDeleteVc->RequestId = pMsgFrame->RequestId;
pDeleteVc->DeviceVcHandle = pVc->DeviceVcContext;
break;
}
case REMOTE_CONDIS_MP_ACTIVATE_VC_MSG:
{
PRCONDIS_MP_ACTIVATE_VC_REQUEST pActivateVc;
PRCONDIS_CALL_MANAGER_PARAMETERS pCallMgrParams;
PRCONDIS_MEDIA_PARAMETERS pMediaParams;
ULONG_PTR FillLocation;
UINT FillOffset;
ASSERT(pCallParameters != NULL);
MessageSize = RNDIS_MESSAGE_SIZE(RCONDIS_MP_ACTIVATE_VC_REQUEST);
if (pCallParameters->CallMgrParameters)
{
MessageSize += (sizeof(RCONDIS_CALL_MANAGER_PARAMETERS) +
pCallParameters->CallMgrParameters->CallMgrSpecific.Length);
}
if (pCallParameters->MediaParameters)
{
MessageSize += (sizeof(RCONDIS_MEDIA_PARAMETERS) +
pCallParameters->MediaParameters->MediaSpecific.Length);
}
pMsgFrame = AllocateMessageAndFrame(pAdapter, MessageSize);
if (pMsgFrame == NULL)
{
break;
}
pMessage = RNDISMP_GET_MSG_FROM_FRAME(pMsgFrame);
pMessage->NdisMessageType = NdisMessageType;
pMsgFrame->NdisMessageType = NdisMessageType;
pActivateVc = &pMessage->Message.CoMiniportActivateVc;
pActivateVc->RequestId = pMsgFrame->RequestId;
pActivateVc->DeviceVcHandle = pVc->DeviceVcContext;
pActivateVc->Flags = pCallParameters->Flags;
FillOffset = RNDIS_MESSAGE_SIZE(RCONDIS_MP_ACTIVATE_VC_REQUEST);
FillLocation = ((ULONG_PTR)pMessage + FillOffset);
//
// Fill in Media parameters, if present.
//
if (pCallParameters->MediaParameters)
{
PCO_SPECIFIC_PARAMETERS pMediaSpecific;
pMediaSpecific = &pCallParameters->MediaParameters->MediaSpecific;
pMediaParams = (PRCONDIS_MEDIA_PARAMETERS)FillLocation;
pActivateVc->MediaParamsOffset = (UINT32)(FillLocation - (ULONG_PTR)pActivateVc);
pActivateVc->MediaParamsLength = sizeof(RCONDIS_MEDIA_PARAMETERS) +
pMediaSpecific->Length;
RNDISMP_MOVE_MEM(pMediaParams,
pCallParameters->MediaParameters,
FIELD_OFFSET(RCONDIS_MEDIA_PARAMETERS, MediaSpecific));
FillLocation += sizeof(RCONDIS_MEDIA_PARAMETERS);
FillOffset += sizeof(RCONDIS_MEDIA_PARAMETERS);
pMediaParams->MediaSpecific.ParameterOffset =
sizeof(RCONDIS_SPECIFIC_PARAMETERS);
pMediaParams->MediaSpecific.ParameterType =
pMediaSpecific->ParamType;
pMediaParams->MediaSpecific.ParameterLength =
pMediaSpecific->Length;
RNDISMP_MOVE_MEM((PVOID)FillLocation,
&pMediaSpecific->Parameters[0],
pMediaSpecific->Length);
FillLocation += pMediaSpecific->Length;
FillOffset += pMediaSpecific->Length;
}
else
{
pActivateVc->MediaParamsOffset = 0;
pActivateVc->MediaParamsLength = 0;
}
//
// Fill in Call manager parameters, if present.
//
if (pCallParameters->CallMgrParameters)
{
PCO_SPECIFIC_PARAMETERS pCallMgrSpecific;
pCallMgrSpecific = &pCallParameters->CallMgrParameters->CallMgrSpecific;
pCallMgrParams = (PRCONDIS_CALL_MANAGER_PARAMETERS)FillLocation;
pActivateVc->CallMgrParamsOffset = (UINT32)(FillLocation - (ULONG_PTR)pActivateVc);
pActivateVc->CallMgrParamsLength = sizeof(RCONDIS_CALL_MANAGER_PARAMETERS) +
pCallMgrSpecific->Length;
RNDISMP_MOVE_MEM(pCallMgrParams,
pCallParameters->CallMgrParameters,
FIELD_OFFSET(RCONDIS_CALL_MANAGER_PARAMETERS, CallMgrSpecific));
FillLocation += sizeof(RCONDIS_CALL_MANAGER_PARAMETERS);
FillOffset += sizeof(RCONDIS_CALL_MANAGER_PARAMETERS);
pCallMgrParams->CallMgrSpecific.ParameterOffset =
sizeof(RCONDIS_SPECIFIC_PARAMETERS);
pCallMgrParams->CallMgrSpecific.ParameterType =
pCallMgrSpecific->ParamType;
pCallMgrParams->CallMgrSpecific.ParameterLength =
pCallMgrSpecific->Length;
RNDISMP_MOVE_MEM((PVOID)FillLocation,
&pCallMgrSpecific->Parameters[0],
pCallMgrSpecific->Length);
FillLocation += pCallMgrSpecific->Length;
FillOffset += pCallMgrSpecific->Length;
}
else
{
pActivateVc->CallMgrParamsOffset = 0;
pActivateVc->CallMgrParamsLength = 0;
}
break;
}
case REMOTE_CONDIS_MP_DEACTIVATE_VC_MSG:
{
PRCONDIS_MP_DEACTIVATE_VC_REQUEST pDeactivateVc;
MessageSize = RNDIS_MESSAGE_SIZE(RCONDIS_MP_DEACTIVATE_VC_REQUEST);
pMsgFrame = AllocateMessageAndFrame(pAdapter, MessageSize);
if (pMsgFrame == NULL)
{
break;
}
pMessage = RNDISMP_GET_MSG_FROM_FRAME(pMsgFrame);
pMessage->NdisMessageType = NdisMessageType;
pMsgFrame->NdisMessageType = NdisMessageType;
pDeactivateVc = &pMessage->Message.CoMiniportDeactivateVc;
pDeactivateVc->RequestId = pMsgFrame->RequestId;
pDeactivateVc->DeviceVcHandle = pVc->DeviceVcContext;
break;
}
default:
ASSERT(FALSE);
pMsgFrame = NULL;
break;
}
return (pMsgFrame);
} // BuildRndisMessageCoMiniport
/****************************************************************************/
/* CompleteSendDataOnVc */
/****************************************************************************/
/* */
/* Routine Description: */
/* */
/* Handle send-completion of CONDIS data */
/* */
/* Arguments: */
/* */
/* pVc - Pointer to Vc */
/* pNdisPacket - Packet being completed */
/* Status - send completion status */
/* */
/* Return: */
/* */
/* VOID */
/* */
/****************************************************************************/
VOID
CompleteSendDataOnVc(IN PRNDISMP_VC pVc,
IN PNDIS_PACKET pNdisPacket,
IN NDIS_STATUS Status)
{
ULONG RefCount;
NdisMCoSendComplete(Status,
pVc->NdisVcHandle,
pNdisPacket);
RNDISMP_DEREF_VC(pVc, &RefCount);
}
/****************************************************************************/
/* IndicateReceiveDataOnVc */
/****************************************************************************/
/* */
/* Routine Description: */
/* */
/* Handle reception of a bunch of CONDIS packets on a Vc. */
/* */
/* Arguments: */
/* */
/* pVc - Pointer to VC on which data arrived. */
/* PacketArray - Array of packets */
/* NumberOfPackets - size of above array */
/* */
/* Return: */
/* */
/* VOID */
/* */
/****************************************************************************/
VOID
IndicateReceiveDataOnVc(IN PRNDISMP_VC pVc,
IN PNDIS_PACKET * PacketArray,
IN UINT NumberOfPackets)
{
UINT i;
do
{
if (pVc->VcState != RNDISMP_VC_ACTIVATED)
{
TRACE1(("Rcv VC data: VC %x, invalid state %d\n", pVc, pVc->VcState));
break;
}
for (i = 0; i < NumberOfPackets; i++)
{
RNDISMP_REF_VC(pVc);
}
NdisMCoIndicateReceivePacket(pVc->NdisVcHandle,
PacketArray,
NumberOfPackets);
}
while (FALSE);
} // IndicateReceiveDataOnVc