Windows NT 4.0 source code leak
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.
 
 
 
 
 
 

633 lines
19 KiB

//**********************************************************************
//**********************************************************************
//
// File Name: RECEIVE.C
//
// Program Name: NetFlex NDIS 3.0 Miniport Driver
//
// Companion Files: None
//
// Function: This module contains the NetFlex Miniport Driver
// interface routines called by the Wrapper and the
// configuration manager.
//
// (c) Compaq Computer Corporation, 1992,1993,1994
//
// This file is licensed by Compaq Computer Corporation to Microsoft
// Corporation pursuant to the letter of August 20, 1992 from
// Gary Stimac to Mark Baber.
//
// History:
//
// 04/15/94 Robert Van Cleve - Converted from NDIS Mac Driver
//
//**********************************************************************
//**********************************************************************
//-------------------------------------
// Include all general companion files
//-------------------------------------
#include <ndis.h>
#include "tmsstrct.h"
#include "macstrct.h"
#include "adapter.h"
#include "protos.h"
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
// Routine Name: NetFlexProcessRcv
//
// Description: This routine looks through the receive lists
// looking for received packets. A receive
// indication is given for each packet received
//
// Input: acb - Pointer to the Adapter's acb
//
// Output: true if we should indicaterecievecomplete
//
// Calls: NdisIndicateReceive
//
// Called_By: NetflxHandleInterrupt
//
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
USHORT
FASTCALL
NetFlexProcessEthRcv(
PACB acb
)
{
PRCV rcvptr;
USHORT FrameSize;
USHORT ReceiveCount = 0;
PUCHAR Temp;
#if (DBG || DBGPRINT)
BOOLEAN IsBroadcast;
PUCHAR SourceAddress;
#endif
//
// While there is recieves to process...
//
rcvptr = acb->acb_rcv_head;
//
// Ensure that our Receive Entry is on an even boundary.
//
ASSERT(!(NdisGetPhysicalAddressLow(rcvptr->RCV_Phys) & 1));
do
{
//
// See if the recieve is on one list...
//
if ((rcvptr->RCV_CSTAT & (RCSTAT_EOF | RCSTAT_SOF)) == (RCSTAT_EOF | RCSTAT_SOF))
{
// Frame is on one list.
//
FrameSize = (USHORT)(SWAPS(rcvptr->RCV_Fsize));
rcvptr->RCV_HeaderLen = HDR_SIZE;
//
// Flush the receive buffer
//
NdisFlushBuffer(rcvptr->RCV_FlushBuffer, FALSE);
#if (DBG || DBGPRINT)
SourceAddress = (PVOID)((PUCHAR)&(rcvptr->RCV_Buf) + 2);
IsBroadcast = ETH_IS_BROADCAST(SourceAddress); // works for eth & tr
if (IsBroadcast)
{
DebugPrint(3,("NF(%d): Recieved broadcast!\n",acb->anum));
}
else if (ETH_IS_MULTICAST(SourceAddress))
{
DebugPrint(3,("NF(%d): Recieved multicast!\n",acb->anum));
}
#endif
//
// For speed...
//
Temp = (PUCHAR) rcvptr->RCV_Buf;
//
// Check for Runt or Normal Packet
//
if (FrameSize >= HDR_SIZE)
{
// Normal Packet
//
ReceiveCount++;
NdisMEthIndicateReceive(acb->acb_handle,
(NDIS_HANDLE)(((PUCHAR) Temp) + HDR_SIZE),
Temp,
(UINT)HDR_SIZE,
(((PUCHAR) Temp) + HDR_SIZE),
(UINT)(FrameSize - HDR_SIZE),
(UINT)(FrameSize - HDR_SIZE));
}
else if (FrameSize >= NET_ADDR_SIZE)
{
ReceiveCount++;
// Runt Packet
//
DebugPrint(1,("NF(%d) - Got Runt! len = %d\n",acb->anum,FrameSize));
NdisMEthIndicateReceive(acb->acb_handle,
(NDIS_HANDLE)(((PUCHAR) Temp) + HDR_SIZE),
Temp,
(UINT)FrameSize,
NULL,
0,
0);
}
#if DBG
else
{
DebugPrint(1,("NF(%d) - Rec - Packetlen = %d",acb->anum,FrameSize));
}
#endif
rcvptr->RCV_CSTAT =
((rcvptr->RCV_Number % acb->RcvIntRatio) == 0) ? RCSTAT_GO_INT : RCSTAT_GO;
//
// Get next receive list
//
rcvptr = rcvptr->RCV_Next;
}
else
{
//
// Frame is too large. Release the frame.
//
acb->acb_gen_objs.frames_rcvd_err++;
DebugPrint(0,("Netflx: Receive Not on one list.\n"));
//
// Clean up the list making up this packet.
//
while (((rcvptr->RCV_CSTAT & (RCSTAT_EOF | RCSTAT_SOF)) != (RCSTAT_EOF | RCSTAT_SOF)) &&
((rcvptr->RCV_CSTAT & RCSTAT_COMPLETE) != 0)
)
{
//
// Clean the list and set the FINT based on ratio.
//
rcvptr->RCV_CSTAT =
((rcvptr->RCV_Number % acb->RcvIntRatio) == 0) ? RCSTAT_GO_INT : RCSTAT_GO;
rcvptr = rcvptr->RCV_Next;
}
}
//
// If we're processing too many, get out
//
if (ReceiveCount >= acb->acb_maxrcvs)
break;
} while (rcvptr->RCV_CSTAT & RCSTAT_COMPLETE);
//
// Update head pointer
//
acb->acb_rcv_head = rcvptr;
//
// Tell Adapter that there are more receives available
//
NdisRawWritePortUshort( acb->SifIntPort, (USHORT) SIFINT_RCVVALID);
//
// Update number of received frames
//
acb->acb_gen_objs.frames_rcvd_ok += ReceiveCount;
return(ReceiveCount);
}
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
// Routine Name: NetFlexProcessTrRcv
//
// Description: This routine looks through the receive lists
// looking for received packets. A receive
// indication is given for each packet received.
//
// Input: acb - Pointer to the Adapter's acb
//
// Output: true if we should indicaterecievecomplete
//
// Calls: NdisIndicateReceive
//
// Called_By: NetflxHandleInterrupt
//
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
USHORT
FASTCALL
NetFlexProcessTrRcv(
PACB acb
)
{
PRCV rcvptr;
USHORT FrameSize;
USHORT HeaderSize;
USHORT ReceiveCount = 0;
PUCHAR Temp;
#if (DBG || DBGPRINT)
BOOLEAN IsBroadcast;
PUCHAR SourceAddress;
#endif
//
// While there is recieves to process...
//
rcvptr = acb->acb_rcv_head;
//
// Ensure that our Receive Entry is on an even boundary.
//
ASSERT(!(NdisGetPhysicalAddressLow(rcvptr->RCV_Phys) & 1));
do
{
// See if the recieve is on one list...
//
if ((rcvptr->RCV_CSTAT & (RCSTAT_EOF | RCSTAT_SOF)) == (RCSTAT_EOF | RCSTAT_SOF))
{
// Frame is on one list.
//
FrameSize = (USHORT)(SWAPS(rcvptr->RCV_Fsize));
HeaderSize = HDR_SIZE;
//
// Flush the receive buffer
//
NdisFlushBuffer(rcvptr->RCV_FlushBuffer, FALSE);
#if (DBG || DBGPRINT)
SourceAddress = (PVOID)((PUCHAR)&(rcvptr->RCV_Buf) + 2);
IsBroadcast = ETH_IS_BROADCAST(SourceAddress); // works for eth & tr
if (IsBroadcast)
{
DebugPrint(3,("NF(%d): Recieved broadcast!\n",acb->anum));
}
else
{
TR_IS_GROUP(SourceAddress,&IsBroadcast);
if (IsBroadcast)
{
DebugPrint(3,("NF(%d): Recieved TR Group!\n",acb->anum));
}
}
TR_IS_FUNCTIONAL(SourceAddress,&IsBroadcast);
if (IsBroadcast)
DebugPrint(2,("NF(%d): Recieved TR Fuctional!\n",acb->anum));
#endif
//
// For speed...
//
Temp = (PUCHAR) rcvptr->RCV_Buf;
//
// Make sure we have at least the AC, FS, SRC & DST fields before
// looking at the source routing info.
//
if (FrameSize >= HeaderSize)
{
// Is the source routing bit is on?
//
if (Temp[8] & 0x80)
{
// Yes, figure out the size of the MAC Frame Header.
//
HeaderSize = (Temp[HDR_SIZE] & 0x1f) + HDR_SIZE;
rcvptr->RCV_HeaderLen = HeaderSize;
//
// Check for Runt or Normal Packet again...
//
if (FrameSize >= HeaderSize)
{
// Normal Packet
//
ReceiveCount++;
NdisMTrIndicateReceive(
acb->acb_handle,
(NDIS_HANDLE)(((PUCHAR) Temp) + HeaderSize),
Temp,
(UINT)HeaderSize,
(((PUCHAR) Temp) + HeaderSize),
(UINT)(FrameSize - HeaderSize),
(UINT)(FrameSize - HeaderSize));
}
else if (FrameSize >= NET_ADDR_SIZE)
{
// Runt Packet
//
ReceiveCount++;
DebugPrint(1,("NF(%d) - Got Runt - len = %d!\n",acb->anum,FrameSize));
NdisMTrIndicateReceive(
acb->acb_handle,
(NDIS_HANDLE)(((PUCHAR) Temp) + HeaderSize),
Temp,
(UINT)FrameSize,
NULL,
0,
0);
}
}
else
{
// No Source Routing info, but has Normal Packet Length
//
rcvptr->RCV_HeaderLen = HeaderSize;
ReceiveCount++;
NdisMTrIndicateReceive(
acb->acb_handle,
(NDIS_HANDLE)(((PUCHAR) Temp) + HeaderSize),
Temp,
(UINT)HeaderSize,
(((PUCHAR) Temp) + HeaderSize),
(UINT)(FrameSize - HeaderSize),
(UINT)(FrameSize - HeaderSize));
}
}
else
{
// No, Frame doesn't have AC, FC, SRC & DST.
// Is it bigger than net_addr_size?
//
if (FrameSize >= NET_ADDR_SIZE)
{
// Yes, so indicate Runt Packet
//
ReceiveCount++;
DebugPrint(1,("NF(%d) - Got Runt - len = %d!\n",acb->anum,FrameSize));
NdisMTrIndicateReceive(
acb->acb_handle,
(NDIS_HANDLE)(((PUCHAR) Temp) + HeaderSize),
Temp,
(UINT)FrameSize,
NULL,
0,
0);
}
}
rcvptr->RCV_CSTAT =
((rcvptr->RCV_Number % acb->RcvIntRatio) == 0) ? RCSTAT_GO_INT : RCSTAT_GO;
//
// Get next receive list
//
rcvptr = rcvptr->RCV_Next;
}
else
{
// Frame is too large. Release the frame.
//
acb->acb_gen_objs.frames_rcvd_err++;
DebugPrint(0,("Netflx: Receive Not on one list.\n"));
//
// Clean up the list making up this packet.
//
while (((rcvptr->RCV_CSTAT & (RCSTAT_EOF | RCSTAT_SOF)) != (RCSTAT_EOF | RCSTAT_SOF)) &&
((rcvptr->RCV_CSTAT & RCSTAT_COMPLETE) != 0))
{
// Clean the list and set the FINT based on ratio.
//
rcvptr->RCV_CSTAT =
((rcvptr->RCV_Number % acb->RcvIntRatio) == 0) ? RCSTAT_GO_INT : RCSTAT_GO;
rcvptr = rcvptr->RCV_Next;
}
}
//
// If we're processing too many, get out
//
if (ReceiveCount >= acb->acb_maxrcvs)
break;
} while (rcvptr->RCV_CSTAT & RCSTAT_COMPLETE);
//
// Update head pointer
//
acb->acb_rcv_head = rcvptr;
//
// Tell Adapter that there are more receives available
//
NdisRawWritePortUshort( acb->SifIntPort, (USHORT) SIFINT_RCVVALID);
//
// Update number of recieved frames
//
acb->acb_gen_objs.frames_rcvd_ok += ReceiveCount;
return ReceiveCount;
}
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
// Routine Name: NetFlexTransferData
//
// Description: This routine copies the received data into
// a packet structure provided by the caller.
//
// Input:
//
// MiniportAdapterContext - The context value returned by the driver when the
// adapter was initialized. In reality this is a pointer to NE3200_ADAPTER.
//
// MiniportReceiveContext - The context value passed by the driver on its call
// to NdisMIndicateReceive. The driver can use this value to determine
// which packet, on which adapter, is being received.
//
// ByteOffset - An unsigned integer specifying the offset within the
// received packet at which the copy is to begin. If the entire packet
// is to be copied, ByteOffset must be zero.
//
// BytesToTransfer - An unsigned integer specifying the number of bytes
// to copy. It is legal to transfer zero bytes; this has no effect. If
// the sum of ByteOffset and BytesToTransfer is greater than the size
// of the received packet, then the remainder of the packet (starting from
// ByteOffset) is transferred, and the trailing portion of the receive
// buffer is not modified.
//
// Packet - A pointer to a descriptor for the packet storage into which
// the MAC is to copy the received packet.
//
// BytesTransfered - A pointer to an unsigned integer. The MAC writes
// the actual number of bytes transferred into this location. This value
// is not valid if the return Status is STATUS_PENDING.
//
// Output:
// Packet - Place to copy data.
// BytesTransferred - Number of bytes copied.
// Returns NDIS_STATUS_SUCCESS for a successful
// completion. Otherwise, an error code is returned.
//
// Called By:
// Miniport Wrapper
//
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
NDIS_STATUS
NetFlexTransferData(
OUT PNDIS_PACKET Packet,
OUT PUINT BytesTransferred,
IN NDIS_HANDLE MiniportAdapterContext,
IN NDIS_HANDLE MiniportReceiveContext,
IN UINT ByteOffset,
IN UINT BytesToTransfer
)
{
PACB acb = (PACB) MiniportAdapterContext;
PNDIS_BUFFER DestinationCurrentBuffer;
UINT DestinationBufferCount;
PUCHAR SourceCurrentAddress;
PVOID DestinationVirtualAddress;
UINT DestinationCurrentLength;
UINT LocalBytesTransferred = 0;
UINT AmountToMove;
UINT Remaining;
//
// Display number of bytes to transfer on the debugger
//
DebugPrint(2,("NF(%d) - Copying %u bytes\n",acb->anum,BytesToTransfer));
//
// Initialize the number of bytes transferred to 0
//
*BytesTransferred = 0;
//
// If we don't have any more to transfer, we're done
//
if (BytesToTransfer == 0)
{
return NDIS_STATUS_SUCCESS;
}
//
// Get the first buffer of the destination.
//
NdisQueryPacket(
Packet,
NULL,
&DestinationBufferCount,
&DestinationCurrentBuffer,
NULL
);
//
// Could have a null packet. If so, we are done.
//
if (DestinationBufferCount == 0)
{
return NDIS_STATUS_SUCCESS;
}
//
// Get information on the buffer.
//
NdisQueryBuffer(
DestinationCurrentBuffer,
&DestinationVirtualAddress,
&DestinationCurrentLength
);
//
// Set up the source address.
//
SourceCurrentAddress = (PCHAR)(MiniportReceiveContext) + ByteOffset;
//
// Do the actual transfer from source to destination
//
while (LocalBytesTransferred < BytesToTransfer)
{
// Check to see whether we've exhausted the current destination
// buffer. If so, move onto the next one.
//
if (DestinationCurrentLength == 0)
{
NdisGetNextBuffer(
DestinationCurrentBuffer,
&DestinationCurrentBuffer
);
if (DestinationCurrentBuffer == NULL)
{
// We've reached the end of the packet. We return
// with what we've done so far. (Which must be shorter
// than requested.)
//
break;
}
NdisQueryBuffer(
DestinationCurrentBuffer,
&DestinationVirtualAddress,
&DestinationCurrentLength
);
continue;
}
//
// Copy the data.
//
Remaining = BytesToTransfer - LocalBytesTransferred;
AmountToMove = DestinationCurrentLength;
AmountToMove = ((Remaining < AmountToMove)?
(Remaining):(AmountToMove));
NdisMoveMemory(
DestinationVirtualAddress,
SourceCurrentAddress,
AmountToMove
);
//
// Update pointers and counters
//
SourceCurrentAddress += AmountToMove;
LocalBytesTransferred += AmountToMove;
DestinationCurrentLength -= AmountToMove;
}
//
// Indicate how many bytes were transferred
//
*BytesTransferred = LocalBytesTransferred;
//
// Display total bytes transferred on debugger
//
DebugPrint(2,("NF(%d) - Total bytes transferred = %x\n",acb->anum,*BytesTransferred));
return NDIS_STATUS_SUCCESS;
}