summaryrefslogtreecommitdiffstats
path: root/private/ntos/ndis/lsl/mlidrcv.c
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--private/ntos/ndis/lsl/mlidrcv.c589
1 files changed, 589 insertions, 0 deletions
diff --git a/private/ntos/ndis/lsl/mlidrcv.c b/private/ntos/ndis/lsl/mlidrcv.c
new file mode 100644
index 000000000..06fc37273
--- /dev/null
+++ b/private/ntos/ndis/lsl/mlidrcv.c
@@ -0,0 +1,589 @@
+/*++
+
+Copyright (c) 1990 Microsoft Corporation
+
+Module Name:
+
+ mlidrcv.c
+
+Abstract:
+
+ This file contains all routines for receiving packets.
+
+Author:
+
+ Sean Selitrennikoff (SeanSe) 3-8-93
+
+Environment:
+
+ Kernel Mode.
+
+Revision History:
+
+--*/
+
+#include <ndis.h>
+#include "lsl.h"
+#include "frames.h"
+#include "mlid.h"
+#include "ndismlid.h"
+
+
+
+UINT32
+ReceiveGetFrameType(
+ PMLID_STRUCT Mlid,
+ PUINT8 MediaHeader,
+ PUINT8 DataBuffer
+ )
+
+/*++
+
+Routine Description:
+
+ This routine returns the ODI FrameID of the MediaHeader and DataBuffer supplied.
+ It examines them to make a determination.
+
+ NOTE: This routine assumes that MediaHeader and DataBuffer have sufficient
+ bytes to make a determination.
+
+ NOTE: Called with Mlid->MlidSpinLock held!!
+
+Arguments:
+
+ Mlid - Pointer to MLID struct that this came in on.
+
+ MediaHeader - Pointer to the raw media header as defined by NDIS 3.0
+
+ MediaHeaderLength - Length of the media header.
+
+ DataBuffer - Pointer to the rest of the packet.
+
+ FrameLength - Length of the NDIS 3.0 data portion of the packet.
+
+Return Value:
+
+ ODI FrameID.
+
+--*/
+
+{
+ //
+ // Switch on media type
+ //
+ switch (Mlid->NdisMlidMedium) {
+
+ case NdisMedium802_5:
+
+
+ //
+ // Find frame type
+ //
+ if ((DataBuffer[0] == 0xAA) &&
+ (DataBuffer[1] == 0xAA) &&
+ (DataBuffer[2] == 0x03)) {
+
+ return(TOKEN_RING_SNAP_FRAME_ID);
+
+ }
+
+ return(TOKEN_RING_802_2_FRAME_ID);
+ break;
+
+
+ case NdisMedium802_3:
+
+ if (*((USHORT UNALIGNED *)(&(MediaHeader[13]))) > 1500) {
+
+ return(ETHERNET_II_FRAME_ID);
+
+ }
+
+ if ((DataBuffer[0] == 0xFF) && (DataBuffer[1] == 0xFF)) {
+
+ return(ETHERNET_802_3_FRAME_ID);
+ }
+
+ if ((DataBuffer[0] == 0xAA) &&
+ (DataBuffer[1] == 0xAA) &&
+ (DataBuffer[2] == 0x03)) {
+
+ return(ETHERNET_SNAP_FRAME_ID);
+
+ }
+
+ return(ETHERNET_802_2_FRAME_ID);
+ break;
+
+
+ case NdisMediumFddi:
+
+ //
+ // Check for short addresses (unsupported)
+ //
+ if ((MediaHeader[0] & 0x40) == 0) {
+
+ return((UINT32)-1);
+ }
+
+ //
+ // Find frame type
+ //
+ if ((DataBuffer[0] == 0xAA) &&
+ (DataBuffer[1] == 0xAA) &&
+ (DataBuffer[2] == 0x03)) {
+
+ return(FDDI_SNAP_FRAME_ID);
+
+ }
+
+ return(FDDI_802_2_FRAME_ID);
+ break;
+
+
+ default:
+
+ //
+ // Should never happen
+ //
+ ASSERT(0);
+ break;
+
+ }
+}
+
+
+VOID
+ReceiveGetProtocolID(
+ PMLID_STRUCT Mlid,
+ PLOOKAHEAD OdiLookAhead,
+ UINT32 FrameID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine sets the ProtocolID field in the lookahead structure. It examines
+ the lookahead structure media header and data pointer, so these must be filled in.
+
+ NOTE: Called with Mlid->MlidSpinLock held!!
+
+Arguments:
+
+ Mlid - Pointer to the MLID which received the packet.
+
+ OdiLookAhead - Pointer to a partially filled in lookahead structure.
+
+ FrameID - Frame ID of the received frame.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ PUINT8 DSAPArea;
+
+ RtlZeroMemory(OdiLookAhead->LkAhd_ProtocolID, 6);
+
+ switch (FrameID) {
+
+ case ETHERNET_II_FRAME_ID:
+
+ OdiLookAhead->LkAhd_ProtocolID[4] = OdiLookAhead->LkAhd_MediaHeaderPtr[12];
+ OdiLookAhead->LkAhd_ProtocolID[5] = OdiLookAhead->LkAhd_MediaHeaderPtr[13];
+ break;
+
+ case ETHERNET_802_3_FRAME_ID:
+
+ break;
+
+ case ETHERNET_SNAP_FRAME_ID:
+
+ RtlCopyMemory(&(OdiLookAhead->LkAhd_ProtocolID[1]),
+ &(OdiLookAhead->LkAhd_MediaHeaderPtr[17]),
+ 5
+ );
+ break;
+
+ case ETHERNET_802_2_FRAME_ID:
+
+ if (OdiLookAhead->LkAhd_MediaHeaderPtr[16] != 0x03) {
+
+ //
+ // A Type II frame
+ //
+ OdiLookAhead->LkAhd_ProtocolID[0] = 0x3;
+ OdiLookAhead->LkAhd_ProtocolID[2] = OdiLookAhead->LkAhd_MediaHeaderPtr[14];
+ OdiLookAhead->LkAhd_ProtocolID[3] = OdiLookAhead->LkAhd_MediaHeaderPtr[15];
+ OdiLookAhead->LkAhd_ProtocolID[4] = OdiLookAhead->LkAhd_MediaHeaderPtr[16];
+ OdiLookAhead->LkAhd_ProtocolID[5] = OdiLookAhead->LkAhd_MediaHeaderPtr[17];
+
+ } else {
+
+ //
+ // A Type I frame
+ //
+ if (OdiLookAhead->LkAhd_MediaHeaderPtr[14] !=
+ OdiLookAhead->LkAhd_MediaHeaderPtr[15]) {
+ OdiLookAhead->LkAhd_ProtocolID[0] = 0x2;
+ OdiLookAhead->LkAhd_ProtocolID[3] = OdiLookAhead->LkAhd_MediaHeaderPtr[14];
+ OdiLookAhead->LkAhd_ProtocolID[4] = OdiLookAhead->LkAhd_MediaHeaderPtr[15];
+ OdiLookAhead->LkAhd_ProtocolID[5] = OdiLookAhead->LkAhd_MediaHeaderPtr[16];
+
+ } else {
+ OdiLookAhead->LkAhd_ProtocolID[5] = OdiLookAhead->LkAhd_MediaHeaderPtr[14];
+ }
+
+ }
+
+ break;
+
+ case TOKEN_RING_SNAP_FRAME_ID:
+
+ if (OdiLookAhead->LkAhd_MediaHeaderPtr[8] & 0x80) {
+ //
+ // Skip Source Routining info
+ //
+
+ DSAPArea = OdiLookAhead->LkAhd_MediaHeaderPtr +
+ 14 +
+ (OdiLookAhead->LkAhd_MediaHeaderPtr[14] & 0x0F);
+ } else{
+
+ DSAPArea = OdiLookAhead->LkAhd_MediaHeaderPtr + 14;
+
+ }
+
+ RtlCopyMemory(&(OdiLookAhead->LkAhd_ProtocolID[1]),
+ DSAPArea + 3,
+ 5
+ );
+ break;
+
+ case TOKEN_RING_802_2_FRAME_ID:
+
+ if (OdiLookAhead->LkAhd_MediaHeaderPtr[8] & 0x80) {
+ //
+ // Skip Source Routining info
+ //
+
+ DSAPArea = OdiLookAhead->LkAhd_MediaHeaderPtr +
+ 14 +
+ (OdiLookAhead->LkAhd_MediaHeaderPtr[14] & 0x0F);
+
+ } else {
+
+ DSAPArea = OdiLookAhead->LkAhd_MediaHeaderPtr + 14;
+
+ }
+
+ if (DSAPArea[2] != 0x03) {
+
+ //
+ // A Type II frame
+ //
+ OdiLookAhead->LkAhd_ProtocolID[0] = 0x3;
+ OdiLookAhead->LkAhd_ProtocolID[2] = DSAPArea[0];
+ OdiLookAhead->LkAhd_ProtocolID[3] = DSAPArea[1];
+ OdiLookAhead->LkAhd_ProtocolID[4] = DSAPArea[2];
+ OdiLookAhead->LkAhd_ProtocolID[5] = DSAPArea[3];
+
+ } else {
+
+ //
+ // A Type I frame
+ //
+ if (DSAPArea[0] != DSAPArea[1]) {
+ OdiLookAhead->LkAhd_ProtocolID[0] = 0x2;
+ OdiLookAhead->LkAhd_ProtocolID[3] = DSAPArea[0];
+ OdiLookAhead->LkAhd_ProtocolID[4] = DSAPArea[1];
+ OdiLookAhead->LkAhd_ProtocolID[5] = DSAPArea[2];
+
+ } else {
+ OdiLookAhead->LkAhd_ProtocolID[5] = DSAPArea[0];
+ }
+
+ }
+
+ break;
+
+ case FDDI_SNAP_FRAME_ID:
+
+ RtlCopyMemory(&(OdiLookAhead->LkAhd_ProtocolID[1]),
+ &(OdiLookAhead->LkAhd_MediaHeaderPtr[18]),
+ 5
+ );
+ break;
+
+ case FDDI_802_2_FRAME_ID:
+
+ if (OdiLookAhead->LkAhd_MediaHeaderPtr[17] != 0x03) {
+
+ //
+ // A Type II frame
+ //
+ OdiLookAhead->LkAhd_ProtocolID[0] = 0x3;
+ OdiLookAhead->LkAhd_ProtocolID[2] = OdiLookAhead->LkAhd_MediaHeaderPtr[15];
+ OdiLookAhead->LkAhd_ProtocolID[3] = OdiLookAhead->LkAhd_MediaHeaderPtr[16];
+ OdiLookAhead->LkAhd_ProtocolID[4] = OdiLookAhead->LkAhd_MediaHeaderPtr[17];
+ OdiLookAhead->LkAhd_ProtocolID[5] = OdiLookAhead->LkAhd_MediaHeaderPtr[18];
+
+ } else {
+
+ //
+ // A Type I frame
+ //
+ if (OdiLookAhead->LkAhd_MediaHeaderPtr[15] !=
+ OdiLookAhead->LkAhd_MediaHeaderPtr[16]) {
+ OdiLookAhead->LkAhd_ProtocolID[0] = 0x2;
+ OdiLookAhead->LkAhd_ProtocolID[3] = OdiLookAhead->LkAhd_MediaHeaderPtr[15];
+ OdiLookAhead->LkAhd_ProtocolID[4] = OdiLookAhead->LkAhd_MediaHeaderPtr[16];
+ OdiLookAhead->LkAhd_ProtocolID[5] = OdiLookAhead->LkAhd_MediaHeaderPtr[17];
+
+ } else {
+ OdiLookAhead->LkAhd_ProtocolID[5] = OdiLookAhead->LkAhd_MediaHeaderPtr[15];
+ }
+
+ }
+
+ break;
+
+ }
+}
+
+
+VOID
+ReceiveSetDestinationType(
+ PMLID_STRUCT Mlid,
+ PLOOKAHEAD OdiLookAhead
+ )
+
+
+/*++
+
+Routine Description:
+
+ This routine sets the DestType field in the lookahead structure. It examines
+ the lookahead structure media header and data pointer, so these must be filled in.
+
+ NOTE: Require the ImmediateAddress field to be filled with the source address.
+ NOTE: Called with Mlid->MlidSpinLock held!!
+
+Arguments:
+
+ Mlid - Pointer to MLID receiving the packet.
+
+ OdiLookAhead - Pointer to a partially filled in lookahead structure.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ BOOLEAN Result;
+
+ if (OdiLookAhead->LkAhd_PktAttr != 0) {
+
+ OdiLookAhead->LkAhd_DestType = 0x20; // Global Error
+ return;
+
+ }
+
+ OdiLookAhead->LkAhd_DestType = 0x0;
+
+ switch (Mlid->NdisMlidMedium) {
+
+ case NdisMedium802_3:
+
+ //*\\ Does not support setting MulticastRemote bit in DestType. Is this OK?
+
+ if (ETH_IS_BROADCAST(OdiLookAhead->LkAhd_ImmediateAddress)) {
+ OdiLookAhead->LkAhd_DestType = 0x3; // Broadcast
+ return;
+ }
+
+ if (ETH_IS_MULTICAST(OdiLookAhead->LkAhd_ImmediateAddress)) {
+ OdiLookAhead->LkAhd_DestType = 0x1; // Multicast
+ return;
+ }
+
+ COMPARE_NETWORK_ADDRESSES(OdiLookAhead->LkAhd_ImmediateAddress,
+ Mlid->ConfigTable.MLIDCFG_NodeAddress,
+ &Result);
+ if (Result) {
+ OdiLookAhead->LkAhd_DestType = 0x80; // Direct
+ return;
+ }
+
+ OdiLookAhead->LkAhd_DestType = 0x4; // Directed to another station
+
+ break;
+
+ case NdisMedium802_5:
+
+ //
+ // First check for SR Info
+ //
+ if (OdiLookAhead->LkAhd_ImmediateAddress[0] & 0x80) {
+
+ //
+ // Yes
+ //
+ if (Mlid->ConfigTable.MLIDCFG_SourceRouting == NULL) {
+
+ //
+ // Set bit and exit
+ //
+ OdiLookAhead->LkAhd_DestType = 0x10; // No Source Routing
+ return;
+ }
+
+ }
+
+ TR_IS_BROADCAST(OdiLookAhead->LkAhd_ImmediateAddress, &Result);
+ if (Result == TRUE) {
+ OdiLookAhead->LkAhd_DestType = 0x3; // Broadcast
+ return;
+ }
+
+ TR_IS_GROUP(OdiLookAhead->LkAhd_ImmediateAddress, &Result);
+ if (Result == TRUE) {
+ OdiLookAhead->LkAhd_DestType = 0x1; // Multicast
+ return;
+ }
+
+ TR_IS_FUNCTIONAL(OdiLookAhead->LkAhd_ImmediateAddress, &Result);
+ if (Result == TRUE) {
+ OdiLookAhead->LkAhd_DestType = 0x1; // Multicast
+ return;
+ }
+
+ COMPARE_NETWORK_ADDRESSES(OdiLookAhead->LkAhd_ImmediateAddress,
+ Mlid->ConfigTable.MLIDCFG_NodeAddress,
+ &Result);
+ if (Result) {
+ OdiLookAhead->LkAhd_DestType = 0x80; // Direct
+ return;
+ }
+
+ OdiLookAhead->LkAhd_DestType = 0x4; // Directed to another station
+
+ break;
+
+ case NdisMediumFddi:
+
+ if (ETH_IS_BROADCAST(OdiLookAhead->LkAhd_ImmediateAddress)) {
+ OdiLookAhead->LkAhd_DestType = 0x3; // Broadcast
+ return;
+ }
+
+ if (ETH_IS_MULTICAST(OdiLookAhead->LkAhd_ImmediateAddress)) {
+ OdiLookAhead->LkAhd_DestType = 0x1; // Multicast
+ return;
+ }
+
+ COMPARE_NETWORK_ADDRESSES(OdiLookAhead->LkAhd_ImmediateAddress,
+ Mlid->ConfigTable.MLIDCFG_NodeAddress,
+ &Result);
+ if (Result) {
+ OdiLookAhead->LkAhd_DestType = 0x80; // Direct
+ return;
+ }
+
+ OdiLookAhead->LkAhd_DestType = 0x4; // Directed to another station
+
+ break;
+
+ }
+
+}
+
+
+NDIS_STATUS
+BuildReceiveBufferChain(
+ PMLID_STRUCT Mlid,
+ PNDIS_PACKET NdisReceivePacket,
+ PECB ReceiveECB
+ )
+
+/*++
+
+Routine Description:
+
+ This routine builds an MDL chain describing the ECB fragment list
+ and attaches it to the NDIS_PACKET.
+
+ NOTE: Called with Mlid->MlidSpinLock held!!
+
+Arguments:
+
+ Mlid - Owning Mlid.
+
+ Packet - Pointer to the NDIS_PACKET to free.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ UINT32 i;
+ PNDIS_BUFFER NdisBuffer;
+ NDIS_STATUS NdisStatus;
+
+ //
+ // Convert ECB fragment list into an MDL chain
+ //
+ for (i = 0; i < ReceiveECB->ECB_FragmentCount; i++) {
+
+ NdisAllocateBuffer(
+ &NdisStatus,
+ &NdisBuffer,
+ Mlid->ReceiveBufferPool,
+ ReceiveECB->ECB_Fragment[i].FragmentAddress,
+ ReceiveECB->ECB_Fragment[i].FragmentLength
+ );
+
+ if (NdisStatus != NDIS_STATUS_SUCCESS) {
+
+ //
+ // Unchain all NDIS_BUFFERs from packet
+ //
+
+ NdisUnchainBufferAtFront(
+ NdisReceivePacket,
+ &NdisBuffer
+ );
+
+ while (NdisBuffer != NULL) {
+
+ NdisFreeBuffer(NdisBuffer);
+
+ NdisUnchainBufferAtFront(
+ NdisReceivePacket,
+ &NdisBuffer
+ );
+
+ }
+
+ return(NDIS_STATUS_RESOURCES);
+
+ }
+
+ NdisChainBufferAtBack(
+ NdisReceivePacket,
+ NdisBuffer
+ );
+
+ }
+
+ return(NDIS_STATUS_SUCCESS);
+
+}
+