📄 recv.c
字号:
/*++
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 + -