From e611b132f9b8abe35b362e5870b74bce94a1e58e Mon Sep 17 00:00:00 2001 From: Adam Date: Sat, 16 May 2020 20:51:50 -0700 Subject: initial commit --- private/ntos/ndis/lance/dectc.c | 301 +++ private/ntos/ndis/lance/dectc.h | 29 + private/ntos/ndis/lance/details.c | 428 ++++ private/ntos/ndis/lance/keywords.h | 56 + private/ntos/ndis/lance/lance.c | 4974 ++++++++++++++++++++++++++++++++++++ private/ntos/ndis/lance/lance.rc | 39 + private/ntos/ndis/lance/lancehrd.h | 479 ++++ private/ntos/ndis/lance/lancesft.h | 962 +++++++ private/ntos/ndis/lance/makefile | 6 + private/ntos/ndis/lance/send.c | 437 ++++ private/ntos/ndis/lance/sources | 47 + private/ntos/ndis/lance/transfer.c | 389 +++ 12 files changed, 8147 insertions(+) create mode 100644 private/ntos/ndis/lance/dectc.c create mode 100644 private/ntos/ndis/lance/dectc.h create mode 100644 private/ntos/ndis/lance/details.c create mode 100644 private/ntos/ndis/lance/keywords.h create mode 100644 private/ntos/ndis/lance/lance.c create mode 100644 private/ntos/ndis/lance/lance.rc create mode 100644 private/ntos/ndis/lance/lancehrd.h create mode 100644 private/ntos/ndis/lance/lancesft.h create mode 100644 private/ntos/ndis/lance/makefile create mode 100644 private/ntos/ndis/lance/send.c create mode 100644 private/ntos/ndis/lance/sources create mode 100644 private/ntos/ndis/lance/transfer.c (limited to 'private/ntos/ndis/lance') diff --git a/private/ntos/ndis/lance/dectc.c b/private/ntos/ndis/lance/dectc.c new file mode 100644 index 000000000..499fca553 --- /dev/null +++ b/private/ntos/ndis/lance/dectc.c @@ -0,0 +1,301 @@ +#ifndef i386 // No INTEL system has a TurboChannel bus. + +/*++ + +Copyright (c) 1990 Microsoft Corporation + +Module Name: + + dectc.c + +Abstract: + + This is the implementation of the card specific callbacks for the + DEC TurboChannel option for the Advanced Micro Devices LANCE (Am 7990) + Ethernet controller. + +Author: + +Environment: + +Revision History: + + 31-Jul-1992 R.D. Lanser: + + Moved/copied code from 'lance.c' to this file for all DEC + TurboChannel (PMAD-AA) specific code. + +--*/ + +#include +#include "lancehrd.h" +#include "lancesft.h" +#include "dectc.h" + + +NDIS_STATUS +LanceDecTcGetConfiguration( + NDIS_HANDLE ConfigHandle, + PLANCE_ADAPTER PAdapter + ) +/*++ +Routine Description: + + This is the Digital TurboChannel configuration routine. This routine + extracts configuration information from the configuration data base. + +Arguments: + + ConfigHandle - Handle for configuration database. + PAdapter - Pointer for the adapter root. + +Return Value: + + NDIS_STATUS_SUCCESS - Configuration get was successfully. + NDIS_STATUS_FAILURE - Configuration get was unsuccessfully. + +--*/ + + +{ + NDIS_STATUS status = NDIS_STATUS_SUCCESS; + + enum { + CS_FIRST_INDEX = 0, + INTERRUPT_VECTOR = CS_FIRST_INDEX, + IRQL, + BASE_ADDR, + CS_NUM_OF_ENTRIES + } csIndex; + + NDIS_STRING configString[CS_NUM_OF_ENTRIES] = { + NDIS_STRING_CONST("InterruptVector"), + NDIS_STRING_CONST("InterruptRequestLevel"), + NDIS_STRING_CONST("BaseAddress"), + }; + + UINT csCount = 0; + + for (csIndex = CS_FIRST_INDEX; csIndex < CS_NUM_OF_ENTRIES; csIndex++) { + + NDIS_STATUS returnedStatus; + PNDIS_CONFIGURATION_PARAMETER returnedValue; + + // + // Read the configuration entry + // + + NdisReadConfiguration( + &returnedStatus, + &returnedValue, + ConfigHandle, + &(configString[csIndex]), + NdisParameterInteger + ); + + if (returnedStatus == NDIS_STATUS_SUCCESS) { + + switch (csIndex) { + + case INTERRUPT_VECTOR: + PAdapter->InterruptNumber = + (CCHAR)returnedValue->ParameterData.IntegerData; + break; + case IRQL: + PAdapter->InterruptRequestLevel = + (CCHAR)returnedValue->ParameterData.IntegerData; + break; + case BASE_ADDR: + PAdapter->HardwareBaseAddr = (PVOID) + (returnedValue->ParameterData.IntegerData); + break; + default: + continue; + } + + csCount++; + + } else { + + status = returnedStatus; + +#if DBG + { + PCCHAR str[CS_NUM_OF_ENTRIES] = { + "InterruptVector", + "InterruptRequestLevel", + "BaseAddress" + } ; + DbgPrint("LANCE: Configuration parameter '%s' not found", + str[csIndex]); + } +#endif + + } + + } // for (csIndex ... + + // + // Fill in the rest of the configuration. + // + + if (status == NDIS_STATUS_SUCCESS) { + if (csCount == CS_NUM_OF_ENTRIES) { + + // + // Treat the RAP, RDP, and NetworkHardwareAddress as port numbers + // (offsets from the first register). This will allow the + // usage of the Ndis{Read/Write}Portxxx macros after the port + // offset address is fixed up in LanceDecTcSoftwareDetails. + // + + // + // The amount of dual ported memory. + // + PAdapter->AmountOfHardwareMemory = LANCE_DECTC_HARDWARE_MEMORY; + // + // The offset of this memory from the base address. + // + PAdapter->HardwareBaseOffset = 0; + // + // The register offsets from the base address. + // + PAdapter->RAP = (ULONG) LANCE_DECTC_RAP_OFFSET; + PAdapter->RDP = (ULONG) LANCE_DECTC_RDP_OFFSET; + // + // Not used for this adapter, simply null it. + // + PAdapter->Nicsr = (ULONG)NULL; + // + // And the offset from the base address for the hardware address. + // + PAdapter->NetworkHardwareAddress = LANCE_DECTC_NETWORK_OFFSET; + + } else { + + // + // Insufficient configuration data. + // + status = NDIS_ERROR_CODE_UNSUPPORTED_CONFIGURATION; + + } + } + + return status; +} + +NDIS_STATUS +LanceDecTcSoftwareDetails( + PLANCE_ADAPTER PAdapter + ) +/*++ +Routine Description: + + Set buffer sizes and number of rings. Also, fixe the port mapping + offset address to avoid large unsigned subtractions in NDIS. See + the following macros in lancehrd.h: + + LANCE_ISR_WRITE_RAP(A,C) NdisRawWritePortUshort (... + LANCE_ISR_READ_RDP(A,C) NdisRawReadPortUshort (... + LANCE_ISR_WRITE_RDP(A,C) NdisRawWritePortUshort (... + LANCE_ISR_WRITE_NICSR(A,C) NdisRawWritePortUshort (... + + The port offset is the mapped address base, and the port number is + the offset from that base (confused yet?). + +Arguments: + + PAdapter - Pointer for the adapter root. + +Return Value: + + NDIS_STATUS_SUCCESS - Configuration get was successfully. + NDIS_STATUS_RESOURCES - Insufficient resources. + +--*/ + + +{ + NDIS_STATUS status = NDIS_STATUS_SUCCESS; + + // + // Set buffer sizes and number of rings. + // + + PAdapter->SizeOfReceiveBuffer = LANCE_128K_SIZE_OF_RECEIVE_BUFFERS; + PAdapter->NumberOfSmallBuffers = LANCE_128K_NUMBER_OF_SMALL_BUFFERS; + PAdapter->NumberOfMediumBuffers= LANCE_128K_NUMBER_OF_MEDIUM_BUFFERS; + PAdapter->NumberOfLargeBuffers = LANCE_128K_NUMBER_OF_LARGE_BUFFERS; + + PAdapter->NumberOfReceiveRings = LANCE_128K_NUMBER_OF_RECEIVE_RINGS; + PAdapter->LogNumberReceiveRings = LANCE_128K_LOG_RECEIVE_RINGS; + + return NDIS_STATUS_SUCCESS; +} + +NDIS_STATUS +LanceDecTcHardwareDetails( + PLANCE_ADAPTER PAdapter + ) +/*++ +Routine Description: + + This routine extracts the network hardware address. + +Arguments: + + PAdapter - Pointer for the adapter root. + +Return Value: + + + NDIS_STATUS_SUCCESS - Success. + NDIS_STATUS_FAILURE - Failure. + +--*/ + + +{ + ULONG port; + ULONG registerValue; + + + + port = (ULONG)(PAdapter->NetworkHardwareAddress); + NdisRawReadPortUlong(port, ®isterValue); + + registerValue = (registerValue & 0x00ff0000u) >> 16; + PAdapter->NetworkAddress[0] = (UCHAR)registerValue; + + port += sizeof(ULONG); + NdisRawReadPortUlong(port, ®isterValue); + registerValue = (registerValue & 0x00ff0000u) >> 16; + PAdapter->NetworkAddress[1] = (UCHAR)registerValue; + + + port += sizeof(ULONG); + NdisRawReadPortUlong(port, ®isterValue); + registerValue = (registerValue & 0x00ff0000u) >> 16; + PAdapter->NetworkAddress[2] = (UCHAR)registerValue; + + + port += sizeof(ULONG); + NdisRawReadPortUlong(port, ®isterValue); + registerValue = (registerValue & 0x00ff0000u) >> 16; + PAdapter->NetworkAddress[3] = (UCHAR)registerValue; + + + port += sizeof(ULONG); + NdisRawReadPortUlong(port, ®isterValue); + registerValue = (registerValue & 0x00ff0000u) >> 16; + PAdapter->NetworkAddress[4] = (UCHAR)registerValue; + + + port += sizeof(ULONG); + NdisRawReadPortUlong(port, ®isterValue); + registerValue = (registerValue & 0x00ff0000u) >> 16; + PAdapter->NetworkAddress[5] = (UCHAR)registerValue; + + return NDIS_STATUS_SUCCESS; +} +#endif // i386 diff --git a/private/ntos/ndis/lance/dectc.h b/private/ntos/ndis/lance/dectc.h new file mode 100644 index 000000000..70e7f8089 --- /dev/null +++ b/private/ntos/ndis/lance/dectc.h @@ -0,0 +1,29 @@ +#ifndef _LANCEDECTC_ +#define _LANCEDECTC_ + + +#define LANCE_DECTC_HARDWARE_MEMORY (0x20000u) // Should be 128K +#define LANCE_DECTC_REGISTER_OFFSET (0x100000) +#define LANCE_DECTC_REGISTER_MAPSIZE (0x1c0080 - 0x100000) +#define LANCE_DECTC_RAP_OFFSET (0x100004 - LANCE_DECTC_REGISTER_OFFSET) +#define LANCE_DECTC_RDP_OFFSET (0x100000 - LANCE_DECTC_REGISTER_OFFSET) +#define LANCE_DECTC_NETWORK_OFFSET (0x1c0000 - LANCE_DECTC_REGISTER_OFFSET) + + +NDIS_STATUS +LanceDecTcGetConfiguration( + NDIS_HANDLE ConfigHandle, + PLANCE_ADAPTER Adapter + ); + +NDIS_STATUS +LanceDecTcSoftwareDetails( + PLANCE_ADAPTER Adapter + ); + +NDIS_STATUS +LanceDecTcHardwareDetails( + PLANCE_ADAPTER Adapter + ); + +#endif // _LANCEDECTC_ diff --git a/private/ntos/ndis/lance/details.c b/private/ntos/ndis/lance/details.c new file mode 100644 index 000000000..963bd74e4 --- /dev/null +++ b/private/ntos/ndis/lance/details.c @@ -0,0 +1,428 @@ +/*++ + +Copyright (c) 1990 Microsoft Corporation + +Module Name: + + transfer.c + +Abstract: + + This file implements the routine that does very architecture + specific things. + +Author: + + Anthony V. Ercolano (Tonye) 02-Oct-1990 + +Environment: + + Kernel Mode - Or whatever is the equivalent on OS/2 and DOS. + +Revision History: + + Sean Selitrennikoff (SeanSe) 10/20/91 + Added code to deal with a DecstationPC + + 31-Jul-1992 R.D. Lanser: + + Moved DEC TurboChannel (PMAD-AA) code to adapter specific routine. + +--*/ + +#include +#include +#include + + +#pragma NDIS_INIT_FUNCTION(LanceHardwareDetails) + +BOOLEAN +LanceHardwareDetails( + IN PLANCE_ADAPTER Adapter + ) + +/*++ + +Routine Description: + + This routine gets the network address from the hardware. + +Arguments: + + Adapter - Where to store the network address. + +Return Value: + + TRUE - if successful. + +--*/ + +{ + UCHAR Signature[] = { 0xff, 0x00, 0x55, 0xaa, 0xff, 0x00, 0x55, 0xaa}; + UCHAR BytesRead[8]; + + UINT ReadCount; + + UINT Place; + + // + // Reset E-PROM state + // + // To do this we first read from the E-PROM address until the + // specific signature is reached (then the next bytes read from + // the E-PROM address will be the ethernet address of the card). + // + + + + // + // Read first part of the signature + // + + for (Place=0; Place < 8; Place++){ + + NdisRawReadPortUchar((ULONG)(Adapter->NetworkHardwareAddress), + &(BytesRead[Place])); + + } + + ReadCount = 8; + + // + // This advances to the front of the circular buffer. + // + + while (ReadCount < 40) { + + // + // Check if we have read the signature. + // + + for (Place = 0; Place < 8; Place++){ + + if (BytesRead[Place] != Signature[Place]){ + + Place = 10; + break; + + } + + } + + // + // If we have read the signature, stop. + // + + if (Place != 10){ + + break; + + } + + // + // else, move all the bytes down one and read then + // next byte. + // + + for (Place = 0; Place < 7; Place++){ + + BytesRead[Place] = BytesRead[Place+1]; + + } + + NdisRawReadPortUchar((ULONG)(Adapter->NetworkHardwareAddress), + &(BytesRead[7])); + + ReadCount++; + } + + + if (ReadCount == 40){ + + return(FALSE); + + } + + + // + // Now read the ethernet address of the card. + // + + + NdisRawReadPortUchar( + (ULONG)(Adapter->NetworkHardwareAddress), + &(Adapter->NetworkAddress[0]) + ); + NdisRawReadPortUchar( + (ULONG)(Adapter->NetworkHardwareAddress), + &(Adapter->NetworkAddress[1]) + ); + NdisRawReadPortUchar( + (ULONG)(Adapter->NetworkHardwareAddress), + &(Adapter->NetworkAddress[2]) + ); + NdisRawReadPortUchar( + (ULONG)(Adapter->NetworkHardwareAddress), + &(Adapter->NetworkAddress[3]) + ); + NdisRawReadPortUchar( + (ULONG)(Adapter->NetworkHardwareAddress), + &(Adapter->NetworkAddress[4]) + ); + NdisRawReadPortUchar( + (ULONG)(Adapter->NetworkHardwareAddress), + &(Adapter->NetworkAddress[5]) + ); + + + + if (!(Adapter->LanceCard & (LANCE_DE201 | LANCE_DE422))) { + + if (Adapter->LanceCard == LANCE_DEPCA){ + + // + // Reset Lan Interface port. + // + + NdisRawWritePortUchar( + (ULONG)(LANCE_DEPCA_LAN_CFG_OFFSET + + Adapter->Nicsr), + 0x00); + + // + // Reset Network Interface Control Status Register + // + + NdisRawWritePortUshort((ULONG)(Adapter->Nicsr), 0x00); + } + + return(TRUE); + + } + + + + + // + // Now do the EPROM Hardware check as outlined in the tech ref. + // + + + // + // Check for NULL address. + // + + for (Place = 0; Place < 6; Place++) { + + if (Adapter->NetworkAddress[Place] != 0) { + + Place = 10; + break; + + } + + } + + if (Place != 10) { + + return(FALSE); + + } + + + + // + // Check that bit 0 is not a 1 + // + + if (Adapter->NetworkAddress[0] & 0x1) { + + return(FALSE); + + } + + + + + + // + // Check that octet[0]->octet[7] == octet[15]->octet[8] + // + + NdisRawReadPortUchar( + (ULONG)(Adapter->NetworkHardwareAddress), + &(BytesRead[6]) + ); + NdisRawReadPortUchar( + (ULONG)(Adapter->NetworkHardwareAddress), + &(BytesRead[7]) + ); + + NdisRawReadPortUchar( + (ULONG)(Adapter->NetworkHardwareAddress), + &(BytesRead[0]) + ); + NdisRawReadPortUchar( + (ULONG)(Adapter->NetworkHardwareAddress), + &(BytesRead[1]) + ); + + if ((BytesRead[7] != BytesRead[0]) || + (BytesRead[6] != BytesRead[1])) { + + return(FALSE); + + } + + + NdisRawReadPortUchar( + (ULONG)(Adapter->NetworkHardwareAddress), + &(BytesRead[5]) + ); + NdisRawReadPortUchar( + (ULONG)(Adapter->NetworkHardwareAddress), + &(BytesRead[4]) + ); + NdisRawReadPortUchar( + (ULONG)(Adapter->NetworkHardwareAddress), + &(BytesRead[3]) + ); + NdisRawReadPortUchar( + (ULONG)(Adapter->NetworkHardwareAddress), + &(BytesRead[2]) + ); + NdisRawReadPortUchar( + (ULONG)(Adapter->NetworkHardwareAddress), + &(BytesRead[1]) + ); + NdisRawReadPortUchar( + (ULONG)(Adapter->NetworkHardwareAddress), + &(BytesRead[0]) + ); + + for (Place = 0; Place < 6; Place++) { + + if (BytesRead[Place] != (UCHAR)(Adapter->NetworkAddress[Place])) { + + return(FALSE); + + } + + } + + + // + // Check that octet[0]->octet[8] == octet[16]->octet[23] + // + + NdisRawReadPortUchar( + (ULONG)(Adapter->NetworkHardwareAddress), + &(BytesRead[0]) + ); + NdisRawReadPortUchar( + (ULONG)(Adapter->NetworkHardwareAddress), + &(BytesRead[1]) + ); + NdisRawReadPortUchar( + (ULONG)(Adapter->NetworkHardwareAddress), + &(BytesRead[2]) + ); + NdisRawReadPortUchar( + (ULONG)(Adapter->NetworkHardwareAddress), + &(BytesRead[3]) + ); + NdisRawReadPortUchar( + (ULONG)(Adapter->NetworkHardwareAddress), + &(BytesRead[4]) + ); + NdisRawReadPortUchar( + (ULONG)(Adapter->NetworkHardwareAddress), + &(BytesRead[5]) + ); + + for (Place = 0; Place < 6; Place++) { + + if (BytesRead[Place] != (UCHAR)(Adapter->NetworkAddress[Place])) { + + return(FALSE); + + } + + } + + + NdisRawReadPortUchar( + (ULONG)(Adapter->NetworkHardwareAddress), + &(BytesRead[0]) + ); + NdisRawReadPortUchar( + (ULONG)(Adapter->NetworkHardwareAddress), + &(BytesRead[1]) + ); + + if ((BytesRead[6] != BytesRead[0]) || + (BytesRead[7] != BytesRead[1])) { + + return(FALSE); + + } + + // + // Check that octet[24] -> octet[31] == signature bytes + // + + + for (Place = 0; Place < 8; Place++){ + + + NdisRawReadPortUchar( + (ULONG)(Adapter->NetworkHardwareAddress), + &(BytesRead[Place]) + ); + + if (BytesRead[Place] != Signature[Place]){ + +#if DBG + DbgPrint("Lance: Hardware failure\n"); +#endif + return(FALSE); + + } + + } + + if (Adapter->LanceCard == LANCE_DEPCA){ + + // + // Reset Lan Interface port. + // + + NdisRawWritePortUchar( + (ULONG)(LANCE_DEPCA_LAN_CFG_OFFSET + + Adapter->Nicsr), + 0x00); + + // + // Reset Network Interface Control Status Register + // + + NdisRawWritePortUshort((ULONG)(Adapter->Nicsr), 0x00); + } + + if (Adapter->LanceCard & (LANCE_DE201 | LANCE_DE422)) { + + // + // Reset Network Interface Control Status Register + // + + NdisRawWritePortUshort((ULONG)(Adapter->Nicsr), 0x00); + + } + + return(TRUE); + +} + + + diff --git a/private/ntos/ndis/lance/keywords.h b/private/ntos/ndis/lance/keywords.h new file mode 100644 index 000000000..988905586 --- /dev/null +++ b/private/ntos/ndis/lance/keywords.h @@ -0,0 +1,56 @@ +/*++ + +Copyright (c) 1990 Microsoft Corporation + +Module Name: + + keywords.h + +Abstract: + + Contains all Ndis2 and Ndis3 mac-specific keywords. + +Author: + + Bob Noradki + +Environment: + + This driver is expected to work in DOS, OS2 and NT at the equivalent + of kernal mode. + + Architecturally, there is an assumption in this driver that we are + on a little endian machine. + +Notes: + + optional-notes + +Revision History: + + + +--*/ +#ifndef NDIS2 +#define NDIS2 0 +#endif + +#if NDIS2 +#define MEMMAPPEDBASEADDRESS NDIS_STRING_CONST("RAMADDRESS") +#define SLOTNUMBER NDIS_STRING_CONST("SLOTNUMBER") +#define IOADDRESS NDIS_STRING_CONST("IOADDRESS") +#define INTERRUPT NDIS_STRING_CONST("INTERRUPT") +#define MAXMULTICASTLIST NDIS_STRING_CONST("MAXMULTICAST") +#define NETWORKADDRESS NDIS_STRING_CONST("NETADDRESS") +#define CARDTYPE NDIS_STRING_CONST("AdapterName") + +#else // NDIS3 + +#define MEMMAPPEDBASEADDRESS NDIS_STRING_CONST("MemoryMappedBaseAddress") +#define IOADDRESS NDIS_STRING_CONST("IoBaseAddress") +#define INTERRUPT NDIS_STRING_CONST("InterruptNumber") +#define MAXMULTICASTLIST NDIS_STRING_CONST("MaximumMulticastList") +#define NETWORKADDRESS NDIS_STRING_CONST("NetworkAddress") +#define CARDTYPE NDIS_STRING_CONST("CardType") + +#endif diff --git a/private/ntos/ndis/lance/lance.c b/private/ntos/ndis/lance/lance.c new file mode 100644 index 000000000..3cabb6a7f --- /dev/null +++ b/private/ntos/ndis/lance/lance.c @@ -0,0 +1,4974 @@ +/*++ + +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 +#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); +} + + + diff --git a/private/ntos/ndis/lance/lance.rc b/private/ntos/ndis/lance/lance.rc new file mode 100644 index 000000000..8cf50295c --- /dev/null +++ b/private/ntos/ndis/lance/lance.rc @@ -0,0 +1,39 @@ +#include +#include + +/*-----------------------------------------------*/ +/* the following lines are specific to this file */ +/*-----------------------------------------------*/ + +/* VER_FILETYPE, VER_FILESUBTYPE, VER_FILEDESCRIPTION_STR + * and VER_INTERNALNAME_STR must be defined before including COMMON.VER + * The strings don't need a '\0', since common.ver has them. + */ +#define VER_FILETYPE VFT_DRV +/* possible values: VFT_UNKNOWN + VFT_APP + VFT_DLL + VFT_DRV + VFT_FONT + VFT_VXD + VFT_STATIC_LIB +*/ +#define VER_FILESUBTYPE VFT2_DRV_NETWORK +/* possible values VFT2_UNKNOWN + VFT2_DRV_PRINTER + VFT2_DRV_KEYBOARD + VFT2_DRV_LANGUAGE + VFT2_DRV_DISPLAY + VFT2_DRV_MOUSE + VFT2_DRV_NETWORK + VFT2_DRV_SYSTEM + VFT2_DRV_INSTALLABLE + VFT2_DRV_SOUND + VFT2_DRV_COMM +*/ +#define VER_FILEDESCRIPTION_STR "DEC Etherworks network driver" +#define VER_INTERNALNAME_STR "LANCE.SYS" +#define VER_ORIGINALFILENAME_STR "LANCE.SYS" + +#include "common.ver" + diff --git a/private/ntos/ndis/lance/lancehrd.h b/private/ntos/ndis/lance/lancehrd.h new file mode 100644 index 000000000..1a9f3c48e --- /dev/null +++ b/private/ntos/ndis/lance/lancehrd.h @@ -0,0 +1,479 @@ +/*++ + +Copyright (c) 1990 Microsoft Corporation + +Module Name: + + lance.c + +Abstract: + + The main program for a LANCE (Local Area Network Controller + Am 7990) MAC driver. + +Author: + + Anthony V. Ercolano (tonye) creation-date 19-Jun-1990 + +Environment: + + This driver is expected to work in DOS, OS2 and NT at the equivalent + of kernal mode. + + Architecturally, there is an assumption in this driver that we are + on a little endian machine. + +Notes: + + optional-notes + +Revision History: + + 31-Jul-1992 R.D. Lanser: + Removed system implementation dependent defines for the DEC + TurboChannel option PMAD-AA (Lance ethernet). + +--*/ + +#ifndef _LANCEHARDWARE_ +#define _LANCEHARDWARE_ + +// +// Compressed ID for DE422 EISA adapter +// + +#define DE422_COMPRESSED_ID 0x2042a310 + +// +// All registers on the LANCE are 16 bits. +// + +#define LANCE_SELECT_CSR0 ((USHORT)0) +#define LANCE_SELECT_CSR1 ((USHORT)1) +#define LANCE_SELECT_CSR2 ((USHORT)2) +#define LANCE_SELECT_CSR3 ((USHORT)3) + +#define LANCE_CSR0_INITIALIZE ((USHORT)(0x0001)) +#define LANCE_CSR0_START ((USHORT)(0x0002)) +#define LANCE_CSR0_STOP ((USHORT)(0x0004)) +#define LANCE_CSR0_TRANSMIT_DEMAND ((USHORT)(0x0008)) +#define LANCE_CSR0_TRANSMITTER_ON ((USHORT)(0x0010)) +#define LANCE_CSR0_RECEIVER_ON ((USHORT)(0x0020)) +#define LANCE_CSR0_INTERRUPT_ENABLE ((USHORT)(0x0040)) +#define LANCE_CSR0_INTERRUPT_FLAG ((USHORT)(0x0080)) +#define LANCE_CSR0_INITIALIZATION_DONE ((USHORT)(0x0100)) +#define LANCE_CSR0_TRANSMITTER_INTERRUPT ((USHORT)(0x0200)) +#define LANCE_CSR0_RECEIVER_INTERRUPT ((USHORT)(0x0400)) +#define LANCE_CSR0_MEMORY_ERROR ((USHORT)(0x0800)) +#define LANCE_CSR0_MISSED_PACKET ((USHORT)(0x1000)) +#define LANCE_CSR0_COLLISION_ERROR ((USHORT)(0x2000)) +#define LANCE_CSR0_BABBLE ((USHORT)(0x4000)) +#define LANCE_CSR0_ERROR_SUMMARY ((USHORT)(0x8000)) +#define LANCE_CSR0_ERROR_BITS ((USHORT)(0xf800)) + + +// +// We define a constant csr3 value that is useful for setting the ACON +// bit in csr3. +// +#define LANCE_CSR3_ACON ((USHORT)0x02) + + +#define LANCE_NICSR_LED_ON ((USHORT)(0x0001)) +#define LANCE_NICSR_INT_ON ((USHORT)(0x0002)) +#define LANCE_NICSR_IMASK ((USHORT)(0x0004)) +#define LANCE_NICSR_128K ((USHORT)(0x0008)) +#define LANCE_NICSR_BUFFER_SIZE ((USHORT)(0x0020)) + + +// +// Definitions for the many different lance card types. +// + +#define LANCE_DEPCA_INTERRUPT_VECTOR 5 +#define LANCE_DEPCA_INTERRUPT_IRQL 5 + +#define LANCE_DE201_INTERRUPT_VECTOR ((CCHAR)5) +#define LANCE_DE201_INTERRUPT_IRQL LANCE_DE201_INTERRUPT_VECTOR + +#define LANCE_DE100_INTERRUPT_VECTOR ((CCHAR)3) +#define LANCE_DE100_INTERRUPT_IRQL LANCE_DE100_INTERRUPT_VECTOR + + + + +#define LANCE_DEPCA_HARDWARE_MEMORY (0x10000) // 64K +#define LANCE_DEPCA_NICSR_ADDRESS ((ULONG)(0x200)) +#define LANCE_DEPCA_BASE ((PVOID)(0xD0000)) +#define LANCE_DEPCA_RAP_OFFSET ((ULONG)(0x006)) +#define LANCE_DEPCA_RDP_OFFSET ((ULONG)(0x004)) +#define LANCE_DEPCA_EPROM_OFFSET ((ULONG)(0x00c)) +#define LANCE_DEPCA_LAN_CFG_OFFSET ((ULONG)(0x600)) + +#define LANCE_DE201_HARDWARE_MEMORY (0x10000) // 64K +#define LANCE_DE201_BASE ((PVOID)(0xD0000)) + +#define LANCE_DE201_PRI_NICSR_ADDRESS ((ULONG)(0x300)) +#define LANCE_DE201_SEC_NICSR_ADDRESS ((ULONG)(0x200)) +#define LANCE_DE201_RAP_OFFSET ((ULONG)(0x006)) +#define LANCE_DE201_RDP_OFFSET ((ULONG)(0x004)) +#define LANCE_DE201_NETWORK_OFFSET ((ULONG)(0x00C)) + +#define LANCE_DE422_NICSR_ADDRESS ((ULONG)(0xC00)) +#define LANCE_DE422_RAP_OFFSET ((ULONG)(0x006)) +#define LANCE_DE422_RDP_OFFSET ((ULONG)(0x004)) +#define LANCE_DE422_NETWORK_OFFSET ((ULONG)(0x00C)) +#define LANCE_DE422_EISA_CONFIGURATION_OFFSET ((ULONG)(0x00C)) +#define LANCE_DE422_EXTENDED_MEMORY_BASE_OFFSET ((ULONG)(0x008)) +#define LANCE_DE422_EISA_IDENTIFICATION_OFFSET ((ULONG)(0x080)) +#define LANCE_DE422_EISA_CONTROL_OFFSET ((ULONG)(0x084)) + + + + + +#define LANCE_NUMBER_OF_TRANSMIT_RINGS ((UINT)64) +#define LANCE_LOG_TRANSMIT_RINGS ((UINT)6) + +#define LANCE_128K_NUMBER_OF_RECEIVE_RINGS ((UINT)128) +#define LANCE_128K_LOG_RECEIVE_RINGS ((UINT)7) + +#define LANCE_64K_NUMBER_OF_RECEIVE_RINGS ((UINT)128) +#define LANCE_64K_LOG_RECEIVE_RINGS ((UINT)7) + +#define LANCE_32K_NUMBER_OF_RECEIVE_RINGS ((UINT)32) +#define LANCE_32K_LOG_RECEIVE_RINGS ((UINT)5) + +#define LANCE_32K_SIZE_OF_RECEIVE_BUFFERS ((UINT)256) +#define LANCE_64K_SIZE_OF_RECEIVE_BUFFERS ((UINT)256) +#define LANCE_128K_SIZE_OF_RECEIVE_BUFFERS ((UINT)512) + +// +// Note: The value of LANCE_SIZE_OF_RECEIVE_BUFFERS should always be the +// largest of the receive buffers sizes. At this time, it is 512 +// for the DEC TurboChannel card. If this size changes, recompile +// loopback.c. +// +#define LANCE_SIZE_OF_RECEIVE_BUFFERS ((UINT)256) +#ifndef i386 +#define LANCE_LOOPBACK_SIZE_OF_RECEIVE_BUFFERS ((UINT)512) +#else +#define LANCE_LOOPBACK_SIZE_OF_RECEIVE_BUFFERS LANCE_SIZE_OF_RECEIVE_BUFFERS +#endif + + +#define LANCE_SMALL_BUFFER_SIZE ((UINT)64) +#define LANCE_MEDIUM_BUFFER_SIZE ((UINT)256) +#define LANCE_LARGE_BUFFER_SIZE ((UINT)1514) + +#define LANCE_128K_NUMBER_OF_SMALL_BUFFERS ((UINT)100) +#define LANCE_128K_NUMBER_OF_MEDIUM_BUFFERS ((UINT)50) +#define LANCE_128K_NUMBER_OF_LARGE_BUFFERS ((UINT)20) + +#define LANCE_64K_NUMBER_OF_SMALL_BUFFERS ((UINT)10) +#define LANCE_64K_NUMBER_OF_MEDIUM_BUFFERS ((UINT)10) +#define LANCE_64K_NUMBER_OF_LARGE_BUFFERS ((UINT)4) + +#define LANCE_32K_NUMBER_OF_SMALL_BUFFERS ((UINT)10) +#define LANCE_32K_NUMBER_OF_MEDIUM_BUFFERS ((UINT)10) +#define LANCE_32K_NUMBER_OF_LARGE_BUFFERS ((UINT)2) + + +#define LANCE_ISR_WRITE_RAP(A,C) NdisRawWritePortUshort((ULONG)((A)->RAP),C) +#define LANCE_ISR_READ_RDP(A,C) NdisRawReadPortUshort((ULONG)((A)->RDP),C) +#define LANCE_ISR_WRITE_RDP(A,C) NdisRawWritePortUshort((ULONG)((A)->RDP),C) +#define LANCE_ISR_WRITE_NICSR(A,C) NdisRawWritePortUshort((ULONG)((A)->Nicsr),C) + + +#define LANCE_GET_LOW_PART_ADDRESS(Adr) \ + ((USHORT)((Adr) & 0xffff)) + +#define LANCE_GET_HIGH_PART_ADDRESS(Adr) \ + ((UCHAR)((Adr) & 0xff0000) >> 16) + +typedef struct _LANCE_INITIALIZATION_BLOCK { + + USHORT ModeRegister; + UCHAR PhysicalAddress[6]; + UCHAR LogicalAddressFilter[8]; + USHORT LowReceiveRingAddress; + UCHAR HighReceiveRingAddress; + UCHAR ReceiveLengthLow5BitsReserved; + USHORT LowTransmitRingAddress; + UCHAR HighTransmitRingAddress; + UCHAR TransmitLengthLow5BitsReserved; + +} LANCE_INITIALIZATION_BLOCK,*PLANCE_INITIALIZATION_BLOCK; + +// +// Define masks to access bits in the mode register of the initialization +// block. +// +#define LANCE_MODE_PROMISCUOUS ((USHORT)(0x8000)) + +// +// Defines for moving to/from shared memory. +// + + +#define LANCE_ZERO_MEMORY_FOR_HARDWARE(Destination,Length) \ + NdisZeroMappedMemory(Destination,Length) + +#define LANCE_MOVE_STRUCT_TO_HARDWARE(Destination,Source) \ + NdisMoveToMappedMemory(&(Destination), &(Source), sizeof(Source)) + +#define LANCE_MOVE_MEMORY_TO_HARDWARE(Destination,Source,Length) \ + NdisMoveToMappedMemory(Destination, Source, Length) + +#define LANCE_MOVE_HARDWARE_TO_MEMORY(Destination,Source,Length) \ + NdisMoveFromMappedMemory(Destination, Source, Length) + +#define LANCE_WRITE_HARDWARE_LOW_PART_ADDRESS(Destination, Source) \ + NdisWriteRegisterUshort((PUSHORT)(&Destination), (USHORT)(Source)) + +#define LANCE_WRITE_HARDWARE_HIGH_PART_ADDRESS(Destination, Source) \ + NdisWriteRegisterUchar((PUCHAR)(&Destination), (UCHAR)(Source)) + +#define LANCE_WRITE_HARDWARE_MEMORY_UCHAR(Destination, Source) \ + NdisWriteRegisterUchar((PUCHAR)(&Destination), (UCHAR)(Source)) + +#define LANCE_WRITE_HARDWARE_MEMORY_USHORT(Destination, Source) \ + NdisWriteRegisterUshort((PUSHORT)(&Destination), (USHORT)(Source)) + +#define LANCE_READ_HARDWARE_MEMORY_UCHAR(Source, Destination) \ + NdisReadRegisterUchar((PUCHAR)(&Source), Destination) + +#define LANCE_READ_HARDWARE_MEMORY_USHORT(Source, Destination) \ + NdisReadRegisterUshort((PUSHORT)(&Source), Destination) + +#if defined(_ALPHA_) + +#define LANCE_SET_RING_BITS(Destination, Data) \ +{ \ + UCHAR Tmp; \ + LANCE_READ_HARDWARE_MEMORY_UCHAR(Destination, &Tmp); \ + LANCE_WRITE_HARDWARE_MEMORY_UCHAR(Destination, Tmp | Data); \ +} + +#else + +#define LANCE_SET_RING_BITS(Destination, Data) (Destination) |= ((Data)) + +#endif // _ALPHA_ + +typedef struct _LANCE_RECEIVE_ENTRY { + + // + // 24 bit pointer to the buffer for the receive + // data. This is written by the host and unchanged + // by the LANCE. + // + USHORT LowReceiveBufferAddress; + UCHAR HighReceiveBufferAddress; + + // + // This char field contains numerous bits describing + // the errors that can occur in the packet as well as + // whether this is the first and/or last buffer in the packet. + // + UCHAR ReceiveSummaryBits; + + // + // This is the twos compliment of the buffer length. + // + // NOTE: The high order 4 bits must be enabled. + // + USHORT BufferByteCount; + + // + // This is the length of the data in the packet. + // + // Note that the high order 4 bits are undefined. + // + USHORT MessageLength; + +} LANCE_RECEIVE_ENTRY,*PLANCE_RECEIVE_ENTRY; + +// +// A number of macros that make accessing the various bits of the receive +// ring entry a little easier as well as providing some validity checks. +// + +// +// Used to set the address of the receive buffer. +// +// Rd is a pointer to a receive descriptor. +// +// Adr is a *physical* address. +// +// +#define LANCE_SET_RECEIVE_BUFFER_ADDRESS(Adptr,Rd,Adr) \ +{ \ + PVOID _Adr = (Adr); \ + PLANCE_ADAPTER _Adptr = (Adptr);\ + PLANCE_RECEIVE_ENTRY _Rd = (Rd); \ + ULONG _Offset;\ + _Offset = (ULONG)_Adr - (ULONG)(_Adptr->MmMappedBaseAddr);\ + _Offset = _Offset + (ULONG)(_Adptr->HardwareBaseOffset);\ + LANCE_WRITE_HARDWARE_LOW_PART_ADDRESS(\ + _Rd->LowReceiveBufferAddress,\ + (USHORT)((ULONG)_Offset) & 0xffff); \ + LANCE_WRITE_HARDWARE_HIGH_PART_ADDRESS(\ + _Rd->HighReceiveBufferAddress,\ + (UCHAR)(((ULONG)_Offset) >> 16) & 0xff); \ +} + + +// +// Used to set the length of the receive buffer. The stored value +// is actually the twos compliment of the length. Note that +// the twos complement of this value must have the high order 4 bits +// enabled. +// +// Rd is a pointer to a receive descriptor. +// +// Len is the unsigned short length of the buffer. +// +#define LANCE_SET_RECEIVE_BUFFER_LENGTH(Rd,Len) \ + LANCE_WRITE_HARDWARE_MEMORY_USHORT(\ + Rd->BufferByteCount,\ + (USHORT)((~Len)+1)\ + ) + +// +// Masks for the summary bits in the receive descriptor. +// +#define LANCE_RECEIVE_END_OF_PACKET ((UCHAR)0x01) +#define LANCE_RECEIVE_START_OF_PACKET ((UCHAR)0x02) +#define LANCE_RECEIVE_BUFFER_ERROR ((UCHAR)0x04) +#define LANCE_RECEIVE_CRC_ERROR ((UCHAR)0x08) +#define LANCE_RECEIVE_OVERFLOW_ERROR ((UCHAR)0x10) +#define LANCE_RECEIVE_FRAMING_ERROR ((UCHAR)0x20) +#define LANCE_RECEIVE_ERROR_SUMMARY ((UCHAR)0x40) +#define LANCE_RECEIVE_OWNED_BY_CHIP ((UCHAR)0x80) + +// +// This macro gets the packet message length from what is +// assumed to be the last buffer in a packet. Note that +// on the lance the length of the data includes the four +// byte CRC so we must subtract four from length in the +// ring entry. +// +// Rd is a pointer to a receive descriptor. +// Value is the place to store the result. +// +#if defined(_ALPHA_) + +#define LANCE_GET_MESSAGE_SIZE(Rd, Value) \ +{ \ + NdisReadRegisterUshort( \ + ((ULONG)Rd + FIELD_OFFSET(LANCE_RECEIVE_ENTRY, MessageLength)), \ + &Value \ + ); \ + Value = (Value & ((USHORT)0x0fff)) -4; \ +} + + +#else + +#define LANCE_GET_MESSAGE_SIZE(Rd, Value) \ + Value = (((Rd->MessageLength) & ((USHORT)0x0fff))-4) + +#endif // _ALPHA_ + +typedef struct _LANCE_TRANSMIT_ENTRY { + + // + // 24 bit pointer to the transmit buffer. This is + // written by the host and unchanged by the LANCE. + // + USHORT LowTransmitBufferAddress; + UCHAR HighTransmitBufferAddress; + + // + // This field contains summary information about the packet. + // + UCHAR TransmitSummaryBits; + + // + // This field contains the "twos complement" of the length + // of the buffer. + // + // NOTE: The high order four bits must be enabled. + // + USHORT BufferByteCount; + + // + // This short contains the error summary information for the + // ring entry. + // + USHORT ErrorSummaryInfo; + +} LANCE_TRANSMIT_ENTRY,*PLANCE_TRANSMIT_ENTRY; + +// +// Masks for the normal summary bits in the transmit descriptor. +// +#define LANCE_TRANSMIT_END_OF_PACKET ((UCHAR)(0x01)) +#define LANCE_TRANSMIT_START_OF_PACKET ((UCHAR)(0x02)) +#define LANCE_TRANSMIT_DEFERRED ((UCHAR)(0x04)) +#define LANCE_TRANSMIT_ONE_RETRY ((UCHAR)(0x08)) +#define LANCE_TRANSMIT_MORE_THAN_ONE_RETRY ((UCHAR)(0x10)) +#define LANCE_TRANSMIT_ANY_ERRORS ((UCHAR)(0x40)) +#define LANCE_TRANSMIT_OWNED_BY_CHIP ((UCHAR)(0x80)) + +// +// Set of masks to recover particular errors that a transmit can encounter. +// +#define LANCE_TRANSMIT_TDR ((USHORT)(0x03ff)) +#define LANCE_TRANSMIT_RETRY ((USHORT)(0x0400)) +#define LANCE_TRANSMIT_LOST_CARRIER ((USHORT)(0x0800)) +#define LANCE_TRANSMIT_LATE_COLLISION ((USHORT)(0x0100)) +#define LANCE_TRANSMIT_UNDERFLOW ((USHORT)(0x4000)) +#define LANCE_TRANSMIT_BUFFER ((USHORT)(0x8000)) + +// +// Used to set the address of the transmit buffer. +// +// Rd is a pointer to a transmit descriptor. +// +// Adr is a *physical* address. +// +// + +#define LANCE_SET_TRANSMIT_BUFFER_ADDRESS(Adptr,Td,Adr) \ +{ \ + PVOID _Adr = (Adr); \ + PLANCE_TRANSMIT_ENTRY _Td = (Td); \ + ULONG _Offset;\ + PLANCE_ADAPTER _Adptr = (Adptr);\ + _Offset = (ULONG)_Adr - (ULONG)(_Adptr->MmMappedBaseAddr);\ + _Offset = _Offset + (ULONG)(_Adptr->HardwareBaseOffset);\ + LANCE_WRITE_HARDWARE_LOW_PART_ADDRESS(\ + _Td->LowTransmitBufferAddress,\ + (USHORT)(((ULONG)_Offset) & 0xffff)\ + );\ + LANCE_WRITE_HARDWARE_HIGH_PART_ADDRESS(\ + _Td->HighTransmitBufferAddress,\ + (UCHAR)((((ULONG)_Offset) >> 16) & 0xff)\ + );\ +} + + +// +// Used to set the length of the transmit buffer. The stored value +// is actually the twos compliment of the length. Note that +// the twos complement of this value must have the high order 4 bits +// enabled. +// +// Td is a pointer to a transmit descriptor. +// +// Len is the unsigned short length of the buffer. +// +#define LANCE_SET_TRANSMIT_BUFFER_LENGTH(Td,Len) \ + LANCE_WRITE_HARDWARE_MEMORY_USHORT(\ + Td->BufferByteCount,\ + (USHORT)((~Len)+1)\ + ) + +#endif // _LANCEHARDWARE_ diff --git a/private/ntos/ndis/lance/lancesft.h b/private/ntos/ndis/lance/lancesft.h new file mode 100644 index 000000000..945b21687 --- /dev/null +++ b/private/ntos/ndis/lance/lancesft.h @@ -0,0 +1,962 @@ +/*++ + +Copyright (c) 1990 Microsoft Corporation + +Module Name: + + lancesft.h + +Abstract: + + The main header for a LANCE (Local Area Network Controller + Am 7990) MAC driver. + +Author: + + Anthony V. Ercolano (tonye) creation-date 19-Jun-1990 + +Environment: + + This driver is expected to work in DOS, OS2 and NT at the equivalent + of kernal mode. + + Architecturally, there is an assumption in this driver that we are + on a little endian machine. + +Notes: + + optional-notes + +Revision History: + + 31-Jul-1992 R.D. Lanser: + + Changed DECST card type to DECTC for the DEC TurboChannel option + PMAD-AA (Lance ethernet). This option will be available for all + TurboChannel systems regardless of CPU type or system. + + Added InterruptRequestLevel to the _LANCE_ADAPTER structure because + 'lance.c' was passing the InterruptVector as the IRQL to the interrupt + connect routine which is not correct. This works on JAZZ because the + JAZZ HalGetInterruptVector is hardcoded to return a fixed IRQL for + EISA devices. + + Removed PhysicalBuffersContained and UsedLanceBuffer field from + _ADAPTER structure. SeanSe says that the code related to this + field was used for adevice that is no longer supported. I removed + the dependent code(or at least what was obvious) from 'send.c'. + +--*/ + +#ifndef _LANCESFT_ +#define _LANCESFT_ + +#define LANCE_NDIS_MAJOR_VERSION 3 +#define LANCE_NDIS_MINOR_VERSION 0 + +#if DBG + +#define LANCELOG 1 +#define LANCE_TRACE 0 + +#else + +#define LANCELOG 0 +#define LANCE_TRACE 0 + +#endif + +#if LANCELOG + +#define LOG_SIZE 256 + +#define TIMER '.' +#define IN_ISR 'i' +#define OUT_ISR 'I' +#define IN_DPC 'd' +#define OUT_DPC 'D' +#define RECEIVE 'R' +#define TRANSMIT 'x' +#define TRANSMIT_COMPLETE 'X' +#define PEND 'p' +#define UNPEND 'P' +#define INDICATE 'r' +#define IN_SEND 's' +#define OUT_SEND 'S' +#define START 'G' +#define RESET_STEP_1 '1' +#define RESET_STEP_2 '2' +#define RESET_SAVE_PACKET 'b' +#define RESET_RECOVER_PACKET 'B' +#define RESET_COMPLETE_PACKET 'c' +#define RESET_STEP_3 '3' +#define REMOVE 'V' +#define CLOSE 'C' +#define UNLOAD 'U' + + + +extern UCHAR Log[LOG_SIZE]; + +extern UCHAR LogPlace; +extern UCHAR LogWrapped; + + + +#define LOG(c) { Log[LogPlace] = (c); Log[(LogPlace+3) % 255] ='\0'; \ + LogPlace = (LogPlace + 1) % 255; } + +#else + +#define LOG(c) + +#endif + + + +extern NDIS_PHYSICAL_ADDRESS HighestAcceptableMax; + +// +// ZZZ These macros are peculiar to NT. +// + +#define LANCE_ALLOC_PHYS(pp, s) NdisAllocateMemory((PVOID *)(pp),(s),0,HighestAcceptableMax) +#define LANCE_FREE_PHYS(p, s) NdisFreeMemory((PVOID)(p),(s),0) +#define LANCE_MOVE_MEMORY(Destination,Source,Length) NdisMoveMemory(Destination,Source,Length) +#define LANCE_ZERO_MEMORY(Destination,Length) NdisZeroMemory(Destination,Length) + + + +// +// Definitions for all the different card types. +// + + +#define LANCE_DE100 0x01 // DE100 card +#define LANCE_DE201 0x02 // DE201 card +#define LANCE_DEPCA 0x04 // Card in a Dec PC x86 machine +#define LANCE_DECST 0x08 // Card in a decstation +#define LANCE_DE422 0x10 // DE422 card +#define LANCE_DECTC 0x20 // TurboChannel PMAD-AA option + +#define LANCE_DE100_NAME LANCE_DEFAULT_NAME +#define LANCE_DE201_NAME LANCE_DEFAULT_NAME +#define LANCE_DEPCA_NAME LANCE_DEFAULT_NAME +#define LANCE_DECST_NAME LANCE_DEFAULT_NAME +#define LANCE_DE422_NAME LANCE_DEFAULT_NAME +#define LANCE_DECTC_NAME LANCE_DEFAULT_NAME +#define LANCE_DEFAULT_NAME "\\Device\\Lance01" + + +// +// This structure is passed as context from the receive interrupt +// processor. Eventually it will be used as a parameter to +// LanceTransferData. LanceTransferData can get two kinds of +// context. It will receive either an ndis packet or it will +// receive a LANCE_RECEIVE_CONTEXT. It will be able to tell +// the difference since the LANCE_RECEIVE_CONTEXT will have +// its low bit set. No pointer to an ndis packet can have its low +// bit set. +// +typedef union _LANCE_RECEIVE_CONTEXT { + + UINT WholeThing; + struct _INFO { + // + // Used to mark that this is context rather than a pointer + // to a packet. + // + UINT IsContext:1; + + // + // The first receive ring descriptor used to hold the packet. + // + UINT FirstBuffer:7; + + // + // The last receive ring descriptor used to hold the packet. + // + UINT LastBuffer:7; + } INFO; + +} LANCE_RECEIVE_CONTEXT,*PLANCE_RECEIVE_CONTEXT; + + + + + + +// +// This record type is inserted into the MacReserved portion +// of the packet header when the packet is going through the +// staged allocation of buffer space prior to the actual send. +// +typedef struct _LANCE_RESERVED { + + // + // Points to the next packet in the chain of queued packets + // being allocated, loopbacked, or waiting for the finish + // of transmission. + // + // The packet will either be on the stage list for allocation, + // the loopback list for loopback processing, on an adapter + // wide doubly linked list (see below) for post transmission + // processing. + // + // We always keep the packet on a list so that in case the + // the adapter is closing down or resetting, all the packets + // can easily be located and "canceled". + // + PNDIS_PACKET Next; + + // + // This gives the index into the array of adapter buffer + // descriptors that contains the packet information. + // + USHORT LanceBuffersIndex; + + // + // When the hardware send is done this will record whether + // the send was successful or not. + // + BOOLEAN SuccessfulTransmit; + +} LANCE_RESERVED,*PLANCE_RESERVED; + +// +// This macro will return a pointer to the lance reserved portion +// of a packet given a pointer to a packet. +// +#define PLANCE_RESERVED_FROM_PACKET(Packet) \ + ((PLANCE_RESERVED)((Packet)->MacReserved)) + +// +// This structure is used to map entries in the ring descriptors +// back to the packets from which the data in the ring descriptor +// originated. +// + +typedef struct _LANCE_RING_TO_PACKET { + + // + // Points to the packet from which data is being transmitted + // through this ring entry. + // + PNDIS_PACKET OwningPacket; + + // + // Index of the ring entry that is being used by the packet. + // + UINT RingIndex; + + // + // When a packet is submitted to the hardware we record + // here whether it used adapter buffers and if so, the buffer + // index. + // + UINT LanceBuffersIndex; + +} LANCE_RING_TO_PACKET,*PLANCE_RING_TO_PACKET; + +// +// If an ndis packet does not meet the hardware contraints then +// an adapter buffer will be allocated. Enough data will be copied +// out of the ndis packet so that by using a combination of the +// adapter buffer and remaining ndis buffers the hardware +// constraints are satisfied. +// +// In the LANCE_ADAPTER structure three threaded lists are kept in +// one array. One points to a list of LANCE_BUFFER_DESCRIPTORS +// that point to small adapter buffers. Another is for medium sized +// buffers and the last for full sized (large) buffers. +// +// The allocation is controlled via a free list head and +// the free lists are "threaded" by a field in the adapter buffer +// descriptor. +// +typedef struct _LANCE_BUFFER_DESCRIPTOR { + + // + // A virtual pointer to a small, medium, or large buffer. + // + PVOID VirtualLanceBuffer; + + // + // Threads the elements of an array of these descriptors into + // a free list. -1 implies no more entries in the list. + // + INT Next; + + // + // Holds the amount of space (in bytes) available in the buffer + // + UINT BufferSize; + + // + // Holds the length of data placed into the buffer. This + // can (and likely will) be less that the actual buffers + // length. + // + UINT DataLength; + +} LANCE_BUFFER_DESCRIPTOR,*PLANCE_BUFFER_DESCRIPTOR; + + +#define LANCE_LENGTH_OF_ADDRESS 6 + +// +// Define the size of the ethernet header. +// +#define LANCE_HEADER_SIZE 14 + +// +// Define Maximum number of bytes a protocol can read during a +// receive data indication. +// +#define LANCE_MAX_LOOKAHEAD ( 248 - LANCE_HEADER_SIZE ) + + + + + +typedef struct _LANCE_ADAPTER { + + // + // The card type of this adapter. + // + UCHAR LanceCard; + + // + // Holds the interrupt object for this adapter. + // + NDIS_MINIPORT_INTERRUPT Interrupt; + + NDIS_MINIPORT_TIMER DeferredTimer; + + // + // Non OS fields of the adapter. + // + + // + // Contains Address first byte of adapter memory is mapped to. + // + PVOID MmMappedBaseAddr; + + // + // Contains address of the hardware memory. + // + PVOID HardwareBaseAddr; + + // + // Offset for Init block from the Lance chip's point of view. + // + ULONG HardwareBaseOffset; + + // + // Amount of memory + // + ULONG AmountOfHardwareMemory; + + // + // For lance implementation that uses dual ported memory this + // field is used to point to the first available memory. + // + PVOID CurrentMemoryFirstFree; + + // + // Address of the first byte following the memory. + // + PVOID MemoryFirstUnavailable; + + // + // Physical address of base io port address + // + ULONG IoBaseAddr; + + // + // Pointer to the RAP register. + // + ULONG RAP; + + // + // Pointer to the RDP register. + // + ULONG RDP; + + // + // Pointer to the NICSR register. + // + ULONG Nicsr; + + // + // Slot Number the De422 is in. + // + UINT SlotNumber; + + // + // Default information to add to the NICSR register value + // + USHORT NicsrDefaultValue; + + // + // Have the interrupts from the card been turned off. + // + BOOLEAN InterruptsStopped; + + // + // Address in memory of the network address + // + ULONG NetworkHardwareAddress; + + // + // The network address from the hardware. + // + CHAR NetworkAddress[LANCE_LENGTH_OF_ADDRESS]; + + // + // The network address from the hardware. + // + CHAR CurrentNetworkAddress[LANCE_LENGTH_OF_ADDRESS]; + + // + // Interrupt number + // + CCHAR InterruptNumber; + + // + // IRQL + // + CCHAR InterruptRequestLevel; + + // + // Holds the number of transmit ring entries. + // + // NOTE NOTE NOTE + // + // There is code that depends on the number of transmit entries + // being a power of two. + // + UINT NumberOfTransmitRings; + + // + // Holds the number of receive ring entries. + // + UINT NumberOfReceiveRings; + + // + // Holds the size of receive buffers. + // + UINT SizeOfReceiveBuffer; + + // + // Holds number of each buffer size. + // + UINT NumberOfSmallBuffers; + UINT NumberOfMediumBuffers; + UINT NumberOfLargeBuffers; + + // + // The log base two of the number of transmit ring entries. + // + UINT LogNumberTransmitRings; + + // + // The log base two of the number of receive ring entries. + // + UINT LogNumberReceiveRings; + + // + // Handle given by NDIS when the MAC registered itself. + // + NDIS_HANDLE NdisDriverHandle; + + // + // Handle given by NDIS when the adapter was registered. + // + NDIS_HANDLE MiniportAdapterHandle; + + // + // Pointer to the LANCE initialization block. + // + PLANCE_INITIALIZATION_BLOCK InitBlock; + + // + // Counter that records the number of transmit rings currently + // available for allocation. + // + UINT NumberOfAvailableRings; + + // + // Pointer to transmit descriptor ring entry that is the + // first ring entry available for allocation of transmit + // buffers. + // + // Can only be accessed when the adapter lock + // is held. + // + PLANCE_TRANSMIT_ENTRY AllocateableRing; + + // + // Pointer to a transmit descriptor ring entry that is the + // first ring entry that the MAC currently has made available + // for transmission. + // + // Can only be accessed when the adapter lock + // is held. + // + PLANCE_TRANSMIT_ENTRY TransmittingRing; + + // + // Pointer to the first packet that has been allocated to + // a transmit packet but has not yet been relinquished to + // the hardware. We need this pointer to keep the transmit + // post processing from running into a packet that has not + // been transmitted. + // + PLANCE_TRANSMIT_ENTRY FirstUncommittedRing; + + // + // Pointer to an array of structs that map transmit ring entries + // back to a packet. + // + PLANCE_RING_TO_PACKET RingToPacket; + + // + // Pointer to the transmit ring. + // + PLANCE_TRANSMIT_ENTRY TransmitRing; + + // + // Pointer to the last transmit ring entry. + // + PLANCE_TRANSMIT_ENTRY LastTransmitRingEntry; + + // + // Pointer to the receive ring. + // + PLANCE_RECEIVE_ENTRY ReceiveRing; + + // + // Listheads for the adapters buffers. If the list + // head is equal to -1 then there are no free elements + // on the list. + // + // The list heads must only be accessed when the + // adapter lock is held. + // + // Note that the listhead at index 0 will always be -1. + // + INT LanceBufferListHeads[4]; + + // + // Pointers to an array of adapter buffer descriptors. + // The array will actually be threaded together by + // three free lists. The lists will be for small, + // medium and full sized packets. + // + PLANCE_BUFFER_DESCRIPTOR LanceBuffers; + + // + // Did we indicate a packet? Used to tell if NdisIndicateReceiveComplete + // should be called. + // + BOOLEAN IndicatedAPacket; + + // + // Pointer to an array of virtual addresses that describe + // the virtual address of each receive ring descriptor buffer. + // + PVOID *ReceiveVAs; + + // + // Index of the receive ring descriptor that started the + // last packet not completely received by the hardware. + // + UINT CurrentReceiveIndex; + + // + // Counters to hold the various number of errors/statistics for both + // reception and transmission. + // + // Can only be accessed when the adapter lock is held. + // + UINT OutOfReceiveBuffers; + UINT CRCError; + UINT FramingError; + UINT RetryFailure; + UINT LostCarrier; + UINT LateCollision; + UINT UnderFlow; + UINT Deferred; + UINT OneRetry; + UINT MoreThanOneRetry; + + // + // Holds counts of more global errors for the driver. If we + // get a memory error then the device needs to be reset. + // + UINT MemoryError; + UINT Babble; + UINT MissedPacket; + + // + // Holds other cool counts. + // + + ULONG Transmit; + ULONG Receive; + + // + // Flag that when enabled lets routines know that a reset + // is in progress. + // + BOOLEAN ResetInProgress; + + // + // Flag that when enabled lets routines know that a reset + // is in progress and the initialization needs doing. + // + BOOLEAN ResetInitStarted; + + // + // The type of the request that caused the adapter to reset. + // + NDIS_REQUEST_TYPE ResetRequestType; + + // + // During an indication this is set to the current indications context + // + LANCE_RECEIVE_CONTEXT IndicatingMacReceiveContext; + + + // + // Look ahead information. + // + + ULONG MaxLookAhead; + + // + // Open information + // + UCHAR MaxMulticastList; + + // + // Will be true the first time that the hardware is initialized + // by the driver initialization. + // + BOOLEAN FirstInitialization; + + // + // Is the adapter being removed + // + BOOLEAN BeingRemoved; + + // + // Will be true if the hardware fails for some reason + // + BOOLEAN HardwareFailure; + + USHORT SavedMemBase; + UINT Reserved1; + UINT Reserved2; + // + // Lookahead buffer for loopback packets + // + UCHAR Lookahead[LANCE_MAX_LOOKAHEAD + LANCE_HEADER_SIZE]; + + UINT PacketFilter; + UINT NumberOfAddresses; + UCHAR MulticastAddresses[32][LANCE_LENGTH_OF_ADDRESS]; + +} LANCE_ADAPTER,*PLANCE_ADAPTER; + +// +// Given a MacContextHandle return the PLANCE_ADAPTER +// it represents. +// +#define PLANCE_ADAPTER_FROM_CONTEXT_HANDLE(Handle) \ + ((PLANCE_ADAPTER)(Handle)) + +// +// Given a pointer to a LANCE_ADAPTER return the +// proper MacContextHandle. +// +#define CONTEXT_HANDLE_FROM_PLANCE_ADAPTER(Ptr) \ + ((NDIS_HANDLE)(Ptr)) + +// +// This macro will act a "epilogue" to every routine in the +// *interface*. It will check whether any requests need +// to defer their processing. It will also decrement the reference +// count on the adapter. If the reference count is zero and there +// is deferred work to do it will insert the interrupt processing +// routine in the DPC queue. +// +// Note that we don't need to include checking for blocked receives +// since blocked receives imply that there will eventually be an +// interrupt. +// +// NOTE: This macro assumes that it is called with the lock acquired. +// +// ZZZ This routine is NT specific. +// +#define LANCE_DO_DEFERRED(Adapter) \ +{ \ + PLANCE_ADAPTER _A = (Adapter); \ + if (_A->ResetInProgress) { \ + NdisMSetTimer(&_A->DeferredTimer, 0);\ + } \ +} + + + + +// +// Procedures which log errors. +// + +typedef enum _LANCE_PROC_ID { + processInterrupt +} LANCE_PROC_ID; + + +#define LANCE_ERRMSG_NDIS_ALLOC_MEM (ULONG)0x01 + + + + + + + + + + + + + + +// +// This macro is used to "allocate" memory for the structures that +// must be shared with the hardware. It assigns a pvoid that is +// at least quadword aligned. +// +#define LANCE_ALLOCATE_MEMORY_FOR_HARDWARE(A,S,P) \ +{ \ + PLANCE_ADAPTER _Adapter = (A); \ + UINT _Size = (((S) + 7)/8)*8; \ + PVOID _HighWater; \ + if (!_Size) { \ + *(P) = NULL; \ + } else { \ + _HighWater = ((PCHAR)_Adapter->CurrentMemoryFirstFree) + _Size; \ + if (((PUCHAR)_HighWater) > \ + (((PUCHAR)_Adapter->MemoryFirstUnavailable) + 1)) { \ + *(P) = NULL; \ + } else { \ + *(P) = _Adapter->CurrentMemoryFirstFree; \ + _Adapter->CurrentMemoryFirstFree = _HighWater; \ + } \ + } \ +} + +// +// We now convert the virtual address to the actual physical address. +// +#define LANCE_GET_HARDWARE_PHYSICAL_ADDRESS(A,P) \ + (ULONG)((PCHAR)P - (PCHAR)(A)->MmMappedBaseAddr + (A)->HardwareBaseOffset) + +// +// This macro is used to "deallocate the memory from the hardware. +// Since this is hardware memory that is only allocated and deallocated +// once this macro really doesn't do anything. +// +#define LANCE_DEALLOCATE_MEMORY_FOR_HARDWARE(A,P)\ +{\ +} + + + + + +// +// These are routines for synchronizing with the ISR +// + + +// +// This structure is used to synchronize reading and writing to ports +// with the ISR. +// + +typedef struct _LANCE_SYNCH_CONTEXT { + + // + // Pointer to the lance adapter for which interrupts are + // being synchronized. + // + PLANCE_ADAPTER Adapter; + + // + // Pointer to a local variable that will receive the value + // + PUSHORT LocalRead; + + // + // Value to write + // + USHORT LocalWrite; + +} LANCE_SYNCH_CONTEXT,*PLANCE_SYNCH_CONTEXT; + + + +#define LANCE_WRITE_RAP(A,C) { \ + LANCE_ISR_WRITE_RAP(A,C);\ +} + + +#define LANCE_WRITE_RDP(A,C) { \ + LANCE_ISR_WRITE_RDP(A,C);\ +} + +#define LANCE_READ_RDP(A,C) { \ + LANCE_ISR_READ_RDP(A,C);\ +} + +#define LANCE_WRITE_NICSR(A,C) { \ + PLANCE_ADAPTER _A = A; \ + LANCE_SYNCH_CONTEXT _C; \ + _C.Adapter = _A; \ + _C.LocalWrite = (C | _A->NicsrDefaultValue); \ + NdisMSynchronizeWithInterrupt( \ + &(_A)->Interrupt, \ + LanceSyncWriteNicsr, \ + &_C \ + ); \ +} + +BOOLEAN +LanceSyncWriteNicsr( + IN PVOID Context + ); + +BOOLEAN +LanceSyncGetInterruptsStopped( + IN PVOID Context + ); + +BOOLEAN +LanceSyncStopChip( + IN PVOID Context + ); + + +// +// We define the external interfaces to the lance driver. +// These routines are only external to permit separate +// compilation. Given a truely fast compiler they could +// all reside in a single file and be static. +// + + +NDIS_STATUS +LanceTransferData( + OUT PNDIS_PACKET Packet, + OUT PUINT BytesTransferred, + IN NDIS_HANDLE MiniportAdapterContext, + IN NDIS_HANDLE MiniportReceiveContext, + IN UINT ByteOffset, + IN UINT BytesToTransfer + ); + +NDIS_STATUS +LanceSend( + IN NDIS_HANDLE MiniportAdapterContext, + IN PNDIS_PACKET Packet, + IN UINT Flags + ); + +extern +VOID +LanceStagedAllocation( + IN PLANCE_ADAPTER Adapter + ); + +extern +VOID +LanceCopyFromPacketToBuffer( + IN PNDIS_PACKET Packet, + IN UINT Offset, + IN UINT BytesToCopy, + OUT PCHAR Buffer, + OUT PUINT BytesCopied + ); + +extern +VOID +LanceCopyFromPacketToPacket( + IN PNDIS_PACKET Destination, + IN UINT DestinationOffset, + IN UINT BytesToCopy, + IN PNDIS_PACKET Source, + IN UINT SourceOffset, + OUT PUINT BytesCopied + ); + +extern +BOOLEAN +LanceHardwareDetails( + IN PLANCE_ADAPTER Adapter + ); + +extern +NDIS_STATUS +LanceRegisterAdapter( + IN PLANCE_ADAPTER Adapter + ); + +VOID +SetupAllocate( + IN PLANCE_ADAPTER Adapter, + IN NDIS_HANDLE MacBindingHandle, + IN PNDIS_PACKET Packet + ); + +VOID +LanceDisableInterrupt( + IN NDIS_HANDLE MiniportAdapterContext + ); + +VOID +LanceEnableInterrupt( + IN NDIS_HANDLE MiniportAdapterContext + ); + +VOID +LanceHalt( + IN PVOID MiniportAdapterContext + ); + +VOID +LanceHandleInterrupt( + IN NDIS_HANDLE Context + ); + +VOID +LanceIsr( + OUT PBOOLEAN InterruptRecognized, + OUT PBOOLEAN QueueDpc, + IN PVOID Context + ); + +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 + ); + +#endif // _LANCESFT_ diff --git a/private/ntos/ndis/lance/makefile b/private/ntos/ndis/lance/makefile new file mode 100644 index 000000000..6ee4f43fa --- /dev/null +++ b/private/ntos/ndis/lance/makefile @@ -0,0 +1,6 @@ +# +# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source +# file to this component. This file merely indirects to the real make file +# that is shared by all the components of NT OS/2 +# +!INCLUDE $(NTMAKEENV)\makefile.def diff --git a/private/ntos/ndis/lance/send.c b/private/ntos/ndis/lance/send.c new file mode 100644 index 000000000..8c7ca93bc --- /dev/null +++ b/private/ntos/ndis/lance/send.c @@ -0,0 +1,437 @@ +/*++ + +Copyright (c) 1990 Microsoft Corporation + +Module Name: + + send.c + +Abstract: + + This file contains the code for putting a packet through the + staged allocation for transmission. + + This is a process of + + 1) Calculating the what would need to be done to the + packet so that the packet can be transmitted on the hardware. + + 2) Potentially allocating adapter buffers and copying user data + to those buffers so that the packet data is transmitted under + the hardware constraints. + + 3) Allocating enough hardware ring entries so that the packet + can be transmitted. + + 4) Relinquish thos ring entries to the hardware. + +Author: + + Anthony V. Ercolano (Tonye) 12-Sept-1990 + +Environment: + + Kernel Mode - Or whatever is the equivalent on OS/2 and DOS. + +Revision History: + + 31-Jul-1992 R.D. Lanser: + + Removed PhysicalBuffersContained and UsedLanceBuffer field from + _ADAPTER structure. SeanSe says that the code related to this + field was used for adevice that is no longer supported. I removed + the dependent code(or at least what was obvious) from 'send.c'. + This old code was generating an erroneous ring buffer count on the + MIPS R3000. I did not test it on the MIPS R4000. The problem goes + away with the removal of the offending code. + +--*/ + +#include +#include +#include + + +// +// Minimum packet size that a transport can send. We subtract 4 bytes +// because we add a 4 byte CRC on the end. +// + +#define MIN_SINGLE_BUFFER ((UINT)LANCE_SMALL_BUFFER_SIZE - 4) + + +// +// It will poke the lance hardware into noticing that there is a packet +// available for transmit. +// +// Note that there is the assumption that the register address +// port (RAP) is already set to zero. +// +#define PROD_TRANSMIT(A) \ + LANCE_WRITE_RDP( \ + A, \ + LANCE_CSR0_TRANSMIT_DEMAND | LANCE_CSR0_INTERRUPT_ENABLE \ + ); + +extern +NDIS_STATUS +LanceSend( + IN NDIS_HANDLE MiniportAdapterContext, + IN PNDIS_PACKET Packet, + IN UINT Flags + ) + +/*++ + +Routine Description: + + The LanceSend request instructs a MAC to transmit a packet through + the adapter onto the medium. + +Arguments: + + Status - The status of the operation. + + MiniportAdapterContext - The context value set by the mini-port. + + Packet - A pointer to a descriptor for the packet that is to be + transmitted. + +Return Value: + + None. + +--*/ + +{ + // + // Pointer to the adapter. + // + PLANCE_ADAPTER Adapter = (PLANCE_ADAPTER)MiniportAdapterContext; + + // + // Pointer to the ring entry to be filled with buffer information. + // + PLANCE_TRANSMIT_ENTRY CurrentRingElement; + + // + // Pointer to the ring to packet entry that records the info about + // this packet. + // + PLANCE_RING_TO_PACKET RingToPacket; + + // + // Length of the packet + // + ULONG TotalVirtualLength; + + // + // Holds the adapter buffer index available for allocation. + // + INT LanceBuffersIndex; + + // + // Points to a successfully allocated adapter buffer descriptor. + // + PLANCE_BUFFER_DESCRIPTOR BufferDescriptor; + + // + // Simple iteration variable. + // + INT i; + + // + // Size of Lance Buffer needed (1==Small, 2==Medium, 3==Large) + // + UCHAR BufferSize; + + // + // If we successfully acquire some ring entries, this + // is the index of the first one. + // + UINT RingIndex; + + // + // Will point into the virtual address space addressed + // by the adapter buffer if one was successfully allocated. + // + PCHAR CurrentDestination; + + // + // Will point to the current source buffer. + // + PNDIS_BUFFER SourceBuffer; + + // + // Points to the virtual address of the source buffers data. + // + PVOID SourceData; + + // + // Will point to the number of bytes of data in the source + // buffer. + // + UINT SourceLength; + + NDIS_STATUS Status; + +#if LANCE_TRACE + DbgPrint("In LanceSend\n"); +#endif + + if (Adapter->HardwareFailure) { + + return(NDIS_STATUS_FAILURE); + + } + + LOG(IN_SEND); + + if (!Adapter->ResetInProgress) { + + if (Adapter->NumberOfAvailableRings == 0) { + + return(NDIS_STATUS_RESOURCES); + + } + + // + // It is reasonable to do a quick check and fail if the packet + // is larger than the maximum an ethernet can handle. + // + + NdisQueryPacket( + Packet, + NULL, + NULL, + &SourceBuffer, + &TotalVirtualLength + ); + + if ((!TotalVirtualLength) || + (TotalVirtualLength > LANCE_LARGE_BUFFER_SIZE)) { + + return(NDIS_STATUS_RESOURCES); + + } else { + + // + // Certain hardware implementation (Decstation) use a dual ported + // memory to communicate with the hardware. This is reasonable since + // it reduces bus contention. When using the dual ported memory, all + // send data must be moved to buffers allocated from the dual ported + // memory. + // + + if (TotalVirtualLength <= LANCE_SMALL_BUFFER_SIZE) { + + BufferSize = 1; + + } else if (TotalVirtualLength <= LANCE_MEDIUM_BUFFER_SIZE) { + + BufferSize = 2; + + } else { + + BufferSize = 3; + + } + + // + // Find a buffer + // + for ( + i = BufferSize; + i <= 3; + i++ + ) { + + if ((LanceBuffersIndex = Adapter->LanceBufferListHeads[i]) != -1) { + + BufferDescriptor = Adapter->LanceBuffers + LanceBuffersIndex; + Adapter->LanceBufferListHeads[i] = BufferDescriptor->Next; + break; + + } + + } + + if (LanceBuffersIndex == -1) { + + // + // Nothing available for the packet. + // + + return NDIS_STATUS_RESOURCES; + + } + + // + // Save the list head index in the buffer descriptor + // to permit easy deallocation later. + // + BufferDescriptor->Next = i; + + // + // Now Acquire the ring + // + RingIndex = Adapter->AllocateableRing - Adapter->TransmitRing; + + // + // Store the info + // + CurrentRingElement = Adapter->AllocateableRing; + + // + // NOTE NOTE NOTE NOTE NOTE NOTE + // + // We can do the next calculation because we know that the number + // or ring entries is a power of two! + // + + Adapter->AllocateableRing = Adapter->TransmitRing + + (((RingIndex) + 1) & + (Adapter->NumberOfTransmitRings-1)); + + Adapter->NumberOfAvailableRings--; + + // + // Copy into buffer + // + + CurrentDestination = BufferDescriptor->VirtualLanceBuffer; + + while ( SourceBuffer != NULL ) { + + NdisQueryBuffer( + SourceBuffer, + &SourceData, + &SourceLength + ); + + LANCE_MOVE_MEMORY_TO_HARDWARE( + CurrentDestination, + SourceData, + SourceLength + ); + + CurrentDestination = (PCHAR)CurrentDestination + SourceLength; + + NdisGetNextBuffer( + SourceBuffer, + &SourceBuffer + ); + + } + + // + // If the packet is less then the minimum size then we + // need to zero out the rest of the packet. + // + + if (TotalVirtualLength < MIN_SINGLE_BUFFER) { + + LANCE_ZERO_MEMORY_FOR_HARDWARE( + CurrentDestination, + MIN_SINGLE_BUFFER - TotalVirtualLength + ); + + BufferDescriptor->DataLength = MIN_SINGLE_BUFFER; + + } else { + + BufferDescriptor->DataLength = TotalVirtualLength; + + } + + // + // Get the position for mapping ring entries to packets. + // We record the owning packet information in the ring packet packet + // structure. + // + RingToPacket = Adapter->RingToPacket + RingIndex; + RingToPacket->OwningPacket = Packet; + RingToPacket->LanceBuffersIndex = LanceBuffersIndex; + RingToPacket->RingIndex = RingIndex; + + // + // Make sure that the ring descriptor is clean. + // + + LANCE_ZERO_MEMORY_FOR_HARDWARE((PUCHAR)CurrentRingElement, + sizeof(LANCE_TRANSMIT_ENTRY) + ); + + LANCE_SET_TRANSMIT_BUFFER_LENGTH( + CurrentRingElement, + BufferDescriptor->DataLength + ); + + + LANCE_SET_TRANSMIT_BUFFER_ADDRESS( + Adapter, + CurrentRingElement, + BufferDescriptor->VirtualLanceBuffer + ); + + LOG(TRANSMIT); + + // + // We update the ring ownership of the last packet under + // the protection of the lock so that the uncommitted packet + // pointer can be updated before the transmit post processing + // can examine it. + // + + LANCE_SET_RING_BITS( + CurrentRingElement->TransmitSummaryBits, + LANCE_TRANSMIT_START_OF_PACKET | + LANCE_TRANSMIT_OWNED_BY_CHIP | + LANCE_TRANSMIT_END_OF_PACKET + ); + + + if (RingIndex == (Adapter->NumberOfTransmitRings-1)) { + + Adapter->FirstUncommittedRing = Adapter->TransmitRing ; + + } else { + + Adapter->FirstUncommittedRing = Adapter->TransmitRing + RingIndex + 1; + + } + + // + // Prod the chip into checking for packets to send. + // + + PROD_TRANSMIT(Adapter); + + Status = NDIS_STATUS_SUCCESS; + + } + + } else if (Adapter->ResetRequestType == NdisRequestGeneric1) { + + Status = NDIS_STATUS_RESET_IN_PROGRESS; + + } else { + + // + // Have the upper layer try again later + // + Status = NDIS_STATUS_RESOURCES; + + } + + LOG(OUT_SEND); + + LANCE_DO_DEFERRED(Adapter); + +#if LANCE_TRACE + DbgPrint("Out LanceSend\n"); +#endif + + return Status; +} + diff --git a/private/ntos/ndis/lance/sources b/private/ntos/ndis/lance/sources new file mode 100644 index 000000000..d6f5951bd --- /dev/null +++ b/private/ntos/ndis/lance/sources @@ -0,0 +1,47 @@ +!IF 0 + +Copyright (c) 1989 Microsoft Corporation + +Module Name: + + sources. + +Abstract: + + This file specifies the target component being built and the list of + sources files needed to build that component. Also specifies optional + compiler switches and libraries that are unique for the component being + built. + + +Author: + + Steve Wood (stevewo) 12-Apr-1990 + +NOTE: Commented description of this file is in \nt\bak\bin\sources.tpl + +!ENDIF + +MAJORCOMP=ntos +MINORCOMP=ndis + +TARGETNAME=lance +TARGETPATH=\nt\public\sdk\lib +TARGETTYPE=DRIVER + +TARGETLIBS=$(BASEDIR)\public\sdk\lib\*\ndis.lib +C_DEFINES=$(C_DEFINES) -DNDIS_MINIPORT_DRIVER + +INCLUDES=..\..\inc + +SOURCES=lance.c \ + send.c \ + transfer.c \ + details.c \ + dectc.c \ + lance.rc + +RELATIVE_DEPTH=..\.. + +MSC_WARNING_LEVEL=/W3 /WX + diff --git a/private/ntos/ndis/lance/transfer.c b/private/ntos/ndis/lance/transfer.c new file mode 100644 index 000000000..d0ded3180 --- /dev/null +++ b/private/ntos/ndis/lance/transfer.c @@ -0,0 +1,389 @@ +/*++ + +Copyright (c) 1990 Microsoft Corporation + +Module Name: + + transfer.c + +Abstract: + + This file contains the code to implement the MacTransferData + API for the ndis 3.0 interface. + +Author: + + Anthony V. Ercolano (Tonye) 12-Sept-1990 + +Environment: + + Kernel Mode - Or whatever is the equivalent on OS/2 and DOS. + +Revision History: + + +--*/ + +#include +#include +#include + + +extern +NDIS_STATUS +LanceTransferData( + OUT PNDIS_PACKET Packet, + OUT PUINT BytesTransferred, + IN NDIS_HANDLE MiniportAdapterContext, + IN NDIS_HANDLE MiniportReceiveContext, + IN UINT ByteOffset, + IN UINT BytesToTransfer + ) + +/*++ + +Routine Description: + + A protocol calls the LanceTransferData request (indirectly via + NdisTransferData) from within its Receive event handler + to instruct the MAC to copy the contents of the received packet + a specified paqcket buffer. + +Arguments: + + Status - Status of the operation. + + MiniportAdapterContext - The context value set by the Miniport. + + MiniportReceiveContext - The context value passed by the MAC on its call + to NdisMEthIndicateReceive. + + ByteOffset - An unsigned integer specifying the offset within the + received packet at which the copy is to begin. If the entire packet + is to be copied, ByteOffset must be zero. + + BytesToTransfer - An unsigned integer specifying the number of bytes + to copy. It is legal to transfer zero bytes; this has no effect. If + the sum of ByteOffset and BytesToTransfer is greater than the size + of the received packet, then the remainder of the packet (starting from + ByteOffset) is transferred, and the trailing portion of the receive + buffer is not modified. + + Packet - A pointer to a descriptor for the packet storage into which + the MAC is to copy the received packet. + + BytesTransfered - A pointer to an unsigned integer. The MAC writes + the actual number of bytes transferred into this location. This value + is not valid if the return status is STATUS_PENDING. + +Return Value: + + The function value is the status of the operation. + + +--*/ + +{ + + PLANCE_ADAPTER Adapter = (PLANCE_ADAPTER)(MiniportAdapterContext); + // + // Keep a local for the number of receive ring entries so + // that we aren't always accessing through the adapter. + // + const UINT TopReceiveIndex = Adapter->NumberOfReceiveRings - 1; + + // + // Used for only a short time to extract the context + // information from the parameter. + // + LANCE_RECEIVE_CONTEXT C; + + // + // Holds the first and last index of the first and last + // receive ring descriptors that hold the current packet. + // + UINT FirstBuffer; + UINT LastBuffer; + + // + // Pointer to the ring descriptor for the current buffer. + // + PLANCE_RECEIVE_ENTRY CurrentEntry; + + // + // Holds the count of the number of ndis buffers comprising + // the destination packet. + // + UINT DestinationBufferCount; + + // + // Points to the buffer into which we are putting data. + // + PNDIS_BUFFER DestinationCurrentBuffer; + + // + // Holds the virtual address of the current destination + // buffer. + // + PVOID DestinationVirtualAddress; + + // + // Holds the virtual address of the current source buffer. + // + PVOID SourceVirtualAddress; + + // + // Holds the length of the current destination buffer. + // + UINT DestinationCurrentLength; + + // + // Holds the length of the current source buffer. + // + UINT SourceCurrentLength; + + // + // Keep a local variable of BytesTransferred so we aren't + // referencing through a pointer. + // + UINT LocalBytesTransferred = 0; + + // + // Index in the ring of the current receive ring descriptor. + // + UINT CurrentSourceIndex; + + ASSERT(!Adapter->ResetInitStarted); + + ByteOffset += LANCE_HEADER_SIZE; + + // + // Take care of boundary condition of zero length copy. + // + + *BytesTransferred = 0; + + ASSERT(sizeof(UINT) >= 2); + ASSERT(sizeof(UINT) == sizeof(NDIS_HANDLE)); + + C.WholeThing = (UINT)MiniportReceiveContext; + FirstBuffer = C.INFO.FirstBuffer; + LastBuffer = C.INFO.LastBuffer; + + // + // Get the first buffer of the destination. + // + + NdisQueryPacket( + Packet, + NULL, + &DestinationBufferCount, + &DestinationCurrentBuffer, + NULL + ); + + // + // Could have a null packet. + // + + if (DestinationBufferCount) { + + NdisQueryBuffer( + DestinationCurrentBuffer, + &DestinationVirtualAddress, + &DestinationCurrentLength + ); + + // + // Get the information for the first buffer of the source. + // + + SourceVirtualAddress = Adapter->ReceiveVAs[FirstBuffer]; + CurrentEntry = Adapter->ReceiveRing + FirstBuffer; + CurrentSourceIndex = FirstBuffer; + + if (CurrentSourceIndex == LastBuffer) { + + // + // The last buffer might only be partially filled with + // transmitted data. There is a field in the last + // ring entry that has the total packet data length. + // + LANCE_GET_MESSAGE_SIZE(CurrentEntry, SourceCurrentLength); + SourceCurrentLength -= LocalBytesTransferred; + + } else { + + SourceCurrentLength = Adapter->SizeOfReceiveBuffer; + + } + + while (LocalBytesTransferred < BytesToTransfer) { + + // + // Check to see whether we've exhausted the current + // destination buffer. If so, move onto the next one. + // + + if (!DestinationCurrentLength) { + + NdisGetNextBuffer( + DestinationCurrentBuffer, + &DestinationCurrentBuffer + ); + + if (!DestinationCurrentBuffer) { + + // + // We've reached the end of the packet. We + // return with what we've done so far. (Which + // must be shorter than requested.) + // + + break; + + } + + NdisQueryBuffer( + DestinationCurrentBuffer, + &DestinationVirtualAddress, + &DestinationCurrentLength + ); + continue; + + } + + + // + // Check to see whether we've exhausted the current + // source buffer. If so, move onto the next one. + // + + if (!SourceCurrentLength) { + + if (CurrentSourceIndex == LastBuffer) { + + // + // We've reached the end of the packet. We + // return with what we've done so far. (Which + // must be shorter than requested.) + // + + break; + + } + + if (CurrentSourceIndex == TopReceiveIndex) { + + CurrentSourceIndex = 0; + CurrentEntry = Adapter->ReceiveRing; + + } else { + + CurrentSourceIndex++; + CurrentEntry++; + + } + + if (CurrentSourceIndex == LastBuffer) { + + // + // The last buffer might only be partially + // filled with transmitted data. There is + // a field in the last ring entry that has + // the total packet data length. + // + LANCE_GET_MESSAGE_SIZE(CurrentEntry, SourceCurrentLength); + SourceCurrentLength -= LocalBytesTransferred; + + } else { + + SourceCurrentLength = + Adapter->SizeOfReceiveBuffer; + + } + + SourceVirtualAddress = + Adapter->ReceiveVAs[CurrentSourceIndex]; + continue; + + } + + // + // Try to get us up to the point to start the copy. + // + + if (ByteOffset) { + + if (ByteOffset > SourceCurrentLength) { + + // + // What we want isn't in this buffer. + // + + ByteOffset -= SourceCurrentLength; + SourceCurrentLength = 0; + continue; + + } else { + + SourceVirtualAddress = + (PCHAR)SourceVirtualAddress + ByteOffset; + SourceCurrentLength -= ByteOffset; + ByteOffset = 0; + + } + + } + + // + // Copy the data. + // + + { + + // + // Holds the amount of data to move. + // + UINT AmountToMove; + + // + // Holds the amount desired remaining. + // + UINT Remaining = BytesToTransfer + - LocalBytesTransferred; + + AmountToMove = + ((SourceCurrentLength <= DestinationCurrentLength)? + (SourceCurrentLength):(DestinationCurrentLength)); + + AmountToMove = ((Remaining < AmountToMove)? + (Remaining):(AmountToMove)); + + LANCE_MOVE_HARDWARE_TO_MEMORY( + DestinationVirtualAddress, + SourceVirtualAddress, + AmountToMove + ); + + DestinationVirtualAddress = + (PCHAR)DestinationVirtualAddress + AmountToMove; + SourceVirtualAddress = + (PCHAR)SourceVirtualAddress + AmountToMove; + + LocalBytesTransferred += AmountToMove; + SourceCurrentLength -= AmountToMove; + DestinationCurrentLength -= AmountToMove; + + } + + } + + *BytesTransferred = LocalBytesTransferred; + + } + + LANCE_DO_DEFERRED(Adapter); + + return NDIS_STATUS_SUCCESS; +} -- cgit v1.2.3