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

📄 send.c

📁 ndis windows网络驱动程序的范例
💻 C
字号:
/*++

Copyright (c) 1996  Microsoft Corporation

Module Name:

    send.c

Abstract:

    routines for sending packets

Author:

    Jim Mateer

Environment:

    Kernel Mode

Revision History:

--*/

#include "ImSamp.h"
#pragma hdrstop


//
// the number of packets the send routines can remember in their stack
// based packet array. If more packets are presented, then memory
// is dynamically allocated
//

#define MAX_LOCAL_PACKET_ARRAY  10

VOID
MPSendPackets(
    IN  NDIS_HANDLE MiniportAdapterContext,
    IN  PPNDIS_PACKET PacketArray,
    IN  UINT NumberOfPackets
    );


VOID
CLSendComplete(
    IN  NDIS_HANDLE ProtocolBindingContext,
    IN  PNDIS_PACKET Packet,
    IN  NDIS_STATUS Status
    );

VOID
PacketCompletion(
    IN PADAPTER Adapter,
    IN PNDIS_PACKET Packet,
    IN NDIS_STATUS Status
   );



VOID
MPSendPackets(
    IN  NDIS_HANDLE             MiniportAdapterContext,
    IN  PPNDIS_PACKET           PacketArray,
    IN  UINT                    NumberOfPackets
    )

/*++

Routine Description:

    Received a xmit request from a Transport. Copy the packets into our own buffers, and then send them
    it on to the lower Miniports, via NdisSendPackets
Arguments:

    See the DDK...

Return Values:

    None

--*/

{
    PADAPTER Adapter = (PADAPTER)MiniportAdapterContext;
    NDIS_STATUS Status;
    PNDIS_PACKET Packet,
    			 XportPacket,
    			 OurPacket,
    			 OurPacketArray[ MAX_LOCAL_PACKET_ARRAY ];
    PSINGLE_LIST_ENTRY PacketEntry = NULL;
    PIM_PACKET_CONTEXT PktContext;
    PNDIS_BUFFER FirstXportBuffer;
    PNDIS_PACKET_OOB_DATA OurOOBData;
    PNDIS_PACKET_OOB_DATA XportOOBData;
    PMEDIA_SPECIFIC_INFORMATION OurMediaArea;
    ULONG PacketLength,
          PacketsToSend = 0,
          i;
   LARGE_INTEGER TotalPacketLength;        // need Large int for ExInterlockedAddLargeInteger

   

    ImDbgOut(DBG_INFO, DBG_SEND, ("(%08X) MPSendPackets: %d XPORT packets\n",
                                  Adapter, NumberOfPackets));

    IMStructAssert( Adapter );



    //
    // if adapter is going away, then fail this request and return
    //

    NdisAcquireSpinLock( &Adapter->Lock );

    if ( Adapter->IMMPState & ADAPTER_STATE_RUNNING ) {

          ImDbgOut( DBG_TRACE, DBG_REFCNTS, ("MPSendPackets: (%08X) Adapter:  Packets to send = 0x2d\n", Adapter, NumberOfPackets));

        Status = NDIS_STATUS_SUCCESS;
    } else {

        Status = NDIS_STATUS_FAILURE;
    }

    NdisReleaseSpinLock( &Adapter->Lock );




	// If we can't process this send, set the status in the packets	and return
    if ( !NT_SUCCESS( Status )) {

        while ( NumberOfPackets-- ) {

            Packet = *PacketArray++;
            NDIS_SET_PACKET_STATUS( Packet, Status );
        }

        ImDbgOut(DBG_FAILURE, DBG_SEND,
                 ("(%08X) MPSendPackets: couldn't send - adapter shutting down\n",
                  Adapter));
        return;
    }



    // Copy the packets into our own buffers 
  	//
    // pop a new packet structure from the list and chain the buffers on it.
    // remember the old packet and place a pointer to the new packet in the
    // local packet array
    //

	 //**********************************************************************************************
    // If you wanted to do any processing, or analysis of the packets before sending them, this would
	// be a good place to add the code.
	//  At this point, we have possesion of the packets sent down by a transport.
	//*********************************************************************************************

    for ( i = 0; i < NumberOfPackets; ++i ) {	   // process the whole array of packets

        XportPacket = PacketArray[ i ];			   // pointer to the packet we are working on

        PacketEntry = NdisInterlockedPopEntrySList(&Adapter->PacketSList,	 // pop a free packet off of our private packet pool
                                                   &Adapter->PacketSListLock);

        if ( PacketEntry == NULL ) {	  // oops, we didn't have any free packets in our pool

            //
            // out of packet space. set the original packet's
            // status so NDIS will queue it and try again later on
            //

            NDIS_SET_PACKET_STATUS( XportPacket, NDIS_STATUS_RESOURCES ); // set the status for the wrapper
            InterlockedIncrement( &Adapter->Stats.OutOfPackets );		 // bump our out of packets counter
            continue;													 // move on to the next packet in the array
        }
		else { // else we got a Packet from our pool

        	OurPacket = CONTAINING_RECORD( PacketEntry, NDIS_PACKET, ProtocolReserved ); //OurPacket = ProtocolReserved of PacketEntry
        	PktContext = IM_PACKET_CONTEXT_FROM_PACKET( Adapter, OurPacket );

        	IMStructAssert1( PktContext, PacketContext );
        	IMAssert( OurPacket->Private.Head == NULL );

        	//
        	// Initialize our context area, chain the buffers from the
        	// upper layer packet and other junk like packet flags
       		 //
			

			// read the xport's packet
        	NdisQueryPacket( XportPacket, NULL, NULL, &FirstXportBuffer, &PacketLength );

			// copy the buffers to our packet. We have to do this copy because the wrapper uses some of the fields
			// in the NDIS_PACKET structure. If we simply sent the packet down, these fields would get overwritten,
			// and we couldn't copmlete the packet  to the transport, when it was completed to us.
        	NdisChainBufferAtFront( OurPacket, FirstXportBuffer );

			// copy any packet flags over, see the DDK
        	NdisSetPacketFlags( OurPacket, NdisGetPacketFlags( XportPacket ));

        	// Copy the Out of Band data, if any
        	XportOOBData = NDIS_OOB_DATA_FROM_PACKET( XportPacket );
        	OurOOBData = NDIS_OOB_DATA_FROM_PACKET( OurPacket );
        	NdisMoveMemory( OurOOBData, XportOOBData, sizeof( NDIS_PACKET_OOB_DATA ));


        	//
        	// set the original packet's status so NDIS won't complete it
        	//

        	NDIS_SET_PACKET_STATUS( XportPacket, NDIS_STATUS_PENDING );
       		//
        	// update our context area so we know what to do with it
        	// when its completed
        	//

        	PktContext->OriginalPacket = XportPacket;

           //
          // add to the array of packets we're going to send out immediately.
          //

        	OurPacketArray[ PacketsToSend++ ] = OurPacket;

        	TotalPacketLength.LowPart += PacketLength;
	   }  // end else if we got a free packet from the pool

    } //end for(Number of packets in the array)
    
    // BUGBUG some of the packets may have been marked pending, and some may have been marked
	// STATUS_RESOURCES. We should be sending only the ones we had free packets for, and the others
	// (the ones we didn't have resources for, should be returned immeadiatly. Make sure this works. 
       //
       // send what ever we have to send now
       //
	
       if ( PacketsToSend > 0 ) {
        
        //
        // send whatever we had resources for
        //

        ImDbgOut(DBG_INFO, DBG_SEND, ("(%08X) MPSendPackets: %d IM    packets @ ",
                                      Adapter, PacketsToSend));

        for ( i = 0; i < PacketsToSend; ++i ) {
            ImDbgOutNoID(DBG_INFO, DBG_SEND, ("%08X, ", OurPacketArray[i]));
        }
        ImDbgOutNoID(DBG_INFO, DBG_SEND, ("\n"));

        NdisSendPackets( Adapter->LowerMPHandle, &OurPacketArray[0], PacketsToSend );
	   }
} // MPSendPackets





VOID
CLSendComplete(
    IN  NDIS_HANDLE             ProtocolBindingContext,
    IN  PNDIS_PACKET            Packet,
    IN  NDIS_STATUS             Status
    )

/*++

Routine Description:

    Completion routine for NdisSendPackets. Most of the work is done elsewhere.
    We only want to check on Transmit when Idle packets during a real send
    completion.

Arguments:

    See the DDK...
											
Return Values:

    None

--*/

{
    PADAPTER Adapter = (PADAPTER)ProtocolBindingContext;
    PIM_PACKET_CONTEXT PktContext;
    



    IMStructAssert( Adapter );

    //
    // do the cleanup thing and check for any transmit when idle packets
    //


    //
    // complete the original packet back to the higher layer
    //

	// get the origional packet, passed down from the transport
    PktContext = IM_PACKET_CONTEXT_FROM_PACKET( Adapter, Packet );

   // we're done with our copy of the packet, so recycle the resources
    PacketCompletion( Adapter, Packet, Status );

   // and complete the orig. packet
    NdisMSendComplete( Adapter->IMNdisHandle, PktContext->OriginalPacket, Status );


} // CLSendComplete


VOID
PacketCompletion(
    IN PADAPTER Adapter,
    IN PNDIS_PACKET Packet,
    IN NDIS_STATUS Status
    )

/*++

Routine Description:


Arguments:

    See the DDK...

Return Values:

    None

--*/

{
    //
    // Reinit the packet struct and
    // push it back on the adapter's packet SList.     

    ImDbgOut(DBG_INFO, DBG_SEND,
             ("(%08X) PacketCompletion: IM Packet %08X, Status: %08X\n",
              Adapter, Packet, Status));
    
   
	// BUGBUG do I have to unchain and free the buffers before I call this?
    NdisReinitializePacket( Packet );

    
    // save the resources in our packet pool
    NdisInterlockedPushEntrySList(&Adapter->PacketSList,
                                  (PSINGLE_LIST_ENTRY)Packet->ProtocolReserved,
                                  &Adapter->PacketSListLock);


} // PacketCompletion

/* end send.c */

⌨️ 快捷键说明

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