summaryrefslogtreecommitdiffstats
path: root/private/ntos/ndis/lsl/ndismlid.c
diff options
context:
space:
mode:
authorAdam <you@example.com>2020-05-17 05:51:50 +0200
committerAdam <you@example.com>2020-05-17 05:51:50 +0200
commite611b132f9b8abe35b362e5870b74bce94a1e58e (patch)
treea5781d2ec0e085eeca33cf350cf878f2efea6fe5 /private/ntos/ndis/lsl/ndismlid.c
downloadNT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.gz
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.bz2
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.lz
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.xz
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.zst
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.zip
Diffstat (limited to '')
-rw-r--r--private/ntos/ndis/lsl/ndismlid.c1183
1 files changed, 1183 insertions, 0 deletions
diff --git a/private/ntos/ndis/lsl/ndismlid.c b/private/ntos/ndis/lsl/ndismlid.c
new file mode 100644
index 000000000..47d779485
--- /dev/null
+++ b/private/ntos/ndis/lsl/ndismlid.c
@@ -0,0 +1,1183 @@
+/*++
+
+Copyright (c) 1990 Microsoft Corporation
+
+Module Name:
+
+ ndismlid.c
+
+Abstract:
+
+ This file contains all the NDIS inteface routines between NDIS mac and this MLID.
+
+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"
+
+
+
+VOID
+NdisMlidOpenAdapterComplete(
+ IN NDIS_HANDLE ProtocolBindingContext,
+ IN NDIS_STATUS Status,
+ IN NDIS_STATUS OpenErrorStatus
+ )
+
+/*++
+
+Routine Description:
+
+ This routine is called by NDIS to indicate that an open adapter
+ is complete. Since we only ever have one outstanding, and then only
+ during initialization, all we do is record the status and set
+ the event to signalled to unblock the initialization thread.
+
+Arguments:
+
+ BindingContext - Pointer to the device object for this driver.
+
+ NdisStatus - The request completion code.
+
+ OpenErrorStatus - More status information.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ PMLID_STRUCT Mlid = (PMLID_STRUCT)ProtocolBindingContext;
+
+ //
+ // Store completion status
+ //
+ Mlid->RequestStatus = Status;
+
+ //
+ // Set event to indicate the completion of the open
+ //
+
+ KeSetEvent(&Mlid->MlidRequestCompleteEvent, 0L, FALSE);
+
+}
+
+VOID
+NdisMlidCloseAdapterComplete(
+ IN NDIS_HANDLE ProtocolBindingContext,
+ IN NDIS_STATUS Status
+ )
+
+/*++
+
+Routine Description:
+
+ This routine is called by NDIS to indicate that a close adapter
+ is complete.
+
+ NOTE: This processing assumes that CloseAdapter is only called during
+ initialization time.
+
+Arguments:
+
+ BindingContext - Pointer to the device object for this driver.
+
+ NdisStatus - The request completion code.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ PMLID_STRUCT Mlid = (PMLID_STRUCT)ProtocolBindingContext;
+
+ //
+ // Store completion status
+ //
+ Mlid->RequestStatus = Status;
+
+ //
+ // Set event to indicate the completion of the open
+ //
+
+ KeSetEvent(&Mlid->MlidRequestCompleteEvent, 0L, FALSE);
+
+}
+
+VOID
+NdisMlidSendComplete(
+ IN NDIS_HANDLE ProtocolBindingContext,
+ IN PNDIS_PACKET Packet,
+ IN NDIS_STATUS Status
+ )
+
+/*++
+
+Routine Description:
+
+ This routine is called when a send has been completed.
+
+Arguments:
+
+ ProtocolBindingContext - A pointer to the MLID_STRUCT that the send was sent across.
+
+ NdisPacket - A pointer to the NDIS_PACKET that we sent.
+
+ Status - the completion status of the send.
+
+Return Value:
+
+ none.
+
+--*/
+
+{
+ PMLID_STRUCT Mlid = (PMLID_STRUCT)ProtocolBindingContext;
+ PECB SendECB;
+ ULONG PacketSize;
+ PUINT64 Statistic;
+ PMLID_RESERVED Reserved = PMLID_RESERVED_FROM_PNDIS_PACKET(Packet);
+
+ //
+ // Get corresponding ECB
+ //
+ SendECB = Reserved->SendECB;
+
+ NdisAcquireSpinLock(&(Mlid->MlidSpinLock));
+
+ NdisQueryPacket(
+ Packet,
+ NULL,
+ NULL,
+ NULL,
+ &PacketSize
+ );
+
+ //
+ // Return resources to Mlid
+ //
+ ReturnSendPacketResources(Packet);
+
+ //
+ // Open the stage
+ //
+ Mlid->StageOpen = TRUE;
+
+ (*((PUINT32)((*(Mlid->StatsTable->StatsTable.MGenericCountsPtr))[14].StatCounter)))--; // MQDepth
+
+ //
+ // Store send status in ECB
+ //
+ if (Status == NDIS_STATUS_SUCCESS) {
+
+ SendECB->ECB_Status = (UINT16)SUCCESSFUL;
+ (*((PUINT32)((*(Mlid->StatsTable->StatsTable.MGenericCountsPtr))[0].StatCounter)))++; // MTotalTxPacketCount
+
+ Statistic = ((PUINT64)((*(Mlid->StatsTable->StatsTable.MGenericCountsPtr))[8].StatCounter)); // MTotalTxOKByteCount;
+ if (((UINT32)0xFFFFFFFF - Statistic->Low_UINT32) < PacketSize) {
+ Statistic->High_UINT32++;
+ }
+ Statistic->Low_UINT32 += PacketSize;
+
+ } else {
+
+ SendECB->ECB_Status = (UINT16)FAIL;
+ (*((PUINT32)((*(Mlid->StatsTable->StatsTable.MGenericCountsPtr))[6].StatCounter)))++; // MTotalTxMiscCount
+
+ }
+
+ //
+ // Call FastSendComplete()
+ //
+ NdisReleaseSpinLock(&(Mlid->MlidSpinLock));
+
+ (*(Mlid->LSLFunctionList->SupportAPIArray[FastSendComplete_INDEX]))(
+ SendECB
+ );
+
+ //
+ // Call Service Events
+ //
+ (*(Mlid->LSLFunctionList->SupportAPIArray[ServiceEvents_INDEX]))(
+ );
+
+ NdisAcquireSpinLock(&(Mlid->MlidSpinLock));
+
+ //
+ // If StageOpen and !InSendPacket and SendsQueued
+ //
+
+ if (Mlid->StageOpen && !Mlid->InSendPacket) {
+
+ //
+ // Send all packets possible for MLID
+ //
+
+ SendPackets(Mlid);
+
+ }
+
+ NdisReleaseSpinLock(&(Mlid->MlidSpinLock));
+
+}
+
+VOID
+NdisMlidTransferDataComplete(
+ IN NDIS_HANDLE ProtocolBindingContext,
+ IN PNDIS_PACKET Packet,
+ IN NDIS_STATUS Status,
+ IN UINT BytesTransferred
+ )
+
+/*++
+
+Routine Description:
+
+ This routine receives control from the physical provider as an
+ indication that an NdisTransferData has completed.
+
+Arguments:
+
+ ProtocolBindingContext - A pointer to the MLID_STRUCT that the transfer data
+ was called for.
+
+ NdisPacket - The packet that contains the data.
+
+ NdisStatus - The completion status for the request.
+
+ BytesTransferred - Number of bytes actually transferred.
+
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ PMLID_STRUCT Mlid = (PMLID_STRUCT)ProtocolBindingContext;
+ PECB ReceiveECB;
+ PMLID_RESERVED Reserved = PMLID_RESERVED_FROM_PNDIS_PACKET(Packet);
+ PNDIS_BUFFER NdisBuffer;
+
+ //
+ // Get corresponding ECB
+ //
+ ReceiveECB = Reserved->SendECB;
+
+ NdisAcquireSpinLock(&(Mlid->MlidSpinLock));
+
+ //
+ // Return resources to Mlid
+ //
+
+ //
+ // Unchain all NDIS_BUFFERs from packet
+ //
+
+ NdisUnchainBufferAtFront(
+ Packet,
+ &NdisBuffer
+ );
+
+ while (NdisBuffer != NULL) {
+
+ NdisFreeBuffer(NdisBuffer);
+
+ NdisUnchainBufferAtFront(
+ Packet,
+ &NdisBuffer
+ );
+
+ }
+
+ NdisFreePacket(Packet);
+
+ //
+ // Store status in ECB
+ //
+ if (Status == NDIS_STATUS_SUCCESS) {
+
+ ReceiveECB->ECB_Status = (UINT16)SUCCESSFUL;
+
+ } else {
+
+ ReceiveECB->ECB_Status = (UINT16)FAIL;
+
+ }
+
+ //
+ // Call FastHoldEvent()
+ //
+ NdisReleaseSpinLock(&(Mlid->MlidSpinLock));
+
+ (*(Mlid->LSLFunctionList->SupportAPIArray[FastHoldEvent_INDEX]))(
+ ReceiveECB
+ );
+
+ //
+ // Call Service Events
+ //
+ (*(Mlid->LSLFunctionList->SupportAPIArray[ServiceEvents_INDEX]))(
+ );
+
+}
+
+VOID
+NdisMlidResetComplete(
+ IN NDIS_HANDLE ProtocolBindingContext,
+ IN NDIS_STATUS Status
+ )
+
+/*++
+
+Routine Description:
+
+ This routine is called by NDIS to indicate that a reset adapter
+ is complete. This routine may be called at initialization time
+ or during runtime. Therefore it merely stores the completion
+ status.
+
+Arguments:
+
+ ProtocolBindingContext - Pointer to the MLID_STRUCT that we submitted the Reset to.
+
+ NdisStatus - The request completion code.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ PMLID_STRUCT Mlid = (PMLID_STRUCT)ProtocolBindingContext;
+
+ //
+ // Store status
+ //
+ Mlid->RequestStatus = Status;
+
+}
+
+VOID
+NdisMlidRequestComplete(
+ IN NDIS_HANDLE ProtocolBindingContext,
+ IN PNDIS_REQUEST NdisRequest,
+ IN NDIS_STATUS Status
+ )
+
+/*++
+
+Routine Description:
+
+ This routine is called by NDIS to indicate that a request is complete.
+ Since we only ever have one request outstanding, all we do is record the
+ status and, if necessary, set the event to signalled to unblock the
+ initialization thread.
+
+Arguments:
+
+ ProtocolBindingContext - Pointer to the MLID_STRUCT that we submitted the request to.
+
+ NdisRequest - The object describing the request.
+
+ NdisStatus - The request completion code.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ PMLID_STRUCT Mlid = (PMLID_STRUCT)ProtocolBindingContext;
+
+ NdisAcquireSpinLock(&(Mlid->MlidSpinLock));
+
+ Mlid->Unloading = FALSE;
+
+ //
+ // Store status
+ //
+ Mlid->RequestStatus = Status;
+
+ if (Mlid->UsingEvent) {
+
+ //
+ // Set event to indicate completion of request
+ //
+
+ NdisReleaseSpinLock(&(Mlid->MlidSpinLock));
+
+ KeSetEvent(&Mlid->MlidRequestCompleteEvent, 0L, FALSE);
+
+ } else if (NdisRequest == (&(Mlid->StatsTable->NdisRequest))) {
+
+ //
+ // This is from the statistic gathering timer.
+ //
+
+ if (Status == NDIS_STATUS_SUCCESS) {
+
+ (*((PUINT32)((*(Mlid->StatsTable->StatsTable.MMediaCountsPtr))
+ [
+ Mlid->StatsTable->StatisticNumber
+ ].StatCounter))) =
+ Mlid->StatsTable->StatisticValue;
+
+ }
+
+ Mlid->StatsTable->StatisticNumber++;
+
+ switch (Mlid->NdisMlidMedium) {
+
+ case NdisMedium802_3:
+
+ if (Mlid->StatsTable->StatisticNumber >= NUM_ETHERNET_COUNTS) {
+ Mlid->StatsTable->StatisticNumber = 0;
+ }
+
+ break;
+
+ case NdisMedium802_5:
+
+ if (Mlid->StatsTable->StatisticNumber >= NUM_TOKEN_RING_COUNTS) {
+ Mlid->StatsTable->StatisticNumber = 0;
+ }
+
+ break;
+
+ case NdisMediumFddi:
+
+ if (Mlid->StatsTable->StatisticNumber >= NUM_FDDI_COUNTS) {
+ Mlid->StatsTable->StatisticNumber = 0;
+ }
+
+ break;
+
+ }
+
+ if (Mlid->StatsTable->StatisticNumber == 0) {
+
+ //
+ // Set timer for 30 seconds from now.
+ //
+ NdisReleaseSpinLock(&(Mlid->MlidSpinLock));
+
+ NdisSetTimer(&(Mlid->StatsTable->StatisticTimer), 30000);
+
+ return;
+
+ }
+
+ NdisReleaseSpinLock(&(Mlid->MlidSpinLock));
+
+ NdisSetTimer(&(Mlid->StatsTable->StatisticTimer), 1);
+
+ return;
+
+ } else {
+
+ //
+ // Free request
+ //
+
+ NdisReleaseSpinLock(&(Mlid->MlidSpinLock));
+
+ ExFreePool(NdisRequest);
+
+ }
+
+}
+
+NDIS_STATUS
+NdisMlidReceive(
+ IN NDIS_HANDLE ProtocolBindingContext,
+ IN NDIS_HANDLE MacReceiveContext,
+ IN PVOID HeaderBuffer,
+ IN UINT HeaderBufferSize,
+ IN PVOID LookAheadBuffer,
+ IN UINT LookaheadBufferSize,
+ IN UINT PacketSize
+ )
+
+/*++
+
+Routine Description:
+
+ This routine receives control from the physical provider as an
+ indication that a frame has been received on the physical link.
+
+Arguments:
+
+ BindingContext - The Adapter Binding specified at initialization time.
+
+ ReceiveContext - A magic cookie for the MAC.
+
+ HeaderBuffer - pointer to a buffer containing the packet header.
+
+ HeaderBufferSize - the size of the header.
+
+ LookaheadBuffer - pointer to a buffer containing the negotiated minimum
+ amount of buffer I get to look at (not including header).
+
+ LookaheadBufferSize - the size of the above. May be less than asked
+ for, if that's all there is.
+
+ PacketSize - Overall size of the packet (not including header).
+
+Return Value:
+
+ NDIS_STATUS - status of operation, one of:
+
+ NDIS_STATUS_SUCCESS if packet accepted,
+ NDIS_STATUS_NOT_RECOGNIZED if not recognized by protocol,
+ NDIS_any_other_thing if I understand, but can't handle.
+
+--*/
+{
+ PMLID_STRUCT Mlid = (PMLID_STRUCT)ProtocolBindingContext;
+ LOOKAHEAD OdiLookAhead;
+ UINT32 MlidHeaderSize;
+ PUINT64 Statistic;
+ UINT8 TmpMediaHeader[64];
+ PECB ReceiveECB;
+
+ NDIS_STATUS NdisStatus;
+ PNDIS_PACKET NdisReceivePacket;
+ PNDIS_BUFFER NdisBuffer;
+ PMLID_RESERVED Reserved;
+ ULONG NdisBytesCopied;
+ UINT32 FrameID;
+
+ //
+ // If MLID is unloading, then return
+ //
+ if (Mlid->Unloading) {
+ return(NDIS_STATUS_SUCCESS);
+ }
+
+ NdisAcquireSpinLock(&(Mlid->MlidSpinLock));
+
+ if (PacketSize < 8) {
+
+ ASSERT(Mlid->PromiscuousModeEnables > 0);
+
+ //
+ // Not enough bytes to determine
+ //
+
+ OdiLookAhead.LkAhd_FrameDataSize = (UINT32)PacketSize;
+ OdiLookAhead.LkAhd_MediaHeaderPtr = (PUINT8)HeaderBuffer;
+
+ OdiLookAhead.LkAhd_DataLookAheadPtr = (PUINT8)LookAheadBuffer;
+ OdiLookAhead.LkAhd_DataLookAheadLen = (UINT32)LookaheadBufferSize;
+
+ switch (Mlid->NdisMlidMedium) {
+
+ case NdisMedium802_3:
+ RtlCopyMemory(&(OdiLookAhead.LkAhd_ImmediateAddress[0]),
+ ((PUINT8)HeaderBuffer) + 6,
+ 6
+ );
+ break;
+
+ case NdisMedium802_5:
+ RtlCopyMemory(&(OdiLookAhead.LkAhd_ImmediateAddress[0]),
+ ((PUINT8)HeaderBuffer) + 8,
+ 6
+ );
+ break;
+
+ case NdisMediumFddi:
+ RtlCopyMemory(&(OdiLookAhead.LkAhd_ImmediateAddress[0]),
+ ((PUINT8)HeaderBuffer) + 7,
+ 6
+ );
+ break;
+
+ }
+
+ OdiLookAhead.LkAhd_BoardNumber = Mlid->BoardNumber;
+ RtlZeroMemory(OdiLookAhead.LkAhd_ProtocolID, 6);
+
+ OdiLookAhead.LkAhd_PktAttr = 0x4; // Runt packet
+ OdiLookAhead.LkAhd_DestType = 0x20; // Global Error
+
+ goto IndicatePacket;
+
+ }
+
+ //
+ // Determine the frame-type of the frame.
+ // this will move the Data Pointer if necessary and modify the Size fields.
+ //
+ FrameID = ReceiveGetFrameType(Mlid,
+ HeaderBuffer,
+ LookAheadBuffer
+ );
+
+ //
+ // If FrameType is not the same as for this MLID, then exit
+ //
+ if ((FrameID != Mlid->ConfigTable.MLIDCFG_FrameID) &&
+ (Mlid->PromiscuousModeEnables == 0)) {
+
+ return(NDIS_STATUS_SUCCESS);
+
+ }
+
+ //
+ // Now get header length based on the FrameID
+ //
+ switch (FrameID) {
+
+ case ETHERNET_II_FRAME_ID:
+ case ETHERNET_802_3_FRAME_ID:
+ MlidHeaderSize = 0;
+ break;
+
+ case FDDI_802_2_FRAME_ID:
+ case TOKEN_RING_802_2_FRAME_ID:
+ case ETHERNET_802_2_FRAME_ID:
+ if (((PUCHAR)LookAheadBuffer)[2] != 0x03) {
+ MlidHeaderSize = 4;
+ } else {
+ MlidHeaderSize = 3;
+ }
+ break;
+
+ case FDDI_SNAP_FRAME_ID:
+ case TOKEN_RING_SNAP_FRAME_ID:
+ case ETHERNET_SNAP_FRAME_ID:
+ MlidHeaderSize = 8;
+ break;
+
+ default:
+ MlidHeaderSize = 0;
+ break;
+
+ }
+ OdiLookAhead.LkAhd_FrameDataSize = (UINT32)PacketSize - MlidHeaderSize;
+
+ if (MlidHeaderSize != 0) {
+
+ //
+ // We must move media header info around so that the ODI media header
+ // is correct.
+ //
+
+ NdisMoveMappedMemory((PUCHAR)TmpMediaHeader,
+ HeaderBuffer,
+ HeaderBufferSize
+ );
+ NdisMoveMappedMemory((PUCHAR)(TmpMediaHeader + HeaderBufferSize),
+ LookAheadBuffer,
+ MlidHeaderSize
+ );
+
+ OdiLookAhead.LkAhd_MediaHeaderPtr = (PUINT8)TmpMediaHeader;
+
+ } else {
+
+ OdiLookAhead.LkAhd_MediaHeaderPtr = (PUINT8)HeaderBuffer;
+
+ }
+
+ //
+ // Fill in buffer portions of ODI LOOKAHEAD structure
+ //
+
+ OdiLookAhead.LkAhd_DataLookAheadPtr = ((PUINT8)LookAheadBuffer) + MlidHeaderSize;
+ OdiLookAhead.LkAhd_DataLookAheadLen = (UINT32)LookaheadBufferSize - MlidHeaderSize;
+
+ switch (Mlid->NdisMlidMedium) {
+
+ case NdisMedium802_3:
+ RtlCopyMemory(&(OdiLookAhead.LkAhd_ImmediateAddress[0]),
+ ((PUINT8)HeaderBuffer) + 6,
+ 6
+ );
+ break;
+
+ case NdisMedium802_5:
+ RtlCopyMemory(&(OdiLookAhead.LkAhd_ImmediateAddress[0]),
+ ((PUINT8)HeaderBuffer) + 8,
+ 6
+ );
+ break;
+
+ case NdisMediumFddi:
+ RtlCopyMemory(&(OdiLookAhead.LkAhd_ImmediateAddress[0]),
+ ((PUINT8)HeaderBuffer) + 7,
+ 6
+ );
+ break;
+
+ }
+
+
+ //
+ // Get the BoardNumber for this NDIS MAC
+ //
+ OdiLookAhead.LkAhd_BoardNumber = Mlid->BoardNumber;
+
+ //
+ // Build protocol ID for the frame
+ //
+ ReceiveGetProtocolID(Mlid, &OdiLookAhead, FrameID);
+
+ //
+ // Fill in the packet attributes.
+ //
+ switch (FrameID) {
+
+ case ETHERNET_II_FRAME_ID:
+ case ETHERNET_802_3_FRAME_ID:
+ case FDDI_SNAP_FRAME_ID:
+ case TOKEN_RING_SNAP_FRAME_ID:
+ case ETHERNET_SNAP_FRAME_ID:
+ OdiLookAhead.LkAhd_PktAttr = 0;
+ break;
+
+ case FDDI_802_2_FRAME_ID:
+ case TOKEN_RING_802_2_FRAME_ID:
+ case ETHERNET_802_2_FRAME_ID:
+ if (((PUCHAR)LookAheadBuffer)[2] != 0x03) {
+ OdiLookAhead.LkAhd_PktAttr = 0x40000000;
+ } else {
+ if (((PUCHAR)LookAheadBuffer)[0] != ((PUCHAR)LookAheadBuffer)[1]) {
+ OdiLookAhead.LkAhd_PktAttr = 0x20000000;
+ } else {
+ OdiLookAhead.LkAhd_PktAttr = 0x0;
+ }
+ }
+ break;
+
+ default:
+ OdiLookAhead.LkAhd_PktAttr = 0x20;
+ break;
+
+ }
+
+
+ //
+ // Update SR info
+ //
+ if (OdiLookAhead.LkAhd_ImmediateAddress[0] & 0x80) {
+
+ //
+ // Yes
+ //
+ if (Mlid->ConfigTable.MLIDCFG_SourceRouting != NULL) {
+
+ //
+ // Call function
+ //*\\ here - Update SR Info. Are parameters correct?
+ (*((PLSL_SR_FUNCTION)(Mlid->ConfigTable.MLIDCFG_SourceRouting)))
+ ( Mlid->BoardNumber,
+ OdiLookAhead.LkAhd_MediaHeaderPtr + 14,
+ OdiLookAhead.LkAhd_ImmediateAddress
+ );
+
+
+ }
+
+ }
+
+ ReceiveSetDestinationType(Mlid, &OdiLookAhead);
+
+ if (OdiLookAhead.LkAhd_DestType & 0x1) {
+ (*((PUINT32)((*(Mlid->StatsTable->StatsTable.MGenericCountsPtr))[11].StatCounter)))++; // MTotalGroupAddrRxCount
+ }
+ (*((PUINT32)((*(Mlid->StatsTable->StatsTable.MGenericCountsPtr))[1].StatCounter)))++; // MTotalRxPacketCount
+
+IndicatePacket:
+
+ Statistic = ((PUINT64)((*(Mlid->StatsTable->StatsTable.MGenericCountsPtr))[8].StatCounter)); // MTotalTxOKByteCount;
+ if (((UINT32)0xFFFFFFFF - Statistic->Low_UINT32) < PacketSize) {
+ Statistic->High_UINT32++;
+ }
+ Statistic->Low_UINT32 += PacketSize;
+
+ NdisReleaseSpinLock(&(Mlid->MlidSpinLock));
+
+ //
+ // CLSL_GetStackECB to obtain and ECB for this packet
+ //
+ ReceiveECB = (*((PECB (*) (PLOOKAHEAD))
+ (Mlid->LSLFunctionList->SupportAPIArray[GetStackECB_INDEX])))(
+ &OdiLookAhead
+ );
+
+
+ if (ReceiveECB == NULL) {
+
+ (*((PUINT32)((*(Mlid->StatsTable->StatsTable.MGenericCountsPtr))[2].StatCounter)))++; // MNoECBAvailableCount
+
+ return(NDIS_STATUS_SUCCESS);
+
+ }
+
+ NdisAcquireSpinLock(&(Mlid->MlidSpinLock));
+
+ //
+ // Get an NDIS_PACKET
+ //
+ NdisAllocatePacket(
+ &NdisStatus,
+ &NdisReceivePacket,
+ Mlid->ReceivePacketPool
+ );
+
+ if (NdisStatus != NDIS_STATUS_SUCCESS) {
+
+ //
+ // Fail ECB and return it
+ //
+
+ (*((PUINT32)((*(Mlid->StatsTable->StatsTable.MGenericCountsPtr))[2].StatCounter)))++; // MNoECBAvailableCount
+
+ NdisReleaseSpinLock(&(Mlid->MlidSpinLock));
+
+ ReceiveECB->ECB_Status = (UINT16)OUT_OF_RESOURCES;
+
+ //
+ // Call CLSL_FastHoldEvent
+ //
+ (*(Mlid->LSLFunctionList->SupportAPIArray[FastHoldEvent_INDEX]))(
+ ReceiveECB
+ );
+
+ //
+ // Call Service Events
+ //
+ (*(Mlid->LSLFunctionList->SupportAPIArray[ServiceEvents_INDEX]))(
+ );
+
+ return(NDIS_STATUS_SUCCESS);
+
+ }
+
+ //
+ // Convert ECB fragment list into an NDIS_BUFFER chain
+ //
+ if (BuildReceiveBufferChain(Mlid, NdisReceivePacket, ReceiveECB) !=
+ NDIS_STATUS_SUCCESS) {
+
+ //
+ // Return resources
+ //
+
+ NdisFreePacket(NdisReceivePacket);
+
+ //
+ // Fail ECB and return it
+ //
+
+ (*((PUINT32)((*(Mlid->StatsTable->StatsTable.MGenericCountsPtr))[2].StatCounter)))++; // MNoECBAvailableCount
+
+ NdisReleaseSpinLock(&(Mlid->MlidSpinLock));
+
+ ReceiveECB->ECB_Status = (UINT16)OUT_OF_RESOURCES;
+
+ //
+ // Call CLSL_FastHoldEvent
+ //
+ (*(Mlid->LSLFunctionList->SupportAPIArray[FastHoldEvent_INDEX]))(
+ ReceiveECB
+ );
+
+ //
+ // Call Service Events
+ //
+ (*(Mlid->LSLFunctionList->SupportAPIArray[ServiceEvents_INDEX]))(
+ );
+
+ return(NDIS_STATUS_SUCCESS);
+
+ }
+
+ //
+ // Store ECB info into packet header
+ //
+ Reserved = PMLID_RESERVED_FROM_PNDIS_PACKET(NdisReceivePacket);
+ Reserved->SendECB = ReceiveECB;
+
+ NdisReleaseSpinLock(&(Mlid->MlidSpinLock));
+
+ //
+ // Call NdisTransferData on ECB, if one exists
+ //
+ NdisTransferData(
+ &NdisStatus,
+ Mlid->NdisBindingHandle,
+ MacReceiveContext,
+ OdiLookAhead.LkAhd_FrameDataStartCopyOffset + MlidHeaderSize,
+ OdiLookAhead.LkAhd_FrameDataBytesWanted - MlidHeaderSize,
+ NdisReceivePacket,
+ &NdisBytesCopied
+ );
+
+ //
+ // If it pended, return
+ //
+ if (NdisStatus == NDIS_STATUS_PENDING) {
+
+ return(NDIS_STATUS_SUCCESS);
+
+ }
+
+ //
+ // Store Status
+ //
+ if (NdisStatus == NDIS_STATUS_SUCCESS) {
+
+ ReceiveECB->ECB_Status = (UINT16)SUCCESSFUL;
+
+ } else {
+
+ ReceiveECB->ECB_Status = (UINT16)FAIL;
+
+ }
+
+ //
+ // Release Resources
+ //
+ NdisAcquireSpinLock(&(Mlid->MlidSpinLock));
+
+ //
+ // Unchain all NDIS_BUFFERs from packet
+ //
+
+ NdisUnchainBufferAtFront(
+ NdisReceivePacket,
+ &NdisBuffer
+ );
+
+ while (NdisBuffer != NULL) {
+
+ NdisFreeBuffer(NdisBuffer);
+
+ NdisUnchainBufferAtFront(
+ NdisReceivePacket,
+ &NdisBuffer
+ );
+
+ }
+
+ NdisFreePacket(NdisReceivePacket);
+
+ NdisReleaseSpinLock(&(Mlid->MlidSpinLock));
+
+ //
+ // Call CLSL_FastHoldEvent
+ //
+ (*(Mlid->LSLFunctionList->SupportAPIArray[FastHoldEvent_INDEX]))(
+ ReceiveECB
+ );
+
+ //
+ // Call Service Events
+ //
+ (*(Mlid->LSLFunctionList->SupportAPIArray[ServiceEvents_INDEX]))(
+ );
+
+ return(NDIS_STATUS_SUCCESS);
+
+}
+
+VOID
+NdisMlidReceiveComplete(
+ IN NDIS_HANDLE ProtocolBindingContext
+ )
+
+/*++
+
+Routine Description:
+
+ Marks the completion of receives from the NDIS_MAC.
+
+Arguments:
+
+ ProtocolBindingContext - Pointer to the MLID_STRUCT that is changing.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ return;
+}
+
+VOID
+NdisMlidStatus(
+ IN NDIS_HANDLE ProtocolBindingContext,
+ IN NDIS_STATUS GeneralStatus,
+ IN PVOID StatusBuffer,
+ IN UINT StatusBufferSize
+ )
+
+/*++
+
+Routine Description:
+
+ This routine is called to indicate status changes in the NDIS_MAC.
+
+Arguments:
+
+ ProtocolBindingContext - Pointer to the MLID_STRUCT that is changing.
+
+ GeneralStatus - NDIS_STATUS that is being indicated.
+
+ StatusBuffer - A buffer containing more information.
+
+ StatusBufferSize - Size of the buffer.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ PMLID_STRUCT Mlid = (PMLID_STRUCT)ProtocolBindingContext;
+ UINT32 RingStatus;
+ UINT32 RingValue;
+
+ //
+ // Switch on status
+ //
+ switch (GeneralStatus) {
+
+ //
+ // NDIS_STATUS_CLOSED
+ // For the MLID call CLSL_DeRegisterMLID
+ // Set closed flag
+ //
+
+ case NDIS_STATUS_CLOSED:
+
+ //
+ // Call DeregisterMlid
+ //
+ (*(Mlid->LSLFunctionList->SupportAPIArray[DeRegisterMLID_INDEX]))(
+ Mlid->BoardNumber
+ );
+
+ //
+ // Set a flag to stop all processing
+ //
+ Mlid->Unloading = TRUE;
+
+ break;
+
+ case NDIS_STATUS_RING_STATUS:
+
+ //
+ // NDIS_STATUS_RING_STATUS
+ // Store new ring status in MLID_ConfigTable.
+ //
+ if (StatusBufferSize != sizeof(UINT32)) {
+
+ break;
+
+ }
+
+ RingStatus = *((UNALIGNED UINT32 *)(StatusBuffer));
+ RingValue = 0;
+
+ if (RingStatus & NDIS_RING_SIGNAL_LOSS) {
+ RingValue |= 0x8000;
+ }
+
+ if (RingStatus & NDIS_RING_HARD_ERROR) {
+ RingValue |= 0x4000;
+ }
+
+ if (RingStatus & NDIS_RING_SOFT_ERROR) {
+ RingValue |= 0x2000;
+ }
+
+ if (RingStatus & NDIS_RING_TRANSMIT_BEACON) {
+ RingValue |= 0x1000;
+ }
+
+ if (RingStatus & NDIS_RING_LOBE_WIRE_FAULT) {
+ RingValue |= 0x0800;
+ }
+
+ if (RingStatus & NDIS_RING_AUTO_REMOVAL_ERROR) {
+ RingValue |= 0x0400;
+ }
+
+ if (RingStatus & NDIS_RING_REMOVE_RECEIVED) {
+ RingValue |= 0x0100;
+ }
+
+ if (RingStatus & NDIS_RING_COUNTER_OVERFLOW) {
+ RingValue |= 0x0080;
+ }
+
+ if (RingStatus & NDIS_RING_SINGLE_STATION) {
+ RingValue |= 0x0040;
+ }
+
+ if (RingStatus & NDIS_RING_RING_RECOVERY) {
+ RingValue |= 0x0020;
+ }
+
+ NdisAcquireSpinLock(&(Mlid->MlidSpinLock));
+
+ *((PUINT32)((*(Mlid->StatsTable->StatsTable.MMediaCountsPtr))[11].StatCounter)) =
+ RingValue;
+
+ NdisReleaseSpinLock(&(Mlid->MlidSpinLock));
+
+ break;
+
+ }
+
+}
+
+VOID
+NdisMlidStatusComplete(
+ IN NDIS_HANDLE ProtocolBindingContext
+ )
+
+/*++
+
+Routine Description:
+
+ Marks the completion of any state previously indicated.
+
+Arguments:
+
+ ProtocolBindingContext - Pointer to the MLID_STRUCT that is changing.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ return;
+}
+