/*++

*******************************************************************************
* Copyright (c) 1994-95 Digi International Inc., All Rights Reserved          *
*                                                                             *
* This  software  contains  proprietary  and  confidential   information   of *
* Digi International  Inc.   By  accepting  transfer  of this copy, Recipient *
* agrees to retain this software in  confidence,  to  prevent  disclosure  to *
* others,  and  to make no  use of this software other than that for which it *
* was delivered.  This is an unpublished copyright work  Digi   International *
* Inc.    Except   as   permitted   by  federal  law,  17 USC 117, copying is *
* strictly prohibited.                                                        *
*                                                                             *
* Digi  International  Inc.  CONFIDENTIAL  -   (Digi    International    Inc. *
* Confidential  when   combined   with   the   aggregated  modules  for  this *
* product) OBJECT CODE ONLY SOURCE MATERIALS                                  *
*                                                                             *
* (C) COPYRIGHT Digi International Inc. 1994-95                               *
*                                                                             *
* All Rights Reserved                                                         *
*                                                                             *
* US   Government   Users   Restricted   Rights   -   Use,   duplication   or *
* disclosure  restricted by GSA ADP Schedule Contract with Digi International *
* Inc.                                                                        *
*                                                                             *
*******************************************************************************

Module Name:

   receive.c

Abstract:

   This module contains routines to handle receiving data.

Author:

   Michael Zarns

Revision History:

   $Log: /Components/Windows/NT/Sync/Lan/RECEIVE.C $
 * 
 * 4     9/26/96 8:24a Mikez
 * Moved all Sxb interface routines into two source files - msg.c and
 * irp.c.  
 * 
 * 3     9/19/96 9:24a Mikez
 * Added X25 PVC support.
 * 
 * 2     8/13/96 10:48a Mikez
 * Fully abstracted Frame Relay code into three routines:  FrSend,
 * FrReceive and FrInit, and one AdapterObject field: RxControlLength.
 * This revision works and support Frame Relay only.
 * 
 * 1     8/05/96 2:14p Mikez
 * 
 * 4     6/28/96 6:38a Mikez
 * Cleaned up commented out code.
 * 
 * 1     3/11/96 3:16p Mikez
 * Revision 1.4  1995/12/06  08:48:51  mikez
 * Corrected calculation of rx IPX packet size.  Also, now use 
 * RemoteNetworkAddress as source MAC address on rx packets.
 * 
 * Revision 1.3  1995/08/23  07:47:45  mikez
 * Fixed IP routing by adding ARP spoofing.  Added IPX routing support.
 * 
 * Revision 1.2  1995/08/17  23:38:43  mikez
 * Mod's to support changed ethernet constants.
 * 
 * Revision 1.1  1995/08/16  12:40:14  mikez
 * Initial revision
 * 

--*/

#include "digilan.h"


VOID
DigiLanIndicateReceive(
	IN PDIGILAN_LOGICAL_ADAPTER pAdapter,
	IN PDIGILAN_FRAME_BUFFER pBuffer,
	IN PDIGILAN_ETHERNET_FRAME pFrame,
	IN ULONG PayloadLength
	)
/*++

Description:

	This routine is called from the Adapter Context Timer Callback routine to send 
	an NdisMEthIndicateReceive notification up to Ndis.

Parameters:

	pAdapter
		Adapter object defines the Sxb VC and virtual Ndis adapter on which the
		packet is received.

	pBuffer
		Address of buffer which holds pFrame to be indicated.  This buffer will be
		freed before returning.

	pFrame
		Address of ethernet/802.3 frame to be indicated.  This will reside inside
		pBuffer.

	PayloadLength
		Length of ethernet/802.3 frame's payload.

Return Value:

	None

--*/
{
	DigiDump( DIGIFLOW, ("Enter DigiLanIndicateReceive\n") );

	NdisMEthIndicateReceive( pAdapter->MiniportAdapterHandle,
	                         pFrame->Payload,
	                         pFrame->Header,
	                         ETHERNET_MAC_HEADER_SIZE,
	                         pFrame->Payload,
	                         PayloadLength,
	                         PayloadLength );

	DigiFreeMem( pBuffer );
	DigiDump( DIGIFLOW, ("Leave DigiLanIndicateReceive\n") );
}



NDIS_STATUS
DigiLanTransferData(
	OUT PNDIS_PACKET pPacket,
	OUT PUINT BytesTransferred,
	IN NDIS_HANDLE MiniportAdapterContext,
	IN NDIS_HANDLE MiniportReceiveContext,
	IN UINT ByteOffset,
	IN UINT BytesToTransfer
	)
/*++

Description:

	A protocol calls the DigiLanTransferData request (indirectly via NdisTransferData)
	from within its Receive event handler to instruct the driver to copy the contents 
	of the received packet a specified packet buffer.

Parameters:

	MiniportAdapterContext
		The handle returned by MiniportInitialize.

	MiniportReceiveContext
		The context value previously registered when the miniport driver called 
		NdisMXxxIndicateReceive. The miniport driver can examine this value to 
		determine which packet is being received.

	ByteOffset
		The offset within the received packet at which the copy is to begin. If the 
		entire packet is be copied, ByteOffset should be zero.

	BytesToTransfer
		The number of bytes to copy. It is legal to transfer zero bytes; this has no 
		effect. The sum of ByteOffset and BytesToTransfer must be less than or equal 
		to the packet size specified in the receive indication.

	Packet
		A descriptor for the packet into which the miniport driver is to copy the 
		received packet.

	BytesTransferred
		A value indicating the number of bytes transferred to this location. This 
		value is invalid if the return value is NDIS_STATUS_PENDING.

Return Value:

	NDIS_STATUS_SUCCESS

--*/
{
	PNDIS_BUFFER pDestinationBuffer;
	PUCHAR pDestinationBufferAddress;
	ULONG DestinationBufferLength;
	ULONG DestinationBufferCount;

	PUCHAR pSourceBufferAddress;
	ULONG LocalBytesTransferred = 0;

	ULONG AmountToMove;


	DigiDump( DIGIFLOW, ("Enter DigiLanTransferData\n") );

	// Not used
	MiniportAdapterContext;

	//
	// We passed this pointer (it's actually pFrame->Payload)into the call to
	// NdisMEthIndicateReceive in DigiLanIndicateReceive.
	//

	pSourceBufferAddress = (PUCHAR)MiniportReceiveContext;

	ASSERT( pSourceBufferAddress );

	//
	// Start reading at the requested offset
	//
	
	pSourceBufferAddress += ByteOffset;

	NdisQueryPacket( pPacket,
	                 NULL,
	                 &DestinationBufferCount,
	                 &pDestinationBuffer,
	                 NULL );

	//
	// Deal with zero length copy
	//

	if ( 0 == BytesToTransfer )
	{
		*BytesTransferred = 0;
		return( NDIS_STATUS_SUCCESS );
	}

	//
	// Could have a null packet
	//

	if ( 0 == DestinationBufferCount )
	{
		*BytesTransferred = 0;
		return( NDIS_STATUS_SUCCESS );
	}

	while ( BytesToTransfer )
	{
		NdisQueryBuffer( pDestinationBuffer,
		                 &pDestinationBufferAddress,
		                 &DestinationBufferLength );

		//
		// Verify that there's room in the current buffer.  If not, move onto
		// the next buffer.
		//

		if ( DestinationBufferLength )
		{
			//
			// Copy the data
			//

			AmountToMove = ( BytesToTransfer < DestinationBufferLength ) ?
								BytesToTransfer : DestinationBufferLength;

			NdisMoveMemory( pDestinationBufferAddress,
			                pSourceBufferAddress,
			                AmountToMove );

			pSourceBufferAddress  += AmountToMove;
			BytesToTransfer       -= AmountToMove;
			LocalBytesTransferred += AmountToMove;

			ASSERT( (INT)BytesToTransfer >= 0 );
		}

		NdisGetNextBuffer( pDestinationBuffer,
		                   &pDestinationBuffer );

		if ( !pDestinationBuffer )
		{
			// We've reached the end of the packet.  Return with what we've
			// done so far.
			break;
		}
	}

	*BytesTransferred = LocalBytesTransferred;

	DigiDump( DIGIFLOW, ("Leave DigiLanTransferData\n") );
	return( NDIS_STATUS_SUCCESS );
}
