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

📄 receive.c

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

Copyright (c) Microsoft Corporation.  All rights reserved.

    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.

Module Name:

        RECV.C
        
Abstract:

    This module contains miniport functions for handling Send & Receive
    packets and other helper routines called by these miniport functions.

Author:  Eliyas Yakub (Jan 11, 2003)
    
Revision History:

Notes:

--*/


#include "ndiswdm.h"

VOID 
MPReturnPacket(
    IN NDIS_HANDLE  MiniportAdapterContext,
    IN PNDIS_PACKET Packet)
/*++

Routine Description:

    NDIS Miniport entry point called whenever protocols are done with
    a packet that we had indicated up and they had queued up for returning
    later.

Arguments:

    MiniportAdapterContext    - pointer to MP_ADAPTER structure
    Packet    - packet being returned.

Return Value:

    None.

--*/
{
    PRCB pRCB = NULL;
    PMP_ADAPTER Adapter;
    
    DEBUGP(MP_TRACE, ("---> MPReturnPacket\n"));

    pRCB = *(PRCB *)Packet->MiniportReserved;

    Adapter = pRCB->Adapter;

    ASSERT(Adapter);
    
    Adapter->nPacketsReturned++;
    
    if(NdisInterlockedDecrement(&pRCB->Ref) == 0)
    {
        NICFreeRCB(pRCB);
    }
    
    DEBUGP(MP_TRACE, ("<--- MPReturnPacket\n"));
}

VOID
NICPostReadsWorkItemCallBack(
    PNDIS_WORK_ITEM WorkItem, 
    PVOID Context
    )
/*++

Routine Description:

   Workitem to post all the free read requests to the target
   driver. This workitme is scheduled from the MiniportInitialize
   worker routine during start and also from the NICFreeRCB whenever
   the outstanding read requests to the target driver goes below
   the NIC_SEND_LOW_WATERMARK.
      
Arguments:

    WorkItem - Pointer to workitem
    
    Dummy - Unused

Return Value:

    None.

--*/
{
    PMP_ADAPTER     Adapter = (PMP_ADAPTER)Context;
    NTSTATUS        ntStatus;
    PRCB            pRCB=NULL;
           
    DEBUGP(MP_TRACE, ("--->NICPostReadsWorkItemCallBack\n"));

    NdisAcquireSpinLock(&Adapter->RecvLock);

    while(MP_IS_READY(Adapter) && !IsListEmpty(&Adapter->RecvFreeList))
    {
        pRCB = (PRCB) RemoveHeadList(&Adapter->RecvFreeList);

        ASSERT(pRCB);// cannot be NULL
        
        //
        // Insert the RCB in the recv busy queue
        //     
        NdisInterlockedIncrement(&Adapter->nBusyRecv);          
        ASSERT(Adapter->nBusyRecv <= NIC_MAX_BUSY_RECVS);
        
        InsertTailList(&Adapter->RecvBusyList, &pRCB->List);

        NdisReleaseSpinLock(&Adapter->RecvLock);

        Adapter->nReadsPosted++;
        ntStatus = NICPostReadRequest(Adapter, pRCB);
        
        if (!NT_SUCCESS ( ntStatus ) ) {
            
            DEBUGP (MP_ERROR, ( "NICPostReadRequest failed %x\n", ntStatus ));
            break;            
        }
        
        NdisAcquireSpinLock(&Adapter->RecvLock);
        
    }

    NdisReleaseSpinLock(&Adapter->RecvLock);

    //
    // Clear the flag to let the WorkItem structure be reused for
    // scheduling another one.
    //
    InterlockedExchange(&Adapter->IsReadWorkItemQueued, FALSE);

    
    MP_DEC_REF(Adapter);     
    
    DEBUGP(MP_TRACE, ("<---NICPostReadsWorkItemCallBack\n"));        
}

NTSTATUS
NICPostReadRequest(
    PMP_ADAPTER Adapter,
    PRCB    pRCB
    )
/*++

Routine Description:

    This routine sends a read IRP to the target device to get
    the incoming network packet from the device.
        
Arguments:

    Adapter    - pointer to the MP_ADAPTER structure
    pRCB    -  Pointer to the RCB block that contains the IRP.


Return Value:

    NT status code

--*/
{
    NTSTATUS        status;
    PIRP            irp = pRCB->Irp;
    PIO_STACK_LOCATION  nextStack;
    PDEVICE_OBJECT   TargetDeviceObject = Adapter->TargetDeviceObject;

    DEBUGP(MP_TRACE, ("--> NICPostReadRequest\n"));

    // 
    // Obtain a pointer to the stack location of the first driver that will be
    // invoked.  This is where the function codes and the parameters are set.
    // 

    nextStack = IoGetNextIrpStackLocation(irp);
    nextStack->MajorFunction = IRP_MJ_READ;
    nextStack->Parameters.Read.Length = NIC_BUFFER_SIZE;
    nextStack->FileObject = Adapter->FileObject;
        
    irp->MdlAddress = (PMDL) pRCB->Buffer;

    pRCB->IrpLock = IRPLOCK_CANCELABLE;    
    pRCB->Ref = 1;

    
    IoSetCompletionRoutine(irp,
                   NICReadRequestCompletion,
                   pRCB,
                   TRUE,
                   TRUE,
                   TRUE);
    //
    // We are making an asynchronous request, so we don't really care
    // about the return status of IoCallDriver.
    //
    (void) IoCallDriver(TargetDeviceObject, irp);

    DEBUGP(MP_TRACE, ("<-- NICPostReadRequest\n"));

    return STATUS_SUCCESS;
}

NTSTATUS
NICReadRequestCompletion(
    IN PDEVICE_OBJECT   DeviceObject,
    IN PIRP             Irp,
    IN PVOID            Context
    )
/*++

Routine Description:

    Completion routine for the read request. This routine
    indicates the received packet from the WDM driver to 
    NDIS. This routine also handles the case where another 
    thread has canceled the read request.
        
Arguments:

    DeviceObject    -  not used. Should be NULL
    Irp    -   Pointer to our read IRP
    Context - pointer to our adapter context structure

Return Value:

    STATUS_MORE_PROCESSING_REQUIRED - because this is an asynchronouse IRP
    and we want to reuse it.
    
--*/
{
    PRCB    pRCB = (PRCB)Context;
    PMP_ADAPTER Adapter = pRCB->Adapter;
    ULONG   bytesRead;
    BOOLEAN bIndicateReceive = FALSE;
    
    DEBUGP(MP_TRACE, ("--> NICReadRequestCompletion\n"));

    
    if(!NT_SUCCESS(Irp->IoStatus.Status)) {       
        
        Adapter->nReadsCompletedWithError++;        
        DEBUGP (MP_LOUD, ("Read request failed %x\n", Irp->IoStatus.Status));        

        //
        // Clear the flag to prevent any more reads from being
        // posted to the target device.
        //
        MP_CLEAR_FLAG(Adapter, fMP_POST_READS);
        
    } else {
    
        Adapter->GoodReceives++;
        bytesRead = (ULONG)Irp->IoStatus.Information;
        DEBUGP (MP_VERY_LOUD, ("Read %d bytes\n", bytesRead));
        Adapter->nBytesRead += bytesRead;
        bIndicateReceive = TRUE;
    }
    
    if (InterlockedExchange((PVOID)&pRCB->IrpLock, IRPLOCK_COMPLETED) 
                    == IRPLOCK_CANCEL_STARTED) {
        // 
        // NICFreeBusyRecvPackets has got the control of the IRP. It will
        // now take the responsibility of freeing  the IRP. 
        // Therefore...
        
        return STATUS_MORE_PROCESSING_REQUIRED;
    }

    if(bIndicateReceive) {
        NICIndicateReceivedPacket(pRCB, bytesRead);                                
    }
    
    if(NdisInterlockedDecrement(&pRCB->Ref) == 0)
    {
        NICFreeRCB(pRCB);
    }
    
    return STATUS_MORE_PROCESSING_REQUIRED;
}

VOID
NICIndicateReceivedPacket(
    IN PRCB             pRCB,
    IN ULONG            BytesToIndicate
    )
/*++

Routine Description:

    Initialize the packet to describe the received data and
    indicate to NDIS.
        
Arguments:

    pRCB - pointer to the RCB block    
    BytesToIndicate - number of bytes to indicate

Return value:

    VOID
--*/
{
    ULONG           PacketLength;
    PNDIS_BUFFER    CurrentBuffer = NULL;
    PETH_HEADER     pEthHeader = NULL;
    PMP_ADAPTER     Adapter = pRCB->Adapter;
    PNDIS_PACKET    Packet = pRCB->Packet;
    KIRQL           oldIrql;
    
    NdisAdjustBufferLength(pRCB->Buffer, BytesToIndicate);

    //
    // Prepare the recv packet
    //

    NdisReinitializePacket(Packet);

    *((PRCB *)Packet->MiniportReserved) = pRCB;

    //
    // Chain the TCB buffers to the packet
    //
    NdisChainBufferAtBack(Packet, pRCB->Buffer);

    NdisQueryPacket(Packet, NULL, NULL, &CurrentBuffer,&PacketLength);

    ASSERT(CurrentBuffer == pRCB->Buffer);

    pEthHeader = (PETH_HEADER)pRCB->pData;

    if(PacketLength >= sizeof(ETH_HEADER) && 
        Adapter->PacketFilter &&
        NICIsPacketAcceptable(Adapter, pEthHeader->DstAddr)){
            
        DEBUGP(MP_LOUD, ("Src Address = %02x-%02x-%02x-%02x-%02x-%02x", 
            pEthHeader->SrcAddr[0],
            pEthHeader->SrcAddr[1],
            pEthHeader->SrcAddr[2],
            pEthHeader->SrcAddr[3],
            pEthHeader->SrcAddr[4],
            pEthHeader->SrcAddr[5]));

        DEBUGP(MP_LOUD, ("  Dest Address = %02x-%02x-%02x-%02x-%02x-%02x\n", 
            pEthHeader->DstAddr[0],
            pEthHeader->DstAddr[1],

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -