1872 lines
72 KiB
C
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
|
|
|