📄 send.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 + -