2086 lines
42 KiB
C
2086 lines
42 KiB
C
|
/*++
|
|||
|
|
|||
|
Copyright (c) 1990 Microsoft Corporation
|
|||
|
|
|||
|
Module Name:
|
|||
|
|
|||
|
lslmlid.c
|
|||
|
|
|||
|
Abstract:
|
|||
|
|
|||
|
This file contains all the MLID interface routines to the LSL
|
|||
|
|
|||
|
Author:
|
|||
|
|
|||
|
Sean Selitrennikoff (SeanSe) 3-8-93
|
|||
|
|
|||
|
Environment:
|
|||
|
|
|||
|
Kernel Mode.
|
|||
|
|
|||
|
Revision History:
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
#include <ndis.h>
|
|||
|
#include "lsl.h"
|
|||
|
#include "frames.h"
|
|||
|
#include "lslmlid.h"
|
|||
|
#include "mlid.h"
|
|||
|
|
|||
|
|
|||
|
//
|
|||
|
// A global which has pointers to the functions in this file. Used for registering
|
|||
|
// with the LSL.
|
|||
|
//
|
|||
|
INFO_BLOCK
|
|||
|
NdisMlidInfoBlock = {
|
|||
|
0xE,
|
|||
|
{
|
|||
|
GetMLIDConfiguration,
|
|||
|
GetMLIDStatistics,
|
|||
|
AddMulticastAddress,
|
|||
|
DeleteMulticastAddress,
|
|||
|
NULL,
|
|||
|
MLIDShutdown,
|
|||
|
MLIDReset,
|
|||
|
NULL,
|
|||
|
NULL,
|
|||
|
SetLookAheadSize,
|
|||
|
PromiscuousChange,
|
|||
|
NULL,
|
|||
|
NULL,
|
|||
|
MLIDManagement
|
|||
|
}
|
|||
|
};
|
|||
|
|
|||
|
MLID_Reg
|
|||
|
NdisMlidHandlerInfo = {
|
|||
|
MLIDSendHandler,
|
|||
|
&NdisMlidInfoBlock
|
|||
|
};
|
|||
|
|
|||
|
|
|||
|
|
|||
|
UINT32
|
|||
|
BuildNewMulticastList(
|
|||
|
PMLID_STRUCT Mlid,
|
|||
|
PUINT8 AddMulticastAddr
|
|||
|
);
|
|||
|
|
|||
|
UINT32
|
|||
|
BuildNewFunctionalAddr(
|
|||
|
PMLID_STRUCT Mlid,
|
|||
|
PUINT8 AddFunctionalAddr
|
|||
|
);
|
|||
|
|
|||
|
|
|||
|
UINT32
|
|||
|
RemoveFromMulticastList(
|
|||
|
PMLID_STRUCT Mlid,
|
|||
|
PUINT8 DelMulticastAddr
|
|||
|
);
|
|||
|
|
|||
|
UINT32
|
|||
|
RemoveFromFunctionalAddr(
|
|||
|
PMLID_STRUCT Mlid,
|
|||
|
PUINT8 DelFunctionalAddr
|
|||
|
);
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
PMLID_ConfigTable
|
|||
|
GetMLIDConfiguration(
|
|||
|
UINT32 BoardNumber
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Returns a pointer to the MLIDs configuration table for the specified logical
|
|||
|
board. This commnand is supported by all MLIDs. A separate configuration
|
|||
|
table is maintained by the MLID for each adapter/frame-type combination.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
BoardNumber - The board number.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
PMLID_ConfigTable - A pointer to tyhe MLIDs configuration table.
|
|||
|
NULL - Reports the BAD_PARAMETER condition, MLID does not exist.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
UINT32 i;
|
|||
|
PMLID_ConfigTable ConfigTable;
|
|||
|
|
|||
|
NdisAcquireSpinLock(&NdisMlidSpinLock);
|
|||
|
|
|||
|
//
|
|||
|
// Verify that BoardNumber is in valid range
|
|||
|
//
|
|||
|
|
|||
|
for (i =0 ; i < AllocatedMlidBoards; i++) {
|
|||
|
|
|||
|
if (MlidBoards[i].BoardNumber == BoardNumber) {
|
|||
|
|
|||
|
break;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
if (i == AllocatedMlidBoards) {
|
|||
|
|
|||
|
NdisReleaseSpinLock(&NdisMlidSpinLock);
|
|||
|
|
|||
|
return(NULL);
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// If BoardNumber is not open, fail.
|
|||
|
//
|
|||
|
|
|||
|
if (MlidBoards[i].Mlid == NULL) {
|
|||
|
|
|||
|
NdisReleaseSpinLock(&NdisMlidSpinLock);
|
|||
|
|
|||
|
return(NULL);
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// If Board is unloading - fail
|
|||
|
//
|
|||
|
if (MlidBoards[i].Mlid->Unloading) {
|
|||
|
|
|||
|
NdisReleaseSpinLock(&NdisMlidSpinLock);
|
|||
|
|
|||
|
return(NULL);
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// return pointer to configuration table.
|
|||
|
//
|
|||
|
|
|||
|
ConfigTable = &(MlidBoards[i].Mlid->ConfigTable);
|
|||
|
|
|||
|
NdisReleaseSpinLock(&NdisMlidSpinLock);
|
|||
|
|
|||
|
return(ConfigTable);
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
PMLID_StatsTable
|
|||
|
GetMLIDStatistics(
|
|||
|
UINT32 BoardNumber
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Returns a pointer to the MLIDs statistics table for the specified board. All
|
|||
|
MLIDs support this command. The MLID maintains one statistics table for each
|
|||
|
physical adapter. Each frame-type (or logical board) present for that physical
|
|||
|
adapter uses the same table. The board number can be any of the logical
|
|||
|
board values present for the physical adapter. Regardless of the logical
|
|||
|
board number, GetMLIDStatistics will return the same table.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
BoardNumber - The board number.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
PMLID_Statistics - A pointer to the MLIDs Statistics Table.
|
|||
|
|
|||
|
NULL - Reports the BAD_PARAMETER condition.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
UINT32 i;
|
|||
|
PMLID_StatsTable StatsTable;
|
|||
|
|
|||
|
NdisAcquireSpinLock(&NdisMlidSpinLock);
|
|||
|
|
|||
|
//
|
|||
|
// Verify that BoardNumber is in valid range
|
|||
|
//
|
|||
|
|
|||
|
for (i =0 ; i < AllocatedMlidBoards; i++) {
|
|||
|
|
|||
|
if (MlidBoards[i].BoardNumber == BoardNumber) {
|
|||
|
|
|||
|
break;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
if (i == AllocatedMlidBoards) {
|
|||
|
|
|||
|
NdisReleaseSpinLock(&NdisMlidSpinLock);
|
|||
|
|
|||
|
return(NULL);
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// If BoardNumber is not open, fail.
|
|||
|
//
|
|||
|
|
|||
|
if (MlidBoards[i].Mlid == NULL) {
|
|||
|
|
|||
|
NdisReleaseSpinLock(&NdisMlidSpinLock);
|
|||
|
|
|||
|
return(NULL);
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// If Board is unloading - fail
|
|||
|
//
|
|||
|
if (MlidBoards[i].Mlid->Unloading) {
|
|||
|
|
|||
|
NdisReleaseSpinLock(&NdisMlidSpinLock);
|
|||
|
|
|||
|
return(NULL);
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// return pointer to statistics table.
|
|||
|
//
|
|||
|
|
|||
|
StatsTable = &(MlidBoards[i].Mlid->StatsTable->StatsTable);
|
|||
|
|
|||
|
NdisReleaseSpinLock(&NdisMlidSpinLock);
|
|||
|
|
|||
|
return(StatsTable);
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
UINT32
|
|||
|
AddMulticastAddress(
|
|||
|
UINT32 BoardNumber,
|
|||
|
PUINT8 AddMulticastAddr
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
The MLID manages enabled multicast addresses according to the physical adapter.
|
|||
|
The format of the multicast address is LAN medium dependent. This routine
|
|||
|
allows a protocol to add a single multicast address.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
BoardNumber - The board number.
|
|||
|
|
|||
|
AddMulticastAddr - A pointer to the multicast address to add.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
SUCCESSFUL - Success.
|
|||
|
OUT_OF_RESOURCES - The MLID has insufficient resources to enable the address.
|
|||
|
BAD_PARAMETER - The address is not valid for the MLIDs media type.
|
|||
|
BAD_COMMAND - Multicast addressing is not supported by the MLID.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
PMLID_STRUCT Mlid;
|
|||
|
UINT32 i;
|
|||
|
UINT32 Status;
|
|||
|
NDIS_STATUS NdisStatus;
|
|||
|
PNDIS_REQUEST NdisMlidRequest;
|
|||
|
|
|||
|
NdisAcquireSpinLock(&NdisMlidSpinLock);
|
|||
|
|
|||
|
//
|
|||
|
// Verify that BoardNumber is in valid range
|
|||
|
//
|
|||
|
|
|||
|
for (i =0 ; i < AllocatedMlidBoards; i++) {
|
|||
|
|
|||
|
if (MlidBoards[i].BoardNumber == BoardNumber) {
|
|||
|
|
|||
|
break;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
if (i == AllocatedMlidBoards) {
|
|||
|
|
|||
|
NdisReleaseSpinLock(&NdisMlidSpinLock);
|
|||
|
|
|||
|
return(BAD_PARAMETER);
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// If BoardNumber is not open, fail.
|
|||
|
//
|
|||
|
|
|||
|
if (MlidBoards[i].Mlid == NULL) {
|
|||
|
|
|||
|
NdisReleaseSpinLock(&NdisMlidSpinLock);
|
|||
|
|
|||
|
return(BAD_PARAMETER);
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// If Board is unloading - fail
|
|||
|
//
|
|||
|
if (MlidBoards[i].Mlid->Unloading) {
|
|||
|
|
|||
|
NdisReleaseSpinLock(&NdisMlidSpinLock);
|
|||
|
|
|||
|
return(BAD_PARAMETER);
|
|||
|
}
|
|||
|
|
|||
|
Mlid = MlidBoards[i].Mlid;
|
|||
|
|
|||
|
NdisAcquireSpinLock(&(Mlid->MlidSpinLock));
|
|||
|
|
|||
|
NdisReleaseSpinLock(&NdisMlidSpinLock);
|
|||
|
|
|||
|
switch (Mlid->NdisMlidMedium) {
|
|||
|
|
|||
|
case NdisMedium802_3:
|
|||
|
Status = BuildNewMulticastList(Mlid, AddMulticastAddr);
|
|||
|
break;
|
|||
|
|
|||
|
case NdisMedium802_5:
|
|||
|
Status = BuildNewFunctionalAddr(Mlid, AddMulticastAddr);
|
|||
|
break;
|
|||
|
|
|||
|
case NdisMediumFddi:
|
|||
|
Status = BuildNewMulticastList(Mlid, AddMulticastAddr);
|
|||
|
break;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
if (Status == DUPLICATE_ENTRY) {
|
|||
|
|
|||
|
//
|
|||
|
// The address already existed, return success
|
|||
|
//
|
|||
|
|
|||
|
NdisReleaseSpinLock(&(Mlid->MlidSpinLock));
|
|||
|
return(SUCCESSFUL);
|
|||
|
}
|
|||
|
|
|||
|
if (Status != SUCCESSFUL) {
|
|||
|
|
|||
|
//
|
|||
|
// return error message -- most likely, OUT_OF_RESOURCES
|
|||
|
//
|
|||
|
NdisReleaseSpinLock(&(Mlid->MlidSpinLock));
|
|||
|
return(Status);
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Allocate NDIS_REQUEST
|
|||
|
//
|
|||
|
NdisMlidRequest = (PNDIS_REQUEST)ExAllocatePool(NonPagedPool, sizeof(NDIS_REQUEST));
|
|||
|
|
|||
|
if (NdisMlidRequest == NULL) {
|
|||
|
|
|||
|
NdisReleaseSpinLock(&(Mlid->MlidSpinLock));
|
|||
|
return(OUT_OF_RESOURCES);
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Build an NDIS request
|
|||
|
//
|
|||
|
NdisMlidRequest->RequestType = NdisRequestSetInformation;
|
|||
|
|
|||
|
switch (Mlid->NdisMlidMedium) {
|
|||
|
|
|||
|
case NdisMedium802_3:
|
|||
|
NdisMlidRequest->DATA.SET_INFORMATION.Oid = OID_802_3_MULTICAST_LIST;
|
|||
|
NdisMlidRequest->DATA.SET_INFORMATION.InformationBuffer = (PVOID)(Mlid->MulticastAddresses.Addresses);
|
|||
|
NdisMlidRequest->DATA.SET_INFORMATION.InformationBufferLength =
|
|||
|
Mlid->MulticastAddresses.MACount * 6;
|
|||
|
break;
|
|||
|
|
|||
|
case NdisMedium802_5:
|
|||
|
NdisMlidRequest->DATA.SET_INFORMATION.Oid = OID_802_5_CURRENT_FUNCTIONAL;
|
|||
|
NdisMlidRequest->DATA.SET_INFORMATION.InformationBuffer = (PVOID)&(Mlid->MulticastAddresses.FunctionalAddr);
|
|||
|
NdisMlidRequest->DATA.SET_INFORMATION.InformationBufferLength = 4;
|
|||
|
break;
|
|||
|
|
|||
|
case NdisMediumFddi:
|
|||
|
NdisMlidRequest->DATA.SET_INFORMATION.Oid = OID_FDDI_LONG_MULTICAST_LIST;
|
|||
|
NdisMlidRequest->DATA.SET_INFORMATION.InformationBuffer = (PVOID)(Mlid->MulticastAddresses.Addresses);
|
|||
|
NdisMlidRequest->DATA.SET_INFORMATION.InformationBufferLength =
|
|||
|
Mlid->MulticastAddresses.MACount * 6;
|
|||
|
break;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
NdisMlidRequest->DATA.SET_INFORMATION.BytesRead = 0;
|
|||
|
NdisMlidRequest->DATA.SET_INFORMATION.BytesNeeded = 0;
|
|||
|
|
|||
|
Mlid->RequestStatus = NDIS_STATUS_PENDING;
|
|||
|
|
|||
|
//
|
|||
|
// Release spin lock
|
|||
|
//
|
|||
|
NdisReleaseSpinLock(&(Mlid->MlidSpinLock));
|
|||
|
|
|||
|
//
|
|||
|
// Submit NDIS request
|
|||
|
//
|
|||
|
|
|||
|
NdisRequest(
|
|||
|
&NdisStatus,
|
|||
|
Mlid->NdisBindingHandle,
|
|||
|
NdisMlidRequest
|
|||
|
);
|
|||
|
|
|||
|
//
|
|||
|
// If it pended, see if it completed already.
|
|||
|
//
|
|||
|
if (NdisStatus == NDIS_STATUS_PENDING) {
|
|||
|
|
|||
|
if ((NDIS_STATUS)Mlid->RequestStatus == NDIS_STATUS_PENDING) {
|
|||
|
|
|||
|
//
|
|||
|
// Assume it will complete successfully
|
|||
|
//
|
|||
|
NdisStatus = NDIS_STATUS_SUCCESS;
|
|||
|
|
|||
|
} else {
|
|||
|
|
|||
|
NdisStatus = (NDIS_STATUS)Mlid->RequestStatus;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
} else {
|
|||
|
|
|||
|
//
|
|||
|
// Free NDIS_REQUEST
|
|||
|
//
|
|||
|
ExFreePool(NdisMlidRequest);
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// return status
|
|||
|
//
|
|||
|
|
|||
|
if (NdisStatus == NDIS_STATUS_SUCCESS) {
|
|||
|
|
|||
|
return(SUCCESSFUL);
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
NdisAcquireSpinLock(&(Mlid->MlidSpinLock));
|
|||
|
|
|||
|
//
|
|||
|
// Remove the address - error
|
|||
|
//
|
|||
|
|
|||
|
switch (Mlid->NdisMlidMedium) {
|
|||
|
|
|||
|
case NdisMedium802_3:
|
|||
|
Status = RemoveFromMulticastList(Mlid, AddMulticastAddr);
|
|||
|
break;
|
|||
|
|
|||
|
case NdisMedium802_5:
|
|||
|
Status = RemoveFromFunctionalAddr(Mlid, AddMulticastAddr);
|
|||
|
break;
|
|||
|
|
|||
|
case NdisMediumFddi:
|
|||
|
Status = RemoveFromMulticastList(Mlid, AddMulticastAddr);
|
|||
|
break;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
NdisReleaseSpinLock(&(Mlid->MlidSpinLock));
|
|||
|
|
|||
|
if (NdisStatus == NDIS_STATUS_RESOURCES) {
|
|||
|
|
|||
|
return(OUT_OF_RESOURCES);
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
return(BAD_PARAMETER);
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
UINT32
|
|||
|
DeleteMulticastAddress(
|
|||
|
UINT32 BoardNumber,
|
|||
|
PUINT8 DelMulticastAddr
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Disables the reception of a previously enabled multicast address.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
BoardNumber - The board number.
|
|||
|
|
|||
|
DelMulticastAddr - The address to remove/disable.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
SUCCESSFUL - Success.
|
|||
|
ITEM_NOT_PRESENT - The specified address is not enabled for the MLID.
|
|||
|
BAD_PARAMETER - The address is not valid for the MLIDs media type.
|
|||
|
BAD_COMMAND - Multicast addressing is not supported by the MLID.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
PMLID_STRUCT Mlid;
|
|||
|
UINT32 i;
|
|||
|
UINT32 Status;
|
|||
|
NDIS_STATUS NdisStatus;
|
|||
|
PNDIS_REQUEST NdisMlidRequest;
|
|||
|
|
|||
|
NdisAcquireSpinLock(&NdisMlidSpinLock);
|
|||
|
|
|||
|
//
|
|||
|
// Verify that BoardNumber is in valid range
|
|||
|
//
|
|||
|
|
|||
|
for (i =0 ; i < AllocatedMlidBoards; i++) {
|
|||
|
|
|||
|
if (MlidBoards[i].BoardNumber == BoardNumber) {
|
|||
|
|
|||
|
break;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
if (i == AllocatedMlidBoards) {
|
|||
|
|
|||
|
NdisReleaseSpinLock(&NdisMlidSpinLock);
|
|||
|
|
|||
|
return(BAD_PARAMETER);
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// If BoardNumber is not open, fail.
|
|||
|
//
|
|||
|
|
|||
|
if (MlidBoards[i].Mlid == NULL) {
|
|||
|
|
|||
|
NdisReleaseSpinLock(&NdisMlidSpinLock);
|
|||
|
|
|||
|
return(BAD_PARAMETER);
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// If Board is unloading - fail
|
|||
|
//
|
|||
|
if (MlidBoards[i].Mlid->Unloading) {
|
|||
|
|
|||
|
NdisReleaseSpinLock(&NdisMlidSpinLock);
|
|||
|
|
|||
|
return(BAD_PARAMETER);
|
|||
|
}
|
|||
|
|
|||
|
Mlid = MlidBoards[i].Mlid;
|
|||
|
|
|||
|
NdisAcquireSpinLock(&(Mlid->MlidSpinLock));
|
|||
|
|
|||
|
NdisReleaseSpinLock(&NdisMlidSpinLock);
|
|||
|
|
|||
|
switch (Mlid->NdisMlidMedium) {
|
|||
|
|
|||
|
case NdisMedium802_3:
|
|||
|
Status = RemoveFromMulticastList(Mlid, DelMulticastAddr);
|
|||
|
break;
|
|||
|
|
|||
|
case NdisMedium802_5:
|
|||
|
Status = RemoveFromFunctionalAddr(Mlid, DelMulticastAddr);
|
|||
|
break;
|
|||
|
|
|||
|
case NdisMediumFddi:
|
|||
|
Status = RemoveFromMulticastList(Mlid, DelMulticastAddr);
|
|||
|
break;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
if (Status == DUPLICATE_ENTRY) {
|
|||
|
|
|||
|
//
|
|||
|
// The address still exists, return success
|
|||
|
//
|
|||
|
|
|||
|
NdisReleaseSpinLock(&(Mlid->MlidSpinLock));
|
|||
|
return(SUCCESSFUL);
|
|||
|
}
|
|||
|
|
|||
|
if (Status != SUCCESSFUL) {
|
|||
|
|
|||
|
//
|
|||
|
// return error message -- most likely, ITEM_NOT_PRESENT
|
|||
|
//
|
|||
|
NdisReleaseSpinLock(&(Mlid->MlidSpinLock));
|
|||
|
return(Status);
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Allocate NDIS_REQUEST
|
|||
|
//
|
|||
|
NdisMlidRequest = (PNDIS_REQUEST)ExAllocatePool(NonPagedPool, sizeof(NDIS_REQUEST));
|
|||
|
|
|||
|
if (NdisMlidRequest == NULL) {
|
|||
|
|
|||
|
NdisReleaseSpinLock(&(Mlid->MlidSpinLock));
|
|||
|
return(OUT_OF_RESOURCES);
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
//
|
|||
|
// Build an NDIS request
|
|||
|
//
|
|||
|
NdisMlidRequest->RequestType = NdisRequestSetInformation;
|
|||
|
|
|||
|
switch (Mlid->NdisMlidMedium) {
|
|||
|
|
|||
|
case NdisMedium802_3:
|
|||
|
NdisMlidRequest->DATA.SET_INFORMATION.Oid = OID_802_3_MULTICAST_LIST;
|
|||
|
NdisMlidRequest->DATA.SET_INFORMATION.InformationBuffer = (PVOID)(Mlid->MulticastAddresses.Addresses);
|
|||
|
NdisMlidRequest->DATA.SET_INFORMATION.InformationBufferLength =
|
|||
|
Mlid->MulticastAddresses.MACount * 6;
|
|||
|
break;
|
|||
|
|
|||
|
case NdisMedium802_5:
|
|||
|
NdisMlidRequest->DATA.SET_INFORMATION.Oid = OID_802_5_CURRENT_FUNCTIONAL;
|
|||
|
NdisMlidRequest->DATA.SET_INFORMATION.InformationBuffer = (PVOID)&(Mlid->MulticastAddresses.FunctionalAddr);
|
|||
|
NdisMlidRequest->DATA.SET_INFORMATION.InformationBufferLength = 4;
|
|||
|
break;
|
|||
|
|
|||
|
case NdisMediumFddi:
|
|||
|
NdisMlidRequest->DATA.SET_INFORMATION.Oid = OID_FDDI_LONG_MULTICAST_LIST;
|
|||
|
NdisMlidRequest->DATA.SET_INFORMATION.InformationBuffer = (PVOID)(Mlid->MulticastAddresses.Addresses);
|
|||
|
NdisMlidRequest->DATA.SET_INFORMATION.InformationBufferLength =
|
|||
|
Mlid->MulticastAddresses.MACount * 6;
|
|||
|
break;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
NdisMlidRequest->DATA.SET_INFORMATION.BytesRead = 0;
|
|||
|
NdisMlidRequest->DATA.SET_INFORMATION.BytesNeeded = 0;
|
|||
|
|
|||
|
Mlid->RequestStatus = NDIS_STATUS_PENDING;
|
|||
|
|
|||
|
//
|
|||
|
// Release spin lock
|
|||
|
//
|
|||
|
NdisReleaseSpinLock(&(Mlid->MlidSpinLock));
|
|||
|
|
|||
|
//
|
|||
|
// Submit NDIS request
|
|||
|
//
|
|||
|
|
|||
|
NdisRequest(
|
|||
|
&NdisStatus,
|
|||
|
Mlid->NdisBindingHandle,
|
|||
|
NdisMlidRequest
|
|||
|
);
|
|||
|
|
|||
|
//
|
|||
|
// If it pended, see if it completed already.
|
|||
|
//
|
|||
|
if (NdisStatus == NDIS_STATUS_PENDING) {
|
|||
|
|
|||
|
if ((NDIS_STATUS)Mlid->RequestStatus == NDIS_STATUS_PENDING) {
|
|||
|
|
|||
|
//
|
|||
|
// Assume it will complete successfully
|
|||
|
//
|
|||
|
NdisStatus = NDIS_STATUS_SUCCESS;
|
|||
|
|
|||
|
} else {
|
|||
|
|
|||
|
NdisStatus = (NDIS_STATUS)Mlid->RequestStatus;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
} else {
|
|||
|
|
|||
|
//
|
|||
|
// Free NDIS_REQUEST
|
|||
|
//
|
|||
|
ExFreePool(NdisMlidRequest);
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// return status
|
|||
|
//
|
|||
|
|
|||
|
if (NdisStatus == NDIS_STATUS_SUCCESS) {
|
|||
|
|
|||
|
return(SUCCESSFUL);
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Put the address back -- error
|
|||
|
//
|
|||
|
|
|||
|
NdisAcquireSpinLock(&(Mlid->MlidSpinLock));
|
|||
|
|
|||
|
switch (Mlid->NdisMlidMedium) {
|
|||
|
|
|||
|
case NdisMedium802_3:
|
|||
|
Status = BuildNewMulticastList(Mlid, DelMulticastAddr);
|
|||
|
break;
|
|||
|
|
|||
|
case NdisMedium802_5:
|
|||
|
Status = BuildNewFunctionalAddr(Mlid, DelMulticastAddr);
|
|||
|
break;
|
|||
|
|
|||
|
case NdisMediumFddi:
|
|||
|
Status = BuildNewMulticastList(Mlid, DelMulticastAddr);
|
|||
|
break;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
NdisReleaseSpinLock(&(Mlid->MlidSpinLock));
|
|||
|
|
|||
|
return(BAD_PARAMETER);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
UINT32
|
|||
|
MLIDShutdown(
|
|||
|
UINT32 BoardNumber,
|
|||
|
UINT32 ShutDownType
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Allows an application to shut down a physical adapter.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
BoardNumber - The board number.
|
|||
|
|
|||
|
ShutDownType - Form of shutdown desired: 0 == shutdown hardware and deregister
|
|||
|
from LSL, 0 != shutdown hardware only.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
SUCCESSFUL - Success.
|
|||
|
FAIL - Could not shutdown hardware.
|
|||
|
BAD_COMMAND - The MLID does not support this command.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
|
|||
|
//
|
|||
|
// Always return BAD_COMMAND. First, because it is easy. Second because
|
|||
|
// we cannot guarantee that the we know of all accesses to the NDIS MAC.
|
|||
|
//
|
|||
|
|
|||
|
return(BAD_COMMAND);
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
UINT32
|
|||
|
MLIDReset(
|
|||
|
UINT32 BoardNumber
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Causes the MLID to totally re-initialize the physical adapter. Leaves any
|
|||
|
multicast addresses that were previously enabled.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
BoardNumber - The board number.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
SUCCESSFUL - Success.
|
|||
|
FAIL - The MLID was unable to reset its hardware.
|
|||
|
BAD_COMMAND - The MLID does not support this command.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
PMLID_STRUCT Mlid;
|
|||
|
UINT32 i;
|
|||
|
NDIS_STATUS NdisStatus;
|
|||
|
|
|||
|
NdisAcquireSpinLock(&NdisMlidSpinLock);
|
|||
|
|
|||
|
//
|
|||
|
// Verify that BoardNumber is in valid range
|
|||
|
//
|
|||
|
|
|||
|
for (i =0 ; i < AllocatedMlidBoards; i++) {
|
|||
|
|
|||
|
if (MlidBoards[i].BoardNumber == BoardNumber) {
|
|||
|
|
|||
|
break;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
if (i == AllocatedMlidBoards) {
|
|||
|
|
|||
|
NdisReleaseSpinLock(&NdisMlidSpinLock);
|
|||
|
|
|||
|
return(FAIL);
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// If BoardNumber is not open, fail.
|
|||
|
//
|
|||
|
|
|||
|
if (MlidBoards[i].Mlid == NULL) {
|
|||
|
|
|||
|
NdisReleaseSpinLock(&NdisMlidSpinLock);
|
|||
|
|
|||
|
return(FAIL);
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// If Board is unloading - fail
|
|||
|
//
|
|||
|
if (MlidBoards[i].Mlid->Unloading) {
|
|||
|
|
|||
|
NdisReleaseSpinLock(&NdisMlidSpinLock);
|
|||
|
|
|||
|
return(FAIL);
|
|||
|
}
|
|||
|
|
|||
|
Mlid = MlidBoards[i].Mlid;
|
|||
|
|
|||
|
NdisAcquireSpinLock(&(Mlid->MlidSpinLock));
|
|||
|
|
|||
|
NdisReleaseSpinLock(&NdisMlidSpinLock);
|
|||
|
|
|||
|
//
|
|||
|
// Hack so that we will cancel all requests until the reset completes
|
|||
|
//
|
|||
|
Mlid->Unloading = TRUE;
|
|||
|
|
|||
|
(*((PUINT32)((*(Mlid->StatsTable->StatsTable.MGenericCountsPtr))[12].StatCounter)))++; // MAdapterResetCount
|
|||
|
|
|||
|
//
|
|||
|
// Time stamp the sucker
|
|||
|
//
|
|||
|
{
|
|||
|
LARGE_INTEGER TimeStamp;
|
|||
|
|
|||
|
KeQuerySystemTime(&TimeStamp);
|
|||
|
(*((PUINT32)((*(Mlid->StatsTable->StatsTable.MGenericCountsPtr))[13].StatCounter))) = // MAdapterOprTimeStamp
|
|||
|
TimeStamp.LowPart;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
//
|
|||
|
// Release spin lock
|
|||
|
//
|
|||
|
NdisReleaseSpinLock(&(Mlid->MlidSpinLock));
|
|||
|
|
|||
|
//
|
|||
|
// Call NdisReset
|
|||
|
//
|
|||
|
|
|||
|
NdisReset(
|
|||
|
&NdisStatus,
|
|||
|
Mlid->NdisBindingHandle
|
|||
|
);
|
|||
|
|
|||
|
//
|
|||
|
// If it pended, see if it completed already.
|
|||
|
//
|
|||
|
if (NdisStatus == NDIS_STATUS_PENDING) {
|
|||
|
|
|||
|
if ((NDIS_STATUS)Mlid->RequestStatus == NDIS_STATUS_PENDING) {
|
|||
|
|
|||
|
//
|
|||
|
// Assume it will complete successfully
|
|||
|
//
|
|||
|
NdisStatus = NDIS_STATUS_SUCCESS;
|
|||
|
|
|||
|
} else {
|
|||
|
|
|||
|
NdisAcquireSpinLock(&(Mlid->MlidSpinLock));
|
|||
|
|
|||
|
Mlid->Unloading = FALSE;
|
|||
|
|
|||
|
NdisReleaseSpinLock(&(Mlid->MlidSpinLock));
|
|||
|
|
|||
|
NdisStatus = (NDIS_STATUS)Mlid->RequestStatus;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
} else {
|
|||
|
|
|||
|
NdisAcquireSpinLock(&(Mlid->MlidSpinLock));
|
|||
|
|
|||
|
Mlid->Unloading = FALSE;
|
|||
|
|
|||
|
NdisReleaseSpinLock(&(Mlid->MlidSpinLock));
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// return status
|
|||
|
//
|
|||
|
if (NdisStatus == NDIS_STATUS_SUCCESS) {
|
|||
|
|
|||
|
return(SUCCESSFUL);
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
return(FAIL);
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
UINT32
|
|||
|
SetLookAheadSize(
|
|||
|
UINT32 BoardNumber,
|
|||
|
UINT32 RequestSize
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Tells the MLID the amount of look ahead data that is needed by the caller
|
|||
|
to properly process received packets.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
BoardNumber - The board number.
|
|||
|
|
|||
|
RequestedSize - Requested look ahead size in bytes.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
SUCCESSFUL - Success.
|
|||
|
BAD_PARAMETER - Requested look ahead size exceed bounds.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
PMLID_STRUCT Mlid;
|
|||
|
UINT32 i;
|
|||
|
UINT32 OldSize;
|
|||
|
NDIS_STATUS NdisStatus;
|
|||
|
PNDIS_REQUEST NdisMlidRequest;
|
|||
|
|
|||
|
//
|
|||
|
// Verify that the size is ok
|
|||
|
//
|
|||
|
|
|||
|
if (RequestSize > (256 - 40)) { // 40 is largest Media header size (TR SNAP w/ SR)
|
|||
|
|
|||
|
return(BAD_PARAMETER);
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
RequestSize += 40;
|
|||
|
|
|||
|
NdisAcquireSpinLock(&NdisMlidSpinLock);
|
|||
|
|
|||
|
//
|
|||
|
// Verify that BoardNumber is in valid range
|
|||
|
//
|
|||
|
|
|||
|
for (i =0 ; i < AllocatedMlidBoards; i++) {
|
|||
|
|
|||
|
if (MlidBoards[i].BoardNumber == BoardNumber) {
|
|||
|
|
|||
|
break;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
if (i == AllocatedMlidBoards) {
|
|||
|
|
|||
|
NdisReleaseSpinLock(&NdisMlidSpinLock);
|
|||
|
|
|||
|
return(BAD_PARAMETER);
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// If BoardNumber is not open, fail.
|
|||
|
//
|
|||
|
|
|||
|
if (MlidBoards[i].Mlid == NULL) {
|
|||
|
|
|||
|
NdisReleaseSpinLock(&NdisMlidSpinLock);
|
|||
|
|
|||
|
return(BAD_PARAMETER);
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// If Board is unloading - fail
|
|||
|
//
|
|||
|
if (MlidBoards[i].Mlid->Unloading) {
|
|||
|
|
|||
|
NdisReleaseSpinLock(&NdisMlidSpinLock);
|
|||
|
|
|||
|
return(BAD_PARAMETER);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
Mlid = MlidBoards[i].Mlid;
|
|||
|
|
|||
|
NdisAcquireSpinLock(&(Mlid->MlidSpinLock));
|
|||
|
|
|||
|
NdisReleaseSpinLock(&NdisMlidSpinLock);
|
|||
|
|
|||
|
//
|
|||
|
// Allocate NDIS_REQUEST
|
|||
|
//
|
|||
|
NdisMlidRequest = (PNDIS_REQUEST)ExAllocatePool(NonPagedPool, sizeof(NDIS_REQUEST));
|
|||
|
|
|||
|
if (NdisMlidRequest == NULL) {
|
|||
|
|
|||
|
NdisReleaseSpinLock(&(Mlid->MlidSpinLock));
|
|||
|
return(OUT_OF_RESOURCES);
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Store lookahead size
|
|||
|
//
|
|||
|
OldSize = Mlid->ConfigTable.MLIDCFG_LookAheadSize;
|
|||
|
Mlid->ConfigTable.MLIDCFG_LookAheadSize = RequestSize;
|
|||
|
|
|||
|
|
|||
|
//
|
|||
|
// Build an NDIS request
|
|||
|
//
|
|||
|
NdisMlidRequest->RequestType = NdisRequestSetInformation;
|
|||
|
|
|||
|
NdisMlidRequest->DATA.SET_INFORMATION.Oid = OID_GEN_MAXIMUM_LOOKAHEAD;
|
|||
|
NdisMlidRequest->DATA.SET_INFORMATION.InformationBuffer = (PVOID)&(Mlid->ConfigTable.MLIDCFG_LookAheadSize);
|
|||
|
NdisMlidRequest->DATA.SET_INFORMATION.InformationBufferLength = sizeof(UINT32);
|
|||
|
|
|||
|
NdisMlidRequest->DATA.SET_INFORMATION.BytesRead = 0;
|
|||
|
NdisMlidRequest->DATA.SET_INFORMATION.BytesNeeded = 0;
|
|||
|
|
|||
|
Mlid->RequestStatus = NDIS_STATUS_PENDING;
|
|||
|
|
|||
|
//
|
|||
|
// Release spin lock
|
|||
|
//
|
|||
|
NdisReleaseSpinLock(&(Mlid->MlidSpinLock));
|
|||
|
|
|||
|
//
|
|||
|
// Submit NDIS request
|
|||
|
//
|
|||
|
|
|||
|
NdisRequest(
|
|||
|
&NdisStatus,
|
|||
|
Mlid->NdisBindingHandle,
|
|||
|
NdisMlidRequest
|
|||
|
);
|
|||
|
|
|||
|
//
|
|||
|
// If it pended, see if it completed already.
|
|||
|
//
|
|||
|
if (NdisStatus == NDIS_STATUS_PENDING) {
|
|||
|
|
|||
|
if ((NDIS_STATUS)Mlid->RequestStatus == NDIS_STATUS_PENDING) {
|
|||
|
|
|||
|
//
|
|||
|
// Assume it will complete successfully
|
|||
|
//
|
|||
|
NdisStatus = NDIS_STATUS_SUCCESS;
|
|||
|
|
|||
|
} else {
|
|||
|
|
|||
|
NdisStatus = (NDIS_STATUS)Mlid->RequestStatus;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
} else {
|
|||
|
|
|||
|
//
|
|||
|
// Free NDIS_REQUEST
|
|||
|
//
|
|||
|
ExFreePool(NdisMlidRequest);
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// return status
|
|||
|
//
|
|||
|
|
|||
|
if (NdisStatus == NDIS_STATUS_SUCCESS) {
|
|||
|
|
|||
|
return(SUCCESSFUL);
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Restore old size
|
|||
|
//
|
|||
|
Mlid->ConfigTable.MLIDCFG_LookAheadSize = OldSize;
|
|||
|
|
|||
|
return(BAD_PARAMETER);
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
UINT32
|
|||
|
PromiscuousChange(
|
|||
|
UINT32 BoardNumber,
|
|||
|
UINT32 PromiscuousState,
|
|||
|
UINT32 PromiscuousMode
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Used to enable and disable promiscuous mode on the MLIDs adapter. A protocol
|
|||
|
stack can enable promiscuous mode multiple times without error; however, only
|
|||
|
the current call is in effect. If the LAN medium or adapter doees not distinquish
|
|||
|
between MAC and non-MAC frames, both frames are assumed for the PromiscuousMode
|
|||
|
mask.
|
|||
|
|
|||
|
The MLID keeps a counter for each promiscuous mode and disables only when the
|
|||
|
count reaches zero.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
BoardNumber - The board number.
|
|||
|
|
|||
|
PromiscuousState - If 0, then disables promiscuous mode, else enables promiscuous mode.
|
|||
|
|
|||
|
PromiscuousMode - Has the mask for what type of frames the MLID is to
|
|||
|
promiscuously receive. 0x1 - MAC Frames, 0x2 - Non-MAC Frames, 0x3 - Both.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
SUCCESSFUL - Success.
|
|||
|
BAD_COMMAND - Promiscuous mode is not supported by the MLID.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
PMLID_STRUCT Mlid;
|
|||
|
UINT32 i;
|
|||
|
UINT32 OldFilterValue;
|
|||
|
UINT32 OldCount;
|
|||
|
NDIS_STATUS NdisStatus;
|
|||
|
PNDIS_REQUEST NdisMlidRequest;
|
|||
|
|
|||
|
NdisAcquireSpinLock(&NdisMlidSpinLock);
|
|||
|
|
|||
|
//
|
|||
|
// Verify that BoardNumber is in valid range
|
|||
|
//
|
|||
|
|
|||
|
for (i =0 ; i < AllocatedMlidBoards; i++) {
|
|||
|
|
|||
|
if (MlidBoards[i].BoardNumber == BoardNumber) {
|
|||
|
|
|||
|
break;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
if (i == AllocatedMlidBoards) {
|
|||
|
|
|||
|
NdisReleaseSpinLock(&NdisMlidSpinLock);
|
|||
|
|
|||
|
return(BAD_PARAMETER);
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// If BoardNumber is not open, fail.
|
|||
|
//
|
|||
|
|
|||
|
if (MlidBoards[i].Mlid == NULL) {
|
|||
|
|
|||
|
NdisReleaseSpinLock(&NdisMlidSpinLock);
|
|||
|
|
|||
|
return(BAD_PARAMETER);
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// If Board is unloading - fail
|
|||
|
//
|
|||
|
if (MlidBoards[i].Mlid->Unloading) {
|
|||
|
|
|||
|
NdisReleaseSpinLock(&NdisMlidSpinLock);
|
|||
|
|
|||
|
return(BAD_PARAMETER);
|
|||
|
}
|
|||
|
|
|||
|
Mlid = MlidBoards[i].Mlid;
|
|||
|
|
|||
|
NdisAcquireSpinLock(&(Mlid->MlidSpinLock));
|
|||
|
|
|||
|
NdisReleaseSpinLock(&NdisMlidSpinLock);
|
|||
|
|
|||
|
//
|
|||
|
// If already enabled and we are to enable it, then increment counter and exit
|
|||
|
//
|
|||
|
if ((PromiscuousState != 0) &&
|
|||
|
(Mlid->PromiscuousModeEnables != 0)) {
|
|||
|
|
|||
|
Mlid->PromiscuousModeEnables++;
|
|||
|
NdisReleaseSpinLock(&(Mlid->MlidSpinLock));
|
|||
|
return(SUCCESSFUL);
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// If we are to disable it and count > 1 then decrement counter and exit
|
|||
|
//
|
|||
|
if ((PromiscuousState == 0) &&
|
|||
|
(Mlid->PromiscuousModeEnables > 1)) {
|
|||
|
|
|||
|
Mlid->PromiscuousModeEnables--;
|
|||
|
|
|||
|
NdisReleaseSpinLock(&(Mlid->MlidSpinLock));
|
|||
|
return(SUCCESSFUL);
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Allocate NDIS_REQUEST
|
|||
|
//
|
|||
|
NdisMlidRequest = (PNDIS_REQUEST)ExAllocatePool(NonPagedPool, sizeof(NDIS_REQUEST));
|
|||
|
|
|||
|
if (NdisMlidRequest == NULL) {
|
|||
|
|
|||
|
NdisReleaseSpinLock(&(Mlid->MlidSpinLock));
|
|||
|
return(OUT_OF_RESOURCES);
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Save old value
|
|||
|
//
|
|||
|
OldFilterValue = Mlid->NdisPacketFilterValue;
|
|||
|
OldCount = Mlid->PromiscuousModeEnables;
|
|||
|
|
|||
|
if (PromiscuousState == 0) {
|
|||
|
|
|||
|
Mlid->PromiscuousModeEnables = 0;
|
|||
|
Mlid->NdisPacketFilterValue &= ~(NDIS_PACKET_TYPE_PROMISCUOUS);
|
|||
|
|
|||
|
} else {
|
|||
|
|
|||
|
Mlid->PromiscuousModeEnables = 1;
|
|||
|
Mlid->NdisPacketFilterValue |= NDIS_PACKET_TYPE_PROMISCUOUS;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Build an NDIS request
|
|||
|
//
|
|||
|
NdisMlidRequest->RequestType = NdisRequestSetInformation;
|
|||
|
|
|||
|
NdisMlidRequest->DATA.SET_INFORMATION.Oid = OID_GEN_CURRENT_PACKET_FILTER;
|
|||
|
NdisMlidRequest->DATA.SET_INFORMATION.InformationBuffer = (PVOID)&(Mlid->NdisPacketFilterValue);
|
|||
|
NdisMlidRequest->DATA.SET_INFORMATION.InformationBufferLength = sizeof(UINT32);
|
|||
|
|
|||
|
NdisMlidRequest->DATA.SET_INFORMATION.BytesRead = 0;
|
|||
|
NdisMlidRequest->DATA.SET_INFORMATION.BytesNeeded = 0;
|
|||
|
|
|||
|
Mlid->RequestStatus = NDIS_STATUS_PENDING;
|
|||
|
|
|||
|
//
|
|||
|
// Release spin lock
|
|||
|
//
|
|||
|
NdisReleaseSpinLock(&(Mlid->MlidSpinLock));
|
|||
|
|
|||
|
//
|
|||
|
// Submit NDIS request
|
|||
|
//
|
|||
|
|
|||
|
NdisRequest(
|
|||
|
&NdisStatus,
|
|||
|
Mlid->NdisBindingHandle,
|
|||
|
NdisMlidRequest
|
|||
|
);
|
|||
|
|
|||
|
//
|
|||
|
// If it pended, see if it completed already.
|
|||
|
//
|
|||
|
if (NdisStatus == NDIS_STATUS_PENDING) {
|
|||
|
|
|||
|
if ((NDIS_STATUS)Mlid->RequestStatus == NDIS_STATUS_PENDING) {
|
|||
|
|
|||
|
//
|
|||
|
// Assume it will complete successfully
|
|||
|
//
|
|||
|
NdisStatus = NDIS_STATUS_SUCCESS;
|
|||
|
|
|||
|
} else {
|
|||
|
|
|||
|
NdisStatus = (NDIS_STATUS)Mlid->RequestStatus;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
} else {
|
|||
|
|
|||
|
//
|
|||
|
// Free NDIS_REQUEST
|
|||
|
//
|
|||
|
ExFreePool(NdisMlidRequest);
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// return status
|
|||
|
//
|
|||
|
|
|||
|
if (NdisStatus == NDIS_STATUS_SUCCESS) {
|
|||
|
|
|||
|
return(SUCCESSFUL);
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// restore state
|
|||
|
//
|
|||
|
NdisAcquireSpinLock(&(Mlid->MlidSpinLock));
|
|||
|
|
|||
|
Mlid->NdisPacketFilterValue = OldFilterValue;
|
|||
|
Mlid->PromiscuousModeEnables = OldCount;
|
|||
|
|
|||
|
NdisReleaseSpinLock(&(Mlid->MlidSpinLock));
|
|||
|
|
|||
|
return(BAD_COMMAND);
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
UINT32
|
|||
|
MLIDManagement(
|
|||
|
UINT32 BoardNumber,
|
|||
|
PECB ManagementECB
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Allows a management entity to access management information from/and control
|
|||
|
an MLID.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
BoardNumber - The board number.
|
|||
|
|
|||
|
ManagementECB - A pointer to an ECB containing the management information.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
SUCCESSFUL - Success.
|
|||
|
RESPONSE_DELAYED - Command will complete asyncronously.
|
|||
|
BAD_COMMAND - Not supported.
|
|||
|
BAD_PARAMETER - The Protocol ID field is invalid.
|
|||
|
NO_SUCH_HANDLER - Management entity for the Management Handle in teh ECB does
|
|||
|
not exist
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
|
|||
|
//
|
|||
|
// Always return BAD_COMMAND.
|
|||
|
//
|
|||
|
|
|||
|
return(BAD_COMMAND);
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
VOID
|
|||
|
MLIDSendHandler(
|
|||
|
PECB SendECB
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine takes an ECB, assembles a packet based on the frame-type and
|
|||
|
sends it on the wire.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
SendECB - A pointer to the ECB discribing the data and destination address for
|
|||
|
the packet.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
None.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
PMLID_STRUCT Mlid;
|
|||
|
UINT32 i;
|
|||
|
BOOLEAN Result;
|
|||
|
|
|||
|
NdisAcquireSpinLock(&NdisMlidSpinLock);
|
|||
|
|
|||
|
//
|
|||
|
// Verify that BoardNumber is in valid range
|
|||
|
//
|
|||
|
|
|||
|
for (i =0 ; i < AllocatedMlidBoards; i++) {
|
|||
|
|
|||
|
if (MlidBoards[i].BoardNumber == SendECB->ECB_BoardNumber) {
|
|||
|
|
|||
|
break;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
if (i == AllocatedMlidBoards) {
|
|||
|
|
|||
|
//
|
|||
|
// Cancel the ECB
|
|||
|
//
|
|||
|
|
|||
|
SendECB->ECB_Status = (UINT16)CANCELED;
|
|||
|
|
|||
|
NdisReleaseSpinLock(&NdisMlidSpinLock);
|
|||
|
|
|||
|
//
|
|||
|
// We could try to find a board number with a link to the LSL, but
|
|||
|
// in any case we might fail. The transport and/or LSL has hosed us,
|
|||
|
// so we will just let it sit.
|
|||
|
//
|
|||
|
return;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// If BoardNumber is not open, fail.
|
|||
|
//
|
|||
|
|
|||
|
if (MlidBoards[i].Mlid == NULL) {
|
|||
|
|
|||
|
|
|||
|
//
|
|||
|
// Cancel the ECB
|
|||
|
//
|
|||
|
|
|||
|
SendECB->ECB_Status = (UINT16)CANCELED;
|
|||
|
|
|||
|
NdisReleaseSpinLock(&NdisMlidSpinLock);
|
|||
|
|
|||
|
//
|
|||
|
// We could try to find a board number with a link to the LSL, but
|
|||
|
// in any case we might fail. The transport and/or LSL has hosed us,
|
|||
|
// so we will just let it sit.
|
|||
|
//
|
|||
|
return;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// If Board is unloading - fail
|
|||
|
//
|
|||
|
if (MlidBoards[i].Mlid->Unloading) {
|
|||
|
|
|||
|
|
|||
|
//
|
|||
|
// Cancel the ECB
|
|||
|
//
|
|||
|
|
|||
|
SendECB->ECB_Status = (UINT16)CANCELED;
|
|||
|
|
|||
|
NdisReleaseSpinLock(&NdisMlidSpinLock);
|
|||
|
|
|||
|
//
|
|||
|
// We could try to find a board number with a link to the LSL, but
|
|||
|
// in any case we might fail. The transport and/or LSL has hosed us,
|
|||
|
// so we will just let it sit.
|
|||
|
//
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
Mlid = MlidBoards[i].Mlid;
|
|||
|
|
|||
|
NdisAcquireSpinLock(&(Mlid->MlidSpinLock));
|
|||
|
|
|||
|
NdisReleaseSpinLock(&NdisMlidSpinLock);
|
|||
|
|
|||
|
//
|
|||
|
// Update MTotalGroupAddrTxCount
|
|||
|
//
|
|||
|
switch (Mlid->NdisMlidMedium) {
|
|||
|
|
|||
|
case NdisMediumFddi:
|
|||
|
case NdisMedium802_3:
|
|||
|
|
|||
|
if (ETH_IS_BROADCAST(SendECB->ECB_ImmediateAddress)) {
|
|||
|
(*((PUINT32)((*(Mlid->StatsTable->StatsTable.MGenericCountsPtr))[10].StatCounter)))++;
|
|||
|
break;
|
|||
|
}
|
|||
|
|
|||
|
if (ETH_IS_MULTICAST(SendECB->ECB_ImmediateAddress)) {
|
|||
|
(*((PUINT32)((*(Mlid->StatsTable->StatsTable.MGenericCountsPtr))[10].StatCounter)))++;
|
|||
|
break;
|
|||
|
}
|
|||
|
|
|||
|
if (ETH_IS_MULTICAST(SendECB->ECB_ImmediateAddress)) {
|
|||
|
(*((PUINT32)((*(Mlid->StatsTable->StatsTable.MGenericCountsPtr))[10].StatCounter)))++;
|
|||
|
break;
|
|||
|
}
|
|||
|
break;
|
|||
|
|
|||
|
case NdisMedium802_5:
|
|||
|
|
|||
|
TR_IS_BROADCAST(SendECB->ECB_ImmediateAddress, &Result);
|
|||
|
if (Result == TRUE) {
|
|||
|
(*((PUINT32)((*(Mlid->StatsTable->StatsTable.MGenericCountsPtr))[10].StatCounter)))++;
|
|||
|
break;
|
|||
|
}
|
|||
|
|
|||
|
TR_IS_GROUP(SendECB->ECB_ImmediateAddress, &Result);
|
|||
|
if (Result == TRUE) {
|
|||
|
(*((PUINT32)((*(Mlid->StatsTable->StatsTable.MGenericCountsPtr))[10].StatCounter)))++;
|
|||
|
break;
|
|||
|
}
|
|||
|
|
|||
|
TR_IS_FUNCTIONAL(SendECB->ECB_ImmediateAddress, &Result);
|
|||
|
if (Result == TRUE) {
|
|||
|
(*((PUINT32)((*(Mlid->StatsTable->StatsTable.MGenericCountsPtr))[10].StatCounter)))++;
|
|||
|
break;
|
|||
|
}
|
|||
|
break;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
(*((PUINT32)((*(Mlid->StatsTable->StatsTable.MGenericCountsPtr))[14].StatCounter)))++; // MQDepth
|
|||
|
|
|||
|
//
|
|||
|
// Put ECB on send queue
|
|||
|
//
|
|||
|
|
|||
|
if (Mlid->FirstPendingSend == NULL) {
|
|||
|
|
|||
|
Mlid->FirstPendingSend = SendECB;
|
|||
|
Mlid->LastPendingSend = SendECB;
|
|||
|
SendECB->ECB_NextLink = NULL;
|
|||
|
SendECB->ECB_PreviousLink = NULL;
|
|||
|
|
|||
|
} else {
|
|||
|
|
|||
|
Mlid->LastPendingSend->ECB_NextLink = SendECB;
|
|||
|
SendECB->ECB_PreviousLink = Mlid->LastPendingSend;
|
|||
|
SendECB->ECB_NextLink = NULL;
|
|||
|
Mlid->LastPendingSend = SendECB;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Send all packets possible
|
|||
|
//
|
|||
|
|
|||
|
if (Mlid->StageOpen && !Mlid->InSendPacket) {
|
|||
|
|
|||
|
SendPackets(Mlid);
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
NdisReleaseSpinLock(&(Mlid->MlidSpinLock));
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
UINT32
|
|||
|
BuildNewMulticastList(
|
|||
|
PMLID_STRUCT Mlid,
|
|||
|
PUINT8 AddMulticastAddr
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine takes a multicast addresses for either Ethernet or FDDI and
|
|||
|
adds it to the Mlids database if it does not exist, otherwise it increments
|
|||
|
the reference count on the address if it does exist.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
Mlid - Pointer to the MLID.
|
|||
|
|
|||
|
AddMulticastAddr - The multicast address to add.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
SUCCESSFUL - Success.
|
|||
|
DUPLICATE_ENTRY - The address already existed in the database.
|
|||
|
OUT_OF_RESOURCES - No memory avaiable to grow database.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
UINT32 i;
|
|||
|
|
|||
|
//
|
|||
|
// If address already exists, increment counter.
|
|||
|
//
|
|||
|
for (i = 0; i < Mlid->MulticastAddresses.MACount; i++) {
|
|||
|
|
|||
|
if (RtlCompareMemory(Mlid->MulticastAddresses.Addresses + i * 6,
|
|||
|
AddMulticastAddr,
|
|||
|
6
|
|||
|
) == 0) {
|
|||
|
|
|||
|
//
|
|||
|
// Increment count and exit
|
|||
|
//
|
|||
|
|
|||
|
Mlid->MulticastAddresses.EnableCounts[i]++;
|
|||
|
return(DUPLICATE_ENTRY);
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Allocate space for new array, if necessary
|
|||
|
//
|
|||
|
if (Mlid->MulticastAddresses.MACount == Mlid->MulticastAddresses.MAAllocated) {
|
|||
|
|
|||
|
PUINT8 TmpAddressArray;
|
|||
|
PUINT32 TmpCountArray;
|
|||
|
|
|||
|
//
|
|||
|
// Allocate memory for new array
|
|||
|
//
|
|||
|
|
|||
|
TmpAddressArray = (PUINT8)ExAllocatePool(NonPagedPool,
|
|||
|
6 * (Mlid->MulticastAddresses.MACount + 2)
|
|||
|
);
|
|||
|
|
|||
|
if (TmpAddressArray == NULL) {
|
|||
|
|
|||
|
return(OUT_OF_RESOURCES);
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
TmpCountArray = (PUINT32)ExAllocatePool(NonPagedPool,
|
|||
|
sizeof(UINT32) *
|
|||
|
(Mlid->MulticastAddresses.MACount + 2)
|
|||
|
);
|
|||
|
|
|||
|
if (TmpCountArray == NULL) {
|
|||
|
|
|||
|
return(OUT_OF_RESOURCES);
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Copy over old addresses
|
|||
|
//
|
|||
|
RtlCopyMemory(TmpAddressArray,
|
|||
|
Mlid->MulticastAddresses.Addresses,
|
|||
|
6 * Mlid->MulticastAddresses.MACount
|
|||
|
);
|
|||
|
|
|||
|
//
|
|||
|
// Copy over old counts
|
|||
|
//
|
|||
|
RtlCopyMemory(TmpCountArray,
|
|||
|
Mlid->MulticastAddresses.EnableCounts,
|
|||
|
sizeof(UINT32) * Mlid->MulticastAddresses.MACount
|
|||
|
);
|
|||
|
|
|||
|
//
|
|||
|
// Free old resources
|
|||
|
//
|
|||
|
ExFreePool(Mlid->MulticastAddresses.Addresses);
|
|||
|
ExFreePool(Mlid->MulticastAddresses.EnableCounts);
|
|||
|
|
|||
|
//
|
|||
|
// Save new space
|
|||
|
//
|
|||
|
Mlid->MulticastAddresses.Addresses = TmpAddressArray;
|
|||
|
Mlid->MulticastAddresses.EnableCounts = TmpCountArray;
|
|||
|
|
|||
|
//
|
|||
|
// Increment allocated count
|
|||
|
//
|
|||
|
Mlid->MulticastAddresses.MAAllocated += 2;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Put address in new slot
|
|||
|
//
|
|||
|
RtlCopyMemory(Mlid->MulticastAddresses.Addresses +
|
|||
|
Mlid->MulticastAddresses.MACount * 6,
|
|||
|
AddMulticastAddr,
|
|||
|
6
|
|||
|
);
|
|||
|
|
|||
|
//
|
|||
|
// Set reference count
|
|||
|
//
|
|||
|
Mlid->MulticastAddresses.EnableCounts[Mlid->MulticastAddresses.MACount] = 1;
|
|||
|
|
|||
|
Mlid->MulticastAddresses.MACount++;
|
|||
|
|
|||
|
return(SUCCESSFUL);
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
UINT32
|
|||
|
BuildNewFunctionalAddr(
|
|||
|
PMLID_STRUCT Mlid,
|
|||
|
PUINT8 AddFunctionalAddr
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine takes a functional address(es) for token ring and
|
|||
|
adds it to the Mlid functional address if it does not exist, otherwise
|
|||
|
it increments the reference count on the address(es) if it does exist.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
Mlid - Pointer to the MLID.
|
|||
|
|
|||
|
AddFunctionalAddr - The functional address to add.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
SUCCESSFUL - Success.
|
|||
|
DUPLICATE_ENTRY - The address already existed in the database.
|
|||
|
OUT_OF_RESOURCES - No memory avaiable to grow database.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
UINT32 i;
|
|||
|
UINT32 ShortenedFunctionalAddr;
|
|||
|
UNALIGNED UINT32 *PAddr;
|
|||
|
UINT32 NewAddressBits;
|
|||
|
UINT32 OldAddressBits;
|
|||
|
|
|||
|
if (Mlid->MulticastAddresses.MAAllocated == 0) {
|
|||
|
|
|||
|
//
|
|||
|
// Get memory for the counts
|
|||
|
//
|
|||
|
|
|||
|
Mlid->MulticastAddresses.EnableCounts = (PUINT32)ExAllocatePool(NonPagedPool,
|
|||
|
sizeof(UINT32) * 32
|
|||
|
);
|
|||
|
|
|||
|
if (Mlid->MulticastAddresses.EnableCounts == NULL) {
|
|||
|
|
|||
|
return(OUT_OF_RESOURCES);
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
RtlZeroMemory(Mlid->MulticastAddresses.EnableCounts, sizeof(UINT32) * 32);
|
|||
|
|
|||
|
Mlid->MulticastAddresses.MAAllocated = 32;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Get low four bytes of address
|
|||
|
//
|
|||
|
PAddr = (UNALIGNED UINT32 *)(AddFunctionalAddr + 2);
|
|||
|
ShortenedFunctionalAddr = *PAddr;
|
|||
|
|
|||
|
//
|
|||
|
// Get new bits and old bits
|
|||
|
//
|
|||
|
OldAddressBits = Mlid->MulticastAddresses.FunctionalAddr & ShortenedFunctionalAddr;
|
|||
|
NewAddressBits = ShortenedFunctionalAddr ^ OldAddressBits;
|
|||
|
|
|||
|
//
|
|||
|
// Increment count of each bit that exists in current functional address
|
|||
|
//
|
|||
|
i = 0;
|
|||
|
|
|||
|
while (OldAddressBits != 0) {
|
|||
|
|
|||
|
if (OldAddressBits & 1) {
|
|||
|
|
|||
|
Mlid->MulticastAddresses.EnableCounts[i]++;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
OldAddressBits >>= 1;
|
|||
|
i++;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
if (NewAddressBits == 0) {
|
|||
|
|
|||
|
return(DUPLICATE_ENTRY);
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Store new bits
|
|||
|
//
|
|||
|
|
|||
|
Mlid->MulticastAddresses.FunctionalAddr |= NewAddressBits;
|
|||
|
|
|||
|
//
|
|||
|
// Set counts of each new address bit
|
|||
|
//
|
|||
|
|
|||
|
i = 0;
|
|||
|
|
|||
|
while (NewAddressBits != 0) {
|
|||
|
|
|||
|
if (NewAddressBits & 1) {
|
|||
|
|
|||
|
Mlid->MulticastAddresses.EnableCounts[i] = 1;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
NewAddressBits >>= 1;
|
|||
|
i++;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
return(SUCCESSFUL);
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
UINT32
|
|||
|
RemoveFromMulticastList(
|
|||
|
PMLID_STRUCT Mlid,
|
|||
|
PUINT8 DelMulticastAddr
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine takes a multicast addresses for either Ethernet or FDDI and
|
|||
|
removes it from the Mlids database if the reference count is one, otherwise
|
|||
|
it decrements the reference count on the address.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
Mlid - Pointer to the MLID.
|
|||
|
|
|||
|
DelMulticastAddr - The multicast address to add.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
SUCCESSFUL - Success and address is removed.
|
|||
|
ITEM_NOT_PRESENT - The address does not exist in the database.
|
|||
|
DUPLICATE_ENTRY - Success and address still exists.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
UINT32 i;
|
|||
|
|
|||
|
//
|
|||
|
// If address already exists, decrement counter.
|
|||
|
//
|
|||
|
for (i = 0; i < Mlid->MulticastAddresses.MACount; i++) {
|
|||
|
|
|||
|
if (RtlCompareMemory(Mlid->MulticastAddresses.Addresses + i * 6,
|
|||
|
DelMulticastAddr,
|
|||
|
6
|
|||
|
) == 0) {
|
|||
|
|
|||
|
//
|
|||
|
// Increment count and exit
|
|||
|
//
|
|||
|
|
|||
|
Mlid->MulticastAddresses.EnableCounts[i]--;
|
|||
|
|
|||
|
//
|
|||
|
// If this is not the last reference we can exit now
|
|||
|
//
|
|||
|
if (Mlid->MulticastAddresses.EnableCounts[i] != 0) {
|
|||
|
|
|||
|
return(DUPLICATE_ENTRY);
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Now we need to adjust the address array and counts array
|
|||
|
//
|
|||
|
|
|||
|
RtlMoveMemory(
|
|||
|
Mlid->MulticastAddresses.Addresses + i * 6,
|
|||
|
Mlid->MulticastAddresses.Addresses + (i + 1) * 6,
|
|||
|
6 * (Mlid->MulticastAddresses.MACount - (i + 1))
|
|||
|
);
|
|||
|
|
|||
|
RtlMoveMemory(
|
|||
|
Mlid->MulticastAddresses.EnableCounts + i,
|
|||
|
Mlid->MulticastAddresses.EnableCounts + (i + 1),
|
|||
|
sizeof(UINT32) * (Mlid->MulticastAddresses.MACount - (i + 1))
|
|||
|
);
|
|||
|
|
|||
|
Mlid->MulticastAddresses.MACount--;
|
|||
|
|
|||
|
return(SUCCESSFUL);
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
return(ITEM_NOT_PRESENT);
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
UINT32
|
|||
|
RemoveFromFunctionalAddr(
|
|||
|
PMLID_STRUCT Mlid,
|
|||
|
PUINT8 DelFunctionalAddr
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine takes functional address(es) for token ring and
|
|||
|
removes it/them from the Mlids database if the reference count i/ares one,
|
|||
|
otherwise it decrements the reference count on the address(es).
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
Mlid - Pointer to the MLID.
|
|||
|
|
|||
|
DelFunctionalAddr - The functional address to remove.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
SUCCESSFUL - Success and address is changed.
|
|||
|
ITEM_NOT_PRESENT - The address does not exist in the database.
|
|||
|
DUPLICATE_ENTRY - Success and address is unchanged.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
UINT32 i;
|
|||
|
UINT32 ShortenedFunctionalAddr;
|
|||
|
UNALIGNED UINT32 *PAddr;
|
|||
|
UINT32 OldAddressBits;
|
|||
|
UINT32 Status = DUPLICATE_ENTRY;
|
|||
|
|
|||
|
if (Mlid->MulticastAddresses.MAAllocated == 0) {
|
|||
|
|
|||
|
return(ITEM_NOT_PRESENT);
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Get low four bytes of address
|
|||
|
//
|
|||
|
PAddr = (UNALIGNED UINT32 *)(DelFunctionalAddr + 2);
|
|||
|
ShortenedFunctionalAddr = *PAddr;
|
|||
|
|
|||
|
//
|
|||
|
// Get new bits and old bits
|
|||
|
//
|
|||
|
OldAddressBits = Mlid->MulticastAddresses.FunctionalAddr & ShortenedFunctionalAddr;
|
|||
|
|
|||
|
if (OldAddressBits != ShortenedFunctionalAddr) {
|
|||
|
|
|||
|
return(ITEM_NOT_PRESENT);
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Increment count of each bit that exists in current functional address
|
|||
|
//
|
|||
|
i = 0;
|
|||
|
|
|||
|
while (OldAddressBits != 0) {
|
|||
|
|
|||
|
if (OldAddressBits & 1) {
|
|||
|
|
|||
|
Mlid->MulticastAddresses.EnableCounts[i]--;
|
|||
|
|
|||
|
if (Mlid->MulticastAddresses.EnableCounts[i] == 0) {
|
|||
|
|
|||
|
//
|
|||
|
// Remove this bit
|
|||
|
//
|
|||
|
|
|||
|
Mlid->MulticastAddresses.FunctionalAddr &= ~(1 << i);
|
|||
|
|
|||
|
Status = SUCCESSFUL;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
OldAddressBits >>= 1;
|
|||
|
i++;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
return(Status);
|
|||
|
|
|||
|
}
|
|||
|
|