mirror of https://github.com/lianthony/NT4.0
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.
4413 lines
93 KiB
4413 lines
93 KiB
/*++
|
|
|
|
Copyright (c) 1990 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
Mlid.c
|
|
|
|
Abstract:
|
|
|
|
This is the main file for the Western Digital
|
|
Ethernet controller. This driver conforms to the NDIS 3.1 interface.
|
|
|
|
Author:
|
|
|
|
Sean Selitrennikoff (SeanSe) 15-Jan-1992
|
|
|
|
Environment:
|
|
|
|
Kernel Mode - Or whatever is the equivalent on OS/2 and DOS.
|
|
|
|
Revision History:
|
|
|
|
|
|
--*/
|
|
|
|
#include <ndis.h>
|
|
#include <efilter.h>
|
|
#include <odihsm.h>
|
|
#include <mlidsft.h>
|
|
#include "keywords.h"
|
|
|
|
#if DBG
|
|
#define STATIC
|
|
#else
|
|
#define STATIC static
|
|
#endif
|
|
|
|
#if DBG
|
|
|
|
|
|
#define LOGSIZE 512
|
|
|
|
extern UCHAR MlidDebugLog[LOGSIZE] = {0};
|
|
extern UINT MlidDebugLogPlace = 0;
|
|
|
|
|
|
extern
|
|
VOID
|
|
LOG (UCHAR A) {
|
|
MlidDebugLog[MlidDebugLogPlace++] = A;
|
|
MlidDebugLog[(MlidDebugLogPlace + 4) % LOGSIZE] = '\0';
|
|
if (MlidDebugLogPlace >= LOGSIZE) MlidDebugLogPlace = 0;
|
|
}
|
|
|
|
|
|
ULONG MlidDebugFlag= MLID_DEBUG_LOG; // MLID_DEBUG_LOG | MLID_DEBUG_LOUD | MLID_DEBUG_VERY_LOUD;
|
|
|
|
#define IF_LOG(A) A
|
|
|
|
#else
|
|
|
|
#define IF_LOG(A)
|
|
|
|
#endif
|
|
|
|
|
|
//
|
|
// This constant is used for places where NdisAllocateMemory
|
|
// needs to be called and the HighestAcceptableAddress does
|
|
// not matter.
|
|
//
|
|
|
|
NDIS_PHYSICAL_ADDRESS HighestAcceptableMax =
|
|
NDIS_PHYSICAL_ADDRESS_CONST(-1,-1);
|
|
|
|
|
|
|
|
//
|
|
// The global MAC block.
|
|
//
|
|
|
|
extern MAC_BLOCK MlidMacBlock={0};
|
|
|
|
|
|
|
|
//
|
|
// If you add to this, make sure to add the
|
|
// a case in MlidFillInGlobalData() and in
|
|
// MlidQueryGlobalStatistics() if global
|
|
// information only or
|
|
// MlidQueryProtocolStatistics() if it is
|
|
// protocol queriable information.
|
|
//
|
|
UINT MlidGlobalSupportedOids[] = {
|
|
OID_GEN_SUPPORTED_LIST,
|
|
OID_GEN_HARDWARE_STATUS,
|
|
OID_GEN_MEDIA_SUPPORTED,
|
|
OID_GEN_MEDIA_IN_USE,
|
|
OID_GEN_MAXIMUM_LOOKAHEAD,
|
|
OID_GEN_MAXIMUM_FRAME_SIZE,
|
|
OID_GEN_MAXIMUM_TOTAL_SIZE,
|
|
OID_GEN_MAC_OPTIONS,
|
|
OID_GEN_PROTOCOL_OPTIONS,
|
|
OID_GEN_LINK_SPEED,
|
|
|
|
/*++
|
|
These are not available
|
|
|
|
OID_GEN_TRANSMIT_BUFFER_SPACE,
|
|
OID_GEN_RECEIVE_BUFFER_SPACE,
|
|
OID_GEN_TRANSMIT_BLOCK_SIZE,
|
|
OID_GEN_RECEIVE_BLOCK_SIZE,
|
|
OID_GEN_VENDOR_ID,
|
|
OID_GEN_VENDOR_DESCRIPTION,
|
|
|
|
--*/
|
|
|
|
OID_GEN_DRIVER_VERSION,
|
|
OID_GEN_CURRENT_PACKET_FILTER,
|
|
OID_GEN_CURRENT_LOOKAHEAD,
|
|
|
|
OID_GEN_XMIT_OK,
|
|
OID_GEN_RCV_OK,
|
|
OID_GEN_XMIT_ERROR,
|
|
OID_GEN_RCV_ERROR,
|
|
OID_GEN_RCV_NO_BUFFER,
|
|
|
|
OID_802_3_PERMANENT_ADDRESS,
|
|
OID_802_3_CURRENT_ADDRESS,
|
|
OID_802_3_MULTICAST_LIST,
|
|
OID_802_3_MAXIMUM_LIST_SIZE,
|
|
OID_802_3_RCV_ERROR_ALIGNMENT,
|
|
OID_802_3_XMIT_ONE_COLLISION,
|
|
OID_802_3_XMIT_MORE_COLLISIONS,
|
|
|
|
OID_802_5_PERMANENT_ADDRESS,
|
|
OID_802_5_CURRENT_ADDRESS,
|
|
OID_802_5_CURRENT_FUNCTIONAL,
|
|
OID_802_5_CURRENT_GROUP,
|
|
OID_802_5_LAST_OPEN_STATUS,
|
|
OID_802_5_CURRENT_RING_STATUS,
|
|
OID_802_5_CURRENT_RING_STATE,
|
|
OID_802_5_LINE_ERRORS,
|
|
OID_802_5_LOST_FRAMES
|
|
};
|
|
|
|
//
|
|
// If you add to this, make sure to add the
|
|
// a case in MlidQueryGlobalStatistics() and in
|
|
// MlidQueryProtocolInformation()
|
|
//
|
|
UINT MlidProtocolSupportedOids[] = {
|
|
OID_GEN_SUPPORTED_LIST,
|
|
OID_GEN_HARDWARE_STATUS,
|
|
OID_GEN_MEDIA_SUPPORTED,
|
|
OID_GEN_MEDIA_IN_USE,
|
|
OID_GEN_MAXIMUM_LOOKAHEAD,
|
|
OID_GEN_MAXIMUM_FRAME_SIZE,
|
|
OID_GEN_MAXIMUM_TOTAL_SIZE,
|
|
OID_GEN_MAC_OPTIONS,
|
|
OID_GEN_PROTOCOL_OPTIONS,
|
|
OID_GEN_LINK_SPEED,
|
|
|
|
/*++
|
|
Not available
|
|
|
|
OID_GEN_TRANSMIT_BUFFER_SPACE,
|
|
OID_GEN_RECEIVE_BUFFER_SPACE,
|
|
OID_GEN_TRANSMIT_BLOCK_SIZE,
|
|
OID_GEN_RECEIVE_BLOCK_SIZE,
|
|
OID_GEN_VENDOR_ID,
|
|
OID_GEN_VENDOR_DESCRIPTION,
|
|
--*/
|
|
|
|
OID_GEN_DRIVER_VERSION,
|
|
OID_GEN_CURRENT_PACKET_FILTER,
|
|
OID_GEN_CURRENT_LOOKAHEAD,
|
|
|
|
OID_802_3_PERMANENT_ADDRESS,
|
|
OID_802_3_CURRENT_ADDRESS,
|
|
OID_802_3_MULTICAST_LIST,
|
|
OID_802_3_MAXIMUM_LIST_SIZE,
|
|
|
|
OID_802_5_PERMANENT_ADDRESS,
|
|
OID_802_5_CURRENT_ADDRESS,
|
|
OID_802_5_CURRENT_FUNCTIONAL,
|
|
OID_802_5_CURRENT_GROUP,
|
|
OID_802_5_LAST_OPEN_STATUS,
|
|
OID_802_5_CURRENT_RING_STATUS,
|
|
OID_802_5_CURRENT_RING_STATE,
|
|
OID_802_5_LINE_ERRORS,
|
|
OID_802_5_LOST_FRAMES
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
UINT
|
|
MlidCopyOver(
|
|
OUT PUCHAR Buf, // destination
|
|
IN PNDIS_PACKET Packet, // source packet
|
|
IN UINT Offset, // offset in packet
|
|
IN UINT Length // number of bytes to copy
|
|
);
|
|
|
|
|
|
|
|
|
|
#ifdef NDIS_WIN
|
|
#ifndef DEBUG
|
|
#pragma code_seg ("_ITEXT","ICODE")
|
|
#endif
|
|
#endif
|
|
|
|
NTSTATUS
|
|
DriverEntry(
|
|
IN PDRIVER_OBJECT DriverObject,
|
|
IN PUNICODE_STRING RegistryPath
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This is the transfer address of the driver. It initializes
|
|
MlidMacBlock and calls NdisInitializeWrapper() and
|
|
NdisRegisterMac().
|
|
|
|
Arguments:
|
|
|
|
Return Value:
|
|
|
|
Indicates the success or failure of the initialization.
|
|
|
|
--*/
|
|
|
|
{
|
|
PMAC_BLOCK NewMacP = &MlidMacBlock;
|
|
NDIS_STATUS Status;
|
|
NDIS_HANDLE NdisWrapperHandle;
|
|
|
|
#ifdef NDIS_NT
|
|
NDIS_STRING MacName = NDIS_STRING_CONST("Smc8000n");
|
|
#endif
|
|
|
|
#ifdef NDIS_WIN
|
|
NDIS_STRING MacName = NDIS_STRING_CONST("SMC8000W");
|
|
#endif
|
|
|
|
//
|
|
// Ensure that the MAC_RESERVED structure will fit in the
|
|
// MacReserved section of a packet.
|
|
//
|
|
|
|
ASSERT(sizeof(MAC_RESERVED) <= sizeof(((PNDIS_PACKET)NULL)->MacReserved));
|
|
|
|
|
|
//
|
|
// Pass the wrapper a pointer to the device object.
|
|
//
|
|
|
|
NdisInitializeWrapper(&NdisWrapperHandle,
|
|
DriverObject,
|
|
RegistryPath,
|
|
NULL
|
|
);
|
|
|
|
//
|
|
// Set up the driver object.
|
|
//
|
|
|
|
NewMacP->DriverObject = DriverObject;
|
|
|
|
NdisAllocateSpinLock(&NewMacP->SpinLock);
|
|
|
|
NewMacP->NdisWrapperHandle = NdisWrapperHandle;
|
|
NewMacP->Unloading = FALSE;
|
|
NewMacP->NumAdapters = 0;
|
|
NewMacP->AdapterQueue = (PMLID_ADAPTER)NULL;
|
|
|
|
|
|
//
|
|
// Prepare to call NdisRegisterMac.
|
|
//
|
|
|
|
NewMacP->MacCharacteristics.MajorNdisVersion = MLID_NDIS_MAJOR_VERSION;
|
|
NewMacP->MacCharacteristics.MinorNdisVersion = MLID_NDIS_MINOR_VERSION;
|
|
NewMacP->MacCharacteristics.Reserved = 0;
|
|
NewMacP->MacCharacteristics.OpenAdapterHandler = MlidOpenAdapter;
|
|
NewMacP->MacCharacteristics.CloseAdapterHandler = MlidCloseAdapter;
|
|
NewMacP->MacCharacteristics.SendHandler = MlidSend;
|
|
NewMacP->MacCharacteristics.TransferDataHandler = MlidTransferData;
|
|
NewMacP->MacCharacteristics.ResetHandler = MlidReset;
|
|
NewMacP->MacCharacteristics.RequestHandler = MlidRequest;
|
|
NewMacP->MacCharacteristics.QueryGlobalStatisticsHandler =
|
|
MlidQueryGlobalStatistics;
|
|
NewMacP->MacCharacteristics.UnloadMacHandler = MlidUnload;
|
|
NewMacP->MacCharacteristics.AddAdapterHandler = MlidAddAdapter;
|
|
NewMacP->MacCharacteristics.RemoveAdapterHandler = MlidRemoveAdapter;
|
|
|
|
NewMacP->MacCharacteristics.Name = MacName;
|
|
|
|
NdisRegisterMac(&Status,
|
|
&NewMacP->NdisMacHandle,
|
|
NdisWrapperHandle,
|
|
(NDIS_HANDLE)&MlidMacBlock,
|
|
&NewMacP->MacCharacteristics,
|
|
sizeof(NewMacP->MacCharacteristics));
|
|
|
|
|
|
if (Status != NDIS_STATUS_SUCCESS) {
|
|
|
|
//
|
|
// NdisRegisterMac failed.
|
|
//
|
|
|
|
NdisFreeSpinLock(&NewMacP->SpinLock);
|
|
NdisTerminateWrapper(NdisWrapperHandle, NULL);
|
|
IF_LOUD( DbgPrint( "NdisRegisterMac failed with code 0x%x\n", Status );)
|
|
return Status;
|
|
}
|
|
|
|
|
|
IF_LOUD( DbgPrint( "NdisRegisterMac succeeded\n" );)
|
|
|
|
IF_LOUD( DbgPrint("Adapter Initialization Complete\n");)
|
|
|
|
return Status;
|
|
|
|
}
|
|
|
|
#ifdef NDIS_WIN
|
|
#ifndef DEBUG
|
|
#pragma code_seg ()
|
|
#endif
|
|
#endif
|
|
|
|
|
|
#ifdef NDIS_WIN
|
|
#ifndef DEBUG
|
|
#pragma code_seg ("_ITEXT","ICODE")
|
|
#endif
|
|
#endif
|
|
|
|
NDIS_STATUS
|
|
MlidAddAdapter(
|
|
IN NDIS_HANDLE MacMacContext,
|
|
IN NDIS_HANDLE ConfigurationHandle,
|
|
IN PNDIS_STRING AdapterName
|
|
)
|
|
/*++
|
|
Routine Description:
|
|
|
|
This is the Mlid MacAddAdapter routine. The system calls this routine
|
|
to add support for a particular Mlid adapter. This routine extracts
|
|
configuration information from the configuration data base and registers
|
|
the adapter with NDIS.
|
|
|
|
Arguments:
|
|
|
|
see NDIS 3.0 spec...
|
|
|
|
Return Value:
|
|
|
|
NDIS_STATUS_SUCCESS - Adapter was successfully added.
|
|
NDIS_STATUS_FAILURE - Adapter was not added, also MAC deregistered.
|
|
|
|
--*/
|
|
{
|
|
|
|
LM_STATUS LmStatus;
|
|
NDIS_HANDLE ConfigHandle;
|
|
PNDIS_CONFIGURATION_PARAMETER ReturnedValue;
|
|
NDIS_STRING MlidDriverNameStr = NDIS_STRING_CONST("MlidDriverName");
|
|
|
|
ULONG ConfigErrorValue = 0;
|
|
BOOLEAN ConfigError = FALSE;
|
|
|
|
PMAC_BLOCK NewMacP = &MlidMacBlock;
|
|
NDIS_STATUS Status;
|
|
PMLID_ADAPTER Adapter;
|
|
NDIS_ADAPTER_INFORMATION AdapterInformation; // needed to register adapter
|
|
|
|
|
|
UNREFERENCED_PARAMETER(MacMacContext);
|
|
|
|
NdisOpenConfiguration(
|
|
&Status,
|
|
&ConfigHandle,
|
|
ConfigurationHandle
|
|
);
|
|
|
|
if (Status != NDIS_STATUS_SUCCESS) {
|
|
|
|
return NDIS_STATUS_FAILURE;
|
|
|
|
}
|
|
|
|
#if i386
|
|
#else
|
|
ASSERT(0);
|
|
#endif
|
|
|
|
//
|
|
// Read MlidDriverName
|
|
//
|
|
|
|
NdisReadConfiguration(
|
|
&Status,
|
|
&ReturnedValue,
|
|
ConfigHandle,
|
|
&MlidDriverNameStr,
|
|
NdisParameterString
|
|
);
|
|
|
|
if (Status != NDIS_STATUS_SUCCESS) {
|
|
|
|
NdisCloseConfiguration(ConfigHandle);
|
|
|
|
return(NDIS_STATUS_FAILURE);
|
|
|
|
}
|
|
|
|
//
|
|
// Here we load the image for the MLID, get the configuration and make the
|
|
// appropriate setup calls
|
|
//*\\ HERE!
|
|
|
|
//
|
|
// Allocate memory for the adapter block now.
|
|
//
|
|
|
|
Status = NdisAllocateMemory( (PVOID *)&Adapter, sizeof(MLID_ADAPTER), 0, HighestAcceptableMax);
|
|
|
|
if (Status != NDIS_STATUS_SUCCESS) {
|
|
|
|
ConfigError = TRUE;
|
|
ConfigErrorValue = NDIS_ERROR_CODE_OUT_OF_RESOURCES;
|
|
|
|
}
|
|
|
|
NdisZeroMemory(Adapter,sizeof(MLID_ADAPTER));
|
|
|
|
//
|
|
// The adapter is initialized, register it with NDIS.
|
|
// This must occur before interrupts are enabled since the
|
|
// InitializeInterrupt routine requires the NdisAdapterHandle
|
|
//
|
|
|
|
//
|
|
// Set up the AdapterInformation structure; zero it
|
|
// first in case it is extended later.
|
|
//
|
|
|
|
NdisZeroMemory (&AdapterInformation, sizeof(NDIS_ADAPTER_INFORMATION));
|
|
AdapterInformation.NumberOfPortDescriptors = 0;
|
|
|
|
Status = NdisRegisterAdapter(&Adapter->NdisAdapterHandle,
|
|
MlidMacBlock.NdisMacHandle,
|
|
(NDIS_HANDLE)Adapter,
|
|
ConfigurationHandle,
|
|
AdapterName,
|
|
&AdapterInformation
|
|
);
|
|
|
|
if (Status != NDIS_STATUS_SUCCESS) {
|
|
|
|
//
|
|
// NdisRegisterAdapter failed.
|
|
//
|
|
|
|
NdisCloseConfiguration(ConfigHandle);
|
|
|
|
NdisFreeMemory(Adapter, sizeof(MLID_ADAPTER), 0);
|
|
return NDIS_STATUS_FAILURE;
|
|
|
|
}
|
|
|
|
|
|
if (ConfigError) {
|
|
|
|
//
|
|
// Log Error and exit.
|
|
//
|
|
|
|
NdisWriteErrorLogEntry(
|
|
Adapter->NdisAdapterHandle,
|
|
ConfigErrorValue,
|
|
1
|
|
);
|
|
|
|
NdisCloseConfiguration(ConfigHandle);
|
|
|
|
NdisDeregisterAdapter(Adapter->NdisAdapterHandle);
|
|
|
|
NdisFreeMemory(Adapter, sizeof(MLID_ADAPTER), 0);
|
|
|
|
return(NDIS_STATUS_FAILURE);
|
|
|
|
}
|
|
|
|
NdisCloseConfiguration(ConfigHandle);
|
|
|
|
|
|
if (MlidRegisterAdapter(Adapter) != NDIS_STATUS_SUCCESS) {
|
|
|
|
//
|
|
// MlidRegisterAdapter failed.
|
|
//
|
|
|
|
NdisDeregisterAdapter(Adapter->NdisAdapterHandle);
|
|
NdisFreeMemory(Adapter, sizeof(MLID_ADAPTER), 0);
|
|
return NDIS_STATUS_FAILURE;
|
|
}
|
|
|
|
IF_LOUD( DbgPrint( "MlidRegisterAdapter succeeded\n" );)
|
|
|
|
|
|
return NDIS_STATUS_SUCCESS;
|
|
}
|
|
|
|
|
|
#ifdef NDIS_WIN
|
|
#ifndef DEBUG
|
|
#pragma code_seg ()
|
|
#endif
|
|
#endif
|
|
|
|
#ifdef NDIS_WIN
|
|
#ifndef DEBUG
|
|
#pragma code_seg ("_ITEXT","ICODE")
|
|
#endif
|
|
#endif
|
|
|
|
NDIS_STATUS
|
|
MlidRegisterAdapter(
|
|
IN PMLID_ADAPTER Adapter
|
|
)
|
|
|
|
/*++
|
|
|
|
|
|
Routine Description:
|
|
|
|
Called when a new adapter should be registered. It allocates space for
|
|
the adapter and open blocks, initializes the adapters block, and
|
|
calls NdisRegisterAdapter().
|
|
|
|
Arguments:
|
|
|
|
Adapter - A pointer to the adapter structure.
|
|
|
|
Return Value:
|
|
|
|
Indicates the success or failure of the registration.
|
|
|
|
--*/
|
|
|
|
{
|
|
UINT i;
|
|
NDIS_PHYSICAL_ADDRESS PhysicalAddress;
|
|
|
|
NDIS_STATUS status; //general purpose return from NDIS calls
|
|
|
|
Adapter->OpenQueue = (PMLID_OPEN)NULL;
|
|
|
|
//
|
|
// Allocate the Spin lock.
|
|
//
|
|
NdisAllocateSpinLock(&Adapter->Lock);
|
|
|
|
Adapter->DeferredDpc = (PVOID)MlidReceiveEvents;
|
|
|
|
NdisInitializeTimer(&(Adapter->DeferredTimer),
|
|
Adapter->DeferredDpc,
|
|
Adapter);
|
|
|
|
//
|
|
// Link us on to the chain of adapters for this MAC.
|
|
//
|
|
|
|
Adapter->MacBlock = &MlidMacBlock;
|
|
NdisAcquireSpinLock(&MlidMacBlock.SpinLock);
|
|
Adapter->NextAdapter = MlidMacBlock.AdapterQueue;
|
|
MlidMacBlock.AdapterQueue = Adapter;
|
|
NdisReleaseSpinLock(&MlidMacBlock.SpinLock);
|
|
|
|
//
|
|
// Set up the interrupt handlers.
|
|
//*\\ HERE!
|
|
|
|
KernelInterrupt = (CCHAR)(Adapter->irq_value);
|
|
|
|
NdisInitializeInterrupt(&status, // status of call
|
|
&(Adapter->NdisInterrupt), // interrupt info str
|
|
Adapter->NdisAdapterHandle,
|
|
(PNDIS_INTERRUPT_SERVICE) MlidInterruptHandler,
|
|
Adapter, // context for ISR, DPC
|
|
(PNDIS_DEFERRED_PROCESSING) MlidInterruptDpc,
|
|
KernelInterrupt, // int #
|
|
KernelInterrupt, // IRQL
|
|
FALSE, // NOT shared
|
|
(Adapter->bus_type == 0) ?
|
|
NdisInterruptLatched : // ATBus
|
|
NdisInterruptLevelSensitive // MCA
|
|
);
|
|
|
|
|
|
if (status != NDIS_STATUS_SUCCESS) {
|
|
|
|
NdisWriteErrorLogEntry(
|
|
Adapter->NdisAdapterHandle,
|
|
NDIS_ERROR_CODE_INTERRUPT_CONNECT,
|
|
0
|
|
);
|
|
|
|
goto fail3;
|
|
}
|
|
|
|
IF_LOUD( DbgPrint("Interrupt Connected\n");)
|
|
|
|
//
|
|
// Map the memory mapped portion of the card.
|
|
//
|
|
//
|
|
|
|
NdisSetPhysicalAddressHigh(PhysicalAddress, 0);
|
|
NdisSetPhysicalAddressLow(PhysicalAddress, (ULONG)(Adapter->ram_base));
|
|
|
|
//
|
|
// Now Initialize the card.
|
|
//*\\ HERE!
|
|
|
|
Adapter->FilterDB = NULL;
|
|
|
|
//
|
|
// Initialize Filter Database
|
|
//*\\ HERE!
|
|
|
|
if (Adapter->TokenRing) {
|
|
|
|
//
|
|
// token ring
|
|
//*\\ HERE!
|
|
|
|
goto fail6;
|
|
|
|
} else {
|
|
|
|
if (!EthCreateFilter(MulticastListMax,
|
|
MlidChangeMulticastAddresses,
|
|
MlidChangeFilterClasses,
|
|
MlidCloseAction,
|
|
Adapter->node_address,
|
|
&Adapter->Lock,
|
|
&Adapter->FilterDB
|
|
)) {
|
|
|
|
NdisWriteErrorLogEntry(
|
|
Adapter->NdisAdapterHandle,
|
|
NDIS_ERROR_CODE_OUT_OF_RESOURCES,
|
|
0
|
|
);
|
|
|
|
status = NDIS_STATUS_FAILURE;
|
|
|
|
goto fail6;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
//
|
|
// Initialize the wake up timer to catch interrupts that
|
|
// don't complete. It fires continuously
|
|
// every 5 seconds, and we check if there are any
|
|
// uncompleted operations from the previous two-second
|
|
// period.
|
|
//
|
|
|
|
Adapter->WakeUpDpc = (PVOID)MlidWakeUpDpc;
|
|
|
|
NdisInitializeTimer(&Adapter->WakeUpTimer,
|
|
(PVOID)(Adapter->WakeUpDpc),
|
|
Adapter );
|
|
|
|
NdisSetTimer(
|
|
&Adapter->WakeUpTimer,
|
|
5000
|
|
);
|
|
|
|
//
|
|
// Initialization completed successfully.
|
|
//
|
|
|
|
IF_LOUD( { DbgPrint(" MlidLan: [OK]\n");})
|
|
|
|
return NDIS_STATUS_SUCCESS;
|
|
|
|
|
|
//
|
|
// Code to unwind what has already been set up when a part of
|
|
// initialization fails, which is jumped into at various
|
|
// points based on where the failure occured. Jumping to
|
|
// a higher-numbered failure point will execute the code
|
|
// for that block and all lower-numbered ones.
|
|
//
|
|
|
|
fail6:
|
|
|
|
NdisUnmapIoSpace(
|
|
Adapter->NdisAdapterHandle,
|
|
Adapter->ram_access,
|
|
Adapter->ram_size * 1024);
|
|
|
|
failmap:
|
|
|
|
NdisRemoveInterrupt(&(Adapter->NdisInterrupt));
|
|
|
|
NdisAcquireSpinLock(&MlidMacBlock.SpinLock);
|
|
|
|
//
|
|
// Take us out of the AdapterQueue.
|
|
//
|
|
|
|
if (MlidMacBlock.AdapterQueue == Adapter) {
|
|
|
|
MlidMacBlock.AdapterQueue = Adapter->NextAdapter;
|
|
|
|
} else {
|
|
|
|
PMLID_ADAPTER TmpAdapter = MlidMacBlock.AdapterQueue;
|
|
|
|
while (TmpAdapter->NextAdapter != Adapter) {
|
|
|
|
TmpAdapter = TmpAdapter->NextAdapter;
|
|
|
|
}
|
|
|
|
TmpAdapter->NextAdapter = TmpAdapter->NextAdapter->NextAdapter;
|
|
}
|
|
|
|
NdisReleaseSpinLock(&MlidMacBlock.SpinLock);
|
|
|
|
fail3:
|
|
NdisFreeSpinLock(&Adapter->Lock);
|
|
|
|
fail1:
|
|
|
|
return status;
|
|
}
|
|
|
|
#ifdef NDIS_WIN
|
|
#ifndef DEBUG
|
|
#pragma code_seg ()
|
|
#endif
|
|
#endif
|
|
|
|
#ifdef NDIS_WIN
|
|
#ifndef DEBUG
|
|
#pragma code_seg ("_ITEXT","ICODE")
|
|
#endif
|
|
#endif
|
|
|
|
NDIS_STATUS
|
|
MlidOpenAdapter(
|
|
OUT PNDIS_STATUS OpenErrorStatus,
|
|
OUT NDIS_HANDLE * MacBindingHandle,
|
|
OUT PUINT SelectedMediumIndex,
|
|
IN PNDIS_MEDIUM MediumArray,
|
|
IN UINT MediumArraySize,
|
|
IN NDIS_HANDLE NdisBindingContext,
|
|
IN NDIS_HANDLE MacAdapterContext,
|
|
IN UINT OpenOptions,
|
|
IN PSTRING AddressingInformation OPTIONAL
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
NDIS function. It initializes the open block and links it in
|
|
the appropriate lists.
|
|
|
|
Arguments:
|
|
|
|
See NDIS 3.0 spec.
|
|
|
|
--*/
|
|
|
|
{
|
|
PMLID_ADAPTER Adapter = ((PMLID_ADAPTER)MacAdapterContext);
|
|
PMLID_OPEN NewOpen;
|
|
NDIS_STATUS Status;
|
|
|
|
//
|
|
// Don't use extended error or OpenOptions for Mlid
|
|
//
|
|
|
|
UNREFERENCED_PARAMETER(OpenOptions);
|
|
|
|
*OpenErrorStatus=NDIS_STATUS_SUCCESS;
|
|
|
|
IF_LOUD( DbgPrint("In Open Adapter\n");)
|
|
|
|
//
|
|
// Scan the media list for our media type (802.3)
|
|
//
|
|
|
|
*SelectedMediumIndex = (UINT)(-1);
|
|
|
|
while (MediumArraySize > 0) {
|
|
|
|
if (MediumArray[--MediumArraySize] == NdisMedium802_3 ) {
|
|
|
|
*SelectedMediumIndex = MediumArraySize;
|
|
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
if (*SelectedMediumIndex == -1) {
|
|
|
|
return NDIS_STATUS_UNSUPPORTED_MEDIA;
|
|
|
|
}
|
|
|
|
//
|
|
// Link this open to the appropriate lists.
|
|
//
|
|
|
|
if (Adapter->HardwareFailure) {
|
|
|
|
return(NDIS_STATUS_FAILURE);
|
|
|
|
}
|
|
|
|
//
|
|
// Allocate memory for the open.
|
|
//
|
|
|
|
|
|
Status = NdisAllocateMemory((PVOID *)&NewOpen, sizeof(MLID_OPEN), 0, HighestAcceptableMax);
|
|
|
|
if (Status != NDIS_STATUS_SUCCESS) {
|
|
|
|
NdisWriteErrorLogEntry(
|
|
Adapter->NdisAdapterHandle,
|
|
NDIS_ERROR_CODE_OUT_OF_RESOURCES,
|
|
0
|
|
);
|
|
|
|
return(NDIS_STATUS_RESOURCES);
|
|
|
|
}
|
|
|
|
NdisAcquireSpinLock(&Adapter->Lock);
|
|
|
|
Adapter->References++;
|
|
|
|
//
|
|
// Link this open to the appropriate lists.
|
|
//
|
|
|
|
if (Adapter->OpenQueue == NULL) {
|
|
|
|
//
|
|
// The first open on this adapter.
|
|
//
|
|
|
|
if (LM_Open_Adapter(&(Adapter->LMAdapter)) != SUCCESS) {
|
|
|
|
IF_LOUD( DbgPrint("OpenFailed!\n");)
|
|
|
|
NdisReleaseSpinLock(&Adapter->Lock);
|
|
|
|
NdisWriteErrorLogEntry(
|
|
Adapter->NdisAdapterHandle,
|
|
NDIS_ERROR_CODE_HARDWARE_FAILURE,
|
|
0
|
|
);
|
|
|
|
return(NDIS_STATUS_FAILURE);
|
|
|
|
}
|
|
|
|
IF_LOUD( DbgPrint("OpenSuccess!\n");)
|
|
|
|
}
|
|
|
|
NewOpen->NextOpen = Adapter->OpenQueue;
|
|
Adapter->OpenQueue = NewOpen;
|
|
|
|
if (Adapter->TokenRing) {
|
|
|
|
//*\\ token ring
|
|
|
|
} else {
|
|
|
|
if (!EthNoteFilterOpenAdapter(
|
|
Adapter->FilterDB,
|
|
NewOpen,
|
|
NdisBindingContext,
|
|
&NewOpen->NdisFilterHandle
|
|
)) {
|
|
|
|
Adapter->References--;
|
|
|
|
Adapter->OpenQueue = NewOpen->NextOpen;
|
|
|
|
NdisReleaseSpinLock(&Adapter->Lock);
|
|
|
|
NdisWriteErrorLogEntry(
|
|
Adapter->NdisAdapterHandle,
|
|
NDIS_ERROR_CODE_OUT_OF_RESOURCES,
|
|
0
|
|
);
|
|
|
|
return NDIS_STATUS_FAILURE;
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
//
|
|
// Set up the open block.
|
|
//
|
|
|
|
NewOpen->Adapter = Adapter;
|
|
NewOpen->MacBlock = Adapter->MacBlock;
|
|
NewOpen->NdisBindingContext = NdisBindingContext;
|
|
NewOpen->AddressingInformation = AddressingInformation;
|
|
NewOpen->Closing = FALSE;
|
|
NewOpen->LookAhead = MLID_MAX_LOOKAHEAD;
|
|
NewOpen->ProtOptionFlags = 0;
|
|
|
|
Adapter->MaxLookAhead = MLID_MAX_LOOKAHEAD;
|
|
|
|
NewOpen->ReferenceCount = 1;
|
|
|
|
*MacBindingHandle = (NDIS_HANDLE)NewOpen;
|
|
|
|
MLID_DO_DEFERRED(Adapter);
|
|
|
|
IF_LOUD( DbgPrint("Out Open Adapter\n");)
|
|
|
|
return NDIS_STATUS_SUCCESS;
|
|
}
|
|
|
|
#ifdef NDIS_WIN
|
|
#ifndef DEBUG
|
|
#pragma code_seg ()
|
|
#endif
|
|
#endif
|
|
|
|
|
|
VOID
|
|
MlidAdjustMaxLookAhead(
|
|
IN PMLID_ADAPTER Adapter
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine finds the open with the maximum lookahead value and
|
|
stores that in the adapter block.
|
|
|
|
NOTE: THIS ROUTINE MUST BE CALLED WITH THE SPINLOCK HELD.
|
|
|
|
Arguments:
|
|
|
|
Adapter - A pointer to the adapter block.
|
|
|
|
Returns:
|
|
|
|
None.
|
|
|
|
--*/
|
|
{
|
|
ULONG CurrentMax = 0;
|
|
PMLID_OPEN CurrentOpen;
|
|
|
|
CurrentOpen = Adapter->OpenQueue;
|
|
|
|
while (CurrentOpen != NULL) {
|
|
|
|
if (CurrentOpen->LookAhead > CurrentMax) {
|
|
|
|
CurrentMax = CurrentOpen->LookAhead;
|
|
|
|
}
|
|
|
|
CurrentOpen = CurrentOpen->NextOpen;
|
|
}
|
|
|
|
if (CurrentMax == 0) {
|
|
|
|
CurrentMax = MLID_MAX_LOOKAHEAD;
|
|
|
|
}
|
|
|
|
Adapter->MaxLookAhead = CurrentMax;
|
|
|
|
}
|
|
|
|
NDIS_STATUS
|
|
MlidCloseAdapter(
|
|
IN NDIS_HANDLE MacBindingHandle
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
NDIS function. Unlinks the open block and frees it.
|
|
|
|
Arguments:
|
|
|
|
See NDIS 3.0 spec.
|
|
|
|
--*/
|
|
|
|
{
|
|
PMLID_OPEN Open = ((PMLID_OPEN)MacBindingHandle);
|
|
PMLID_ADAPTER Adapter = Open->Adapter;
|
|
PMLID_OPEN TmpOpen;
|
|
NDIS_STATUS StatusToReturn;
|
|
|
|
NdisAcquireSpinLock(&Adapter->Lock);
|
|
|
|
if (Open->Closing) {
|
|
|
|
//
|
|
// The open is already being closed.
|
|
//
|
|
|
|
NdisReleaseSpinLock(&Adapter->Lock);
|
|
|
|
return NDIS_STATUS_CLOSING;
|
|
}
|
|
|
|
Adapter->References++;
|
|
|
|
Open->ReferenceCount++;
|
|
|
|
//
|
|
// Remove this open from the list for this adapter.
|
|
//
|
|
|
|
if (Open == Adapter->OpenQueue) {
|
|
|
|
Adapter->OpenQueue = Open->NextOpen;
|
|
|
|
} else {
|
|
|
|
TmpOpen = Adapter->OpenQueue;
|
|
|
|
while (TmpOpen->NextOpen != Open) {
|
|
|
|
TmpOpen = TmpOpen->NextOpen;
|
|
|
|
}
|
|
|
|
TmpOpen->NextOpen = Open->NextOpen;
|
|
}
|
|
|
|
|
|
|
|
//
|
|
// Remove from Filter package to block all receives.
|
|
//
|
|
|
|
if (Adapter->TokenRing) {
|
|
|
|
//*\\ token ring
|
|
|
|
} else {
|
|
|
|
StatusToReturn = EthDeleteFilterOpenAdapter(
|
|
Adapter->FilterDB,
|
|
Open->NdisFilterHandle,
|
|
NULL
|
|
);
|
|
|
|
}
|
|
|
|
|
|
//
|
|
// If the status is successful that merely implies that
|
|
// we were able to delete the reference to the open binding
|
|
// from the filtering code. If we have a successful status
|
|
// at this point we still need to check whether the reference
|
|
// count to determine whether we can close.
|
|
//
|
|
//
|
|
// The delete filter routine can return a "special" status
|
|
// that indicates that there is a current NdisIndicateReceive
|
|
// on this binding. See below.
|
|
//
|
|
|
|
if (StatusToReturn == NDIS_STATUS_SUCCESS) {
|
|
|
|
//
|
|
// Check whether the reference count is two. If
|
|
// it is then we can get rid of the memory for
|
|
// this open.
|
|
//
|
|
// A count of two indicates one for this routine
|
|
// and one for the filter which we *know* we can
|
|
// get rid of.
|
|
//
|
|
|
|
if (Open->ReferenceCount != 2) {
|
|
|
|
//
|
|
// We are not the only reference to the open. Remove
|
|
// it from the open list and delete the memory.
|
|
//
|
|
|
|
|
|
Open->Closing = TRUE;
|
|
|
|
//
|
|
// Account for this routines reference to the open
|
|
// as well as reference because of the original open.
|
|
//
|
|
|
|
Open->ReferenceCount -= 2;
|
|
|
|
//
|
|
// Change the status to indicate that we will
|
|
// be closing this later.
|
|
//
|
|
|
|
StatusToReturn = NDIS_STATUS_PENDING;
|
|
|
|
} else {
|
|
|
|
Open->ReferenceCount -= 2;
|
|
|
|
}
|
|
|
|
} else if (StatusToReturn == NDIS_STATUS_PENDING) {
|
|
|
|
Open->Closing = TRUE;
|
|
|
|
//
|
|
// Account for this routines reference to the open
|
|
// as well as reference because of the original open.
|
|
//
|
|
|
|
Open->ReferenceCount -= 2;
|
|
|
|
} else if (StatusToReturn == NDIS_STATUS_CLOSING_INDICATING) {
|
|
|
|
//
|
|
// When we have this status it indicates that the filtering
|
|
// code was currently doing an NdisIndicateReceive. It
|
|
// would not be wise to delete the memory for the open at
|
|
// this point. The filtering code will call our close action
|
|
// routine upon return from NdisIndicateReceive and that
|
|
// action routine will decrement the reference count for
|
|
// the open.
|
|
//
|
|
|
|
Open->Closing = TRUE;
|
|
|
|
//
|
|
// This status is private to the filtering routine. Just
|
|
// tell the caller the the close is pending.
|
|
//
|
|
|
|
StatusToReturn = NDIS_STATUS_PENDING;
|
|
|
|
//
|
|
// Account for this routines reference to the open.
|
|
//
|
|
|
|
Open->ReferenceCount--;
|
|
|
|
} else {
|
|
|
|
//
|
|
// Account for this routines reference to the open.
|
|
//
|
|
|
|
Open->ReferenceCount--;
|
|
|
|
}
|
|
|
|
//
|
|
// See if this is the last reference to this open.
|
|
//
|
|
|
|
if (Open->ReferenceCount == 0) {
|
|
|
|
//
|
|
// Check if the MaxLookAhead needs adjustment.
|
|
//
|
|
|
|
if (Open->LookAhead == Adapter->MaxLookAhead) {
|
|
|
|
MlidAdjustMaxLookAhead(Adapter);
|
|
|
|
}
|
|
|
|
|
|
if (Adapter->OpenQueue == NULL) {
|
|
|
|
//
|
|
// We can disable the card.
|
|
//
|
|
|
|
if (NdisSynchronizeWithInterrupt(
|
|
&(Adapter->NdisInterrupt),
|
|
(PVOID)MlidSyncCloseAdapter,
|
|
(PVOID)(&(Adapter->LMAdapter))
|
|
) == FALSE) {
|
|
|
|
NdisWriteErrorLogEntry(
|
|
Adapter->NdisAdapterHandle,
|
|
NDIS_ERROR_CODE_HARDWARE_FAILURE,
|
|
0
|
|
);
|
|
|
|
IF_LOUD( DbgPrint("CloseAdapter FAILED!\n");)
|
|
|
|
} else {
|
|
|
|
|
|
IF_LOUD( DbgPrint("CloseAdapter Success!\n");)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
//
|
|
// Will get removed when count drops to zero.
|
|
//
|
|
|
|
StatusToReturn = NDIS_STATUS_PENDING;
|
|
|
|
}
|
|
|
|
|
|
MLID_DO_DEFERRED(Adapter);
|
|
|
|
return(StatusToReturn);
|
|
|
|
}
|
|
|
|
NDIS_STATUS
|
|
MlidRequest(
|
|
IN NDIS_HANDLE MacBindingHandle,
|
|
IN PNDIS_REQUEST NdisRequest
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine allows a protocol to query and set information
|
|
about the MAC.
|
|
|
|
Arguments:
|
|
|
|
MacBindingHandle - The context value returned by the MAC when the
|
|
adapter was opened. In reality, it is a pointer to PMLID_OPEN.
|
|
|
|
NdisRequest - A structure which contains the request type (Set or
|
|
Query), an array of operations to perform, and an array for holding
|
|
the results of the operations.
|
|
|
|
Return Value:
|
|
|
|
The function value is the status of the operation.
|
|
|
|
--*/
|
|
|
|
{
|
|
NDIS_STATUS StatusToReturn = NDIS_STATUS_SUCCESS;
|
|
|
|
PMLID_OPEN Open = (PMLID_OPEN)(MacBindingHandle);
|
|
PMLID_ADAPTER Adapter = (Open->Adapter);
|
|
|
|
|
|
IF_LOUD( DbgPrint("In Request\n");)
|
|
|
|
NdisAcquireSpinLock(&Adapter->Lock);
|
|
|
|
//
|
|
// Ensure that the open does not close while in this function.
|
|
//
|
|
|
|
Open->ReferenceCount++;
|
|
|
|
Adapter->References++;
|
|
|
|
//
|
|
// Process request
|
|
//
|
|
|
|
if (Open->Closing) {
|
|
|
|
NdisReleaseSpinLock(&Adapter->Lock);
|
|
|
|
StatusToReturn = NDIS_STATUS_CLOSING;
|
|
|
|
} else if (NdisRequest->RequestType == NdisRequestQueryInformation) {
|
|
|
|
NdisReleaseSpinLock(&Adapter->Lock);
|
|
|
|
StatusToReturn = MlidQueryInformation(Adapter, Open, NdisRequest);
|
|
|
|
} else if (NdisRequest->RequestType == NdisRequestSetInformation) {
|
|
|
|
if (Adapter->HardwareFailure) {
|
|
|
|
NdisReleaseSpinLock(&Adapter->Lock);
|
|
|
|
StatusToReturn = NDIS_STATUS_FAILURE;
|
|
|
|
} else {
|
|
|
|
NdisReleaseSpinLock(&Adapter->Lock);
|
|
|
|
StatusToReturn = MlidSetInformation(Adapter,Open,NdisRequest);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
NdisReleaseSpinLock(&Adapter->Lock);
|
|
|
|
StatusToReturn = NDIS_STATUS_NOT_RECOGNIZED;
|
|
|
|
}
|
|
|
|
NdisAcquireSpinLock(&Adapter->Lock);
|
|
|
|
MlidRemoveReference(Open);
|
|
|
|
MLID_DO_DEFERRED(Adapter);
|
|
|
|
IF_LOUD( DbgPrint("Out Request\n");)
|
|
|
|
return(StatusToReturn);
|
|
|
|
}
|
|
|
|
NDIS_STATUS
|
|
MlidQueryProtocolInformation(
|
|
IN PMLID_ADAPTER Adapter,
|
|
IN PMLID_OPEN Open,
|
|
IN NDIS_OID Oid,
|
|
IN BOOLEAN GlobalMode,
|
|
IN PVOID InfoBuffer,
|
|
IN UINT BytesLeft,
|
|
OUT PUINT BytesNeeded,
|
|
OUT PUINT BytesWritten
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
The MlidQueryProtocolInformation process a Query request for
|
|
NDIS_OIDs that are specific to a binding about the MAC. Note that
|
|
some of the OIDs that are specific to bindings are also queryable
|
|
on a global basis. Rather than recreate this code to handle the
|
|
global queries, I use a flag to indicate if this is a query for the
|
|
global data or the binding specific data.
|
|
|
|
Arguments:
|
|
|
|
Adapter - a pointer to the adapter.
|
|
|
|
Open - a pointer to the open instance.
|
|
|
|
Oid - the NDIS_OID to process.
|
|
|
|
GlobalMode - Some of the binding specific information is also used
|
|
when querying global statistics. This is a flag to specify whether
|
|
to return the global value, or the binding specific value.
|
|
|
|
PlaceInInfoBuffer - a pointer into the NdisRequest->InformationBuffer
|
|
into which store the result of the query.
|
|
|
|
BytesLeft - the number of bytes left in the InformationBuffer.
|
|
|
|
BytesNeeded - If there is not enough room in the information buffer
|
|
then this will contain the number of bytes needed to complete the
|
|
request.
|
|
|
|
BytesWritten - a pointer to the number of bytes written into the
|
|
InformationBuffer.
|
|
|
|
Return Value:
|
|
|
|
The function value is the status of the operation.
|
|
|
|
--*/
|
|
|
|
{
|
|
NDIS_MEDIUM Medium = NdisMedium802_3;
|
|
ULONG GenericULong;
|
|
USHORT GenericUShort;
|
|
UCHAR GenericArray[6];
|
|
|
|
NDIS_STATUS StatusToReturn = NDIS_STATUS_SUCCESS;
|
|
|
|
//
|
|
// Common variables for pointing to result of query
|
|
//
|
|
|
|
PVOID MoveSource = (PVOID)(&GenericULong);
|
|
ULONG MoveBytes = sizeof(ULONG);
|
|
|
|
NDIS_HARDWARE_STATUS HardwareStatus = NdisHardwareStatusReady;
|
|
|
|
//
|
|
// General Algorithm:
|
|
//
|
|
// Switch(Request)
|
|
// Get requested information
|
|
// Store results in a common variable.
|
|
// Copy result in common variable to result buffer.
|
|
//
|
|
|
|
//
|
|
// Make sure that ulong is 4 bytes. Else GenericULong must change
|
|
// to something of size 4.
|
|
//
|
|
ASSERT(sizeof(ULONG) == 4);
|
|
|
|
|
|
IF_LOUD( DbgPrint("In QueryProtocol\n");)
|
|
|
|
//
|
|
// Make sure no changes occur while processing.
|
|
//
|
|
|
|
NdisAcquireSpinLock(&Adapter->Lock);
|
|
|
|
//
|
|
// Switch on request type
|
|
//
|
|
|
|
switch (Oid) {
|
|
|
|
case OID_GEN_MAC_OPTIONS:
|
|
|
|
GenericULong = (ULONG)(NDIS_MAC_OPTION_TRANSFERS_NOT_PEND |
|
|
NDIS_MAC_OPTION_RECEIVE_SERIALIZED |
|
|
NDIS_MAC_OPTION_NO_LOOPBACK
|
|
);
|
|
|
|
break;
|
|
|
|
case OID_GEN_SUPPORTED_LIST:
|
|
|
|
if (Adapter->TokenRing) {
|
|
|
|
//*\\ token ring
|
|
|
|
break;
|
|
}
|
|
|
|
if (!GlobalMode) {
|
|
|
|
MoveSource = (PVOID)(MlidProtocolSupportedOids);
|
|
MoveBytes = sizeof(MlidProtocolSupportedOids);
|
|
|
|
} else {
|
|
|
|
MoveSource = (PVOID)(MlidGlobalSupportedOids);
|
|
MoveBytes = sizeof(MlidGlobalSupportedOids);
|
|
|
|
}
|
|
break;
|
|
|
|
case OID_GEN_HARDWARE_STATUS:
|
|
|
|
if (Adapter->HardwareFailure) {
|
|
|
|
HardwareStatus = NdisHardwareStatusNotReady;
|
|
|
|
} else {
|
|
|
|
HardwareStatus = NdisHardwareStatusReady;
|
|
|
|
}
|
|
|
|
MoveSource = (PVOID)(&HardwareStatus);
|
|
MoveBytes = sizeof(NDIS_HARDWARE_STATUS);
|
|
|
|
break;
|
|
|
|
case OID_GEN_MEDIA_SUPPORTED:
|
|
case OID_GEN_MEDIA_IN_USE:
|
|
|
|
if (Adapter->TokenRing) {
|
|
|
|
Medium = NdisMedium802_5;
|
|
|
|
}
|
|
|
|
MoveSource = (PVOID) (&Medium);
|
|
MoveBytes = sizeof(NDIS_MEDIUM);
|
|
break;
|
|
|
|
case OID_GEN_MAXIMUM_LOOKAHEAD:
|
|
|
|
GenericULong = MLID_MAX_LOOKAHEAD;
|
|
|
|
break;
|
|
|
|
|
|
case OID_GEN_MAXIMUM_FRAME_SIZE:
|
|
|
|
if (Adapter->TokenRing) {
|
|
|
|
GenericULong = Adapter->xmit_buf_size - MLID_HEADER_SIZE;
|
|
|
|
} else {
|
|
|
|
GenericULong = (ULONG)(MLID_MAX_PACKET_SIZE - MLID_HEADER_SIZE);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
case OID_GEN_MAXIMUM_TOTAL_SIZE:
|
|
|
|
if (Adapter->TokenRing) {
|
|
|
|
GenericULong = Adapter->xmit_buf_size;
|
|
|
|
} else {
|
|
|
|
GenericULong = (ULONG)(MLID_MAX_PACKET_SIZE);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
case OID_GEN_LINK_SPEED:
|
|
|
|
if (Adapter->TokenRing) {
|
|
|
|
if ((Adapter->media_type & MEDIA_UTP_16) ||
|
|
(Adapter->media_type & MEDIA_STP_16)) {
|
|
|
|
GenericULong = 160000;
|
|
|
|
} else {
|
|
|
|
GenericULong = 40000;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
GenericULong = (ULONG)(100000);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
case OID_GEN_TRANSMIT_BUFFER_SPACE:
|
|
|
|
GenericULong = (ULONG)(Adapter->num_of_tx_buffs
|
|
* Adapter->xmit_buf_size);
|
|
|
|
break;
|
|
|
|
case OID_GEN_RECEIVE_BUFFER_SPACE:
|
|
|
|
GenericULong = (ULONG)((Adapter->ram_size * 1024) -
|
|
(Adapter->num_of_tx_buffs
|
|
* Adapter->xmit_buf_size));
|
|
|
|
break;
|
|
|
|
case OID_GEN_TRANSMIT_BLOCK_SIZE:
|
|
|
|
GenericULong = (ULONG)(Adapter->buffer_page_size);
|
|
|
|
break;
|
|
|
|
case OID_GEN_RECEIVE_BLOCK_SIZE:
|
|
|
|
GenericULong = (ULONG)(Adapter->buffer_page_size);
|
|
|
|
break;
|
|
|
|
case OID_GEN_VENDOR_ID:
|
|
|
|
NdisMoveMemory(
|
|
(PVOID)&GenericULong,
|
|
Adapter->permanent_node_address,
|
|
3
|
|
);
|
|
GenericULong &= 0xFFFFFF00;
|
|
MoveSource = (PVOID)(&GenericULong);
|
|
MoveBytes = sizeof(GenericULong);
|
|
break;
|
|
|
|
case OID_GEN_VENDOR_DESCRIPTION:
|
|
|
|
MoveSource = (PVOID)"SMC Adapter.";
|
|
MoveBytes = 13;
|
|
|
|
break;
|
|
|
|
case OID_GEN_DRIVER_VERSION:
|
|
|
|
GenericUShort = ((USHORT)MLID_NDIS_MAJOR_VERSION << 8) |
|
|
MLID_NDIS_MINOR_VERSION;
|
|
|
|
MoveSource = (PVOID)(&GenericUShort);
|
|
MoveBytes = sizeof(GenericUShort);
|
|
break;
|
|
|
|
|
|
case OID_GEN_CURRENT_PACKET_FILTER:
|
|
|
|
if (Adapter->TokenRing) {
|
|
|
|
StatusToReturn = NDIS_STATUS_NOT_SUPPORTED;
|
|
|
|
//*\\ token ring
|
|
|
|
break;
|
|
}
|
|
|
|
if (GlobalMode) {
|
|
|
|
UINT Filter;
|
|
|
|
Filter = ETH_QUERY_FILTER_CLASSES(Adapter->FilterDB);
|
|
|
|
GenericULong = (ULONG)(Filter);
|
|
|
|
} else {
|
|
|
|
UINT Filter = 0;
|
|
|
|
Filter = ETH_QUERY_PACKET_FILTER(Adapter->FilterDB,
|
|
Open->NdisFilterHandle);
|
|
|
|
GenericULong = (ULONG)(Filter);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case OID_GEN_CURRENT_LOOKAHEAD:
|
|
|
|
if ( GlobalMode ) {
|
|
|
|
GenericULong = (ULONG)(Adapter->MaxLookAhead);
|
|
|
|
} else {
|
|
|
|
GenericULong = Open->LookAhead;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case OID_802_3_PERMANENT_ADDRESS:
|
|
|
|
if (Adapter->TokenRing) {
|
|
|
|
StatusToReturn = NDIS_STATUS_NOT_SUPPORTED;
|
|
break;
|
|
}
|
|
|
|
MLID_MOVE_MEM((PCHAR)GenericArray,
|
|
Adapter->permanent_node_address,
|
|
ETH_LENGTH_OF_ADDRESS);
|
|
|
|
MoveSource = (PVOID)(GenericArray);
|
|
MoveBytes = sizeof(Adapter->permanent_node_address);
|
|
break;
|
|
|
|
case OID_802_3_CURRENT_ADDRESS:
|
|
|
|
if (Adapter->TokenRing) {
|
|
|
|
StatusToReturn = NDIS_STATUS_NOT_SUPPORTED;
|
|
break;
|
|
}
|
|
|
|
MLID_MOVE_MEM((PCHAR)GenericArray,
|
|
Adapter->node_address,
|
|
ETH_LENGTH_OF_ADDRESS);
|
|
|
|
MoveSource = (PVOID)(GenericArray);
|
|
MoveBytes = sizeof(Adapter->node_address);
|
|
break;
|
|
|
|
case OID_802_3_MULTICAST_LIST:
|
|
|
|
if (Adapter->TokenRing) {
|
|
|
|
StatusToReturn = NDIS_STATUS_NOT_SUPPORTED;
|
|
|
|
break;
|
|
}
|
|
|
|
{
|
|
UINT NumAddresses;
|
|
|
|
|
|
if (GlobalMode) {
|
|
|
|
NumAddresses = ETH_NUMBER_OF_GLOBAL_FILTER_ADDRESSES(Adapter->FilterDB);
|
|
|
|
if ((NumAddresses * ETH_LENGTH_OF_ADDRESS) > BytesLeft) {
|
|
|
|
*BytesNeeded = (NumAddresses * ETH_LENGTH_OF_ADDRESS);
|
|
|
|
StatusToReturn = NDIS_STATUS_INVALID_LENGTH;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
EthQueryGlobalFilterAddresses(
|
|
&StatusToReturn,
|
|
Adapter->FilterDB,
|
|
BytesLeft,
|
|
&NumAddresses,
|
|
InfoBuffer
|
|
);
|
|
|
|
*BytesWritten = NumAddresses * ETH_LENGTH_OF_ADDRESS;
|
|
|
|
//
|
|
// Should not be an error since we held the spinlock
|
|
// nothing should have changed.
|
|
//
|
|
|
|
ASSERT(StatusToReturn == NDIS_STATUS_SUCCESS);
|
|
|
|
} else {
|
|
|
|
NumAddresses = EthNumberOfOpenFilterAddresses(
|
|
Adapter->FilterDB,
|
|
Open->NdisFilterHandle
|
|
);
|
|
|
|
if ((NumAddresses * ETH_LENGTH_OF_ADDRESS) > BytesLeft) {
|
|
|
|
*BytesNeeded = (NumAddresses * ETH_LENGTH_OF_ADDRESS);
|
|
|
|
StatusToReturn = NDIS_STATUS_INVALID_LENGTH;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
EthQueryOpenFilterAddresses(
|
|
&StatusToReturn,
|
|
Adapter->FilterDB,
|
|
Open->NdisFilterHandle,
|
|
BytesLeft,
|
|
&NumAddresses,
|
|
InfoBuffer
|
|
);
|
|
|
|
//
|
|
// Should not be an error since we held the spinlock
|
|
// nothing should have changed.
|
|
//
|
|
|
|
ASSERT(StatusToReturn == NDIS_STATUS_SUCCESS);
|
|
|
|
*BytesWritten = NumAddresses * ETH_LENGTH_OF_ADDRESS;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
break;
|
|
|
|
case OID_802_3_MAXIMUM_LIST_SIZE:
|
|
|
|
if (Adapter->TokenRing) {
|
|
|
|
StatusToReturn = NDIS_STATUS_NOT_SUPPORTED;
|
|
break;
|
|
}
|
|
|
|
GenericULong = (ULONG) (Adapter->MulticastListMax);
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
StatusToReturn = NDIS_STATUS_NOT_SUPPORTED;
|
|
break;
|
|
}
|
|
|
|
if ((StatusToReturn == NDIS_STATUS_SUCCESS) &&
|
|
(Oid != OID_802_3_MULTICAST_LIST)) {
|
|
|
|
if (MoveBytes > BytesLeft) {
|
|
|
|
//
|
|
// Not enough room in InformationBuffer. Punt
|
|
//
|
|
|
|
*BytesNeeded = MoveBytes - BytesLeft;
|
|
|
|
StatusToReturn = NDIS_STATUS_INVALID_LENGTH;
|
|
|
|
} else {
|
|
|
|
//
|
|
// Store result.
|
|
//
|
|
|
|
MLID_MOVE_MEM(InfoBuffer, MoveSource, MoveBytes);
|
|
|
|
(*BytesWritten) += MoveBytes;
|
|
|
|
}
|
|
}
|
|
|
|
NdisReleaseSpinLock(&Adapter->Lock);
|
|
|
|
IF_LOUD( DbgPrint("Out QueryProtocol\n");)
|
|
|
|
return(StatusToReturn);
|
|
}
|
|
|
|
NDIS_STATUS
|
|
MlidQueryInformation(
|
|
IN PMLID_ADAPTER Adapter,
|
|
IN PMLID_OPEN Open,
|
|
IN PNDIS_REQUEST NdisRequest
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
The MlidQueryInformation is used by MlidRequest to query information
|
|
about the MAC.
|
|
|
|
Arguments:
|
|
|
|
Adapter - A pointer to the adapter.
|
|
|
|
Open - A pointer to a particular open instance.
|
|
|
|
NdisRequest - A structure which contains the request type (Query),
|
|
an array of operations to perform, and an array for holding
|
|
the results of the operations.
|
|
|
|
Return Value:
|
|
|
|
The function value is the status of the operation.
|
|
|
|
--*/
|
|
|
|
{
|
|
|
|
UINT BytesWritten = 0;
|
|
UINT BytesNeeded = 0;
|
|
UINT BytesLeft = NdisRequest->DATA.QUERY_INFORMATION.InformationBufferLength;
|
|
PUCHAR InfoBuffer = (PUCHAR)(NdisRequest->DATA.QUERY_INFORMATION.InformationBuffer);
|
|
|
|
NDIS_STATUS StatusToReturn = NDIS_STATUS_SUCCESS;
|
|
|
|
|
|
IF_LOUD( DbgPrint("In QueryInfor\n");)
|
|
|
|
StatusToReturn = MlidQueryProtocolInformation(
|
|
Adapter,
|
|
Open,
|
|
NdisRequest->DATA.QUERY_INFORMATION.Oid,
|
|
FALSE,
|
|
InfoBuffer,
|
|
BytesLeft,
|
|
&BytesNeeded,
|
|
&BytesWritten
|
|
);
|
|
|
|
|
|
NdisRequest->DATA.QUERY_INFORMATION.BytesWritten = BytesWritten;
|
|
|
|
NdisRequest->DATA.QUERY_INFORMATION.BytesNeeded = BytesNeeded;
|
|
|
|
IF_LOUD( DbgPrint("Out QueryInfor\n");)
|
|
|
|
return(StatusToReturn);
|
|
}
|
|
|
|
NDIS_STATUS
|
|
MlidSetInformation(
|
|
IN PMLID_ADAPTER Adapter,
|
|
IN PMLID_OPEN Open,
|
|
IN PNDIS_REQUEST NdisRequest
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
The MlidSetInformation is used by MlidRequest to set information
|
|
about the MAC.
|
|
|
|
Arguments:
|
|
|
|
Adapter - A pointer to the adapter.
|
|
|
|
Open - A pointer to an open instance.
|
|
|
|
NdisRequest - A structure which contains the request type (Set),
|
|
an array of operations to perform, and an array for holding
|
|
the results of the operations.
|
|
|
|
Return Value:
|
|
|
|
The function value is the status of the operation.
|
|
|
|
--*/
|
|
|
|
{
|
|
|
|
//
|
|
// General Algorithm:
|
|
//
|
|
// Verify length
|
|
// Switch(Request)
|
|
// Process Request
|
|
//
|
|
|
|
UINT BytesRead = 0;
|
|
UINT BytesNeeded = 0;
|
|
UINT BytesLeft = NdisRequest->DATA.SET_INFORMATION.InformationBufferLength;
|
|
PUCHAR InfoBuffer = (PUCHAR)(NdisRequest->DATA.SET_INFORMATION.InformationBuffer);
|
|
|
|
//
|
|
// Variables for a particular request
|
|
//
|
|
|
|
NDIS_OID Oid;
|
|
UINT OidLength;
|
|
|
|
//
|
|
// Variables for holding the new values to be used.
|
|
//
|
|
|
|
ULONG LookAhead;
|
|
ULONG Filter;
|
|
|
|
NDIS_STATUS StatusToReturn = NDIS_STATUS_SUCCESS;
|
|
|
|
|
|
IF_LOUD( DbgPrint("In SetInfo\n");)
|
|
|
|
|
|
|
|
//
|
|
// Get Oid and Length of request
|
|
//
|
|
|
|
Oid = NdisRequest->DATA.SET_INFORMATION.Oid;
|
|
|
|
OidLength = BytesLeft;
|
|
|
|
switch (Oid) {
|
|
|
|
|
|
case OID_802_3_MULTICAST_LIST:
|
|
|
|
if (Adapter->TokenRing) {
|
|
|
|
StatusToReturn = NDIS_STATUS_NOT_SUPPORTED;
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Verify length
|
|
//
|
|
|
|
if ((OidLength % ETH_LENGTH_OF_ADDRESS) != 0){
|
|
|
|
StatusToReturn = NDIS_STATUS_INVALID_LENGTH;
|
|
|
|
NdisRequest->DATA.SET_INFORMATION.BytesRead = 0;
|
|
NdisRequest->DATA.SET_INFORMATION.BytesNeeded = 0;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
StatusToReturn = MlidSetMulticastAddresses(
|
|
Adapter,
|
|
Open,
|
|
NdisRequest,
|
|
(UINT)(OidLength / ETH_LENGTH_OF_ADDRESS),
|
|
(PVOID)InfoBuffer
|
|
);
|
|
break;
|
|
|
|
|
|
case OID_GEN_CURRENT_PACKET_FILTER:
|
|
|
|
if (Adapter->TokenRing) {
|
|
|
|
//*\\ token ring
|
|
|
|
StatusToReturn = NDIS_STATUS_NOT_SUPPORTED;
|
|
break;
|
|
}
|
|
|
|
|
|
//
|
|
// Verify length
|
|
//
|
|
|
|
if (OidLength != 4 ) {
|
|
|
|
StatusToReturn = NDIS_STATUS_INVALID_LENGTH;
|
|
|
|
NdisRequest->DATA.SET_INFORMATION.BytesRead = 0;
|
|
NdisRequest->DATA.SET_INFORMATION.BytesNeeded = 0;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
MLID_MOVE_MEM(&Filter, InfoBuffer, 4);
|
|
|
|
//
|
|
// Verify bits
|
|
//
|
|
|
|
if (Filter & (NDIS_PACKET_TYPE_SOURCE_ROUTING |
|
|
NDIS_PACKET_TYPE_SMT |
|
|
NDIS_PACKET_TYPE_MAC_FRAME |
|
|
NDIS_PACKET_TYPE_FUNCTIONAL |
|
|
NDIS_PACKET_TYPE_ALL_FUNCTIONAL |
|
|
NDIS_PACKET_TYPE_GROUP
|
|
)) {
|
|
|
|
StatusToReturn = NDIS_STATUS_NOT_SUPPORTED;
|
|
|
|
NdisRequest->DATA.SET_INFORMATION.BytesRead = 4;
|
|
NdisRequest->DATA.SET_INFORMATION.BytesNeeded = 0;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
StatusToReturn = MlidSetPacketFilter(Adapter,
|
|
Open,
|
|
NdisRequest,
|
|
Filter
|
|
);
|
|
|
|
|
|
|
|
break;
|
|
|
|
case OID_GEN_CURRENT_LOOKAHEAD:
|
|
|
|
//
|
|
// Verify length
|
|
//
|
|
|
|
if (OidLength != 4) {
|
|
|
|
StatusToReturn = NDIS_STATUS_INVALID_LENGTH;
|
|
|
|
NdisRequest->DATA.SET_INFORMATION.BytesRead = 0;
|
|
NdisRequest->DATA.SET_INFORMATION.BytesNeeded = 0;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
MLID_MOVE_MEM(&LookAhead, InfoBuffer, 4);
|
|
|
|
if (LookAhead <= (MLID_MAX_LOOKAHEAD)) {
|
|
|
|
if (LookAhead > Adapter->MaxLookAhead) {
|
|
|
|
Adapter->MaxLookAhead = LookAhead;
|
|
|
|
Open->LookAhead = LookAhead;
|
|
|
|
} else {
|
|
|
|
if ((Open->LookAhead == Adapter->MaxLookAhead) &&
|
|
(LookAhead < Open->LookAhead)) {
|
|
|
|
Open->LookAhead = LookAhead;
|
|
|
|
MlidAdjustMaxLookAhead(Adapter);
|
|
|
|
} else {
|
|
|
|
Open->LookAhead = LookAhead;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
} else {
|
|
|
|
StatusToReturn = NDIS_STATUS_INVALID_LENGTH;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case OID_GEN_PROTOCOL_OPTIONS:
|
|
|
|
//
|
|
// Verify length
|
|
//
|
|
|
|
if (OidLength != 4) {
|
|
|
|
StatusToReturn = NDIS_STATUS_INVALID_LENGTH;
|
|
|
|
NdisRequest->DATA.SET_INFORMATION.BytesRead = 0;
|
|
NdisRequest->DATA.SET_INFORMATION.BytesNeeded = 0;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
MLID_MOVE_MEM(&Open->ProtOptionFlags, InfoBuffer, 4);
|
|
StatusToReturn = NDIS_STATUS_SUCCESS;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
StatusToReturn = NDIS_STATUS_NOT_SUPPORTED;
|
|
|
|
NdisRequest->DATA.SET_INFORMATION.BytesRead = 0;
|
|
NdisRequest->DATA.SET_INFORMATION.BytesNeeded = 0;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
if (StatusToReturn == NDIS_STATUS_SUCCESS) {
|
|
|
|
NdisRequest->DATA.SET_INFORMATION.BytesRead = BytesLeft;
|
|
NdisRequest->DATA.SET_INFORMATION.BytesNeeded = 0;
|
|
|
|
}
|
|
|
|
|
|
IF_LOUD( DbgPrint("Out SetInfo\n");)
|
|
|
|
return(StatusToReturn);
|
|
}
|
|
|
|
|
|
STATIC
|
|
NDIS_STATUS
|
|
MlidSetPacketFilter(
|
|
IN PMLID_ADAPTER Adapter,
|
|
IN PMLID_OPEN Open,
|
|
IN PNDIS_REQUEST NdisRequest,
|
|
IN UINT PacketFilter
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
The MlidSetPacketFilter request allows a protocol to control the types
|
|
of packets that it receives from the MAC.
|
|
|
|
Arguments:
|
|
|
|
Adapter - A pointer to the adapter structure.
|
|
|
|
Open - A pointer to the open block giving the request.
|
|
|
|
NdisRequest - The NDIS_REQUEST with the set packet filter command in it.
|
|
|
|
PacketFilter - A bit mask that contains flags that correspond to specific
|
|
classes of received packets. If a particular bit is set in the mask,
|
|
then packet reception for that class of packet is enabled. If the
|
|
bit is clear, then packets that fall into that class are not received
|
|
by the client. A single exception to this rule is that if the promiscuous
|
|
bit is set, then the client receives all packets on the network, regardless
|
|
of the state of the other flags.
|
|
|
|
Return Value:
|
|
|
|
The function value is the status of the operation.
|
|
|
|
--*/
|
|
|
|
{
|
|
//
|
|
// Keeps track of the *MAC's* status. The status will only be
|
|
// reset if the filter change action routine is called.
|
|
//
|
|
NDIS_STATUS StatusOfFilterChange = NDIS_STATUS_SUCCESS;
|
|
|
|
NdisAcquireSpinLock(&Adapter->Lock);
|
|
|
|
IF_LOUD( DbgPrint("In SetFilter\n");)
|
|
|
|
if (!Open->Closing) {
|
|
|
|
//
|
|
// Increment the open while it is going through the filtering
|
|
// routines.
|
|
//
|
|
|
|
Open->ReferenceCount++;
|
|
|
|
StatusOfFilterChange = EthFilterAdjust(
|
|
Adapter->FilterDB,
|
|
Open->NdisFilterHandle,
|
|
NdisRequest,
|
|
PacketFilter,
|
|
TRUE
|
|
);
|
|
|
|
Open->ReferenceCount--;
|
|
|
|
} else {
|
|
|
|
StatusOfFilterChange = NDIS_STATUS_CLOSING;
|
|
|
|
}
|
|
|
|
NdisReleaseSpinLock(&Adapter->Lock);
|
|
|
|
IF_LOUD( DbgPrint("Out SetFilter\n");)
|
|
|
|
return StatusOfFilterChange;
|
|
}
|
|
|
|
|
|
|
|
|
|
STATIC
|
|
NDIS_STATUS
|
|
MlidSetMulticastAddresses(
|
|
IN PMLID_ADAPTER Adapter,
|
|
IN PMLID_OPEN Open,
|
|
IN PNDIS_REQUEST NdisRequest,
|
|
IN UINT NumAddresses,
|
|
IN CHAR AddressList[][ETH_LENGTH_OF_ADDRESS]
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function calls into the filter package in order to set the
|
|
multicast address list for the card to the specified list.
|
|
|
|
Arguments:
|
|
|
|
Adapter - A pointer to the adapter block.
|
|
|
|
Open - A pointer to the open block submitting the request.
|
|
|
|
NdisRequest - The NDIS_REQUEST with the set multicast address list command
|
|
in it.
|
|
|
|
NumAddresses - A count of the number of addresses in the addressList.
|
|
|
|
AddressList - An array of multicast addresses that this open instance
|
|
wishes to accept.
|
|
|
|
|
|
Return Value:
|
|
|
|
The function value is the status of the operation.
|
|
|
|
--*/
|
|
|
|
{
|
|
|
|
//
|
|
// Keeps track of the *MAC's* status. The status will only be
|
|
// reset if the filter change action routine is called.
|
|
//
|
|
NDIS_STATUS StatusOfFilterChange = NDIS_STATUS_SUCCESS;
|
|
|
|
IF_LOUD( DbgPrint("In SetMulticast\n");)
|
|
|
|
NdisAcquireSpinLock(&Adapter->Lock);
|
|
|
|
if (!Open->Closing) {
|
|
|
|
//
|
|
// Increment the open while it is going through the filtering
|
|
// routines.
|
|
//
|
|
|
|
Open->ReferenceCount++;
|
|
|
|
StatusOfFilterChange = EthChangeFilterAddresses(
|
|
Adapter->FilterDB,
|
|
Open->NdisFilterHandle,
|
|
NdisRequest,
|
|
NumAddresses,
|
|
AddressList,
|
|
TRUE
|
|
);
|
|
Open->ReferenceCount--;
|
|
|
|
} else {
|
|
|
|
StatusOfFilterChange = NDIS_STATUS_CLOSING;
|
|
|
|
}
|
|
|
|
NdisReleaseSpinLock(&Adapter->Lock);
|
|
|
|
IF_LOUD( DbgPrint("Out SetMulticast\n");)
|
|
|
|
return StatusOfFilterChange;
|
|
}
|
|
|
|
|
|
|
|
NDIS_STATUS
|
|
MlidFillInGlobalData(
|
|
IN PMLID_ADAPTER Adapter,
|
|
IN PNDIS_REQUEST NdisRequest
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine completes a GlobalStatistics request. It is critical that
|
|
if information is needed from the Adapter->* fields, they have been
|
|
updated before this routine is called.
|
|
|
|
Arguments:
|
|
|
|
Adapter - A pointer to the Adapter.
|
|
|
|
NdisRequest - A structure which contains the request type (Global
|
|
Query), an array of operations to perform, and an array for holding
|
|
the results of the operations.
|
|
|
|
Return Value:
|
|
|
|
The function value is the status of the operation.
|
|
|
|
--*/
|
|
{
|
|
//
|
|
// General Algorithm:
|
|
//
|
|
// Switch(Request)
|
|
// Get requested information
|
|
// Store results in a common variable.
|
|
// default:
|
|
// Try protocol query information
|
|
// If that fails, fail query.
|
|
//
|
|
// Copy result in common variable to result buffer.
|
|
// Finish processing
|
|
|
|
UINT BytesWritten = 0;
|
|
UINT BytesNeeded = 0;
|
|
UINT BytesLeft = NdisRequest->DATA.QUERY_INFORMATION.InformationBufferLength;
|
|
PUCHAR InfoBuffer = (PUCHAR)(NdisRequest->DATA.QUERY_INFORMATION.InformationBuffer);
|
|
|
|
NDIS_STATUS StatusToReturn = NDIS_STATUS_SUCCESS;
|
|
|
|
//
|
|
// This variable holds result of query
|
|
//
|
|
|
|
ULONG GenericULong;
|
|
|
|
//
|
|
// Make sure that long is 4 bytes. Else GenericULong must change
|
|
// to something of size 4.
|
|
//
|
|
ASSERT(sizeof(ULONG) == 4);
|
|
|
|
|
|
StatusToReturn = MlidQueryProtocolInformation(
|
|
Adapter,
|
|
NULL,
|
|
NdisRequest->DATA.QUERY_INFORMATION.Oid,
|
|
TRUE,
|
|
InfoBuffer,
|
|
BytesLeft,
|
|
&BytesNeeded,
|
|
&BytesWritten
|
|
);
|
|
|
|
|
|
if (StatusToReturn == NDIS_STATUS_NOT_SUPPORTED) {
|
|
|
|
StatusToReturn = NDIS_STATUS_SUCCESS;
|
|
|
|
//
|
|
// Switch on request type
|
|
//
|
|
|
|
switch (NdisRequest->DATA.QUERY_INFORMATION.Oid) {
|
|
|
|
case OID_GEN_XMIT_OK:
|
|
|
|
GenericULong = (ULONG)(Adapter->FramesXmitGood);
|
|
|
|
break;
|
|
|
|
case OID_GEN_RCV_OK:
|
|
|
|
GenericULong = (ULONG)(Adapter->FramesRcvGood);
|
|
|
|
break;
|
|
|
|
case OID_GEN_XMIT_ERROR:
|
|
|
|
GenericULong = (ULONG)(Adapter->FramesXmitBad);
|
|
|
|
break;
|
|
|
|
case OID_GEN_RCV_ERROR:
|
|
|
|
if (Adapter->TokenRing) {
|
|
|
|
StatusToReturn = NDIS_STATUS_NOT_SUPPORTED;
|
|
break;
|
|
}
|
|
|
|
GenericULong = (ULONG)(Adapter->CrcErrors);
|
|
|
|
break;
|
|
|
|
case OID_GEN_RCV_NO_BUFFER:
|
|
|
|
if (Adapter->TokenRing) {
|
|
|
|
StatusToReturn = NDIS_STATUS_NOT_SUPPORTED;
|
|
break;
|
|
}
|
|
|
|
GenericULong = (ULONG)(Adapter->MissedPackets);
|
|
|
|
break;
|
|
|
|
case OID_802_3_RCV_ERROR_ALIGNMENT:
|
|
|
|
if (Adapter->TokenRing) {
|
|
|
|
StatusToReturn = NDIS_STATUS_NOT_SUPPORTED;
|
|
break;
|
|
}
|
|
|
|
GenericULong = (ULONG)(Adapter->FrameAlignmentErrors);
|
|
|
|
break;
|
|
|
|
case OID_802_3_XMIT_ONE_COLLISION:
|
|
|
|
if (Adapter->TokenRing) {
|
|
|
|
StatusToReturn = NDIS_STATUS_NOT_SUPPORTED;
|
|
break;
|
|
}
|
|
|
|
GenericULong = (ULONG)(Adapter->FramesXmitOneCollision);
|
|
|
|
break;
|
|
|
|
case OID_802_3_XMIT_MORE_COLLISIONS:
|
|
|
|
if (Adapter->TokenRing) {
|
|
|
|
StatusToReturn = NDIS_STATUS_NOT_SUPPORTED;
|
|
break;
|
|
}
|
|
|
|
GenericULong = (ULONG)(Adapter->FramesXmitManyCollisions);
|
|
|
|
break;
|
|
|
|
|
|
default:
|
|
|
|
StatusToReturn = NDIS_STATUS_NOT_SUPPORTED;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
//
|
|
// Check to make sure there is enough room in the
|
|
// buffer to store the result.
|
|
//
|
|
|
|
if (BytesLeft >= sizeof(ULONG)) {
|
|
|
|
//
|
|
// Store the result.
|
|
//
|
|
|
|
MLID_MOVE_MEM(
|
|
(PVOID)InfoBuffer,
|
|
(PVOID)(&GenericULong),
|
|
sizeof(ULONG)
|
|
);
|
|
|
|
BytesWritten += sizeof(ULONG);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
NdisRequest->DATA.QUERY_INFORMATION.BytesWritten = BytesWritten;
|
|
|
|
NdisRequest->DATA.QUERY_INFORMATION.BytesNeeded = BytesNeeded;
|
|
|
|
return(StatusToReturn);
|
|
}
|
|
|
|
NDIS_STATUS
|
|
MlidQueryGlobalStatistics(
|
|
IN NDIS_HANDLE MacAdapterContext,
|
|
IN PNDIS_REQUEST NdisRequest
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
The MlidQueryGlobalStatistics is used by the protocol to query
|
|
global information about the MAC.
|
|
|
|
Arguments:
|
|
|
|
MacAdapterContext - The value associated with the adapter that is being
|
|
opened when the MAC registered the adapter with NdisRegisterAdapter.
|
|
|
|
NdisRequest - A structure which contains the request type (Query),
|
|
an array of operations to perform, and an array for holding
|
|
the results of the operations.
|
|
|
|
Return Value:
|
|
|
|
The function value is the status of the operation.
|
|
|
|
--*/
|
|
|
|
{
|
|
|
|
//
|
|
// General Algorithm:
|
|
//
|
|
//
|
|
// Check if a request is going to pend...
|
|
// If so, pend the entire operation.
|
|
//
|
|
// Else
|
|
// Fill in the request block.
|
|
//
|
|
//
|
|
|
|
PMLID_ADAPTER Adapter = (PMLID_ADAPTER)(MacAdapterContext);
|
|
|
|
NDIS_STATUS StatusToReturn = NDIS_STATUS_SUCCESS;
|
|
|
|
//
|
|
// Check if a request is valid and going to pend...
|
|
// If so, pend the entire operation.
|
|
//
|
|
|
|
|
|
//
|
|
// Switch on request type
|
|
//
|
|
|
|
switch (NdisRequest->DATA.QUERY_INFORMATION.Oid) {
|
|
case OID_GEN_SUPPORTED_LIST:
|
|
case OID_GEN_HARDWARE_STATUS:
|
|
case OID_GEN_MEDIA_SUPPORTED:
|
|
case OID_GEN_MEDIA_IN_USE:
|
|
case OID_GEN_MAXIMUM_LOOKAHEAD:
|
|
case OID_GEN_MAXIMUM_FRAME_SIZE:
|
|
case OID_GEN_MAXIMUM_TOTAL_SIZE:
|
|
case OID_GEN_MAC_OPTIONS:
|
|
case OID_GEN_LINK_SPEED:
|
|
case OID_GEN_TRANSMIT_BUFFER_SPACE:
|
|
case OID_GEN_RECEIVE_BUFFER_SPACE:
|
|
case OID_GEN_TRANSMIT_BLOCK_SIZE:
|
|
case OID_GEN_RECEIVE_BLOCK_SIZE:
|
|
case OID_GEN_VENDOR_ID:
|
|
case OID_GEN_VENDOR_DESCRIPTION:
|
|
case OID_GEN_DRIVER_VERSION:
|
|
case OID_GEN_CURRENT_PACKET_FILTER:
|
|
case OID_GEN_CURRENT_LOOKAHEAD:
|
|
case OID_GEN_XMIT_OK:
|
|
case OID_GEN_RCV_OK:
|
|
case OID_GEN_XMIT_ERROR:
|
|
case OID_GEN_RCV_ERROR:
|
|
|
|
break;
|
|
|
|
case OID_802_3_PERMANENT_ADDRESS:
|
|
case OID_802_3_CURRENT_ADDRESS:
|
|
case OID_GEN_RCV_NO_BUFFER:
|
|
case OID_802_3_MULTICAST_LIST:
|
|
case OID_802_3_MAXIMUM_LIST_SIZE:
|
|
case OID_802_3_RCV_ERROR_ALIGNMENT:
|
|
case OID_802_3_XMIT_ONE_COLLISION:
|
|
case OID_802_3_XMIT_MORE_COLLISIONS:
|
|
|
|
if (Adapter->TokenRing) {
|
|
|
|
StatusToReturn = NDIS_STATUS_NOT_SUPPORTED;
|
|
break;
|
|
|
|
}
|
|
break;
|
|
|
|
default:
|
|
|
|
StatusToReturn = NDIS_STATUS_NOT_SUPPORTED;
|
|
|
|
break;
|
|
}
|
|
|
|
NdisInterlockedAddUlong(&Adapter->References, 1, &Adapter->Lock);
|
|
|
|
if (StatusToReturn == NDIS_STATUS_SUCCESS) {
|
|
|
|
StatusToReturn = MlidFillInGlobalData(Adapter, NdisRequest);
|
|
|
|
}
|
|
|
|
NdisAcquireSpinLock(&Adapter->Lock);
|
|
|
|
MLID_DO_DEFERRED(Adapter);
|
|
|
|
return(StatusToReturn);
|
|
}
|
|
|
|
|
|
VOID
|
|
MlidRemoveAdapter(
|
|
IN PVOID MacAdapterContext
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
MlidRemoveAdapter removes an adapter previously registered
|
|
with NdisRegisterAdapter.
|
|
|
|
Arguments:
|
|
|
|
MacAdapterContext - The context value that the MAC passed
|
|
to NdisRegisterAdapter; actually as pointer to an
|
|
MLID_ADAPTER.
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
{
|
|
|
|
PMLID_ADAPTER Adapter;
|
|
BOOLEAN Canceled;
|
|
|
|
Adapter = PMLID_ADAPTER_FROM_CONTEXT_HANDLE(MacAdapterContext);
|
|
|
|
LM_Free_Resources(&Adapter->LMAdapter);
|
|
|
|
ASSERT(Adapter->OpenQueue == (PMLID_OPEN)NULL);
|
|
|
|
//
|
|
// There are no opens left, so remove ourselves.
|
|
//
|
|
|
|
NdisCancelTimer(&Adapter->WakeUpTimer, &Canceled);
|
|
|
|
if ( !Canceled ) {
|
|
NdisStallExecution(500000);
|
|
}
|
|
|
|
//
|
|
// Take us out of the AdapterQueue.
|
|
//
|
|
|
|
NdisAcquireSpinLock(&MlidMacBlock.SpinLock);
|
|
|
|
Adapter->Removed = TRUE;
|
|
|
|
if (MlidMacBlock.AdapterQueue == Adapter) {
|
|
|
|
MlidMacBlock.AdapterQueue = Adapter->NextAdapter;
|
|
|
|
} else {
|
|
|
|
PMLID_ADAPTER TmpAdaptP = MlidMacBlock.AdapterQueue;
|
|
|
|
while (TmpAdaptP->NextAdapter != Adapter) {
|
|
|
|
TmpAdaptP = TmpAdaptP->NextAdapter;
|
|
|
|
}
|
|
|
|
TmpAdaptP->NextAdapter = TmpAdaptP->NextAdapter->NextAdapter;
|
|
}
|
|
|
|
NdisReleaseSpinLock(&MlidMacBlock.SpinLock);
|
|
|
|
NdisRemoveInterrupt(&(Adapter->NdisInterrupt));
|
|
|
|
NdisUnmapIoSpace(
|
|
Adapter->NdisAdapterHandle,
|
|
Adapter->ram_access,
|
|
Adapter->ram_size * 1024);
|
|
|
|
if (Adapter->TokenRing) {
|
|
|
|
//*\\ token ring
|
|
|
|
} else {
|
|
|
|
EthDeleteFilter(Adapter->FilterDB);
|
|
|
|
}
|
|
|
|
NdisDeregisterAdapter(Adapter->NdisAdapterHandle);
|
|
|
|
NdisFreeSpinLock(&Adapter->Lock);
|
|
|
|
NdisFreeMemory(Adapter, sizeof(MLID_ADAPTER), 0);
|
|
|
|
return;
|
|
}
|
|
|
|
VOID
|
|
MlidUnload(
|
|
IN NDIS_HANDLE MacMacContext
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
MlidUnload is called when the MAC is to unload itself.
|
|
|
|
Arguments:
|
|
|
|
MacMacContext - actually a pointer to MlidMacBlock.
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
|
|
{
|
|
NDIS_STATUS InitStatus;
|
|
|
|
UNREFERENCED_PARAMETER(MacMacContext);
|
|
|
|
NdisDeregisterMac(
|
|
&InitStatus,
|
|
MlidMacBlock.NdisMacHandle
|
|
);
|
|
|
|
NdisFreeSpinLock(&MlidMacBlock.SpinLock);
|
|
|
|
NdisTerminateWrapper(
|
|
MlidMacBlock.NdisWrapperHandle,
|
|
NULL
|
|
);
|
|
|
|
return;
|
|
}
|
|
|
|
NDIS_STATUS
|
|
MlidSend(
|
|
IN NDIS_HANDLE MacBindingHandle,
|
|
IN PNDIS_PACKET Packet
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
NDIS function. Sends a packet on the wire
|
|
|
|
Arguments:
|
|
|
|
See NDIS 3.0 spec.
|
|
|
|
--*/
|
|
|
|
{
|
|
PMLID_OPEN Open = PMLID_OPEN_FROM_BINDING_HANDLE(MacBindingHandle);
|
|
PMLID_ADAPTER Adapter = Open->Adapter;
|
|
PMAC_RESERVED Reserved = RESERVED(Packet);
|
|
UINT PacketLength;
|
|
NDIS_STATUS Status;
|
|
|
|
|
|
//
|
|
// Check that the packet is not too short or too long.
|
|
//
|
|
|
|
NdisQueryPacket(Packet, NULL, NULL, NULL, &PacketLength);
|
|
|
|
if (PacketLength < (ETH_LENGTH_OF_ADDRESS*2) || PacketLength > 1514) {
|
|
|
|
return NDIS_STATUS_FAILURE;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (Adapter->HardwareFailure) {
|
|
|
|
return(NDIS_STATUS_FAILURE);
|
|
|
|
}
|
|
|
|
if (Adapter->ResetInProgress) {
|
|
|
|
return(NDIS_STATUS_RESET_IN_PROGRESS);
|
|
|
|
}
|
|
|
|
//
|
|
// Ensure that the open won't close during this function.
|
|
//
|
|
|
|
if (Open->Closing) {
|
|
|
|
return NDIS_STATUS_CLOSING;
|
|
|
|
}
|
|
|
|
NdisAcquireSpinLock(&Adapter->Lock);
|
|
|
|
IF_LOG(LOG('s'));
|
|
|
|
Open->ReferenceCount++;
|
|
|
|
Adapter->References++;
|
|
|
|
//
|
|
// Set up the MacReserved section of the packet.
|
|
//
|
|
|
|
Reserved->Open = Open;
|
|
|
|
Reserved->NextPacket = (PNDIS_PACKET)NULL;
|
|
|
|
|
|
|
|
|
|
//
|
|
// Set Reserved->Loopback
|
|
//
|
|
|
|
MlidSetLoopbackFlag(Adapter, Open, Packet);
|
|
|
|
|
|
|
|
|
|
IF_LOUD( DbgPrint("Sending a packet for Open 0x%lx\n", Reserved->Open);)
|
|
|
|
|
|
//
|
|
// We do not Open->ReferenceCount-- because that will be done when
|
|
// then send completes.
|
|
//
|
|
|
|
|
|
if (Reserved->Directed) {
|
|
|
|
//
|
|
// Put it directly on loopback queue.
|
|
//
|
|
|
|
IF_VERY_LOUD( DbgPrint("Putting Packet 0x%lx on Loopback queue\n",Packet);)
|
|
|
|
IF_LOG(LOG('l'));
|
|
|
|
if (Adapter->LoopbackQueue == NULL) {
|
|
|
|
Adapter->LoopbackQueue = Adapter->LoopbackQTail = Packet;
|
|
|
|
} else {
|
|
|
|
RESERVED(Adapter->LoopbackQTail)->NextPacket = Packet;
|
|
|
|
Adapter->LoopbackQTail = Packet;
|
|
|
|
}
|
|
|
|
Status = NDIS_STATUS_PENDING;
|
|
|
|
} else {
|
|
|
|
//
|
|
// Put Packet on queue to hit the wire.
|
|
//
|
|
|
|
if (Adapter->XmitQueue != NULL) {
|
|
|
|
IF_LOG(LOG('q'));
|
|
|
|
RESERVED(Adapter->XmitQTail)->NextPacket = Packet;
|
|
|
|
Adapter->XmitQTail = Packet;
|
|
|
|
} else {
|
|
|
|
PNDIS_PACKET PreviousTail;
|
|
|
|
//
|
|
// We have to assume it will be sent. In case the send completes
|
|
// before we have time to add it.
|
|
//
|
|
|
|
if (Adapter->PacketsOnCard == NULL) {
|
|
|
|
PreviousTail = NULL;
|
|
|
|
Adapter->PacketsOnCard = Adapter->PacketsOnCardTail = Packet;
|
|
|
|
} else {
|
|
|
|
PreviousTail = Adapter->PacketsOnCardTail;
|
|
|
|
RESERVED(Adapter->PacketsOnCardTail)->NextPacket = Packet;
|
|
|
|
Adapter->PacketsOnCardTail = Packet;
|
|
|
|
}
|
|
|
|
IF_LOG(LOG('t'));
|
|
|
|
if (LM_Send(Packet, &Adapter->LMAdapter) == OUT_OF_RESOURCES) {
|
|
|
|
IF_LOG(LOG('Q'));
|
|
|
|
//
|
|
// Remove it from list of packets on card and add it to xmit
|
|
// queue.
|
|
//
|
|
|
|
if (PreviousTail == NULL) {
|
|
|
|
Adapter->PacketsOnCard = Adapter->PacketsOnCardTail = NULL;
|
|
|
|
} else {
|
|
|
|
Adapter->PacketsOnCardTail = PreviousTail;
|
|
|
|
RESERVED(Adapter->PacketsOnCardTail)->NextPacket = NULL;
|
|
|
|
}
|
|
|
|
Adapter->XmitQueue = Packet;
|
|
|
|
Adapter->XmitQTail = Packet;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
Status = NDIS_STATUS_PENDING;
|
|
|
|
}
|
|
|
|
|
|
MLID_DO_DEFERRED(Adapter);
|
|
|
|
IF_LOG(LOG('S'));
|
|
|
|
return Status;
|
|
|
|
}
|
|
|
|
UINT
|
|
MlidCompareMemory(
|
|
IN PUCHAR String1,
|
|
IN PUCHAR String2,
|
|
IN UINT Length
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Determines if two arrays of bytes are equal.
|
|
|
|
Arguments:
|
|
|
|
String1, String2 - the two arrays to check.
|
|
|
|
Length - the first length bytes to compare.
|
|
|
|
Return Value:
|
|
|
|
0 if equal, -1 if not.
|
|
|
|
--*/
|
|
{
|
|
UINT i;
|
|
|
|
for (i=0; i<Length; i++) {
|
|
if (String1[i] != String2[i]) {
|
|
return (UINT)(-1);
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
|
|
NDIS_STATUS
|
|
MlidReset(
|
|
IN NDIS_HANDLE MacBindingHandle
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
NDIS function.
|
|
|
|
Arguments:
|
|
|
|
See NDIS 3.0 spec.
|
|
|
|
--*/
|
|
|
|
{
|
|
PMLID_OPEN Open = ((PMLID_OPEN)MacBindingHandle);
|
|
PMLID_ADAPTER Adapter = Open->Adapter;
|
|
|
|
|
|
if (Open->Closing) {
|
|
|
|
return(NDIS_STATUS_CLOSING);
|
|
|
|
}
|
|
|
|
if (Adapter->ResetRequested) {
|
|
|
|
return(NDIS_STATUS_SUCCESS);
|
|
|
|
}
|
|
|
|
NdisAcquireSpinLock(&Adapter->Lock);
|
|
|
|
IF_LOUD( DbgPrint("In MlidReset\n");)
|
|
|
|
IF_LOG(LOG('r'));
|
|
|
|
//
|
|
// Ensure that the open does not close while in this function.
|
|
//
|
|
|
|
Open->ReferenceCount++;
|
|
|
|
Adapter->References++;
|
|
|
|
|
|
Adapter->ResetRequested = TRUE;
|
|
|
|
//
|
|
// Needed in case the reset pends somewhere along the line.
|
|
//
|
|
|
|
Adapter->ResetOpen = Open;
|
|
|
|
MLID_DO_DEFERRED(Adapter);
|
|
|
|
IF_LOUD( DbgPrint("Out MlidReset\n");)
|
|
|
|
return(NDIS_STATUS_PENDING);
|
|
|
|
}
|
|
|
|
STATIC
|
|
NDIS_STATUS
|
|
MlidChangeMulticastAddresses(
|
|
IN UINT OldFilterCount,
|
|
IN CHAR OldAddresses[][ETH_LENGTH_OF_ADDRESS],
|
|
IN UINT NewFilterCount,
|
|
IN CHAR NewAddresses[][ETH_LENGTH_OF_ADDRESS],
|
|
IN NDIS_HANDLE MacBindingHandle,
|
|
IN PNDIS_REQUEST NdisRequest,
|
|
IN BOOLEAN Set
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Action routine that will get called when a particular filter
|
|
class is first used or last cleared.
|
|
|
|
NOTE: This routine assumes that it is called with the lock
|
|
acquired.
|
|
|
|
Arguments:
|
|
|
|
|
|
OldFilterCount - The number of addresses that used to be on the card.
|
|
|
|
OldAddresses - A list of all the addresses that used to be on the card.
|
|
|
|
NewFilterCount - The number of addresses that should now be on the card.
|
|
|
|
NewAddresses - A list of addresses that should be put on the card.
|
|
|
|
MacBindingHandle - The context value returned by the MAC when the
|
|
adapter was opened. In reality, it is a pointer to MLID_OPEN.
|
|
|
|
NdisRequest - The request which submitted the filter change.
|
|
Must use when completing this request with the NdisCompleteRequest
|
|
service, if the MAC completes this request asynchronously.
|
|
|
|
Set - If true the change resulted from a set, otherwise the
|
|
change resulted from a open closing.
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
|
|
--*/
|
|
|
|
{
|
|
|
|
|
|
PMLID_ADAPTER Adapter = PMLID_ADAPTER_FROM_BINDING_HANDLE(MacBindingHandle);
|
|
|
|
UNREFERENCED_PARAMETER(Set);
|
|
UNREFERENCED_PARAMETER(NdisRequest);
|
|
UNREFERENCED_PARAMETER(OldAddresses);
|
|
UNREFERENCED_PARAMETER(OldFilterCount);
|
|
|
|
if (LM_Set_Multi_Address(NewAddresses, NewFilterCount, &Adapter->LMAdapter)
|
|
!= SUCCESS) {
|
|
|
|
return(NDIS_STATUS_FAILURE);
|
|
|
|
} else {
|
|
|
|
return(NDIS_STATUS_SUCCESS);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
STATIC
|
|
NDIS_STATUS
|
|
MlidChangeFilterClasses(
|
|
IN UINT OldFilterClasses,
|
|
IN UINT NewFilterClasses,
|
|
IN NDIS_HANDLE MacBindingHandle,
|
|
IN PNDIS_REQUEST NdisRequest,
|
|
IN BOOLEAN Set
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Action routine that will get called when an address is added to
|
|
the filter that wasn't referenced by any other open binding.
|
|
|
|
NOTE: This routine assumes that it is called with the lock
|
|
acquired.
|
|
|
|
Arguments:
|
|
|
|
OldFilterClasses - A bit mask that is currently on the card telling
|
|
which packet types to accept.
|
|
|
|
NewFilterClasses - A bit mask that should be put on the card telling
|
|
which packet types to accept.
|
|
|
|
MacBindingHandle - The context value returned by the MAC when the
|
|
adapter was opened. In reality, it is a pointer to MLID_OPEN.
|
|
|
|
NdisRequest - The NDIS_REQUEST which submitted the filter change command.
|
|
|
|
Set - A flag telling if the command is a result of a close or not.
|
|
|
|
Return Value:
|
|
|
|
Status of the change (successful or pending).
|
|
|
|
|
|
--*/
|
|
|
|
{
|
|
|
|
PMLID_ADAPTER Adapter = PMLID_ADAPTER_FROM_BINDING_HANDLE(MacBindingHandle);
|
|
|
|
UNREFERENCED_PARAMETER(Set);
|
|
UNREFERENCED_PARAMETER(OldFilterClasses);
|
|
UNREFERENCED_PARAMETER(NewFilterClasses);
|
|
UNREFERENCED_PARAMETER(NdisRequest);
|
|
|
|
|
|
if (LM_Set_Receive_Mask(&(Adapter->LMAdapter)) != SUCCESS) {
|
|
|
|
return(NDIS_STATUS_FAILURE);
|
|
|
|
} else {
|
|
|
|
return(NDIS_STATUS_SUCCESS);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
STATIC
|
|
VOID
|
|
MlidCloseAction(
|
|
IN NDIS_HANDLE MacBindingHandle
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Action routine that will get called when a particular binding
|
|
was closed while it was indicating through NdisIndicateReceive
|
|
|
|
All this routine needs to do is to decrement the reference count
|
|
of the binding.
|
|
|
|
NOTE: This routine assumes that it is called with the lock acquired.
|
|
|
|
Arguments:
|
|
|
|
MacBindingHandle - The context value returned by the MAC when the
|
|
adapter was opened. In reality, it is a pointer to MLID_OPEN.
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
|
|
--*/
|
|
|
|
{
|
|
|
|
PMLID_OPEN_FROM_BINDING_HANDLE(MacBindingHandle)->ReferenceCount--;
|
|
|
|
}
|
|
|
|
BOOLEAN
|
|
MlidInterruptHandler(
|
|
IN PVOID ServiceContext
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This is the interrupt handler which is registered with the operating
|
|
system. Only one interrupt is handled at one time, even if several
|
|
are pending (i.e. transmit complete and receive).
|
|
|
|
Arguments:
|
|
|
|
ServiceContext - pointer to the adapter object
|
|
|
|
Return Value:
|
|
|
|
TRUE, if the DPC is to be executed, otherwise FALSE.
|
|
|
|
--*/
|
|
|
|
{
|
|
PMLID_ADAPTER Adapter = ((PMLID_ADAPTER)ServiceContext);
|
|
|
|
IF_LOUD( DbgPrint("In MlidISR\n");)
|
|
|
|
IF_LOG(LOG('i'));
|
|
|
|
//
|
|
// Force the INT signal from the chip low. When the
|
|
// interrupt is acknowledged interrupts will be unblocked,
|
|
// which will cause a rising edge on the interrupt line
|
|
// if there is another interrupt pending on the card.
|
|
//
|
|
|
|
IF_LOUD( DbgPrint( " blocking interrupts\n" );)
|
|
|
|
LM_Disable_Adapter(&Adapter->LMAdapter);
|
|
|
|
IF_LOG(LOG('I'));
|
|
|
|
return(TRUE);
|
|
|
|
}
|
|
|
|
VOID
|
|
MlidInterruptDpc(
|
|
IN PVOID SystemSpecific1,
|
|
IN PVOID InterruptContext,
|
|
IN PVOID SystemSpecific2,
|
|
IN PVOID SystemSpecific3
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This is the deffered processing routine for interrupts, it examines the
|
|
global 'InterruptReg' to determine what deffered processing is necessary
|
|
and dispatches control to the Rcv and Xmt handlers.
|
|
|
|
Arguments:
|
|
SystemSpecific1, SystemSpecific2, SystemSpecific3 - not used
|
|
InterruptContext - a handle to the adapter block.
|
|
|
|
Return Value:
|
|
|
|
NONE.
|
|
|
|
--*/
|
|
{
|
|
PMLID_ADAPTER Adapter = ((PMLID_ADAPTER)InterruptContext);
|
|
BOOLEAN RequeueRcv = FALSE;
|
|
|
|
UNREFERENCED_PARAMETER(SystemSpecific1);
|
|
UNREFERENCED_PARAMETER(SystemSpecific2);
|
|
UNREFERENCED_PARAMETER(SystemSpecific3);
|
|
|
|
IF_LOG(LOG('d'));
|
|
|
|
|
|
IF_LOUD( DbgPrint("==>IntDpc\n");)
|
|
|
|
NdisDprAcquireSpinLock(&Adapter->Lock);
|
|
|
|
if ( Adapter->ProcessingDpc ) {
|
|
NdisDprReleaseSpinLock(&Adapter->Lock);
|
|
return;
|
|
}
|
|
|
|
Adapter->ProcessingDpc = TRUE;
|
|
Adapter->References++;
|
|
|
|
do {
|
|
|
|
Adapter->WakeUpTimeout = FALSE;
|
|
|
|
NdisDprReleaseSpinLock(&Adapter->Lock);
|
|
|
|
RequeueRcv = MlidReceiveEvents(NULL, (PVOID)Adapter, NULL, NULL);
|
|
|
|
NdisDprAcquireSpinLock(&Adapter->Lock);
|
|
|
|
MlidTransmitEvents(Adapter);
|
|
|
|
//
|
|
// This causes any transmit that may have caused a tranmitted packet
|
|
// to loopback and indicate the packet.
|
|
//
|
|
|
|
} while ( (Adapter->LoopbackQueue != (PNDIS_PACKET)NULL) || RequeueRcv);
|
|
|
|
Adapter->ProcessingDpc = FALSE;
|
|
|
|
//
|
|
// Reenable interrupts
|
|
//
|
|
|
|
Adapter->InterruptMask = PACKET_RECEIVE_ENABLE |
|
|
PACKET_TRANSMIT_ENABLE |
|
|
RECEIVE_ERROR_ENABLE |
|
|
TRANSMIT_ERROR_ENABLE |
|
|
OVERWRITE_WARNING_ENABLE |
|
|
COUNTER_OVERFLOW_ENABLE;
|
|
|
|
NdisSynchronizeWithInterrupt(
|
|
&(Adapter->NdisInterrupt),
|
|
LM_Enable_Adapter,
|
|
&Adapter->LMAdapter
|
|
);
|
|
|
|
MLID_DO_DEFERRED(Adapter);
|
|
|
|
IF_LOUD( DbgPrint("<==IntDpc\n");)
|
|
|
|
IF_LOG(LOG('D'));
|
|
|
|
}
|
|
|
|
VOID
|
|
MlidIndicateLoopbackPacket(
|
|
IN PMLID_ADAPTER Adapter,
|
|
IN PNDIS_PACKET Packet
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine indicates a packet to the current host.
|
|
|
|
NOTE: THIS ROUTINE MUST BE CALLED WITH THE SPINLOCK HELD.
|
|
|
|
Arguments:
|
|
|
|
Adapter - Pointer to the adapter structure.
|
|
|
|
Packet - Pointer to the packet to indicate.
|
|
|
|
Return Value:
|
|
|
|
NONE.
|
|
|
|
--*/
|
|
{
|
|
UINT IndicateLen;
|
|
UINT PacketLen;
|
|
|
|
//
|
|
// Store that we are indicating a loopback packet
|
|
//
|
|
|
|
Adapter->IndicatingPacket = Packet;
|
|
Adapter->IndicatedAPacket = TRUE;
|
|
|
|
//
|
|
// Indicate packet.
|
|
//
|
|
|
|
IF_LOUD( DbgPrint("Indicating loopback packet\n");)
|
|
|
|
//
|
|
// Indicate up to 252 bytes.
|
|
//
|
|
|
|
NdisQueryPacket(Packet, NULL, NULL, NULL, &PacketLen);
|
|
|
|
if (PacketLen >= ETH_LENGTH_OF_ADDRESS) {
|
|
|
|
IndicateLen = (PacketLen > (Adapter->MaxLookAhead + MLID_HEADER_SIZE) ?
|
|
(Adapter->MaxLookAhead + MLID_HEADER_SIZE) :
|
|
PacketLen
|
|
);
|
|
|
|
//
|
|
// Copy the lookahead data into a contiguous buffer.
|
|
//
|
|
|
|
MlidCopyOver(Adapter->LookAhead,
|
|
Packet,
|
|
0,
|
|
IndicateLen
|
|
);
|
|
|
|
NdisDprReleaseSpinLock(&Adapter->Lock);
|
|
|
|
|
|
//
|
|
// Indicate packet
|
|
//
|
|
|
|
if (Adapter->TokenRing) {
|
|
|
|
//*\\ token ring
|
|
|
|
} else {
|
|
|
|
if (PacketLen < MLID_HEADER_SIZE) {
|
|
|
|
//
|
|
// Runt packet
|
|
//
|
|
|
|
EthFilterIndicateReceive(
|
|
Adapter->FilterDB,
|
|
(NDIS_HANDLE)Adapter,
|
|
(PCHAR)Adapter->LookAhead,
|
|
Adapter->LookAhead,
|
|
PacketLen,
|
|
NULL,
|
|
0,
|
|
0
|
|
);
|
|
|
|
} else {
|
|
|
|
EthFilterIndicateReceive(
|
|
Adapter->FilterDB,
|
|
(NDIS_HANDLE)Adapter,
|
|
(PCHAR)Adapter->LookAhead,
|
|
Adapter->LookAhead,
|
|
MLID_HEADER_SIZE,
|
|
Adapter->LookAhead + MLID_HEADER_SIZE,
|
|
IndicateLen - MLID_HEADER_SIZE,
|
|
PacketLen - MLID_HEADER_SIZE
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
NdisDprAcquireSpinLock(&Adapter->Lock);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
BOOLEAN
|
|
MlidReceiveEvents(
|
|
IN PVOID SystemSpecific1,
|
|
IN PVOID Context,
|
|
IN PVOID SystemSpecific2,
|
|
IN PVOID SystemSpecific3
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine handles all Receive deferred processing, this includes any
|
|
packets that never went through the XmitQueue and need to be indicated
|
|
(Loopbacked), and all card events.
|
|
|
|
Arguments:
|
|
|
|
Context - a handle to the adapter block.
|
|
|
|
Return Value:
|
|
|
|
Do we need to requeue this Rcv.
|
|
|
|
--*/
|
|
{
|
|
|
|
PMLID_ADAPTER Adapter = (PMLID_ADAPTER)(Context);
|
|
PNDIS_PACKET Packet;
|
|
PMLID_OPEN TmpOpen;
|
|
NDIS_STATUS Status;
|
|
BOOLEAN RequeueRcv;
|
|
|
|
IF_LOG(LOG('e'));
|
|
|
|
NdisDprAcquireSpinLock(&Adapter->Lock);
|
|
|
|
Adapter->References++;
|
|
|
|
RequeueRcv = (BOOLEAN)(LM_Service_Receive_Events(&Adapter->LMAdapter) ==
|
|
REQUEUE_LATER);
|
|
|
|
while (Adapter->LoopbackQueue != NULL) {
|
|
|
|
//
|
|
// Take packet off queue.
|
|
//
|
|
|
|
Packet = Adapter->LoopbackQueue;
|
|
|
|
if (Packet == Adapter->LoopbackQTail) {
|
|
|
|
Adapter->LoopbackQTail = NULL;
|
|
|
|
}
|
|
|
|
Adapter->LoopbackQueue = RESERVED(Packet)->NextPacket;
|
|
|
|
//
|
|
// Indicate the packet
|
|
//
|
|
|
|
MlidIndicateLoopbackPacket(Adapter,Packet);
|
|
|
|
|
|
//
|
|
// Complete the packet send.
|
|
//
|
|
|
|
Adapter->FramesXmitGood++;
|
|
|
|
//
|
|
// Save this, since once we complete the send
|
|
// Reserved is no longer valid.
|
|
//
|
|
|
|
TmpOpen = RESERVED(Packet)->Open;
|
|
|
|
IF_VERY_LOUD( DbgPrint("Completing send for packet 0x%x\n",Packet);)
|
|
|
|
NdisDprReleaseSpinLock(&Adapter->Lock);
|
|
|
|
NdisCompleteSend(TmpOpen->NdisBindingContext,
|
|
Packet,
|
|
NDIS_STATUS_SUCCESS
|
|
);
|
|
|
|
NdisDprAcquireSpinLock(&Adapter->Lock);
|
|
|
|
MlidRemoveReference(TmpOpen);
|
|
|
|
}
|
|
|
|
//
|
|
// If any indications done, then
|
|
//
|
|
// CompleteIndications();
|
|
//
|
|
|
|
if (Adapter->IndicatedAPacket) {
|
|
|
|
Adapter->IndicatedAPacket = FALSE;
|
|
|
|
NdisDprReleaseSpinLock(&Adapter->Lock);
|
|
|
|
if (Adapter->TokenRing) {
|
|
|
|
//*\\ token ring
|
|
|
|
} else {
|
|
|
|
EthFilterIndicateReceiveComplete(Adapter->FilterDB);
|
|
|
|
}
|
|
|
|
NdisDprAcquireSpinLock(&Adapter->Lock);
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((Adapter->ResetRequested) && (Adapter->References == 1)) {
|
|
|
|
PNDIS_PACKET Packet;
|
|
PMLID_OPEN TmpOpen;
|
|
|
|
IF_LOG(LOG('R'));
|
|
|
|
IF_VERY_LOUD( DbgPrint("Starting Reset\n");)
|
|
|
|
Adapter->ResetInProgress = TRUE;
|
|
|
|
NdisSynchronizeWithInterrupt(
|
|
&(Adapter->NdisInterrupt),
|
|
LM_Disable_Adapter,
|
|
&Adapter->LMAdapter
|
|
);
|
|
|
|
//
|
|
// Indicate Status to all opens
|
|
//
|
|
|
|
IF_VERY_LOUD( DbgPrint("Indicating status\n");)
|
|
|
|
TmpOpen = Adapter->OpenQueue;
|
|
|
|
while (TmpOpen != (PMLID_OPEN)NULL) {
|
|
|
|
AddRefWhileHoldingSpinLock(Adapter, TmpOpen);
|
|
|
|
NdisDprReleaseSpinLock(&Adapter->Lock);
|
|
|
|
NdisIndicateStatus(TmpOpen->NdisBindingContext,
|
|
NDIS_STATUS_RESET_START,
|
|
NULL,
|
|
0
|
|
);
|
|
|
|
|
|
NdisDprAcquireSpinLock(&Adapter->Lock);
|
|
|
|
MlidRemoveReference(TmpOpen);
|
|
|
|
TmpOpen = TmpOpen->NextOpen;
|
|
|
|
}
|
|
|
|
//
|
|
// Reset the Card.
|
|
//
|
|
|
|
IF_VERY_LOUD( DbgPrint("Resetting the card\n");)
|
|
|
|
if (LM_Initialize_Adapter(&Adapter->LMAdapter) != SUCCESS) {
|
|
|
|
Adapter->HardwareFailure = TRUE;
|
|
|
|
NdisWriteErrorLogEntry(
|
|
Adapter->NdisAdapterHandle,
|
|
NDIS_ERROR_CODE_HARDWARE_FAILURE,
|
|
0
|
|
);
|
|
|
|
} else {
|
|
|
|
Adapter->HardwareFailure = FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
// Put packets that were on the card on to the front of the xmit
|
|
// queue.
|
|
//
|
|
|
|
if (Adapter->PacketsOnCard != NULL) {
|
|
|
|
IF_VERY_LOUD( DbgPrint("Moving Packets On card\n");)
|
|
|
|
RESERVED(Adapter->PacketsOnCardTail)->NextPacket = Adapter->XmitQueue;
|
|
|
|
Adapter->XmitQueue = Adapter->PacketsOnCard;
|
|
|
|
Adapter->PacketsOnCard = Adapter->PacketsOnCardTail = NULL;
|
|
|
|
}
|
|
|
|
|
|
//
|
|
// Put packets on loopback queue on xmit queue
|
|
//
|
|
|
|
if (Adapter->LoopbackQueue != NULL) {
|
|
|
|
RESERVED(Adapter->LoopbackQTail)->NextPacket = Adapter->XmitQueue;
|
|
|
|
Adapter->XmitQueue = Adapter->LoopbackQueue;
|
|
|
|
}
|
|
|
|
|
|
//
|
|
// Wipe out loopback queue.
|
|
//
|
|
|
|
Adapter->LoopbackQueue = Adapter->LoopbackQTail = (PNDIS_PACKET)NULL;
|
|
|
|
|
|
//
|
|
// Abort all xmits
|
|
//
|
|
|
|
IF_VERY_LOUD( DbgPrint("Killing Xmits\n");)
|
|
|
|
while (Adapter->XmitQueue != NULL) {
|
|
|
|
Packet = Adapter->XmitQueue;
|
|
|
|
Adapter->XmitQueue = RESERVED(Packet)->NextPacket;
|
|
|
|
TmpOpen = RESERVED(Packet)->Open;
|
|
|
|
NdisDprReleaseSpinLock(&Adapter->Lock);
|
|
|
|
NdisCompleteSend(TmpOpen->NdisBindingContext,
|
|
Packet,
|
|
NDIS_STATUS_REQUEST_ABORTED
|
|
);
|
|
|
|
NdisDprAcquireSpinLock(&Adapter->Lock);
|
|
|
|
MlidRemoveReference(TmpOpen);
|
|
|
|
}
|
|
|
|
Adapter->XmitQTail = NULL;
|
|
|
|
if (!Adapter->HardwareFailure) {
|
|
|
|
LM_Open_Adapter(&Adapter->LMAdapter);
|
|
|
|
}
|
|
|
|
Adapter->ResetInProgress = FALSE;
|
|
|
|
IF_VERY_LOUD( DbgPrint("Indicating Done\n");)
|
|
|
|
//
|
|
// Indicate Reset is done
|
|
//
|
|
|
|
//
|
|
// Indicate Status to all opens
|
|
//
|
|
|
|
IF_VERY_LOUD( DbgPrint("Indicating status\n");)
|
|
|
|
TmpOpen = Adapter->OpenQueue;
|
|
|
|
while (TmpOpen != (PMLID_OPEN)NULL) {
|
|
|
|
AddRefWhileHoldingSpinLock(Adapter, TmpOpen);
|
|
|
|
NdisDprReleaseSpinLock(&Adapter->Lock);
|
|
|
|
if (Adapter->HardwareFailure) {
|
|
|
|
NdisIndicateStatus(TmpOpen->NdisBindingContext,
|
|
NDIS_STATUS_CLOSED,
|
|
NULL,
|
|
0
|
|
);
|
|
|
|
}
|
|
|
|
Status = (Adapter->HardwareFailure) ?
|
|
NDIS_STATUS_FAILURE :
|
|
NDIS_STATUS_SUCCESS;
|
|
|
|
|
|
NdisIndicateStatus(TmpOpen->NdisBindingContext,
|
|
NDIS_STATUS_RESET_END,
|
|
&Status,
|
|
sizeof(Status)
|
|
);
|
|
|
|
NdisIndicateStatusComplete(TmpOpen->NdisBindingContext);
|
|
|
|
NdisDprAcquireSpinLock(&Adapter->Lock);
|
|
|
|
MlidRemoveReference(TmpOpen);
|
|
|
|
TmpOpen = TmpOpen->NextOpen;
|
|
|
|
}
|
|
|
|
NdisDprReleaseSpinLock(&Adapter->Lock);
|
|
|
|
NdisCompleteReset(Adapter->ResetOpen->NdisBindingContext,
|
|
(Adapter->HardwareFailure) ?
|
|
NDIS_STATUS_FAILURE :
|
|
NDIS_STATUS_SUCCESS
|
|
);
|
|
|
|
NdisDprAcquireSpinLock(&Adapter->Lock);
|
|
|
|
MlidRemoveReference(Adapter->ResetOpen);
|
|
|
|
//
|
|
// Reset the flag
|
|
//
|
|
|
|
|
|
IF_VERY_LOUD( DbgPrint("Restarting Adapter\n");)
|
|
|
|
Adapter->ResetRequested = FALSE;
|
|
|
|
LM_Open_Adapter(&Adapter->LMAdapter);
|
|
|
|
}
|
|
|
|
#if DBG
|
|
|
|
else if (Adapter->ResetRequested) {
|
|
|
|
IF_LOUD( DbgPrint("No reset because count is... 0x%x\n", Adapter->References);)
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
Adapter->References--;
|
|
|
|
IF_LOG(LOG('E'));
|
|
|
|
NdisDprReleaseSpinLock(&Adapter->Lock);
|
|
|
|
return(RequeueRcv);
|
|
|
|
}
|
|
|
|
|
|
VOID
|
|
MlidTransmitEvents(
|
|
IN PMLID_ADAPTER Adapter
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine handles all transmit deferred processing.
|
|
|
|
NOTE : Called with lock held!!
|
|
|
|
Arguments:
|
|
|
|
Adapter - pointer to the adapter structure.
|
|
|
|
Return Value:
|
|
|
|
NONE.
|
|
|
|
--*/
|
|
{
|
|
|
|
if (Adapter->ResetInProgress) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
IF_LOG(LOG('w'));
|
|
|
|
LM_Service_Transmit_Events(&Adapter->LMAdapter);
|
|
|
|
IF_LOG(LOG('W'));
|
|
|
|
}
|
|
|
|
UINT
|
|
MlidCopyOver(
|
|
OUT PUCHAR Buf, // destination
|
|
IN PNDIS_PACKET Packet, // source packet
|
|
IN UINT Offset, // offset in packet
|
|
IN UINT Length // number of bytes to copy
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Copies bytes from a packet into a buffer. Used to copy data
|
|
out of a packet during loopback indications.
|
|
|
|
Arguments:
|
|
|
|
Buf - the destination buffer
|
|
Packet - the source packet
|
|
Offset - the offset in the packet to start copying at
|
|
Length - the number of bytes to copy
|
|
|
|
Return Value:
|
|
|
|
The actual number of bytes copied; will be less than Length if
|
|
the packet length is less than Offset+Length.
|
|
|
|
--*/
|
|
|
|
{
|
|
PNDIS_BUFFER CurBuffer;
|
|
UINT BytesCopied;
|
|
PUCHAR BufVA;
|
|
UINT BufLen;
|
|
UINT ToCopy;
|
|
UINT CurOffset;
|
|
|
|
|
|
BytesCopied = 0;
|
|
|
|
//
|
|
// First find a spot Offset bytes into the packet.
|
|
//
|
|
|
|
CurOffset = 0;
|
|
|
|
NdisQueryPacket(Packet, NULL, NULL, &CurBuffer, NULL);
|
|
|
|
while (CurBuffer != (PNDIS_BUFFER)NULL) {
|
|
|
|
NdisQueryBuffer(CurBuffer, (PVOID *)&BufVA, &BufLen);
|
|
|
|
if (CurOffset + BufLen > Offset) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
CurOffset += BufLen;
|
|
|
|
NdisGetNextBuffer(CurBuffer, &CurBuffer);
|
|
|
|
}
|
|
|
|
|
|
//
|
|
// See if the end of the packet has already been passed.
|
|
//
|
|
|
|
if (CurBuffer == (PNDIS_BUFFER)NULL) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
//
|
|
// Now copy over Length bytes.
|
|
//
|
|
|
|
BufVA += (Offset - CurOffset);
|
|
|
|
BufLen -= (Offset - CurOffset);
|
|
|
|
for (;;) {
|
|
|
|
ToCopy = (BytesCopied+BufLen > Length) ? Length - BytesCopied : BufLen;
|
|
|
|
MLID_MOVE_MEM(Buf+BytesCopied, BufVA, ToCopy);
|
|
|
|
BytesCopied += ToCopy;
|
|
|
|
|
|
if (BytesCopied == Length) {
|
|
|
|
return BytesCopied;
|
|
|
|
}
|
|
|
|
NdisGetNextBuffer(CurBuffer, &CurBuffer);
|
|
|
|
if (CurBuffer == (PNDIS_BUFFER)NULL) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
NdisQueryBuffer(CurBuffer, (PVOID *)&BufVA, &BufLen);
|
|
|
|
}
|
|
|
|
return BytesCopied;
|
|
|
|
}
|
|
|
|
|
|
|
|
NDIS_STATUS
|
|
MlidTransferData(
|
|
IN NDIS_HANDLE MacBindingHandle,
|
|
IN NDIS_HANDLE MacReceiveContext,
|
|
IN UINT ByteOffset,
|
|
IN UINT BytesToTransfer,
|
|
OUT PNDIS_PACKET Packet,
|
|
OUT PUINT BytesTransferred
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
NDIS function.
|
|
|
|
Arguments:
|
|
|
|
see NDIS 3.0 spec.
|
|
|
|
Notes:
|
|
|
|
- The MacReceiveContext will be a pointer to the open block for
|
|
the packet.
|
|
- The LoopbackPacket field in the adapter block will be NULL if this
|
|
is a call for a normal packet, otherwise it will be set to point
|
|
to the loopback packet.
|
|
|
|
--*/
|
|
{
|
|
PMLID_OPEN Open = PMLID_OPEN_FROM_BINDING_HANDLE(MacBindingHandle);
|
|
PMLID_ADAPTER Adapter = Open->Adapter;
|
|
PNDIS_BUFFER CurrentBuffer;
|
|
PUCHAR BufferVA;
|
|
UINT BufferLength, Copied;
|
|
UINT CurrentOffset;
|
|
|
|
UNREFERENCED_PARAMETER(MacReceiveContext);
|
|
|
|
ByteOffset += MLID_HEADER_SIZE;
|
|
|
|
if (Adapter->IndicatingPacket != NULL) {
|
|
|
|
IF_LOUD( DbgPrint("Transferring data for loopback packet\n");)
|
|
|
|
//
|
|
// It is a loopback packet
|
|
//
|
|
|
|
NdisQueryPacket(Packet, NULL, NULL, &CurrentBuffer, NULL);
|
|
|
|
CurrentOffset = ByteOffset;
|
|
|
|
while (CurrentBuffer != (PNDIS_BUFFER)NULL) {
|
|
|
|
NdisQueryBuffer(CurrentBuffer, (PVOID *)&BufferVA, &BufferLength);
|
|
|
|
NdisAcquireSpinLock(&Adapter->Lock);
|
|
|
|
Copied =
|
|
MlidCopyOver(BufferVA,
|
|
Adapter->IndicatingPacket,
|
|
CurrentOffset,
|
|
BufferLength
|
|
);
|
|
|
|
NdisReleaseSpinLock(&Adapter->Lock);
|
|
|
|
CurrentOffset += Copied;
|
|
|
|
if (Copied < BufferLength) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
NdisGetNextBuffer(CurrentBuffer, &CurrentBuffer);
|
|
|
|
}
|
|
|
|
//
|
|
// We are done, return.
|
|
//
|
|
|
|
|
|
*BytesTransferred = CurrentOffset - ByteOffset;
|
|
|
|
return(NDIS_STATUS_SUCCESS);
|
|
|
|
} else if (Adapter->IndicatedAPacket) {
|
|
|
|
NdisAcquireSpinLock(&Adapter->Lock);
|
|
|
|
IF_LOUD( DbgPrint("Transferring data for card packet\n");)
|
|
|
|
if (LM_Receive_Copy(
|
|
BytesTransferred,
|
|
BytesToTransfer,
|
|
ByteOffset,
|
|
Packet,
|
|
&(Adapter->LMAdapter)) != SUCCESS) {
|
|
|
|
//
|
|
// Copy failed.
|
|
//
|
|
|
|
*BytesTransferred = 0;
|
|
|
|
NdisReleaseSpinLock(&Adapter->Lock);
|
|
|
|
return(NDIS_STATUS_FAILURE);
|
|
|
|
} else {
|
|
|
|
NdisReleaseSpinLock(&Adapter->Lock);
|
|
|
|
return(NDIS_STATUS_SUCCESS);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
return(NDIS_STATUS_NOT_INDICATING);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
BOOLEAN
|
|
MlidSyncCloseAdapter(
|
|
IN PVOID Context
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function is used to synchronize with the lower MAC layer close
|
|
calls that may access the same areas of the LM that are accessed in
|
|
the ISR.
|
|
|
|
Arguments:
|
|
|
|
see NDIS 3.0 spec.
|
|
|
|
Notes:
|
|
|
|
returns TRUE on success, else FALSE.
|
|
|
|
--*/
|
|
{
|
|
|
|
if (LM_Close_Adapter((Ptr_Adapter_Struc)Context) == SUCCESS) {
|
|
|
|
return(TRUE);
|
|
|
|
} else {
|
|
|
|
return(FALSE);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
VOID
|
|
MlidWakeUpDpc(
|
|
IN PVOID SystemSpecific1,
|
|
IN PVOID Context,
|
|
IN PVOID SystemSpecific2,
|
|
IN PVOID SystemSpecific3
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This DPC routine is queued every 5 seconds to check on the
|
|
queues. If an interrupt was not received
|
|
in the last 5 seconds and there should have been one,
|
|
then we abort all operations.
|
|
|
|
Arguments:
|
|
|
|
Context - Really a pointer to the adapter.
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
{
|
|
PMLID_ADAPTER Adapter = (PMLID_ADAPTER)Context;
|
|
PMLID_OPEN TmpOpen;
|
|
PNDIS_PACKET TransmitPacket;
|
|
PMAC_RESERVED Reserved;
|
|
|
|
UNREFERENCED_PARAMETER(SystemSpecific1);
|
|
UNREFERENCED_PARAMETER(SystemSpecific2);
|
|
UNREFERENCED_PARAMETER(SystemSpecific3);
|
|
|
|
NdisAcquireSpinLock(&Adapter->Lock);
|
|
|
|
if ((Adapter->WakeUpTimeout) &&
|
|
((Adapter->PacketsOnCard != NULL) ||
|
|
(Adapter->XmitQueue != NULL))) {
|
|
|
|
//
|
|
// We had a pending operation the last time we ran,
|
|
// and it has not been completed...we need to complete
|
|
// it now.
|
|
|
|
Adapter->WakeUpTimeout = FALSE;
|
|
|
|
Adapter->HardwareFailure = TRUE;
|
|
|
|
if (Adapter->WakeUpErrorCount < 10) {
|
|
|
|
Adapter->WakeUpErrorCount++;
|
|
|
|
NdisWriteErrorLogEntry(
|
|
Adapter->NdisAdapterHandle,
|
|
NDIS_ERROR_CODE_HARDWARE_FAILURE,
|
|
0
|
|
);
|
|
|
|
}
|
|
|
|
while (Adapter->PacketsOnCard != NULL) {
|
|
|
|
TransmitPacket = Adapter->PacketsOnCard;
|
|
|
|
Reserved = RESERVED(TransmitPacket);
|
|
|
|
Adapter->PacketsOnCard = Reserved->NextPacket;
|
|
|
|
if (Adapter->PacketsOnCard == NULL) {
|
|
|
|
Adapter->PacketsOnCardTail = NULL;
|
|
|
|
}
|
|
|
|
TmpOpen = Reserved->Open;
|
|
|
|
NdisReleaseSpinLock(&Adapter->Lock);
|
|
|
|
NdisCompleteSend(
|
|
TmpOpen->NdisBindingContext,
|
|
TransmitPacket,
|
|
NDIS_STATUS_SUCCESS
|
|
);
|
|
|
|
NdisAcquireSpinLock(&Adapter->Lock);
|
|
|
|
TmpOpen->ReferenceCount--;
|
|
|
|
}
|
|
|
|
while (Adapter->XmitQueue != NULL) {
|
|
|
|
TransmitPacket = Adapter->XmitQueue;
|
|
|
|
Reserved = RESERVED(TransmitPacket);
|
|
|
|
//
|
|
// Remove the packet from the queue.
|
|
//
|
|
|
|
Adapter->XmitQueue = Reserved->NextPacket;
|
|
|
|
if (Adapter->XmitQueue == NULL) {
|
|
|
|
Adapter->XmitQTail = NULL;
|
|
|
|
}
|
|
|
|
TmpOpen = Reserved->Open;
|
|
|
|
NdisReleaseSpinLock(&Adapter->Lock);
|
|
|
|
NdisCompleteSend(
|
|
TmpOpen->NdisBindingContext,
|
|
TransmitPacket,
|
|
NDIS_STATUS_SUCCESS
|
|
);
|
|
|
|
NdisAcquireSpinLock(&Adapter->Lock);
|
|
|
|
TmpOpen->ReferenceCount--;
|
|
|
|
}
|
|
|
|
Adapter->WakeUpTimeout = FALSE;
|
|
|
|
//
|
|
// reinitialize the card
|
|
//
|
|
|
|
if (LM_Initialize_Adapter(&Adapter->LMAdapter) != SUCCESS) {
|
|
|
|
Adapter->HardwareFailure = TRUE;
|
|
|
|
NdisWriteErrorLogEntry(
|
|
Adapter->NdisAdapterHandle,
|
|
NDIS_ERROR_CODE_HARDWARE_FAILURE,
|
|
0
|
|
);
|
|
|
|
} else {
|
|
|
|
Adapter->HardwareFailure = FALSE;
|
|
|
|
}
|
|
|
|
//
|
|
// reenable interrupts
|
|
//
|
|
|
|
LM_Enable_Adapter(&Adapter->LMAdapter);
|
|
|
|
NdisReleaseSpinLock(&Adapter->Lock);
|
|
|
|
} else {
|
|
|
|
if ((Adapter->PacketsOnCard != NULL) ||
|
|
(Adapter->XmitQueue != NULL)) {
|
|
|
|
Adapter->WakeUpTimeout = TRUE;
|
|
|
|
}
|
|
|
|
NdisReleaseSpinLock(&Adapter->Lock);
|
|
|
|
|
|
}
|
|
|
|
//
|
|
// Fire off another Dpc to execute after 5 seconds
|
|
//
|
|
|
|
NdisSetTimer(
|
|
&Adapter->WakeUpTimer,
|
|
5000
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|