|
|
/*++
Copyright (c) 1996-1999 Microsoft Corporation
Module Name:
recv.c
Abstract:
routines to handle receiving data
Author:
Charlie Wickham (charlwi) 08-May-1996 Rajesh Sundaram (rajeshsu) 01-Aug-1998.
Environment:
Kernel Mode
Revision History:
--*/
#include "psched.h"
#pragma hdrstop
/* External */
/* Static */
/* Forward */ /* Generated by Emacs 19.17.0 on Thu May 09 10:34:39 1996 */
INT ClReceivePacket( IN NDIS_HANDLE ProtocolBindingContext, IN PNDIS_PACKET Packet );
VOID MpReturnPacket( IN NDIS_HANDLE MiniportAdapterContext, IN PNDIS_PACKET Packet );
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 );
/* End Forward */
VOID PsAllocateRecvPacket(PNDIS_STATUS Status, PPNDIS_PACKET Packet, PADAPTER Adapter) {
if(!Adapter->RecvPacketPool) { PS_LOCK_DPC(&Adapter->Lock);
if(!Adapter->RecvPacketPool) { NDIS_HANDLE PoolHandle = (void *) NDIS_PACKET_POOL_TAG_FOR_PSCHED;
NdisAllocatePacketPoolEx(Status, &PoolHandle, MIN_PACKET_POOL_SIZE, MAX_PACKET_POOL_SIZE, sizeof(PS_RECV_PACKET_CONTEXT));
if(*Status != NDIS_STATUS_SUCCESS) { Adapter->Stats.OutOfPackets ++; PS_UNLOCK_DPC(&Adapter->Lock);
return; }
//
// We successfully allocated a packet pool. We can now free the Fixed Size Block pool for the packet-stack API
//
Adapter->RecvPacketPool = PoolHandle;
}
PS_UNLOCK_DPC(&Adapter->Lock); }
NdisDprAllocatePacket(Status, Packet, Adapter->RecvPacketPool); }
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, switch to miniport mode and continue the packet along its way
Arguments:
See the DDK...
Return Values:
None
--*/
{ PADAPTER Adapter = (PADAPTER)ProtocolBindingContext; NDIS_STATUS Status; PPS_RECV_PACKET_CONTEXT ContextArea; PNDIS_PACKET OurPacket; BOOLEAN Remaining;
PsStructAssert( Adapter );
if(!Adapter->PsNdisHandle) { return 0; }
if(Adapter->MediaType == NdisMediumWan && Adapter->ProtocolType == ARP_ETYPE_IP) { //
// Munge s-mac and d-mac so that wanarp is happy.
//
PNDIS_BUFFER pNdisBuf; UINT Len; PETH_HEADER pAddr; PUSHORT id; PPS_WAN_LINK WanLink; pNdisBuf = MpPacket->Private.Head; NdisQueryBuffer(pNdisBuf, &pAddr, &Len); if(Len < sizeof(ETH_HEADER)) { return NDIS_STATUS_FAILURE; }
id = (PUSHORT)&pAddr->DestAddr[0];
PS_LOCK(&Adapter->Lock);
if((WanLink = (PPS_WAN_LINK)g_WanLinkTable[*id]) == 0) { PS_UNLOCK(&Adapter->Lock); return NDIS_STATUS_FAILURE; }
if(WanLink->State != WanStateOpen) { PS_UNLOCK(&Adapter->Lock); return NDIS_STATUS_FAILURE; }
NdisMoveMemory(pAddr, &WanLink->RecvHeader, FIELD_OFFSET(ETH_HEADER, Type));
PS_UNLOCK(&Adapter->Lock); }
NdisIMGetCurrentPacketStack(MpPacket, &Remaining);
if(Remaining != 0) { Status = NDIS_GET_PACKET_STATUS(MpPacket);
if (TimeStmpRecvPacket) { if (!(TimeStmpRecvPacket)( NULL, NULL, NULL, MpPacket, Adapter->MediaType )) { PsDbgRecv(DBG_FAILURE, DBG_RECEIVE, CL_RECV_PACKET, OURS, Adapter, MpPacket, 0); } } NdisMIndicateReceivePacket(Adapter->PsNdisHandle, &MpPacket, 1);
return((Status != NDIS_STATUS_RESOURCES) ? 1 : 0); } else {
PsAllocateRecvPacket(&Status, &OurPacket, Adapter);
if(Status == NDIS_STATUS_SUCCESS) { PsDbgRecv(DBG_INFO, DBG_RECEIVE, CL_RECV_PACKET, ENTER, Adapter, OurPacket, MpPacket); //
// Save Original Packet
//
ContextArea = PS_RECV_PACKET_CONTEXT_FROM_PACKET(OurPacket); ContextArea->OriginalPacket = MpPacket; OurPacket->Private.Head = MpPacket->Private.Head; OurPacket->Private.Tail = MpPacket->Private.Tail; //
// Get the original packet (it could be the same packet as one received or a different one
// based on # of layered MPs) and set it on the indicated packet so the OOB stuff is visible
// correctly at the top.
//
NDIS_SET_ORIGINAL_PACKET(OurPacket, NDIS_GET_ORIGINAL_PACKET(MpPacket)); NDIS_SET_PACKET_HEADER_SIZE(OurPacket, NDIS_GET_PACKET_HEADER_SIZE(MpPacket)); //
// Set Packet Flags
//
NdisGetPacketFlags(OurPacket) = NdisGetPacketFlags(MpPacket); Status = NDIS_GET_PACKET_STATUS(MpPacket); NDIS_SET_PACKET_STATUS(OurPacket, Status); if (TimeStmpRecvPacket) { if (!(TimeStmpRecvPacket)( NULL, NULL, NULL, OurPacket, Adapter->MediaType )) { PsDbgRecv(DBG_FAILURE, DBG_RECEIVE, CL_RECV_PACKET, OURS, Adapter, OurPacket, OurPacket); } }
NdisMIndicateReceivePacket(Adapter->PsNdisHandle, &OurPacket, 1);
if (Status == NDIS_STATUS_RESOURCES) { NdisDprFreePacket(OurPacket); } return((Status != NDIS_STATUS_RESOURCES) ? 1 : 0); } else { //
// out of resources. indicate that we're not hanging onto the packet
//
PsDbgRecv(DBG_FAILURE, DBG_RECEIVE, CL_RECV_PACKET, NO_RESOURCES, Adapter, 0, MpPacket); Adapter->Stats.OutOfPackets ++; return 0; } }
} // 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; PPS_RECV_PACKET_CONTEXT PktContext; PNDIS_PACKET MyPacket; BOOLEAN Remaining;
PsStructAssert(Adapter);
NdisIMGetCurrentPacketStack(Packet, &Remaining);
if(Remaining != 0) { NdisReturnPackets(&Packet, 1); } else {
//
// see if the OriginalPacket field indicates that this belongs
// to someone below us and return it now
//
PktContext = PS_RECV_PACKET_CONTEXT_FROM_PACKET(Packet);
MyPacket = PktContext->OriginalPacket;
PsDbgRecv(DBG_INFO, DBG_RECEIVE, MP_RETURN_PACKET, RETURNING, Adapter, Packet, MyPacket);
NdisDprFreePacket(Packet);
NdisReturnPackets(&MyPacket, 1); }
} // 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; PNDIS_PACKET MyPacket, Packet; NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
PsStructAssert(Adapter);
if(!Adapter->PsNdisHandle) { Status = NDIS_STATUS_FAILURE; } else { do { //
// If this was indicated by the miniport below as a packet, then get that packet
// pointer and indicate it as a packet as well (with appropriate status).
// This way the OOB stuff is accessible to the transport above us.
//
Packet = NdisGetReceivedPacket(Adapter->LowerMpHandle, MacReceiveContext);
if (Packet != NULL) { BOOLEAN Remaining;
//
// Check if there are any more packet stacks left. If there is need to keep per packet information,
// then the packet stack (which is returned by the api) can be used to store that
//
NdisIMGetCurrentPacketStack(Packet, &Remaining); if (Remaining != 0) { NDIS_STATUS OldPacketStatus; if (TimeStmpRecvPacket) {
if (!(TimeStmpRecvPacket)( NULL, NULL, NULL, Packet, Adapter->MediaType )) {
PsDbgRecv(DBG_FAILURE, DBG_RECEIVE, CL_RECV_IND, OURS, Adapter, Packet, Packet); }
}
//
// Save the old status, and set packet status to NDIS_STATUS_RESOURCES
// because we can't have the protocol above us retain the packet -- it
// can go away as soon as we return from this function.
//
OldPacketStatus = NDIS_GET_PACKET_STATUS(Packet); NDIS_SET_PACKET_STATUS(Packet, NDIS_STATUS_RESOURCES);
NdisMIndicateReceivePacket(Adapter->PsNdisHandle, &Packet, 1);
//
// Restore the old Status
//
NDIS_SET_PACKET_STATUS(Packet, OldPacketStatus);
// Since we had set the packet status to NDIS_STATUS_RESOURCES, our
// ReturnPacket handler won't be called for this packet.
break; }
//
// Get a packet off the pool and indicate that up
//
PsAllocateRecvPacket(&Status, &MyPacket, Adapter);
if (Status == NDIS_STATUS_SUCCESS) { MyPacket->Private.Head = Packet->Private.Head; MyPacket->Private.Tail = Packet->Private.Tail; //
// Get the original packet (it could be the same packet as one received or
// a different one based on # of layered MPs) and set it on the indicated
// packet so the OOB stuff is visible correctly at the top.
//
NDIS_SET_ORIGINAL_PACKET(MyPacket, NDIS_GET_ORIGINAL_PACKET(Packet));
NDIS_SET_PACKET_HEADER_SIZE(MyPacket, HeaderBufferSize); //
// Set Packet Flags
//
NdisGetPacketFlags(MyPacket) = NdisGetPacketFlags(Packet); //
// Make sure the status is set to NDIS_STATUS_RESOURCES.
//
NDIS_SET_PACKET_STATUS(MyPacket, NDIS_STATUS_RESOURCES);
if (TimeStmpRecvPacket) {
if (!(TimeStmpRecvPacket)( NULL, NULL, NULL, MyPacket, Adapter->MediaType )) {
PsDbgRecv(DBG_FAILURE, DBG_RECEIVE, CL_RECV_IND, OURS, Adapter, MyPacket, MyPacket); }
}
NdisMIndicateReceivePacket(Adapter->PsNdisHandle, &MyPacket, 1); PsAssert (NDIS_GET_PACKET_STATUS(MyPacket) == NDIS_STATUS_RESOURCES);
NdisDprFreePacket(MyPacket);
break; } }
//
// Fall through if the miniport below us has either not indicated a packet or we
// could not allocate one
//
Adapter->IndicateRcvComplete = TRUE;
//
// If the timestamp driver is present.
//
//
if (TimeStmpRecvIndication) {
if (!(TimeStmpRecvIndication)( NULL, NULL, NULL, HeaderBuffer, HeaderBufferSize, LookAheadBuffer, LookAheadBufferSize, PacketSize, Adapter->IPHeaderOffset )) {
PsDbgRecv(DBG_FAILURE, DBG_RECEIVE, CL_RECV_IND, OURS, Adapter, (PNDIS_PACKET) LookAheadBuffer, NULL); }
}
switch (Adapter->MediaType) { case NdisMedium802_3: case NdisMediumWan:
NdisMEthIndicateReceive(Adapter->PsNdisHandle, MacReceiveContext, HeaderBuffer, HeaderBufferSize, LookAheadBuffer, LookAheadBufferSize, PacketSize); break;
case NdisMedium802_5: NdisMTrIndicateReceive(Adapter->PsNdisHandle, MacReceiveContext, HeaderBuffer, HeaderBufferSize, LookAheadBuffer, LookAheadBufferSize, PacketSize); break;
case NdisMediumFddi: NdisMFddiIndicateReceive(Adapter->PsNdisHandle, MacReceiveContext, HeaderBuffer, HeaderBufferSize, LookAheadBuffer, LookAheadBufferSize, PacketSize); break;
default: PsAssert (0); Status = NDIS_STATUS_FAILURE; break; }
} while (FALSE); }
return Status;
} // ClReceiveIndication
VOID ClReceiveComplete( IN NDIS_HANDLE ProtocolBindingContext )
/*++
Routine Description:
Called by NIC via NdisIndicateReceiveComplete. Continue this indication up to the higher layer
Arguments:
See the DDK...
Return Values:
None
--*/
{ PADAPTER Adapter = (PADAPTER)ProtocolBindingContext;
PsStructAssert(Adapter);
PsDbgRecv(DBG_INFO, DBG_RECEIVE, CL_RECV_COMPL, ENTER, Adapter, 0, 0);
if((Adapter->PsNdisHandle != NULL) && Adapter->IndicateRcvComplete) {
switch(Adapter->MediaType){
case NdisMediumWan: case NdisMedium802_3:
NdisMEthIndicateReceiveComplete(Adapter->PsNdisHandle); break;
case NdisMedium802_5:
NdisMTrIndicateReceiveComplete(Adapter->PsNdisHandle); break;
case NdisMediumFddi:
NdisMFddiIndicateReceiveComplete(Adapter->PsNdisHandle); break;
default:
PsAssert(FALSE); } } Adapter->IndicateRcvComplete = FALSE;
} // ClReceiveComplete
NDIS_STATUS MpTransferData( OUT PNDIS_PACKET Packet, OUT PUINT BytesTransferred, IN NDIS_HANDLE MiniportAdapterContext, IN NDIS_HANDLE MiniportReceiveContext, IN UINT ByteOffset, IN UINT BytesToTransfer )
/*++
Routine Description:
Arguments:
See the DDK...
Return Values:
None
--*/
{ PADAPTER Adapter = (PADAPTER)MiniportAdapterContext; NDIS_STATUS Status;
PsStructAssert(Adapter);
PsDbgRecv(DBG_INFO, DBG_RECEIVE, MP_XFER_DATA, ENTER, Adapter, 0, 0);
if(IsDeviceStateOn(Adapter) == FALSE) { return NDIS_STATUS_FAILURE; }
NdisTransferData( &Status, Adapter->LowerMpHandle, MiniportReceiveContext, ByteOffset, BytesToTransfer, Packet, BytesTransferred);
return Status;
} // MpTransferData
VOID ClTransferDataComplete( IN NDIS_HANDLE ProtocolBindingContext, IN PNDIS_PACKET Packet, IN NDIS_STATUS Status, IN UINT BytesTransferred )
/*++
Routine Description:
Completion routine for NdisTransferData
Arguments:
See the DDK...
Return Values:
None
--*/
{ PADAPTER Adapter = (PADAPTER)ProtocolBindingContext; PPS_RECV_PACKET_CONTEXT PktContext;
PsStructAssert(Adapter);
PsDbgRecv(DBG_INFO, DBG_RECEIVE, CL_XFER_COMPL, ENTER, Adapter, Packet, 0);
if(Adapter->PsNdisHandle) { NdisMTransferDataComplete( Adapter->PsNdisHandle, Packet, Status, BytesTransferred); }
} // ClTransferDataComplete
UINT ClCoReceivePacket( IN NDIS_HANDLE ProtocolBindingContext, IN NDIS_HANDLE ProtocolVcContext, IN PNDIS_PACKET Packet ) { //
// We don't do anything special in the coreceive path. Just call ClReceivePacket.
//
return ClReceivePacket(ProtocolBindingContext, Packet);
} // ClCoReceivePacket
/* end recv.c */
|