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