Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

247 lines
9.5 KiB

/*
ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ
(C) Copyright 1998
All rights reserved.
ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ
Portions of this software are:
(C) Copyright 1995, 1999 TriplePoint, Inc. -- http://www.TriplePoint.com
License to use this software is granted under the terms outlined in
the TriplePoint Software Services Agreement.
(C) Copyright 1992 Microsoft Corp. -- http://www.Microsoft.com
License to use this software is granted under the terms outlined in
the Microsoft Windows Device Driver Development Kit.
ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ
@doc INTERNAL Receive Receive_c
@module Receive.c |
This module implements the Miniport packet receive routines. Basically,
the asynchronous receive processing routine. This module is very
dependent on the hardware/firmware interface and should be looked at
whenever changes to these interfaces occur.
@head3 Contents |
@index class,mfunc,func,msg,mdata,struct,enum | Receive_c
@end
ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ
*/
/* @doc EXTERNAL INTERNAL
ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ
@topic 3.4 Receiving Packets General |
A WAN miniport calls NdisMWanIndicateReceive to indicate that a
packet has arrived and that the entire packet (there is no lookahead)
is available for inspection. When this call is made, NDISWAN indicates
the arrival of the packet to the ProtocolReceive handlers of bound
higher-level drivers.
<f Note>: Since the entire packet is always passed up, the miniport driver will
never receive a transfer-data call (the data is copied by NDISWAN and
then passed up to the next higher driver). The entire packet is always
passed up due to compression and encryption that might have been applied
to the packet. Also, because the link is point-to-point, at least one
bound protocol will always want to look at the packet.
The data contained in the header is the same as that received on the
NIC. The NIC driver will not remove any headers or trailers from the
data it receives. The transmitting driver cannot add padding to the
packet.
A WAN miniport calls NdisMWanIndicateReceiveComplete to indicate the
end of one or more receive indications so that protocols can postprocess
received packets. As a result, NDISWAN calls the ProtocolReceiveComplete
handler(s) of bound protocols to notifying each protocol that it can
now process the received data. In its receive-complete handler, a
protocol need not operate under the severe time constraints that it
does in its receive handler.
The protocol should assume that interrupts are enabled during the
call to ProtocolReceiveComplete. In an SMP machine, the receive
handler and the receive complete handler can be running concurrently
on different processors.
Note that a WAN driver need not deliver NdisMWanIndicateReceiveComplete
indications in one-to-one correspondence with NdisMWanIndicateReceive
indications. It can issue a single receive-complete indication
after several receive indications have occurred. For example, a
WAN miniport could call NdisMWanIndicateReceiveComplete from its
receive handler every ten packets or before exiting the handler,
whichever occurs first.
@topic 3.5 Receiving Packets Specific |
Packets are recevied asynchronously by the Miniport from the driver's
BChannel services as a stream of raw HDLC frames. See the Sending
Packets section for details on the frame format.
When a call is connected, the Miniport pre-loads the driver receive queue
with the number of buffers defined by the registry parameter
<p ReceiveBuffersPerLink>.
When the driver has read an HDLC frame from the associated BChannel, it calls
the Miniport routine <f BChannelEventHandler> with <t BREASON_RECEIVE_DONE>.
The Miniport then calls <f CardNotifyReceive> which de-queues the buffer
from the link's <p ReceivePendingList> and places it on the adapter's
<p ReceiveCompleteList>. <f CardNotifyReceive> then schedules the routine
<f MiniportTimer> to be called as soon as it is safe to process the
event (i.e. the Miniport can be re-entered).
When <f MiniportTimer> runs, it calls <f ReceivePacketHandler> to
process ALL the packets on the <p ReceiveCompleteList>. Each packet is
dequeued and passed up to <f NdisMWanIndicateReceive>. After the packet
is copied by the WAN wrapper, the buffer is then reset and posted back to
the driver so it can be used to receive another frame.
After all packets have been processed by the <f ReceivePacketHandler>,
before leaving <f MiniportTimer>, <f NdisMWanIndicateReceiveComplete>
is called so the WAN wrapper can do its post-processing.
@end
*/
#define __FILEID__ RECEIVE_OBJECT_TYPE
// Unique file ID for error logging
#include "Miniport.h" // Defines all the miniport objects
#if defined(NDIS_LCODE)
# pragma NDIS_LCODE // Windows 95 wants this code locked down!
# pragma NDIS_LDATA
#endif
/* @doc INTERNAL Receive Receive_c ReceivePacketHandler
ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ
@func
<f ReceivePacketHandler> is called from <f MiniportTimer> to handle
a packet receive event. We enter here with interrupts enabled on
the adapter and the processor, but the NDIS Wrapper holds a spin lock
since we are executing on an NDIS timer thread.
@comm
We loop in here until all the available incoming packets have been passed
up to the protocol stack. As we find each good packet, it is passed up
to the protocol stack using <f NdisMWanIndicateReceive>. When NDIS
returns control from this call, we resubmit the packet to the adapter
so it can be used to receive another incoming packet. The link flag
<p NeedReceiveCompleteIndication> is set TRUE if any packets are received
on a particular link. This is used later, before returning from the
async event handler, to notify NDIS of any ReceiveCompleteIndications.
*/
void ReceivePacketHandler(
IN PBCHANNEL_OBJECT pBChannel, // @parm
// A Pointer to one of our <t BCHANNEL_OBJECT>'s.
IN PUCHAR ReceiveBuffer, // @parm
// Pointer to first byte received.
IN ULONG BytesReceived // @parm
// Number of bytes received.
)
{
DBG_FUNC("ReceivePacketHandler")
NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
PMINIPORT_ADAPTER_OBJECT pAdapter;
// A pointer to the <t MINIPORT_ADAPTER_OBJECT> instance.
ASSERT(pBChannel && pBChannel->ObjectType == BCHANNEL_OBJECT_TYPE);
pAdapter = GET_ADAPTER_FROM_BCHANNEL(pBChannel);
DBG_ENTER(pAdapter);
/*
// I find it useful to do this nest check, just so I can make sure
// I handle it correctly when it happens.
*/
if (++(pAdapter->NestedDataHandler) > 1)
{
DBG_ERROR(pAdapter,("NestedDataHandler=%d > 1\n",
pAdapter->NestedDataHandler));
}
/*
// Is there someone up there who cares?
*/
if (pBChannel->NdisLinkContext == NULL)
{
DBG_WARNING(pAdapter, ("Packet recvd on disconnected line #%d\n",pBChannel->BChannelIndex));
}
#ifdef NDISWAN_BUG // NDISWAN is sometimes setting this to zero - ignore it!
/*
// Return if we were told to expect nothing.
*/
else if (pBChannel->WanLinkInfo.MaxRecvFrameSize == 0)
{
DBG_WARNING(pAdapter,("Packet size=%d > %d\n",
BytesReceived, pBChannel->WanLinkInfo.MaxRecvFrameSize));
}
#endif // NDISWAN_BUG
else
{
pAdapter->TotalRxBytes += BytesReceived;
pAdapter->TotalRxPackets++;
/*
// We have to accept the frame if possible, I just want to know
// if somebody has lied to us...
*/
if (BytesReceived > pBChannel->WanLinkInfo.MaxRecvFrameSize)
{
DBG_NOTICE(pAdapter,("Packet size=%d > %d\n",
BytesReceived, pBChannel->WanLinkInfo.MaxRecvFrameSize));
}
DBG_RX(pAdapter, pBChannel->BChannelIndex,
BytesReceived, ReceiveBuffer);
/*
// Indiciate the packet up to the protocol stack.
*/
NdisMWanIndicateReceive(
&Status,
pAdapter->MiniportAdapterHandle,
pBChannel->NdisLinkContext,
ReceiveBuffer,
BytesReceived
);
if (Status == NDIS_STATUS_SUCCESS)
{
pBChannel->NeedReceiveCompleteIndication = TRUE;
}
else
{
DBG_WARNING(pAdapter,("NdisMWanIndicateReceive returned error 0x%X\n",
Status));
}
}
/*
// I find it useful to do this nest check, just so I can make sure
// I handle it correctly when it happens.
*/
if (--(pAdapter->NestedDataHandler) < 0)
{
DBG_ERROR(pAdapter,("NestedDataHandler=%d < 0\n",
pAdapter->NestedDataHandler));
}
DBG_LEAVE(pAdapter);
}