📄 protocol.c
字号:
InformationBuffer;
pNdisRequest->DATA.QUERY_INFORMATION.InformationBufferLength =
InformationBufferLength;
break;
case NdisRequestSetInformation:
pNdisRequest->DATA.SET_INFORMATION.Oid = Oid;
pNdisRequest->DATA.SET_INFORMATION.InformationBuffer =
InformationBuffer;
pNdisRequest->DATA.SET_INFORMATION.InformationBufferLength =
InformationBufferLength;
break;
default:
ASSERT(FALSE);
break;
}
NdisRequest(&Status,
pAdapt->BindingHandle,
pNdisRequest);
if (Status != NDIS_STATUS_PENDING)
{
PtRequestComplete(
(NDIS_HANDLE)pAdapt,
pNdisRequest,
Status);
}
}
while (FALSE);
}
VOID
PtUnbindAdapter(
OUT PNDIS_STATUS Status,
IN NDIS_HANDLE ProtocolBindingContext,
IN NDIS_HANDLE UnbindContext
)
/*++
Routine Description:
Called by NDIS when we are required to unbind to the adapter below.
Go through all VELANs on the adapter and shut them down.
Arguments:
Status Placeholder for return status
ProtocolBindingContext Pointer to the adapter structure
UnbindContext Context for NdisUnbindComplete() if this pends
Return Value:
Status from closing the binding.
--*/
{
PADAPT pAdapt =(PADAPT)ProtocolBindingContext;
PLIST_ENTRY p;
PVELAN pVElan = NULL;
LOCK_STATE LockState;
UNREFERENCED_PARAMETER(UnbindContext);
DBGPRINT(MUX_LOUD, ("==> PtUnbindAdapter: Adapt %p\n", pAdapt));
//
// Stop all VELANs associated with the adapter.
// Repeatedly find the first unprocessed VELAN on
// the adapter, mark it, and stop it.
//
MUX_ACQUIRE_ADAPT_READ_LOCK(pAdapt, &LockState);
do
{
for (p = pAdapt->VElanList.Flink;
p != &pAdapt->VElanList;
p = p->Flink)
{
pVElan = CONTAINING_RECORD(p, VELAN, Link);
if (!pVElan->DeInitializing)
{
pVElan->DeInitializing = TRUE;
break;
}
}
if (p != &pAdapt->VElanList)
{
ASSERT(pVElan == CONTAINING_RECORD(p, VELAN, Link));
//
// Got a VELAN to stop. Add a temp ref
// so that the VELAN won't go away when
// we release the ADAPT lock below.
//
PtReferenceVElan(pVElan, (PUCHAR)"UnbindTemp");
//
// Release the read lock because we want to
// run StopVElan at passive IRQL.
//
MUX_RELEASE_ADAPT_READ_LOCK(pAdapt, &LockState);
PtStopVElan(pVElan);
PtDereferenceVElan(pVElan, (PUCHAR)"UnbindTemp");
MUX_ACQUIRE_ADAPT_READ_LOCK(pAdapt, &LockState);
}
else
{
//
// No unmarked VELAN, so exit.
//
break;
}
}
while (TRUE);
//
// Wait until all VELANs are unlinked from the adapter.
// This is so that we don't attempt to forward down packets
// and/or requests from VELANs after calling NdisCloseAdapter.
//
while (!IsListEmpty(&pAdapt->VElanList))
{
MUX_RELEASE_ADAPT_READ_LOCK(pAdapt, &LockState);
DBGPRINT(MUX_INFO, ("PtUnbindAdapter: pAdapt %p, VELANlist not yet empty\n",
pAdapt));
NdisMSleep(2000);
MUX_ACQUIRE_ADAPT_READ_LOCK(pAdapt, &LockState);
}
MUX_RELEASE_ADAPT_READ_LOCK(pAdapt, &LockState);
//
// Close the binding to the lower adapter.
//
if (pAdapt->BindingHandle != NULL)
{
NdisResetEvent(&pAdapt->Event);
NdisCloseAdapter(Status, pAdapt->BindingHandle);
//
// Wait for it to complete.
//
if (*Status == NDIS_STATUS_PENDING)
{
NdisWaitEvent(&pAdapt->Event, 0);
*Status = pAdapt->Status;
}
}
else
{
//
// Binding Handle should not be NULL.
//
*Status = NDIS_STATUS_FAILURE;
ASSERT(0);
}
//
// Remove the adapter from the global AdapterList
//
MUX_ACQUIRE_MUTEX(&GlobalMutex);
RemoveEntryList(&pAdapt->Link);
MUX_RELEASE_MUTEX(&GlobalMutex);
//
// Free all the resources associated with this Adapter except the
// ADAPT struct itself, because that will be freed by
// PtDereferenceAdapter call when the reference drops to zero.
// Note: Every VELAN associated with this Adapter takes a ref count
// on it. So the adapter memory wouldn't be freed until all the VELANs
// are shutdown.
//
PtDereferenceAdapter(pAdapt, (PUCHAR)"Unbind");
DBGPRINT(MUX_INFO, ("<== PtUnbindAdapter: Adapt %p\n", pAdapt));
}
VOID
PtCloseAdapterComplete(
IN NDIS_HANDLE ProtocolBindingContext,
IN NDIS_STATUS Status
)
/*++
Routine Description:
Completion for the CloseAdapter call.
Arguments:
ProtocolBindingContext Pointer to the adapter structure
Status Completion status
Return Value:
None.
--*/
{
PADAPT pAdapt =(PADAPT)ProtocolBindingContext;
DBGPRINT(MUX_INFO, ("==> PtCloseAdapterComplete: Adapt %p, Status %x\n",
pAdapt, Status));
pAdapt->Status = Status;
NdisSetEvent(&pAdapt->Event);
}
VOID
PtResetComplete(
IN NDIS_HANDLE ProtocolBindingContext,
IN NDIS_STATUS Status
)
/*++
Routine Description:
Completion for the reset.
Arguments:
ProtocolBindingContext Pointer to the adapter structure
Status Completion status
Return Value:
None.
--*/
{
#if DBG
PADAPT pAdapt =(PADAPT)ProtocolBindingContext;
#endif
#if !DBG
UNREFERENCED_PARAMETER(ProtocolBindingContext);
UNREFERENCED_PARAMETER(Status);
#endif
DBGPRINT(MUX_ERROR, ("==> PtResetComplete: Adapt %p, Status %x\n",
pAdapt, Status));
//
// We never issue a reset, so we should not be here.
//
ASSERT(0);
}
VOID
PtRequestComplete(
IN NDIS_HANDLE ProtocolBindingContext,
IN PNDIS_REQUEST NdisRequest,
IN NDIS_STATUS Status
)
/*++
Routine Description:
Completion handler for an NDIS request sent to a lower
miniport.
Arguments:
ProtocolBindingContext Pointer to the adapter structure
NdisRequest The completed request
Status Completion status
Return Value:
None
--*/
{
PADAPT pAdapt = (PADAPT)ProtocolBindingContext;
PMUX_NDIS_REQUEST pMuxNdisRequest;
pMuxNdisRequest = CONTAINING_RECORD(NdisRequest, MUX_NDIS_REQUEST, Request);
ASSERT(pMuxNdisRequest->pCallback != NULL);
//
// Completion is handled by the callback routine:
//
(*pMuxNdisRequest->pCallback)(pAdapt,
pMuxNdisRequest,
Status);
}
VOID
PtCompleteForwardedRequest(
IN PADAPT pAdapt,
IN PMUX_NDIS_REQUEST pMuxNdisRequest,
IN NDIS_STATUS Status
)
/*++
Routine Description:
Handle completion of an NDIS request that was originally
submitted to our VELAN miniport and was forwarded down
to the lower binding.
We do some postprocessing, to cache the results of
certain queries.
Arguments:
pAdapt - Adapter on which the request was forwarded
pMuxNdisRequest - super-struct for request
Status - request completion status
Return Value:
None
--*/
{
PVELAN pVElan = NULL;
PNDIS_REQUEST pNdisRequest = &pMuxNdisRequest->Request;
NDIS_OID Oid = pNdisRequest->DATA.SET_INFORMATION.Oid;
UNREFERENCED_PARAMETER(pAdapt);
//
// Get the originating VELAN. The VELAN will not be dereferenced
// away until the pended request is completed.
//
pVElan = pMuxNdisRequest->pVElan;
ASSERT(pVElan != NULL);
ASSERT(pMuxNdisRequest == &pVElan->Request);
if (Status != NDIS_STATUS_SUCCESS)
{
DBGPRINT(MUX_WARN, ("PtCompleteForwardedReq: pVElan %p, OID %x, Status %x\n",
pVElan,
pMuxNdisRequest->Request.DATA.QUERY_INFORMATION.Oid,
Status));
}
//
// Complete the original request.
//
switch (pNdisRequest->RequestType)
{
case NdisRequestQueryInformation:
*pVElan->BytesReadOrWritten =
pNdisRequest->DATA.QUERY_INFORMATION.BytesWritten;
*pVElan->BytesNeeded =
pNdisRequest->DATA.QUERY_INFORMATION.BytesNeeded;
//
// Before completing the request, do any necessary
// post-processing.
//
Oid = pNdisRequest->DATA.QUERY_INFORMATION.Oid;
if (Status == NDIS_STATUS_SUCCESS)
{
if (Oid == OID_GEN_LINK_SPEED)
{
NdisMoveMemory (&pVElan->LinkSpeed,
pNdisRequest->DATA.QUERY_INFORMATION.InformationBuffer,
sizeof(ULONG));
}
else if (Oid == OID_PNP_CAPABILITIES)
{
PtPostProcessPnPCapabilities(pVElan,
pNdisRequest->DATA.QUERY_INFORMATION.InformationBuffer,
pNdisRequest->DATA.QUERY_INFORMATION.InformationBufferLength);
}
}
NdisMQueryInformationComplete(pVElan->MiniportAdapterHandle, Status);
break;
case NdisRequestSetInformation:
*pVElan->BytesReadOrWritten =
pNdisRequest->DATA.SET_INFORMATION.BytesRead;
*pVElan->BytesNeeded =
pNdisRequest->DATA.SET_INFORMATION.BytesNeeded;
//
// Before completing the request, cache relevant information
// in our structure.
//
if (Status == NDIS_STATUS_SUCCESS)
{
Oid = pNdisRequest->DATA.SET_INFORMATION.Oid;
switch (Oid)
{
case OID_GEN_CURRENT_LOOKAHEAD:
NdisMoveMemory(&pVElan->LookAhead,
pNdisRequest->DATA.QUERY_INFORMATION.InformationBuffer,
sizeof(ULONG));
break;
default:
break;
}
}
NdisMSetInformationComplete(pVElan->MiniportAdapterHandle, Status);
break;
default:
ASSERT(FALSE);
break;
}
MUX_DECR_PENDING_SENDS(pVElan);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -