diff options
author | Adam <you@example.com> | 2020-05-17 05:51:50 +0200 |
---|---|---|
committer | Adam <you@example.com> | 2020-05-17 05:51:50 +0200 |
commit | e611b132f9b8abe35b362e5870b74bce94a1e58e (patch) | |
tree | a5781d2ec0e085eeca33cf350cf878f2efea6fe5 /private/ntos/ndis/odimac | |
download | NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.gz NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.bz2 NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.lz NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.xz NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.zst NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.zip |
Diffstat (limited to 'private/ntos/ndis/odimac')
-rw-r--r-- | private/ntos/ndis/odimac/keywords.h | 54 | ||||
-rw-r--r-- | private/ntos/ndis/odimac/mlid.c | 4413 | ||||
-rw-r--r-- | private/ntos/ndis/odimac/mlidsft.h | 814 | ||||
-rw-r--r-- | private/ntos/ndis/odimac/odihsm.h | 418 | ||||
-rw-r--r-- | private/ntos/ndis/odimac/umi.c | 336 |
5 files changed, 6035 insertions, 0 deletions
diff --git a/private/ntos/ndis/odimac/keywords.h b/private/ntos/ndis/odimac/keywords.h new file mode 100644 index 000000000..35896713e --- /dev/null +++ b/private/ntos/ndis/odimac/keywords.h @@ -0,0 +1,54 @@ +/*++ + +Copyright (c) 1990 Microsoft Corporation + +Module Name: + + keywords.h + +Abstract: + + Contains all Ndis2 and Ndis3 mac-specific keywords. + +Author: + + Bob Noradki + +Environment: + + This driver is expected to work in DOS, OS2 and NT at the equivalent + of kernal mode. + + Architecturally, there is an assumption in this driver that we are + on a little endian machine. + +Notes: + + optional-notes + +Revision History: + + + +--*/ +#ifndef NDIS2 +#define NDIS2 0 +#endif + +#if NDIS2 + +#define IOBASE NDIS_STRING_CONST("IOBASE") +#define MAXMULTICASTLIST NDIS_STRING_CONST("MAXMULTICAST") +#define NETADDRESS NDIS_STRING_CONST("NETADDRESS") +#define INTERRUPT NDIS_STRING_CONST("IRQ") +#define MEMMAPPEDBASEADDRESS NDIS_STRING_CONST("RAMADDRESS") + +#else // NDIS3 + +#define IOBASE NDIS_STRING_CONST("IoBaseAddress") +#define MAXMULTICASTLIST NDIS_STRING_CONST("MaximumMulticastList") +#define NETADDRESS NDIS_STRING_CONST("NetworkAddress") +#define INTERRUPT NDIS_STRING_CONST("InterruptNumber") +#define MEMMAPPEDBASEADDRESS NDIS_STRING_CONST("MemoryMappedBaseAddress") + +#endif diff --git a/private/ntos/ndis/odimac/mlid.c b/private/ntos/ndis/odimac/mlid.c new file mode 100644 index 000000000..67826a8f1 --- /dev/null +++ b/private/ntos/ndis/odimac/mlid.c @@ -0,0 +1,4413 @@ +/*++ + +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 + ); + +} + + + diff --git a/private/ntos/ndis/odimac/mlidsft.h b/private/ntos/ndis/odimac/mlidsft.h new file mode 100644 index 000000000..f705b1357 --- /dev/null +++ b/private/ntos/ndis/odimac/mlidsft.h @@ -0,0 +1,814 @@ +/*++ + +Copyright (c) 1990 Microsoft Corporation + +Module Name: + + MLIDsft.h + +Abstract: + + The main header for an Western Digital MAC driver. + +Author: + + Anthony V. Ercolano (tonye) creation-date 19-Jun-1990 (Driver Model) + + Sean Selitrennikoff (seanse) original MLID code. + +Environment: + + This driver is expected to work in DOS, OS2 and NT at the equivalent + of kernal mode. + + Architecturally, there is an assumption in this driver that we are + on a little endian machine. + +Notes: + + optional-notes + +Revision History: + + +--*/ + +#ifndef _MLIDSFT_ +#define _MLIDSFT_ + +#define MLID_NDIS_MAJOR_VERSION 3 +#define MLID_NDIS_MINOR_VERSION 0 + +// +// This macro is used along with the flags to selectively +// turn on debugging. +// + +#if DBG + +#define IF_MLIDDEBUG(f) if (MlidDebugFlag & (f)) + +extern ULONG MlidDebugFlag; + +#define MLID_DEBUG_LOUD 0x00000001 // debugging info +#define MLID_DEBUG_VERY_LOUD 0x00000002 // excessive debugging info +#define MLID_DEBUG_LOG 0x00000004 // enable MLIDLog +#define MLID_DEBUG_CHECK_DUP_SENDS 0x00000008 // check for duplicate sends +#define MLID_DEBUG_TRACK_PACKET_LENS 0x00000010 // track directed packet lens +#define MLID_DEBUG_WORKAROUND1 0x00000020 // drop DFR/DIS packets +#define MLID_DEBUG_CARD_BAD 0x00000040 // dump data if CARD_BAD +#define MLID_DEBUG_CARD_TESTS 0x00000080 // print reason for failing + + + +// +// Macro for deciding whether to dump lots of debugging information. +// + +#define IF_LOUD(A) IF_MLIDDEBUG( MLID_DEBUG_LOUD ) { A } +#define IF_VERY_LOUD(A) IF_MLIDDEBUG( MLID_DEBUG_VERY_LOUD ) { A } + +#else + +#define IF_LOUD(A) +#define IF_VERY_LOUD(A) + +#endif + + +// +// Macros for services that differ between DOS and NT, we may consider adding these +// into the NDIS spec. +// + + +// +// controls the number of transmit buffers on the packet. +// Choices are 1 or 2. +// + +#define DEFAULT_NUMBUFFERS 2 + + +// +// Macros for moving memory around +// + +#define MLID_MOVE_MEM(dest,src,size) NdisMoveMemory(dest,src,size) +#define MLID_MOVE_MEM_TO_SHARED_RAM(dest,src,size) NdisMoveToMappedMemory(dest,src,size) +#define MLID_MOVE_SHARED_RAM_TO_MEM(dest,src,size) NdisMoveFromMappedMemory(dest,src,size) + +#define MLID_MOVE_DWORD_TO_SHARED_RAM(dest,src) NdisWriteRegisterUlong((PULONG)(dest),(ULONG)(src)) +#define MLID_MOVE_SHARED_RAM_TO_DWORD(dest,src) NdisReadRegisterUlong((PULONG)(src),(PULONG)(dest)) + +#define MLID_MOVE_UCHAR_TO_SHARED_RAM(dest,src) NdisWriteRegisterUchar((PUCHAR)(dest),(UCHAR)(src)) +#define MLID_MOVE_SHARED_RAM_TO_UCHAR(dest,src) NdisReadRegisterUchar((PUCHAR)(src),(PUCHAR)(dest)) + +#define MLID_MOVE_USHORT_TO_SHARED_RAM(dest,src) NdisWriteRegisterUshort((PUSHORT)(dest),(USHORT)(src)) +#define MLID_MOVE_SHARED_RAM_TO_USHORT(dest,src) NdisReadRegisterUshort((PUSHORT)(src),(PUSHORT)(dest)) + + +// +// Only have one of these structures. +// + +typedef struct _MAC_BLOCK { + + // + // NDIS wrapper information. + // + + NDIS_HANDLE NdisMacHandle; // returned from NdisRegisterMac + NDIS_HANDLE NdisWrapperHandle; // returned from NdisInitializeWrapper + NDIS_MAC_CHARACTERISTICS MacCharacteristics; + + // + // Adapters registered for this MAC. + // + + UINT NumAdapters; + struct _MLID_ADAPTER * AdapterQueue; + NDIS_SPIN_LOCK SpinLock; // guards NumAdapter and AdapterQueue + + // + // driver object. + // + + PDRIVER_OBJECT DriverObject; + + BOOLEAN Unloading; + +} MAC_BLOCK, * PMAC_BLOCK; + + + + + + +// +// One of these structures per adapter registered. +// + +typedef struct _MLID_ADAPTER { + + // + // Adapter structure for LMI. + // This must occur first in the adapter structure. + // + + Adapter_Struc LMAdapter; + + // + // Spin lock for adapter structure + // + NDIS_SPIN_LOCK Lock; + + + // + // Links with our MAC. + // + + PMAC_BLOCK MacBlock; + struct _MLID_ADAPTER * NextAdapter; // used by MacBlock->OpenQueue + + // + // Opens for this adapter. + // + + struct _MLID_OPEN * OpenQueue; + + + // + // Number of references to the adapter. + // + ULONG References; + + UINT MulticastListMax; + + // + // Transmit queue. + // + + PNDIS_PACKET XmitQueue; // packets waiting to be transmitted + PNDIS_PACKET XmitQTail; + + PNDIS_PACKET PacketsOnCard; // List of packets that the card is + // is currently transmitting + PNDIS_PACKET PacketsOnCardTail; + + // + // Loopback queue; + // + + PNDIS_PACKET LoopbackQueue; // directed packets waiting to be received + PNDIS_PACKET LoopbackQTail; + PNDIS_PACKET IndicatingPacket; + BOOLEAN IndicatedAPacket; + + // + // These are for the current packet being indicated. + // + + UCHAR PacketHeader[4]; // the NIC appended header + UINT PacketLen; // the overall length of the packet + + + + // + // Statistics used by Set/QueryInformation. + // + + ULONG FramesXmitGood; // Good Frames Transmitted + ULONG FramesRcvGood; // Good Frames Received + + ULONG FramesXmitBad; // Bad Frames Transmitted + ULONG FramesXmitOneCollision; // Frames Transmitted with one collision + ULONG FramesXmitManyCollisions; // Frames Transmitted with > 1 collision + ULONG FramesXmitDeferred; // Frames where xmit was deferred + ULONG FramesXmitOverWrite; // Frames where xmit was overwritten + ULONG FramesXmitHeartbeat; // Frames lost heartbeat + ULONG FramesXmitUnderruns; // Frames where FIFO underran + + ULONG FrameAlignmentErrors; // FAE errors counted + ULONG CrcErrors; // CRC errors counted + ULONG MissedPackets; // missed packet counted + ULONG TooBig; // received packets too large counted + ULONG Overruns; // received packets with FIFO overrun + + ULONG CongestionCount; + ULONG FCSErrors; + ULONG BurstErrors; + ULONG ACErrors; + ULONG AbortDelimiters; + ULONG FailedReturns; + ULONG FramesCopied; + ULONG FrequencyErrors; + ULONG MonitorCount; + ULONG DMAUnderruns; + + // + // Reset information. + // + + BOOLEAN HardwareFailure; // Did the hardware fail in some way + BOOLEAN ResetRequested; // TRUE if a reset is needed + BOOLEAN ResetInProgress; // TRUE if a reset is in progress + struct _MLID_OPEN * ResetOpen; // who called MLIDReset + + UINT ByteToWrite; // temp storage + + + // + // Look Ahead information. + // + + ULONG MaxLookAhead; + + + // + // Handling deferred events + // + + NDIS_TIMER DeferredTimer; + PVOID DeferredDpc; + + BOOLEAN ReceiveEventsQueued; + BOOLEAN TransmitEventsQueued; + + BOOLEAN Removed; + + // + // For handling missing interrupts (caused by user mis-configs) + // + + PVOID WakeUpDpc; + NDIS_TIMER WakeUpTimer; + BOOLEAN WakeUpTimeout; + UCHAR WakeUpErrorCount; + BOOLEAN ProcessingDpc; + +} MLID_ADAPTER, * PMLID_ADAPTER; + + + + +// +// Given a MacBindingHandle this macro returns a pointer to the +// MLID_ADAPTER. +// +#define PMLID_ADAPTER_FROM_BINDING_HANDLE(Handle) \ + (((PMLID_OPEN)(Handle))->Adapter) + +// +// Given a MacContextHandle return the PMLID_ADAPTER +// it represents. +// +#define PMLID_ADAPTER_FROM_CONTEXT_HANDLE(Handle) \ + ((PMLID_ADAPTER)(Handle)) + +// +// Given a pointer to a MLID_ADAPTER return the +// proper MacContextHandle. +// +#define CONTEXT_HANDLE_FROM_PMLID_ADAPTER(Ptr) \ + ((NDIS_HANDLE)(Ptr)) + + +// +// Given a pointer to a MLID_ADAPTER, return the +// pointer to the LMAdapter. +// +#define Ptr_Adapter_Struc_FROM_PMLID_ADAPTER(P)\ + (&((P)->LMAdapter)) + +// +// Given a pointer to a LMAdapter, return the +// pointer to the MLID_ADAPTER. +// +#define PMLID_ADAPTER_FROM_Ptr_Adapter_Struc(P)\ + ((PMLID_ADAPTER)(P)) + + + + +// +// Macros to extract high and low bytes of a word. +// + +#define MSB(Value) ((UCHAR)(((Value) >> 8) & 0xff)) +#define LSB(Value) ((UCHAR)((Value) & 0xff)) + + +// +// One of these per open on an adapter. +// + +typedef struct _MLID_OPEN { + + // + // NDIS wrapper information. + // + + NDIS_HANDLE NdisBindingContext; // passed to MacOpenAdapter + PSTRING AddressingInformation; // not used currently + + // + // Links to our adapter. + // + + PMLID_ADAPTER Adapter; + struct _MLID_OPEN * NextOpen; + + // + // Links to our MAC. + // + + PMAC_BLOCK MacBlock; // faster than using AdapterBlock->MacBlock + + + // + // Handle of this adapter in the filter database. + // + NDIS_HANDLE NdisFilterHandle; + + // + // Indication information + // + + UINT LookAhead; + + // + // Reset/Close information. + // + + UINT ReferenceCount; // number of reasons this open can't close + BOOLEAN Closing; // is a close pending + + NDIS_REQUEST CloseFilterRequest; // Holds Requests for pending close op + NDIS_REQUEST CloseAddressRequest;// Holds Requests for pending close op + + UINT ProtOptionFlags; + +} MLID_OPEN, * PMLID_OPEN; + + +// +// This macro returns a pointer to a PMLID_OPEN given a MacBindingHandle. +// +#define PMLID_OPEN_FROM_BINDING_HANDLE(Handle) \ + ((PMLID_OPEN)(Handle)) + +// +// This macro returns a NDIS_HANDLE from a PMLID_OPEN +// +#define BINDING_HANDLE_FROM_PMLID_OPEN(Open) \ + ((NDIS_HANDLE)(Open)) + + + + + +// +// What we map into the reserved section of a packet. +// Cannot be more than 16 bytes (see ASSERT in MLID.c). +// + +typedef struct _MAC_RESERVED { + PNDIS_PACKET NextPacket; // used to link in the queues (4 bytes) + PMLID_OPEN Open; // open that called MLIDSend (4 bytes) + BOOLEAN Loopback; // is this a loopback packet (1 byte) + BOOLEAN Directed; // is this a directed packet (1 byte) +} MAC_RESERVED, * PMAC_RESERVED; + + +// +// These appear in the status field of MAC_RESERVED; they are +// used because there is not enough room for a full NDIS_HANDLE. +// + +#define RESERVED_SUCCESS ((USHORT)0) +#define RESERVED_FAILURE ((USHORT)1) + + +// +// Retrieve the MAC_RESERVED structure from a packet. +// + +#define RESERVED(Packet) ((PMAC_RESERVED)((Packet)->MacReserved)) + + +// +// This macro will act a "epilogue" to every routine in the +// *interface*. It will check whether any requests need +// to defer their processing. It will also decrement the reference +// count on the adapter. If the reference count is zero and there +// is deferred work to do it will insert the interrupt processing +// routine in the DPC queue. +// +// Note that we don't need to include checking for blocked receives +// since blocked receives imply that there will eventually be an +// interrupt. +// +// NOTE: This macro assumes that it is called with the lock acquired. +// +// +#define MLID_DO_DEFERRED(Adapter) \ +{ \ + PMLID_ADAPTER _A = (Adapter); \ + _A->References--; \ + if ((!_A->References) && \ + ((_A->ResetRequested && (!_A->ReceiveEventsQueued)) || \ + ((_A->LoopbackQueue != NULL) && (!_A->ReceiveEventsQueued)))) \ + {\ + _A->ReceiveEventsQueued = TRUE; \ + NdisReleaseSpinLock(&_A->Lock); \ + NdisSetTimer(&_A->DeferredTimer, 0);\ + } else { \ + NdisReleaseSpinLock(&_A->Lock); \ + } \ +} + + + + +// +// Declarations for functions in MLID.c. +// + +NDIS_STATUS +MlidRegisterAdapter( + IN PMLID_ADAPTER Adapter, + IN UINT NumBuffers, + IN UINT MulticastListMax, + IN UCHAR NodeAddress[ETH_LENGTH_OF_ADDRESS] + ); + + +BOOLEAN +MlidInterruptHandler( + IN PVOID ServiceContext // will be a pointer to the adapter block + ); + +VOID +MlidInterruptDpc( + IN PVOID SystemSpecific1, + IN PVOID InterruptContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3 + ); + +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 + ); + + +NDIS_STATUS +MlidCloseAdapter( + IN NDIS_HANDLE MacBindingHandle + ); + + +BOOLEAN +MlidAddReference( + IN PMLID_OPEN OpenP + ); + + +#define MlidRemoveReference(_Open) \ +{ \ + PMLID_ADAPTER _Adapter = _Open->Adapter; \ + PMLID_OPEN _TmpOpen = _Open; \ + --_TmpOpen->ReferenceCount; \ + if (_TmpOpen->ReferenceCount == 0) { \ + if (_TmpOpen == _Adapter->OpenQueue) { \ + _Adapter->OpenQueue = _TmpOpen->NextOpen; \ + } else { \ + _TmpOpen = _Adapter->OpenQueue; \ + while (_TmpOpen->NextOpen != _Open) { \ + _TmpOpen = _TmpOpen->NextOpen; \ + } \ + _TmpOpen->NextOpen = _Open->NextOpen; \ + _TmpOpen = _Open; \ + } \ + if (_TmpOpen->LookAhead == _Adapter->MaxLookAhead) {\ + MlidAdjustMaxLookAhead(_Adapter); \ + } \ + NdisReleaseSpinLock(&_Adapter->Lock); \ + NdisCompleteCloseAdapter (_TmpOpen->NdisBindingContext, NDIS_STATUS_SUCCESS); \ + NdisFreeMemory(_TmpOpen, sizeof(MLID_OPEN), 0); \ + NdisAcquireSpinLock(&_Adapter->Lock); \ + if (_Adapter->OpenQueue == NULL) { \ + NdisSynchronizeWithInterrupt( \ + &(_Adapter->LMAdapter.NdisInterrupt), \ + (PVOID)MlidSyncCloseAdapter, \ + (PVOID)(&(_Adapter->LMAdapter)) \ + ); \ + } \ + } \ +} + +VOID +MlidAdjustMaxLookAhead( + IN PMLID_ADAPTER Adapter + ); + +NDIS_STATUS +MlidReset( + IN NDIS_HANDLE MacBindingHandle + ); + +NDIS_STATUS +MlidRequest( + IN NDIS_HANDLE MacBindingHandle, + IN PNDIS_REQUEST NdisRequest + ); + +NDIS_STATUS +MlidQueryInformation( + IN PMLID_ADAPTER Adapter, + IN PMLID_OPEN Open, + IN PNDIS_REQUEST NdisRequest + ); + +NDIS_STATUS +MlidSetInformation( + IN PMLID_ADAPTER Adapter, + IN PMLID_OPEN Open, + IN PNDIS_REQUEST NdisRequest + ); + +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] + ); + +NDIS_STATUS +MlidSetPacketFilter( + IN PMLID_ADAPTER Adapter, + IN PMLID_OPEN Open, + IN PNDIS_REQUEST NdisRequest, + IN UINT PacketFilter + ); + +NDIS_STATUS +MlidQueryGlobalStatistics( + IN NDIS_HANDLE MacBindingHandle, + IN PNDIS_REQUEST NdisRequest + ); + +VOID +MlidUnload( + IN NDIS_HANDLE MacMacContext + ); + +NDIS_STATUS +MlidAddAdapter( + IN NDIS_HANDLE NdisMacContext, + IN NDIS_HANDLE ConfigurationHandle, + IN PNDIS_STRING AdaptName + ); + +VOID +MlidRemoveAdapter( + IN PVOID MacAdapterContext + ); + +VOID +MlidInterruptDpc( + IN PVOID SystemSpecific1, + IN PVOID InterruptContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3 + ); + +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 + ); + +NDIS_STATUS +MlidChangeFilterClasses( + IN UINT OldFilterClasses, + IN UINT NewFilterClasses, + IN NDIS_HANDLE MacBindingHandle, + IN PNDIS_REQUEST NdisRequest, + IN BOOLEAN Set + ); + + +VOID +MlidCloseAction( + IN NDIS_HANDLE MacBindingHandle + ); + + +UINT +MlidPacketSize( + IN PNDIS_PACKET Packet + ); + + +INDICATE_STATUS +MlidIndicatePacket( + IN PMLID_ADAPTER Adapter + ); + + +NDIS_STATUS +MlidTransferData( + IN NDIS_HANDLE MacBindingHandle, + IN NDIS_HANDLE MacReceiveContext, + IN UINT ByteOffset, + IN UINT BytesToTransfer, + OUT PNDIS_PACKET Packet, + OUT PUINT BytesTransferred + ); + +BOOLEAN +MlidReceiveEvents( + IN PVOID SystemSpecific1, + IN PVOID Context, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3 + ); + +VOID +MlidTransmitEvents( + IN PMLID_ADAPTER Adapter + ); + +NDIS_STATUS +MlidSend( + IN NDIS_HANDLE MacBindingHandle, + IN PNDIS_PACKET Packet + ); + +UINT +MlidCompareMemory( + IN PUCHAR String1, + IN PUCHAR String2, + IN UINT Length + ); + +VOID +MlidSetLoopbackFlag( + IN PMLID_ADAPTER Adapter, + IN PMLID_OPEN Open, + IN OUT PNDIS_PACKET Packet + ); + +VOID +MlidIndicateLoopbackPacket( + IN PMLID_ADAPTER Adapter, + IN PNDIS_PACKET Packet + ); + +BOOLEAN +MlidSyncCloseAdapter( + IN PVOID Context + ); + +BOOLEAN +MlidSyncSend( + IN PVOID Context + ); + +BOOLEAN +MlidSyncSetMulticastAddress( + IN PVOID Context + ); + +VOID +MlidWakeUpDpc( + IN PVOID SystemSpecific1, + IN PVOID Context, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3 + ); + +//++ +// +// VOID +// AddRefWhileHoldingSpinLock( +// IN PMLID_ADAPTER Adapter, +// IN PMLID_OPEN OpenP +// ) +// +// Routine Description: +// +// Adds a reference to an open. Similar to AddReference, but +// called with Adapter->Lock held. +// +// Arguments: +// +// Adapter - The adapter block of OpenP. +// OpenP - The open block that is being referenced. +// +// Return Value: +// +// None. +// +//-- + +#define AddRefWhileHoldingSpinLock(Adapter, OpenP) { \ + ++((OpenP)->ReferenceCount); \ +} + + + +//++ +// +// BOOLEAN +// MlidAddressEqual( +// IN UCHAR Address1[ETH_LENGTH_OF_ADDRESS], +// IN UCHAR Address2[ETH_LENGTH_OF_ADDRESS] +// ) +// +// Routine Description: +// +// Compares two Ethernet addresses. +// +// Arguments: +// +// Address1 - The first address. +// Address2 - The second address. +// +// Return Value: +// +// TRUE if the addresses are equal. +// FALSE if they are not. +// +//-- + +#define MlidAddressEqual(Address1, Address2) \ + ((Address1)[4] == (Address2)[4] && \ + MlidCompareMemory((Address1), (Address2), ETH_LENGTH_OF_ADDRESS) == 0) + + +#endif // MLIDSFT + + + + + + + diff --git a/private/ntos/ndis/odimac/odihsm.h b/private/ntos/ndis/odimac/odihsm.h new file mode 100644 index 000000000..0d17f1c0c --- /dev/null +++ b/private/ntos/ndis/odimac/odihsm.h @@ -0,0 +1,418 @@ +/*++ + +Copyright (c) 1990 Microsoft Corporation + +Module Name: + + odihsm.h + +Abstract: + + This contains all the definitions for the ODI HSM structures. + +Author: + + Sean Selitrennikoff (seanse) 15-Jan-92 + +Environment: + + Kernel mode, FSD + +Revision History: + + +--*/ + + +typedef struct _ADAPTER_STRUC{ + + UCHAR bus_type; // 0 = ISA, 1 = MCA + + UCHAR mc_slot_num; // MCA bus only + + USHORT pos_id; // Adapter POS ID (Mca only) + + USHORT io_base; // Adapter I/O Base + + PUCHAR adapter_text_ptr; // See LM_Get_Config + + USHORT irq_value; // IRQ line used by hardware + + USHORT rom_size; // num of 1K blocks + + ULONG rom_base; // physical address of ROM + + PVOID rom_access; // Pointer into VM of rom_base + + USHORT ram_size; // num of 1K blocks + + ULONG ram_base; // physical address of RAM + + PVOID ram_access; // Pointer into VM of ram_base + + USHORT ram_usable; // num of 1K blocks that can be accessed at once + + USHORT io_base_new; // new i/o base addr for LM_Put_Config + + UCHAR node_address[6]; // network address + + UCHAR permanent_node_address[6]; // network address burned into card. + + UCHAR multi_address[6]; // multicase address + + USHORT max_packet_size; // for this MAC driver + + USHORT buffer_page_size; // size of adapters RAM TX/RX buffer pages. + + USHORT num_of_tx_buffs; // TX bufss in adapter RAM + + USHORT receive_lookahead_size; + + USHORT receive_mask; + + USHORT adapter_status; + + USHORT media_type; + + USHORT bic_type; + + USHORT nic_type; + + USHORT adapter_type; + + NDIS_HANDLE NdisAdapterHandle; + + NDIS_MCA_POS_DATA PosData; + + BOOLEAN TokenRing; + + // + // Token Ring Specific stuff + // + + + USHORT ring_status; + + UCHAR funct_address[4]; + + UCHAR group_address[6]; + + // + // These counters must be initialized by the upper layer. + // + + + // + // Common counters... + // + + PULONG ptr_rx_CRC_errors; + + PULONG ptr_rx_lost_pkts; + + + // + // Token Ring counters + // + + PULONG ptr_rx_congestion; + + PULONG ptr_FCS_error; + + PULONG ptr_burst_error; + + PULONG ptr_AC_error; + + PULONG ptr_tx_abort_delimiter; + + PULONG ptr_tx_failed_return; + + PULONG ptr_frames_copied; + + PULONG ptr_frequency_error; + + PULONG ptr_monitor_gen_count; + + PULONG ptr_DMA_underruns; + + // + // Ethernet specific counters. Must be initialized by upper layer. + // + + PULONG ptr_rx_too_big; + + PULONG ptr_rx_align_errors; + + PULONG ptr_rx_overruns; + + PULONG ptr_tx_deferred; + + PULONG ptr_tx_max_collisions; + + PULONG ptr_tx_one_collision; + + PULONG ptr_tx_mult_collisions; + + PULONG ptr_tx_ow_collision; + + PULONG ptr_tx_CD_heartbeat; + + PULONG ptr_tx_carrier_lost; + + PULONG ptr_tx_underruns; + + + + + ULONG board_id; + + USHORT mode_bits; + + USHORT status_bits; + + USHORT xmit_buf_size; + + USHORT config_mode; // 1 == Store config in EEROM + + + + + UCHAR State; + + BOOLEAN BufferOverflow; // does an overflow need to be handled + + UCHAR InterruptMask; + + BOOLEAN UMRequestedInterrupt; // Has LM_Interrupt() been called. + + + + NDIS_INTERRUPT NdisInterrupt; // interrupt info used by wrapper + + UCHAR Current; + + // + // Transmit information. + // + + XMIT_BUF NextBufToFill; // where to copy next packet to + XMIT_BUF NextBufToXmit; // valid if CurBufXmitting is -1 + XMIT_BUF CurBufXmitting; // -1 if none is + BOOLEAN TransmitInterruptPending; // transmit interrupt and overwrite error? + UINT PacketLens[MAX_XMIT_BUFS]; + BUFFER_STATUS BufferStatus[MAX_XMIT_BUFS]; + + PUCHAR ReceiveStart; // start of card receive area + PUCHAR ReceiveStop; // end of card receive area + + + // + // Loopback information + // + + PNDIS_PACKET LoopbackQueue; // queue of packets to loop back + PNDIS_PACKET LoopbackQTail; + PNDIS_PACKET LoopbackPacket; // current one we are looping back + + // + // Receive information + // + + PUCHAR IndicatingPacket; + BOOLEAN OverWriteHandling; // Currently handling an overwrite + BOOLEAN OverWriteStartTransmit; + UCHAR StartBuffer; // Start buffer number to receive into + UCHAR LastBuffer; // Last buffer number + 1 + UINT PacketLen; + + // + // Interrupt Information + // + + UCHAR LaarHold; + + // + // Pointer to the filter database for the MAC. + // + PETH_FILTER FilterDB; + +}Adapter_Struc, *Ptr_Adapter_Struc; + + + + +// +// LMI Status and Return codes +// + +typedef USHORT LM_STATUS; + +#define SUCCESS 0x0 +#define ADAPTER_AND_CONFIG 0x1 // Adapter found and config info gotten +#define ADAPTER_NO_CONFIG 0x2 // Adapter found, no config info found +#define NOT_MY_INTERRUPT 0x3 // No interrupt found in LM_Service_Events +#define FRAME_REJECTED 0x4 +#define EVENTS_DISABLED 0x5 // Disables LM_Service_Events from reporting + // any further interrupts. +#define OUT_OF_RESOURCES 0x6 +#define OPEN_FAILED 0x7 +#define HARDWARE_FAILED 0x8 +#define INITIALIZE_FAILED 0x9 +#define CLOSE_FAILED 0xA +#define MAX_COLLISIONS 0xB +#define FIFO_UNDERRUN 0xC +#define BUFFER_TOO_SMALL 0xD +#define ADAPTER_CLOSED 0xE +#define FAILURE 0xF + +#define REQUEUE_LATER 0x12 + +#define INVALID_FUNCTION 0x80 +#define INVALID_PARAMETER 0x81 + +#define ADAPTER_NOT_FOUND 0xFFFF + + + +// +// Function Definitions. +// + + +extern +LM_STATUS +LM_Send( + PNDIS_PACKET Packet, + Ptr_Adapter_Struc Adapter + ); + + + +extern +LM_STATUS +LM_Interrupt_req( + Ptr_Adapter_Struc Adapter + ); + + +extern +LM_STATUS +LM_Service_Receive_Events( + Ptr_Adapter_Struc Adapter + ); + +extern +LM_STATUS +LM_Service_Transmit_Events( + Ptr_Adapter_Struc Adapter + ); + + +extern +LM_STATUS +LM_Receive_Copy( + PULONG Bytes_Transferred, + ULONG Byte_Count, + ULONG Offset, + PNDIS_PACKET Packet, + Ptr_Adapter_Struc Adapter + ); + + +extern +LM_STATUS +LM_Receive_Lookahead( + ULONG Byte_Count, + ULONG Offset, + PUCHAR Buffer, + Ptr_Adapter_Struc Adapter + ); + +extern +LM_STATUS +LM_Get_Mca_Io_Base_Address( + IN Ptr_Adapter_Struc Adapt, + IN NDIS_HANDLE ConfigurationHandle, + OUT USHORT *IoBaseAddress + ); + +extern +LM_STATUS +LM_Get_Config( + Ptr_Adapter_Struc Adapter + ); + +extern +LM_STATUS +LM_Free_Resources( + Ptr_Adapter_Struc Adapt + ); + +extern +LM_STATUS +LM_Initialize_Adapter( + Ptr_Adapter_Struc Adapter + ); + + +extern +LM_STATUS +LM_Open_Adapter( + Ptr_Adapter_Struc Adapter + ); + + +extern +LM_STATUS +LM_Close_Adapter( + Ptr_Adapter_Struc Adapter + ); + + +extern +LM_STATUS +LM_Disable_Adapter( + Ptr_Adapter_Struc Adapter + ); + +extern +LM_STATUS +LM_Disable_Adapter_Receives( + Ptr_Adapter_Struc Adapt + ); + +extern +LM_STATUS +LM_Disable_Adapter_Transmits( + Ptr_Adapter_Struc Adapt + ); + +extern +LM_STATUS +LM_Enable_Adapter( + Ptr_Adapter_Struc Adapter + ); + + +extern +LM_STATUS +LM_Enable_Adapter_Receives( + Ptr_Adapter_Struc Adapt + ); + +extern +LM_STATUS +LM_Enable_Adapter_Transmits( + Ptr_Adapter_Struc Adapt + ); + +#define LM_Set_Multi_Address(Addresses, Count, Adapter) (SUCCESS) + + +extern +LM_STATUS +LM_Set_Receive_Mask( + Ptr_Adapter_Struc Adapter + ); + + diff --git a/private/ntos/ndis/odimac/umi.c b/private/ntos/ndis/odimac/umi.c new file mode 100644 index 000000000..d007f8af8 --- /dev/null +++ b/private/ntos/ndis/odimac/umi.c @@ -0,0 +1,336 @@ +/*++ + +Copyright (c) 1990 Microsoft Corporation + +Module Name: + + umi.c + +Abstract: + + Upper MAC Interface functions for the NDIS 3.0 Western Digital driver. + +Author: + + Sean Selitrennikoff (seanse) 15-Jan-92 + +Environment: + + Kernel mode, FSD + +Revision History: + + +--*/ + +#include <ndis.h> +#include <efilter.h> +#include "wdlmi.h" +#include "wdhrd.h" +#include "wdsft.h" +#include "wdumi.h" + + + +#if DBG + +extern UCHAR WdDebugLog[]; +extern UCHAR WdDebugLogPlace; + +#define IF_LOG(A) A + +#else + +#define IF_LOG(A) + +#endif + + +LM_STATUS +UM_Send_Complete( + LM_STATUS Status, + Ptr_Adapter_Struc Adapt + ) +/*++ + +Routine Description: + + This routine is called back when the packet on the front of + PacketsOnCard has been fully transmitted by the Lower MAC. + + + NOTE: The lock is held before the LM_ routines are called and + therefore held at the beginning of this call. + +Arguments: + + Status - Status of the send. + + Adapt - A pointer to an LMI adapter structure. + +Return: + + SUCCESS + EVENTS_DISABLED + +--*/ +{ + + PWD_ADAPTER Adapter = PWD_ADAPTER_FROM_Ptr_Adapter_Struc(Adapt); + PWD_OPEN Open; + PNDIS_PACKET Packet; + + + + ASSERT(Adapter->PacketsOnCard != NULL); + + IF_LOG(LOG('c')); + + // + // Remove Packet from list. + // + + Packet = Adapter->PacketsOnCard; + + Adapter->PacketsOnCard = RESERVED(Packet)->NextPacket; + + if (Adapter->PacketsOnCard == NULL) { + + Adapter->PacketsOnCardTail = NULL; + + } + + Open = RESERVED(Packet)->Open; + + + IF_LOUD( DbgPrint("Completing send for open 0x%lx\n",Open);) + + + if (RESERVED(Packet)->Loopback) { + + // + // Put packet on loopback + // + + if (Adapter->LoopbackQueue == NULL) { + + Adapter->LoopbackQueue = Adapter->LoopbackQTail = Packet; + + } else { + + RESERVED(Adapter->LoopbackQTail)->NextPacket = Packet; + + Adapter->LoopbackQTail = Packet; + + } + + RESERVED(Packet)->NextPacket = NULL; + + } else { + + IF_LOUD( DbgPrint("Not a loopback packet\n");) + + // + // Complete send + // + + if (Status == SUCCESS) { + Adapter->FramesXmitGood++; + } else { + Adapter->FramesXmitBad++; + } + + NdisReleaseSpinLock(&Adapter->Lock); + + NdisCompleteSend(Open->NdisBindingContext, + Packet, + (Status == SUCCESS ? NDIS_STATUS_SUCCESS : + NDIS_STATUS_FAILURE) + ); + + NdisAcquireSpinLock(&Adapter->Lock); + + WdRemoveReference(Open); + + } + + // + // If there are any sends waiting and there is not a reset to be + // done, queue them up + // + + if ((Adapter->XmitQueue != NULL) && !(Adapter->ResetRequested)) { + + // + // Remove packet from front. + // + + Packet = Adapter->XmitQueue; + + Adapter->XmitQueue = RESERVED(Packet)->NextPacket; + + if (Adapter->XmitQueue == NULL) { + + Adapter->XmitQTail = NULL; + + } + + // + // Start packet send. + // + + IF_LOG(LOG('t')); + + Status = LM_Send(Packet, Adapt); + + if (Status == OUT_OF_RESOURCES) { + + IF_LOG(LOG('2')); + + // + // Put packet back on xmit queue. + // + + if (Adapter->XmitQueue != NULL) { + + RESERVED(Packet)->NextPacket = Adapter->XmitQueue; + + Adapter->XmitQueue = Packet; + + } else { + + Adapter->XmitQueue = Packet; + + Adapter->XmitQTail = Packet; + + } + + } else if (Status == SUCCESS) { + + // + // Put packet at end of card list. + // + + if (Adapter->PacketsOnCard == NULL) { + + Adapter->PacketsOnCard = Adapter->PacketsOnCardTail = Packet; + + } else { + + RESERVED(Adapter->PacketsOnCardTail)->NextPacket = Packet; + + Adapter->PacketsOnCardTail = Packet; + + } + + RESERVED(Packet)->NextPacket = NULL; + + } + + } + + IF_LOG(LOG('C')); + + return(SUCCESS); + +} + + +LM_STATUS +UM_Receive_Packet( + ULONG PacketSize, + Ptr_Adapter_Struc Adapt + ) +/*++ + +Routine Description: + + This routine is called whenever the lower MAC receives a packet. + + +Arguments: + + PacketSize - Total size of the packet + + Adapt - A pointer to an LMI adapter structure. + +Return: + + SUCCESS + EVENTS_DISABLED + +--*/ +{ + PWD_ADAPTER Adapter = PWD_ADAPTER_FROM_Ptr_Adapter_Struc(Adapt); + ULONG IndicateLen; + + // + // Setup for indication + // + + Adapter->IndicatedAPacket = TRUE; + + Adapter->IndicatingPacket = (PNDIS_PACKET)NULL; + + IndicateLen = ((Adapter->MaxLookAhead + WD_HEADER_SIZE) > PacketSize ? + PacketSize : + Adapter->MaxLookAhead + WD_HEADER_SIZE + ); + + if (LM_Receive_Lookahead( + IndicateLen, + 0, + Adapter->LookAhead, + &(Adapter->LMAdapter)) != SUCCESS) { + + return(SUCCESS); + + } + + // + // Indicate packet + // + + Adapter->FramesRcvGood++; + + NdisReleaseSpinLock(&Adapter->Lock); + + if (PacketSize < WD_HEADER_SIZE) { + + if (PacketSize >= ETH_LENGTH_OF_ADDRESS) { + + // + // Runt packet + // + + EthFilterIndicateReceive( + Adapt->FilterDB, + (NDIS_HANDLE)Adapter, + (PCHAR)Adapter->LookAhead, + Adapter->LookAhead, + PacketSize, + NULL, + 0, + 0 + ); + + } + + } else { + + EthFilterIndicateReceive( + Adapt->FilterDB, + (NDIS_HANDLE)Adapter, + (PCHAR)Adapter->LookAhead, + Adapter->LookAhead, + WD_HEADER_SIZE, + Adapter->LookAhead + WD_HEADER_SIZE, + IndicateLen - WD_HEADER_SIZE, + PacketSize - WD_HEADER_SIZE + ); + } + + NdisAcquireSpinLock(&Adapter->Lock); + + return(SUCCESS); +} |