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
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);
|
|
}
|
|
|