4975 lines
116 KiB
C
4975 lines
116 KiB
C
/*++
|
||
|
||
Copyright (c) 1990 Microsoft Corporation
|
||
|
||
Module Name:
|
||
|
||
lance.c
|
||
|
||
Abstract:
|
||
|
||
This is the main file for the Advanced Micro Devices LANCE (Am 7990)
|
||
Ethernet controller. This driver conforms to the NDIS 3.0 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:
|
||
|
||
|
||
--*/
|
||
|
||
#include <ndis.h>
|
||
#include "lancehrd.h"
|
||
#include "lancesft.h"
|
||
#include "dectc.h"
|
||
#include "keywords.h"
|
||
|
||
//#if DBG
|
||
#define STATIC
|
||
//#else
|
||
//#define STATIC static
|
||
//#endif
|
||
|
||
|
||
#if DBG
|
||
|
||
UCHAR LanceSendFails[256] = {0};
|
||
UCHAR LanceSendFailPlace = 0;
|
||
|
||
#endif
|
||
|
||
|
||
NDIS_HANDLE LanceNdisWrapperHandle = NULL;
|
||
PDRIVER_OBJECT LanceDriverObject = NULL;
|
||
|
||
//
|
||
// 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);
|
||
|
||
|
||
#if LANCELOG
|
||
|
||
UCHAR Log[LOG_SIZE] = {0};
|
||
|
||
UCHAR LogPlace = 0;
|
||
UCHAR LogWrapped = 0;
|
||
|
||
UCHAR LancePrintLog = 0;
|
||
|
||
#endif
|
||
|
||
|
||
//
|
||
// If you add to this, make sure to add the
|
||
// LanceQueryInformation() if it is
|
||
// queriable information.
|
||
//
|
||
UINT LanceGlobalSupportedOids[] = {
|
||
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
|
||
};
|
||
|
||
//
|
||
// We define a constant csr0 value that is useful for initializing
|
||
// an already stopped LANCE.
|
||
//
|
||
// This also enables the chip for interrupts.
|
||
//
|
||
#define LANCE_CSR0_INIT_CHIP ((USHORT)0x41)
|
||
|
||
//
|
||
// We define a constant csr0 value that is useful for clearing all of
|
||
// the interesting bits that *could* be set on an interrupt.
|
||
//
|
||
#define LANCE_CSR0_CLEAR_INTERRUPT_BITS ((USHORT)0x7f00)
|
||
|
||
VOID
|
||
LanceDeferredTimerRoutine(
|
||
IN PVOID SystemSpecific1,
|
||
IN NDIS_HANDLE Context,
|
||
IN PVOID SystemSpecific2,
|
||
IN PVOID SystemSpecific3
|
||
);
|
||
|
||
NDIS_STATUS
|
||
LanceQueryInformation(
|
||
IN NDIS_HANDLE MiniportAdapterContext,
|
||
IN NDIS_OID Oid,
|
||
IN PVOID InformationBuffer,
|
||
IN ULONG InformationBufferLength,
|
||
OUT PULONG BytesWritten,
|
||
OUT PULONG BytesNeeded
|
||
);
|
||
|
||
NDIS_STATUS
|
||
LanceSetInformation(
|
||
IN NDIS_HANDLE MiniportAdapterContext,
|
||
IN NDIS_OID Oid,
|
||
IN PVOID InformationBuffer,
|
||
IN ULONG InformationBufferLength,
|
||
OUT PULONG BytesRead,
|
||
OUT PULONG BytesNeeded
|
||
);
|
||
|
||
NDIS_STATUS
|
||
LanceReset(
|
||
OUT PBOOLEAN AddressingReset,
|
||
IN NDIS_HANDLE MiniportAdapterContext
|
||
);
|
||
|
||
BOOLEAN
|
||
AllocateAdapterMemory(
|
||
IN PLANCE_ADAPTER Adapter
|
||
);
|
||
|
||
NDIS_STATUS
|
||
LanceSetPacketFilter(
|
||
IN PLANCE_ADAPTER Adapter,
|
||
IN NDIS_REQUEST_TYPE NdisRequestType,
|
||
IN UINT PacketFilter
|
||
);
|
||
|
||
NDIS_STATUS
|
||
LanceChangeMulticastAddresses(
|
||
IN PLANCE_ADAPTER Adapter,
|
||
IN UINT NewAddressCount,
|
||
IN CHAR NewAddresses[][LANCE_LENGTH_OF_ADDRESS],
|
||
IN NDIS_REQUEST_TYPE NdisRequestType
|
||
);
|
||
|
||
VOID
|
||
DeleteAdapterMemory(
|
||
IN PLANCE_ADAPTER Adapter
|
||
);
|
||
|
||
VOID
|
||
RelinquishReceivePacket(
|
||
IN PLANCE_ADAPTER Adapter,
|
||
IN UINT StartingIndex,
|
||
IN UINT NumberOfBuffers
|
||
);
|
||
|
||
BOOLEAN
|
||
ProcessReceiveInterrupts(
|
||
IN PLANCE_ADAPTER Adapter
|
||
);
|
||
|
||
NDIS_STATUS
|
||
LanceRegisterAdapter(
|
||
IN PLANCE_ADAPTER Adapter
|
||
);
|
||
|
||
BOOLEAN
|
||
ProcessTransmitInterrupts(
|
||
IN PLANCE_ADAPTER Adapter
|
||
);
|
||
|
||
UINT
|
||
CalculateCRC(
|
||
IN UINT NumberOfBytes,
|
||
IN PCHAR Input
|
||
);
|
||
|
||
VOID
|
||
LanceStartChip(
|
||
IN PLANCE_ADAPTER Adapter
|
||
);
|
||
|
||
VOID
|
||
LanceSetInitializationBlock(
|
||
IN PLANCE_ADAPTER Adapter
|
||
);
|
||
|
||
VOID
|
||
SetInitBlockAndInit(
|
||
IN PLANCE_ADAPTER Adapter
|
||
);
|
||
|
||
VOID
|
||
StartAdapterReset(
|
||
IN PLANCE_ADAPTER Adapter
|
||
);
|
||
|
||
VOID
|
||
SetupForReset(
|
||
IN PLANCE_ADAPTER Adapter,
|
||
IN NDIS_REQUEST_TYPE RequestType
|
||
);
|
||
|
||
NDIS_STATUS
|
||
LanceInitialInit(
|
||
IN PLANCE_ADAPTER Adapter
|
||
);
|
||
|
||
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 primary initialization routine for the lance driver.
|
||
It is simply responsible for the intializing the wrapper and registering
|
||
the MAC. It then calls a system and architecture specific routine that
|
||
will initialize and register each adapter.
|
||
|
||
Arguments:
|
||
|
||
DriverObject - Pointer to driver object created by the system.
|
||
|
||
Return Value:
|
||
|
||
The status of the operation.
|
||
|
||
--*/
|
||
|
||
{
|
||
//
|
||
// Receives the status of the NdisRegisterMac operation.
|
||
//
|
||
NDIS_STATUS Status;
|
||
NDIS_HANDLE NdisWrapperHandle;
|
||
NDIS_MINIPORT_CHARACTERISTICS LanceChar;
|
||
NDIS_STRING MacName = NDIS_STRING_CONST("Lance");
|
||
|
||
#if NDIS_WIN
|
||
UCHAR pIds[sizeof (EISA_MCA_ADAPTER_IDS) + sizeof (ULONG)];
|
||
#endif
|
||
|
||
#if NDIS_WIN
|
||
((PEISA_MCA_ADAPTER_IDS)pIds)->nEisaAdapters=1;
|
||
((PEISA_MCA_ADAPTER_IDS)pIds)->nMcaAdapters=0;
|
||
*(PULONG)(((PEISA_MCA_ADAPTER_IDS)pIds)->IdArray)=DE422_COMPRESSED_ID;
|
||
(PVOID)DriverObject=(PVOID)pIds;
|
||
#endif
|
||
|
||
//
|
||
// Initialize the wrapper.
|
||
//
|
||
NdisInitializeWrapper(
|
||
&NdisWrapperHandle,
|
||
DriverObject,
|
||
RegistryPath,
|
||
NULL
|
||
);
|
||
|
||
//
|
||
// Initialize the MAC characteristics for the call to
|
||
// NdisRegisterMac.
|
||
//
|
||
NdisZeroMemory(&LanceChar, sizeof(LanceChar));
|
||
LanceChar.MajorNdisVersion = LANCE_NDIS_MAJOR_VERSION;
|
||
LanceChar.MinorNdisVersion = LANCE_NDIS_MINOR_VERSION;
|
||
LanceChar.CheckForHangHandler = NULL;
|
||
LanceChar.DisableInterruptHandler = LanceDisableInterrupt;
|
||
LanceChar.EnableInterruptHandler = LanceEnableInterrupt;
|
||
LanceChar.HaltHandler = LanceHalt;
|
||
LanceChar.HandleInterruptHandler = LanceHandleInterrupt;
|
||
LanceChar.InitializeHandler = LanceInitialize;
|
||
LanceChar.ISRHandler = LanceIsr;
|
||
LanceChar.QueryInformationHandler = LanceQueryInformation;
|
||
LanceChar.ReconfigureHandler = NULL;
|
||
LanceChar.ResetHandler = LanceReset;
|
||
LanceChar.SendHandler = LanceSend;
|
||
LanceChar.SetInformationHandler = LanceSetInformation;
|
||
LanceChar.TransferDataHandler = LanceTransferData;
|
||
|
||
Status = NdisMRegisterMiniport(
|
||
NdisWrapperHandle,
|
||
&LanceChar,
|
||
sizeof(LanceChar)
|
||
);
|
||
if (Status != NDIS_STATUS_SUCCESS)
|
||
{
|
||
NdisTerminateWrapper(NdisWrapperHandle, NULL);
|
||
}
|
||
|
||
return(Status);
|
||
}
|
||
|
||
#pragma NDIS_INIT_FUNCTION(LanceInitialize)
|
||
|
||
extern
|
||
NDIS_STATUS
|
||
LanceInitialize(
|
||
OUT PNDIS_STATUS OpenErrorStatus,
|
||
OUT PUINT SelectedMediumIndex,
|
||
IN PNDIS_MEDIUM MediumArray,
|
||
IN UINT MediumArraySize,
|
||
IN NDIS_HANDLE MiniportAdapterHandle,
|
||
IN NDIS_HANDLE ConfigurationHandle
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
NE3200Initialize starts an adapter.
|
||
|
||
Arguments:
|
||
|
||
See NDIS 3.0 Miniport spec.
|
||
|
||
Return Value:
|
||
|
||
NDIS_STATUS_SUCCESS
|
||
NDIS_STATUS_PENDING
|
||
|
||
--*/
|
||
|
||
{
|
||
//
|
||
// Pointer for the adapter root.
|
||
//
|
||
PLANCE_ADAPTER Adapter;
|
||
|
||
|
||
NDIS_HANDLE ConfigHandle;
|
||
PNDIS_CONFIGURATION_PARAMETER ReturnedValue;
|
||
NDIS_STRING IoAddressStr = IOADDRESS;
|
||
NDIS_STRING MaxMulticastListStr = MAXMULTICASTLIST;
|
||
NDIS_STRING NetworkAddressStr = NETWORKADDRESS;
|
||
NDIS_STRING InterruptStr = INTERRUPT;
|
||
NDIS_STRING CardStr = CARDTYPE;
|
||
NDIS_STRING MemoryBaseAddrStr = MEMMAPPEDBASEADDRESS;
|
||
|
||
#if NDIS2
|
||
NDIS_STRING DE201Str = NDIS_STRING_CONST("DE201");
|
||
NDIS_STRING DE100Str = NDIS_STRING_CONST("DE100");
|
||
NDIS_STRING DEPCAStr = NDIS_STRING_CONST("DEPCA");
|
||
NDIS_STRING DECTCStr = NDIS_STRING_CONST("DECTC");
|
||
NDIS_STRING DE422Str = NDIS_STRING_CONST("DE422");
|
||
NDIS_STRING DE200Str = NDIS_STRING_CONST("DE200");
|
||
NDIS_STRING DE101Str = NDIS_STRING_CONST("DE101");
|
||
#endif
|
||
|
||
NDIS_EISA_FUNCTION_INFORMATION EisaData;
|
||
USHORT ConfigValue = 0;
|
||
UCHAR HiBaseValue = 0;
|
||
|
||
UINT MaxMulticastList = 32;
|
||
PVOID NetAddress;
|
||
UINT Length;
|
||
|
||
USHORT RegUshort;
|
||
UCHAR RegUchar;
|
||
UINT LanceSlot = 1;
|
||
|
||
BOOLEAN ConfigError = FALSE;
|
||
NDIS_STATUS ConfigErrorCode;
|
||
NDIS_STATUS Status;
|
||
|
||
|
||
//
|
||
// Search for correct medium.
|
||
//
|
||
|
||
for (; MediumArraySize > 0; MediumArraySize--){
|
||
|
||
if (MediumArray[MediumArraySize - 1] == NdisMedium802_3){
|
||
|
||
MediumArraySize--;
|
||
|
||
break;
|
||
|
||
}
|
||
|
||
}
|
||
|
||
if (MediumArray[MediumArraySize] != NdisMedium802_3){
|
||
|
||
return( NDIS_STATUS_UNSUPPORTED_MEDIA );
|
||
|
||
}
|
||
|
||
*SelectedMediumIndex = MediumArraySize;
|
||
|
||
//
|
||
// Allocate the Adapter block.
|
||
//
|
||
|
||
LANCE_ALLOC_PHYS(&Adapter, sizeof(LANCE_ADAPTER));
|
||
if (Adapter == NULL)
|
||
{
|
||
return( NDIS_STATUS_RESOURCES ) ;
|
||
}
|
||
|
||
LANCE_ZERO_MEMORY(Adapter, sizeof(LANCE_ADAPTER));
|
||
|
||
Adapter->MaxLookAhead = LANCE_MAX_LOOKAHEAD;
|
||
|
||
//
|
||
// Start with the default card
|
||
//
|
||
|
||
Adapter->LanceCard = LANCE_DE201;
|
||
Adapter->MiniportAdapterHandle = MiniportAdapterHandle;
|
||
|
||
Adapter->IoBaseAddr = LANCE_DE201_PRI_NICSR_ADDRESS;
|
||
Adapter->HardwareBaseAddr = LANCE_DE201_BASE;
|
||
Adapter->AmountOfHardwareMemory = LANCE_DE201_HARDWARE_MEMORY;
|
||
Adapter->InterruptNumber = LANCE_DE201_INTERRUPT_VECTOR;
|
||
Adapter->InterruptRequestLevel = LANCE_DE201_INTERRUPT_VECTOR;
|
||
Adapter->BeingRemoved = FALSE;
|
||
|
||
NdisOpenConfiguration(&Status, &ConfigHandle, ConfigurationHandle);
|
||
if (Status != NDIS_STATUS_SUCCESS)
|
||
return(Status);
|
||
|
||
#if NDIS2
|
||
//
|
||
// Read Card Type
|
||
//
|
||
|
||
NdisReadConfiguration(
|
||
&Status,
|
||
&ReturnedValue,
|
||
ConfigHandle,
|
||
&CardStr,
|
||
NdisParameterString
|
||
);
|
||
if (Status == NDIS_STATUS_SUCCESS)
|
||
{
|
||
if (NdisEqualString (&ReturnedValue->ParameterData.StringData, &DE201Str, 1)) {
|
||
Adapter->LanceCard = LANCE_DE201;
|
||
} else if (NdisEqualString (&ReturnedValue->ParameterData.StringData, &DE100Str, 1)) {
|
||
Adapter->LanceCard = LANCE_DE100;
|
||
} else if (NdisEqualString (&ReturnedValue->ParameterData.StringData, &DEPCAStr, 1)) {
|
||
Adapter->LanceCard = LANCE_DEPCA;
|
||
#ifndef i386
|
||
} else if (NdisEqualString (&ReturnedValue->ParameterData.StringData, &DECTCStr, 1)) {
|
||
Adapter->LanceCard = LANCE_DECTC;
|
||
ConfigErrorCode = LanceDecTcGetConfiguration(ConfigHandle, Adapter);
|
||
if ( ConfigErrorCode != NDIS_STATUS_SUCCESS ) {
|
||
ConfigError = TRUE;
|
||
}
|
||
#endif // i386
|
||
} else if (NdisEqualString (&ReturnedValue->ParameterData.StringData, &DE422Str, 1)) {
|
||
Adapter->LanceCard = LANCE_DE422;
|
||
} else if (NdisEqualString (&ReturnedValue->ParameterData.StringData, &DE200Str, 1)) {
|
||
//
|
||
// This is the De200, but it operates exactly like the 201.
|
||
//
|
||
Adapter->LanceCard = LANCE_DE201;
|
||
} else if (NdisEqualString (&ReturnedValue->ParameterData.StringData, &DE101Str, 1)) {
|
||
//
|
||
// This is the De101, but it operates exactly like the 100.
|
||
//
|
||
Adapter->LanceCard = LANCE_DE100;
|
||
} else {
|
||
ConfigError = TRUE;
|
||
ConfigErrorCode = NDIS_ERROR_CODE_UNSUPPORTED_CONFIGURATION;
|
||
goto RegisterAdapter;
|
||
}
|
||
|
||
}
|
||
|
||
|
||
#else
|
||
//
|
||
// Read Card Type
|
||
//
|
||
|
||
NdisReadConfiguration(
|
||
&Status,
|
||
&ReturnedValue,
|
||
ConfigHandle,
|
||
&CardStr,
|
||
NdisParameterInteger
|
||
);
|
||
if (Status == NDIS_STATUS_SUCCESS)
|
||
{
|
||
if (ReturnedValue->ParameterData.IntegerData == 2)
|
||
{
|
||
Adapter->LanceCard = LANCE_DE201;
|
||
}
|
||
else if (ReturnedValue->ParameterData.IntegerData == 1)
|
||
{
|
||
Adapter->LanceCard = LANCE_DE100;
|
||
}
|
||
else if (ReturnedValue->ParameterData.IntegerData == 3)
|
||
{
|
||
Adapter->LanceCard = LANCE_DEPCA;
|
||
|
||
#ifndef i386
|
||
}
|
||
else if (ReturnedValue->ParameterData.IntegerData == 4)
|
||
{
|
||
Adapter->LanceCard = LANCE_DECTC;
|
||
|
||
ConfigErrorCode = LanceDecTcGetConfiguration(ConfigHandle, Adapter);
|
||
|
||
if ( ConfigErrorCode != NDIS_STATUS_SUCCESS )
|
||
{
|
||
ConfigError = TRUE;
|
||
}
|
||
#endif // i386
|
||
|
||
}
|
||
else if (ReturnedValue->ParameterData.IntegerData == 5)
|
||
{
|
||
Adapter->LanceCard = LANCE_DE422;
|
||
}
|
||
else if (ReturnedValue->ParameterData.IntegerData == 6)
|
||
{
|
||
//
|
||
// This is the De200, but it operates exactly like the 201.
|
||
//
|
||
Adapter->LanceCard = LANCE_DE201;
|
||
}
|
||
else if (ReturnedValue->ParameterData.IntegerData == 7)
|
||
{
|
||
//
|
||
// This is the De101, but it operates exactly like the 100.
|
||
//
|
||
Adapter->LanceCard = LANCE_DE100;
|
||
}
|
||
else
|
||
{
|
||
ConfigError = TRUE;
|
||
ConfigErrorCode = NDIS_ERROR_CODE_UNSUPPORTED_CONFIGURATION;
|
||
|
||
goto RegisterAdapter;
|
||
}
|
||
}
|
||
#endif
|
||
|
||
//
|
||
// Read MaxMulticastList
|
||
//
|
||
NdisReadConfiguration(
|
||
&Status,
|
||
&ReturnedValue,
|
||
ConfigHandle,
|
||
&MaxMulticastListStr,
|
||
NdisParameterInteger
|
||
);
|
||
if (Status == NDIS_STATUS_SUCCESS)
|
||
{
|
||
MaxMulticastList = ReturnedValue->ParameterData.IntegerData;
|
||
}
|
||
|
||
//
|
||
// Read net address
|
||
//
|
||
NdisReadNetworkAddress(
|
||
&Status,
|
||
&NetAddress,
|
||
&Length,
|
||
ConfigHandle
|
||
);
|
||
|
||
if ((Length == LANCE_LENGTH_OF_ADDRESS) && (Status == NDIS_STATUS_SUCCESS))
|
||
{
|
||
NdisMoveMemory(
|
||
Adapter->CurrentNetworkAddress,
|
||
NetAddress,
|
||
LANCE_LENGTH_OF_ADDRESS
|
||
);
|
||
}
|
||
|
||
if (Adapter->LanceCard & (LANCE_DE201 | LANCE_DE100))
|
||
{
|
||
//
|
||
// Read IoAddress
|
||
//
|
||
NdisReadConfiguration(
|
||
&Status,
|
||
&ReturnedValue,
|
||
ConfigHandle,
|
||
&IoAddressStr,
|
||
NdisParameterHexInteger
|
||
);
|
||
if (Status == NDIS_STATUS_SUCCESS)
|
||
{
|
||
if (ReturnedValue->ParameterData.IntegerData == LANCE_DE201_PRI_NICSR_ADDRESS)
|
||
{
|
||
Adapter->IoBaseAddr = LANCE_DE201_PRI_NICSR_ADDRESS;
|
||
}
|
||
else if (ReturnedValue->ParameterData.IntegerData == LANCE_DE201_SEC_NICSR_ADDRESS)
|
||
{
|
||
Adapter->IoBaseAddr = LANCE_DE201_SEC_NICSR_ADDRESS;
|
||
}
|
||
else
|
||
{
|
||
ConfigError = TRUE;
|
||
ConfigErrorCode = NDIS_ERROR_CODE_BAD_IO_BASE_ADDRESS;
|
||
|
||
goto RegisterAdapter;
|
||
}
|
||
}
|
||
|
||
//
|
||
// Read Interrupt
|
||
//
|
||
NdisReadConfiguration(
|
||
&Status,
|
||
&ReturnedValue,
|
||
ConfigHandle,
|
||
&InterruptStr,
|
||
NdisParameterInteger
|
||
);
|
||
if (Status == NDIS_STATUS_SUCCESS)
|
||
{
|
||
Adapter->InterruptNumber = (CCHAR)ReturnedValue->ParameterData.IntegerData;
|
||
Adapter->InterruptRequestLevel = Adapter->InterruptNumber;
|
||
|
||
if (Adapter->LanceCard == LANCE_DE201)
|
||
{
|
||
if (!((Adapter->InterruptNumber == 5) ||
|
||
(Adapter->InterruptNumber == 9) ||
|
||
(Adapter->InterruptNumber == 10) ||
|
||
(Adapter->InterruptNumber == 11) ||
|
||
(Adapter->InterruptNumber == 15))) {
|
||
|
||
ConfigError = TRUE;
|
||
ConfigErrorCode = NDIS_ERROR_CODE_UNSUPPORTED_CONFIGURATION;
|
||
|
||
goto RegisterAdapter;
|
||
|
||
}
|
||
|
||
} else {
|
||
|
||
if (!((Adapter->InterruptNumber == 2) ||
|
||
(Adapter->InterruptNumber == 3) ||
|
||
(Adapter->InterruptNumber == 4) ||
|
||
(Adapter->InterruptNumber == 5) ||
|
||
(Adapter->InterruptNumber == 7))) {
|
||
|
||
ConfigError = TRUE;
|
||
ConfigErrorCode = NDIS_ERROR_CODE_UNSUPPORTED_CONFIGURATION;
|
||
|
||
goto RegisterAdapter;
|
||
|
||
}
|
||
|
||
}
|
||
|
||
}
|
||
|
||
|
||
|
||
//
|
||
// Read MemoryBaseAddress
|
||
//
|
||
|
||
NdisReadConfiguration(
|
||
&Status,
|
||
&ReturnedValue,
|
||
ConfigHandle,
|
||
&MemoryBaseAddrStr,
|
||
NdisParameterHexInteger
|
||
);
|
||
|
||
if (Status == NDIS_STATUS_SUCCESS) {
|
||
|
||
#if NDIS2
|
||
Adapter->HardwareBaseAddr = (PVOID)((ReturnedValue->ParameterData.IntegerData) << 4);
|
||
#else
|
||
Adapter->HardwareBaseAddr = (PVOID)(ReturnedValue->ParameterData.IntegerData);
|
||
#endif
|
||
if (!((Adapter->HardwareBaseAddr == (PVOID)0xC0000) ||
|
||
(Adapter->HardwareBaseAddr == (PVOID)0xC8000) ||
|
||
(Adapter->HardwareBaseAddr == (PVOID)0xD0000) ||
|
||
(Adapter->HardwareBaseAddr == (PVOID)0xD8000) ||
|
||
(Adapter->HardwareBaseAddr == (PVOID)0xE0000) ||
|
||
(Adapter->HardwareBaseAddr == (PVOID)0xE8000))) {
|
||
|
||
ConfigError = TRUE;
|
||
ConfigErrorCode = NDIS_ERROR_CODE_UNSUPPORTED_CONFIGURATION;
|
||
|
||
goto RegisterAdapter;
|
||
|
||
}
|
||
|
||
}
|
||
|
||
|
||
if (((ULONG)Adapter->HardwareBaseAddr) & 0x8000) {
|
||
|
||
Adapter->AmountOfHardwareMemory = 0x8000;
|
||
Adapter->HardwareBaseOffset = 0x8000;
|
||
|
||
} else {
|
||
|
||
Adapter->AmountOfHardwareMemory = 0x10000;
|
||
Adapter->HardwareBaseOffset = 0x0;
|
||
|
||
}
|
||
|
||
} else if (Adapter->LanceCard == LANCE_DEPCA) {
|
||
|
||
Adapter->InterruptNumber = LANCE_DEPCA_INTERRUPT_VECTOR;
|
||
Adapter->InterruptRequestLevel = LANCE_DEPCA_INTERRUPT_VECTOR;
|
||
Adapter->AmountOfHardwareMemory = LANCE_DEPCA_HARDWARE_MEMORY;
|
||
Adapter->HardwareBaseAddr = LANCE_DEPCA_BASE;
|
||
Adapter->IoBaseAddr = LANCE_DEPCA_NICSR_ADDRESS;
|
||
|
||
} else if (Adapter->LanceCard == LANCE_DE422) {
|
||
|
||
PUCHAR CurrentChar;
|
||
BOOLEAN LastEntry;
|
||
UCHAR InitType;
|
||
USHORT PortAddress, PortValue, Mask;
|
||
|
||
//
|
||
// Read Slot Number
|
||
//
|
||
NdisReadEisaSlotInformation(
|
||
&Status,
|
||
ConfigurationHandle,
|
||
&(Adapter->SlotNumber),
|
||
&EisaData
|
||
);
|
||
|
||
if (Status != NDIS_STATUS_SUCCESS) {
|
||
|
||
ConfigError = TRUE;
|
||
ConfigErrorCode = NDIS_ERROR_CODE_UNSUPPORTED_CONFIGURATION;
|
||
|
||
goto RegisterAdapter;
|
||
|
||
}
|
||
|
||
//
|
||
// Setup Ports
|
||
//
|
||
|
||
Adapter->IoBaseAddr = (((ULONG)Adapter->SlotNumber) << 12) +
|
||
LANCE_DE422_NICSR_ADDRESS;
|
||
|
||
Adapter->NetworkHardwareAddress = Adapter->IoBaseAddr + LANCE_DE422_NETWORK_OFFSET;
|
||
|
||
CurrentChar = (PUCHAR) (EisaData.InitializationData);
|
||
LastEntry = FALSE;
|
||
|
||
while (!LastEntry) {
|
||
|
||
InitType = *(CurrentChar++);
|
||
PortAddress = *((USHORT UNALIGNED *) CurrentChar++);
|
||
|
||
CurrentChar++;
|
||
|
||
if ((InitType & 0x80) == 0) {
|
||
LastEntry = TRUE;
|
||
}
|
||
|
||
|
||
|
||
if (PortAddress == (USHORT)(Adapter->NetworkHardwareAddress)) {
|
||
|
||
PortValue = *((USHORT UNALIGNED *) CurrentChar++);
|
||
|
||
} else if (PortAddress == ((Adapter->SlotNumber << 12) +
|
||
LANCE_DE422_NICSR_ADDRESS +
|
||
LANCE_DE422_EXTENDED_MEMORY_BASE_OFFSET)) {
|
||
|
||
PortValue = (USHORT)(*(CurrentChar++));
|
||
|
||
} else {
|
||
|
||
continue;
|
||
|
||
}
|
||
|
||
|
||
|
||
if (InitType & 0x40) {
|
||
|
||
if (PortAddress == Adapter->NetworkHardwareAddress) {
|
||
|
||
Mask = *((USHORT UNALIGNED *) CurrentChar++);
|
||
|
||
} else {
|
||
|
||
Mask = (USHORT)(*(CurrentChar++));
|
||
|
||
}
|
||
|
||
} else {
|
||
|
||
Mask = 0;
|
||
|
||
}
|
||
|
||
if (PortAddress == Adapter->NetworkHardwareAddress) {
|
||
|
||
ConfigValue &= Mask;
|
||
ConfigValue |= PortValue;
|
||
|
||
} else {
|
||
|
||
HiBaseValue &= (UCHAR)Mask;
|
||
HiBaseValue |= (UCHAR)PortValue;
|
||
|
||
}
|
||
|
||
}
|
||
|
||
//
|
||
// Interpret values
|
||
//
|
||
|
||
switch (ConfigValue & 0x78) {
|
||
|
||
case 0x40:
|
||
|
||
Adapter->InterruptNumber = 11;
|
||
break;
|
||
|
||
case 0x20:
|
||
|
||
Adapter->InterruptNumber = 10;
|
||
break;
|
||
|
||
case 0x10:
|
||
|
||
Adapter->InterruptNumber = 9;
|
||
break;
|
||
|
||
case 0x08:
|
||
|
||
Adapter->InterruptNumber = 5;
|
||
break;
|
||
|
||
default:
|
||
|
||
ConfigError = TRUE;
|
||
ConfigErrorCode = NDIS_ERROR_CODE_UNSUPPORTED_CONFIGURATION;
|
||
|
||
goto RegisterAdapter;
|
||
|
||
}
|
||
|
||
Adapter->InterruptRequestLevel = Adapter->InterruptNumber;
|
||
|
||
//
|
||
// We postpone the rest of the processing since we have to read from
|
||
// the NICSR to get the amount of hardware memory and cannot do that
|
||
// until after we have called NdisRegisterAdapter.
|
||
//
|
||
|
||
}
|
||
|
||
RegisterAdapter:
|
||
|
||
NdisCloseConfiguration(ConfigHandle);
|
||
|
||
if (ConfigError) {
|
||
|
||
NdisWriteErrorLogEntry(
|
||
Adapter->MiniportAdapterHandle,
|
||
ConfigErrorCode,
|
||
0
|
||
);
|
||
|
||
LANCE_FREE_PHYS(Adapter, sizeof(LANCE_ADAPTER));
|
||
|
||
return(NDIS_STATUS_FAILURE);
|
||
|
||
}
|
||
|
||
NdisMSetAttributes(
|
||
MiniportAdapterHandle,
|
||
(NDIS_HANDLE)Adapter,
|
||
FALSE,
|
||
(Adapter->LanceCard == LANCE_DE422) ?
|
||
NdisInterfaceEisa :
|
||
NdisInterfaceIsa
|
||
);
|
||
|
||
//
|
||
// Register the IoPortRanges
|
||
//
|
||
|
||
if (Adapter->LanceCard & (LANCE_DE100 | LANCE_DE201)) {
|
||
|
||
Status = NdisMRegisterIoPortRange(
|
||
(PVOID *)(&(Adapter->Nicsr)),
|
||
MiniportAdapterHandle,
|
||
Adapter->IoBaseAddr,
|
||
0x10
|
||
);
|
||
|
||
Adapter->RAP = Adapter->Nicsr + LANCE_DE201_RAP_OFFSET;
|
||
Adapter->RDP = Adapter->Nicsr + LANCE_DE201_RDP_OFFSET;
|
||
Adapter->NetworkHardwareAddress = Adapter->Nicsr + LANCE_DE201_NETWORK_OFFSET;
|
||
|
||
} else if (Adapter->LanceCard == LANCE_DE422) {
|
||
|
||
Status = NdisMRegisterIoPortRange(
|
||
(PVOID *)(&(Adapter->Nicsr)),
|
||
MiniportAdapterHandle,
|
||
Adapter->IoBaseAddr,
|
||
0x90
|
||
);
|
||
|
||
Adapter->RAP = Adapter->Nicsr + LANCE_DE422_RAP_OFFSET;
|
||
Adapter->RDP = Adapter->Nicsr + LANCE_DE422_RDP_OFFSET;
|
||
Adapter->NetworkHardwareAddress = Adapter->Nicsr + LANCE_DE422_NETWORK_OFFSET;
|
||
|
||
} else if (Adapter->LanceCard == LANCE_DEPCA) {
|
||
|
||
Status = NdisMRegisterIoPortRange(
|
||
(PVOID *)(&(Adapter->Nicsr)),
|
||
MiniportAdapterHandle,
|
||
Adapter->IoBaseAddr,
|
||
0x10
|
||
);
|
||
|
||
Adapter->LanceCard = LANCE_DE100;
|
||
Adapter->RAP = Adapter->Nicsr + LANCE_DEPCA_RAP_OFFSET;
|
||
Adapter->RDP = Adapter->Nicsr + LANCE_DEPCA_RDP_OFFSET;
|
||
Adapter->NetworkHardwareAddress = Adapter->Nicsr + LANCE_DEPCA_EPROM_OFFSET;
|
||
|
||
}
|
||
|
||
#ifndef i386
|
||
|
||
else if (Adapter->LanceCard == LANCE_DECTC) {
|
||
|
||
Status = NdisMRegisterIoPortRange(
|
||
(PVOID *)(&(Adapter->Nicsr)),
|
||
MiniportAdapterHandle,
|
||
((ULONG)Adapter->HardwareBaseAddr) + LANCE_DECTC_REGISTER_OFFSET,
|
||
LANCE_DECTC_REGISTER_MAPSIZE
|
||
);
|
||
|
||
Adapter->RAP = Adapter->Nicsr + LANCE_DEPCA_RAP_OFFSET;
|
||
Adapter->RDP = Adapter->Nicsr + LANCE_DEPCA_RDP_OFFSET;
|
||
Adapter->NetworkHardwareAddress = Adapter->Nicsr + LANCE_DEPCA_EPROM_OFFSET;
|
||
|
||
}
|
||
|
||
#endif
|
||
|
||
if (Status != NDIS_STATUS_SUCCESS) {
|
||
|
||
LANCE_FREE_PHYS(Adapter, sizeof(LANCE_ADAPTER));
|
||
|
||
return Status;
|
||
|
||
}
|
||
|
||
//
|
||
// Now we get the rest of the information necessary for the DE422.
|
||
//
|
||
if (Adapter->LanceCard == LANCE_DE422)
|
||
{
|
||
//
|
||
// Verify card is a DE422
|
||
//
|
||
|
||
NdisRawReadPortUshort(
|
||
(Adapter->Nicsr + LANCE_DE422_EISA_IDENTIFICATION_OFFSET),
|
||
&RegUshort
|
||
);
|
||
|
||
if (RegUshort != 0xA310) {
|
||
|
||
//
|
||
// Not a DE422 card
|
||
//
|
||
|
||
NdisWriteErrorLogEntry(
|
||
Adapter->MiniportAdapterHandle,
|
||
NDIS_ERROR_CODE_ADAPTER_NOT_FOUND,
|
||
0
|
||
);
|
||
|
||
Status = NDIS_STATUS_FAILURE;
|
||
goto Fail1;
|
||
|
||
}
|
||
|
||
NdisRawReadPortUshort(
|
||
Adapter->Nicsr +
|
||
LANCE_DE422_EISA_IDENTIFICATION_OFFSET + 2,
|
||
&RegUshort
|
||
);
|
||
|
||
if (RegUshort != 0x2042) {
|
||
|
||
//
|
||
// Not a DE422 card
|
||
//
|
||
|
||
NdisWriteErrorLogEntry(
|
||
Adapter->MiniportAdapterHandle,
|
||
NDIS_ERROR_CODE_ADAPTER_NOT_FOUND,
|
||
0
|
||
);
|
||
|
||
Status = NDIS_STATUS_FAILURE;
|
||
goto Fail1;
|
||
|
||
}
|
||
|
||
//
|
||
// Check that the card is enabled.
|
||
//
|
||
|
||
NdisRawReadPortUchar(
|
||
Adapter->Nicsr +
|
||
LANCE_DE422_EISA_CONTROL_OFFSET,
|
||
&RegUchar
|
||
);
|
||
|
||
if (!(RegUchar & 0x1)) {
|
||
|
||
NdisWriteErrorLogEntry(
|
||
Adapter->MiniportAdapterHandle,
|
||
NDIS_ERROR_CODE_ADAPTER_DISABLED,
|
||
0
|
||
);
|
||
|
||
Status = NDIS_STATUS_FAILURE;
|
||
goto Fail1;
|
||
|
||
}
|
||
|
||
//
|
||
// Get Memory size
|
||
//
|
||
|
||
NdisRawReadPortUshort(
|
||
Adapter->Nicsr,
|
||
&RegUshort
|
||
);
|
||
|
||
if (RegUshort & LANCE_NICSR_BUFFER_SIZE) {
|
||
|
||
Adapter->AmountOfHardwareMemory = 0x8000;
|
||
|
||
} else if (RegUshort & LANCE_NICSR_128K) {
|
||
|
||
Adapter->AmountOfHardwareMemory = 0x20000;
|
||
Adapter->NicsrDefaultValue = LANCE_NICSR_128K;
|
||
|
||
} else {
|
||
|
||
Adapter->AmountOfHardwareMemory = 0x10000;
|
||
|
||
}
|
||
|
||
//
|
||
// Get Base memory address
|
||
//
|
||
|
||
switch (Adapter->AmountOfHardwareMemory) {
|
||
|
||
case 0x8000:
|
||
|
||
switch (ConfigValue & 0x07) {
|
||
|
||
case 0x04:
|
||
|
||
Adapter->HardwareBaseAddr = (PVOID)((HiBaseValue << 24) + 0xC8000);
|
||
Adapter->HardwareBaseOffset = 0x8000;
|
||
break;
|
||
|
||
case 0x05:
|
||
|
||
Adapter->HardwareBaseAddr = (PVOID)((HiBaseValue << 24) + 0xE8000);
|
||
Adapter->HardwareBaseOffset = 0x8000;
|
||
break;
|
||
|
||
case 0x06:
|
||
|
||
Adapter->HardwareBaseAddr = (PVOID)((HiBaseValue << 24) + 0xD8000);
|
||
Adapter->HardwareBaseOffset = 0x8000;
|
||
break;
|
||
|
||
case 0x07:
|
||
|
||
Adapter->HardwareBaseAddr = (PVOID)((HiBaseValue << 24) + 0xF8000);
|
||
Adapter->HardwareBaseOffset = 0x8000;
|
||
break;
|
||
|
||
default:
|
||
|
||
NdisWriteErrorLogEntry(
|
||
Adapter->MiniportAdapterHandle,
|
||
NDIS_ERROR_CODE_UNSUPPORTED_CONFIGURATION,
|
||
0
|
||
);
|
||
|
||
Status = NDIS_STATUS_FAILURE;
|
||
goto Fail1;
|
||
|
||
}
|
||
break;
|
||
|
||
case 0x10000:
|
||
|
||
switch (ConfigValue & 0x07) {
|
||
|
||
case 0x00:
|
||
|
||
Adapter->HardwareBaseAddr = (PVOID)((HiBaseValue << 24) + 0xC0000);
|
||
Adapter->HardwareBaseOffset = 0x0000;
|
||
break;
|
||
|
||
case 0x01:
|
||
|
||
Adapter->HardwareBaseAddr = (PVOID)((HiBaseValue << 24) + 0xE0000);
|
||
Adapter->HardwareBaseOffset = 0x0000;
|
||
break;
|
||
|
||
case 0x02:
|
||
|
||
Adapter->HardwareBaseAddr = (PVOID)((HiBaseValue << 24) + 0xD0000);
|
||
Adapter->HardwareBaseOffset = 0x0000;
|
||
break;
|
||
|
||
case 0x03:
|
||
|
||
Adapter->HardwareBaseAddr = (PVOID)((HiBaseValue << 24) + 0xF0000);
|
||
Adapter->HardwareBaseOffset = 0x0000;
|
||
break;
|
||
|
||
default:
|
||
|
||
NdisWriteErrorLogEntry(
|
||
Adapter->MiniportAdapterHandle,
|
||
NDIS_ERROR_CODE_UNSUPPORTED_CONFIGURATION,
|
||
0
|
||
);
|
||
|
||
Status = NDIS_STATUS_FAILURE;
|
||
goto Fail1;
|
||
|
||
}
|
||
break;
|
||
|
||
case 0x20000:
|
||
|
||
switch (ConfigValue & 0x07) {
|
||
|
||
case 0x00:
|
||
|
||
Adapter->HardwareBaseAddr = (PVOID)((HiBaseValue << 24) + 0xC0000);
|
||
Adapter->HardwareBaseOffset = 0x0000;
|
||
break;
|
||
|
||
case 0x01:
|
||
|
||
Adapter->HardwareBaseAddr = (PVOID)((HiBaseValue << 24) + 0xD0000);
|
||
Adapter->HardwareBaseOffset = 0x0000;
|
||
break;
|
||
|
||
default:
|
||
|
||
NdisWriteErrorLogEntry(
|
||
Adapter->MiniportAdapterHandle,
|
||
NDIS_ERROR_CODE_UNSUPPORTED_CONFIGURATION,
|
||
0
|
||
);
|
||
|
||
Status = NDIS_STATUS_FAILURE;
|
||
goto Fail1;
|
||
|
||
}
|
||
|
||
break;
|
||
|
||
}
|
||
|
||
}
|
||
|
||
//
|
||
// Set the port addresses and the network address.
|
||
//
|
||
|
||
Adapter->InterruptsStopped = FALSE;
|
||
Adapter->MaxMulticastList = MaxMulticastList;
|
||
|
||
Status = LanceRegisterAdapter( Adapter );
|
||
|
||
if (Status != NDIS_STATUS_SUCCESS) {
|
||
|
||
goto Fail1;
|
||
}
|
||
|
||
return Status;
|
||
|
||
Fail1:
|
||
|
||
//
|
||
// Deregister the IoPortRanges
|
||
//
|
||
|
||
if (Adapter->LanceCard & (LANCE_DE100 | LANCE_DE201)) {
|
||
|
||
NdisMDeregisterIoPortRange(
|
||
MiniportAdapterHandle,
|
||
Adapter->IoBaseAddr,
|
||
0x10,
|
||
(PVOID)(Adapter->Nicsr)
|
||
);
|
||
|
||
} else if (Adapter->LanceCard == LANCE_DE422) {
|
||
|
||
NdisMDeregisterIoPortRange(
|
||
MiniportAdapterHandle,
|
||
Adapter->IoBaseAddr,
|
||
0x90,
|
||
(PVOID)(Adapter->Nicsr)
|
||
);
|
||
|
||
}
|
||
|
||
LANCE_FREE_PHYS(Adapter, sizeof(LANCE_ADAPTER));
|
||
|
||
return(Status);
|
||
}
|
||
|
||
|
||
VOID
|
||
LanceHalt(
|
||
IN PVOID MiniportAdapterContext
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
LanceHalt stops an adapter and deregisters everything.
|
||
|
||
Arguments:
|
||
|
||
MiniportAdapterContext - The context value that the driver when
|
||
LanceInitialize is called. Actually as pointer to an
|
||
LANCE_ADAPTER.
|
||
|
||
Return Value:
|
||
|
||
None.
|
||
|
||
--*/
|
||
{
|
||
|
||
PLANCE_ADAPTER Adapter;
|
||
|
||
Adapter = PLANCE_ADAPTER_FROM_CONTEXT_HANDLE(MiniportAdapterContext);
|
||
|
||
LOG(REMOVE);
|
||
|
||
//
|
||
// bug 2275
|
||
//
|
||
|
||
LanceSyncStopChip(Adapter);
|
||
|
||
NdisMDeregisterInterrupt(&(Adapter->Interrupt));
|
||
|
||
#if NDIS_WIN
|
||
|
||
//
|
||
// Restore saved values
|
||
//
|
||
{
|
||
PUCHAR pTemp = Adapter->MmMappedBaseAddr;
|
||
|
||
(UINT)pTemp &= 0xffff0000;
|
||
(UINT)pTemp |= 0x0000bffe;
|
||
|
||
NdisWriteRegisterUshort((PUSHORT)pTemp, Adapter->SavedMemBase);
|
||
|
||
pTemp = Adapter->MmMappedBaseAddr;
|
||
NdisWriteRegisterUlong((PULONG)pTemp, Adapter->Reserved1);
|
||
NdisWriteRegisterUlong((PULONG)pTemp, Adapter->Reserved2);
|
||
}
|
||
|
||
#endif
|
||
|
||
NdisMUnmapIoSpace(
|
||
Adapter->MiniportAdapterHandle,
|
||
Adapter->MmMappedBaseAddr,
|
||
Adapter->AmountOfHardwareMemory
|
||
);
|
||
|
||
//
|
||
// bug3327
|
||
//
|
||
NdisRawWritePortUshort((ULONG)(Adapter->Nicsr), 0x04);
|
||
|
||
if (Adapter->LanceCard & (LANCE_DE100 | LANCE_DE201)) {
|
||
|
||
NdisMDeregisterIoPortRange(
|
||
Adapter->MiniportAdapterHandle,
|
||
Adapter->IoBaseAddr,
|
||
0x10,
|
||
(PVOID)(Adapter->Nicsr)
|
||
);
|
||
|
||
} else if (Adapter->LanceCard == LANCE_DE422) {
|
||
|
||
NdisMDeregisterIoPortRange(
|
||
Adapter->MiniportAdapterHandle,
|
||
Adapter->IoBaseAddr,
|
||
0x90,
|
||
(PVOID)(Adapter->Nicsr)
|
||
);
|
||
|
||
}
|
||
|
||
DeleteAdapterMemory(Adapter);
|
||
|
||
NdisFreeMemory(Adapter, sizeof(LANCE_ADAPTER), 0);
|
||
|
||
return;
|
||
}
|
||
|
||
#pragma NDIS_INIT_FUNCTION(LanceRegisterAdapter)
|
||
|
||
NDIS_STATUS
|
||
LanceRegisterAdapter(
|
||
IN PLANCE_ADAPTER Adapter
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine is responsible for the allocation of the datastructures
|
||
for the driver as well as any hardware specific details necessary
|
||
to talk with the device.
|
||
|
||
Arguments:
|
||
|
||
Adapter - Pointer to the adapter block.
|
||
|
||
Return Value:
|
||
|
||
Returns false if anything occurred that prevents the initialization
|
||
of the adapter.
|
||
|
||
--*/
|
||
{
|
||
//
|
||
// Result of Ndis Calls.
|
||
//
|
||
NDIS_STATUS Status;
|
||
|
||
|
||
//
|
||
// We put in this assertion to make sure that ushort are 2 bytes.
|
||
// if they aren't then the initialization block definition needs
|
||
// to be changed.
|
||
//
|
||
// Also all of the logic that deals with status registers assumes
|
||
// that control registers are only 2 bytes.
|
||
//
|
||
|
||
ASSERT(sizeof(USHORT) == 2);
|
||
|
||
//
|
||
// This assertion checks that the network address in the initialization
|
||
// block does start on the third byte of the initalization block.
|
||
//
|
||
// If this is true then other fields in the initialization block
|
||
// and the send and receive descriptors should be at their correct
|
||
// locations.
|
||
//
|
||
|
||
#ifdef NDIS_NT
|
||
ASSERT(FIELD_OFFSET(LANCE_INITIALIZATION_BLOCK,PhysicalAddress[0]) == 2);
|
||
#else
|
||
ASSERT(&((PLANCE_INITIALIZATION_BLOCK)0)->PhysicalAddress[0] == (PVOID)2);
|
||
#endif //NDIS_NT
|
||
|
||
//
|
||
// Allocate memory for all of the adapter structures.
|
||
//
|
||
|
||
Adapter->NumberOfTransmitRings = LANCE_NUMBER_OF_TRANSMIT_RINGS;
|
||
Adapter->LogNumberTransmitRings = LANCE_LOG_TRANSMIT_RINGS;
|
||
|
||
#ifndef i386
|
||
|
||
if (Adapter->LanceCard == LANCE_DECTC) {
|
||
|
||
Status = LanceDecTcSoftwareDetails(Adapter);
|
||
if (Status != NDIS_STATUS_SUCCESS) {
|
||
return Status;
|
||
}
|
||
|
||
} else
|
||
|
||
|
||
#endif
|
||
|
||
{
|
||
|
||
if (Adapter->AmountOfHardwareMemory == 0x20000) {
|
||
|
||
ASSERT(Adapter->LanceCard == LANCE_DE422);
|
||
|
||
Adapter->SizeOfReceiveBuffer = LANCE_128K_SIZE_OF_RECEIVE_BUFFERS;
|
||
Adapter->NumberOfSmallBuffers = LANCE_128K_NUMBER_OF_SMALL_BUFFERS;
|
||
Adapter->NumberOfMediumBuffers= LANCE_128K_NUMBER_OF_MEDIUM_BUFFERS;
|
||
Adapter->NumberOfLargeBuffers = LANCE_128K_NUMBER_OF_LARGE_BUFFERS;
|
||
|
||
Adapter->NumberOfReceiveRings = LANCE_128K_NUMBER_OF_RECEIVE_RINGS;
|
||
Adapter->LogNumberReceiveRings = LANCE_128K_LOG_RECEIVE_RINGS;
|
||
|
||
} else if (Adapter->AmountOfHardwareMemory == 0x10000) {
|
||
|
||
Adapter->NumberOfReceiveRings = LANCE_64K_NUMBER_OF_RECEIVE_RINGS;
|
||
Adapter->LogNumberReceiveRings = LANCE_64K_LOG_RECEIVE_RINGS;
|
||
|
||
Adapter->SizeOfReceiveBuffer = LANCE_64K_SIZE_OF_RECEIVE_BUFFERS;
|
||
Adapter->NumberOfSmallBuffers = LANCE_64K_NUMBER_OF_SMALL_BUFFERS;
|
||
Adapter->NumberOfMediumBuffers= LANCE_64K_NUMBER_OF_MEDIUM_BUFFERS;
|
||
Adapter->NumberOfLargeBuffers = LANCE_64K_NUMBER_OF_LARGE_BUFFERS;
|
||
|
||
} else {
|
||
|
||
Adapter->NumberOfReceiveRings = LANCE_32K_NUMBER_OF_RECEIVE_RINGS;
|
||
Adapter->LogNumberReceiveRings = LANCE_32K_LOG_RECEIVE_RINGS;
|
||
|
||
Adapter->SizeOfReceiveBuffer = LANCE_32K_SIZE_OF_RECEIVE_BUFFERS;
|
||
Adapter->NumberOfSmallBuffers = LANCE_32K_NUMBER_OF_SMALL_BUFFERS;
|
||
Adapter->NumberOfMediumBuffers= LANCE_32K_NUMBER_OF_MEDIUM_BUFFERS;
|
||
Adapter->NumberOfLargeBuffers = LANCE_32K_NUMBER_OF_LARGE_BUFFERS;
|
||
|
||
}
|
||
|
||
}
|
||
|
||
#ifndef i386
|
||
|
||
if (((Adapter->LanceCard == LANCE_DECTC) &&
|
||
(LanceDecTcHardwareDetails(Adapter) == NDIS_STATUS_SUCCESS)) ||
|
||
LanceHardwareDetails(Adapter))
|
||
|
||
#else
|
||
|
||
if (LanceHardwareDetails(Adapter))
|
||
|
||
#endif
|
||
{
|
||
NDIS_PHYSICAL_ADDRESS PhysicalAddress;
|
||
|
||
//
|
||
// Get hold of the RAP and RDP address as well
|
||
// as filling in the hardware assigned network
|
||
// address.
|
||
//
|
||
|
||
if ((Adapter->CurrentNetworkAddress[0] == 0x00) &&
|
||
(Adapter->CurrentNetworkAddress[1] == 0x00) &&
|
||
(Adapter->CurrentNetworkAddress[2] == 0x00) &&
|
||
(Adapter->CurrentNetworkAddress[3] == 0x00) &&
|
||
(Adapter->CurrentNetworkAddress[4] == 0x00) &&
|
||
(Adapter->CurrentNetworkAddress[5] == 0x00)) {
|
||
|
||
Adapter->CurrentNetworkAddress[0] = Adapter->NetworkAddress[0];
|
||
Adapter->CurrentNetworkAddress[1] = Adapter->NetworkAddress[1];
|
||
Adapter->CurrentNetworkAddress[2] = Adapter->NetworkAddress[2];
|
||
Adapter->CurrentNetworkAddress[3] = Adapter->NetworkAddress[3];
|
||
Adapter->CurrentNetworkAddress[4] = Adapter->NetworkAddress[4];
|
||
Adapter->CurrentNetworkAddress[5] = Adapter->NetworkAddress[5];
|
||
|
||
}
|
||
|
||
NdisSetPhysicalAddressHigh(PhysicalAddress, 0);
|
||
NdisSetPhysicalAddressLow(PhysicalAddress, (ULONG)(Adapter->HardwareBaseAddr));
|
||
|
||
Status = NdisMMapIoSpace(
|
||
&(Adapter->MmMappedBaseAddr),
|
||
Adapter->MiniportAdapterHandle,
|
||
PhysicalAddress,
|
||
Adapter->AmountOfHardwareMemory
|
||
);
|
||
|
||
if (Status != NDIS_STATUS_SUCCESS) {
|
||
|
||
NdisWriteErrorLogEntry(
|
||
Adapter->MiniportAdapterHandle,
|
||
NDIS_ERROR_CODE_RESOURCE_CONFLICT,
|
||
0
|
||
);
|
||
|
||
return(Status);
|
||
|
||
}
|
||
|
||
#if NDIS_WIN
|
||
|
||
//
|
||
// Save card setup information that is in card on-board memory
|
||
//
|
||
{
|
||
PUCHAR pTemp = (PUCHAR) (Adapter->MmMappedBaseAddr);
|
||
|
||
(UINT)pTemp &= 0xffff0000;
|
||
(UINT)pTemp |= 0x0000bffe;
|
||
|
||
NdisReadRegisterUshort((PUSHORT)pTemp, &(Adapter->SavedMemBase));
|
||
pTemp = (PUCHAR) (Adapter->MmMappedBaseAddr);
|
||
|
||
NdisReadRegisterUlong((PULONG)pTemp, &(Adapter->Reserved1));
|
||
NdisReadRegisterUlong((PULONG)pTemp, &(Adapter->Reserved2));
|
||
|
||
}
|
||
|
||
#endif
|
||
|
||
Adapter->CurrentMemoryFirstFree = Adapter->MmMappedBaseAddr;
|
||
|
||
|
||
Adapter->MemoryFirstUnavailable =
|
||
(PUCHAR)(Adapter->CurrentMemoryFirstFree) +
|
||
Adapter->AmountOfHardwareMemory;
|
||
|
||
if (!AllocateAdapterMemory(Adapter)) {
|
||
|
||
NdisWriteErrorLogEntry(
|
||
Adapter->MiniportAdapterHandle,
|
||
NDIS_ERROR_CODE_OUT_OF_RESOURCES,
|
||
0
|
||
);
|
||
|
||
return( NDIS_STATUS_ADAPTER_NOT_FOUND );
|
||
|
||
}
|
||
|
||
Adapter->AllocateableRing = Adapter->TransmitRing;
|
||
Adapter->TransmittingRing = Adapter->TransmitRing;
|
||
Adapter->FirstUncommittedRing = Adapter->TransmitRing;
|
||
Adapter->NumberOfAvailableRings = Adapter->NumberOfTransmitRings;
|
||
Adapter->LastTransmitRingEntry = Adapter->TransmitRing +
|
||
(Adapter->NumberOfTransmitRings-1);
|
||
|
||
Adapter->CurrentReceiveIndex = 0;
|
||
Adapter->OutOfReceiveBuffers = 0;
|
||
Adapter->CRCError = 0;
|
||
Adapter->FramingError = 0;
|
||
Adapter->RetryFailure = 0;
|
||
Adapter->LostCarrier = 0;
|
||
Adapter->LateCollision = 0;
|
||
Adapter->UnderFlow = 0;
|
||
Adapter->Deferred = 0;
|
||
Adapter->OneRetry = 0;
|
||
Adapter->MoreThanOneRetry = 0;
|
||
Adapter->ResetInProgress = FALSE;
|
||
Adapter->ResetInitStarted = FALSE;
|
||
Adapter->FirstInitialization = TRUE;
|
||
Adapter->HardwareFailure = FALSE;
|
||
|
||
//
|
||
// First we make sure that the device is stopped. We call
|
||
// directly since we don't have an Interrupt object yet.
|
||
//
|
||
|
||
LanceSyncStopChip(Adapter);
|
||
|
||
|
||
//
|
||
// Initialize the interrupt.
|
||
//
|
||
|
||
Status = NdisMRegisterInterrupt(
|
||
&Adapter->Interrupt,
|
||
Adapter->MiniportAdapterHandle,
|
||
Adapter->InterruptNumber,
|
||
Adapter->InterruptRequestLevel,
|
||
FALSE,
|
||
FALSE,
|
||
NdisInterruptLatched
|
||
);
|
||
|
||
if (Status != NDIS_STATUS_SUCCESS){
|
||
|
||
NdisWriteErrorLogEntry(
|
||
Adapter->MiniportAdapterHandle,
|
||
NDIS_ERROR_CODE_INTERRUPT_CONNECT,
|
||
0
|
||
);
|
||
|
||
NdisMUnmapIoSpace(
|
||
Adapter->MiniportAdapterHandle,
|
||
Adapter->MmMappedBaseAddr,
|
||
Adapter->AmountOfHardwareMemory
|
||
);
|
||
|
||
DeleteAdapterMemory(Adapter);
|
||
|
||
return Status;
|
||
}
|
||
|
||
if ((Status = LanceInitialInit(Adapter)) != NDIS_STATUS_SUCCESS) {
|
||
|
||
|
||
NdisWriteErrorLogEntry(
|
||
Adapter->MiniportAdapterHandle,
|
||
NDIS_ERROR_CODE_HARDWARE_FAILURE,
|
||
0
|
||
);
|
||
|
||
NdisMUnmapIoSpace(
|
||
Adapter->MiniportAdapterHandle,
|
||
Adapter->MmMappedBaseAddr,
|
||
Adapter->AmountOfHardwareMemory
|
||
);
|
||
|
||
DeleteAdapterMemory(Adapter);
|
||
|
||
NdisMDeregisterInterrupt(&Adapter->Interrupt);
|
||
|
||
}
|
||
|
||
NdisMInitializeTimer(
|
||
&Adapter->DeferredTimer,
|
||
Adapter->MiniportAdapterHandle,
|
||
LanceDeferredTimerRoutine,
|
||
(PVOID)Adapter
|
||
);
|
||
|
||
|
||
return Status;
|
||
|
||
} else {
|
||
|
||
NdisWriteErrorLogEntry(
|
||
Adapter->MiniportAdapterHandle,
|
||
NDIS_ERROR_CODE_ADAPTER_NOT_FOUND,
|
||
0
|
||
);
|
||
|
||
return NDIS_STATUS_FAILURE;
|
||
|
||
}
|
||
|
||
}
|
||
|
||
|
||
#pragma NDIS_INIT_FUNCTION(LanceInitialInit)
|
||
|
||
NDIS_STATUS
|
||
LanceInitialInit(
|
||
IN PLANCE_ADAPTER Adapter
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine sets up the initial init of the driver.
|
||
|
||
Arguments:
|
||
|
||
Adapter - The adapter for the hardware.
|
||
|
||
Return Value:
|
||
|
||
None.
|
||
|
||
--*/
|
||
|
||
{
|
||
if (Adapter->LanceCard & (LANCE_DE201 | LANCE_DE100 | LANCE_DE422))
|
||
{
|
||
//
|
||
// Allow interrupts
|
||
//
|
||
Adapter->InterruptsStopped = FALSE;
|
||
|
||
LOG(UNPEND);
|
||
|
||
LANCE_WRITE_NICSR(Adapter, LANCE_NICSR_INT_ON);
|
||
}
|
||
|
||
SetInitBlockAndInit(Adapter);
|
||
|
||
|
||
//
|
||
// The only way that first initialization could have
|
||
// been turned off is if we actually initialized.
|
||
//
|
||
if (!Adapter->FirstInitialization)
|
||
{
|
||
//
|
||
// We can start the chip. We may not
|
||
// have any bindings to indicateto but this
|
||
// is unimportant.
|
||
//
|
||
LanceStartChip(Adapter);
|
||
return NDIS_STATUS_SUCCESS;
|
||
}
|
||
else
|
||
{
|
||
return(NDIS_STATUS_FAILURE);
|
||
}
|
||
|
||
}
|
||
|
||
|
||
STATIC
|
||
VOID
|
||
LanceStartChip(
|
||
IN PLANCE_ADAPTER Adapter
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine is used to start an already initialized lance.
|
||
|
||
Arguments:
|
||
|
||
Adapter - The adapter for the LANCE to start.
|
||
|
||
Return Value:
|
||
|
||
None.
|
||
|
||
--*/
|
||
|
||
{
|
||
|
||
if (Adapter->ResetInProgress) {
|
||
|
||
return;
|
||
|
||
}
|
||
|
||
//
|
||
// Set the RAP to csr0.
|
||
//
|
||
|
||
LANCE_WRITE_RAP(
|
||
Adapter,
|
||
LANCE_SELECT_CSR0
|
||
);
|
||
|
||
//
|
||
// Set the RDP to a start chip.
|
||
//
|
||
|
||
LANCE_WRITE_RDP(
|
||
Adapter,
|
||
LANCE_CSR0_START | LANCE_CSR0_INTERRUPT_ENABLE
|
||
);
|
||
|
||
}
|
||
|
||
extern
|
||
VOID
|
||
LanceIsr(
|
||
OUT PBOOLEAN InterruptRecognized,
|
||
OUT PBOOLEAN QueueDpc,
|
||
IN PVOID Context
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Interrupt service routine for the lance.
|
||
|
||
Arguments:
|
||
|
||
Context - Really a pointer to the adapter.
|
||
|
||
Return Value:
|
||
|
||
None.
|
||
|
||
--*/
|
||
|
||
{
|
||
|
||
//
|
||
// Will hold the value from the csr.
|
||
//
|
||
USHORT LocalCSR0Value;
|
||
|
||
//
|
||
// Holds the pointer to the adapter.
|
||
//
|
||
PLANCE_ADAPTER Adapter = Context;
|
||
|
||
BOOLEAN StoppedInterrupts=FALSE;
|
||
|
||
LOG(IN_ISR);
|
||
|
||
*QueueDpc = FALSE;
|
||
*InterruptRecognized = FALSE;
|
||
|
||
if ((Adapter->LanceCard & (LANCE_DE201 | LANCE_DE100 | LANCE_DE422)) &&
|
||
!Adapter->InterruptsStopped
|
||
)
|
||
{
|
||
//
|
||
// Pend interrupts
|
||
//
|
||
StoppedInterrupts = TRUE;
|
||
Adapter->InterruptsStopped = TRUE;
|
||
|
||
LOG(PEND);
|
||
|
||
LANCE_ISR_WRITE_NICSR(
|
||
Adapter,
|
||
LANCE_NICSR_IMASK | LANCE_NICSR_LED_ON | LANCE_NICSR_INT_ON
|
||
);
|
||
}
|
||
|
||
//
|
||
// We don't need to select csr0, as the only way we could get
|
||
// an interrupt is to have already selected 0.
|
||
//
|
||
LANCE_ISR_READ_RDP(Adapter, &LocalCSR0Value);
|
||
if (LocalCSR0Value & LANCE_CSR0_INTERRUPT_FLAG)
|
||
{
|
||
*InterruptRecognized = TRUE;
|
||
|
||
//
|
||
// It's our interrupt. Clear only those bits that we got
|
||
// in this read of csr0. We do it this way incase any new
|
||
// reasons for interrupts occur between the time that we
|
||
// read csr0 and the time that we clear the bits.
|
||
//
|
||
LANCE_ISR_WRITE_RDP(
|
||
Adapter,
|
||
(USHORT)((LANCE_CSR0_CLEAR_INTERRUPT_BITS & LocalCSR0Value) |
|
||
LANCE_CSR0_INTERRUPT_ENABLE)
|
||
);
|
||
if (Adapter->FirstInitialization &&
|
||
(LocalCSR0Value & LANCE_CSR0_INITIALIZATION_DONE)
|
||
)
|
||
{
|
||
Adapter->FirstInitialization = FALSE;
|
||
}
|
||
}
|
||
|
||
//
|
||
// Enable the interrupts.
|
||
//
|
||
if ((Adapter->LanceCard & (LANCE_DE201 | LANCE_DE100 | LANCE_DE422)) &&
|
||
StoppedInterrupts
|
||
)
|
||
{
|
||
//
|
||
// Allow interrupts
|
||
//
|
||
Adapter->InterruptsStopped = FALSE;
|
||
|
||
LOG(UNPEND);
|
||
|
||
LANCE_ISR_WRITE_NICSR(Adapter, LANCE_NICSR_INT_ON);
|
||
}
|
||
|
||
LOG(OUT_ISR);
|
||
|
||
return;
|
||
}
|
||
STATIC
|
||
VOID
|
||
LanceDisableInterrupt(
|
||
IN NDIS_HANDLE MiniportAdapterContext
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine disables interrupts on the adapter.
|
||
|
||
Arguments:
|
||
|
||
Context - Really a pointer to the adapter.
|
||
|
||
Return Value:
|
||
|
||
None.
|
||
|
||
--*/
|
||
|
||
{
|
||
PLANCE_ADAPTER Adapter = (PLANCE_ADAPTER)MiniportAdapterContext;
|
||
|
||
//
|
||
// Pend any interrupts
|
||
//
|
||
ASSERT(Adapter->LanceCard & (LANCE_DE201 | LANCE_DE100 | LANCE_DE422));
|
||
|
||
LOG(PEND);
|
||
|
||
LANCE_ISR_WRITE_NICSR(
|
||
Adapter,
|
||
LANCE_NICSR_IMASK | LANCE_NICSR_LED_ON | LANCE_NICSR_INT_ON
|
||
);
|
||
}
|
||
|
||
|
||
STATIC
|
||
VOID
|
||
LanceEnableInterrupt(
|
||
IN NDIS_HANDLE MiniportAdapterContext
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine enables interrupts on the adapter.
|
||
|
||
Arguments:
|
||
|
||
Context - Really a pointer to the adapter.
|
||
|
||
Return Value:
|
||
|
||
None.
|
||
|
||
--*/
|
||
{
|
||
PLANCE_ADAPTER Adapter = (PLANCE_ADAPTER)MiniportAdapterContext;
|
||
|
||
ASSERT(Adapter->LanceCard & (LANCE_DE201 | LANCE_DE100 | LANCE_DE422));
|
||
|
||
//
|
||
// Allow interrupts
|
||
//
|
||
|
||
LOG(UNPEND);
|
||
|
||
LANCE_ISR_WRITE_NICSR(Adapter, LANCE_NICSR_INT_ON);
|
||
}
|
||
VOID
|
||
LanceDeferredTimerRoutine(
|
||
IN PVOID SystemSpecific1,
|
||
IN NDIS_HANDLE Context,
|
||
IN PVOID SystemSpecific2,
|
||
IN PVOID SystemSpecific3
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This DPC routine is used to handle deferred processing via a timer.
|
||
|
||
Arguments:
|
||
|
||
Context - Really a pointer to the adapter.
|
||
|
||
Return Value:
|
||
|
||
None.
|
||
|
||
--*/
|
||
|
||
{
|
||
LanceHandleInterrupt(Context);
|
||
}
|
||
|
||
VOID
|
||
LanceHandleInterrupt(
|
||
IN NDIS_HANDLE Context
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This DPC routine is queued by the interrupt service routine.
|
||
|
||
Arguments:
|
||
|
||
Context - Really a pointer to the adapter.
|
||
|
||
Return Value:
|
||
|
||
None.
|
||
|
||
--*/
|
||
|
||
{
|
||
//
|
||
// Holds the pointer to the adapter.
|
||
//
|
||
PLANCE_ADAPTER Adapter = Context;
|
||
|
||
//
|
||
// Holds a value of csr0.
|
||
//
|
||
USHORT Csr = 0;
|
||
USHORT LocalCSR0Value;
|
||
|
||
LOG(IN_DPC);
|
||
|
||
//
|
||
// Loop until there are no more processing sources.
|
||
//
|
||
for (;;)
|
||
{
|
||
//
|
||
// We don't need to select csr0, as the only way we could get
|
||
// an interrupt is to have already selected 0.
|
||
//
|
||
LANCE_ISR_READ_RDP(Adapter, &LocalCSR0Value);
|
||
|
||
if (LocalCSR0Value & LANCE_CSR0_INTERRUPT_FLAG)
|
||
{
|
||
//
|
||
// It's our interrupt. Clear only those bits that we got
|
||
// in this read of csr0. We do it this way incase any new
|
||
// reasons for interrupts occur between the time that we
|
||
// read csr0 and the time that we clear the bits.
|
||
//
|
||
LANCE_ISR_WRITE_RDP(
|
||
Adapter,
|
||
(USHORT)((LANCE_CSR0_CLEAR_INTERRUPT_BITS & LocalCSR0Value) |
|
||
LANCE_CSR0_INTERRUPT_ENABLE)
|
||
);
|
||
|
||
//
|
||
// Or the csr value into the adapter version of csr 0.
|
||
//
|
||
Csr |= LocalCSR0Value;
|
||
}
|
||
|
||
//
|
||
// Check the interrupt source and other reasons
|
||
// for processing. If there are no reasons to
|
||
// process then exit this loop.
|
||
//
|
||
if (((!Adapter->ResetInitStarted) &&
|
||
((Csr & (LANCE_CSR0_MEMORY_ERROR |
|
||
LANCE_CSR0_MISSED_PACKET |
|
||
LANCE_CSR0_BABBLE |
|
||
LANCE_CSR0_RECEIVER_INTERRUPT |
|
||
LANCE_CSR0_TRANSMITTER_INTERRUPT)) ||
|
||
(Adapter->ResetInProgress))) ||
|
||
(Csr & LANCE_CSR0_INITIALIZATION_DONE)
|
||
)
|
||
{
|
||
|
||
}
|
||
else
|
||
{
|
||
break;
|
||
}
|
||
|
||
//
|
||
// Check for initialization.
|
||
//
|
||
// Note that we come out of the synchronization above holding
|
||
// the spinlock.
|
||
//
|
||
if (Csr & LANCE_CSR0_INITIALIZATION_DONE)
|
||
{
|
||
//
|
||
// Possibly undefined reason why the reset was requested.
|
||
//
|
||
// It is undefined if the adapter initiated the reset
|
||
// request on its own. It could do that if there
|
||
// were some sort of error.
|
||
//
|
||
NDIS_REQUEST_TYPE ResetRequestType;
|
||
|
||
LOG(RESET_STEP_3);
|
||
|
||
ASSERT(!Adapter->FirstInitialization);
|
||
|
||
Csr &= ~LANCE_CSR0_INITIALIZATION_DONE;
|
||
|
||
Adapter->ResetInProgress = FALSE;
|
||
Adapter->ResetInitStarted = FALSE;
|
||
|
||
//
|
||
// We save off the open that caused this reset incase
|
||
// we get *another* reset while we're indicating the
|
||
// last reset is done.
|
||
//
|
||
ResetRequestType = Adapter->ResetRequestType;
|
||
|
||
if (ResetRequestType == NdisRequestSetInformation)
|
||
{
|
||
//
|
||
// It was a request submitted by a protocol.
|
||
//
|
||
NdisMSetInformationComplete(
|
||
Adapter->MiniportAdapterHandle,
|
||
NDIS_STATUS_SUCCESS
|
||
);
|
||
}
|
||
else
|
||
{
|
||
//
|
||
// It was a reset command.
|
||
//
|
||
if (ResetRequestType == NdisRequestGeneric1)
|
||
{
|
||
//
|
||
// Is was a reset request
|
||
//
|
||
NdisMResetComplete(
|
||
Adapter->MiniportAdapterHandle,
|
||
NDIS_STATUS_SUCCESS,
|
||
FALSE
|
||
);
|
||
}
|
||
}
|
||
|
||
//
|
||
// Restart the chip.
|
||
//
|
||
LanceStartChip(Adapter);
|
||
|
||
goto LoopBottom;
|
||
}
|
||
|
||
//
|
||
// If we have a reset in progress and the adapters reference
|
||
// count is 1 (meaning no routine is in the interface and
|
||
// we are the only "active" interrupt processing routine) then
|
||
// it is safe to start the reset.
|
||
//
|
||
if (Adapter->ResetInProgress &&
|
||
!Adapter->ResetInitStarted
|
||
)
|
||
{
|
||
#if LANCE_TRACE
|
||
DbgPrint("Starting Initialization.\n");
|
||
#endif
|
||
StartAdapterReset(Adapter);
|
||
|
||
Adapter->ResetInitStarted = TRUE;
|
||
goto LoopBottom;
|
||
}
|
||
|
||
//
|
||
// Check for non-packet related errors.
|
||
//
|
||
if (Csr & (LANCE_CSR0_MEMORY_ERROR |
|
||
LANCE_CSR0_MISSED_PACKET |
|
||
LANCE_CSR0_BABBLE)
|
||
)
|
||
{
|
||
if (Csr & LANCE_CSR0_MISSED_PACKET)
|
||
{
|
||
Adapter->MissedPacket++;
|
||
}
|
||
else if (Csr & LANCE_CSR0_BABBLE)
|
||
{
|
||
//
|
||
// A babble error implies that we've sent a
|
||
// packet that is greater than the ethernet length.
|
||
// This implies that the driver is broken.
|
||
//
|
||
Adapter->Babble++;
|
||
|
||
NdisWriteErrorLogEntry(
|
||
Adapter->MiniportAdapterHandle,
|
||
NDIS_ERROR_CODE_DRIVER_FAILURE,
|
||
2,
|
||
(ULONG)processInterrupt,
|
||
(ULONG)0x1
|
||
);
|
||
}
|
||
else
|
||
{
|
||
//
|
||
// Could only be a memory error. This shuts down
|
||
// the receiver and the transmitter. We have to
|
||
// reset to get the device started again.
|
||
//
|
||
Adapter->MemoryError++;
|
||
|
||
SetupForReset(
|
||
Adapter,
|
||
NdisRequestGeneric4 // Means MAC issued
|
||
);
|
||
}
|
||
|
||
Csr &= ~LANCE_CSR0_ERROR_BITS;
|
||
}
|
||
|
||
//
|
||
// Check the interrupt vector and see if there are any
|
||
// more receives to process. After we process any
|
||
// other interrupt source we always come back to the top
|
||
// of the loop to check if any more receive packets have
|
||
// come in. This is to lessen the probability that we
|
||
// drop a receive.
|
||
//
|
||
if (Csr & LANCE_CSR0_RECEIVER_INTERRUPT)
|
||
{
|
||
if (ProcessReceiveInterrupts(Adapter))
|
||
{
|
||
Csr &= ~LANCE_CSR0_RECEIVER_INTERRUPT;
|
||
}
|
||
}
|
||
|
||
//
|
||
// Process the transmit interrupts if there are any.
|
||
//
|
||
if (Csr & LANCE_CSR0_TRANSMITTER_INTERRUPT)
|
||
{
|
||
//
|
||
// We need to check if the transmitter has
|
||
// stopped as a result of an error. If it
|
||
// has then we really need to reset the adapter.
|
||
//
|
||
if (!(Csr & LANCE_CSR0_TRANSMITTER_ON))
|
||
{
|
||
//
|
||
// Might as well turn off the transmitter interrupt
|
||
// source since we won't ever be processing them
|
||
// and we don't want to come back here again.
|
||
//
|
||
Csr &= ~LANCE_CSR0_TRANSMITTER_INTERRUPT;
|
||
|
||
//
|
||
// Before we setup for the reset make sure that
|
||
// we aren't already resetting.
|
||
//
|
||
if (!Adapter->ResetInProgress)
|
||
{
|
||
SetupForReset(
|
||
Adapter,
|
||
NdisRequestGeneric4 // means MAC issued
|
||
);
|
||
}
|
||
|
||
goto LoopBottom;
|
||
}
|
||
else
|
||
{
|
||
if (!ProcessTransmitInterrupts(Adapter))
|
||
{
|
||
//
|
||
// Process interrupts returns false if it
|
||
// finds no more work to do. If this so we
|
||
// turn off the transmitter interrupt source.
|
||
//
|
||
Csr &= ~LANCE_CSR0_TRANSMITTER_INTERRUPT;
|
||
}
|
||
}
|
||
}
|
||
|
||
LoopBottom:;
|
||
|
||
}
|
||
|
||
//
|
||
// Check if we indicated any packets.
|
||
//
|
||
// Note: The only way to get out of the loop (via the break above) is
|
||
// while we're still holding the spin lock.
|
||
//
|
||
if (Adapter->IndicatedAPacket)
|
||
{
|
||
Adapter->IndicatedAPacket = FALSE;
|
||
|
||
NdisMEthIndicateReceiveComplete(Adapter->MiniportAdapterHandle);
|
||
}
|
||
|
||
LOG(OUT_DPC);
|
||
}
|
||
|
||
#pragma NDIS_INIT_FUNCTION(AllocateAdapterMemory)
|
||
|
||
BOOLEAN
|
||
AllocateAdapterMemory(
|
||
IN PLANCE_ADAPTER Adapter
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine allocates memory for:
|
||
|
||
- Transmit ring entries
|
||
|
||
- Receive ring entries
|
||
|
||
- Receive buffers
|
||
|
||
- Adapter buffers for use if user transmit buffers don't meet hardware
|
||
contraints
|
||
|
||
- Structures to map transmit ring entries back to the packets.
|
||
|
||
Arguments:
|
||
|
||
Adapter - The adapter to allocate memory for.
|
||
|
||
Return Value:
|
||
|
||
Returns FALSE if some memory needed for the adapter could not
|
||
be allocated.
|
||
|
||
--*/
|
||
|
||
{
|
||
|
||
//
|
||
// Pointer to a transmit ring entry. Used while initializing
|
||
// the ring.
|
||
//
|
||
PLANCE_TRANSMIT_ENTRY CurrentTransmitEntry;
|
||
|
||
//
|
||
// Pointer to a receive ring entry. Used while initializing
|
||
// the ring.
|
||
//
|
||
PLANCE_RECEIVE_ENTRY CurrentReceiveEntry;
|
||
|
||
//
|
||
// Simple iteration variable.
|
||
//
|
||
UINT i;
|
||
|
||
//
|
||
// These variables exist to reduce the amount of checking below.
|
||
//
|
||
|
||
ULONG NumberOfSmallBuffers;
|
||
ULONG NumberOfMediumBuffers;
|
||
ULONG NumberOfLargeBuffers;
|
||
|
||
|
||
NumberOfSmallBuffers = Adapter->NumberOfSmallBuffers;
|
||
NumberOfMediumBuffers = Adapter->NumberOfMediumBuffers;
|
||
NumberOfLargeBuffers = Adapter->NumberOfLargeBuffers;
|
||
|
||
|
||
|
||
//
|
||
// Allocate memory for the initialization block. Note that
|
||
// this memory can not cross a page boundary.
|
||
//
|
||
|
||
LANCE_ALLOCATE_MEMORY_FOR_HARDWARE(
|
||
Adapter,
|
||
sizeof(LANCE_INITIALIZATION_BLOCK),
|
||
&Adapter->InitBlock
|
||
);
|
||
|
||
if (Adapter->InitBlock == NULL) {
|
||
DeleteAdapterMemory(Adapter);
|
||
return FALSE;
|
||
}
|
||
|
||
//
|
||
// Allocate the transmit ring descriptors.
|
||
//
|
||
|
||
LANCE_ALLOCATE_MEMORY_FOR_HARDWARE(
|
||
Adapter,
|
||
sizeof(LANCE_TRANSMIT_ENTRY)*Adapter->NumberOfTransmitRings,
|
||
&Adapter->TransmitRing
|
||
)
|
||
|
||
if (Adapter->TransmitRing == NULL) {
|
||
DeleteAdapterMemory(Adapter);
|
||
return FALSE;
|
||
}
|
||
|
||
//
|
||
// We have the transmit ring descriptors. Make sure each is
|
||
// in a clean state.
|
||
//
|
||
|
||
for (
|
||
i = 0, CurrentTransmitEntry = Adapter->TransmitRing;
|
||
i < Adapter->NumberOfTransmitRings;
|
||
i++,CurrentTransmitEntry++
|
||
) {
|
||
|
||
LANCE_ZERO_MEMORY_FOR_HARDWARE(
|
||
(PUCHAR)CurrentTransmitEntry,
|
||
sizeof(LANCE_TRANSMIT_ENTRY)
|
||
);
|
||
|
||
}
|
||
|
||
|
||
//
|
||
// Allocate all of the receive ring entries
|
||
//
|
||
|
||
LANCE_ALLOCATE_MEMORY_FOR_HARDWARE(
|
||
Adapter,
|
||
sizeof(LANCE_RECEIVE_ENTRY)*Adapter->NumberOfReceiveRings,
|
||
&Adapter->ReceiveRing
|
||
)
|
||
|
||
if (Adapter->ReceiveRing == NULL) {
|
||
DeleteAdapterMemory(Adapter);
|
||
return FALSE;
|
||
}
|
||
|
||
//
|
||
// We have the receive ring descriptors. Allocate an
|
||
// array to hold the virtual addresses of each receive
|
||
// buffer.
|
||
//
|
||
|
||
LANCE_ALLOC_PHYS(
|
||
&(Adapter->ReceiveVAs),
|
||
sizeof(PVOID) * Adapter->NumberOfReceiveRings
|
||
);
|
||
|
||
if (Adapter->ReceiveVAs == NULL) {
|
||
DeleteAdapterMemory(Adapter);
|
||
return FALSE;
|
||
}
|
||
|
||
//
|
||
// Clean the above memory
|
||
//
|
||
|
||
LANCE_ZERO_MEMORY(
|
||
Adapter->ReceiveVAs,
|
||
(sizeof(PVOID)*Adapter->NumberOfReceiveRings)
|
||
);
|
||
|
||
|
||
//
|
||
// We have the receive ring descriptors. Allocate a buffer
|
||
// for each descriptor and make sure descriptor is in a clean state.
|
||
//
|
||
// While we're at it, relinquish ownership of the ring discriptors to
|
||
// the lance.
|
||
//
|
||
|
||
for (
|
||
i = 0, CurrentReceiveEntry = Adapter->ReceiveRing;
|
||
i < Adapter->NumberOfReceiveRings;
|
||
i++,CurrentReceiveEntry++
|
||
) {
|
||
|
||
LANCE_ALLOCATE_MEMORY_FOR_HARDWARE(
|
||
Adapter,
|
||
Adapter->SizeOfReceiveBuffer,
|
||
&Adapter->ReceiveVAs[i]
|
||
);
|
||
|
||
if (Adapter->ReceiveVAs[i] == NULL) {
|
||
DeleteAdapterMemory(Adapter);
|
||
return FALSE;
|
||
}
|
||
|
||
|
||
LANCE_SET_RECEIVE_BUFFER_ADDRESS(
|
||
Adapter,
|
||
CurrentReceiveEntry,
|
||
Adapter->ReceiveVAs[i]
|
||
);
|
||
|
||
|
||
LANCE_SET_RECEIVE_BUFFER_LENGTH(
|
||
CurrentReceiveEntry,
|
||
Adapter->SizeOfReceiveBuffer
|
||
);
|
||
|
||
LANCE_WRITE_HARDWARE_MEMORY_UCHAR(
|
||
CurrentReceiveEntry->ReceiveSummaryBits,
|
||
LANCE_RECEIVE_OWNED_BY_CHIP
|
||
);
|
||
|
||
}
|
||
|
||
//
|
||
// Allocate the ring to packet structure.
|
||
//
|
||
|
||
LANCE_ALLOC_PHYS(
|
||
&(Adapter->RingToPacket),
|
||
sizeof(LANCE_RING_TO_PACKET) * Adapter->NumberOfTransmitRings
|
||
);
|
||
|
||
if (Adapter->RingToPacket == NULL) {
|
||
DeleteAdapterMemory(Adapter);
|
||
return FALSE;
|
||
}
|
||
|
||
LANCE_ZERO_MEMORY(
|
||
Adapter->RingToPacket,
|
||
sizeof(LANCE_RING_TO_PACKET) * Adapter->NumberOfTransmitRings
|
||
);
|
||
|
||
//
|
||
// Allocate the array of buffer descriptors.
|
||
//
|
||
|
||
LANCE_ALLOC_PHYS(
|
||
&(Adapter->LanceBuffers),
|
||
sizeof(LANCE_BUFFER_DESCRIPTOR) *
|
||
(NumberOfSmallBuffers +
|
||
NumberOfMediumBuffers +
|
||
NumberOfLargeBuffers)
|
||
);
|
||
|
||
if (Adapter->LanceBuffers == NULL) {
|
||
DeleteAdapterMemory(Adapter);
|
||
return FALSE;
|
||
}
|
||
|
||
//
|
||
// Zero the memory of all the descriptors so that we can
|
||
// know which buffers wern't allocated incase we can't allocate
|
||
// them all.
|
||
//
|
||
LANCE_ZERO_MEMORY(
|
||
Adapter->LanceBuffers,
|
||
sizeof(LANCE_BUFFER_DESCRIPTOR)*
|
||
(NumberOfSmallBuffers +
|
||
NumberOfMediumBuffers +
|
||
NumberOfLargeBuffers)
|
||
);
|
||
|
||
//
|
||
// Allocate each of the small lance buffers and fill in the
|
||
// buffer descriptor.
|
||
//
|
||
|
||
Adapter->LanceBufferListHeads[0] = -1;
|
||
Adapter->LanceBufferListHeads[1] = 0;
|
||
|
||
for (
|
||
i = 0;
|
||
i < NumberOfSmallBuffers;
|
||
i++
|
||
) {
|
||
|
||
LANCE_ALLOCATE_MEMORY_FOR_HARDWARE(
|
||
Adapter,
|
||
LANCE_SMALL_BUFFER_SIZE,
|
||
&Adapter->LanceBuffers[i].VirtualLanceBuffer
|
||
);
|
||
|
||
if (Adapter->LanceBuffers[i].VirtualLanceBuffer == NULL) {
|
||
DeleteAdapterMemory(Adapter);
|
||
return FALSE;
|
||
}
|
||
|
||
Adapter->LanceBuffers[i].Next = i+1;
|
||
Adapter->LanceBuffers[i].BufferSize = LANCE_SMALL_BUFFER_SIZE;
|
||
|
||
}
|
||
|
||
//
|
||
// Make sure that the last buffer correctly terminates the free list.
|
||
//
|
||
|
||
Adapter->LanceBuffers[i-1].Next = -1;
|
||
|
||
//
|
||
// Do the medium buffers now.
|
||
//
|
||
|
||
Adapter->LanceBufferListHeads[2] = i;
|
||
|
||
for (
|
||
;
|
||
i < NumberOfSmallBuffers + NumberOfMediumBuffers;
|
||
i++
|
||
) {
|
||
|
||
LANCE_ALLOCATE_MEMORY_FOR_HARDWARE(
|
||
Adapter,
|
||
LANCE_MEDIUM_BUFFER_SIZE,
|
||
&Adapter->LanceBuffers[i].VirtualLanceBuffer
|
||
);
|
||
|
||
if (Adapter->LanceBuffers[i].VirtualLanceBuffer == NULL) {
|
||
DeleteAdapterMemory(Adapter);
|
||
return FALSE;
|
||
}
|
||
|
||
|
||
Adapter->LanceBuffers[i].Next = i+1;
|
||
Adapter->LanceBuffers[i].BufferSize = LANCE_MEDIUM_BUFFER_SIZE;
|
||
|
||
}
|
||
|
||
//
|
||
// Make sure that the last buffer correctly terminates the free list.
|
||
//
|
||
|
||
Adapter->LanceBuffers[i-1].Next = -1;
|
||
|
||
|
||
Adapter->LanceBufferListHeads[3] = i;
|
||
|
||
for (
|
||
;
|
||
i < NumberOfSmallBuffers + NumberOfMediumBuffers + NumberOfLargeBuffers;
|
||
i++
|
||
) {
|
||
|
||
|
||
LANCE_ALLOCATE_MEMORY_FOR_HARDWARE(
|
||
Adapter,
|
||
LANCE_LARGE_BUFFER_SIZE,
|
||
&Adapter->LanceBuffers[i].VirtualLanceBuffer
|
||
);
|
||
|
||
if (Adapter->LanceBuffers[i].VirtualLanceBuffer == NULL) {
|
||
DeleteAdapterMemory(Adapter);
|
||
return FALSE;
|
||
}
|
||
|
||
|
||
Adapter->LanceBuffers[i].Next = i+1;
|
||
Adapter->LanceBuffers[i].BufferSize = LANCE_LARGE_BUFFER_SIZE;
|
||
|
||
}
|
||
|
||
//
|
||
// Make sure that the last buffer correctly terminates the free list.
|
||
//
|
||
|
||
Adapter->LanceBuffers[i-1].Next = -1;
|
||
|
||
return TRUE;
|
||
|
||
}
|
||
|
||
|
||
STATIC
|
||
VOID
|
||
DeleteAdapterMemory(
|
||
IN PLANCE_ADAPTER Adapter
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine deallocates memory for:
|
||
|
||
- Transmit ring entries
|
||
|
||
- Receive ring entries
|
||
|
||
- Receive buffers
|
||
|
||
- Adapter buffers for use if user transmit buffers don't meet hardware
|
||
contraints
|
||
|
||
- Structures to map transmit ring entries back to the packets.
|
||
|
||
Arguments:
|
||
|
||
Adapter - The adapter to deallocate memory for.
|
||
|
||
Return Value:
|
||
|
||
None.
|
||
|
||
--*/
|
||
|
||
{
|
||
|
||
//
|
||
// These variables exist to reduce the amount of checking below.
|
||
//
|
||
|
||
ULONG NumberOfSmallBuffers;
|
||
ULONG NumberOfMediumBuffers;
|
||
ULONG NumberOfLargeBuffers;
|
||
|
||
NumberOfSmallBuffers = Adapter->NumberOfSmallBuffers;
|
||
NumberOfMediumBuffers = Adapter->NumberOfMediumBuffers;
|
||
NumberOfLargeBuffers = Adapter->NumberOfLargeBuffers;
|
||
|
||
|
||
if (Adapter->InitBlock) {
|
||
|
||
LANCE_DEALLOCATE_MEMORY_FOR_HARDWARE(
|
||
Adapter,
|
||
Adapter->InitBlock
|
||
);
|
||
|
||
}
|
||
|
||
if (Adapter->TransmitRing) {
|
||
|
||
LANCE_DEALLOCATE_MEMORY_FOR_HARDWARE(
|
||
Adapter,
|
||
Adapter->TransmitRing
|
||
);
|
||
|
||
}
|
||
|
||
if (Adapter->ReceiveRing) {
|
||
|
||
LANCE_DEALLOCATE_MEMORY_FOR_HARDWARE(
|
||
Adapter,
|
||
Adapter->ReceiveRing
|
||
);
|
||
|
||
}
|
||
|
||
if (Adapter->ReceiveVAs) {
|
||
|
||
UINT i;
|
||
|
||
for (
|
||
i = 0;
|
||
i < Adapter->NumberOfReceiveRings;
|
||
i++
|
||
) {
|
||
|
||
if (Adapter->ReceiveVAs[i]) {
|
||
|
||
LANCE_DEALLOCATE_MEMORY_FOR_HARDWARE(
|
||
Adapter,
|
||
Adapter->ReceiveVAs[i]
|
||
);
|
||
|
||
} else {
|
||
|
||
break;
|
||
|
||
}
|
||
|
||
}
|
||
|
||
LANCE_FREE_PHYS(
|
||
Adapter->ReceiveVAs,
|
||
sizeof(PVOID) * Adapter->NumberOfReceiveRings
|
||
);
|
||
|
||
}
|
||
|
||
if (Adapter->RingToPacket) {
|
||
|
||
LANCE_FREE_PHYS(
|
||
Adapter->RingToPacket,
|
||
sizeof(LANCE_RING_TO_PACKET) * Adapter->NumberOfTransmitRings
|
||
);
|
||
|
||
}
|
||
|
||
if (Adapter->LanceBuffers) {
|
||
|
||
UINT i;
|
||
|
||
for (
|
||
i = 0;
|
||
i < NumberOfSmallBuffers + NumberOfMediumBuffers + NumberOfLargeBuffers;
|
||
i++) {
|
||
|
||
if (Adapter->LanceBuffers[i].VirtualLanceBuffer) {
|
||
|
||
LANCE_DEALLOCATE_MEMORY_FOR_HARDWARE(
|
||
Adapter,
|
||
Adapter->LanceBuffers[i].VirtualLanceBuffer
|
||
);
|
||
|
||
} else {
|
||
|
||
break;
|
||
|
||
}
|
||
|
||
}
|
||
|
||
LANCE_FREE_PHYS(
|
||
Adapter->LanceBuffers,
|
||
sizeof(LANCE_BUFFER_DESCRIPTOR) *
|
||
(NumberOfSmallBuffers +
|
||
NumberOfMediumBuffers +
|
||
NumberOfLargeBuffers)
|
||
);
|
||
|
||
}
|
||
|
||
}
|
||
|
||
|
||
NDIS_STATUS
|
||
LanceQueryInformation(
|
||
IN PNDIS_HANDLE MiniportAdapterContext,
|
||
IN NDIS_OID Oid,
|
||
IN PVOID InfoBuffer,
|
||
IN ULONG BytesLeft,
|
||
OUT PULONG BytesWritten,
|
||
OUT PULONG BytesNeeded
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
The LanceQuerylInformation process a Query request for
|
||
NDIS_OIDs that are specific to a binding about the mini-port.
|
||
|
||
Arguments:
|
||
|
||
Status - The status of the operation.
|
||
|
||
MiniportAdapterContext - a pointer to the adapter.
|
||
|
||
Oid - the NDIS_OID to process.
|
||
|
||
InfoBuffer - 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:
|
||
|
||
None.
|
||
|
||
--*/
|
||
|
||
{
|
||
PLANCE_ADAPTER Adapter = (PLANCE_ADAPTER)MiniportAdapterContext;
|
||
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;
|
||
ULONG MoveBytes;
|
||
|
||
NDIS_HARDWARE_STATUS HardwareStatus = NdisHardwareStatusReady;
|
||
|
||
//
|
||
// Make sure that ulong is 4 bytes. Else GenericULong must change
|
||
// to something of size 4.
|
||
//
|
||
ASSERT(sizeof(ULONG) == 4);
|
||
|
||
|
||
#if LANCE_TRACE
|
||
DbgPrint("In LanceQueryInfo\n");
|
||
#endif
|
||
|
||
//
|
||
// Set default values
|
||
//
|
||
|
||
MoveSource = (PVOID)(&GenericULong);
|
||
MoveBytes = sizeof(GenericULong);
|
||
|
||
//
|
||
// 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:
|
||
|
||
MoveSource = (PVOID)(LanceGlobalSupportedOids);
|
||
MoveBytes = sizeof(LanceGlobalSupportedOids);
|
||
break;
|
||
|
||
case OID_GEN_HARDWARE_STATUS:
|
||
|
||
|
||
if (Adapter->ResetInProgress){
|
||
|
||
HardwareStatus = NdisHardwareStatusReset;
|
||
|
||
} else {
|
||
|
||
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 = LANCE_MAX_LOOKAHEAD;
|
||
|
||
break;
|
||
|
||
|
||
case OID_GEN_MAXIMUM_FRAME_SIZE:
|
||
|
||
GenericULong = (ULONG)(LANCE_LARGE_BUFFER_SIZE - LANCE_HEADER_SIZE);
|
||
|
||
break;
|
||
|
||
|
||
case OID_GEN_MAXIMUM_TOTAL_SIZE:
|
||
|
||
GenericULong = (ULONG)(LANCE_LARGE_BUFFER_SIZE);
|
||
|
||
break;
|
||
|
||
|
||
case OID_GEN_LINK_SPEED:
|
||
|
||
GenericULong = (ULONG)(100000);
|
||
|
||
break;
|
||
|
||
|
||
case OID_GEN_TRANSMIT_BUFFER_SPACE:
|
||
|
||
GenericULong = (ULONG)((LANCE_SMALL_BUFFER_SIZE * Adapter->NumberOfSmallBuffers) +
|
||
(LANCE_MEDIUM_BUFFER_SIZE * Adapter->NumberOfMediumBuffers) +
|
||
(LANCE_LARGE_BUFFER_SIZE * Adapter->NumberOfLargeBuffers));
|
||
|
||
|
||
break;
|
||
|
||
case OID_GEN_RECEIVE_BUFFER_SPACE:
|
||
|
||
GenericULong = (ULONG)(Adapter->NumberOfReceiveRings *
|
||
Adapter->SizeOfReceiveBuffer);
|
||
|
||
break;
|
||
|
||
case OID_GEN_TRANSMIT_BLOCK_SIZE:
|
||
|
||
GenericULong = (ULONG)(LANCE_SMALL_BUFFER_SIZE);
|
||
|
||
break;
|
||
|
||
case OID_GEN_RECEIVE_BLOCK_SIZE:
|
||
|
||
GenericULong = (ULONG)(Adapter->SizeOfReceiveBuffer);
|
||
|
||
break;
|
||
|
||
case OID_GEN_VENDOR_ID:
|
||
|
||
NdisMoveMemory(
|
||
(PVOID)(&GenericULong),
|
||
Adapter->NetworkAddress,
|
||
3
|
||
);
|
||
|
||
GenericULong &= 0xFFFFFF00;
|
||
|
||
if (Adapter->LanceCard == LANCE_DE201) {
|
||
|
||
GenericULong |= 0x01;
|
||
|
||
} else if (Adapter->LanceCard == LANCE_DE100) {
|
||
|
||
GenericULong |= 0x02;
|
||
|
||
} else if (Adapter->LanceCard == LANCE_DE422) {
|
||
|
||
GenericULong |= 0x03;
|
||
|
||
} else {
|
||
|
||
GenericULong |= 0x04;
|
||
|
||
}
|
||
break;
|
||
|
||
case OID_GEN_VENDOR_DESCRIPTION:
|
||
|
||
if (Adapter->LanceCard == LANCE_DE201) {
|
||
|
||
MoveSource = (PVOID)"DEC Etherworks Turbo Adapter";
|
||
MoveBytes = 29;
|
||
|
||
} else if (Adapter->LanceCard == LANCE_DE100) {
|
||
|
||
MoveSource = (PVOID)"DEC Etherworks Adapter";
|
||
MoveBytes = 23;
|
||
|
||
} else if (Adapter->LanceCard == LANCE_DE422) {
|
||
|
||
MoveSource = (PVOID)"DEC Etherworks Turbo EISA Adapter";
|
||
MoveBytes = 34;
|
||
|
||
} else {
|
||
|
||
MoveSource = (PVOID)"Lance Adapter.";
|
||
MoveBytes = 15;
|
||
|
||
}
|
||
|
||
break;
|
||
|
||
case OID_GEN_DRIVER_VERSION:
|
||
|
||
GenericUShort = (LANCE_NDIS_MAJOR_VERSION << 8) | LANCE_NDIS_MINOR_VERSION;
|
||
|
||
MoveSource = (PVOID)(&GenericUShort);
|
||
MoveBytes = sizeof(GenericUShort);
|
||
break;
|
||
|
||
case OID_GEN_CURRENT_LOOKAHEAD:
|
||
|
||
GenericULong = Adapter->SizeOfReceiveBuffer;
|
||
|
||
break;
|
||
|
||
case OID_802_3_PERMANENT_ADDRESS:
|
||
|
||
LANCE_MOVE_MEMORY((PCHAR)GenericArray,
|
||
Adapter->NetworkAddress,
|
||
LANCE_LENGTH_OF_ADDRESS
|
||
);
|
||
|
||
MoveSource = (PVOID)(GenericArray);
|
||
MoveBytes = sizeof(Adapter->NetworkAddress);
|
||
break;
|
||
|
||
case OID_802_3_CURRENT_ADDRESS:
|
||
|
||
|
||
LANCE_MOVE_MEMORY((PCHAR)GenericArray,
|
||
Adapter->CurrentNetworkAddress,
|
||
LANCE_LENGTH_OF_ADDRESS
|
||
);
|
||
|
||
MoveSource = (PVOID)(GenericArray);
|
||
MoveBytes = sizeof(Adapter->CurrentNetworkAddress);
|
||
break;
|
||
|
||
case OID_802_3_MAXIMUM_LIST_SIZE:
|
||
|
||
GenericULong = Adapter->MaxMulticastList;
|
||
|
||
break;
|
||
|
||
case OID_GEN_XMIT_OK:
|
||
|
||
GenericULong = (ULONG)(Adapter->Transmit + Adapter->LateCollision);
|
||
|
||
break;
|
||
|
||
case OID_GEN_RCV_OK:
|
||
|
||
GenericULong = (ULONG)(Adapter->Receive);
|
||
|
||
break;
|
||
|
||
case OID_GEN_XMIT_ERROR:
|
||
|
||
GenericULong = (ULONG)(Adapter->LostCarrier);
|
||
|
||
break;
|
||
|
||
case OID_GEN_RCV_ERROR:
|
||
|
||
GenericULong = (ULONG)(Adapter->CRCError);
|
||
|
||
break;
|
||
|
||
case OID_GEN_RCV_NO_BUFFER:
|
||
|
||
GenericULong = (ULONG)(Adapter->OutOfReceiveBuffers);
|
||
|
||
break;
|
||
|
||
case OID_802_3_RCV_ERROR_ALIGNMENT:
|
||
|
||
GenericULong = (ULONG)(Adapter->FramingError);
|
||
|
||
break;
|
||
|
||
case OID_802_3_XMIT_ONE_COLLISION:
|
||
|
||
GenericULong = (ULONG)(Adapter->OneRetry);
|
||
|
||
break;
|
||
|
||
case OID_802_3_XMIT_MORE_COLLISIONS:
|
||
|
||
GenericULong = (ULONG)(Adapter->MoreThanOneRetry);
|
||
|
||
break;
|
||
|
||
default:
|
||
|
||
StatusToReturn = NDIS_STATUS_NOT_SUPPORTED;
|
||
break;
|
||
}
|
||
|
||
if (StatusToReturn == NDIS_STATUS_SUCCESS){
|
||
|
||
if (MoveBytes > BytesLeft){
|
||
|
||
//
|
||
// Not enough room in InformationBuffer. Punt
|
||
//
|
||
|
||
*BytesNeeded = MoveBytes;
|
||
|
||
StatusToReturn = NDIS_STATUS_INVALID_LENGTH;
|
||
|
||
} else {
|
||
|
||
//
|
||
// Store result.
|
||
//
|
||
|
||
LANCE_MOVE_MEMORY(InfoBuffer, MoveSource, MoveBytes);
|
||
|
||
(*BytesWritten) += MoveBytes;
|
||
|
||
}
|
||
}
|
||
|
||
#if LANCE_TRACE
|
||
DbgPrint("Out LanceQueryInfo\n");
|
||
#endif
|
||
|
||
LANCE_DO_DEFERRED(Adapter);
|
||
|
||
return StatusToReturn;
|
||
}
|
||
|
||
NDIS_STATUS
|
||
LanceSetInformation(
|
||
IN NDIS_HANDLE MiniportAdapterContext,
|
||
IN NDIS_OID Oid,
|
||
IN PVOID InformationBuffer,
|
||
IN ULONG InformationBufferLength,
|
||
OUT PULONG BytesRead,
|
||
OUT PULONG BytesNeeded
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
The LanceSetInformation is used by LanceRequest to set information
|
||
about the MAC.
|
||
|
||
Note: Assumes it is called with the lock held.
|
||
|
||
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.
|
||
|
||
--*/
|
||
|
||
{
|
||
|
||
PLANCE_ADAPTER Adapter = (PLANCE_ADAPTER)(MiniportAdapterContext);
|
||
//
|
||
// General Algorithm:
|
||
//
|
||
// For each request
|
||
// 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 values to be used.
|
||
//
|
||
|
||
ULONG LookAhead;
|
||
ULONG Filter;
|
||
|
||
NDIS_STATUS Status;
|
||
|
||
#if LANCE_TRACE
|
||
DbgPrint("In LanceSetInfo\n");
|
||
#endif
|
||
|
||
//
|
||
// Get Oid and Length of next request
|
||
//
|
||
|
||
OidLength = BytesLeft;
|
||
|
||
Status = NDIS_STATUS_SUCCESS;
|
||
|
||
switch (Oid) {
|
||
|
||
case OID_802_3_MULTICAST_LIST:
|
||
|
||
//
|
||
// Verify length
|
||
//
|
||
|
||
if ((OidLength % LANCE_LENGTH_OF_ADDRESS) != 0){
|
||
|
||
*BytesRead = 0;
|
||
*BytesNeeded = 0;
|
||
|
||
return( NDIS_STATUS_INVALID_LENGTH );
|
||
|
||
}
|
||
|
||
Status = LanceChangeMulticastAddresses(
|
||
Adapter,
|
||
OidLength / LANCE_LENGTH_OF_ADDRESS,
|
||
(CHAR (*)[LANCE_LENGTH_OF_ADDRESS])InfoBuffer,
|
||
NdisRequestSetInformation
|
||
);
|
||
|
||
break;
|
||
|
||
|
||
case OID_GEN_CURRENT_PACKET_FILTER:
|
||
|
||
//
|
||
// Verify length
|
||
//
|
||
|
||
if (OidLength != 4) {
|
||
|
||
Status = NDIS_STATUS_INVALID_LENGTH;
|
||
|
||
*BytesRead = 0;
|
||
*BytesNeeded = 0;
|
||
|
||
break;
|
||
|
||
}
|
||
|
||
|
||
LANCE_MOVE_MEMORY(&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;
|
||
|
||
}
|
||
|
||
Status = LanceSetPacketFilter(
|
||
Adapter,
|
||
NdisRequestSetInformation,
|
||
Filter
|
||
);
|
||
|
||
break;
|
||
|
||
case OID_GEN_CURRENT_LOOKAHEAD:
|
||
|
||
//
|
||
// Verify length
|
||
//
|
||
if (OidLength != 4)
|
||
{
|
||
Status = NDIS_STATUS_INVALID_LENGTH;
|
||
|
||
*BytesRead = 0;
|
||
*BytesNeeded = 4;
|
||
|
||
break;
|
||
}
|
||
|
||
LANCE_MOVE_MEMORY(&LookAhead, InfoBuffer, 4);
|
||
|
||
if (LookAhead <= (LANCE_MAX_LOOKAHEAD))
|
||
{
|
||
Status = NDIS_STATUS_SUCCESS;
|
||
}
|
||
else
|
||
{
|
||
Status = NDIS_STATUS_INVALID_LENGTH;
|
||
}
|
||
|
||
*BytesRead = 4;
|
||
*BytesNeeded = 0;
|
||
break;
|
||
|
||
default:
|
||
|
||
Status = NDIS_STATUS_INVALID_OID;
|
||
|
||
*BytesRead = 0;
|
||
*BytesNeeded = 0;
|
||
|
||
break;
|
||
}
|
||
|
||
if (Status == NDIS_STATUS_SUCCESS){
|
||
|
||
*BytesRead = OidLength;
|
||
*BytesNeeded = 0;
|
||
|
||
}
|
||
|
||
#if LANCE_TRACE
|
||
DbgPrint("Out LanceSetInfo\n");
|
||
#endif
|
||
|
||
LANCE_DO_DEFERRED(Adapter);
|
||
|
||
return Status;
|
||
}
|
||
|
||
STATIC
|
||
NDIS_STATUS
|
||
LanceSetPacketFilter(
|
||
IN PLANCE_ADAPTER Adapter,
|
||
IN NDIS_REQUEST_TYPE NdisRequestType,
|
||
IN UINT PacketFilter
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
The LanceSetPacketFilter request allows a protocol to control the types
|
||
of packets that it receives from the MAC.
|
||
|
||
Note : Assumes that the lock is currently held.
|
||
|
||
Arguments:
|
||
|
||
Adapter - Pointer to the LANCE_ADAPTER.
|
||
|
||
NdisRequestType - Code to indicate from where this routine is being called.
|
||
|
||
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;
|
||
|
||
|
||
#if LANCE_TRACE
|
||
DbgPrint("In LanceSetPacketFilter\n");
|
||
#endif
|
||
|
||
//
|
||
// Check to see if the device is already resetting.
|
||
//
|
||
|
||
if (Adapter->ResetInProgress || Adapter->HardwareFailure)
|
||
{
|
||
return(NDIS_STATUS_FAILURE);
|
||
}
|
||
|
||
//
|
||
// We need to add this to the hardware multicast filtering.
|
||
//
|
||
Adapter->PacketFilter = PacketFilter;
|
||
|
||
SetupForReset(Adapter, NdisRequestType);
|
||
|
||
#if LANCE_TRACE
|
||
DbgPrint("Out LanceSetPacketFilter\n");
|
||
#endif
|
||
|
||
return(NDIS_STATUS_PENDING);
|
||
}
|
||
|
||
STATIC
|
||
UINT
|
||
CalculateCRC(
|
||
IN UINT NumberOfBytes,
|
||
IN PCHAR Input
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Calculates a 32 bit crc value over the input number of bytes.
|
||
|
||
Arguments:
|
||
|
||
NumberOfBytes - The number of bytes in the input.
|
||
|
||
Input - An input "string" to calculate a CRC over.
|
||
|
||
Return Value:
|
||
|
||
A 32 bit crc value.
|
||
|
||
|
||
--*/
|
||
|
||
{
|
||
|
||
const UINT POLY = 0x04c11db6;
|
||
UINT CRCValue = 0xffffffff;
|
||
|
||
ASSERT(sizeof(UINT) == 4);
|
||
|
||
for ( ; NumberOfBytes; NumberOfBytes-- ) {
|
||
|
||
UINT CurrentBit;
|
||
UCHAR CurrentByte = *Input;
|
||
Input++;
|
||
|
||
for ( CurrentBit = 8; CurrentBit; CurrentBit-- ) {
|
||
|
||
UINT CurrentCRCHigh = CRCValue >> 31;
|
||
|
||
CRCValue <<= 1;
|
||
|
||
if (CurrentCRCHigh ^ (CurrentByte & 0x01)) {
|
||
|
||
CRCValue ^= POLY;
|
||
CRCValue |= 0x00000001;
|
||
|
||
}
|
||
|
||
CurrentByte >>= 1;
|
||
|
||
}
|
||
|
||
}
|
||
|
||
return CRCValue;
|
||
|
||
}
|
||
|
||
STATIC
|
||
NDIS_STATUS
|
||
LanceChangeMulticastAddresses(
|
||
IN PLANCE_ADAPTER Adapter,
|
||
IN UINT NewAddressCount,
|
||
IN CHAR NewAddresses[][LANCE_LENGTH_OF_ADDRESS],
|
||
IN NDIS_REQUEST_TYPE NdisRequestType
|
||
)
|
||
|
||
/*++
|
||
|
||
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:
|
||
|
||
Adapter - The adapter.
|
||
|
||
NewAddressCount - Number of Addresses that should be put on the adapter.
|
||
|
||
NewAddresses - An array of all the multicast addresses that should
|
||
now be used.
|
||
|
||
NdisRequestType - The request type.
|
||
|
||
Return Value:
|
||
|
||
Status of the operation.
|
||
|
||
|
||
--*/
|
||
|
||
{
|
||
#if LANCE_TRACE
|
||
DbgPrint("In LanceChangeMultiAdresses\n");
|
||
#endif
|
||
|
||
//
|
||
// Check to see if the device is already resetting. If it is
|
||
// then pend this add.
|
||
//
|
||
if (Adapter->ResetInProgress || Adapter->HardwareFailure)
|
||
{
|
||
|
||
return(NDIS_STATUS_FAILURE);
|
||
}
|
||
|
||
//
|
||
// We need to add this to the hardware multicast filtering.
|
||
//
|
||
Adapter->NumberOfAddresses = NewAddressCount;
|
||
|
||
NdisMoveMemory(
|
||
Adapter->MulticastAddresses,
|
||
NewAddresses,
|
||
NewAddressCount * LANCE_LENGTH_OF_ADDRESS
|
||
);
|
||
|
||
SetupForReset(Adapter, NdisRequestType);
|
||
|
||
|
||
#if LANCE_TRACE
|
||
DbgPrint("Out LanceChangeMultiAdresses\n");
|
||
#endif
|
||
|
||
return(NDIS_STATUS_PENDING);
|
||
|
||
}
|
||
|
||
NDIS_STATUS
|
||
LanceReset(
|
||
OUT PBOOLEAN AddressingReset,
|
||
IN NDIS_HANDLE MiniportAdapterContext
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
The LanceReset request instructs the mini-port to issue a hardware reset
|
||
to the network adapter. The Miniport also resets its software state. See
|
||
the description of MiniportReset for a detailed description of this request.
|
||
|
||
Arguments:
|
||
|
||
Status - Status of the operation.
|
||
|
||
AddressingReset - Not used.
|
||
|
||
MiniportAdapterContext - The context value set by this mini-port.
|
||
|
||
Return Value:
|
||
|
||
The function value is the status of the operation.
|
||
|
||
|
||
--*/
|
||
|
||
{
|
||
//
|
||
// Holds the status that should be returned to the caller.
|
||
//
|
||
PLANCE_ADAPTER Adapter = (PLANCE_ADAPTER)MiniportAdapterContext;
|
||
|
||
SetupForReset(
|
||
Adapter,
|
||
NdisRequestGeneric1 // Means Reset
|
||
);
|
||
|
||
LANCE_DO_DEFERRED(Adapter);
|
||
|
||
return(NDIS_STATUS_PENDING);
|
||
}
|
||
|
||
STATIC
|
||
VOID
|
||
LanceSetInitializationBlock(
|
||
IN PLANCE_ADAPTER Adapter
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine simply fills the initialization block
|
||
with the information necessary for initialization.
|
||
|
||
Arguments:
|
||
|
||
Adapter - The adapter which holds the initialization block
|
||
to initialize.
|
||
|
||
Return Value:
|
||
|
||
None.
|
||
|
||
|
||
--*/
|
||
|
||
{
|
||
|
||
ULONG PhysAdr;
|
||
|
||
UINT PacketFilters;
|
||
|
||
PLANCE_RECEIVE_ENTRY CurrentEntry = Adapter->ReceiveRing;
|
||
USHORT Mode;
|
||
UCHAR RingNumber;
|
||
UCHAR i;
|
||
|
||
#if LANCE_TRACE
|
||
DbgPrint("in SetInitBlock\n");
|
||
#endif
|
||
|
||
LANCE_ZERO_MEMORY_FOR_HARDWARE(
|
||
(PUCHAR)Adapter->InitBlock,
|
||
sizeof(LANCE_INITIALIZATION_BLOCK)
|
||
);
|
||
|
||
//
|
||
// Set the card address.
|
||
//
|
||
for (i = 0; i < LANCE_LENGTH_OF_ADDRESS; i++)
|
||
{
|
||
LANCE_WRITE_HARDWARE_MEMORY_UCHAR(
|
||
Adapter->InitBlock->PhysicalAddress[i],
|
||
Adapter->CurrentNetworkAddress[i]
|
||
);
|
||
}
|
||
|
||
//
|
||
// Setup the transmit ring.
|
||
//
|
||
PhysAdr = LANCE_GET_HARDWARE_PHYSICAL_ADDRESS(
|
||
Adapter,
|
||
Adapter->TransmitRing
|
||
);
|
||
|
||
LANCE_WRITE_HARDWARE_LOW_PART_ADDRESS(
|
||
Adapter->InitBlock->LowTransmitRingAddress,
|
||
LANCE_GET_LOW_PART_ADDRESS(PhysAdr)
|
||
);
|
||
|
||
LANCE_WRITE_HARDWARE_HIGH_PART_ADDRESS(
|
||
Adapter->InitBlock->HighTransmitRingAddress,
|
||
LANCE_GET_HIGH_PART_ADDRESS(PhysAdr)
|
||
);
|
||
|
||
//
|
||
// Setup the receive ring.
|
||
//
|
||
PhysAdr = LANCE_GET_HARDWARE_PHYSICAL_ADDRESS(
|
||
Adapter,
|
||
Adapter->ReceiveRing
|
||
);
|
||
|
||
//
|
||
// Set that the chip owns each entry in the ring
|
||
//
|
||
for (CurrentEntry = Adapter->ReceiveRing, RingNumber = 0;
|
||
RingNumber < Adapter->NumberOfReceiveRings ;
|
||
RingNumber++, CurrentEntry++
|
||
)
|
||
{
|
||
LANCE_WRITE_HARDWARE_MEMORY_UCHAR(
|
||
CurrentEntry->ReceiveSummaryBits,
|
||
LANCE_RECEIVE_OWNED_BY_CHIP
|
||
);
|
||
}
|
||
|
||
LANCE_WRITE_HARDWARE_LOW_PART_ADDRESS(
|
||
Adapter->InitBlock->LowReceiveRingAddress,
|
||
LANCE_GET_LOW_PART_ADDRESS(PhysAdr)
|
||
);
|
||
|
||
LANCE_WRITE_HARDWARE_HIGH_PART_ADDRESS(
|
||
Adapter->InitBlock->HighReceiveRingAddress,
|
||
LANCE_GET_HIGH_PART_ADDRESS(PhysAdr)
|
||
);
|
||
|
||
LANCE_WRITE_HARDWARE_MEMORY_UCHAR(
|
||
Adapter->InitBlock->TransmitLengthLow5BitsReserved,
|
||
(UCHAR)(Adapter->LogNumberTransmitRings << 5)
|
||
);
|
||
|
||
LANCE_WRITE_HARDWARE_MEMORY_UCHAR(
|
||
Adapter->InitBlock->ReceiveLengthLow5BitsReserved,
|
||
(UCHAR)(Adapter->LogNumberReceiveRings << 5)
|
||
);
|
||
|
||
//
|
||
// Set up the address filtering.
|
||
//
|
||
// First get hold of the combined packet filter.
|
||
//
|
||
PacketFilters = Adapter->PacketFilter;
|
||
|
||
#if LANCE_TRACE
|
||
DbgPrint("Filters 0x%x\n", PacketFilters);
|
||
#endif
|
||
|
||
if (PacketFilters & NDIS_PACKET_TYPE_PROMISCUOUS)
|
||
{
|
||
//
|
||
// If one binding is promiscuous there is no point in
|
||
// setting up any other filtering. Every packet is
|
||
// going to be accepted by the hardware.
|
||
//
|
||
LANCE_READ_HARDWARE_MEMORY_USHORT(
|
||
Adapter->InitBlock->ModeRegister,
|
||
&Mode
|
||
);
|
||
|
||
LANCE_WRITE_HARDWARE_MEMORY_USHORT(
|
||
Adapter->InitBlock->ModeRegister,
|
||
Mode | LANCE_MODE_PROMISCUOUS
|
||
);
|
||
}
|
||
else
|
||
{
|
||
//
|
||
// Turn off promiscuous bit
|
||
//
|
||
LANCE_READ_HARDWARE_MEMORY_USHORT(
|
||
Adapter->InitBlock->ModeRegister,
|
||
&Mode
|
||
);
|
||
|
||
LANCE_WRITE_HARDWARE_MEMORY_USHORT(
|
||
Adapter->InitBlock->ModeRegister,
|
||
Mode & (~LANCE_MODE_PROMISCUOUS)
|
||
);
|
||
|
||
if (PacketFilters & NDIS_PACKET_TYPE_ALL_MULTICAST)
|
||
{
|
||
//
|
||
// We turn on all the bits in the filter since one binding
|
||
// wants every multicast address.
|
||
//
|
||
LANCE_WRITE_HARDWARE_MEMORY_UCHAR(
|
||
Adapter->InitBlock->LogicalAddressFilter[0],
|
||
0xff
|
||
);
|
||
LANCE_WRITE_HARDWARE_MEMORY_UCHAR(
|
||
Adapter->InitBlock->LogicalAddressFilter[1],
|
||
0xff
|
||
);
|
||
LANCE_WRITE_HARDWARE_MEMORY_UCHAR(
|
||
Adapter->InitBlock->LogicalAddressFilter[2],
|
||
0xff
|
||
);
|
||
LANCE_WRITE_HARDWARE_MEMORY_UCHAR(
|
||
Adapter->InitBlock->LogicalAddressFilter[3],
|
||
0xff
|
||
);
|
||
LANCE_WRITE_HARDWARE_MEMORY_UCHAR(
|
||
Adapter->InitBlock->LogicalAddressFilter[4],
|
||
0xff
|
||
);
|
||
LANCE_WRITE_HARDWARE_MEMORY_UCHAR(
|
||
Adapter->InitBlock->LogicalAddressFilter[5],
|
||
0xff
|
||
);
|
||
LANCE_WRITE_HARDWARE_MEMORY_UCHAR(
|
||
Adapter->InitBlock->LogicalAddressFilter[6],
|
||
0xff
|
||
);
|
||
LANCE_WRITE_HARDWARE_MEMORY_UCHAR(
|
||
Adapter->InitBlock->LogicalAddressFilter[7],
|
||
0xff
|
||
);
|
||
}
|
||
else if (PacketFilters & NDIS_PACKET_TYPE_MULTICAST)
|
||
{
|
||
//
|
||
// At least one open binding wants multicast addresses.
|
||
//
|
||
// We get the multicast addresses from the filter and
|
||
// put each one through a CRC. We then take the high
|
||
// order 6 bits from the 32 bit CRC and set that bit
|
||
// in the logical address filter.
|
||
//
|
||
UINT NumberOfAddresses;
|
||
|
||
NumberOfAddresses = Adapter->NumberOfAddresses;
|
||
|
||
ASSERT(sizeof(ULONG) == 4);
|
||
|
||
for ( ; NumberOfAddresses; NumberOfAddresses--)
|
||
{
|
||
UINT CRCValue;
|
||
|
||
UINT HashValue = 0;
|
||
|
||
CRCValue = CalculateCRC(
|
||
6,
|
||
Adapter->MulticastAddresses[NumberOfAddresses-1]
|
||
);
|
||
|
||
HashValue |= ((CRCValue & 0x00000001)?(0x00000020):(0x00000000));
|
||
HashValue |= ((CRCValue & 0x00000002)?(0x00000010):(0x00000000));
|
||
HashValue |= ((CRCValue & 0x00000004)?(0x00000008):(0x00000000));
|
||
HashValue |= ((CRCValue & 0x00000008)?(0x00000004):(0x00000000));
|
||
HashValue |= ((CRCValue & 0x00000010)?(0x00000002):(0x00000000));
|
||
HashValue |= ((CRCValue & 0x00000020)?(0x00000001):(0x00000000));
|
||
|
||
LANCE_READ_HARDWARE_MEMORY_UCHAR(
|
||
Adapter->InitBlock->LogicalAddressFilter[HashValue >> 3],
|
||
&RingNumber
|
||
);
|
||
|
||
LANCE_WRITE_HARDWARE_MEMORY_UCHAR(
|
||
Adapter->InitBlock->LogicalAddressFilter[HashValue >> 3],
|
||
RingNumber | (1 << (HashValue & 0x00000007))
|
||
);
|
||
}
|
||
}
|
||
}
|
||
|
||
#if LANCE_TRACE
|
||
DbgPrint("out SetInitBlock\n");
|
||
#endif
|
||
}
|
||
|
||
|
||
STATIC
|
||
BOOLEAN
|
||
ProcessReceiveInterrupts(
|
||
IN PLANCE_ADAPTER Adapter
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Process the packets that have finished receiving.
|
||
|
||
NOTE: This routine assumes that no other thread of execution
|
||
is processing receives! THE LOCK MUST BE HELD
|
||
|
||
Arguments:
|
||
|
||
Adapter - The adapter to indicate to.
|
||
|
||
Return Value:
|
||
|
||
Whether to clear the interrupt or not.
|
||
|
||
--*/
|
||
|
||
{
|
||
//
|
||
// We don't get here unless there was a receive. Loop through
|
||
// the receive descriptors starting at the last known descriptor
|
||
// owned by the hardware that begins a packet.
|
||
//
|
||
// Examine each receive ring descriptor for errors.
|
||
//
|
||
// We keep an array whose elements are indexed by the ring
|
||
// index of the receive descriptors. The arrays elements are
|
||
// the virtual addresses of the buffers pointed to by
|
||
// each ring descriptor.
|
||
//
|
||
// When we have the entire packet (and error processing doesn't
|
||
// prevent us from indicating it), we give the routine that
|
||
// processes the packet through the filter, the buffers virtual
|
||
// address (which is always the lookahead size) and as the
|
||
// MAC context the index to the first and last ring descriptors
|
||
// comprising the packet.
|
||
//
|
||
|
||
//
|
||
// Index of the ring descriptor in the ring.
|
||
//
|
||
UINT CurrentIndex = Adapter->CurrentReceiveIndex;
|
||
|
||
//
|
||
// Pointer to the ring descriptor being examined.
|
||
//
|
||
PLANCE_RECEIVE_ENTRY CurrentEntry = Adapter->ReceiveRing + CurrentIndex;
|
||
|
||
//
|
||
// Hold in a local the top receive ring index so that we don't
|
||
// need to get it from the adapter all the time.
|
||
//
|
||
const UINT TopReceiveIndex = Adapter->NumberOfReceiveRings - 1;
|
||
|
||
//
|
||
// Boolean to record the fact that we've finished processing
|
||
// one packet and we're about to start a new one.
|
||
//
|
||
BOOLEAN NewPacket = FALSE;
|
||
|
||
//
|
||
// Count of the number of buffers in the current packet.
|
||
//
|
||
UINT NumberOfBuffers = 1;
|
||
|
||
//
|
||
// Pointer to host addressable space for the lookahead buffer
|
||
//
|
||
PUCHAR LookaheadBuffer;
|
||
|
||
ULONG ReceivePacketCount = 0;
|
||
|
||
for (; ; )
|
||
{
|
||
UCHAR ReceiveSummaryBits;
|
||
|
||
//
|
||
// Check to see whether we own the packet. If
|
||
// we don't then simply return to the caller.
|
||
//
|
||
|
||
LANCE_READ_HARDWARE_MEMORY_UCHAR(
|
||
CurrentEntry->ReceiveSummaryBits,
|
||
&ReceiveSummaryBits
|
||
);
|
||
|
||
if (ReceiveSummaryBits & LANCE_RECEIVE_OWNED_BY_CHIP)
|
||
{
|
||
LOG(RECEIVE);
|
||
|
||
return(TRUE);
|
||
}
|
||
else if (ReceivePacketCount > 10)
|
||
{
|
||
LOG(RECEIVE)
|
||
|
||
return(FALSE);
|
||
}
|
||
else if (ReceiveSummaryBits & LANCE_RECEIVE_ERROR_SUMMARY)
|
||
{
|
||
//
|
||
// We have an error in the packet. Record
|
||
// the details of the error.
|
||
//
|
||
|
||
//
|
||
// Synch with the set/query information routines.
|
||
//
|
||
if (ReceiveSummaryBits & LANCE_RECEIVE_BUFFER_ERROR)
|
||
{
|
||
//
|
||
// Probably ran out of descriptors.
|
||
//
|
||
|
||
Adapter->OutOfReceiveBuffers++;
|
||
}
|
||
else if (ReceiveSummaryBits & LANCE_RECEIVE_CRC_ERROR)
|
||
{
|
||
Adapter->CRCError++;
|
||
}
|
||
else if (ReceiveSummaryBits & LANCE_RECEIVE_OVERFLOW_ERROR)
|
||
{
|
||
Adapter->OutOfReceiveBuffers++;
|
||
}
|
||
else if (ReceiveSummaryBits & LANCE_RECEIVE_FRAMING_ERROR)
|
||
{
|
||
Adapter->FramingError++;
|
||
}
|
||
|
||
ReceivePacketCount++;
|
||
|
||
//
|
||
// Give the packet back to the hardware.
|
||
//
|
||
|
||
RelinquishReceivePacket(
|
||
Adapter,
|
||
Adapter->CurrentReceiveIndex,
|
||
NumberOfBuffers
|
||
);
|
||
|
||
NewPacket = TRUE;
|
||
}
|
||
else if (ReceiveSummaryBits & LANCE_RECEIVE_END_OF_PACKET)
|
||
{
|
||
//
|
||
// We've reached the end of the packet. Prepare
|
||
// the parameters for indication, then indicate.
|
||
//
|
||
|
||
UINT PacketSize;
|
||
UINT LookAheadSize;
|
||
|
||
LANCE_RECEIVE_CONTEXT Context;
|
||
|
||
ASSERT(sizeof(LANCE_RECEIVE_CONTEXT) == sizeof(NDIS_HANDLE));
|
||
|
||
//
|
||
// Check just before we do indications that we aren't
|
||
// resetting.
|
||
//
|
||
if (Adapter->ResetInProgress)
|
||
{
|
||
return(TRUE);
|
||
}
|
||
|
||
Context.INFO.IsContext = TRUE;
|
||
Context.INFO.FirstBuffer = Adapter->CurrentReceiveIndex;
|
||
Context.INFO.LastBuffer = CurrentIndex;
|
||
|
||
LANCE_GET_MESSAGE_SIZE(CurrentEntry, PacketSize);
|
||
|
||
LookAheadSize = PacketSize;
|
||
|
||
//
|
||
// Find amount to indicate.
|
||
//
|
||
|
||
LookAheadSize = ((LookAheadSize < Adapter->SizeOfReceiveBuffer) ?
|
||
LookAheadSize :
|
||
Adapter->SizeOfReceiveBuffer);
|
||
|
||
LookAheadSize -= LANCE_HEADER_SIZE;
|
||
|
||
//
|
||
// Increment the number of packets succesfully received.
|
||
//
|
||
|
||
Adapter->Receive++;
|
||
|
||
LOG(INDICATE);
|
||
|
||
Adapter->IndicatingMacReceiveContext = Context;
|
||
|
||
Adapter->IndicatedAPacket = TRUE;
|
||
|
||
NdisCreateLookaheadBufferFromSharedMemory(
|
||
(PVOID)(Adapter->ReceiveVAs[Adapter->CurrentReceiveIndex]),
|
||
LookAheadSize + LANCE_HEADER_SIZE,
|
||
&LookaheadBuffer
|
||
);
|
||
|
||
if (LookaheadBuffer != NULL)
|
||
{
|
||
if (PacketSize < LANCE_HEADER_SIZE)
|
||
{
|
||
if (PacketSize >= ETH_LENGTH_OF_ADDRESS)
|
||
{
|
||
//
|
||
// Runt packet
|
||
//
|
||
|
||
NdisMEthIndicateReceive(
|
||
Adapter->MiniportAdapterHandle,
|
||
(NDIS_HANDLE)Context.WholeThing,
|
||
LookaheadBuffer,
|
||
PacketSize,
|
||
NULL,
|
||
0,
|
||
0
|
||
);
|
||
}
|
||
}
|
||
else
|
||
{
|
||
NdisMEthIndicateReceive(
|
||
Adapter->MiniportAdapterHandle,
|
||
(NDIS_HANDLE)Context.WholeThing,
|
||
LookaheadBuffer,
|
||
LANCE_HEADER_SIZE,
|
||
LookaheadBuffer + LANCE_HEADER_SIZE,
|
||
LookAheadSize,
|
||
PacketSize - LANCE_HEADER_SIZE
|
||
);
|
||
}
|
||
|
||
NdisDestroyLookaheadBufferFromSharedMemory(LookaheadBuffer);
|
||
}
|
||
|
||
ReceivePacketCount++;
|
||
|
||
//
|
||
// Give the packet back to the hardware.
|
||
//
|
||
|
||
RelinquishReceivePacket(
|
||
Adapter,
|
||
Adapter->CurrentReceiveIndex,
|
||
NumberOfBuffers
|
||
);
|
||
|
||
NewPacket = TRUE;
|
||
}
|
||
|
||
//
|
||
// We're at some indermediate packet. Advance to
|
||
// the next one.
|
||
//
|
||
if (CurrentIndex == TopReceiveIndex)
|
||
{
|
||
CurrentIndex = 0;
|
||
CurrentEntry = Adapter->ReceiveRing;
|
||
}
|
||
else
|
||
{
|
||
CurrentIndex++;
|
||
CurrentEntry++;
|
||
}
|
||
|
||
if (NewPacket)
|
||
{
|
||
Adapter->CurrentReceiveIndex = CurrentIndex;
|
||
NewPacket = FALSE;
|
||
NumberOfBuffers = 0;
|
||
}
|
||
|
||
NumberOfBuffers++;
|
||
|
||
if (NumberOfBuffers > (TopReceiveIndex + 1))
|
||
{
|
||
//
|
||
// Error! For some reason we wrapped without ever seeing
|
||
// the end of packet. The card is hosed. Stop the
|
||
// whole process.
|
||
//
|
||
|
||
//
|
||
// There are opens to notify
|
||
//
|
||
Adapter->HardwareFailure = TRUE;
|
||
|
||
NdisMIndicateStatus(
|
||
Adapter->MiniportAdapterHandle,
|
||
NDIS_STATUS_CLOSING,
|
||
NULL,
|
||
0
|
||
);
|
||
|
||
NdisMIndicateStatusComplete(Adapter->MiniportAdapterHandle);
|
||
|
||
NdisMDeregisterInterrupt(&(Adapter->Interrupt));
|
||
|
||
NdisWriteErrorLogEntry(
|
||
Adapter->MiniportAdapterHandle,
|
||
NDIS_ERROR_CODE_HARDWARE_FAILURE,
|
||
0
|
||
);
|
||
|
||
return(TRUE);
|
||
}
|
||
}
|
||
}
|
||
|
||
STATIC
|
||
VOID
|
||
RelinquishReceivePacket(
|
||
IN PLANCE_ADAPTER Adapter,
|
||
IN UINT StartingIndex,
|
||
IN UINT NumberOfBuffers
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Gives a range of receive descriptors back to the hardware.
|
||
|
||
Arguments:
|
||
|
||
Adapter - The adapter that the ring works with.
|
||
|
||
StartingIndex - The first ring to return. Note that since
|
||
we are dealing with a ring, this value could be greater than
|
||
the EndingIndex.
|
||
|
||
NumberOfBuffers - The number of buffers (or ring descriptors) in
|
||
the current packet.
|
||
|
||
Return Value:
|
||
|
||
None.
|
||
|
||
--*/
|
||
|
||
{
|
||
|
||
//
|
||
// Index of the ring descriptor in the ring.
|
||
//
|
||
UINT CurrentIndex = StartingIndex;
|
||
|
||
//
|
||
// Pointer to the ring descriptor being returned.
|
||
//
|
||
PLANCE_RECEIVE_ENTRY CurrentEntry = Adapter->ReceiveRing + CurrentIndex;
|
||
|
||
//
|
||
// Hold in a local so that we don't need to access via the adapter.
|
||
//
|
||
const UINT TopReceiveIndex = Adapter->NumberOfReceiveRings - 1;
|
||
|
||
UCHAR Tmp;
|
||
|
||
LANCE_READ_HARDWARE_MEMORY_UCHAR(CurrentEntry->ReceiveSummaryBits, &Tmp);
|
||
|
||
ASSERT(!(Tmp & LANCE_RECEIVE_OWNED_BY_CHIP));
|
||
ASSERT(Tmp & LANCE_RECEIVE_START_OF_PACKET);
|
||
|
||
for ( ; NumberOfBuffers; NumberOfBuffers-- )
|
||
{
|
||
LANCE_WRITE_HARDWARE_MEMORY_UCHAR(
|
||
CurrentEntry->ReceiveSummaryBits,
|
||
LANCE_RECEIVE_OWNED_BY_CHIP
|
||
);
|
||
|
||
if (CurrentIndex == TopReceiveIndex)
|
||
{
|
||
CurrentEntry = Adapter->ReceiveRing;
|
||
CurrentIndex = 0;
|
||
}
|
||
else
|
||
{
|
||
CurrentEntry++;
|
||
CurrentIndex++;
|
||
}
|
||
}
|
||
}
|
||
|
||
STATIC
|
||
BOOLEAN
|
||
ProcessTransmitInterrupts(
|
||
IN PLANCE_ADAPTER Adapter
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Process the packets that have finished transmitting.
|
||
|
||
NOTE: This routine assumes that it is being executed in a
|
||
single thread of execution. CALLED WITH LOCK HELD!!!
|
||
|
||
Arguments:
|
||
|
||
Adapter - The adapter that was sent from.
|
||
|
||
Return Value:
|
||
|
||
This function will return TRUE if it finished up the
|
||
send on a packet. It will return FALSE if for some
|
||
reason there was no packet to process.
|
||
|
||
--*/
|
||
|
||
{
|
||
//
|
||
// Index into the ring to packet structure. This index points
|
||
// to the first ring entry for the first buffer used for transmitting
|
||
// the packet.
|
||
//
|
||
UINT FirstIndex;
|
||
|
||
//
|
||
// Pointer to the last ring entry for the packet to be transmitted.
|
||
// This pointer might actually point to a ring entry before the first
|
||
// ring entry for the packet since the ring structure is, simply, a ring.
|
||
//
|
||
PLANCE_TRANSMIT_ENTRY LastRingEntry;
|
||
|
||
//
|
||
// Pointer to the packet that started this transmission.
|
||
//
|
||
PNDIS_PACKET OwningPacket;
|
||
|
||
UCHAR TransmitSummaryBits;
|
||
USHORT ErrorSummaryInfo;
|
||
|
||
//
|
||
// Used to hold the ring to packet mapping information so that
|
||
// we can release the ring entries as quickly as possible.
|
||
//
|
||
LANCE_RING_TO_PACKET SavedRingMapping;
|
||
|
||
|
||
//
|
||
// Get hold of the first transmitted packet.
|
||
//
|
||
|
||
//
|
||
// First we check that this is a packet that was transmitted
|
||
// but not already processed. Recall that this routine
|
||
// will be called repeatedly until this tests false, Or we
|
||
// hit a packet that we don't completely own.
|
||
//
|
||
|
||
//
|
||
// NOTE: I found a problem where FirstUncommitedRing wraps around
|
||
// and becomes equal to TransmittingRing. This only happens when
|
||
// NumberOfAvailableRings is 0 (JohnsonA)
|
||
//
|
||
|
||
if ((Adapter->TransmittingRing == Adapter->FirstUncommittedRing) &&
|
||
(Adapter->NumberOfAvailableRings > 0)
|
||
)
|
||
{
|
||
return(FALSE);
|
||
}
|
||
else
|
||
{
|
||
FirstIndex = Adapter->TransmittingRing - Adapter->TransmitRing;
|
||
}
|
||
|
||
|
||
//
|
||
// We put the mapping into a local variable so that we
|
||
// can return the mapping as soon as possible.
|
||
//
|
||
|
||
SavedRingMapping = Adapter->RingToPacket[FirstIndex];
|
||
|
||
//
|
||
// Get a pointer to the last ring entry for this packet.
|
||
//
|
||
|
||
LastRingEntry = Adapter->TransmitRing + SavedRingMapping.RingIndex;
|
||
|
||
//
|
||
// Get a pointer to the owning packet .
|
||
//
|
||
OwningPacket = SavedRingMapping.OwningPacket;
|
||
|
||
SavedRingMapping.OwningPacket = NULL;
|
||
|
||
if (OwningPacket == NULL)
|
||
{
|
||
//
|
||
// We seem to be in a messed up state. Ignore this interrupt and
|
||
// the wake up dpc will reset the card if necessary.
|
||
//
|
||
|
||
ASSERT(OwningPacket != NULL);
|
||
return(FALSE);
|
||
}
|
||
|
||
//
|
||
// Check that the host does indeed own this entire packet.
|
||
//
|
||
|
||
LANCE_READ_HARDWARE_MEMORY_UCHAR(
|
||
LastRingEntry->TransmitSummaryBits,
|
||
&TransmitSummaryBits
|
||
);
|
||
|
||
if (TransmitSummaryBits & LANCE_TRANSMIT_OWNED_BY_CHIP)
|
||
{
|
||
//
|
||
// We don't own this last packet. We return FALSE to indicate
|
||
// that we don't have any more packets to work on.
|
||
//
|
||
return(FALSE);
|
||
}
|
||
else
|
||
{
|
||
//
|
||
// Pointer to the current ring descriptor being examine for errors
|
||
// and the statistics accumulated during its transmission.
|
||
//
|
||
PLANCE_TRANSMIT_ENTRY CurrentRingEntry;
|
||
|
||
//
|
||
// Holds whether the packet successfully transmitted or not.
|
||
//
|
||
BOOLEAN Successful = TRUE;
|
||
PLANCE_BUFFER_DESCRIPTOR BufferDescriptor = Adapter->LanceBuffers +
|
||
SavedRingMapping.LanceBuffersIndex;
|
||
INT ListHeadIndex = BufferDescriptor->Next;
|
||
|
||
LOG(TRANSMIT_COMPLETE);
|
||
|
||
CurrentRingEntry = Adapter->TransmitRing + FirstIndex;
|
||
|
||
//
|
||
// now return these buffers to the adapter.
|
||
//
|
||
|
||
BufferDescriptor->Next = Adapter->LanceBufferListHeads[ListHeadIndex];
|
||
Adapter->LanceBufferListHeads[ListHeadIndex] = SavedRingMapping.LanceBuffersIndex;
|
||
|
||
//
|
||
// Since the host owns the entire packet check the ring
|
||
// entries from first to last for any errors in transmission.
|
||
// Any errors found or multiple tries should be recorded in
|
||
// the information structure for the adapter.
|
||
//
|
||
// We treat Late Collisions as success since the packet was
|
||
// fully transmitted and may have been received.
|
||
//
|
||
for (;;)
|
||
{
|
||
LANCE_READ_HARDWARE_MEMORY_UCHAR(
|
||
CurrentRingEntry->TransmitSummaryBits,
|
||
&TransmitSummaryBits
|
||
);
|
||
|
||
LANCE_READ_HARDWARE_MEMORY_USHORT(
|
||
CurrentRingEntry->ErrorSummaryInfo,
|
||
&ErrorSummaryInfo
|
||
);
|
||
|
||
if ((TransmitSummaryBits & LANCE_TRANSMIT_ANY_ERRORS) &&
|
||
!(ErrorSummaryInfo & LANCE_TRANSMIT_LATE_COLLISION)
|
||
)
|
||
{
|
||
if (ErrorSummaryInfo & LANCE_TRANSMIT_RETRY)
|
||
{
|
||
Adapter->RetryFailure++;
|
||
}
|
||
else if (ErrorSummaryInfo & LANCE_TRANSMIT_LOST_CARRIER)
|
||
{
|
||
Adapter->LostCarrier++;
|
||
}
|
||
else if (ErrorSummaryInfo & LANCE_TRANSMIT_UNDERFLOW)
|
||
{
|
||
Adapter->UnderFlow++;
|
||
}
|
||
|
||
#if DBG
|
||
LanceSendFails[LanceSendFailPlace] = (UCHAR)(ErrorSummaryInfo);
|
||
LanceSendFailPlace++;
|
||
#endif
|
||
|
||
#if LANCE_TRACE
|
||
DbgPrint("Unsuccessful Transmit 0x%x\n", ErrorSummaryInfo);
|
||
#endif
|
||
|
||
Successful = FALSE;
|
||
|
||
//
|
||
// Move the pointer to transmitting but unprocessed
|
||
// ring entries to after this packet, and recover
|
||
// the remaining now available ring entries.
|
||
//
|
||
|
||
Adapter->NumberOfAvailableRings +=
|
||
(CurrentRingEntry <= LastRingEntry)?
|
||
((LastRingEntry - CurrentRingEntry)+1):
|
||
((Adapter->LastTransmitRingEntry - CurrentRingEntry) +
|
||
(LastRingEntry-Adapter->TransmitRing) + 2);
|
||
|
||
if (LastRingEntry == Adapter->LastTransmitRingEntry)
|
||
{
|
||
Adapter->TransmittingRing = Adapter->TransmitRing;
|
||
}
|
||
else
|
||
{
|
||
Adapter->TransmittingRing = LastRingEntry + 1;
|
||
}
|
||
|
||
break;
|
||
}
|
||
else
|
||
{
|
||
//
|
||
// Logical variable that records whether this
|
||
// is the last packet.
|
||
//
|
||
|
||
BOOLEAN DoneWithPacket = TransmitSummaryBits & LANCE_TRANSMIT_END_OF_PACKET;
|
||
|
||
if (ErrorSummaryInfo & LANCE_TRANSMIT_LATE_COLLISION)
|
||
{
|
||
Adapter->LateCollision++;
|
||
}
|
||
|
||
if (TransmitSummaryBits & LANCE_TRANSMIT_START_OF_PACKET)
|
||
{
|
||
//
|
||
// Collect some statistics on how many tries were needed.
|
||
//
|
||
if (TransmitSummaryBits & LANCE_TRANSMIT_DEFERRED)
|
||
{
|
||
Adapter->Deferred++;
|
||
}
|
||
else if (TransmitSummaryBits & LANCE_TRANSMIT_ONE_RETRY)
|
||
{
|
||
Adapter->OneRetry++;
|
||
}
|
||
else if (TransmitSummaryBits & LANCE_TRANSMIT_MORE_THAN_ONE_RETRY)
|
||
{
|
||
Adapter->MoreThanOneRetry++;
|
||
}
|
||
}
|
||
|
||
if (CurrentRingEntry == Adapter->LastTransmitRingEntry)
|
||
{
|
||
CurrentRingEntry = Adapter->TransmitRing;
|
||
}
|
||
else
|
||
{
|
||
CurrentRingEntry++;
|
||
}
|
||
|
||
Adapter->TransmittingRing = CurrentRingEntry;
|
||
Adapter->NumberOfAvailableRings++;
|
||
|
||
if (DoneWithPacket)
|
||
{
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
|
||
//
|
||
// Store result
|
||
//
|
||
if (Successful)
|
||
{
|
||
//
|
||
// Increment number of packets successfully sent.
|
||
//
|
||
Adapter->Transmit++;
|
||
}
|
||
|
||
NdisMSendResourcesAvailable(Adapter->MiniportAdapterHandle);
|
||
|
||
return(TRUE);
|
||
}
|
||
}
|
||
|
||
STATIC
|
||
VOID
|
||
StartAdapterReset(
|
||
IN PLANCE_ADAPTER Adapter
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This is the first phase of resetting the adapter hardware.
|
||
|
||
It makes the following assumptions:
|
||
|
||
1) That the hardware has been stopped.
|
||
|
||
2) That it can not be preempted.
|
||
|
||
3) That no other adapter activity can occur.
|
||
|
||
When this routine is finished all of the adapter information
|
||
will be as if the driver was just initialized.
|
||
|
||
Arguments:
|
||
|
||
Adapter - The adapter whose hardware is to be reset.
|
||
|
||
Return Value:
|
||
|
||
None.
|
||
|
||
--*/
|
||
|
||
{
|
||
UINT i;
|
||
|
||
#if LANCE_TRACE
|
||
DbgPrint("In StartAdapterReset\n");
|
||
#endif
|
||
|
||
LOG(RESET_STEP_2);
|
||
|
||
Adapter->NumberOfAvailableRings = Adapter->NumberOfTransmitRings;
|
||
Adapter->AllocateableRing = Adapter->TransmitRing;
|
||
Adapter->TransmittingRing = Adapter->TransmitRing;
|
||
Adapter->FirstUncommittedRing = Adapter->TransmitRing;
|
||
|
||
Adapter->CurrentReceiveIndex = 0;
|
||
|
||
//
|
||
// Clean all of the receive ring entries.
|
||
//
|
||
{
|
||
|
||
PLANCE_RECEIVE_ENTRY CurrentReceive = Adapter->ReceiveRing;
|
||
const PLANCE_RECEIVE_ENTRY After = Adapter->ReceiveRing +
|
||
Adapter->NumberOfReceiveRings;
|
||
|
||
do
|
||
{
|
||
LANCE_WRITE_HARDWARE_MEMORY_UCHAR(
|
||
CurrentReceive->ReceiveSummaryBits,
|
||
LANCE_RECEIVE_OWNED_BY_CHIP
|
||
);
|
||
|
||
CurrentReceive++;
|
||
|
||
} while (CurrentReceive != After);
|
||
}
|
||
|
||
|
||
//
|
||
// Clean all of the transmit ring entries.
|
||
//
|
||
|
||
{
|
||
PLANCE_TRANSMIT_ENTRY CurrentTransmit = Adapter->TransmitRing;
|
||
const PLANCE_TRANSMIT_ENTRY After = Adapter->TransmitRing+
|
||
Adapter->NumberOfTransmitRings;
|
||
|
||
do
|
||
{
|
||
LANCE_WRITE_HARDWARE_MEMORY_UCHAR(
|
||
CurrentTransmit->TransmitSummaryBits,
|
||
0x00
|
||
);
|
||
|
||
CurrentTransmit++;
|
||
} while (CurrentTransmit != After);
|
||
}
|
||
|
||
//
|
||
// Recover all of the adapter buffers.
|
||
//
|
||
|
||
for (i = 0;
|
||
i < (Adapter->NumberOfSmallBuffers +
|
||
Adapter->NumberOfMediumBuffers +
|
||
Adapter->NumberOfLargeBuffers);
|
||
i++
|
||
)
|
||
{
|
||
Adapter->LanceBuffers[i].Next = i+1;
|
||
}
|
||
|
||
Adapter->LanceBufferListHeads[0] = -1;
|
||
Adapter->LanceBufferListHeads[1] = 0;
|
||
Adapter->LanceBuffers[(Adapter->NumberOfSmallBuffers)-1].Next = -1;
|
||
Adapter->LanceBufferListHeads[2] = Adapter->NumberOfSmallBuffers;
|
||
Adapter->LanceBuffers[(Adapter->NumberOfSmallBuffers +
|
||
Adapter->NumberOfMediumBuffers)-1].Next = -1;
|
||
Adapter->LanceBufferListHeads[3] = Adapter->NumberOfSmallBuffers +
|
||
Adapter->NumberOfMediumBuffers;
|
||
Adapter->LanceBuffers[(Adapter->NumberOfSmallBuffers+
|
||
Adapter->NumberOfMediumBuffers+
|
||
Adapter->NumberOfLargeBuffers)-1].Next = -1;
|
||
|
||
SetInitBlockAndInit(Adapter);
|
||
|
||
#if LANCE_TRACE
|
||
DbgPrint("Out StartAdapterReset\n");
|
||
#endif
|
||
|
||
}
|
||
|
||
STATIC
|
||
VOID
|
||
SetInitBlockAndInit(
|
||
IN PLANCE_ADAPTER Adapter
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
It is this routines responsibility to make sure that the
|
||
initialization block is filled and the chip is initialized
|
||
*but not* started.
|
||
|
||
NOTE: This routine assumes that it is called with the lock
|
||
acquired OR that only a single thread of execution is working
|
||
with this particular adapter.
|
||
|
||
Arguments:
|
||
|
||
Adapter - The adapter whose hardware is to be initialized.
|
||
|
||
Return Value:
|
||
|
||
None.
|
||
|
||
--*/
|
||
{
|
||
|
||
ULONG PhysAdr;
|
||
|
||
//
|
||
// Fill in the adapters initialization block.
|
||
//
|
||
LanceSetInitializationBlock(Adapter);
|
||
|
||
PhysAdr = LANCE_GET_HARDWARE_PHYSICAL_ADDRESS(Adapter,Adapter->InitBlock);
|
||
|
||
//
|
||
// Make sure that it does have even byte alignment.
|
||
//
|
||
ASSERT((PhysAdr & 0x01)==0);
|
||
|
||
//
|
||
// Write the address of the initialization block to csr1 and csr2.
|
||
//
|
||
LANCE_WRITE_RAP(Adapter, LANCE_SELECT_CSR1);
|
||
LANCE_WRITE_RDP(Adapter, LANCE_GET_LOW_PART_ADDRESS(PhysAdr));
|
||
LANCE_WRITE_RAP(Adapter, LANCE_SELECT_CSR2);
|
||
LANCE_WRITE_RDP(Adapter, LANCE_GET_HIGH_PART_ADDRESS(PhysAdr));
|
||
|
||
//
|
||
// Write to csr0 to initialize the chip.
|
||
//
|
||
LANCE_WRITE_RAP(Adapter, LANCE_SELECT_CSR0);
|
||
LANCE_WRITE_RDP(Adapter, LANCE_CSR0_INIT_CHIP);
|
||
|
||
//
|
||
// Delay execution for 1/2 second to give the lance
|
||
// time to initialize.
|
||
//
|
||
NdisStallExecution( 500000 );
|
||
}
|
||
|
||
STATIC
|
||
VOID
|
||
SetupForReset(
|
||
IN PLANCE_ADAPTER Adapter,
|
||
IN NDIS_REQUEST_TYPE NdisRequestType
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine is used to fill in the who and why a reset is
|
||
being set up as well as setting the appropriate fields in the
|
||
adapter.
|
||
|
||
NOTE: This routine must be called with the lock acquired.
|
||
|
||
Arguments:
|
||
|
||
Adapter - The adapter whose hardware is to be initialized.
|
||
|
||
NdisRequestType - The reason for the reset.
|
||
|
||
Return Value:
|
||
|
||
None.
|
||
|
||
--*/
|
||
{
|
||
|
||
#if LANCE_TRACE
|
||
DbgPrint("In SetupForReset\n");
|
||
#endif
|
||
|
||
LOG(RESET_STEP_1);
|
||
|
||
//
|
||
// Shut down the chip. We won't be doing any more work until
|
||
// the reset is complete.
|
||
//
|
||
NdisMSynchronizeWithInterrupt(
|
||
&Adapter->Interrupt,
|
||
LanceSyncStopChip,
|
||
(PVOID)Adapter
|
||
);
|
||
|
||
//
|
||
// Once the chip is stopped we can't get any more interrupts.
|
||
// Any interrupts that are "queued" for processing could
|
||
// only possibly service this reset. It is therefore safe for
|
||
// us to clear the adapter global csr value.
|
||
//
|
||
Adapter->ResetInProgress = TRUE;
|
||
Adapter->ResetInitStarted = FALSE;
|
||
|
||
//
|
||
// Shut down all of the transmit queues so that the
|
||
// transmit portion of the chip will eventually calm down.
|
||
//
|
||
Adapter->ResetRequestType = NdisRequestType;
|
||
|
||
#if LANCE_TRACE
|
||
DbgPrint("Out SetupForReset\n");
|
||
#endif
|
||
}
|
||
|
||
|
||
STATIC
|
||
BOOLEAN
|
||
LanceSyncWriteNicsr(
|
||
IN PVOID Context
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine is used by the normal interrupt processing routine
|
||
to synchronize with interrupts from the card. It will
|
||
Write to the NIC Status Register.
|
||
|
||
Arguments:
|
||
|
||
Context - This is really a pointer to a record type peculiar
|
||
to this routine. The record contains a pointer to the adapter
|
||
and a pointer to an address which holds the value to write.
|
||
|
||
Return Value:
|
||
|
||
Always returns false.
|
||
|
||
--*/
|
||
|
||
{
|
||
|
||
PLANCE_SYNCH_CONTEXT C = Context;
|
||
|
||
LANCE_ISR_WRITE_NICSR(C->Adapter, C->LocalWrite);
|
||
|
||
return FALSE;
|
||
|
||
}
|
||
|
||
STATIC
|
||
BOOLEAN
|
||
LanceSyncStopChip(
|
||
IN PVOID Context
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine is used to stop a lance.
|
||
|
||
|
||
|
||
Arguments:
|
||
|
||
Adapter - The adapter for the LANCE to stop.
|
||
|
||
Return Value:
|
||
|
||
FALSE
|
||
|
||
--*/
|
||
|
||
{
|
||
|
||
PLANCE_ADAPTER Adapter = (PLANCE_ADAPTER)Context;
|
||
|
||
//
|
||
// Set the RAP to csr0.
|
||
//
|
||
LANCE_ISR_WRITE_RAP(Adapter, LANCE_SELECT_CSR0);
|
||
|
||
//
|
||
// Set the RDP to stop chip.
|
||
//
|
||
LANCE_ISR_WRITE_RDP(Adapter, LANCE_CSR0_STOP);
|
||
|
||
if (Adapter->LanceCard & (LANCE_DE201 | LANCE_DE100 | LANCE_DE422))
|
||
{
|
||
//
|
||
// Always reset the ACON bit after a stop.
|
||
//
|
||
LANCE_ISR_WRITE_RAP(Adapter, LANCE_SELECT_CSR3);
|
||
|
||
LANCE_ISR_WRITE_RDP(Adapter, LANCE_CSR3_ACON);
|
||
}
|
||
|
||
//
|
||
// Select CSR0 again.
|
||
//
|
||
LANCE_ISR_WRITE_RAP(Adapter, LANCE_SELECT_CSR0);
|
||
|
||
return(FALSE);
|
||
}
|
||
|
||
|
||
|