summaryrefslogtreecommitdiffstats
path: root/private/ntos/ndis/netflex/receive.c
diff options
context:
space:
mode:
Diffstat (limited to 'private/ntos/ndis/netflex/receive.c')
-rw-r--r--private/ntos/ndis/netflex/receive.c633
1 files changed, 633 insertions, 0 deletions
diff --git a/private/ntos/ndis/netflex/receive.c b/private/ntos/ndis/netflex/receive.c
new file mode 100644
index 000000000..1219cb033
--- /dev/null
+++ b/private/ntos/ndis/netflex/receive.c
@@ -0,0 +1,633 @@
+//**********************************************************************
+//**********************************************************************
+//
+// 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;
+}