summaryrefslogtreecommitdiffstats
path: root/private/ntos/ndis/elnkii.new/elnkii.c
diff options
context:
space:
mode:
Diffstat (limited to 'private/ntos/ndis/elnkii.new/elnkii.c')
-rw-r--r--private/ntos/ndis/elnkii.new/elnkii.c1825
1 files changed, 1825 insertions, 0 deletions
diff --git a/private/ntos/ndis/elnkii.new/elnkii.c b/private/ntos/ndis/elnkii.new/elnkii.c
new file mode 100644
index 000000000..2d17a1e35
--- /dev/null
+++ b/private/ntos/ndis/elnkii.new/elnkii.c
@@ -0,0 +1,1825 @@
+/*++
+
+Copyright (c) 1990 Microsoft Corporation
+
+Module Name:
+
+ elnkii.c
+
+Abstract:
+
+ This is the main file for the Etherlink II
+ Ethernet controller. This driver conforms to the NDIS 3.1 interface.
+
+ The idea for handling loopback and sends simultaneously is largely
+ adapted from the EtherLink II NDIS driver by Adam Barr.
+
+Author:
+
+ Anthony V. Ercolano (Tonye) 20-Jul-1990
+
+Environment:
+
+ Kernel Mode - Or whatever is the equivalent on OS/2 and DOS.
+
+Revision History:
+
+ Dec 1991 by Sean Selitrennikoff - Modified Elnkii code by AdamBa to
+ fit into the model by TonyE.
+
+ 12/15/94 [kyleb] Converted to miniport.
+
+--*/
+
+#include <ndis.h>
+#include "elnkhrd.h"
+#include "elnksft.h"
+#include "keywords.h"
+
+#if DBG
+#define STATIC
+#else
+#define STATIC static
+#endif
+
+
+#if DBG
+
+ULONG ElnkiiDebugFlag = ELNKII_DEBUG_LOUD;
+
+//
+// Debug tracing definitions
+//
+#define ELNKII_LOG_SIZE 256
+
+UCHAR ElnkiiLogBuffer[ELNKII_LOG_SIZE] = {0};
+UINT ElnkiiLogLoc = 0;
+
+VOID ElnkiiLog(UCHAR c)
+{
+ ElnkiiLogBuffer[ElnkiiLogLoc++] = c;
+ ElnkiiLogBuffer[(ElnkiiLogLoc + 4) % ELNKII_LOG_SIZE] = '\0';
+
+ if (ElnkiiLogLoc >= ELNKII_LOG_SIZE)
+ ElnkiiLogLoc = 0;
+}
+#endif
+
+//
+// This constant is used for places where NdisAllocateMemory
+// needs to be called and the HighestAcceptableAddress does
+// not matter.
+//
+
+static const NDIS_PHYSICAL_ADDRESS HighestAcceptableMax =
+ NDIS_PHYSICAL_ADDRESS_CONST(-1,-1);
+
+
+//
+// The global MAC block.
+//
+
+DRIVER_BLOCK ElnkiiMiniportBlock = {0};
+
+//
+// List of supported OIDs for this miniport.
+//
+STATIC UINT ElnkiiSupportedOids[] =
+{
+ 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,
+ 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
+};
+
+
+//
+// Determines whether failing the initial card test will prevent
+// the adapter from being registered.
+//
+
+#ifdef CARD_TEST
+
+BOOLEAN InitialCardTest = TRUE;
+
+#else // CARD_TEST
+
+BOOLEAN InitialCardTest = FALSE;
+
+#endif // CARD_TEST
+
+NTSTATUS
+DriverEntry(
+ IN PDRIVER_OBJECT DriverObject,
+ IN PUNICODE_STRING RegistryPath
+ );
+
+#pragma NDIS_INIT_FUNCTION(DriverEntry)
+
+
+
+NTSTATUS DriverEntry(
+ IN PDRIVER_OBJECT DriverObject,
+ IN PUNICODE_STRING RegistryPath
+)
+
+/*++
+
+Routine Description:
+
+ This is the transfer address of the driver. It initializes
+ ElnkiiMacBlock and calls NdisInitializeWrapper() and
+ NdisRegisterMac().
+
+Arguments:
+
+Return Value:
+
+ Indicates the success or failure of the initialization.
+
+--*/
+
+{
+ NDIS_HANDLE NdisWrapperHandle; // Handle referring the wrapper to
+ // this driver.
+ PDRIVER_BLOCK pNewMac; // Pointer to global information about
+ // this driver.
+ NDIS_STATUS Status; // Holds the status of NDIS functions.
+
+ //
+ // Characteristics table for the miniport.
+ //
+ NDIS_MINIPORT_CHARACTERISTICS ElnkiiChar;
+
+
+#if DBG
+
+ ElnkiiDebugFlag = ELNKII_DEBUG_LOUD;
+ __asm int 3
+
+#endif
+
+
+ //
+ // Initialize some locals.
+ //
+ pNewMac = &ElnkiiMiniportBlock;
+
+ //
+ // Pass the wrapper a pointer to the device object.
+ //
+ NdisMInitializeWrapper(
+ &NdisWrapperHandle,
+ DriverObject,
+ RegistryPath,
+ NULL
+ );
+
+ //
+ // Save info about this miniport.
+ //
+ pNewMac->NdisWrapperHandle = NdisWrapperHandle;
+ pNewMac->AdapterQueue = (PELNKII_ADAPTER)NULL;
+
+ //
+ // Initialize the miniport's characteristics table.
+ //
+ ElnkiiChar.MajorNdisVersion = ELNKII_NDIS_MAJOR_VERSION;
+ ElnkiiChar.MinorNdisVersion = ELNKII_NDIS_MINOR_VERSION;
+ ElnkiiChar.CheckForHangHandler = ElnkiiCheckForHang;
+ ElnkiiChar.ReconfigureHandler = NULL;
+ ElnkiiChar.InitializeHandler = ElnkiiInitialize;
+
+ ElnkiiChar.DisableInterruptHandler = ElnkiiDisableInterrupt;
+ ElnkiiChar.EnableInterruptHandler = ElnkiiEnableInterrupt;
+ ElnkiiChar.HaltHandler = ElnkiiHalt;
+ ElnkiiChar.HandleInterruptHandler = ElnkiiHandleInterrupt;
+ ElnkiiChar.ISRHandler = ElnkiiIsr;
+ ElnkiiChar.QueryInformationHandler = ElnkiiQueryInformation;
+ ElnkiiChar.ResetHandler = ElnkiiReset;
+ ElnkiiChar.SendHandler = ElnkiiSend;
+ ElnkiiChar.SetInformationHandler = ElnkiiSetInformation;
+ ElnkiiChar.TransferDataHandler = ElnkiiTransferData;
+
+ //
+ // Register the miniport with the wrapper.
+ //
+ Status = NdisMRegisterMiniport(
+ NdisWrapperHandle,
+ &ElnkiiChar,
+ sizeof(ElnkiiChar)
+ );
+ if (Status != NDIS_STATUS_SUCCESS)
+ {
+ IF_LOUD(DbgPrint("NdisMRegisterMiniport failed with code 0x%x\n", Status);)
+
+ NdisTerminateWrapper(NdisWrapperHandle, NULL);
+ return(Status);
+ }
+
+ IF_LOUD( DbgPrint( "NdisMRegisterMiniport succeeded\n" );)
+ IF_LOUD( DbgPrint("Adapter Initialization Complete\n");)
+
+ return(NDIS_STATUS_SUCCESS);
+}
+
+#pragma NDIS_INIT_FUNCTION(ReadBaseIoAddress)
+
+
+VOID ReadBaseIoAddress(
+ OUT PNDIS_STATUS pStatus,
+ OUT PVOID *ppIoBaseAddress,
+ IN NDIS_HANDLE hConfig,
+ IN NDIS_HANDLE MiniportAdapterHandle
+)
+{
+ #define MAX_POSSIBLE_BASE_ADDRESSES 8
+
+ PNDIS_CONFIGURATION_PARAMETER ReturnedValue;
+
+ NDIS_STRING IOAddressStr = IOBASE;
+ NDIS_STATUS Status;
+ UINT c;
+ PVOID PossibleIoBases[] = { (PVOID)0x2e0, (PVOID)0x2a0,
+ (PVOID)0x280, (PVOID)0x250,
+ (PVOID)0x350, (PVOID)0x330,
+ (PVOID)0x310, (PVOID)0x300 };
+
+ //
+ // Read the I/O base address.
+ //
+ NdisReadConfiguration(
+ &Status,
+ &ReturnedValue,
+ hConfig,
+ &IOAddressStr,
+ NdisParameterHexInteger
+ );
+ if (NDIS_STATUS_SUCCESS == Status)
+ {
+ //
+ // We read an address from the registry.
+ //
+ *ppIoBaseAddress = (PVOID)ReturnedValue->ParameterData.IntegerData;
+
+ //
+ // Verify the I/O base address.
+ //
+ for (c = 0; c < MAX_POSSIBLE_BASE_ADDRESSES; c++)
+ {
+ if (*ppIoBaseAddress == PossibleIoBases[c])
+ break;
+ }
+
+ //
+ // Is the base address that we read valid?
+ //
+ if (MAX_POSSIBLE_BASE_ADDRESSES == c)
+ {
+ NdisWriteErrorLogEntry(
+ MiniportAdapterHandle,
+ NDIS_ERROR_CODE_UNSUPPORTED_CONFIGURATION,
+ 1,
+ (ULONG)*ppIoBaseAddress
+ );
+
+ *pStatus = NDIS_STATUS_FAILURE;
+ }
+ }
+ else
+ {
+ //
+ // No address was read, use the default.
+ //
+ *pStatus = NDIS_STATUS_SUCCESS;
+ }
+
+ #undef MAX_POSSIBLE_BASE_ADDRESS
+}
+
+#pragma NDIS_INIT_FUNCTION(ReadInterruptNumber)
+
+VOID ReadInterruptNumber(
+ OUT PNDIS_STATUS pStatus,
+ OUT PCCHAR pInterruptNumber,
+ IN NDIS_HANDLE hConfig,
+ IN NDIS_HANDLE MiniportAdapterHandle
+)
+{
+ #define MAX_INTERRUPT_VALUES 4
+
+ PNDIS_CONFIGURATION_PARAMETER ReturnedValue;
+
+ NDIS_STRING InterruptStr = INTERRUPT;
+ CCHAR InterruptValues[] = { 2, 3, 4, 5 };
+ NDIS_STATUS Status;
+ UINT c;
+
+ //
+ // Read the interrupt number from the registry.
+ //
+ NdisReadConfiguration(
+ &Status,
+ &ReturnedValue,
+ hConfig,
+ &InterruptStr,
+ NdisParameterHexInteger
+ );
+ if (NDIS_STATUS_SUCCESS == Status)
+ {
+ //
+ // We read an entry from the registry.
+ //
+ *pInterruptNumber = (CCHAR)ReturnedValue->ParameterData.IntegerData;
+
+ //
+ // Verify the interrupt number.
+ //
+ for (c = 0; c < MAX_INTERRUPT_VALUES; c++)
+ {
+ if (*pInterruptNumber == InterruptValues[c])
+ break;
+ }
+
+ if (MAX_INTERRUPT_VALUES == c)
+ {
+ //
+ // See if this works!!!!
+ //
+ NdisWriteErrorLogEntry(
+ MiniportAdapterHandle,
+ NDIS_ERROR_CODE_UNSUPPORTED_CONFIGURATION,
+ 1,
+ *pInterruptNumber
+ );
+
+ *pStatus = NDIS_STATUS_FAILURE;
+ }
+ }
+ else
+ {
+ //
+ // No interrupt number was read, use the default.
+ //
+ *pStatus = NDIS_STATUS_SUCCESS;
+ }
+}
+
+NDIS_STATUS ElnkiiRegisterAdapter(
+ IN PELNKII_ADAPTER pAdapter,
+ IN NDIS_HANDLE ConfigurationHandle
+)
+{
+ UINT c;
+ BOOLEAN fCardPresent;
+ BOOLEAN fIoBaseCorrect;
+ NDIS_STATUS Status;
+
+ //
+ // Verify that NumBuffers <= MAX_XMIT_BUFS
+ //
+ if (pAdapter->NumBuffers > MAX_XMIT_BUFS)
+ return(NDIS_STATUS_RESOURCES);
+
+ //
+ // Inform the wrapper of the physical attributes of this adapter.
+ //
+ NdisMSetAttributes(
+ pAdapter->MiniportAdapterHandle,
+ (NDIS_HANDLE)pAdapter,
+ FALSE,
+ NdisInterfaceIsa
+ );
+
+ //
+ // Register the port addresses.
+ //
+ Status = NdisMRegisterIoPortRange(
+ (PVOID)(&(pAdapter->MappedIoBaseAddr)),
+ pAdapter->MiniportAdapterHandle,
+ (ULONG)pAdapter->IoBaseAddr,
+ 0x10
+ );
+ if (NDIS_STATUS_SUCCESS != Status)
+ goto fail1;
+
+ //
+ // Register the gate array addresses.
+ //
+ Status = NdisMRegisterIoPortRange(
+ (PVOID)&pAdapter->MappedGaBaseAddr,
+ pAdapter->MiniportAdapterHandle,
+ (ULONG)pAdapter->IoBaseAddr + 0x400,
+ 0x10
+ );
+ if (NDIS_STATUS_SUCCESS != Status)
+ goto fail2;
+
+ //
+ // Map the memory mapped portion of the card.
+ //
+ // If the pAdapter->MemMapped is FALSE, CardGetMemBaseAddr wil not
+ // return the actual MemBaseAddr, but it will still return
+ // CardPresent and IoBaseCorrect.
+ //
+ pAdapter->MemBaseAddr = CardGetMemBaseAddr(
+ pAdapter,
+ &fCardPresent,
+ &fIoBaseCorrect
+ );
+ if (!fCardPresent)
+ {
+ //
+ // The card does not seem to be there.
+ //
+ NdisWriteErrorLogEntry(
+ pAdapter->MiniportAdapterHandle,
+ NDIS_ERROR_CODE_ADAPTER_NOT_FOUND,
+ 0
+ );
+
+ Status = NDIS_STATUS_ADAPTER_NOT_FOUND;
+
+ goto fail1;
+ }
+
+ if (!fIoBaseCorrect)
+ {
+ //
+ // The card is there, but the I/O base address jumper is
+ // not where we expect it to be.
+ //
+ NdisWriteErrorLogEntry(
+ pAdapter->MiniportAdapterHandle,
+ NDIS_ERROR_CODE_BAD_IO_BASE_ADDRESS,
+ 0
+ );
+
+ Status = NDIS_STATUS_ADAPTER_NOT_FOUND;
+
+ goto fail1;
+ }
+
+ if (pAdapter->MemMapped && (NULL == pAdapter->MemBaseAddr))
+ {
+ //
+ // The card does not appear to be mapped.
+ //
+ pAdapter->MemMapped = FALSE;
+ }
+
+ //
+ // For memory-mapped operation, map the card's transmit/receive
+ // area into memory space. For programmed I/O, we will refer
+ // to transmit/receive memory in terms of offsets in the card's
+ // 32K address space; for an 8K card this is always the second
+ // 8K piece, starting at 0x2000.
+ //
+ if (pAdapter->MemMapped)
+ {
+ NDIS_PHYSICAL_ADDRESS PhysicalAddress;
+
+ NdisSetPhysicalAddressHigh(PhysicalAddress, 0);
+ NdisSetPhysicalAddressLow(PhysicalAddress, (ULONG)pAdapter->MemBaseAddr);
+
+ Status = NdisMMapIoSpace(
+ (PVOID *)(&pAdapter->XmitStart),
+ pAdapter->MiniportAdapterHandle,
+ PhysicalAddress,
+ 0x2000
+ );
+ if (NDIS_STATUS_SUCCESS != Status)
+ {
+ NdisWriteErrorLogEntry(
+ pAdapter->MiniportAdapterHandle,
+ NDIS_ERROR_CODE_RESOURCE_CONFLICT,
+ 0
+ );
+
+ goto fail2;
+ }
+ }
+ else
+ {
+ //
+ // Programmed I/O
+ //
+ pAdapter->XmitStart = (PUCHAR)0x2000;
+ }
+
+ //
+ // For the NicXXX fields, always use the addressing system
+ // starting at 0x2000 (or 0x20, since they contain the MSB only).
+ //
+ pAdapter->NicXmitStart = 0x20;
+
+ //
+ // The start of the receive space.
+ //
+ pAdapter->PageStart = pAdapter->XmitStart +
+ (pAdapter->NumBuffers * TX_BUF_SIZE);
+ pAdapter->NicPageStart = pAdapter->NicXmitStart +
+ (UCHAR)(pAdapter->NumBuffers * BUFS_PER_TX);
+
+ //
+ // The end of the receive space.
+ //
+ pAdapter->PageStop = pAdapter->XmitStart + 0x2000;
+ pAdapter->NicPageStop = pAdapter->NicXmitStart + (UCHAR)0x20;
+
+ //
+ // Initialize the receive variables.
+ //
+ pAdapter->NicReceiveConfig = RCR_REJECT_ERR;
+
+ //
+ // Initialize the transmit buffer control.
+ //
+ pAdapter->CurBufXmitting = (XMIT_BUF)-1;
+ pAdapter->BufferOverflow = FALSE;
+ pAdapter->OverflowRestartXmitDpc = FALSE;
+
+ //
+ // Mark the buffers as empty.
+ //
+ for (c = 0; c < pAdapter->NumBuffers; c++ )
+ pAdapter->BufferStatus[c] = EMPTY;
+
+ //
+ // The transmit and loopback queues start out empty.
+ // Alredy done since the structure is zero'd out.
+ //
+
+ //
+ // Clear the tally counters.
+ // Already done since the structure is zero'd out.
+ //
+
+ //
+ // Read the Ethernet address off of the PROM.
+ //
+ CardReadEthernetAddress(pAdapter);
+
+ //
+ // Initialize the NIC and Gate Array registers.
+ //
+ pAdapter->NicInterruptMask = IMR_RCV |
+ IMR_XMIT |
+ IMR_XMIT_ERR |
+ IMR_OVERFLOW;
+
+ //
+ // Link us on to the chain of adapters for this miniport.
+ //
+ pAdapter->pNextElnkiiAdapter = ElnkiiMiniportBlock.AdapterQueue;
+ ElnkiiMiniportBlock.AdapterQueue = pAdapter;
+
+ //
+ // Turn off the card.
+ //
+ SyncCardStop(pAdapter);
+
+ //
+ // Set flag to ignore interrupts.
+ //
+ pAdapter->InCardTest = TRUE;
+
+ //
+ // Initialize the interrupt.
+ //
+ Status = NdisMRegisterInterrupt(
+ &pAdapter->Interrupt,
+ pAdapter->MiniportAdapterHandle,
+ pAdapter->InterruptNumber,
+ pAdapter->InterruptNumber,
+ FALSE,
+ FALSE,
+ NdisInterruptLatched
+ );
+ if (NDIS_STATUS_SUCCESS != Status)
+ {
+ NdisWriteErrorLogEntry(
+ pAdapter->MiniportAdapterHandle,
+ NDIS_ERROR_CODE_INTERRUPT_CONNECT,
+ 0
+ );
+
+ goto fail3;
+ }
+
+ IF_LOUD( DbgPrint("Interrupt Connected\n"); )
+
+ //
+ // Initialize the card.
+ //
+ if (!CardSetup(pAdapter))
+ {
+ //
+ // The NIC could not be initialized.
+ //
+ NdisWriteErrorLogEntry(
+ pAdapter->MiniportAdapterHandle,
+ NDIS_ERROR_CODE_ADAPTER_NOT_FOUND,
+ 0
+ );
+
+ Status = NDIS_STATUS_ADAPTER_NOT_FOUND;
+
+ goto fail4;
+ }
+
+ //
+ // Perform card tests.
+ //
+ if (!CardTest(pAdapter))
+ {
+ //
+ // The tests failed, InitialCardTest determines whether this
+ // causes the whole initialization to fail.
+ //
+ if (InitialCardTest)
+ {
+ NdisWriteErrorLogEntry(
+ pAdapter->MiniportAdapterHandle,
+ NDIS_ERROR_CODE_HARDWARE_FAILURE,
+ 0
+ );
+
+ Status = NDIS_STATUS_DEVICE_FAILED;
+
+ goto fail4;
+ }
+ }
+
+ //
+ // Normal mode now.
+ //
+ pAdapter->InCardTest = FALSE;
+
+ //
+ // Start the card.
+ //
+ CardStart(pAdapter);
+
+ return(NDIS_STATUS_SUCCESS);
+
+fail4:
+ //
+ // Deregister the interrupt.
+ //
+ NdisMDeregisterInterrupt(&pAdapter->Interrupt);
+
+fail3:
+ //
+ // Take us out of the AdapterQueue.
+ //
+ if (ElnkiiMiniportBlock.AdapterQueue == pAdapter)
+ {
+ ElnkiiMiniportBlock.AdapterQueue = pAdapter->pNextElnkiiAdapter;
+ }
+ else
+ {
+ PELNKII_ADAPTER pTmp = ElnkiiMiniportBlock.AdapterQueue;
+
+ while (pTmp->pNextElnkiiAdapter != pAdapter)
+ {
+ pTmp = pTmp->pNextElnkiiAdapter;
+ }
+
+ pTmp->pNextElnkiiAdapter = pTmp->pNextElnkiiAdapter->pNextElnkiiAdapter;
+ }
+
+ //
+ // We already enabled the interrupt on the card, so turn it off.
+ //
+ NdisRawWritePortUchar(pAdapter->MappedGaBaseAddr + GA_INT_DMA_CONFIG, 0x00);
+
+fail2:
+
+ if (NULL != pAdapter->MappedIoBaseAddr)
+ {
+ //
+ // Deregister the base I/O port range.
+ //
+ NdisMDeregisterIoPortRange(
+ pAdapter->MiniportAdapterHandle,
+ (ULONG)pAdapter->IoBaseAddr,
+ 0x10,
+ pAdapter->MappedIoBaseAddr
+ );
+ }
+
+ if (NULL != pAdapter->MappedGaBaseAddr)
+ {
+ //
+ // Deregister the gate array I/O port range.
+ //
+ NdisMDeregisterIoPortRange(
+ pAdapter->MiniportAdapterHandle,
+ (ULONG)pAdapter->IoBaseAddr + 0x400,
+ 0x10,
+ pAdapter->MappedGaBaseAddr
+ );
+ }
+
+fail1:
+
+ return(Status);
+}
+
+#pragma NDIS_INIT_FUNCTION(ElnkiiInitialize)
+
+NDIS_STATUS ElnkiiInitialize(
+ OUT PNDIS_STATUS OpenErrorStatus,
+ OUT PUINT SelectedMediumIndex,
+ IN PNDIS_MEDIUM MediumArray,
+ IN UINT MediumArraySize,
+ IN NDIS_HANDLE MiniportAdapterHandle,
+ IN NDIS_HANDLE ConfigurationHandle
+)
+{
+ PELNKII_ADAPTER pAdapter; // Pointer to the new adapter.
+ NDIS_HANDLE hConfig; // Handle for reading the registry.
+ ULONG NetAddressLength; // Number of bytes in the address.
+ PVOID NetAddress; // The network address that the adapter
+ // should use instead of the burned
+ // in default address.
+ NDIS_STATUS Status;
+ UINT c; // Temporary count variable.
+
+ //
+ // TRUE if there is a configuration error.
+ //
+ BOOLEAN ConfigError;
+
+ //
+ // A special value to log concerning the error.
+ //
+ ULONG ConfigErrorValue;
+
+
+ //
+ // Value read from the registry.
+ //
+ PNDIS_CONFIGURATION_PARAMETER ReturnedValue; // Value read from registry.
+
+ //
+ // String names of the parameters that will be
+ // read from the registry.
+ //
+ NDIS_STRING MaxMulticastListStr = MAXMULTICAST;
+ NDIS_STRING NetworkAddressStr = NETWORK_ADDRESS;
+ NDIS_STRING MemoryMappedStr = MEMORYMAPPED;
+ NDIS_STRING TransceiverStr = TRANSCEIVER;
+
+#if NDIS2
+ NDIS_STRING ExternalStr = NDIS_STRING_CONST("EXTERNAL");
+#endif
+
+ //
+ // These are used when calling ElnkiiRegisterAdapter.
+ //
+ PVOID IoBaseAddress;
+ CCHAR InterruptNumber;
+ BOOLEAN ExternalTransceiver;
+ BOOLEAN MemMapped;
+ UINT MaxMulticastList;
+
+ //
+ // Initialize some locals.
+ //
+ ConfigError = FALSE;
+ ConfigErrorValue = 0;
+
+ IoBaseAddress = DEFAULT_IOBASEADDR;
+ InterruptNumber = DEFAULT_INTERRUPTNUMBER;
+ ExternalTransceiver = DEFAULT_EXTERNALTRANSCEIVER;
+ MemMapped = DEFAULT_MEMMAPPED;
+ MaxMulticastList = DEFAULT_MULTICASTLISTMAX;
+
+ //
+ // Search for the 802.3 medium type in the given array.
+ //
+ for
+ (
+ c = 0;
+ c < MediumArraySize;
+ c++
+ )
+ {
+ //
+ // If we find it, stop looking.
+ //
+ if (NdisMedium802_3 == MediumArray[c])
+ break;
+ }
+
+ //
+ // Did we find our medium?
+ //
+ if (c == MediumArraySize)
+ return(NDIS_STATUS_UNSUPPORTED_MEDIA);
+
+ //
+ // Save the index of the type to return to wrapper.
+ //
+ *SelectedMediumIndex = c;
+
+ //
+ // Allocate some memory for the adapter block.
+ //
+ Status = NdisAllocateMemory(
+ (PVOID *)&pAdapter,
+ sizeof(ELNKII_ADAPTER),
+ 0,
+ HighestAcceptableMax
+ );
+ if (NDIS_STATUS_SUCCESS != Status)
+ return(Status);
+
+ //
+ // Initialize the adapter block.
+ //
+ NdisZeroMemory(pAdapter, sizeof(ELNKII_ADAPTER));
+
+ //
+ // Open the configuration space.
+ //
+ NdisOpenConfiguration(&Status, &hConfig, ConfigurationHandle);
+ if (NDIS_STATUS_SUCCESS != Status)
+ {
+ NdisFreeMemory(pAdapter, sizeof(ELNKII_ADAPTER), 0);
+ return(NDIS_STATUS_FAILURE);
+ }
+
+ //
+ // Read the base I/O address.
+ //
+ ReadBaseIoAddress(&Status, &IoBaseAddress, hConfig, MiniportAdapterHandle);
+ if (NDIS_STATUS_SUCCESS != Status)
+ return(Status);
+
+ //
+ // Read the interrupt number.
+ //
+ ReadInterruptNumber(
+ &Status,
+ &InterruptNumber,
+ hConfig,
+ MiniportAdapterHandle
+ );
+ if (NDIS_STATUS_SUCCESS != Status)
+ return(Status);
+
+
+#if !NDIS2
+ //
+ // Read the MaxMulticastList
+ //
+ NdisReadConfiguration(
+ &Status,
+ &ReturnedValue,
+ hConfig,
+ &MaxMulticastListStr,
+ NdisParameterInteger
+ );
+
+ if (NDIS_STATUS_SUCCESS == Status)
+ MaxMulticastList = ReturnedValue->ParameterData.IntegerData;
+
+#endif
+
+#if NDIS_NT
+ //
+ // Read Memory Mapped information.
+ //
+ NdisReadConfiguration(
+ &Status,
+ &ReturnedValue,
+ hConfig,
+ &MemoryMappedStr,
+ NdisParameterHexInteger
+ );
+ if (NDIS_STATUS_SUCCESS == Status)
+ {
+ MemMapped =
+ (ReturnedValue->ParameterData.IntegerData == 0) ? FALSE : TRUE;
+ }
+
+#endif
+
+#if NDIS2
+ //
+ // Read NDIS2 transceiver type.
+ //
+ NdisReadConfiguration(
+ &Status,
+ &ReturnedValue,
+ hConfig,
+ &TransceiverStr,
+ NdisParameterString
+ );
+ if (NDIS_STATUS_SUCCESS == Status)
+ {
+ if (NdisEqualString(&ReturnedValue->ParameterData.StringData, &ExternalStr, 1))
+ ExternalTransceiver = TRUE;
+ }
+
+#else
+ //
+ // Read NDIS3 transceiver type.
+ //
+ NdisReadConfiguration(
+ &Status,
+ &ReturnedValue,
+ hConfig,
+ &TransceiverStr,
+ NdisParameterInteger
+ );
+ if (NDIS_STATUS_SUCCESS == Status)
+ {
+ ExternalTransceiver =
+ (ReturnedValue->ParameterData.IntegerData == 1) ? TRUE : FALSE;
+ }
+#endif
+
+
+ //
+ // Read network address.
+ //
+ NdisReadNetworkAddress(
+ &Status,
+ &NetAddress,
+ &NetAddressLength,
+ hConfig
+ );
+ if
+ (
+ (ETH_LENGTH_OF_ADDRESS == NetAddressLength) &&
+ (NDIS_STATUS_SUCCESS == Status)
+ )
+ {
+ //
+ // We have a valid ethernet address, save it.
+ //
+ ETH_COPY_NETWORK_ADDRESS(pAdapter->StationAddress, NetAddress);
+ }
+
+
+ //
+ // Close the configuration space.
+ //
+ NdisCloseConfiguration(hConfig);
+
+ IF_LOUD( DbgPrint(
+ "Registering adapter # buffers %ld, "
+ "I/O base address 0x%lx, interrupt number %ld,"
+ "external %c, memory mapped %c, max multicast %ld\n",
+ DEFAULT_NUMBUFFERS,
+ IoBaseAddress,
+ InterruptNumber,
+ ExternalTransceiver ? 'Y' : 'N',
+ MemMapped ? 'Y' : 'N',
+ DEFAULT_MULTICASTLISTMAX
+ );)
+
+ //
+ // Set up the parameters.
+ //
+ pAdapter->NumBuffers = DEFAULT_NUMBUFFERS;
+ pAdapter->IoBaseAddr = IoBaseAddress;
+ pAdapter->ExternalTransceiver = ExternalTransceiver;
+ pAdapter->InterruptNumber = InterruptNumber;
+ pAdapter->MemMapped = MemMapped;
+ pAdapter->MulticastListMax = MaxMulticastList;
+ pAdapter->MiniportAdapterHandle = MiniportAdapterHandle;
+
+ //
+ // Register the adapter.
+ //
+ Status = ElnkiiRegisterAdapter(pAdapter, ConfigurationHandle);
+ if (NDIS_STATUS_SUCCESS != Status)
+ {
+ NdisFreeMemory(pAdapter, sizeof(ELNKII_ADAPTER), 0);
+
+ return(NDIS_STATUS_FAILURE);
+ }
+
+ IF_LOUD(DbgPrint("ElnkiiRegisterAdapter succeeded\n");)
+
+ return(NDIS_STATUS_SUCCESS);
+}
+
+
+
+
+NDIS_STATUS ElnkiiQueryInformation(
+ IN NDIS_HANDLE MiniportAdapterContext,
+ IN NDIS_OID Oid,
+ IN PVOID InformationBuffer,
+ IN ULONG InformationBufferLength,
+ OUT PULONG BytesWritten,
+ OUT PULONG BytesNeeded
+)
+/*++
+
+Routine Description:
+
+ The ElnkiiQueryInformation processes a query request for NDIS_OIDs that
+ are specific about the Driver.
+
+Arguments:
+
+ MiniportAdapterContext - A pointer to the adapter.
+ Oid - The NDIS_OID to process.
+ InformationBuffer - A pointer to the NdisRequest->InformationBuffer
+ into which we store the result of the query.
+ InformationBufferLength - Number of bytes in the information buffer.
+ BytesWritten - A pointer to the number of bytes written into
+ 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.
+
+Return Value:
+
+ The function value is the status of the operation.
+
+--*/
+
+{
+ //
+ // Poiter to the adapter structure.
+ //
+ PELNKII_ADAPTER pAdapter = (PELNKII_ADAPTER)MiniportAdapterContext;
+
+ //
+ // 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 BytesLeft = InformationBufferLength;
+ PUCHAR InfoBuffer = (PUCHAR)InformationBuffer;
+ NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
+ NDIS_HARDWARE_STATUS HardwareStatus = NdisHardwareStatusReady;
+ NDIS_MEDIUM Medium = NdisMedium802_3;
+
+ ULONG GenericULong;
+ USHORT GenericUShort;
+ UCHAR GenericArray[6];
+ UINT MoveBytes = sizeof(ULONG);
+ PVOID MoveSource = (PVOID)&GenericULong;
+
+ //
+ // Make sure that in is 4 bytes. Else GenericULong must change
+ // to something of size 4.
+ //
+ ASSERT(sizeof(ULONG) == 4);
+
+ //
+ // 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);
+
+ if (!pAdapter->MemMapped)
+ GenericULong |= NDIS_MAC_OPTION_COPY_LOOKAHEAD_DATA;
+
+ break;
+
+ case OID_GEN_SUPPORTED_LIST:
+ MoveSource = (PVOID)ElnkiiSupportedOids;
+ MoveBytes = sizeof(ElnkiiSupportedOids);
+
+ break;
+
+ case OID_GEN_HARDWARE_STATUS:
+ HardwareStatus = NdisHardwareStatusReady;
+ MoveSource = (PVOID)&HardwareStatus;
+ MoveBytes = sizeof(NDIS_HARDWARE_STATUS);
+
+ break;
+
+ case OID_GEN_MEDIA_SUPPORTED:
+ case OID_GEN_MEDIA_IN_USE:
+ MoveSource = (PVOID)&Medium;
+ MoveBytes = sizeof(NDIS_MEDIUM);
+
+ break;
+
+ case OID_GEN_MAXIMUM_LOOKAHEAD:
+
+ GenericULong = ELNKII_MAX_LOOKAHEAD;
+
+ break;
+
+ case OID_GEN_MAXIMUM_FRAME_SIZE:
+
+ GenericULong = (ULONG)(1514 - ELNKII_HEADER_SIZE);
+
+ break;
+
+ case OID_GEN_MAXIMUM_TOTAL_SIZE:
+
+ GenericULong = (ULONG)1514;
+
+ break;
+
+ case OID_GEN_LINK_SPEED:
+
+ GenericULong = (ULONG)100000;
+
+ break;
+
+ case OID_GEN_TRANSMIT_BUFFER_SPACE:
+
+ GenericULong = (ULONG)(pAdapter->NumBuffers * TX_BUF_SIZE);
+
+ break;
+
+ case OID_GEN_RECEIVE_BUFFER_SPACE:
+
+ GenericULong = (ULONG)0x2000;
+ GenericULong -= (pAdapter->NumBuffers *
+ ((TX_BUF_SIZE / 256) + 1) * 256);
+
+ //
+ // Subtract off receive buffer overhead
+ //
+ {
+ ULONG TmpUlong = GenericULong / 256;
+
+ TmpUlong *= 4;
+
+ GenericULong -= TmpUlong;
+ }
+
+ //
+ // Round to nearest 256 bytes
+ //
+ GenericULong = (GenericULong / 256) * 256;
+
+ break;
+
+ case OID_GEN_TRANSMIT_BLOCK_SIZE:
+
+ GenericULong = (ULONG)TX_BUF_SIZE;
+
+ break;
+
+ case OID_GEN_RECEIVE_BLOCK_SIZE:
+
+ GenericULong = (ULONG)256;
+
+ break;
+
+ case OID_GEN_VENDOR_ID:
+
+ NdisMoveMemory(
+ (PVOID)(&GenericULong),
+ pAdapter->PermanentAddress,
+ 3
+ );
+
+ GenericULong &= 0xFFFFFF00;
+
+ break;
+
+ case OID_GEN_VENDOR_DESCRIPTION:
+
+ MoveSource = (PVOID)"Etherlink II Adapter.";
+ MoveBytes = 22;
+
+ break;
+
+ case OID_GEN_DRIVER_VERSION:
+
+ GenericUShort = ((USHORT)ELNKII_NDIS_MAJOR_VERSION << 8) |
+ ELNKII_NDIS_MINOR_VERSION;
+
+ MoveSource = (PVOID)&GenericUShort;
+ MoveBytes = sizeof(GenericUShort);
+
+ break;
+
+ case OID_GEN_CURRENT_LOOKAHEAD:
+
+ GenericULong = (ULONG)(pAdapter->MaxLookAhead);
+
+ break;
+
+ case OID_802_3_PERMANENT_ADDRESS:
+ ELNKII_MOVE_MEM((PCHAR)GenericArray,
+ pAdapter->PermanentAddress,
+ ETH_LENGTH_OF_ADDRESS);
+
+ MoveSource = (PVOID)GenericArray;
+ MoveBytes = sizeof(pAdapter->PermanentAddress);
+ break;
+
+ case OID_802_3_CURRENT_ADDRESS:
+
+ ELNKII_MOVE_MEM((PCHAR)GenericArray,
+ pAdapter->StationAddress,
+ ETH_LENGTH_OF_ADDRESS);
+
+ MoveSource = (PVOID)GenericArray;
+ MoveBytes = sizeof(pAdapter->StationAddress);
+ break;
+
+ case OID_802_3_MAXIMUM_LIST_SIZE:
+
+ GenericULong = (ULONG)pAdapter->MulticastListMax;
+
+ break;
+
+ case OID_GEN_XMIT_OK:
+
+ GenericULong = (UINT)pAdapter->FramesXmitGood;
+
+ break;
+
+ case OID_GEN_RCV_OK:
+
+ GenericULong = (UINT)pAdapter->FramesRcvGood;
+
+ break;
+
+ case OID_GEN_XMIT_ERROR:
+
+ GenericULong = (UINT)pAdapter->FramesXmitBad;
+
+ break;
+
+ case OID_GEN_RCV_ERROR:
+
+ GenericULong = (UINT)pAdapter->CrcErrors;
+
+ case OID_GEN_RCV_NO_BUFFER:
+
+ GenericULong = (UINT)pAdapter->MissedPackets;
+
+ break;
+
+ case OID_802_3_RCV_ERROR_ALIGNMENT:
+
+ GenericULong = (UINT)pAdapter->FrameAlignmentErrors;
+
+ break;
+
+ case OID_802_3_XMIT_ONE_COLLISION:
+
+ GenericULong = (UINT)pAdapter->FramesXmitOneCollision;
+
+ break;
+
+ case OID_802_3_XMIT_MORE_COLLISIONS:
+
+ GenericULong = (UINT)pAdapter->FramesXmitManyCollisions;
+
+ break;
+
+ default:
+
+ Status = NDIS_STATUS_NOT_SUPPORTED;
+ break;
+ }
+
+ if (NDIS_STATUS_SUCCESS == Status)
+ {
+ if (MoveBytes > BytesLeft)
+ {
+ //
+ // Not enough room in InformationBuffer.
+ //
+ *BytesNeeded = MoveBytes;
+
+ Status = NDIS_STATUS_INVALID_LENGTH;
+ }
+ else
+ {
+ //
+ // Store the result.
+ //
+ ELNKII_MOVE_MEM(InfoBuffer, MoveSource, MoveBytes);
+
+ (*BytesWritten) += MoveBytes;
+ }
+ }
+
+ return(Status);
+}
+
+
+
+NDIS_STATUS DispatchSetPacketFilter(
+ IN PELNKII_ADAPTER pAdapter
+)
+
+/*++
+
+Routine Description:
+
+ Sets the appropriate bits in the adapter filters
+ and modifies the card Receive Configuration Register if needed.
+
+Arguments:
+
+ pAdapter - Pointer to the adapter block
+
+Return Value:
+
+ The final status (always NDIS_STATUS_SUCCESS).
+
+Notes:
+
+ - Note that to receive all multicast packets the multicast
+ registers on the card must be filled with 1's. To be
+ promiscuous that must be done as well as setting the
+ promiscuous physical flag in the RCR. This must be done
+ as long as ANY protocol bound to this adapter has their
+ filter set accordingly.
+
+--*/
+
+
+{
+ UINT PacketFilter;
+
+ //
+ // See what has to be put on the card.
+ //
+ if
+ (
+ pAdapter->PacketFilter &
+ (NDIS_PACKET_TYPE_ALL_MULTICAST | NDIS_PACKET_TYPE_PROMISCUOUS)
+ )
+ {
+ //
+ // Need "all multicast" now.
+ //
+ CardSetAllMulticast(pAdapter);
+ }
+ else
+ {
+ //
+ // No longer need "all multicast".
+ //
+ DispatchSetMulticastAddressList(pAdapter);
+ }
+
+ //
+ // The multicast bit in the RCR should be on if ANY protocol wants
+ // multicast/all multicast packets (or is promiscuous).
+ //
+ if
+ (
+ pAdapter->PacketFilter &
+ (NDIS_PACKET_TYPE_ALL_MULTICAST |
+ NDIS_PACKET_TYPE_MULTICAST |
+ NDIS_PACKET_TYPE_PROMISCUOUS)
+ )
+ {
+ pAdapter->NicReceiveConfig |= RCR_MULTICAST;
+ }
+ else
+ {
+ pAdapter->NicReceiveConfig &= ~RCR_MULTICAST;
+ }
+
+ //
+ // The promiscuous physical bit in the RCR should be on if ANY
+ // protocol wants to be promiscuous.
+ //
+ if (pAdapter->PacketFilter & NDIS_PACKET_TYPE_PROMISCUOUS)
+ pAdapter->NicReceiveConfig |= RCR_ALL_PHYS;
+ else
+ pAdapter->NicReceiveConfig &= ~RCR_ALL_PHYS;
+
+
+ //
+ // The broadcast bit in the RCR should be on if ANY protocol wants
+ // broadcast packets (or is promiscuous).
+ //
+ if
+ (
+ pAdapter->PacketFilter &
+ (NDIS_PACKET_TYPE_BROADCAST | NDIS_PACKET_TYPE_PROMISCUOUS)
+ )
+ {
+ pAdapter->NicReceiveConfig |= RCR_BROADCAST;
+ }
+ else
+ {
+ pAdapter->NicReceiveConfig &= ~RCR_BROADCAST;
+ }
+
+ CardSetReceiveConfig(pAdapter);
+
+ return(NDIS_STATUS_SUCCESS);
+}
+
+
+
+NDIS_STATUS DispatchSetMulticastAddressList(
+ IN PELNKII_ADAPTER pAdapter
+)
+
+/*++
+
+Routine Description:
+
+ Sets the multicast list for this open
+
+Arguments:
+
+ AdaptP - Pointer to the adapter block
+
+Return Value:
+
+Implementation Note:
+
+ When invoked, we are to make it so that the multicast list in the filter
+ package becomes the multicast list for the adapter. To do this, we
+ determine the required contents of the NIC multicast registers and
+ update them.
+
+
+--*/
+{
+
+ //
+ // Update the local copy of the NIC multicast regs
+ // and copy them to the NIC
+ //
+
+ CardFillMulticastRegs(pAdapter);
+
+ CardCopyMulticastRegs(pAdapter);
+
+ return NDIS_STATUS_SUCCESS;
+}
+
+
+
+NDIS_STATUS ElnkiiSetInformation(
+ IN NDIS_HANDLE MiniportAdapterContext,
+ IN NDIS_OID Oid,
+ IN PVOID InformationBuffer,
+ IN ULONG InformationBufferLength,
+ OUT PULONG BytesRead,
+ OUT PULONG BytesNeeded
+)
+/*++
+
+Routine Description:
+
+ The ElnkiiSetInformation is used by ElnkiiRequest to set information
+ about the MAC.
+
+Arguments:
+
+ MiniportAdapterContext - Context registered with the wrapper, actually
+ a pointer to the adapter information.
+ Oid - The OID to set.
+ InformationBuffer - Holds the new data for the OID.
+ InformationBufferLength - Length of the InformationBuffer.
+ BytesRead - If the call is successful, returns the number
+ of bytes read from InformationBuffer.
+ BytesNeeded - If there is not enough data in InformationBuffer
+ to satisfy the OID, returns the amount of
+ storage needed.
+
+Return Value:
+
+ The function value is the status of the operation.
+
+--*/
+{
+ //
+ // Pointer to the adapter structure.
+ //
+ PELNKII_ADAPTER pAdapter = (PELNKII_ADAPTER)MiniportAdapterContext;
+
+ //
+ // General Algorithm:
+ //
+ // Verify length
+ // Switch(Request)
+ // Process Request
+ //
+ UINT BytesLeft = InformationBufferLength;
+ PUCHAR InfoBuffer = (PUCHAR)InformationBuffer;
+
+ //
+ // Variables for a particular request.
+ //
+ UINT OidLength;
+
+ //
+ // Variables for holding the new value to be used.
+ //
+ ULONG LookAhead;
+ ULONG Filter;
+
+ //
+ // Status of the operation.
+ //
+ NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
+
+ //
+ // Get Oid and Length of request
+ //
+ OidLength = BytesLeft;
+
+ switch (Oid)
+ {
+ case OID_802_3_MULTICAST_LIST:
+ //
+ // Verify length
+ //
+ if ((OidLength % ETH_LENGTH_OF_ADDRESS) != 0)
+ {
+ Status = NDIS_STATUS_INVALID_LENGTH;
+ *BytesRead = 0;
+ *BytesNeeded = 0;
+
+ break;
+ }
+
+ NdisMoveMemory(pAdapter->MulticastAddresses, InfoBuffer, OidLength);
+
+ //
+ // If we are currently receiving all multicast or
+ // we are in promiscuous then we DO NOT call this,
+ // or it will reset thoes settings.
+ //
+ if
+ (
+ !(pAdapter->PacketFilter & (NDIS_PACKET_TYPE_ALL_MULTICAST |
+ NDIS_PACKET_TYPE_PROMISCUOUS))
+ )
+ {
+ Status = DispatchSetMulticastAddressList(pAdapter);
+ }
+ else
+ {
+ //
+ // Our list of multicast addresses is kept by the wrapper.
+ //
+ Status = NDIS_STATUS_SUCCESS;
+ }
+
+ break;
+
+
+ case OID_GEN_CURRENT_PACKET_FILTER:
+
+ //
+ // Verify length
+ //
+ if (OidLength != 4 )
+ {
+ Status = NDIS_STATUS_INVALID_LENGTH;
+
+ *BytesRead = 0;
+ *BytesNeeded = 0;
+
+ break;
+
+ }
+
+ ELNKII_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)
+ )
+ {
+ Status = NDIS_STATUS_NOT_SUPPORTED;
+
+ *BytesRead = 4;
+ *BytesNeeded = 0;
+
+ break;
+
+ }
+
+ pAdapter->PacketFilter = Filter;
+ Status = DispatchSetPacketFilter(pAdapter);
+
+ break;
+
+ case OID_GEN_CURRENT_LOOKAHEAD:
+
+ //
+ // Verify length
+ //
+
+ if (OidLength != 4)
+ {
+ Status = NDIS_STATUS_INVALID_LENGTH;
+
+ *BytesRead = 0;
+ *BytesNeeded = 0;
+
+ break;
+ }
+
+ //
+ // Store the new value.
+ //
+ ELNKII_MOVE_MEM(&LookAhead, InfoBuffer, 4);
+
+ if (LookAhead <= ELNKII_MAX_LOOKAHEAD)
+ pAdapter->MaxLookAhead = LookAhead;
+ else
+ Status = NDIS_STATUS_INVALID_LENGTH;
+
+ break;
+
+ default:
+
+ Status = NDIS_STATUS_INVALID_OID;
+
+ *BytesRead = 0;
+ *BytesNeeded = 0;
+
+ break;
+ }
+
+ if (Status == NDIS_STATUS_SUCCESS)
+ {
+ *BytesRead = BytesLeft;
+ *BytesNeeded = 0;
+ }
+
+ return(Status);
+}
+
+
+VOID ElnkiiHalt(
+ IN NDIS_HANDLE MiniportAdapterContext
+)
+{
+ PELNKII_ADAPTER pAdapter;
+
+ //
+ // Get a pointer to our adapter information.
+ //
+ pAdapter = (PELNKII_ADAPTER)MiniportAdapterContext;
+
+ //
+ // Stop the card.
+ //
+ CardStop(pAdapter);
+
+ //
+ // Disconnect the interrupt line.
+ //
+ NdisMDeregisterInterrupt(&pAdapter->Interrupt);
+
+ //
+ // Pause, waiting for any DPC stuff to clear.
+ //
+ NdisStallExecution(250000);
+
+ NdisMDeregisterIoPortRange(
+ pAdapter->MiniportAdapterHandle,
+ (ULONG)pAdapter->IoBaseAddr,
+ 0x10,
+ pAdapter->MappedIoBaseAddr
+ );
+
+ NdisMDeregisterIoPortRange(
+ pAdapter->MiniportAdapterHandle,
+ (ULONG)pAdapter->IoBaseAddr + 0x400,
+ 0x10,
+ pAdapter->MappedGaBaseAddr
+ );
+
+ //
+ // Remove the adapter from the global queue of adapters.
+ //
+ if (ElnkiiMiniportBlock.AdapterQueue == pAdapter)
+ {
+ ElnkiiMiniportBlock.AdapterQueue = pAdapter->pNextElnkiiAdapter;
+ }
+ else
+ {
+ PELNKII_ADAPTER pTmp = ElnkiiMiniportBlock.AdapterQueue;
+
+ while (pTmp->pNextElnkiiAdapter != pAdapter)
+ {
+ pTmp = pTmp->pNextElnkiiAdapter;
+ }
+
+ pTmp->pNextElnkiiAdapter = pTmp->pNextElnkiiAdapter->pNextElnkiiAdapter;
+ }
+
+ //
+ // Free up the memory.
+ //
+ NdisFreeMemory(pAdapter, sizeof(ELNKII_ADAPTER), 0);
+
+ return;
+}
+
+
+
+NDIS_STATUS ElnkiiReset(
+ OUT PBOOLEAN pfAddressingReset,
+ IN NDIS_HANDLE MiniportAdapterContext
+)
+
+/*++
+
+Routine Description:
+
+ NDIS function.
+
+Arguments:
+
+ See NDIS 3.0 spec.
+
+--*/
+
+{
+ PELNKII_ADAPTER pAdapter = (PELNKII_ADAPTER)MiniportAdapterContext;
+ UINT c;
+
+ //
+ // Clear the values for transmits, they will be reset after the
+ // the reset is completed.
+ //
+ pAdapter->NextBufToFill = 0;
+ pAdapter->NextBufToXmit = 0;
+ pAdapter->CurBufXmitting = (XMIT_BUF)-1;
+
+ pAdapter->XmitQueue = NULL;
+ pAdapter->XmitQTail = NULL;
+
+ //
+ // Mark the buffers as empty.
+ //
+ for (c = 0; c < pAdapter->NumBuffers; c++)
+ pAdapter->BufferStatus[c] = EMPTY;
+
+ //
+ // Physically reset the card.
+ //
+ pAdapter->NicInterruptMask = IMR_RCV | IMR_XMIT | IMR_XMIT_ERR | IMR_OVERFLOW;
+
+ return(CardReset(pAdapter) ? NDIS_STATUS_SUCCESS : NDIS_STATUS_FAILURE);
+}
+