📄 protocol.c
字号:
/*++
Copyright(c) 1992-2000 Microsoft Corporation
Module Name:
protocol.c
Abstract:
NDIS Protocol Entry points and utility functions for the NDIS
MUX Intermediate Miniport sample.
The protocol edge binds to Ethernet (NdisMedium802_3) adapters,
and initiates creation of zero or more Virtual Ethernet LAN (VELAN)
miniport instances by calling NdisIMInitializeDeviceInstanceEx once
for each VELAN configured over a lower binding.
Environment:
Kernel mode.
Revision History:
--*/
#include "precomp.h"
#pragma hdrstop
#define MODULE_NUMBER MODULE_PROT
VOID
PtBindAdapter(
OUT PNDIS_STATUS Status,
IN NDIS_HANDLE BindContext,
IN PNDIS_STRING DeviceName,
IN PVOID SystemSpecific1,
IN PVOID SystemSpecific2
)
/*++
Routine Description:
Called by NDIS to bind to a miniport below. This routine
creates a binding by calling NdisOpenAdapter, and then
initiates creation of all configured VELANs on this binding.
Arguments:
Status - Return status of bind here.
BindContext - Can be passed to NdisCompleteBindAdapter if this
call is pended.
DeviceName - Device name to bind to. This is passed to
NdisOpenAdapter.
SystemSpecific1 - Can be passed to NdisOpenProtocolConfiguration to
read per-binding information
SystemSpecific2 - Unused
Return Value:
*Status is set to NDIS_STATUS_SUCCESS if no failure occurred
while handling this call, otherwise an error code.
--*/
{
PADAPT pAdapt = NULL;
NDIS_STATUS OpenErrorStatus;
UINT MediumIndex;
PNDIS_STRING pConfigString;
ULONG Length;
UNREFERENCED_PARAMETER(BindContext);
UNREFERENCED_PARAMETER(SystemSpecific2);
pConfigString = (PNDIS_STRING)SystemSpecific1;
DBGPRINT(MUX_LOUD, ("==> Protocol BindAdapter: %ws\n", pConfigString->Buffer));
do
{
//
// Allocate memory for Adapter struct plus the config
// string with two extra WCHARs for NULL termination.
//
Length = sizeof(ADAPT) +
pConfigString->MaximumLength + sizeof(WCHAR);
NdisAllocateMemoryWithTag(&pAdapt, Length , TAG);
if (pAdapt == NULL)
{
*Status = NDIS_STATUS_RESOURCES;
break;
}
//
// Initialize the adapter structure
//
NdisZeroMemory(pAdapt, sizeof(ADAPT));
(VOID)PtReferenceAdapter(pAdapt, (PUCHAR)"openadapter");
//
// Copy in the Config string - we will use this to open the
// registry section for this adapter at a later point.
//
pAdapt->ConfigString.MaximumLength = pConfigString->MaximumLength;
pAdapt->ConfigString.Length = pConfigString->Length;
pAdapt->ConfigString.Buffer = (PWCHAR)((PUCHAR)pAdapt +
sizeof(ADAPT));
NdisMoveMemory(pAdapt->ConfigString.Buffer,
pConfigString->Buffer,
pConfigString->Length);
pAdapt->ConfigString.Buffer[pConfigString->Length/sizeof(WCHAR)] =
((WCHAR)0);
NdisInitializeEvent(&pAdapt->Event);
NdisInitializeListHead(&pAdapt->VElanList);
pAdapt->PtDevicePowerState = NdisDeviceStateD0;
MUX_INIT_ADAPT_RW_LOCK(pAdapt);
//
// TODO: Allocate a packet pool and buffers for send & receive.
//
// Now open the adapter below and complete the initialization
//
NdisOpenAdapter(Status,
&OpenErrorStatus,
&pAdapt->BindingHandle,
&MediumIndex,
MediumArray,
sizeof(MediumArray)/sizeof(NDIS_MEDIUM),
ProtHandle,
pAdapt,
DeviceName,
0,
NULL);
if (*Status == NDIS_STATUS_PENDING)
{
NdisWaitEvent(&pAdapt->Event, 0);
*Status = pAdapt->Status;
}
if (*Status != NDIS_STATUS_SUCCESS)
{
pAdapt->BindingHandle = NULL;
break;
}
pAdapt->Medium = MediumArray[MediumIndex];
//
// Add this adapter to the global AdapterList
//
MUX_ACQUIRE_MUTEX(&GlobalMutex);
InsertTailList(&AdapterList, &pAdapt->Link);
MUX_RELEASE_MUTEX(&GlobalMutex);
//
// Get some information from the adapter below.
//
PtQueryAdapterInfo(pAdapt);
//
// Start all VELANS configured on this adapter.
//
*Status = PtBootStrapVElans(pAdapt);
} while(FALSE);
if (*Status != NDIS_STATUS_SUCCESS)
{
if (pAdapt != NULL)
{
//
// For some reason, the driver cannot create velan for the binding
//
if (pAdapt->BindingHandle != NULL)
{
NDIS_STATUS LocalStatus;
//
// Close the binding the driver opened above
//
NdisResetEvent(&pAdapt->Event);
NdisCloseAdapter(&LocalStatus, pAdapt->BindingHandle);
pAdapt->BindingHandle = NULL;
if (LocalStatus == NDIS_STATUS_PENDING)
{
NdisWaitEvent(&pAdapt->Event, 0);
}
MUX_ACQUIRE_MUTEX(&GlobalMutex);
RemoveEntryList(&pAdapt->Link);
MUX_RELEASE_MUTEX(&GlobalMutex);
}
PtDereferenceAdapter(pAdapt, (PUCHAR)"openadapter");
pAdapt = NULL;
}
}
DBGPRINT(MUX_INFO, ("<== Protocol BindAdapter: pAdapt %p, Status %x\n", pAdapt, *Status));
}
VOID
PtOpenAdapterComplete(
IN NDIS_HANDLE ProtocolBindingContext,
IN NDIS_STATUS Status,
IN NDIS_STATUS OpenErrorStatus
)
/*++
Routine Description:
Completion routine for NdisOpenAdapter issued from within the
PtBindAdapter. Simply unblock the caller.
Arguments:
ProtocolBindingContext Pointer to the adapter
Status Status of the NdisOpenAdapter call
OpenErrorStatus Secondary status(ignored by us).
Return Value:
None
--*/
{
PADAPT pAdapt =(PADAPT)ProtocolBindingContext;
UNREFERENCED_PARAMETER(OpenErrorStatus);
DBGPRINT(MUX_LOUD, ("==> PtOpenAdapterComplete: Adapt %p, Status %x\n", pAdapt, Status));
pAdapt->Status = Status;
NdisSetEvent(&pAdapt->Event);
}
VOID
PtQueryAdapterInfo(
IN PADAPT pAdapt
)
/*++
Routine Description:
Query the adapter we are bound to for some standard OID values
which we cache.
Arguments:
pAdapt Pointer to the adapter
Return Value:
None
--*/
{
//
// Get the link speed.
//
pAdapt->LinkSpeed = MUX_DEFAULT_LINK_SPEED;
PtQueryAdapterSync(pAdapt,
OID_GEN_LINK_SPEED,
&pAdapt->LinkSpeed,
sizeof(pAdapt->LinkSpeed));
//
// Get the max lookahead size.
//
pAdapt->MaxLookAhead = MUX_DEFAULT_LOOKAHEAD_SIZE;
PtQueryAdapterSync(pAdapt,
OID_GEN_MAXIMUM_LOOKAHEAD,
&pAdapt->MaxLookAhead,
sizeof(pAdapt->MaxLookAhead));
//
// Get the Ethernet MAC address.
//
PtQueryAdapterSync(pAdapt,
OID_802_3_CURRENT_ADDRESS,
&pAdapt->CurrentAddress,
sizeof(pAdapt->CurrentAddress));
}
VOID
PtQueryAdapterSync(
IN PADAPT pAdapt,
IN NDIS_OID Oid,
IN PVOID InformationBuffer,
IN ULONG InformationBufferLength
)
/*++
Routine Description:
Utility routine to query the adapter for a single OID value. This
blocks for the query to complete.
Arguments:
pAdapt Pointer to the adapter
Oid OID to query for
InformationBuffer Place for the result
InformationBufferLength Length of the above
Return Value:
None.
--*/
{
PMUX_NDIS_REQUEST pMuxNdisRequest = NULL;
NDIS_STATUS Status;
do
{
NdisAllocateMemoryWithTag(&pMuxNdisRequest, sizeof(MUX_NDIS_REQUEST), TAG);
if (pMuxNdisRequest == NULL)
{
break;
}
pMuxNdisRequest->pVElan = NULL; // internal request
//
// Set up completion routine.
//
pMuxNdisRequest->pCallback = PtCompleteBlockingRequest;
NdisInitializeEvent(&pMuxNdisRequest->Event);
pMuxNdisRequest->Request.RequestType = NdisRequestQueryInformation;
pMuxNdisRequest->Request.DATA.QUERY_INFORMATION.Oid = Oid;
pMuxNdisRequest->Request.DATA.QUERY_INFORMATION.InformationBuffer =
InformationBuffer;
pMuxNdisRequest->Request.DATA.QUERY_INFORMATION.InformationBufferLength =
InformationBufferLength;
NdisRequest(&Status,
pAdapt->BindingHandle,
&pMuxNdisRequest->Request);
if (Status == NDIS_STATUS_PENDING)
{
NdisWaitEvent(&pMuxNdisRequest->Event, 0);
Status = pMuxNdisRequest->Status;
}
}
while (FALSE);
if (NULL != pMuxNdisRequest)
{
NdisFreeMemory(pMuxNdisRequest, sizeof(MUX_NDIS_REQUEST), 0);
}
}
VOID
PtRequestAdapterAsync(
IN PADAPT pAdapt,
IN NDIS_REQUEST_TYPE RequestType,
IN NDIS_OID Oid,
IN PVOID InformationBuffer,
IN ULONG InformationBufferLength,
IN PMUX_REQ_COMPLETE_HANDLER pCallback
)
/*++
Routine Description:
Utility routine to query the adapter for a single OID value.
This completes asynchronously, i.e. the calling thread is
not blocked until the request completes.
Arguments:
pAdapt Pointer to the adapter
RequestType NDIS request type
Oid OID to set/query
InformationBuffer Input/output buffer
InformationBufferLength Length of the above
pCallback Function to call on request completion
Return Value:
None.
--*/
{
PMUX_NDIS_REQUEST pMuxNdisRequest = NULL;
PNDIS_REQUEST pNdisRequest;
NDIS_STATUS Status;
do
{
NdisAllocateMemoryWithTag(&pMuxNdisRequest, sizeof(MUX_NDIS_REQUEST), TAG);
if (pMuxNdisRequest == NULL)
{
break;
}
pMuxNdisRequest->pVElan = NULL; // internal request
//
// Set up completion routine.
//
pMuxNdisRequest->pCallback = pCallback;
pNdisRequest = &pMuxNdisRequest->Request;
pNdisRequest->RequestType = RequestType;
switch (RequestType)
{
case NdisRequestQueryInformation:
pNdisRequest->DATA.QUERY_INFORMATION.Oid = Oid;
pNdisRequest->DATA.QUERY_INFORMATION.InformationBuffer =
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -