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

📄 recv.c

📁 ndis windows网络驱动程序的范例
💻 C
📖 第 1 页 / 共 2 页
字号:
/*++

Copyright (c) 1996  Microsoft Corporation

Module Name:

    recv.c

Abstract:

    routines to handle receiving data

Author:

    Jim Mateer

Environment:

    Kernel Mode

Revision History:

--*/

#include "ImSamp.h"
#pragma hdrstop


INT
CLReceivePacket(
	IN	NDIS_HANDLE				ProtocolBindingContext,
	IN	PNDIS_PACKET			Packet
	);

VOID
MPReturnPacket(
	IN	NDIS_HANDLE				MiniportAdapterContext,
	IN	PNDIS_PACKET			Packet
	);

NDIS_STATUS
CLReceiveIndication(
	IN	NDIS_HANDLE				ProtocolBindingContext,
	IN	NDIS_HANDLE				MacReceiveContext,
	IN	PVOID					HeaderBuffer,
	IN	UINT					HeaderBufferSize,
	IN	PVOID					LookAheadBuffer,
	IN	UINT					LookaheadBufferSize,
	IN	UINT					PacketSize
	);

VOID
CLReceiveComplete(
	IN	NDIS_HANDLE				ProtocolBindingContext
	);

NDIS_STATUS
MPTransferData(
	OUT PNDIS_PACKET			Packet,
	OUT PUINT					BytesTransferred,
	IN	NDIS_HANDLE				MiniportAdapterContext,
	IN	NDIS_HANDLE				MiniportReceiveContext,
	IN	UINT					ByteOffset,
	IN	UINT					BytesToTransfer
	);

VOID
CLTransferDataComplete(
    IN  NDIS_HANDLE     ProtocolBindingContext,
    IN  PNDIS_PACKET    pNdisPacket,
    IN  NDIS_STATUS     Status,
    IN  UINT            BytesTransferred
    );



INT
CLReceivePacket(
	IN	NDIS_HANDLE ProtocolBindingContext,
	IN	PNDIS_PACKET MPPacket
	)

/*++

Routine Description:

    Called by the NIC to indicate a data as an NDIS_PACKET. Make a copy of the
    packet struct and continue the packet along its way

Arguments:

    See the DDK...

Return Values:

    None

--*/

{
    PADAPTER Adapter = (PADAPTER)ProtocolBindingContext;
    NDIS_STATUS Status;
    NDIS_STATUS OurPacketStatus;
    PSINGLE_LIST_ENTRY PacketEntry = NULL;
    PIM_PACKET_CONTEXT ContextArea;
    PNDIS_PACKET OurPacket;
    PNDIS_BUFFER FirstBuffer;
    PVOID MediaSpecificInfo;
    UINT SizeOfMediaSpecificInfo;
    BOOLEAN KeepPacket;
    PNDIS_PACKET_OOB_DATA OurOOBData;
    PNDIS_PACKET_OOB_DATA MPOOBData;
    INT ReturnedRefCount;

    IMStructAssert( Adapter );

    //
    // return this packet now if we're not in the running state
    //

    NdisAcquireSpinLock( &Adapter->Lock );

    if ( Adapter->IMMPState & ADAPTER_STATE_RUNNING ) {

        Status = NDIS_STATUS_SUCCESS;
        ImDbgOut( DBG_TRACE, DBG_REFCNTS, ("(%08X) +Adapter:\n", Adapter));
    } else {

        Status = NDIS_STATUS_FAILURE;
    }

    NdisReleaseSpinLock( &Adapter->Lock );

    if ( !NT_SUCCESS( Status )) {
        return 0;
    }

    //
    // now get a packet entry off our S List
    //

    PacketEntry = NdisInterlockedPopEntrySList( &Adapter->PacketSList, &Adapter->PacketSListLock );

    if ( PacketEntry == NULL ) {

        //
        // out of resources. indicate that we're not hanging onto the packet
        //

        ImDbgOut( DBG_FAILURE, DBG_RECEIVE, ("CLReceivePacket: Out Of IM Packets!!!\n" ));

        DerefAdapter( Adapter );
        InterlockedIncrement( &Adapter->Stats.OutOfPackets );
        return 0;
    }

    //
    // got a free packet. If it's the last one, set the packet status such that
    // NDIS will know we're running short of resources. Initialize our context
    // area, chain the buffers from the miniport's packet and copy OOB and
    // other junk like packet flags
    //

    OurPacket = CONTAINING_RECORD( PacketEntry, NDIS_PACKET, ProtocolReserved );

    IMAssert( OurPacket->Private.Head == NULL );

      if ( NdisQueryDepthSList( &Adapter->PacketSList ) == 0 ) {

        OurPacketStatus = NDIS_STATUS_RESOURCES;
    } else {
        OurPacketStatus = NDIS_STATUS_SUCCESS;
    }

    NDIS_SET_PACKET_STATUS( OurPacket, OurPacketStatus );

    ContextArea = IM_PACKET_CONTEXT_FROM_PACKET( Adapter, OurPacket );
    IMStructAssert1( ContextArea, PacketContext );

    ContextArea->OriginalPacket = MPPacket;

    ImDbgOut(DBG_INFO, DBG_RECEIVE,
             ("(%08X) CLReceivePacket: IM Packet %08X MP Packet %08X\n",
              Adapter, OurPacket, MPPacket));

    NdisQueryPacket( MPPacket, NULL, NULL, &FirstBuffer, NULL );
    NdisChainBufferAtFront( OurPacket, FirstBuffer );

    NdisSetPacketFlags( OurPacket, NdisGetPacketFlags( MPPacket ));

    MPOOBData = NDIS_OOB_DATA_FROM_PACKET( MPPacket );
    OurOOBData = NDIS_OOB_DATA_FROM_PACKET( OurPacket );
    NdisMoveMemory( OurOOBData, MPOOBData, sizeof( NDIS_PACKET_OOB_DATA ));

    //
    // set the packet array to point to our packet and indicate it up
    //

    NdisMIndicateReceivePacket( Adapter->IMNdisHandle, &OurPacket, 1 );

    //
    // now check the packet's status to see if we can return it
    //

    Status = NDIS_GET_PACKET_STATUS( OurPacket );

    if ( Status != NDIS_STATUS_PENDING ) {

        ImDbgOut(DBG_INFO, DBG_RECEIVE,
                 ("(%08X) CLReceivePacket: Returning MP Packet %08X\n", Adapter, MPPacket));

        //
        // if upper layer is done with then so are we. put our packet back on
        // the SList, release the ref we took out, and return indicating we're
        // done with the MP packet
        //

        NdisReinitializePacket( OurPacket );

        NdisInterlockedPushEntrySList(&Adapter->PacketSList,
                                      (PSINGLE_LIST_ENTRY)OurPacket->ProtocolReserved,
                                      &Adapter->PacketSListLock);

        DerefAdapter( Adapter );

        ReturnedRefCount = 0;
    } else {

        ReturnedRefCount = 1;       // up the ref count on the packet
    }

    return ReturnedRefCount;
}                           // CLReceivePacket


VOID
MPReturnPacket(
	IN	NDIS_HANDLE				MiniportAdapterContext,
	IN	PNDIS_PACKET			Packet
	)

/*++

Routine Description:

     Potentially return a packet we indicated previously to the underlying miniport.
     It might be one of ours from a ProtocolReceive indication, so we disassemble it
     and return the packet and its buffers to their respective S Lists

Arguments:

    See the DDK...

Return Values:

    None

--*/

{
    PADAPTER Adapter = (PADAPTER)MiniportAdapterContext;
    PIM_PACKET_CONTEXT PktContext;
    PNDIS_PACKET MPPacket;
    PNDIS_BUFFER NdisBuffer;
    PIM_BUFFER_CONTEXT BufContext;
    UINT Length;
    PUCHAR MediaArea;
    UINT Size;

    IMStructAssert( Adapter );

    //
    // see if the OriginalPacket field indicates that this belongs to someone below
    // us and return it now
    //

    PktContext = IM_PACKET_CONTEXT_FROM_PACKET( Adapter, Packet );
    IMStructAssert1( PktContext, PacketContext );

    MPPacket = PktContext->OriginalPacket;

    ImDbgOut(DBG_INFO, DBG_RECEIVE,
             ("(%08X) MPReturnPacket: IM Packet %08X\n",
              Adapter, Packet));

    if ( MPPacket ) {

    	ImDbgOut(DBG_INFO, DBG_RECEIVE,
             ("(%08X) MPReturnPacket: Returning MP Packet %08X\n",
              Adapter, Packet));

        NdisReturnPackets( &MPPacket, 1 );

    } else {

        //
        // if a media specific area was allocated, free it now
        //

        NDIS_GET_PACKET_MEDIA_SPECIFIC_INFO( Packet, &MediaArea, &Size );

        if ( MediaArea ) {

            IMFreePool( MediaArea );
        }

        //
        // return the buffers back to the appropriate S Lists. First one may be
        // from the lookahead or the residual pool followed by an optional residual.
        // In each case, we set the buffer context area to point back to our NDIS
        // buffer so we can find it when this entry is popped off the list.
        //

        NdisUnchainBufferAtFront( Packet, &NdisBuffer );

        IMAssert( NdisBuffer != NULL );

        NdisQueryBuffer( NdisBuffer, &BufContext, &Length );
        BufContext->NdisBuffer = NdisBuffer;

        if ( Length > Adapter->LookaheadBufferSize ) {

            NdisInterlockedPushEntrySList(&Adapter->ResidualSList,
                                          &BufContext->SListEntry,
                                          &Adapter->ResidualSListLock);

            IMAssert( ConfigData.ResidualPoolSize <= NdisQueryDepthSList( &Adapter->ResidualSList ));
        } else {
            NdisInterlockedPushEntrySList(&Adapter->LookaheadSList,
                                          &BufContext->SListEntry,
                                          &Adapter->LookaheadSListLock);

            IMAssert( NdisQueryDepthSList( &Adapter->LookaheadSList ) <= ConfigData.LookaheadPoolSize );
        }

        NdisUnchainBufferAtFront( Packet, &NdisBuffer );

        if ( NdisBuffer ) {

            NdisQueryBuffer( NdisBuffer, &BufContext, &Length );
            BufContext->NdisBuffer = NdisBuffer;

            NdisInterlockedPushEntrySList(&Adapter->ResidualSList,
                                          &BufContext->SListEntry,
                                          &Adapter->ResidualSListLock);

            IMAssert( NdisQueryDepthSList( &Adapter->ResidualSList ) <= ConfigData.ResidualPoolSize );
        }
    }

    //
    // re-init the packet and push it back on its S List. Release the ref we took out
    // in ClReceivePacket
    //

    NdisReinitializePacket( Packet );
    NdisInterlockedPushEntrySList(&Adapter->PacketSList,
                                  (PSINGLE_LIST_ENTRY)Packet->ProtocolReserved,
                                  &Adapter->PacketSListLock);
    DerefAdapter( Adapter );

} // MPReturnPacket


NDIS_STATUS
CLReceiveIndication(
	IN	NDIS_HANDLE				ProtocolBindingContext,
	IN	NDIS_HANDLE				MacReceiveContext,
	IN	PVOID					HeaderBuffer,
	IN	UINT					HeaderBufferSize,
	IN	PVOID					LookaheadBuffer,
	IN	UINT					LookaheadBufferSize,
	IN	UINT					PacketSize
	)

/*++

 Routine Description:

    Called by NIC to notify protocol of incoming data. Copy the data into a cached
    packet we set up during initialization and indicate that packet to the higher
    layer

Arguments:

    See the DDK...

Return Values:

    None

--*/

{
    PADAPTER Adapter = (PADAPTER)ProtocolBindingContext;
    PSLIST_HEADER SList;
    PNDIS_SPIN_LOCK SListLock;
    PSINGLE_LIST_ENTRY PacketEntry;
    PSINGLE_LIST_ENTRY LookaheadEntry;
    PSINGLE_LIST_ENTRY ResidualEntry = NULL;
    PIM_PACKET_CONTEXT PktContext;
    PNDIS_BUFFER LookaheadNdisBuffer;
    PNDIS_BUFFER ResidualNdisBuffer;
    PNDIS_PACKET OurPacket;
    NDIS_STATUS Status;

⌨️ 快捷键说明

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