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.
 
 
 
 
 
 

1183 lines
26 KiB

/*++
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;
}