⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 protocol.c

📁 网络驱动开发
💻 C
📖 第 1 页 / 共 5 页
字号:
/*++

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 + -