summaryrefslogtreecommitdiffstats
path: root/private/ntos/ndis/wd
diff options
context:
space:
mode:
Diffstat (limited to 'private/ntos/ndis/wd')
-rw-r--r--private/ntos/ndis/wd/keywords.h54
-rw-r--r--private/ntos/ndis/wd/lmi.c5854
-rw-r--r--private/ntos/ndis/wd/makefile6
-rw-r--r--private/ntos/ndis/wd/sources44
-rw-r--r--private/ntos/ndis/wd/umi.c347
-rw-r--r--private/ntos/ndis/wd/wd.c4599
-rw-r--r--private/ntos/ndis/wd/wdhrd.h915
-rw-r--r--private/ntos/ndis/wd/wdlan.rc39
-rw-r--r--private/ntos/ndis/wd/wdlmi.h865
-rw-r--r--private/ntos/ndis/wd/wdlmireg.h424
-rw-r--r--private/ntos/ndis/wd/wdsft.h852
-rw-r--r--private/ntos/ndis/wd/wdumi.h45
12 files changed, 14044 insertions, 0 deletions
diff --git a/private/ntos/ndis/wd/keywords.h b/private/ntos/ndis/wd/keywords.h
new file mode 100644
index 000000000..35896713e
--- /dev/null
+++ b/private/ntos/ndis/wd/keywords.h
@@ -0,0 +1,54 @@
+/*++
+
+Copyright (c) 1990 Microsoft Corporation
+
+Module Name:
+
+ keywords.h
+
+Abstract:
+
+ Contains all Ndis2 and Ndis3 mac-specific keywords.
+
+Author:
+
+ Bob Noradki
+
+Environment:
+
+ This driver is expected to work in DOS, OS2 and NT at the equivalent
+ of kernal mode.
+
+ Architecturally, there is an assumption in this driver that we are
+ on a little endian machine.
+
+Notes:
+
+ optional-notes
+
+Revision History:
+
+
+
+--*/
+#ifndef NDIS2
+#define NDIS2 0
+#endif
+
+#if NDIS2
+
+#define IOBASE NDIS_STRING_CONST("IOBASE")
+#define MAXMULTICASTLIST NDIS_STRING_CONST("MAXMULTICAST")
+#define NETADDRESS NDIS_STRING_CONST("NETADDRESS")
+#define INTERRUPT NDIS_STRING_CONST("IRQ")
+#define MEMMAPPEDBASEADDRESS NDIS_STRING_CONST("RAMADDRESS")
+
+#else // NDIS3
+
+#define IOBASE NDIS_STRING_CONST("IoBaseAddress")
+#define MAXMULTICASTLIST NDIS_STRING_CONST("MaximumMulticastList")
+#define NETADDRESS NDIS_STRING_CONST("NetworkAddress")
+#define INTERRUPT NDIS_STRING_CONST("InterruptNumber")
+#define MEMMAPPEDBASEADDRESS NDIS_STRING_CONST("MemoryMappedBaseAddress")
+
+#endif
diff --git a/private/ntos/ndis/wd/lmi.c b/private/ntos/ndis/wd/lmi.c
new file mode 100644
index 000000000..e41581ef9
--- /dev/null
+++ b/private/ntos/ndis/wd/lmi.c
@@ -0,0 +1,5854 @@
+/*++
+
+Copyright (c) 1990 Microsoft Corporation
+
+Module Name:
+
+ lmi.c
+
+Abstract:
+
+ Lower MAC Interface functions for the NDIS 3.0 Western Digital driver.
+
+Author:
+
+ Sean Selitrennikoff (seanse) 15-Jan-92
+
+Environment:
+
+ Kernel mode, FSD
+
+Revision History:
+
+
+--*/
+
+#include <ndis.h>
+#include <efilter.h>
+#include "wdlmireg.h"
+#include "wdlmi.h"
+#include "wdhrd.h"
+#include "wdsft.h"
+#include "wdumi.h"
+
+extern MAC_BLOCK WdMacBlock;
+
+#if DBG
+
+extern UCHAR WdDebugLog[];
+extern UCHAR WdDebugLogPlace;
+
+UCHAR LmiDebugLogPlace = 0;
+ULONG LmiDebugLog[256] = {0};
+
+#define IF_LOG(A) A
+
+extern
+VOID
+LOG (UCHAR A);
+
+#else
+
+#define IF_LOG(A)
+
+#endif
+
+
+
+#if DBG
+
+#define LMI_LOUD 0x01
+
+UCHAR LmiDebugFlag = 0x00;
+
+#define IF_LMI_LOUD(A) {if (LmiDebugFlag & LMI_LOUD){ A; }}
+
+#else
+
+#define IF_LMI_LOUD(A)
+
+#endif
+
+
+
+
+
+
+VOID
+CardGetBoardId(
+ IN NDIS_HANDLE NdisAdapterHandle,
+ IN UINT BaseAddr,
+ IN BOOLEAN Mca,
+ OUT PULONG BoardIdMask
+ );
+
+
+VOID
+CardGetBaseInfo(
+ IN NDIS_HANDLE NdisAdapterHandle,
+ IN UINT BaseAddr,
+ IN BOOLEAN Mca,
+ OUT PULONG BoardIdMask
+ );
+
+
+VOID
+CardGetEepromInfo(
+ IN NDIS_HANDLE NdisAdapterHandle,
+ IN UINT BaseAddr,
+ IN BOOLEAN Mca,
+ OUT PULONG BoardIdMask
+ );
+
+VOID
+CardGetRamSize(
+ IN NDIS_HANDLE NdisAdapterHandle,
+ IN UINT BaseAddr,
+ IN BOOLEAN Mca,
+ IN UINT RevNumber,
+ OUT PULONG BoardIdMask
+ );
+
+BOOLEAN
+CardCheckFor690(
+ IN NDIS_HANDLE NdisAdapterHandle,
+ IN UINT BaseAddr
+ );
+
+UINT
+CardGetConfig(
+ IN NDIS_HANDLE NdisAdapterHandle,
+ IN UINT BaseAddr,
+ IN BOOLEAN Mca,
+ OUT PCNFG_Adapter Config
+ );
+
+VOID
+CardSendPacket(
+ IN Ptr_Adapter_Struc Adapter
+ );
+
+
+VOID
+CardCopyDown(
+ IN Ptr_Adapter_Struc Adapter,
+ IN PNDIS_PACKET Packet
+ );
+
+BOOLEAN
+SyncGetCurrent(
+ IN PVOID Context
+ );
+
+BOOLEAN
+SyncSetAllMulticast(
+ IN PVOID Context
+ );
+
+BOOLEAN
+SyncClearMulticast(
+ IN PVOID Context
+ );
+
+
+
+#pragma NDIS_INIT_FUNCTION(CardGetBoardId)
+
+VOID
+CardGetBoardId(
+ IN NDIS_HANDLE NdisAdapterHandle,
+ IN UINT BaseAddr,
+ IN BOOLEAN Mca,
+ OUT PULONG BoardIdMask
+ )
+/*++
+
+Routine Description:
+
+ This routine will determine which WD80xx card is installed and set the
+ BoardIdMask to the feature bits.
+
+Arguments:
+
+ NdisAdapterHandle - Handle returned by Ndis after NdisRegisterAdapter call.
+
+ BaseAddr - The base address for I/O to the board.
+
+ Mca - TRUE if the machine is micro-channel, else the machine is AT.
+
+ BoardIdMask - Returns the feature mask of the installed board.
+
+
+Return:
+
+ none.
+
+--*/
+{
+ UCHAR IdByte;
+ UINT RevNumber;
+
+ //
+ // Init mask.
+ //
+
+ *BoardIdMask = 0;
+
+ //
+ // GetBoardRevNumber(Mca);
+ //
+
+ IF_LMI_LOUD(DbgPrint("Getting BoardId\n"));
+
+
+ NdisReadPortUchar(NdisAdapterHandle,
+ BaseAddr + WD_ID_BYTE,
+ &IdByte
+ );
+
+
+ IF_LMI_LOUD(DbgPrint("Idbyte is 0x%x\n",IdByte));
+
+ RevNumber = IdByte & WD_BOARD_REV_MASK;
+
+ RevNumber >>= 1;
+
+
+ //
+ // Check rev is valid.
+ //
+
+ if (RevNumber == 0) {
+
+ return;
+
+ }
+
+
+
+ //
+ // if (Mca) AddFeatureBits(MCA);
+ //
+
+ if (Mca) {
+
+ *BoardIdMask |= MICROCHANNEL;
+ }
+
+
+
+ //
+ // GetBaseInfo(BaseAddr, Mca, BoardIdMask);
+ //
+
+ CardGetBaseInfo(NdisAdapterHandle, BaseAddr, Mca, BoardIdMask);
+
+
+ IF_LMI_LOUD(DbgPrint("GetBaseInfo: Id is now 0x%x\n",*BoardIdMask));
+
+
+ //
+ // GetMediaType(BaseAddr, Mca, BoardIdMask);
+ //
+
+ if (IdByte & WD_MEDIA_TYPE_BIT) {
+
+ *BoardIdMask |= ETHERNET_MEDIA;
+
+ } else {
+
+ if (RevNumber != 1) {
+
+ *BoardIdMask |= TWISTED_PAIR_MEDIA;
+
+ } else {
+
+ *BoardIdMask |= STARLAN_MEDIA;
+
+ }
+
+ }
+
+ IF_LMI_LOUD(DbgPrint("GetMediaType: Id is now 0x%x\n",*BoardIdMask));
+
+ //
+ // if (RevNumber >= 2) then
+ // GetIdByteInfo(BaseAddr, Mca, RevNumber, BoardIdMask);
+ //
+
+ if (RevNumber >= 2) {
+
+ if (IdByte & WD_BUS_TYPE_BIT) {
+
+ ASSERT(Mca);
+
+ }
+
+ //
+ // For two cards this bit means use alternate IRQ
+ //
+
+ if (IdByte & WD_SOFT_CONFIG_BIT) {
+
+ if (((*BoardIdMask & WD8003EB) == WD8003EB) ||
+ ((*BoardIdMask & WD8003W) == WD8003W)) {
+
+ *BoardIdMask |= ALTERNATE_IRQ_BIT;
+
+ }
+
+ }
+
+ }
+
+
+
+ IF_LMI_LOUD(DbgPrint("Rev > 2: Id is now 0x%x\n",*BoardIdMask));
+
+ //
+ // if (RevNumber >= 3) then
+ // if (!Mca) then
+ // AddFeatureBits(EEPROM_OVERRIDE, 584_CHIP, EXTRA_EEPROM_OVERRIDE);
+ // GetEepromInfo(BaseAddr, Mca, RevNumber, EEPromBoardIdMask);
+ // AddFeatureBits(EEPromBoardIdMask);
+ // else
+ // AddFeatureBits(594_CHIP);
+ // GetRamSize(BaseAddr, Mca, RevNumber, BoardIdMask);
+ // else
+ // GetRamSize(BaseAddr, Mca, RevNumber, BoardIdMask);
+ //
+
+ if (RevNumber >= 3) {
+
+ ULONG EEPromMask;
+
+ if (!Mca) {
+
+ *BoardIdMask &= (WD_584_ID_EEPROM_OVERRIDE |
+ WD_584_EXTRA_EEPROM_OVERRIDE);
+
+ *BoardIdMask |= INTERFACE_584_CHIP;
+
+ CardGetEepromInfo(NdisAdapterHandle, BaseAddr, Mca, &EEPromMask);
+
+ *BoardIdMask |= EEPromMask;
+
+ IF_LMI_LOUD(DbgPrint("GetEEPromInfo: Id is now 0x%x\n",*BoardIdMask));
+
+ } else {
+
+ *BoardIdMask |= INTERFACE_594_CHIP;
+
+ CardGetRamSize(NdisAdapterHandle, BaseAddr, Mca, RevNumber, BoardIdMask);
+
+ IF_LMI_LOUD(DbgPrint("CardGetRamSize: Id is now 0x%x\n",*BoardIdMask));
+
+ }
+
+ } else {
+
+ CardGetRamSize(NdisAdapterHandle, BaseAddr, Mca, RevNumber, BoardIdMask);
+
+ IF_LMI_LOUD(DbgPrint("CardGetRamSize2: Id is now 0x%x\n",*BoardIdMask));
+
+ }
+
+
+ //
+ // if (RevNumber >= 4) then
+ // AddFeatureBits(ADVANCED_FEATURES);
+ //
+
+ if (RevNumber >= 4) {
+
+ *BoardIdMask |= ADVANCED_FEATURES;
+
+ }
+
+ //
+ // if (CheckFor690(BaseAddr)) then
+ // AddFeatureBits(690_CHIP);
+ //
+
+
+ if (CardCheckFor690(NdisAdapterHandle, BaseAddr)) {
+
+ *BoardIdMask |= NIC_690_BIT;
+
+ }
+
+ IF_LMI_LOUD(DbgPrint("CheckFor690: Id is now 0x%x\n",*BoardIdMask));
+
+}
+
+
+
+#pragma NDIS_INIT_FUNCTION(CardGetBaseInfo)
+
+VOID
+CardGetBaseInfo(
+ IN NDIS_HANDLE NdisAdapterHandle,
+ IN UINT BaseAddr,
+ IN BOOLEAN Mca,
+ OUT PULONG BoardIdMask
+ )
+/*++
+
+Routine Description:
+
+ This routine will get the following information about the card:
+ Is there an interface chip,
+ Are some registers aliased,
+ Is the board 16 bit,
+ Is the board in a 16 bit slot.
+
+
+
+Arguments:
+
+ NdisAdapterHandle - Handle returned by Ndis after NdisRegisterAdapter call.
+
+ BaseAddr - The base address for I/O to the board.
+
+ Mca - TRUE if the machine is micro-channel, else the machine is AT.
+
+ BoardIdMask - Returns the feature mask of the installed board.
+
+
+Return:
+
+ none.
+
+--*/
+{
+ UCHAR RegValue;
+ UCHAR SaveValue;
+ UCHAR TmpValue;
+ ULONG Register;
+
+ BOOLEAN ExistsAnInterfaceChip = FALSE;
+
+ //
+ // Does there exist and interface chip?
+ //
+ //
+ // Get original value
+ //
+
+ NdisReadPortUchar(NdisAdapterHandle, BaseAddr + WD_REG_7, &SaveValue);
+
+ //
+ // Put something into chip (if it exists).
+ //
+
+ NdisWritePortUchar(NdisAdapterHandle, BaseAddr + WD_REG_7, 0x35);
+
+ //
+ // Swamp bus with something else.
+ //
+
+ NdisReadPortUchar(NdisAdapterHandle, BaseAddr, &RegValue);
+
+ //
+ // Read from chip
+ //
+
+ NdisReadPortUchar(NdisAdapterHandle, BaseAddr + WD_REG_7, &RegValue);
+
+ //
+ // Was the value saved on the chip??
+ //
+
+ if (RegValue == 0x35) {
+
+ //
+ // Try it again just for kicks.
+ //
+
+ NdisWritePortUchar(NdisAdapterHandle, BaseAddr + WD_REG_7, 0x3A);
+
+ //
+ // Swamp bus with something else.
+ //
+
+ NdisReadPortUchar(NdisAdapterHandle, BaseAddr, &RegValue);
+
+ //
+ // Read from chip
+ //
+
+ NdisReadPortUchar(NdisAdapterHandle, BaseAddr + WD_REG_7, &RegValue);
+
+ //
+ // Was the value saved on the chip??
+ //
+
+ if (RegValue == 0x3A) {
+
+ ExistsAnInterfaceChip = TRUE;
+
+ }
+
+ }
+
+ //
+ // Write back original value.
+ //
+
+ NdisWritePortUchar(NdisAdapterHandle, BaseAddr + WD_REG_7, SaveValue);
+
+
+
+
+
+
+ //
+ // if (Mca) then
+ //
+ // if (ExistsAnInterfaceChip) then
+ //
+ // AddFeatureBits(INTERFACE_CHIP)
+ //
+ // return;
+ //
+
+ if (Mca) {
+
+ if (ExistsAnInterfaceChip) {
+
+ *BoardIdMask |= INTERFACE_CHIP;
+
+ }
+
+ return;
+
+ }
+
+
+
+
+ //
+ //
+ // if (BoardUsesAliasing(BaseAddr)) then
+ //
+ // return;
+ //
+
+
+ for (Register = WD_REG_1; Register < WD_REG_6; Register++) {
+
+ NdisReadPortUchar(NdisAdapterHandle, BaseAddr + Register, &RegValue);
+
+ NdisReadPortUchar(NdisAdapterHandle, BaseAddr + Register + WD_LAN_OFFSET, &SaveValue);
+
+ if (RegValue != SaveValue) {
+
+ break;
+
+ }
+
+ }
+
+ if (Register == WD_REG_6) {
+
+ //
+ // Check register 7
+ //
+
+ NdisReadPortUchar(NdisAdapterHandle, BaseAddr + Register, &RegValue);
+
+ NdisReadPortUchar(NdisAdapterHandle, BaseAddr + Register + WD_LAN_OFFSET, &SaveValue);
+
+ }
+
+ if (RegValue == SaveValue) {
+
+ return;
+
+ }
+
+
+
+
+ //
+ //
+ // if (ExistsAnInterfaceChip) then
+ //
+ // AddFeatureBits(INTERFACE_CHIP);
+ //
+ // else
+ //
+ // if (BoardIs16Bit(BaseAddr)) then
+ //
+ // AddFeatureBits(BOARD_16BIT);
+ //
+ // if (InA16BitSlot(BaseAddr)) then
+ //
+ // AddFeatureBits(SLOT_16BIT);
+ //
+ //
+ //
+ //
+
+
+ if (ExistsAnInterfaceChip) {
+
+ *BoardIdMask |= INTERFACE_CHIP;
+
+ } else {
+
+ //
+ // Save original value.
+ //
+
+ NdisReadPortUchar(NdisAdapterHandle, BaseAddr + WD_REG_1, &SaveValue);
+
+ //
+ // Now flip 16 bit value and write it back.
+ //
+
+ RegValue = (SaveValue & (UCHAR)WD_SIXTEEN_BIT);
+
+ NdisWritePortUchar(NdisAdapterHandle,
+ BaseAddr + WD_REG_1,
+ (UCHAR)(SaveValue ^ WD_SIXTEEN_BIT));
+
+ //
+ // Swamp bus with something else.
+ //
+
+ NdisReadPortUchar(NdisAdapterHandle, BaseAddr, &TmpValue);
+
+ //
+ // Read back value.
+ //
+
+ NdisReadPortUchar(NdisAdapterHandle, BaseAddr + WD_REG_1, &TmpValue);
+
+ if ((TmpValue & (UCHAR)WD_SIXTEEN_BIT) == RegValue) {
+
+ //
+ // If the flip stayed, we have a 16 bit chip.
+ //
+
+ //
+ // Put back orginal value.
+ //
+
+ NdisWritePortUchar(NdisAdapterHandle,
+ BaseAddr + WD_REG_1,
+ (UCHAR)(SaveValue & 0xFE)
+ );
+
+
+ *BoardIdMask |= BOARD_16BIT;
+
+
+
+ //
+ // Now check if it is a 16 bit slot....
+ //
+
+
+ NdisReadPortUchar(NdisAdapterHandle,
+ BaseAddr + WD_REG_1,
+ &RegValue
+ );
+
+ if (RegValue & WD_SIXTEEN_BIT) {
+
+ *BoardIdMask |= SLOT_16BIT;
+
+ }
+
+ } else {
+
+ //
+ // Put back original value.
+ //
+
+ NdisWritePortUchar(NdisAdapterHandle,
+ BaseAddr + WD_REG_1,
+ SaveValue
+ );
+ }
+
+ }
+
+}
+
+
+
+#pragma NDIS_INIT_FUNCTION(CardGetEepromInfo)
+
+VOID
+CardGetEepromInfo(
+ IN NDIS_HANDLE NdisAdapterHandle,
+ IN UINT BaseAddr,
+ IN BOOLEAN Mca,
+ OUT PULONG BoardIdMask
+ )
+/*++
+
+Routine Description:
+
+ This routine will get the following information about the card:
+ Bus type,
+ Bus size,
+ Media type,
+ IRQ - primary or alternate,
+ RAM size
+
+
+ In this case All other information in the top 16 bits of the BoardIdMask
+ are zeroed and replaced with these values since EEProm values are
+ overriding old values.
+
+
+
+Arguments:
+
+ NdisAdapterHandle - Handle returned by Ndis after NdisRegisterAdapter call.
+
+ BaseAddr - The base address for I/O to the board.
+
+ Mca - TRUE if the machine is micro-channel, else the machine is AT.
+
+ BoardIdMask - Returns the feature mask of the installed board.
+
+
+Return:
+
+ none.
+
+--*/
+{
+ UCHAR RegValue;
+
+
+ //
+ // *BoardIdMask = 0;
+ //
+
+ *BoardIdMask = 0;
+
+ //
+ // RecallEEPromData(NdisAdapterHandle, BaseAddr, Mca);
+ //
+
+ IF_LMI_LOUD(DbgPrint("Recalling EEPromData\n"));
+
+ NdisReadPortUchar(NdisAdapterHandle, BaseAddr + WD_REG_1, &RegValue);
+
+ RegValue &= WD_584_ICR_MASK;
+
+ RegValue |= WD_584_OTHER_BIT;
+
+ NdisWritePortUchar(NdisAdapterHandle, BaseAddr + WD_REG_1, RegValue);
+
+
+ NdisReadPortUchar(NdisAdapterHandle, BaseAddr + WD_REG_3, &RegValue);
+
+ RegValue &= WD_584_EAR_MASK;
+
+ RegValue |= WD_584_ENGR_PAGE;
+
+ NdisWritePortUchar(NdisAdapterHandle, BaseAddr + WD_REG_3, RegValue);
+
+
+ NdisReadPortUchar(NdisAdapterHandle, BaseAddr + WD_REG_1, &RegValue);
+
+ RegValue &= WD_584_ICR_MASK;
+
+ RegValue |= (WD_584_RLA | WD_584_OTHER_BIT);
+
+ NdisWritePortUchar(NdisAdapterHandle, BaseAddr + WD_REG_1, RegValue);
+
+
+ NdisReadPortUchar(NdisAdapterHandle, BaseAddr + WD_REG_1, &RegValue);
+
+ while (RegValue & WD_584_RECALL_DONE) {
+
+ NdisReadPortUchar(NdisAdapterHandle, BaseAddr + WD_REG_1, &RegValue);
+
+ }
+
+
+
+ //
+ // if (Mca) then AddFeatureBits(MICROCHANNEL);
+ //
+
+ if (Mca) {
+
+ *BoardIdMask |= MICROCHANNEL;
+
+ }
+
+
+ NdisReadPortUchar(NdisAdapterHandle, BaseAddr + WD_584_EEPROM_1, &RegValue);
+
+ IF_LMI_LOUD(DbgPrint("RegValue is 0x%x\n",RegValue));
+
+
+ //
+ // if (RamPaging) then
+ //
+ // AddFeatureBits(PAGED_RAM);
+ //
+
+ if ((RegValue & WD_584_EEPROM_PAGING_MASK) == WD_584_EEPROM_RAM_PAGING) {
+
+ *BoardIdMask |= PAGED_RAM;
+
+ }
+
+
+ //
+ // if (RomPaging) then
+ //
+ // AddFeatureBits(PAGED_ROM);
+ //
+
+ if ((RegValue & WD_584_EEPROM_PAGING_MASK) == WD_584_EEPROM_ROM_PAGING) {
+
+ *BoardIdMask |= PAGED_ROM;
+
+ }
+
+
+
+
+
+ //
+ // if (16BitBus) then
+ //
+ // AddFeatureBits(BOARD_16BIT);
+ //
+ // if (16BitSlot) then
+ //
+ // AddFeatureBits(SLOT_16BIT);
+ //
+
+ if ((RegValue & WD_584_EEPROM_BUS_SIZE_MASK) == WD_584_EEPROM_BUS_SIZE_16BIT) {
+
+ *BoardIdMask |= BOARD_16BIT;
+
+
+ //
+ // Now check if it is a 16 bit slot....
+ //
+
+
+ NdisReadPortUchar(NdisAdapterHandle,
+ BaseAddr + WD_REG_1,
+ &RegValue
+ );
+
+ IF_LMI_LOUD(DbgPrint("RegValue is 0x%x\n",RegValue));
+
+ if (RegValue & WD_SIXTEEN_BIT) {
+
+ *BoardIdMask |= SLOT_16BIT;
+
+ }
+
+ }
+
+
+ IF_LMI_LOUD(DbgPrint("16 Bit : Id is now 0x%x\n",*BoardIdMask));
+
+ //
+ // if (StarLanMedia) then
+ //
+ // AddFeatureBits(STARLAN_MEDIA);
+ //
+ // else
+ //
+ // if (TpMedia) then
+ //
+ // AddFeatureBits(TWISTED_PAIR_MEDIA);
+ //
+ // else
+ //
+ // if (EwMedia) then
+ //
+ // AddFeatureBits(EW_MEDIA);
+ //
+ // else
+ //
+ // AddFeatureBits(ETHERNET_MEDIA);
+ //
+ //
+
+ NdisReadPortUchar(NdisAdapterHandle, BaseAddr + WD_584_EEPROM_0, &RegValue);
+
+ IF_LMI_LOUD(DbgPrint("RegValue is 0x%x\n",RegValue));
+
+ if ((RegValue & WD_584_EEPROM_MEDIA_MASK) == WD_584_STARLAN_TYPE) {
+
+ *BoardIdMask |= STARLAN_MEDIA;
+
+ } else if ((RegValue & WD_584_EEPROM_MEDIA_MASK) == WD_584_TP_TYPE) {
+
+ *BoardIdMask |= TWISTED_PAIR_MEDIA;
+
+ } else if ((RegValue & WD_584_EEPROM_MEDIA_MASK) == WD_584_EW_TYPE) {
+
+ *BoardIdMask |= EW_MEDIA;
+
+ } else {
+
+ *BoardIdMask |= ETHERNET_MEDIA;
+
+ }
+
+
+ IF_LMI_LOUD(DbgPrint("MediaType: Id is now 0x%x\n",*BoardIdMask));
+
+
+ //
+ // if (AlternateIrq) then AddFeatureBits(ALTERNATE_IRQ_BIT);
+ //
+
+ if ((RegValue & WD_584_EEPROM_IRQ_MASK) != WD_584_PRIMARY_IRQ) {
+
+ *BoardIdMask |= ALTERNATE_IRQ_BIT;
+
+ }
+
+
+
+ IF_LMI_LOUD(DbgPrint("AltIrq: Id is now 0x%x\n",*BoardIdMask));
+
+ //
+ // GetRamSize(BaseAddr + EEPROM_1);
+ //
+ //
+
+
+ if ((RegValue & WD_584_EEPROM_RAM_SIZE_MASK) == WD_584_EEPROM_RAM_SIZE_8K) {
+
+ *BoardIdMask |= RAM_SIZE_8K;
+
+ } else {
+
+ if ((RegValue & WD_584_EEPROM_RAM_SIZE_MASK) == WD_584_EEPROM_RAM_SIZE_16K) {
+
+ if (!(*BoardIdMask & BOARD_16BIT)) {
+
+ *BoardIdMask |= RAM_SIZE_16K;
+
+ } else if (!(*BoardIdMask & SLOT_16BIT)) {
+
+ *BoardIdMask |= RAM_SIZE_8K;
+
+ } else {
+
+ *BoardIdMask |= RAM_SIZE_16K;
+
+ }
+
+ } else {
+
+ if ((RegValue & WD_584_EEPROM_RAM_SIZE_MASK) ==
+ WD_584_EEPROM_RAM_SIZE_32K) {
+
+ *BoardIdMask |= RAM_SIZE_32K;
+
+ } else {
+
+ if ((RegValue & WD_584_EEPROM_RAM_SIZE_MASK) ==
+ WD_584_EEPROM_RAM_SIZE_64K) {
+
+ if (!(*BoardIdMask & BOARD_16BIT)) {
+
+ *BoardIdMask |= RAM_SIZE_64K;
+
+ } else {
+
+ if (!(*BoardIdMask & SLOT_16BIT)) {
+
+ *BoardIdMask |= RAM_SIZE_32K;
+
+ } else {
+
+ *BoardIdMask |= RAM_SIZE_64K;
+
+ }
+
+ }
+
+ } else {
+
+ *BoardIdMask |= RAM_SIZE_UNKNOWN;
+
+ }
+
+ }
+
+ }
+
+ }
+
+
+ IF_LMI_LOUD(DbgPrint("RamSize: Id is now 0x%x\n",*BoardIdMask));
+
+ //
+ // RecallLanAddressFromEEProm(NdisAdapterHandle, BaseAddr);
+ //
+
+
+
+ NdisReadPortUchar(NdisAdapterHandle, BaseAddr + WD_REG_1, &RegValue);
+
+ RegValue &= WD_584_ICR_MASK;
+
+ RegValue |= WD_584_OTHER_BIT;
+
+ NdisWritePortUchar(NdisAdapterHandle, BaseAddr + WD_REG_1, RegValue);
+
+
+ NdisReadPortUchar(NdisAdapterHandle, BaseAddr + WD_REG_3, &RegValue);
+
+ RegValue &= WD_584_EAR_MASK;
+
+ RegValue |= WD_584_EA6;
+
+ NdisWritePortUchar(NdisAdapterHandle, BaseAddr + WD_REG_3, RegValue);
+
+
+ NdisReadPortUchar(NdisAdapterHandle, BaseAddr + WD_REG_1, &RegValue);
+
+ RegValue &= WD_584_ICR_MASK;
+
+ RegValue |= WD_584_RLA;
+
+ NdisWritePortUchar(NdisAdapterHandle, BaseAddr + WD_REG_1, RegValue);
+
+ NdisReadPortUchar(NdisAdapterHandle, BaseAddr + WD_REG_1, &RegValue);
+
+ while (RegValue & WD_584_RECALL_DONE) {
+
+ NdisReadPortUchar(NdisAdapterHandle, BaseAddr + WD_REG_1, &RegValue);
+
+ }
+
+ IF_LMI_LOUD(DbgPrint("Exiting GetEEPromInfo: Id is now 0x%x\n",*BoardIdMask));
+
+}
+
+
+#pragma NDIS_INIT_FUNCTION(CardGetRamSize)
+
+VOID
+CardGetRamSize(
+ IN NDIS_HANDLE NdisAdapterHandle,
+ IN UINT BaseAddr,
+ IN BOOLEAN Mca,
+ IN UINT RevNumber,
+ OUT PULONG BoardIdMask
+ )
+/*++
+
+Routine Description:
+
+ This routine will get the following information about the card:
+ Ram size.
+
+ The card must be either Mca and have a RevNumber > 2, or any kind of
+ bus and a RevNumber < 3 for this routine to work.
+
+Arguments:
+
+ NdisAdapterHandle - Handle returned by Ndis after NdisRegisterAdapter call.
+
+ BaseAddr - The base address for I/O to the board.
+
+ Mca - TRUE if the machine is micro-channel, else the machine is AT.
+
+ RevNumber - The reversion number of the board.
+
+ BoardIdMask - Returns the feature mask of the installed board.
+
+
+Return:
+
+ none.
+
+--*/
+{
+ UCHAR RegValue;
+
+ //
+ // if (RevNumber < 2) then
+ //
+ // if (Mca) then
+ //
+ // AddFeatureBits(RAM_SIZE_16K);
+ //
+ // else
+ //
+ // if (16BitBus) then
+ //
+ // if (16BitSlot) then
+ //
+ // AddFeatureBits(RAM_SIZE_16K);
+ //
+ // else
+ //
+ // AddFeatureBits(RAM_SIZE_8K);
+ //
+ // else
+ //
+ // if (!HaveInterfaceChip) then
+ //
+ // AddFeatureBits(RAM_SIZE_UNKNOWN);
+ //
+ // else
+ //
+ // ReadFromChipRamSize();
+ // else
+ //
+ // switch (CardType)
+ //
+ // case WD8003E:
+ // case WD8003S:
+ // case WD8003WT:
+ // case WD8003W:
+ // case WD8003EB:
+ //
+ // if (CardSaysLargeRam) then
+ //
+ // AddFeatureBits(RAM_SIZE_32K);
+ //
+ // else
+ //
+ // AddFeatureBits(RAM_SIZE_8K);
+ //
+ // break;
+ //
+ // case MICROCHANNEL:
+ //
+ // if (CardSaysLargeRam) then
+ //
+ // AddFeatureBits(RAM_SIZE_64K);
+ //
+ // else
+ //
+ // AddFeatureBits(RAM_SIZE_16K);
+ //
+ // break;
+ //
+ // case WD8013EBT:
+ //
+ // if (16BitSlot) then
+ //
+ //
+ // if (CardSaysLargeRam) then
+ //
+ // AddFeatureBits(RAM_SIZE_64K);
+ //
+ // else
+ //
+ // AddFeatureBits(RAM_SIZE_16K);
+ //
+ // else
+ //
+ // if (CardSaysLargeRam) then
+ //
+ // AddFeatureBits(RAM_SIZE_32K);
+ //
+ // else
+ //
+ // AddFeatureBits(RAM_SIZE_8K);
+ //
+ // break;
+ //
+ // default:
+ //
+ // AddFeatureBits(RAM_SIZE_UNKNOWN);
+ //
+
+
+
+
+
+ if (RevNumber < 2) {
+
+ if (Mca) {
+
+ *BoardIdMask |= RAM_SIZE_16K;
+
+ } else {
+
+ if (*BoardIdMask & BOARD_16BIT) {
+
+ if (*BoardIdMask & SLOT_16BIT) {
+
+ *BoardIdMask |= RAM_SIZE_16K;
+
+ } else {
+
+ *BoardIdMask |= RAM_SIZE_8K;
+
+ }
+
+ } else {
+
+ if (!(*BoardIdMask & INTERFACE_CHIP)) {
+
+ *BoardIdMask |= RAM_SIZE_8K;
+
+ } else {
+
+ NdisReadPortUchar(NdisAdapterHandle,
+ BaseAddr + WD_REG_1,
+ &RegValue
+ );
+
+ if (RegValue & WD_MSB_583_BIT) {
+
+ *BoardIdMask |= RAM_SIZE_32K;
+
+ } else {
+
+ *BoardIdMask |= RAM_SIZE_8K;
+
+ }
+
+ }
+
+ }
+
+ }
+
+ } else {
+
+
+ NdisReadPortUchar(NdisAdapterHandle,
+ BaseAddr + WD_ID_BYTE,
+ &RegValue
+ );
+
+ if (*BoardIdMask & MICROCHANNEL) {
+
+ if (RegValue & WD_RAM_SIZE_BIT) {
+
+ *BoardIdMask |= RAM_SIZE_64K;
+
+ } else {
+
+ *BoardIdMask |= RAM_SIZE_16K;
+
+ }
+
+ } else {
+
+ switch (*BoardIdMask & STATIC_ID_MASK) {
+
+ case WD8003E:
+ case WD8003S:
+ case WD8003WT:
+ case WD8003W:
+ case WD8003EB:
+
+ if (RegValue & WD_RAM_SIZE_BIT) {
+
+ *BoardIdMask |= RAM_SIZE_32K;
+
+ } else {
+
+ *BoardIdMask |= RAM_SIZE_8K;
+
+ }
+
+ break;
+
+ case WD8013EBT:
+
+ if (*BoardIdMask & SLOT_16BIT) {
+
+ if (RegValue & WD_RAM_SIZE_BIT) {
+
+ *BoardIdMask |= RAM_SIZE_64K;
+
+ } else {
+
+ *BoardIdMask |= RAM_SIZE_16K;
+
+ }
+
+ } else {
+
+ if (RegValue & WD_RAM_SIZE_BIT) {
+
+ *BoardIdMask |= RAM_SIZE_32K;
+
+ } else {
+
+ *BoardIdMask |= RAM_SIZE_8K;
+
+ }
+ }
+
+ break;
+
+ default:
+
+ *BoardIdMask |= RAM_SIZE_UNKNOWN;
+
+ }
+
+ }
+
+ }
+
+}
+
+
+#pragma NDIS_INIT_FUNCTION(CardCheckFor690)
+
+BOOLEAN
+CardCheckFor690(
+ IN NDIS_HANDLE NdisAdapterHandle,
+ IN UINT BaseAddr
+ )
+/*++
+
+Routine Description:
+
+ This routine will determine if there the card has a 690 chip or the
+ older 8390 chips.
+
+Arguments:
+
+ NdisAdapterHandle - Handle returned by Ndis after NdisRegisterAdapter call.
+
+ BaseAddr - The base address for I/O to the board.
+
+
+Return:
+
+ TRUE if there is a 690, else FALSE (it is 8390 chip).
+
+--*/
+
+{
+
+ //
+ // Old register values.
+ //
+
+ UCHAR NICSave;
+ UCHAR TCRSave;
+
+
+ UCHAR TCRValue;
+
+
+ //
+ // NICSave = GetCurrentRegisterValue(NICRegister);
+ //
+
+ NdisReadPortUchar(NdisAdapterHandle, BaseAddr + WD_690_CR, &NICSave);
+
+ NICSave = NICSave & (UCHAR)(~(UCHAR)WD_690_TXP);
+
+
+ //
+ // SwitchToPage2();
+ //
+
+
+ NdisWritePortUchar(NdisAdapterHandle,
+ BaseAddr + WD_690_CR,
+ (UCHAR)((NICSave & WD_690_PSMASK) | WD_690_PS2)
+ );
+
+
+ //
+ // TCRSave = GetCurrentRegisterValue(TCRRegister);
+ //
+
+ NdisReadPortUchar(NdisAdapterHandle,
+ BaseAddr + WD_690_CR + WD_690_TCR,
+ &TCRSave
+ );
+
+
+ //
+ // SwitchToPage0();
+ //
+
+ NdisWritePortUchar(NdisAdapterHandle,
+ BaseAddr + WD_690_CR,
+ (UCHAR)((NICSave & WD_690_PSMASK) | WD_690_PS0)
+ );
+
+
+ //
+ // WriteRegister(TCRRegister, TestValue);
+ //
+
+ NdisWritePortUchar(NdisAdapterHandle,
+ BaseAddr + WD_690_CR + WD_690_TCR,
+ WD_690_TCR_TEST_VAL
+ );
+
+
+ //
+ // SwitchToPage2();
+ //
+
+ NdisWritePortUchar(NdisAdapterHandle,
+ BaseAddr + WD_690_CR,
+ (UCHAR)((NICSave & WD_690_PSMASK) | WD_690_PS2)
+ );
+
+ //
+ // TCRValue = GetCurrentRegisterValue(TCRRegister);
+ //
+
+ NdisReadPortUchar(NdisAdapterHandle,
+ BaseAddr + WD_690_CR + WD_690_TCR,
+ &TCRValue
+ );
+
+
+ //
+ // SwitchToPage0();
+ //
+
+ NdisWritePortUchar(NdisAdapterHandle,
+ BaseAddr + WD_690_CR,
+ (UCHAR)((NICSave & WD_690_PSMASK) | WD_690_PS0)
+ );
+
+ //
+ // WriteRegister(TCRRegister, TCRSave);
+ //
+
+ NdisWritePortUchar(NdisAdapterHandle,
+ BaseAddr + WD_690_CR + WD_690_TCR,
+ TCRSave
+ );
+
+ //
+ // WriteRegister(NICRegister, NICSave);
+ //
+
+ NdisWritePortUchar(NdisAdapterHandle,
+ BaseAddr + WD_690_CR,
+ NICSave
+ );
+
+ return((TCRValue & WD_690_TCR_TEST_VAL) != (UCHAR)WD_690_TCR_TEST_VAL);
+
+}
+
+
+
+#pragma NDIS_INIT_FUNCTION(CardGetConfig)
+
+UINT
+CardGetConfig(
+ IN NDIS_HANDLE NdisAdapterHandle,
+ IN UINT BaseAddr,
+ IN BOOLEAN Mca,
+ OUT PCNFG_Adapter Config
+ )
+/*++
+
+Routine Description:
+
+ This routine will get the configuration information about the card.
+
+
+Arguments:
+
+ NdisAdapterHandle - Handle returned by Ndis after NdisRegisterAdapter call.
+
+ BaseAddr - The base address for I/O to the board.
+
+ Mca - TRUE if the machine is micro-channel, else the machine is AT.
+
+ Config - a structure with the configuration info.
+
+
+Return:
+
+ 0, if found board and configuration information retrieved.
+ 1, if found board and no configuration.
+ -1, if board not found.
+
+--*/
+{
+ UCHAR RegValue1, RegValue2;
+ USHORT RegValue;
+
+ UNREFERENCED_PARAMETER(BaseAddr);
+
+ if (Mca) {
+
+ //
+ // Get McaConfig
+ //
+
+
+
+ Config->cnfg_bus = 1;
+
+ //
+ // if (594Group()) then
+ //
+ // ReturnValue = Get594ConfigInfo();
+ //
+ // else if (593Group()) then
+ //
+ // ReturnValue = Get593ConfigInfo();
+ //
+ // else
+ //
+ // return(-1);
+ //
+
+ RegValue = Config->PosData.AdapterId;
+
+ Config->cnfg_pos_id = RegValue;
+
+ switch (RegValue) {
+
+ case CNFG_ID_8003E:
+ case CNFG_ID_8003S:
+ case CNFG_ID_8003W:
+ case CNFG_ID_BISTRO03E:
+
+ Config->cnfg_bic_type = BIC_593_CHIP;
+
+ //
+ // Get593Io();
+ //
+
+ RegValue1 = Config->PosData.PosData1;
+
+ RegValue1 &= 0xFE;
+
+ Config->cnfg_base_io = (USHORT)(RegValue1 << 4);
+
+
+
+ //
+ // Get593Irq();
+ //
+
+ RegValue1 = Config->PosData.PosData4;
+
+ RegValue1 &= 0x3;
+
+ if (RegValue1 == 0) {
+
+ Config->cnfg_irq_line = 3;
+
+ } else if (RegValue1 == 1) {
+
+ Config->cnfg_irq_line = 4;
+
+ } else if (RegValue1 == 2) {
+
+ Config->cnfg_irq_line = 10;
+
+ } else {
+
+ Config->cnfg_irq_line = 15;
+
+ }
+
+
+
+ //
+ // Get593RamBase();
+ //
+
+ RegValue1 = Config->PosData.PosData2;
+
+ RegValue1 = (RegValue1 & (UCHAR)0xFC);
+
+ Config->cnfg_ram_base = (ULONG)RegValue1 << 12;
+
+
+
+ //
+ // Get593RamSize();
+ //
+
+ Config->cnfg_ram_size = CNFG_SIZE_16KB;
+ Config->cnfg_ram_usable = CNFG_SIZE_16KB;
+
+
+
+ //
+ // Get593RomBase();
+ //
+
+ RegValue1 = Config->PosData.PosData3;
+
+ RegValue1 = (RegValue1 & (UCHAR)0xFC);
+
+ Config->cnfg_rom_base = (ULONG)RegValue1 << 12;
+
+
+ //
+ // Get593RomSize();
+ //
+
+ RegValue1 = Config->PosData.PosData3;
+
+ RegValue1 &= 0x03;
+
+ if (RegValue1 == 0) {
+
+ Config->cnfg_rom_size = CNFG_SIZE_16KB;
+
+ } else if (RegValue1 == 1) {
+
+ Config->cnfg_rom_size = CNFG_SIZE_32KB;
+
+ } else if (RegValue1 == 2) {
+
+ Config->cnfg_rom_size = ROM_DISABLE;
+
+ } else {
+
+ Config->cnfg_rom_size = CNFG_SIZE_64KB;
+
+ }
+
+
+ break;
+
+ case CNFG_ID_8013E:
+ case CNFG_ID_8013W:
+ case CNFG_ID_8115TRA:
+ case CNFG_ID_BISTRO13E:
+ case CNFG_ID_BISTRO13W:
+
+
+ Config->cnfg_bic_type = BIC_594_CHIP;
+
+ //
+ // Get594Io();
+ //
+
+ RegValue1 = Config->PosData.PosData1;
+
+ RegValue1 &= 0xF0;
+
+ Config->cnfg_base_io = ((USHORT)RegValue1 << 8) | (USHORT)0x800;
+
+
+
+ //
+ // Get594Irq();
+ //
+
+ RegValue1 = Config->PosData.PosData4;
+
+ RegValue1 &= 0xC;
+
+ if (RegValue1 == 0) {
+
+ Config->cnfg_irq_line = 3;
+
+ } else if (RegValue1 == 0x4) {
+
+ Config->cnfg_irq_line = 4;
+
+ } else if (RegValue1 == 0x8) {
+
+ Config->cnfg_irq_line = 10;
+
+ } else {
+
+ Config->cnfg_irq_line = 14;
+
+ }
+
+
+
+ //
+ // Get594RamBase();
+ //
+
+ RegValue1 = Config->PosData.PosData2;
+
+ if (RegValue1 & 0x8) { // Above cseg
+
+ if (RegValue1 & 0x80) { // above 1 meg
+
+ Config->cnfg_ram_base = ((ULONG)(RegValue1 & 0x7) << 13)
+ + 0xFD0000;
+
+ } else {
+
+ Config->cnfg_ram_base = ((ULONG)(RegValue1 & 0x7) << 13)
+ + 0x0D0000;
+
+
+ }
+
+ } else {
+
+ if (RegValue1 & 0x80) { // above 1 meg
+
+ Config->cnfg_ram_base = ((ULONG)(RegValue1 & 0x7) << 13)
+ + 0xFC0000;
+
+ } else {
+
+ Config->cnfg_ram_base = ((ULONG)(RegValue1 & 0x7) << 13)
+ + 0x0C0000;
+
+
+ }
+
+ }
+
+
+ //
+ // Get594RamSize();
+ //
+
+ RegValue1 &= 0x30;
+
+ RegValue1 >>= 4;
+
+ Config->cnfg_ram_usable = (USHORT)CNFG_SIZE_8KB << RegValue1;
+
+
+ if (RegValue == CNFG_ID_8115TRA) {
+
+ Config->cnfg_ram_size = (USHORT)CNFG_SIZE_64KB;
+
+ } else {
+
+ Config->cnfg_ram_size = Config->cnfg_ram_usable;
+
+ }
+
+
+
+
+ //
+ // Get594RomBase();
+ //
+
+ RegValue1 = Config->PosData.PosData3;
+
+ if (RegValue1 & 0x8) { // Above cseg
+
+ Config->cnfg_rom_base = ((ULONG)(RegValue1 & 0x7) << 13)
+ + 0xD0000;
+
+ } else {
+
+ Config->cnfg_rom_base = ((ULONG)(RegValue1 & 0x7) << 13)
+ + 0x0C0000;
+
+ }
+
+
+
+
+ //
+ // Get594RomSize();
+ //
+
+ RegValue1 >>= 4;
+
+ if (RegValue1 == 0) {
+
+ Config->cnfg_rom_size = CNFG_SIZE_8KB;
+
+ } else if (RegValue1 == 1) {
+
+ Config->cnfg_rom_size = CNFG_SIZE_16KB;
+
+ } else if (RegValue1 == 2) {
+
+ Config->cnfg_rom_size = CNFG_SIZE_32KB;
+
+ } else {
+
+ Config->cnfg_rom_size = ROM_DISABLE;
+
+ }
+
+
+
+
+ //
+ // Get594MediaType();
+ //
+
+ RegValue1 = Config->PosData.PosData4;
+
+ RegValue1 &= CNFG_MEDIA_TYPE_MASK;
+
+ Config->cnfg_media_type = RegValue1;
+
+ break;
+
+ default:
+
+ return((UINT)-1);
+
+ }
+
+ //
+ // GetBoardId();
+ //
+
+ CardGetBoardId(NdisAdapterHandle,
+ Config->cnfg_base_io,
+ Mca,
+ &(Config->cnfg_bid));
+
+ return(0);
+
+ } else {
+
+ //
+ // Get AtConfig
+ //
+
+ Config->cnfg_bus = 0;
+
+ //
+ // if (!BoardIsThere()) then
+ //
+ // return(-1);
+ //
+
+ RegValue2 = 0;
+
+ for (RegValue = 0; RegValue < 8; RegValue++) {
+
+ NdisReadPortUchar(NdisAdapterHandle,
+ Config->cnfg_base_io + 0x8 + RegValue,
+ &RegValue1
+ );
+
+ IF_LMI_LOUD(DbgPrint("First number is 0x%x\n", RegValue1));
+
+ RegValue2 += RegValue1;
+
+ }
+
+ if (RegValue2 != 0xFF) {
+
+ IF_LMI_LOUD(DbgPrint("The sum was 0x%x\n", RegValue2));
+
+ return((UINT)-1);
+
+ }
+
+
+
+ //
+ // GetBoardId();
+ //
+
+ CardGetBoardId(NdisAdapterHandle,
+ Config->cnfg_base_io,
+ Mca,
+ &(Config->cnfg_bid));
+
+
+ IF_LMI_LOUD(DbgPrint("Got Board Id. Mask is 0x%x\n", Config->cnfg_bid));
+
+ //
+ // CopyRamSize();
+ //
+
+ if (((Config->cnfg_bid & RAM_SIZE_MASK) != RAM_SIZE_8K) &&
+ ((Config->cnfg_bid & RAM_SIZE_MASK) != RAM_SIZE_64K)) {
+
+ IF_LMI_LOUD(DbgPrint("here\n"));
+
+ Config->cnfg_ram_size = (USHORT)CNFG_SIZE_8KB <<
+ (((Config->cnfg_bid & (ULONG)RAM_SIZE_MASK) >> 16) - 2);
+
+ if (Config->cnfg_bid & PAGED_RAM) {
+
+ Config->cnfg_ram_usable = CNFG_SIZE_16KB;
+
+ } else {
+
+ Config->cnfg_ram_usable = Config->cnfg_ram_size;
+
+ }
+
+ } else {
+
+ Config->cnfg_ram_usable = Config->cnfg_ram_size;
+
+ }
+
+ //
+ // if (ThereIsAnInterfaceChip) then
+ //
+ // GetChipConfigInfo();
+ // return(0);
+ //
+ // else
+ //
+ // VerifyLanAddrIsWd();
+ // return(1);
+ //
+
+
+ if (!(Config->cnfg_bid & INTERFACE_CHIP)) {
+
+ Config->cnfg_bic_type = BIC_NO_CHIP;
+
+ NdisReadPortUchar(NdisAdapterHandle,
+ Config->cnfg_base_io + 0x8,
+ &RegValue1
+ );
+
+ if (RegValue1 != 0x00) {
+
+ return((UINT)-1);
+
+ }
+
+ NdisReadPortUchar(NdisAdapterHandle,
+ Config->cnfg_base_io + 0x9,
+ &RegValue1
+ );
+
+ if (RegValue1 != 0x00) {
+
+ return((UINT)-1);
+
+ }
+
+ NdisReadPortUchar(NdisAdapterHandle,
+ Config->cnfg_base_io + 0xA,
+ &RegValue1
+ );
+
+ if (RegValue1 != 0xC0) {
+
+ return((UINT)-1);
+
+ }
+
+ return(1);
+
+ }
+
+ //
+ // Store BIC type.
+ //
+
+
+ if ((Config->cnfg_bid & INTERFACE_CHIP_MASK) == INTERFACE_5X3_CHIP) {
+
+ Config->cnfg_bic_type = BIC_583_CHIP;
+
+ } else {
+
+ Config->cnfg_bic_type = BIC_584_CHIP;
+
+ }
+
+ //
+ // Get58xIrq();
+ //
+
+ RegValue1 = 0;
+
+ if ((Config->cnfg_bid & INTERFACE_CHIP_MASK) != INTERFACE_5X3_CHIP) {
+
+ NdisReadPortUchar(NdisAdapterHandle,
+ Config->cnfg_base_io + CNFG_ICR_583,
+ &RegValue1
+ );
+
+ IF_LMI_LOUD(DbgPrint("When reading for IRQ, I got 0x%x for RegValue1\n", RegValue1));
+
+ RegValue1 &= CNFG_ICR_IR2_584;
+
+ }
+
+ NdisReadPortUchar(NdisAdapterHandle,
+ Config->cnfg_base_io + CNFG_IRR_583,
+ &RegValue2
+ );
+
+ IF_LMI_LOUD(DbgPrint("When reading for IRQ, I got 0x%x for RegValue2\n", RegValue2));
+
+ RegValue2 &= CNFG_IRR_IRQS;
+
+ IF_LMI_LOUD(DbgPrint("RegValue2 is now 0x%x\n", RegValue2));
+
+ RegValue2 >>= 5;
+
+ IF_LMI_LOUD(DbgPrint("RegValue2 is now 0x%x\n", RegValue2));
+
+ if (RegValue2 == 0) {
+
+ if (RegValue1 == 0) {
+
+ Config->cnfg_irq_line = 2;
+
+ } else {
+
+ Config->cnfg_irq_line = 10;
+
+ }
+
+ } else if (RegValue2 == 1) {
+
+ if (RegValue1 == 0) {
+
+ Config->cnfg_irq_line = 3;
+
+ } else {
+
+ Config->cnfg_irq_line = 11;
+
+ }
+
+ } else if (RegValue2 == 2) {
+
+ if (RegValue1 == 0) {
+
+ if (Config->cnfg_bid & ALTERNATE_IRQ_BIT) {
+
+ Config->cnfg_irq_line = 5;
+
+ } else {
+
+ Config->cnfg_irq_line = 4;
+
+ }
+
+ } else {
+
+ Config->cnfg_irq_line = 15;
+
+ }
+
+ } else if (RegValue2 == 3) {
+
+ if (RegValue1 == 0) {
+
+ Config->cnfg_irq_line = 7;
+
+ } else {
+
+ Config->cnfg_irq_line = 4;
+
+ }
+
+ } else {
+
+ //
+ // ERROR! Choose 3.
+ //
+
+ IF_LMI_LOUD(DbgPrint("Error, could not find IRQL. Choosing 3.\n"));
+
+ Config->cnfg_irq_line = 3;
+
+ }
+
+
+ //
+ // Get58xIrqStatus();
+ //
+
+ NdisReadPortUchar(NdisAdapterHandle,
+ Config->cnfg_base_io + CNFG_IRR_583,
+ &RegValue1
+ );
+
+ Config->cnfg_mode_bits1 &= (~INTERRUPT_STATUS_BIT);
+
+ if (RegValue1 & INTERRUPT_STATUS_BIT) {
+
+ Config->cnfg_mode_bits1 |= INTERRUPT_STATUS_BIT;
+
+ }
+
+
+ //
+ // Get58xRamBase();
+ //
+
+ NdisReadPortUchar(NdisAdapterHandle, Config->cnfg_base_io, &RegValue1);
+
+ IF_LMI_LOUD(DbgPrint("When reading for RAM base, I got 0x%x for RegValue1\n", RegValue1));
+
+ RegValue1 &= 0x3F;
+
+ if ((Config->cnfg_bid & INTERFACE_CHIP_MASK) == INTERFACE_5X3_CHIP) {
+
+ RegValue1 |= 0x40;
+
+ Config->cnfg_ram_base = (ULONG)RegValue1 << 13;
+
+ } else {
+
+ NdisReadPortUchar(NdisAdapterHandle,
+ Config->cnfg_base_io + CNFG_LAAR_584,
+ &RegValue2
+ );
+
+ RegValue2 &= CNFG_LAAR_MASK;
+
+ RegValue2 <<= 3;
+
+ RegValue2 |= ((RegValue1 & 0x38) >> 3);
+
+ Config->cnfg_ram_base = ((ULONG)RegValue2 << 16) + (((ULONG)(RegValue1 & 0x7)) << 13);
+
+ }
+
+ //
+ // Get58xRomBase();
+ //
+
+ NdisReadPortUchar(NdisAdapterHandle,
+ Config->cnfg_base_io + CNFG_BIO_583,
+ &RegValue1
+ );
+
+ IF_LMI_LOUD(DbgPrint("When reading for ROM base, I got 0x%x for RegValue1\n", RegValue1));
+
+ RegValue1 &= 0x3E;
+
+ RegValue1 |= 0x40;
+
+ Config->cnfg_rom_base = (ULONG)RegValue1 << 13;
+
+
+
+
+ //
+ // Get58xRomSize();
+ //
+
+ NdisReadPortUchar(NdisAdapterHandle,
+ Config->cnfg_base_io + CNFG_BIO_583,
+ &RegValue1
+ );
+
+ IF_LMI_LOUD(DbgPrint("When reading for ROM size, I got 0x%x for RegValue1\n", RegValue1));
+
+ RegValue1 &= 0xC0;
+
+ if (RegValue1 == 0) {
+
+ Config->cnfg_rom_size = ROM_DISABLE;
+
+ } else {
+
+ RegValue1 >>= 6;
+
+ Config->cnfg_rom_size = (USHORT)CNFG_SIZE_8KB << RegValue1;
+
+ }
+
+
+
+
+
+
+ //
+ // Get58xBootStatus();
+ //
+
+ NdisReadPortUchar(NdisAdapterHandle,
+ Config->cnfg_base_io + CNFG_GP2,
+ &RegValue1
+ );
+
+ IF_LMI_LOUD(DbgPrint("When reading for Boot Status, I got 0x%x for RegValue1\n", RegValue1));
+
+ IF_LMI_LOUD(DbgPrint("Config mode bits are 0x%x\n", Config->cnfg_mode_bits1));
+
+ Config->cnfg_mode_bits1 &= (~BOOT_STATUS_MASK);
+
+ if (RegValue1 & CNFG_GP2_BOOT_NIBBLE) {
+
+ Config->cnfg_mode_bits1 |= BOOT_TYPE_1;
+
+ }
+
+
+
+ //
+ // Get58xZeroWaitState();
+ //
+
+ NdisReadPortUchar(NdisAdapterHandle,
+ Config->cnfg_base_io + CNFG_IRR_583,
+ &RegValue1
+ );
+
+ IF_LMI_LOUD(DbgPrint("When reading for ZWS, I got 0x%x for RegValue1\n", RegValue1));
+
+ Config->cnfg_mode_bits1 &= (~ZERO_WAIT_STATE_MASK);
+
+ if (RegValue1 & CNFG_IRR_ZWS) {
+
+ Config->cnfg_mode_bits1 |= ZERO_WAIT_STATE_8_BIT;
+
+ }
+
+ if (Config->cnfg_bid & BOARD_16BIT) {
+
+ NdisReadPortUchar(NdisAdapterHandle,
+ Config->cnfg_base_io + CNFG_LAAR_584,
+ &RegValue1
+ );
+
+ IF_LMI_LOUD(DbgPrint("When reading for ZWS16, I got 0x%x for RegValue1\n", RegValue1));
+
+ if (RegValue1 & CNFG_LAAR_ZWS) {
+
+ Config->cnfg_mode_bits1 |= ZERO_WAIT_STATE_16_BIT;
+
+ }
+
+ }
+
+
+ //
+ // GetAdvancedFeatures();
+ //
+
+ NdisReadPortUchar(NdisAdapterHandle,
+ Config->cnfg_base_io + CNFG_IRR_583,
+ &RegValue1
+ );
+
+ Config->cnfg_mode_bits1 &= (~CNFG_INTERFACE_TYPE_MASK);
+
+ if (Config->cnfg_bid & ADVANCED_FEATURES) {
+
+ Config->cnfg_mode_bits1 |= ZERO_WAIT_STATE_8_BIT;
+
+ }
+
+ if ((RegValue1 & 0x6) == 2) {
+
+ Config->cnfg_mode_bits1 |= STARLAN_10_INTERFACE;
+ Config->cnfg_media_type = MEDIA_S10;
+
+ } else if ((RegValue1 & 0x6) == 4) {
+
+ Config->cnfg_mode_bits1 |= BNC_INTERFACE;
+ Config->cnfg_media_type = MEDIA_BNC;
+
+ } else {
+
+ Config->cnfg_mode_bits1 |= AUI_10BT_INTERFACE;
+ Config->cnfg_media_type = MEDIA_AUI_UTP;
+
+ }
+
+
+ return(0);
+
+ }
+
+}
+
+
+BOOLEAN
+CardSetup(
+ Ptr_Adapter_Struc Adapt
+ )
+/*++
+
+Routine Description:
+
+ This routine will setup the Receive and transmit spaces of the card.
+
+
+Arguments:
+
+ Adapt - A pointer to an LMI adapter structure.
+
+Return:
+
+ TRUE if successful, else FALSE
+
+--*/
+{
+ ULONG i;
+ UCHAR SaveValue;
+ UCHAR RegValue;
+ BOOLEAN NoLoad;
+
+
+
+ //
+ // Reset IC
+ //
+
+ NdisReadPortUchar(Adapt->NdisAdapterHandle,
+ Adapt->io_base + MEMORY_SELECT_REG,
+ &SaveValue
+ );
+
+ RegValue = SaveValue | (UCHAR)RESET;
+
+ NdisWritePortUchar(Adapt->NdisAdapterHandle,
+ Adapt->io_base + MEMORY_SELECT_REG,
+ RegValue
+ );
+
+ //
+ // Wait for reset to complete. (2 ms)
+ //
+
+ UM_Delay(2000);
+
+ //
+ // Put back original value
+ //
+
+ NdisWritePortUchar(Adapt->NdisAdapterHandle,
+ Adapt->io_base + MEMORY_SELECT_REG,
+ (UCHAR)(SaveValue & (~RESET))
+ );
+
+
+
+ //
+ // Enable Ram
+ //
+
+
+ if (Adapt->board_id & (MICROCHANNEL | INTERFACE_CHIP)) {
+
+ NdisReadPortUchar(Adapt->NdisAdapterHandle,
+ Adapt->io_base + MEMORY_ENABLE_RESET_REG,
+ &RegValue
+ );
+
+ NdisWritePortUchar(Adapt->NdisAdapterHandle,
+ Adapt->io_base + MEMORY_ENABLE_RESET_REG,
+ (UCHAR)((RegValue & ~RESET) | MEMORY_ENABLE)
+ );
+
+ } else {
+
+ RegValue = (((UCHAR)(((PUSHORT)Adapt->ram_base) + 2) << 3) |
+ (UCHAR)(Adapt->ram_base >> 13)
+ );
+
+ NdisWritePortUchar(Adapt->NdisAdapterHandle,
+ Adapt->io_base + MEMORY_ENABLE_RESET_REG,
+ (UCHAR)(RegValue | MEMORY_ENABLE)
+ );
+
+ }
+
+
+
+ //
+ // Load LAN Address
+ //
+
+ NoLoad = FALSE;
+
+
+ for (i=0; i < 6; i++) {
+
+ if (Adapt->node_address[i] != (UCHAR)0) {
+
+ NoLoad = TRUE;
+
+ }
+
+ }
+
+
+ for (i=0; i < 6; i++) {
+
+ //
+ // Read from IC
+ //
+
+ NdisReadPortUchar(Adapt->NdisAdapterHandle,
+ Adapt->io_base + LAN_ADDRESS_REG + i,
+ &(Adapt->permanent_node_address[i])
+ );
+
+
+ }
+
+ if (!NoLoad) {
+
+ for (i=0; i < 6 ; i++) {
+
+ Adapt->node_address[i] = Adapt->permanent_node_address[i];
+ }
+
+
+ }
+
+
+
+
+
+ //
+ // Init NIC
+ //
+
+ //
+ // Maintain reset
+ //
+
+ NdisWritePortUchar(Adapt->NdisAdapterHandle,
+ Adapt->io_base + COMMAND_REG,
+ STOP | REMOTE_ABORT_COMPLETE
+ );
+
+ //
+ // Reset Remote_byte_count registers
+ //
+ NdisWritePortUchar(Adapt->NdisAdapterHandle,
+ Adapt->io_base + REMOTE_BYTE_COUNT_REG0,
+ 0
+ );
+ NdisWritePortUchar(Adapt->NdisAdapterHandle,
+ Adapt->io_base + REMOTE_BYTE_COUNT_REG1,
+ 0
+ );
+
+
+ //
+ // Make sure reset is bit is set
+ //
+
+ NdisReadPortUchar(Adapt->NdisAdapterHandle,
+ Adapt->io_base + INTERRUPT_STATUS_REG,
+ &RegValue
+ );
+
+ if (!(RegValue & RESET)) {
+
+ //
+ // Wait 1600 ms
+ //
+
+ UM_Delay(1600000);
+
+ }
+
+
+ RegValue = RECEIVE_FIFO_THRESHOLD_8 |
+ BURST_DMA_SELECT; // Fifo depth | DMA Burst select
+
+ if (Adapt->board_id & (MICROCHANNEL | SLOT_16BIT)) {
+
+ // Allow 16 bit transfers
+
+ RegValue |= WORD_TRANSFER_SELECT;
+
+ }
+
+ IF_LMI_LOUD(DbgPrint("Writing 0x%x to DCON\n", RegValue));
+
+ NdisWritePortUchar(Adapt->NdisAdapterHandle,
+ Adapt->io_base + DATA_CONFIG_REG,
+ RegValue
+ );
+
+
+ //
+ // Set Receive Mask
+ //
+
+ LM_Set_Receive_Mask(Adapt);
+
+
+ //
+ // loopback operation while setting up rings.
+ //
+
+ NdisWritePortUchar(Adapt->NdisAdapterHandle,
+ Adapt->io_base + TRANSMIT_CONFIG_REG,
+ LOOPBACK_MODE2
+ );
+
+ //
+ // Write first Receive ring buffer number
+ //
+
+ NdisWritePortUchar(Adapt->NdisAdapterHandle,
+ Adapt->io_base + PAGE_START_REG,
+ Adapt->StartBuffer
+ );
+
+ //
+ // Write last Receive ring buffer number
+ //
+
+ NdisWritePortUchar(Adapt->NdisAdapterHandle,
+ Adapt->io_base + PAGE_STOP_REG,
+ Adapt->LastBuffer
+ );
+
+
+ //
+ // Write buffer number where the card cannot write beyond.
+ //
+
+ NdisWritePortUchar(Adapt->NdisAdapterHandle,
+ Adapt->io_base + BOUNDARY_REG,
+ Adapt->StartBuffer
+ );
+
+ //
+ // Clear all interrupt status bits
+ //
+
+ NdisWritePortUchar(Adapt->NdisAdapterHandle,
+ Adapt->io_base + INTERRUPT_STATUS_REG,
+ 0xFF
+ );
+
+
+ //
+ // Set Interrupt Mask
+ //
+
+ Adapt->InterruptMask = PACKET_RECEIVE_ENABLE |
+ PACKET_TRANSMIT_ENABLE |
+ RECEIVE_ERROR_ENABLE |
+ TRANSMIT_ERROR_ENABLE |
+ OVERWRITE_WARNING_ENABLE |
+ COUNTER_OVERFLOW_ENABLE;
+
+
+ NdisWritePortUchar(Adapt->NdisAdapterHandle,
+ Adapt->io_base + INTERRUPT_MASK_REG,
+ Adapt->InterruptMask
+ );
+
+ //
+ // Maintain reset and select page 1
+ //
+
+ NdisWritePortUchar(Adapt->NdisAdapterHandle,
+ Adapt->io_base + COMMAND_REG,
+ STOP | REMOTE_ABORT_COMPLETE | PAGE_SELECT_1
+ );
+
+
+
+
+ //
+ // Write physical address
+ //
+
+ for (i = 0; i < 6; i++) {
+
+ NdisWritePortUchar(Adapt->NdisAdapterHandle,
+ Adapt->io_base + PHYSICAL_ADDRESS_REG0 + i,
+ Adapt->node_address[i]
+ );
+ }
+
+
+ //
+ // Load next pointer.
+ //
+
+ NdisWritePortUchar(Adapt->NdisAdapterHandle,
+ Adapt->io_base + CURRENT_BUFFER_REG,
+ (UCHAR)(Adapt->StartBuffer + 1)
+ );
+
+
+ //
+ // Clear out shared memory.
+ //
+
+ NdisZeroMappedMemory((PVOID)(Adapt->ram_access), (Adapt->ram_usable * 1024));
+
+ //
+ // Init Command Register again.
+ //
+
+ NdisWritePortUchar(Adapt->NdisAdapterHandle,
+ Adapt->io_base + COMMAND_REG,
+ STOP | REMOTE_ABORT_COMPLETE
+ );
+
+
+ //
+ // If this is an MCA card then we need to set the EIL (Enable Interrupt
+ // Line) on the BIC. We will use the NIC Interrupt Mask Register
+ // to control which interrupts get through.
+ //
+
+ if (((Adapt->board_id & MICROCHANNEL) &&
+ ((Adapt->board_id & INTERFACE_CHIP_MASK) == INTERFACE_5X3_CHIP))
+ ||
+ ((Adapt->board_id & INTERFACE_CHIP_MASK) == INTERFACE_594_CHIP)) {
+
+ //
+ // Enable 59x Chip
+ //
+
+ NdisReadPortUchar(Adapt->NdisAdapterHandle,
+ Adapt->io_base + COMMUNICATION_CONTROL_REG,
+ &RegValue
+ );
+
+ NdisWritePortUchar(Adapt->NdisAdapterHandle,
+ Adapt->io_base + COMMUNICATION_CONTROL_REG,
+ (UCHAR)(RegValue | CCR_INTERRUPT_ENABLE)
+ );
+
+ }
+
+
+ if (!(Adapt->board_id & BOARD_16BIT)) {
+
+ return(TRUE);
+
+ }
+
+
+
+ //
+ // Init LAAR register
+ //
+
+ IF_LMI_LOUD(DbgPrint("Board_id is 0x%x\n",Adapt->board_id));
+
+ if (Adapt->board_id & MICROCHANNEL) {
+
+ Adapt->LaarHold = 0;
+
+ } else {
+
+ if (Adapt->board_id & INTERFACE_CHIP) {
+
+
+ NdisReadPortUchar(Adapt->NdisAdapterHandle,
+ Adapt->io_base + LA_ADDRESS_REG,
+ &RegValue
+ );
+
+ RegValue &= LAAR_MASK;
+
+ RegValue |= ((Adapt->ram_base + 2) >> 3);
+
+ Adapt->LaarHold = RegValue;
+
+ } else {
+
+ Adapt->LaarHold = INIT_LAAR_VALUE;
+
+ }
+
+ if (Adapt->board_id & SLOT_16BIT) {
+
+ Adapt->LaarHold |= LAN_16BIT_ENABLE;
+
+ }
+
+ IF_LMI_LOUD(DbgPrint("Writing 0x%x to LAAR\n",Adapt->LaarHold));
+
+ NdisWritePortUchar(Adapt->NdisAdapterHandle,
+ Adapt->io_base + LA_ADDRESS_REG,
+ Adapt->LaarHold
+ );
+
+ }
+
+ return(TRUE);
+
+}
+
+VOID
+CardSendPacket(
+ IN Ptr_Adapter_Struc Adapt
+ )
+/*++
+
+Routine Description:
+
+ This will fire off the packet in the NextBufToXmit field.
+
+Arguments:
+
+ Adapt - A pointer to an LMI adapter structure.
+
+Return:
+
+--*/
+{
+ PUCHAR BufferAddress;
+ USHORT BufferSize;
+
+ ASSERT(Adapt->TransmitInterruptPending == FALSE);
+
+ ASSERT(Adapt->CurBufXmitting == (XMIT_BUF)-1);
+
+ ASSERT(Adapt->NextBufToXmit != (XMIT_BUF)-1);
+
+ ASSERT(Adapt->BufferStatus[Adapt->NextBufToXmit] == FULL);
+
+
+
+ Adapt->CurBufXmitting = Adapt->NextBufToXmit;
+
+
+ //
+ // Update NextBufToXmit counter.
+ //
+
+ Adapt->NextBufToXmit++;
+
+ if (Adapt->NextBufToXmit == (XMIT_BUF)(Adapt->num_of_tx_buffs)) {
+
+ Adapt->NextBufToXmit = 0;
+
+ }
+
+
+
+ if (Adapt->BufferStatus[Adapt->NextBufToXmit] != FULL) {
+
+ Adapt->NextBufToXmit = (XMIT_BUF)-1;
+
+ }
+
+
+
+
+ BufferAddress = ((PUCHAR)Adapt->ram_base) +
+ (Adapt->CurBufXmitting * Adapt->xmit_buf_size);
+
+ BufferSize = (USHORT)(Adapt->PacketLens[Adapt->CurBufXmitting]);
+
+ //
+ // Write Buffer Address
+ //
+
+ NdisWritePortUchar(Adapt->NdisAdapterHandle,
+ Adapt->io_base + TRANSMIT_PAGE_START_REG,
+ (UCHAR)(((ULONG)BufferAddress) >> 8)
+ );
+
+ //
+ // Write size of buffer
+ //
+
+ NdisWritePortUchar(Adapt->NdisAdapterHandle,
+ Adapt->io_base + TRANSMIT_BYTE_COUNT_REG0,
+ (UCHAR)(BufferSize & 0xFF)
+ );
+
+ NdisWritePortUchar(Adapt->NdisAdapterHandle,
+ Adapt->io_base + TRANSMIT_BYTE_COUNT_REG1,
+ (UCHAR)(BufferSize >> 8)
+ );
+
+ if (Adapt->OverWriteHandling && !(Adapt->board_id & NIC_690_BIT)) {
+
+ Adapt->OverWriteStartTransmit = TRUE;
+
+ return;
+
+ } else {
+
+ Adapt->TransmitInterruptPending = TRUE;
+
+ IF_LOG(LOG('!'));
+
+ }
+
+ //
+ // Start transmit
+ //
+
+ NdisWritePortUchar(Adapt->NdisAdapterHandle,
+ Adapt->io_base + COMMAND_REG,
+ START | TRANSMIT_PACKET | REMOTE_ABORT_COMPLETE
+ );
+
+}
+
+VOID
+CardCopyDown(
+ IN Ptr_Adapter_Struc Adapt,
+ IN PNDIS_PACKET Packet
+ )
+/*++
+
+Routine Description:
+
+ This routine will copy down the data in a packet onto the card.
+
+Arguments:
+
+ Adapt - A pointer to an LMI adapter structure.
+
+ Packet - The packet to copy down.
+
+Return:
+
+--*/
+{
+ PUCHAR BufferAddress;
+ UINT UNALIGNED *NdisBufAddress;
+ UCHAR UNALIGNED *NdisBufRest;
+ PNDIS_BUFFER CurrentBuffer;
+ ULONG DataToTransfer;
+ UINT CurrentLength;
+ UINT NdisBufLength;
+
+ //
+ // if (Slot16Bit) then
+ //
+ // Enable 16Bit Memory Access;
+ //
+
+ if (Adapt->board_id & SLOT_16BIT) {
+
+ IF_LMI_LOUD(DbgPrint("Writing 0x%x to LAAR\n",Adapt->LaarHold | MEMORY_16BIT_ENABLE));
+
+ NdisWritePortUchar(Adapt->NdisAdapterHandle,
+ Adapt->io_base + LA_ADDRESS_REG,
+ (UCHAR)(Adapt->LaarHold | MEMORY_16BIT_ENABLE)
+ );
+
+ }
+
+
+
+ //
+ // GetVirtualAddressOfXmitBuffer();
+ //
+
+ BufferAddress = ((PUCHAR)(Adapt->ram_access)) +
+ (Adapt->NextBufToFill * Adapt->xmit_buf_size);
+
+ //
+ // Copy each buffer over.
+ //
+
+ NdisQueryPacket(Packet, NULL, NULL, &CurrentBuffer, NULL);
+
+ CurrentLength = 0;
+
+ while (CurrentBuffer) {
+
+ NdisQueryBuffer(CurrentBuffer, (PVOID *)&NdisBufAddress, &NdisBufLength);
+
+ if ((Adapt->board_id & MICROCHANNEL) &&
+ (!(Adapt->board_id & INTERFACE_594_CHIP))) {
+
+ //
+ // Then we have a bogon card which can only handle evenly
+ // aligned WORD transfers... do it by hand.
+ //
+
+ ULONG i, BytesToCopy, NumberToCopy;
+ UCHAR MissedBy;
+ PUINT AdapterAddress;
+ UINT UNALIGNED *NdisBufAddressSave = NdisBufAddress;
+
+ //
+ // Do first part to get the destination aligned.
+ //
+
+ MissedBy = (UCHAR)(((ULONG)BufferAddress) % sizeof(UINT));
+
+ AdapterAddress = (PUINT)(BufferAddress - MissedBy);
+
+ //
+ // Get current value of this word.
+ //
+
+ DataToTransfer = *AdapterAddress;
+
+
+ //
+ // OR in the bytes for the new part of this WORD.
+ //
+
+ NdisBufRest = (UCHAR UNALIGNED *)NdisBufAddress;
+
+ BytesToCopy = sizeof(UINT) - MissedBy;
+
+ if (NdisBufLength < BytesToCopy) {
+
+ BytesToCopy = NdisBufLength;
+
+ }
+
+ for (i = 0; i < BytesToCopy; i++) {
+
+ //
+ // Clear old value in this byte
+ //
+
+ DataToTransfer &= ~(0x00FF << ((MissedBy + i) * 8));
+
+
+ //
+ // Store new value - no sign extension plz.
+ //
+
+ DataToTransfer |= (((UINT)(*NdisBufRest)) << ((MissedBy + i) * 8) &
+ (0x00FF << ((MissedBy + i) * 8)));
+
+ NdisBufRest++;
+
+ }
+
+
+ //
+ // Store previous WORD
+ //
+
+ WD_MOVE_DWORD_TO_SHARED_RAM(AdapterAddress, DataToTransfer);
+
+ AdapterAddress++;
+
+
+
+
+
+ //
+ // Update location and bytes left to copy
+ //
+
+ NdisBufAddress = (UINT UNALIGNED *)NdisBufRest;
+
+ BytesToCopy = NdisBufLength - BytesToCopy;
+
+ ASSERT((((ULONG)AdapterAddress) % sizeof(UINT)) == 0);
+
+ //
+ // Now copy Dwords across.
+ //
+
+ NumberToCopy = BytesToCopy / sizeof(UINT);
+
+ for (i=0; i < NumberToCopy; i++) {
+
+ WD_MOVE_DWORD_TO_SHARED_RAM(AdapterAddress, *((PULONG)(NdisBufAddress)));
+
+ AdapterAddress++;
+
+ NdisBufAddress++;
+
+ }
+
+ if ((BytesToCopy % sizeof(UINT)) != 0){
+
+ //
+ // We have some residual to copy.
+ //
+
+ MissedBy = (UCHAR)(BytesToCopy % sizeof(UINT));
+
+ NdisBufRest = (UCHAR UNALIGNED *)NdisBufAddress;
+
+ DataToTransfer = 0;
+
+ for (i = 0; i < MissedBy; i++) {
+
+ DataToTransfer |= ((UINT)(*NdisBufRest)) << (i * 8);
+
+ NdisBufRest++;
+
+ }
+
+ WD_MOVE_DWORD_TO_SHARED_RAM(AdapterAddress, DataToTransfer);
+
+ }
+
+ NdisBufAddress = NdisBufAddressSave;
+
+ } else {
+
+ WD_MOVE_MEM_TO_SHARED_RAM(BufferAddress, (PUCHAR)NdisBufAddress, NdisBufLength);
+
+ }
+
+ BufferAddress += NdisBufLength;
+
+ CurrentLength += NdisBufLength;
+
+ NdisGetNextBuffer(CurrentBuffer, &CurrentBuffer);
+
+ }
+
+
+ //
+ // if (Slot16Bit) then
+ //
+ // TurnOff16BitMemoryAccess;
+ //
+
+ if (Adapt->board_id & SLOT_16BIT) {
+
+ IF_LMI_LOUD(DbgPrint("Writing 0x%x to LAAR\n",Adapt->LaarHold));
+
+ NdisWritePortUchar(Adapt->NdisAdapterHandle,
+ Adapt->io_base + LA_ADDRESS_REG,
+ Adapt->LaarHold
+ );
+
+ }
+
+ //
+ // if (PacketLength < MIN_PACKET_SIZE) then
+ //
+ // StoreSize = MIN_PACKET_SIZE;
+ //
+ // else
+ //
+ // StoreSize = PacketLength;
+ //
+
+ if (CurrentLength < 60) {
+
+ Adapt->PacketLens[Adapt->NextBufToFill] = 60;
+
+ } else {
+
+ Adapt->PacketLens[Adapt->NextBufToFill] = CurrentLength;
+
+ }
+
+}
+
+VOID
+CardHandleReceive(
+ IN Ptr_Adapter_Struc Adapt
+ )
+/*++
+
+Routine Description:
+
+ This will clear the receive ring of all received packets.
+
+Arguments:
+
+ Adapt - A pointer to an LMI adapter structure.
+
+Return:
+
+--*/
+{
+
+ UCHAR Current;
+ UCHAR Boundary;
+
+ PUCHAR BufferAddress;
+
+ UINT PacketSize;
+ UCHAR PacketStatus;
+ UCHAR NextPacket;
+
+ LM_STATUS Status;
+
+ NdisSynchronizeWithInterrupt(
+ &(Adapt->NdisInterrupt),
+ SyncGetCurrent,
+ Adapt
+ );
+
+ Current = Adapt->Current;
+
+
+ //
+ // Get BOUNDARY + 1 buffer pointer
+ //
+
+ NdisReadPortUchar(Adapt->NdisAdapterHandle,
+ Adapt->io_base + BOUNDARY_REG,
+ &Boundary
+ );
+
+
+ IF_LMI_LOUD(DbgPrint("Current Starts at 0x%x, Boundary at 0x%x\n",Current,Boundary));
+
+ Boundary++;
+
+ if (Boundary >= Adapt->LastBuffer) {
+
+ Boundary = Adapt->StartBuffer;
+
+ }
+
+ //
+ // DoReceives:
+ //
+ // while (BOUNDARY != CURRENT) then
+ //
+
+DoReceives:
+
+ while (Boundary != Current) {
+
+ //
+ // if (STARLAN) then
+ //
+
+ if ((Adapt->board_id & MEDIA_MASK) == STARLAN_MEDIA) {
+
+ //
+ // MapCURRENTToLocalAddressSpace();
+ //
+
+ BufferAddress = ((PUCHAR)(Adapt->ram_access)) +
+ Boundary * Adapt->buffer_page_size;
+
+ //
+ // GetReceiveStatus();
+ //
+
+ WD_MOVE_SHARED_RAM_TO_UCHAR(&PacketStatus, BufferAddress);
+
+ //
+ // GetNextPacketBufferNumber();
+ //
+
+ WD_MOVE_SHARED_RAM_TO_UCHAR(&NextPacket, BufferAddress + 1);
+
+ //
+ // GetPacketLength();
+ //
+
+ PacketSize = 0;
+
+ WD_MOVE_SHARED_RAM_TO_USHORT(&PacketSize, BufferAddress + 2);
+
+ PacketSize = PacketSize - (UINT)BufferAddress;
+
+ if (((INT)PacketSize) < 0) {
+
+ UINT Tmp;
+
+ PacketSize = (UINT)((Adapt->LastBuffer *
+ Adapt->buffer_page_size
+ )
+ - (UINT)BufferAddress);
+
+ Tmp = (NextPacket - Adapt->StartBuffer) - 1;
+
+ PacketSize += (Tmp * Adapt->buffer_page_size);
+
+ }
+
+ if ((PacketSize & 0xFF) > 0xFC) {
+
+ PacketSize += Adapt->buffer_page_size;
+ }
+
+ } else {
+
+ //
+ // if (Slot16Bit) then
+ //
+ // Enable16BitLAAR();
+ //
+
+ if (Adapt->board_id & SLOT_16BIT) {
+
+ IF_LMI_LOUD(DbgPrint("Writing 0x%x to LAAR\n",Adapt->LaarHold | MEMORY_16BIT_ENABLE));
+
+ NdisWritePortUchar(Adapt->NdisAdapterHandle,
+ Adapt->io_base + LA_ADDRESS_REG,
+ (UCHAR)(Adapt->LaarHold | MEMORY_16BIT_ENABLE)
+ );
+
+ }
+
+ //
+ // MapCURRENTToLocalAddressSpace();
+ //
+
+ BufferAddress = ((PUCHAR)(Adapt->ram_access)) +
+ Boundary * Adapt->buffer_page_size;
+
+ //
+ // GetPacketLength();
+ //
+
+ PacketSize = 0;
+
+ WD_MOVE_SHARED_RAM_TO_USHORT(&PacketSize, BufferAddress + 2);
+
+ //
+ // GetReceiveStatus();
+ //
+
+ WD_MOVE_SHARED_RAM_TO_UCHAR(&PacketStatus, BufferAddress);
+
+ //
+ // GetNextPacketBufferNumber();
+ //
+
+ WD_MOVE_SHARED_RAM_TO_UCHAR(&NextPacket, BufferAddress + 1);
+
+ IF_LOG(LOG('V'));
+
+ IF_LOG(LmiDebugLog[LmiDebugLogPlace++] = (ULONG)BufferAddress);
+ IF_LOG(LmiDebugLog[LmiDebugLogPlace++] = (ULONG)NextPacket);
+
+ IF_LMI_LOUD(DbgPrint("This packet starts at 0x%x, size 0x%x, next 0x%x\n", BufferAddress, PacketSize, NextPacket));
+
+ if (!((NextPacket >= Adapt->StartBuffer) && (NextPacket <= Adapt->LastBuffer))) {
+
+ //
+ // Next pointer appears hosed. This has occured once on an MP
+ // machine such that it looked like we hit a moment in time
+ // where the card had updated CURRENT, but had not updated the
+ // shared ram yet. If we get in here we will just skip ahead
+ // to the end of the receive ring.
+ //
+
+#if DBG
+
+ //
+ // I want to see the system where this happens again.
+ //
+
+ NdisSynchronizeWithInterrupt(
+ &(Adapt->NdisInterrupt),
+ SyncGetCurrent,
+ Adapt
+ );
+
+ Current = Adapt->Current;
+
+ {
+
+ ULONG p0, p1, p2, p3;
+ ULONG p;
+
+ p = LmiDebugLog[(char)LmiDebugLogPlace - 4];
+
+ if ((p < (ULONG)(Adapt->ReceiveStart)) ||
+ (p > (ULONG)(Adapt->ReceiveStop))) {
+
+ p0 = p1 = p2 = p3 = 0;
+
+ } else {
+
+ p0 = *((PULONG)(p));
+ p1 = *((PULONG)(p+4));
+ p2 = *((PULONG)(p+8));
+ p3 = *((PULONG)(p+12));
+
+ }
+
+ DbgPrint("WDLAN : 0x%x, 0x%x, 0x%x, 0x%x: 0x%x 0x%x 0x%x 0x%x\n",
+ Boundary,
+ NextPacket,
+ Current,
+ BufferAddress,
+ *((PULONG)(BufferAddress)),
+ *((PULONG)(BufferAddress + 4)),
+ *((PULONG)(BufferAddress + 8)),
+ *((PULONG)(BufferAddress + 12))
+ );
+
+ DbgPrint("WDLAN : 0x%x: 0x%x 0x%x 0x%x 0x%x\n",
+ p, p0, p1, p2, p3
+ );
+
+ }
+#endif
+
+ Boundary = NextPacket = Current;
+
+ if (Boundary > Adapt->LastBuffer) {
+
+ Boundary = ((Boundary - Adapt->LastBuffer) + Adapt->StartBuffer);
+
+ }
+
+ IF_LMI_LOUD(DbgPrint("Boundary updated to 0x%x because of bad NextPointer\n",
+ (Boundary == Adapt->StartBuffer) ? Adapt->LastBuffer - 1 : Boundary-1));
+
+ NdisWritePortUchar(Adapt->NdisAdapterHandle,
+ Adapt->io_base + BOUNDARY_REG,
+ (UCHAR)((Boundary == Adapt->StartBuffer) ?
+ Adapt->LastBuffer - 1 :
+ Boundary - 1)
+ );
+
+
+ break;
+
+ }
+
+ //
+ // if (Slot16Bit) then
+ //
+ // TurnOff16BitLAAR();
+ //
+
+ if (Adapt->board_id & SLOT_16BIT) {
+
+ IF_LMI_LOUD(DbgPrint("Writing 0x%x to LAAR\n",Adapt->LaarHold));
+
+ NdisWritePortUchar(Adapt->NdisAdapterHandle,
+ Adapt->io_base + LA_ADDRESS_REG,
+ Adapt->LaarHold
+ );
+
+ }
+
+ }
+
+ //
+ // Skip over NIC header
+ //
+
+ Adapt->IndicatingPacket = BufferAddress + 4;
+
+ Adapt->PacketLen = PacketSize - 4;
+
+
+ //
+ // UM_Receive_Packet();
+ //
+
+ Status = UM_Receive_Packet(PacketSize - 4, Adapt);
+
+ //
+ // UpdateBOUNDARY();
+ //
+
+ Boundary = NextPacket;
+
+ if (Boundary > Adapt->LastBuffer) {
+
+ Boundary = ((Boundary - Adapt->LastBuffer) + Adapt->StartBuffer);
+
+ }
+
+ IF_LMI_LOUD(DbgPrint("Boundary updated to 0x%x\n",
+ (Boundary == Adapt->StartBuffer) ? Adapt->LastBuffer - 1 : Boundary-1));
+
+ NdisWritePortUchar(Adapt->NdisAdapterHandle,
+ Adapt->io_base + BOUNDARY_REG,
+ (UCHAR)((Boundary == Adapt->StartBuffer) ?
+ Adapt->LastBuffer - 1 :
+ Boundary - 1)
+ );
+
+
+
+ //
+ // if (UMReturnStatus == EVENTS_DISABLED) then
+ //
+ // return;
+ //
+ //
+
+ if (Status == EVENTS_DISABLED) {
+
+ return;
+
+ }
+
+ }
+
+
+ //
+ // ClearReceiveInterrupt();
+ //
+
+ NdisWritePortUchar(Adapt->NdisAdapterHandle,
+ Adapt->io_base + INTERRUPT_STATUS_REG,
+ PACKET_RECEIVED_NO_ERROR
+ );
+
+
+
+ NdisSynchronizeWithInterrupt(
+ &(Adapt->NdisInterrupt),
+ SyncGetCurrent,
+ Adapt
+ );
+
+ Current = Adapt->Current;
+
+ //
+ // Get BOUNDARY + 1 buffer pointer
+ //
+
+ NdisReadPortUchar(Adapt->NdisAdapterHandle,
+ Adapt->io_base + BOUNDARY_REG,
+ &Boundary
+ );
+
+ IF_LMI_LOUD(DbgPrint("Current restarts at 0x%x, Boundary at 0x%x\n",Current,Boundary));
+
+ Boundary++;
+
+ if (Boundary >= Adapt->LastBuffer) {
+
+ Boundary = Adapt->StartBuffer;
+
+ }
+
+ //
+ // MapCURRENTToLocalAddressSpace();
+ //
+
+ BufferAddress = ((PUCHAR)(Adapt->ram_access)) + Boundary * Adapt->buffer_page_size;
+
+
+
+ //
+ // if (BOUNDARY + 1 != CURRENT) then
+ //
+ // goto DoReceive;
+ //
+
+ if (Boundary != Current) {
+
+ goto DoReceives;
+ }
+
+
+
+
+ //
+ // Ring is empty!
+ //
+
+
+
+
+ //
+ // if (DoingOverWriteHandling) then
+ //
+
+ if (Adapt->OverWriteHandling) {
+
+
+ IF_LOG(LOG('%'));
+
+ //
+ // ClearOverWriteBit();
+ //
+
+ NdisWritePortUchar(Adapt->NdisAdapterHandle,
+ Adapt->io_base + INTERRUPT_STATUS_REG,
+ OVERWRITE_WARNING
+ );
+
+ //
+ // ClearOverWriteFlag();
+ //
+
+ Adapt->OverWriteHandling = FALSE;
+
+
+ //
+ // if (NIC_690) then
+ //
+
+ if (Adapt->board_id & NIC_690_BIT) {
+
+ //
+ // ReadBOUNDARY();
+ //
+
+ NdisReadPortUchar(Adapt->NdisAdapterHandle,
+ Adapt->io_base + BOUNDARY_REG,
+ &Boundary
+ );
+
+ //
+ // WriteBOUNDARY();
+ //
+
+ NdisWritePortUchar(Adapt->NdisAdapterHandle,
+ Adapt->io_base + BOUNDARY_REG,
+ Boundary
+ );
+
+ } else {
+
+ //
+ // Acknowledge All interrupts so far.
+ //
+
+ NdisWritePortUchar(Adapt->NdisAdapterHandle,
+ Adapt->io_base + INTERRUPT_STATUS_REG,
+ 0xFF
+ );
+
+
+ //
+ // TakeNICOutOfLoopbackMode();
+ //
+
+ NdisWritePortUchar(Adapt->NdisAdapterHandle,
+ Adapt->io_base + TRANSMIT_CONFIG_REG,
+ 0
+ );
+
+ //
+ // WriteNewInterruptBits();
+ //
+
+ Current = START | REMOTE_ABORT_COMPLETE;
+
+ if (Adapt->OverWriteStartTransmit) {
+
+ Adapt->OverWriteStartTransmit = FALSE;
+
+ Current |= TRANSMIT_PACKET;
+
+ }
+
+ NdisWritePortUchar(Adapt->NdisAdapterHandle,
+ Adapt->io_base + COMMAND_REG,
+ Current
+ );
+
+ }
+
+ }
+
+ return;
+
+}
+
+
+
+#pragma NDIS_INIT_FUNCTION(LM_Get_Mca_Io_Base_Address)
+
+LM_STATUS
+LM_Get_Mca_Io_Base_Address(
+ IN Ptr_Adapter_Struc Adapt,
+ IN NDIS_HANDLE ConfigurationHandle,
+ OUT USHORT *IoBaseAddress
+ )
+/*++
+
+Routine Description:
+
+ This routine will get the configuration information about the card.
+
+
+Arguments:
+
+ Adapt - A pointer to an LMI adapter structure.
+
+Return:
+
+ 0 for success, else -1.
+
+--*/
+{
+ NDIS_STATUS Status;
+ UCHAR RegValue1, RegValue2;
+ USHORT RegValue;
+ ULONG SlotNumber;
+
+ //
+ // Get slot info
+ //
+
+ NdisReadMcaPosInformation(
+ &Status,
+ ConfigurationHandle,
+ &SlotNumber,
+ &Adapt->PosData
+ );
+
+ if (Status != NDIS_STATUS_SUCCESS) {
+
+ *IoBaseAddress = 0;
+ return((LM_STATUS)-1);
+
+ }
+
+ Adapt->mc_slot_num = (UCHAR)SlotNumber;
+
+ //
+ // GetPosId();
+ //
+
+ RegValue1 = Adapt->PosData.PosData2;
+
+ RegValue2 = Adapt->PosData.PosData1;
+
+ //
+ // if (594Group()) then
+ //
+ // ReturnValue = Get594ConfigInfo();
+ //
+ // else if (593Group()) then
+ //
+ // ReturnValue = Get593ConfigInfo();
+ //
+ // else
+ //
+ // return(-1);
+ //
+
+ RegValue = Adapt->PosData.AdapterId;
+
+ switch (RegValue) {
+
+ case CNFG_ID_8003E:
+ case CNFG_ID_8003S:
+ case CNFG_ID_8003W:
+ case CNFG_ID_BISTRO03E:
+
+ //
+ // Get593Io();
+ //
+
+ RegValue1 = Adapt->PosData.PosData1;
+
+ RegValue1 &= 0xFE;
+
+ *IoBaseAddress = ((USHORT)RegValue1) << 4;
+
+ break;
+
+ case CNFG_ID_8013E:
+ case CNFG_ID_8013W:
+ case CNFG_ID_8115TRA:
+ case CNFG_ID_BISTRO13E:
+ case CNFG_ID_BISTRO13W:
+
+
+ //
+ // Get594Io();
+ //
+
+ RegValue1 = Adapt->PosData.PosData1;
+
+ RegValue1 &= 0xF0;
+
+ *IoBaseAddress = ((USHORT)RegValue1 << 8) | (USHORT)0x800;
+
+ break;
+
+ default:
+
+ //
+ // Not a recognized card
+ //
+
+ *IoBaseAddress = 0;
+
+ return((LM_STATUS)-1);
+
+ }
+
+ return(0);
+
+}
+
+#pragma NDIS_INIT_FUNCTION(LM_Get_Config)
+
+LM_STATUS
+LM_Get_Config(
+ Ptr_Adapter_Struc Adapt
+ )
+/*++
+
+Routine Description:
+
+ This routine will get the configuration information about the card.
+
+
+Arguments:
+
+ Adapt - A pointer to an LMI adapter structure.
+
+Return:
+
+ ADAPTER_AND_CONFIG,
+ ADAPTER_NO_CONFIG,
+ ADAPTER_NOT_FOUND
+
+--*/
+{
+
+ CNFG_Adapter Config;
+ UINT ReturnValue;
+
+ //
+ // Set Defaults
+ //
+
+ Config.cnfg_mode_bits1 = 0;
+ Config.cnfg_bic_type = 0;
+ Config.cnfg_nic_type = 0;
+ Config.cnfg_bus = Adapt->bus_type;
+ Config.cnfg_ram_base = 0xD0000;
+ Config.cnfg_irq_line = 3;
+ Config.cnfg_base_io = Adapt->io_base;
+ Config.cnfg_ram_size = CNFG_SIZE_8KB;
+ Config.cnfg_slot = Adapt->mc_slot_num;
+ Config.PosData = Adapt->PosData;
+
+ //
+ // Turn Off interrupts
+ //
+
+ LM_Disable_Adapter(Adapt);
+
+
+ ReturnValue = CardGetConfig(Adapt->NdisAdapterHandle,
+ (UINT)(Adapt->io_base),
+ (BOOLEAN)((Adapt->bus_type == (UCHAR)1)? TRUE : FALSE),
+ &Config
+ );
+
+ //
+ // Set defaults for LM
+ //
+
+ Adapt->num_of_tx_buffs = 1;
+
+ Adapt->xmit_buf_size = 0x600; // A multiple of 256 > 1514.
+
+
+ //
+ // Turn On interrupts
+ //
+
+ LM_Enable_Adapter(Adapt);
+
+ Adapt->board_id = Config.cnfg_bid;
+
+ Adapt->adapter_text_ptr = (ULONG)NULL;
+
+
+ Adapt->io_base = Config.cnfg_base_io;
+ Adapt->irq_value = Config.cnfg_irq_line;
+ Adapt->ram_base = Config.cnfg_ram_base;
+ Adapt->ram_size = Config.cnfg_ram_size;
+ Adapt->ram_usable = Config.cnfg_ram_usable;
+ Adapt->rom_base = Config.cnfg_rom_base;
+ Adapt->rom_size = Config.cnfg_rom_size;
+ Adapt->media_type = Config.cnfg_media_type;
+ Adapt->mc_slot_num = (UCHAR)Config.cnfg_slot;
+ Adapt->mode_bits = Config.cnfg_mode_bits1;
+ Adapt->bic_type = Config.cnfg_bic_type;
+ Adapt->nic_type = Config.cnfg_nic_type;
+ Adapt->pos_id = Config.cnfg_pos_id;
+
+ IF_LMI_LOUD(DbgPrint("Io 0x%x, Irq 0x%x, RamBase 0x%x, RamSize 0x%x\n",
+ Adapt->io_base,
+ Adapt->irq_value,
+ Adapt->ram_base,
+ Adapt->ram_size
+ ));
+
+
+ if (ReturnValue == 0) {
+
+ return(ADAPTER_AND_CONFIG);
+
+ } else if (ReturnValue == 1) {
+
+ return(ADAPTER_NO_CONFIG);
+
+ }
+
+ return(ADAPTER_NOT_FOUND);
+
+}
+
+
+
+LM_STATUS
+LM_Free_Resources(
+ Ptr_Adapter_Struc Adapt
+ )
+/*++
+
+Routine Description:
+
+ This routine will free up any resources for this adapter.
+
+Arguments:
+
+ Adapt - A pointer to an LMI adapter structure.
+
+
+Return:
+
+ SUCCESS
+ FAILURE
+
+--*/
+{
+ if (Adapt->State == REMOVED) {
+
+ return(SUCCESS);
+
+ }
+
+ Adapt->State == REMOVED;
+
+ return(SUCCESS);
+}
+
+LM_STATUS
+LM_Initialize_Adapter(
+ Ptr_Adapter_Struc Adapt
+ )
+/*++
+
+Routine Description:
+
+ This routine will do a hardware reset, self test, and initialization of
+ the adapter.
+
+ The node_address field (if non-zero) is copied to the card, and if
+ zero, is copied from the card. The following fields must be set by
+ the UM : base_io, ram_size, ram_access, node_address, max_packet_size,
+ buffer_page_size, num_of_tx_buffs, and receive_mask.
+
+
+Arguments:
+
+ Adapt - A pointer to an LMI adapter structure.
+
+
+Return:
+
+ SUCCESS
+ ADAPTER_HARDWARE_FAILED
+ INITIALIZE_FAILED
+
+--*/
+{
+
+ ULONG i;
+
+ //
+ // Disable interrupts.
+ //
+
+ LM_Disable_Adapter(Adapt);
+
+
+ //
+ // Initialize the transmit buffer control.
+ //
+
+ Adapt->CurBufXmitting = (XMIT_BUF)-1;
+ Adapt->NextBufToFill = (XMIT_BUF)0;
+ Adapt->NextBufToXmit = (XMIT_BUF)-1;
+ Adapt->TransmitInterruptPending = FALSE;
+ Adapt->OverWriteStartTransmit = FALSE;
+ IF_LOG(LOG('?'));
+
+ for (i=0; i<Adapt->num_of_tx_buffs; i++) {
+
+ Adapt->BufferStatus[i] = EMPTY;
+ Adapt->PacketLens[i] = 0;
+
+ }
+
+ //
+ // The start of the receive space.
+ //
+
+ Adapt->Current = 0;
+
+ Adapt->ReceiveStart = ((PUCHAR)(Adapt->ram_access)) +
+ (Adapt->num_of_tx_buffs * Adapt->xmit_buf_size);
+
+
+ //
+ // The end of the receive space.
+ //
+
+ Adapt->ReceiveStop = ((PUCHAR)(Adapt->ram_access)) + (Adapt->ram_size * 1024);
+
+
+
+ //
+ // Set receive info
+ //
+
+
+ Adapt->StartBuffer = (UCHAR)(((PUCHAR)(Adapt->ReceiveStart) -
+ (PUCHAR)(Adapt->ram_access)) / Adapt->buffer_page_size);
+
+
+ Adapt->LastBuffer = (UCHAR)(((Adapt->ram_size * 1024) == 0x10000) ? 0xFF :
+ ((Adapt->ram_size * 1024) / WD_BUFFER_PAGE_SIZE) & 0xFF);
+
+
+ IF_LMI_LOUD(DbgPrint("Ring info: Base Addr 0x%lx; ReceiveStart 0x%lx; ReceiveStop 0x%lx\n",
+ Adapt->ram_access, Adapt->ReceiveStart, Adapt->ReceiveStop));
+ IF_LMI_LOUD(DbgPrint(" Start Rcv Ring 0x%x; Last Rcv Ring 0x%x\n",
+ Adapt->StartBuffer, Adapt->LastBuffer));
+
+ //
+ // Set card up
+ //
+
+
+ if (!CardSetup(Adapt)) {
+
+ Adapt->State = REMOVED;
+
+ return(INITIALIZE_FAILED);
+
+ }
+
+ Adapt->State = INITIALIZED;
+
+ return(SUCCESS);
+}
+
+
+
+LM_STATUS
+LM_Enable_Adapter(
+ Ptr_Adapter_Struc Adapt
+ )
+/*++
+
+Routine Description:
+
+ This routine will enable interrupts on the card.
+
+Arguments:
+
+ Adapt - A pointer to an LMI adapter structure.
+
+
+Return:
+
+ SUCCESS
+
+--*/
+{
+ ULONG BoardInterface = (Adapt->board_id & INTERFACE_CHIP_MASK);
+
+ if (Adapt->State != OPEN) {
+
+ return(SUCCESS);
+
+ }
+
+ IF_LOG(LOG('Z'));
+
+ //
+ // Enable NIC; Select Page 0, write Mask
+ //
+
+ NdisWritePortUchar(Adapt->NdisAdapterHandle,
+ Adapt->io_base + COMMAND_REG,
+ REMOTE_ABORT_COMPLETE
+ );
+
+ NdisWritePortUchar(Adapt->NdisAdapterHandle,
+ Adapt->io_base + INTERRUPT_MASK_REG,
+ Adapt->InterruptMask
+ );
+
+ return(SUCCESS);
+}
+
+LM_STATUS
+LM_Disable_Adapter(
+ Ptr_Adapter_Struc Adapt
+ )
+/*++
+
+Routine Description:
+
+ This routine will disable interrupts on the card.
+
+Arguments:
+
+ Adapt - A pointer to an LMI adapter structure.
+
+
+Return:
+
+ SUCCESS
+
+--*/
+{
+
+ ULONG BoardInterface = (Adapt->board_id & INTERFACE_CHIP_MASK);
+
+ IF_LOG(LOG('z'));
+
+ //
+ // Disable board interrupts...
+ //
+
+ //
+ // disable NIC; Select Page 0, write Mask
+ //
+
+ NdisWritePortUchar(Adapt->NdisAdapterHandle,
+ Adapt->io_base + COMMAND_REG,
+ REMOTE_ABORT_COMPLETE
+ );
+
+ NdisWritePortUchar(Adapt->NdisAdapterHandle,
+ Adapt->io_base + INTERRUPT_MASK_REG,
+ 0
+ );
+
+ return(SUCCESS);
+
+}
+
+
+LM_STATUS
+LM_Open_Adapter(
+ Ptr_Adapter_Struc Adapt
+ )
+/*++
+
+Routine Description:
+
+ This routine will open the adapter, initializing it if necessary.
+
+Arguments:
+
+ Adapt - A pointer to an LMI adapter structure.
+
+
+Return:
+
+ SUCCESS
+ OPEN_FAILED
+ ADAPTER_HARDWARE_FAILED
+
+--*/
+{
+ LM_STATUS Status;
+
+ if (Adapt->State == OPEN) {
+
+ return(SUCCESS);
+
+ }
+
+ if (Adapt->State == CLOSED) {
+
+ Status = LM_Initialize_Adapter(Adapt);
+
+ if (Status != SUCCESS) {
+
+ return(Status);
+
+ }
+
+ }
+
+
+ if (Adapt->State != INITIALIZED) {
+
+ return(OPEN_FAILED);
+
+ }
+
+ NdisWritePortUchar(Adapt->NdisAdapterHandle,
+ Adapt->io_base + COMMAND_REG,
+ START | REMOTE_ABORT_COMPLETE
+ );
+
+ if (Adapt->mode_bits & MANUAL_CRC) {
+
+ NdisWritePortUchar(Adapt->NdisAdapterHandle,
+ Adapt->io_base + TRANSMIT_CONFIG_REG,
+ MANUAL_CRC_GENERATION
+ );
+
+ } else {
+
+ NdisWritePortUchar(Adapt->NdisAdapterHandle,
+ Adapt->io_base + TRANSMIT_CONFIG_REG,
+ 0
+ );
+
+ }
+
+ Adapt->State = OPEN;
+
+ LM_Enable_Adapter(Adapt);
+
+ return(SUCCESS);
+
+}
+
+LM_STATUS
+LM_Close_Adapter(
+ Ptr_Adapter_Struc Adapt
+ )
+/*++
+
+Routine Description:
+
+ This routine will close the adapter, stopping the card.
+
+Arguments:
+
+ Adapt - A pointer to an LMI adapter structure.
+
+
+Return:
+
+ SUCCESS
+ CLOSE_FAILED
+ ADAPTER_HARDWARE_FAILED
+
+--*/
+{
+
+ if (Adapt->State != OPEN) {
+
+ return(CLOSE_FAILED);
+
+ }
+
+ LM_Disable_Adapter(Adapt);
+
+ NdisWritePortUchar(Adapt->NdisAdapterHandle,
+ Adapt->io_base + COMMAND_REG,
+ STOP | REMOTE_ABORT_COMPLETE
+ );
+
+ UM_Delay(1600000);
+
+ Adapt->State = CLOSED;
+
+ return(SUCCESS);
+
+}
+
+LM_STATUS
+LM_Set_Receive_Mask(
+ Ptr_Adapter_Struc Adapt
+ )
+/*++
+
+Routine Description:
+
+ This routine will set the adapter to the receive mask in the filter
+ package.
+
+Arguments:
+
+ Adapt - A pointer to an LMI adapter structure.
+
+
+Return:
+
+ SUCCESS
+ INVALID_FUNCTION
+
+--*/
+{
+ UCHAR RegValue = 0;
+ UINT FilterClasses;
+
+ //
+ // Select Page 0
+ //
+
+ NdisWritePortUchar(Adapt->NdisAdapterHandle,
+ Adapt->io_base + COMMAND_REG,
+ REMOTE_ABORT_COMPLETE
+ );
+
+
+ //
+ // Set the card's mask
+ //
+
+ if (Adapt->FilterDB != NULL) {
+
+ FilterClasses = ETH_QUERY_FILTER_CLASSES(Adapt->FilterDB);
+
+ } else {
+
+ FilterClasses = 0;
+
+ }
+
+ if ((FilterClasses & NDIS_PACKET_TYPE_MULTICAST) ||
+ (FilterClasses & NDIS_PACKET_TYPE_ALL_MULTICAST)) {
+
+ if (!(Adapt->board_id & NIC_690_BIT)) {
+
+ NdisSynchronizeWithInterrupt(
+ &(Adapt->NdisInterrupt),
+ SyncSetAllMulticast,
+ Adapt
+ );
+
+ }
+
+ RegValue |= 0x8;
+
+ } else {
+
+ if (!(Adapt->board_id & NIC_690_BIT)) {
+
+ NdisSynchronizeWithInterrupt(
+ &(Adapt->NdisInterrupt),
+ SyncClearMulticast,
+ Adapt
+ );
+
+ }
+
+ }
+
+
+ if (FilterClasses & NDIS_PACKET_TYPE_BROADCAST) {
+
+ RegValue |= 0x4;
+
+ }
+
+
+ if (FilterClasses & NDIS_PACKET_TYPE_PROMISCUOUS) {
+
+ RegValue |= 0x1C;
+
+ }
+
+
+ //
+ // Write mask to card
+ //
+
+ NdisWritePortUchar(Adapt->NdisAdapterHandle,
+ Adapt->io_base + RECEIVE_STATUS_REG,
+ RegValue
+ );
+
+ return(SUCCESS);
+}
+
+LM_STATUS
+LM_Service_Receive_Events(
+ Ptr_Adapter_Struc Adapt
+ )
+/*++
+
+Routine Description:
+
+ This routine will handle all interrupts from the adapter.
+
+Arguments:
+
+ Adapt - A pointer to an LMI adapter structure.
+
+
+Return:
+
+ SUCCESS
+ REQUEUE_LATER
+ NOT_MY_INTERRUPT
+
+--*/
+{
+ UCHAR InterruptStatus;
+ BOOLEAN NoEventsServiced = TRUE;
+ ULONG ReceivePacketCount = 0;
+
+ //
+ // Get Interrupt Status
+ //
+
+ NdisReadPortUchar(Adapt->NdisAdapterHandle,
+ Adapt->io_base + INTERRUPT_STATUS_REG,
+ &InterruptStatus
+ );
+
+ //
+ // Consider only the relevant bits.
+ //
+
+ InterruptStatus &= (OVERWRITE_WARNING |
+ ISR_COUNTER_OVERFLOW |
+ PACKET_RECEIVED_NO_ERROR |
+ RECEIVE_ERROR
+ );
+
+
+ while (InterruptStatus != 0) {
+
+ NoEventsServiced = FALSE;
+
+ if (ReceivePacketCount > 10) {
+
+ return(REQUEUE_LATER);
+
+ }
+
+ ReceivePacketCount++;
+
+ //
+ // if (RingOverFlowed) then
+ //
+ // if (BoardNICIsNot690) then
+ //
+ // ResetNIC();
+ //
+ // HandleReceive();
+ //
+ // Continue;
+ //
+
+ if (InterruptStatus & OVERWRITE_WARNING) {
+
+ IF_LOG(LOG('o'));
+
+ Adapt->OverWriteHandling = TRUE;
+
+ //
+ // if (BoardNICIsNot690) then
+ //
+ // ResetNIC();
+ //
+ // HandleReceive();
+ //
+
+ if (!(Adapt->board_id & NIC_690_BIT)) {
+
+ //
+ // Stop the NIC
+ //
+
+ NdisWritePortUchar(Adapt->NdisAdapterHandle,
+ Adapt->io_base + COMMAND_REG,
+ STOP | REMOTE_ABORT_COMPLETE
+ );
+
+ //
+ // Reset Remote_byte_count registers
+ //
+
+ NdisWritePortUchar(Adapt->NdisAdapterHandle,
+ Adapt->io_base + REMOTE_BYTE_COUNT_REG0,
+ 0
+ );
+ NdisWritePortUchar(Adapt->NdisAdapterHandle,
+ Adapt->io_base + REMOTE_BYTE_COUNT_REG1,
+ 0
+ );
+
+ //
+ // Wait for reset to complete
+ //
+
+ NdisReadPortUchar(Adapt->NdisAdapterHandle,
+ Adapt->io_base + INTERRUPT_STATUS_REG,
+ &InterruptStatus
+ );
+
+ if (!(InterruptStatus & RESET)) {
+
+ UM_Delay(1600000);
+
+ }
+
+
+ //
+ // Put in loopback mode 1
+ //
+
+ NdisWritePortUchar(Adapt->NdisAdapterHandle,
+ Adapt->io_base + TRANSMIT_CONFIG_REG,
+ LOOPBACK_MODE1
+ );
+
+ //
+ // Restart NIC
+ //
+
+ NdisWritePortUchar(Adapt->NdisAdapterHandle,
+ Adapt->io_base + COMMAND_REG,
+ START | REMOTE_ABORT_COMPLETE
+ );
+
+
+ //
+ // If we started a packet transmitting and we reached here,
+ // we never got the interrupt for it. Assume it made it
+ // and complete the send.
+ //
+
+ if (Adapt->TransmitInterruptPending) {
+
+ ASSERT(Adapt->CurBufXmitting != (XMIT_BUF)-1);
+
+ Adapt->TransmitInterruptPending = FALSE;
+
+ Adapt->BufferStatus[Adapt->CurBufXmitting] = EMPTY;
+
+ IF_LOG(LOG('?'));
+
+ Adapt->CurBufXmitting = (XMIT_BUF)-1;
+
+ if (Adapt->NextBufToXmit != (XMIT_BUF)-1) {
+
+ //
+ // Start next xmit (this will really only set up
+ // for the xmit, and CardHandleReceive will issue
+ // the xmit command.)
+ //
+
+ CardSendPacket(Adapt);
+
+ }
+
+ UM_Send_Complete(SUCCESS, Adapt);
+
+ }
+
+ }
+
+ //
+ // Clear Receive Rings
+ //
+
+ CardHandleReceive(Adapt);
+
+ goto LoopBottom;
+
+ }
+
+
+
+
+
+
+
+
+
+ //
+ // if (CounterOverflow) then
+ //
+ // HandleOverflow();
+ //
+
+
+ if (InterruptStatus & ISR_COUNTER_OVERFLOW) {
+
+ UCHAR Count;
+
+ //
+ // Update Alignment count
+ //
+
+ NdisReadPortUchar(Adapt->NdisAdapterHandle,
+ Adapt->io_base + ALIGNMENT_ERROR_REG,
+ &Count
+ );
+
+ (*(Adapt->ptr_rx_align_errors)) += Count;
+
+ //
+ // Update CRC Count
+ //
+
+ NdisReadPortUchar(Adapt->NdisAdapterHandle,
+ Adapt->io_base + CRC_ERROR_REG,
+ &Count
+ );
+
+ (*(Adapt->ptr_rx_CRC_errors)) += Count;
+
+
+ //
+ // Update MissedPacket Count
+ //
+
+ NdisReadPortUchar(Adapt->NdisAdapterHandle,
+ Adapt->io_base + MISSED_PACKET_REG,
+ &Count
+ );
+
+ (*(Adapt->ptr_rx_lost_pkts)) += Count;
+
+ //
+ // Write ISR
+ //
+
+ NdisWritePortUchar(Adapt->NdisAdapterHandle,
+ Adapt->io_base + INTERRUPT_STATUS_REG,
+ ISR_COUNTER_OVERFLOW
+ );
+
+ goto LoopBottom;
+
+ }
+
+
+
+
+
+
+
+
+ //
+ // if (PacketWasReceived) then
+ //
+ // HandleReceive();
+ //
+
+ if (InterruptStatus & PACKET_RECEIVED_NO_ERROR) {
+
+ CardHandleReceive(Adapt);
+
+ goto LoopBottom;
+
+ }
+
+
+
+
+
+
+
+
+
+ //
+ // if (ReceiveError) then
+ //
+ // HandleReceiveError();
+ //
+
+ if (InterruptStatus & RECEIVE_ERROR) {
+
+ //
+ // Get receive status
+ //
+
+ NdisReadPortUchar(Adapt->NdisAdapterHandle,
+ Adapt->io_base + RECEIVE_STATUS_REG,
+ &InterruptStatus
+ );
+
+ //
+ // if (CRCError) then
+ //
+ // UpdateCRCCounter();
+ //
+
+ if (InterruptStatus & RECEIVE_CRC_ERROR) {
+
+ (*(Adapt->ptr_rx_CRC_errors))++;
+
+ }
+
+
+ //
+ // if (FrameAlignmentError) then
+ //
+ // UpdateFrameAlignmentCounter();
+ //
+
+ if (InterruptStatus & RECEIVE_ALIGNMENT_ERROR) {
+
+ UCHAR AlignmentCount;
+
+ NdisReadPortUchar(Adapt->NdisAdapterHandle,
+ Adapt->io_base + ALIGNMENT_ERROR_REG,
+ &AlignmentCount
+ );
+
+ (*(Adapt->ptr_rx_align_errors)) += AlignmentCount;
+
+ }
+
+
+
+
+ //
+ // if (FIFOUnderrunError) then
+ //
+ // UpdateFIFOCounter();
+ //
+
+ if (InterruptStatus & RECEIVE_FIFO_UNDERRUN) {
+
+ (*(Adapt->ptr_rx_overruns))++;
+
+ }
+
+
+
+
+ //
+ // if (LostPacketError) then
+ //
+ // UpdateLostPacketCounter();
+ //
+
+ if (InterruptStatus & RECEIVE_MISSED_PACKET) {
+
+ UCHAR MissedPacketCount;
+
+ NdisReadPortUchar(Adapt->NdisAdapterHandle,
+ Adapt->io_base + MISSED_PACKET_REG,
+ &MissedPacketCount
+ );
+
+ (*(Adapt->ptr_rx_lost_pkts)) += MissedPacketCount;
+
+ }
+
+
+ //
+ // Write ISR
+ //
+
+ NdisWritePortUchar(Adapt->NdisAdapterHandle,
+ Adapt->io_base + INTERRUPT_STATUS_REG,
+ RECEIVE_ERROR
+ );
+
+ goto LoopBottom;
+
+ }
+
+
+LoopBottom:
+
+
+
+
+ //
+ // Get Interrupt Status
+ //
+
+ NdisReadPortUchar(Adapt->NdisAdapterHandle,
+ Adapt->io_base + INTERRUPT_STATUS_REG,
+ &InterruptStatus
+ );
+
+ //
+ // Consider only the relevant bits.
+ //
+
+ InterruptStatus &= (OVERWRITE_WARNING |
+ ISR_COUNTER_OVERFLOW |
+ PACKET_RECEIVED_NO_ERROR |
+ RECEIVE_ERROR
+ );
+
+ }
+
+
+ //
+ //
+ // if (UMRequestedInterrupt) then
+ //
+ // UM_Interrupt();
+ //
+ // return (SUCCESS);
+
+ if (Adapt->UMRequestedInterrupt) {
+
+ Adapt->UMRequestedInterrupt = FALSE;
+
+ UM_Interrupt(Adapt);
+
+ return(SUCCESS);
+
+ }
+
+
+
+ //
+ // if (NoEventsServiced) then
+ //
+ // return (NOT_MY_INTERRUPT);
+ //
+
+
+ if (NoEventsServiced) {
+
+ return(NOT_MY_INTERRUPT);
+
+ }
+
+ //
+ // return(SUCCESS);
+ //
+
+ return(SUCCESS);
+}
+
+
+LM_STATUS
+LM_Service_Transmit_Events(
+ Ptr_Adapter_Struc Adapt
+ )
+/*++
+
+Routine Description:
+
+ This routine will handle all interrupts from the adapter.
+
+Arguments:
+
+ Adapt - A pointer to an LMI adapter structure.
+
+
+Return:
+
+ SUCCESS
+ NOT_MY_INTERRUPT
+
+--*/
+{
+ UCHAR InterruptStatus;
+
+ //
+ // Get Interrupt Status
+ //
+
+ NdisReadPortUchar(Adapt->NdisAdapterHandle,
+ Adapt->io_base + INTERRUPT_STATUS_REG,
+ &InterruptStatus
+ );
+
+ //
+ // Consider only the relevant bits.
+ //
+
+ InterruptStatus &= (OVERWRITE_WARNING |
+ PACKET_TRANSMITTED_NO_ERROR |
+ TRANSMIT_ERROR
+ );
+
+ while ((InterruptStatus & (PACKET_TRANSMITTED_NO_ERROR | TRANSMIT_ERROR))
+ != 0) {
+
+ if ((InterruptStatus & OVERWRITE_WARNING) && !(Adapt->board_id & NIC_690_BIT)) {
+
+ Adapt->TransmitInterruptPending = FALSE;
+
+ IF_LOG(LOG('?'));
+ IF_LOG(LOG('O'));
+
+ break;
+
+ }
+
+ //
+ // if (PacketWasTransmitted) then
+ //
+ // HandleTransmit();
+ //
+
+ if (InterruptStatus & PACKET_TRANSMITTED_NO_ERROR) {
+
+ if (Adapt->CurBufXmitting == (XMIT_BUF)-1) {
+
+ //
+ // We have seen a bad card where this occurred once. So, here is
+ // some code to recover from such a bad state.
+ //
+ // Reset the card and hope that solves the problem. NOTE: This
+ // code is cut and pasted from LM_Open_Adapter().
+ //
+
+ LM_Initialize_Adapter(Adapt);
+
+ if (Adapt->State != INITIALIZED) {
+
+ //
+ // Init failed, we are really hosed. Break and exit
+ //
+
+ break;
+
+ }
+
+ NdisWritePortUchar(Adapt->NdisAdapterHandle,
+ Adapt->io_base + COMMAND_REG,
+ START | REMOTE_ABORT_COMPLETE
+ );
+
+ if (Adapt->mode_bits & MANUAL_CRC) {
+
+ NdisWritePortUchar(Adapt->NdisAdapterHandle,
+ Adapt->io_base + TRANSMIT_CONFIG_REG,
+ MANUAL_CRC_GENERATION
+ );
+
+ } else {
+
+ NdisWritePortUchar(Adapt->NdisAdapterHandle,
+ Adapt->io_base + TRANSMIT_CONFIG_REG,
+ 0
+ );
+
+ }
+
+ Adapt->State = OPEN;
+
+ LM_Enable_Adapter(Adapt);
+
+ //
+ // On DBG builds I want to see if the recovery works, since we
+ // cannot reproduce this problem.
+ //
+
+ ASSERT(Adapt->CurBufXmitting != (XMIT_BUF)-1);
+
+ break;
+
+ }
+
+
+ //
+ // Write ISR
+ //
+
+ NdisWritePortUchar(Adapt->NdisAdapterHandle,
+ Adapt->io_base + INTERRUPT_STATUS_REG,
+ PACKET_TRANSMITTED_NO_ERROR
+ );
+
+ Adapt->TransmitInterruptPending = FALSE;
+
+ IF_LOG(LOG('?'));
+
+ Adapt->BufferStatus[Adapt->CurBufXmitting] = EMPTY;
+
+ Adapt->CurBufXmitting = (XMIT_BUF)-1;
+
+ if (Adapt->NextBufToXmit != (XMIT_BUF)-1) {
+
+ //
+ // Start next xmit
+ //
+
+ CardSendPacket(Adapt);
+
+ }
+
+ if (UM_Send_Complete(SUCCESS, Adapt) != EVENTS_DISABLED) {
+
+ goto LoopBottom;
+
+ } else {
+
+ break;
+
+ }
+
+ }
+
+
+
+
+
+
+ //
+ // if (TransmitError) then
+ //
+ // HandleTransmitError();
+ //
+
+ if (InterruptStatus & TRANSMIT_ERROR) {
+
+ //
+ // Write ISR
+ //
+
+ NdisWritePortUchar(Adapt->NdisAdapterHandle,
+ Adapt->io_base + INTERRUPT_STATUS_REG,
+ TRANSMIT_ERROR
+ );
+
+ //
+ // Get Transmit Status
+ //
+
+ NdisReadPortUchar(Adapt->NdisAdapterHandle,
+ Adapt->io_base + TRANSMIT_STATUS_REG,
+ &InterruptStatus
+ );
+
+ //
+ // Check error type and update counter
+ //
+
+ if (InterruptStatus & TRANSMIT_ABORT) {
+
+ (*(Adapt->ptr_tx_max_collisions))++;
+
+ } else if (InterruptStatus & TRANSMIT_FIFO_UNDERRUN) {
+
+ (*(Adapt->ptr_tx_underruns))++;
+
+ }
+
+ ASSERT(Adapt->CurBufXmitting != (XMIT_BUF)-1);
+
+ Adapt->TransmitInterruptPending = FALSE;
+
+ IF_LOG(LOG('?'));
+
+ Adapt->BufferStatus[Adapt->CurBufXmitting] = EMPTY;
+
+ Adapt->CurBufXmitting = (XMIT_BUF)-1;
+
+ if (Adapt->NextBufToXmit != (XMIT_BUF)-1) {
+
+ //
+ // Start next xmit
+ //
+
+ CardSendPacket(Adapt);
+
+ }
+
+ if (UM_Send_Complete((LM_STATUS)((InterruptStatus & TRANSMIT_ABORT) ?
+ MAX_COLLISIONS : FIFO_UNDERRUN),
+ Adapt
+ ) == EVENTS_DISABLED) {
+
+ break;
+
+ }
+
+ }
+
+
+
+
+
+LoopBottom:
+
+
+
+
+ //
+ // Get Interrupt Status
+ //
+
+ NdisReadPortUchar(Adapt->NdisAdapterHandle,
+ Adapt->io_base + INTERRUPT_STATUS_REG,
+ &InterruptStatus
+ );
+
+ //
+ // Consider only the relevant bits.
+ //
+
+ InterruptStatus &= (OVERWRITE_WARNING |
+ PACKET_TRANSMITTED_NO_ERROR |
+ TRANSMIT_ERROR
+ );
+
+
+ }
+
+
+ //
+ // return(SUCCESS);
+ //
+
+ return(SUCCESS);
+}
+
+LM_STATUS
+LM_Send(
+ PNDIS_PACKET Packet,
+ Ptr_Adapter_Struc Adapt
+ )
+/*++
+
+Routine Description:
+
+ This routine will copy a packet to the card and start a transmit if
+ possible
+
+Arguments:
+
+ Packet - The packet to put on the wire.
+
+ Adapt - A pointer to an LMI adapter structure.
+
+
+Return:
+
+ SUCCESS
+ OUT_OF_RESOURCES
+
+--*/
+{
+ XMIT_BUF Buffer = Adapt->NextBufToFill;
+
+ //
+ // if (NoBufferToFill) then
+ //
+ // return OUT_OF_RESOURCES;
+ //
+
+ if (Adapt->BufferStatus[Buffer] != EMPTY) {
+
+ return(OUT_OF_RESOURCES);
+
+ }
+
+ //
+ // Update current buffer status
+ //
+
+ Adapt->BufferStatus[Buffer] = FILLING;
+
+ //
+ // Copy down data
+ //
+
+ CardCopyDown(Adapt, Packet);
+
+ //
+ // Move NextBufToFill
+ //
+
+ Adapt->NextBufToFill++;
+
+ if (Adapt->NextBufToFill == MAX_XMIT_BUFS) {
+
+ Adapt->NextBufToFill = 0;
+
+ }
+
+
+ //
+ // Update current buffer status
+ //
+
+ Adapt->BufferStatus[Buffer] = FULL;
+
+
+ //
+ // Check if o.k. to send packet
+ //
+
+ if (Adapt->NextBufToXmit == (XMIT_BUF)-1) {
+
+ Adapt->NextBufToXmit = Buffer;
+
+ if (Adapt->CurBufXmitting == (XMIT_BUF)-1) {
+
+ IF_LOG(LOG('X'));
+
+ CardSendPacket(Adapt);
+
+ }
+
+ }
+
+ //
+ // return success
+ //
+
+ return(SUCCESS);
+
+}
+
+
+extern
+LM_STATUS
+LM_Receive_Copy(
+ PULONG Bytes_Transferred,
+ ULONG Byte_Count,
+ ULONG Offset,
+ PNDIS_PACKET Packet,
+ Ptr_Adapter_Struc Adapt
+ )
+/*++
+
+Routine Description:
+
+ This routine will copy from the card into the Packet.
+
+Arguments:
+
+ Bytes_Transferred - The number of bytes transferred.
+
+ Byte_Count - The number of bytes to transfer.
+
+ Offset - Offset into the receive buffer from which to receive
+
+ Packet - The packet to put on the wire.
+
+ Adapt - A pointer to an LMI adapter structure.
+
+
+Return:
+
+ SUCCESS
+ OUT_OF_RESOURCES
+
+--*/
+{
+ UINT BytesLeft, BytesWanted, BytesNow;
+ PUCHAR CurrentCardLoc;
+ UINT UNALIGNED *BufferVA;
+ UINT BufferLength, BufferOffset;
+ PNDIS_BUFFER CurrentBuffer;
+
+ *Bytes_Transferred = 0;
+
+ //
+ // See how much data there is to transfer.
+ //
+
+ if (Offset + Byte_Count > Adapt->PacketLen) {
+
+ BytesWanted = Adapt->PacketLen - Offset;
+
+ } else {
+
+ BytesWanted = Byte_Count;
+
+ }
+
+ BytesLeft = BytesWanted;
+
+
+ //
+ // Determine where the copying should start.
+ //
+
+ CurrentCardLoc = (PUCHAR)(Adapt->IndicatingPacket) + Offset;
+ if (CurrentCardLoc > Adapt->ReceiveStop) {
+ CurrentCardLoc = Adapt->ReceiveStart + (CurrentCardLoc - Adapt->ReceiveStop);
+ }
+
+ NdisQueryPacket(Packet, NULL, NULL, &CurrentBuffer, NULL);
+
+ NdisQueryBuffer(CurrentBuffer, (PVOID *)&BufferVA, &BufferLength);
+
+ BufferOffset = 0;
+
+
+ //
+ // Enable 16 bit memory access if possible
+ //
+
+ if (Adapt->board_id & SLOT_16BIT) {
+
+ IF_LMI_LOUD(DbgPrint("Writing 0x%x to LAAR\n",Adapt->LaarHold | MEMORY_16BIT_ENABLE));
+
+ NdisWritePortUchar(Adapt->NdisAdapterHandle,
+ Adapt->io_base + LA_ADDRESS_REG,
+ (UCHAR)(Adapt->LaarHold | MEMORY_16BIT_ENABLE)
+ );
+
+ }
+
+
+ //
+ // Loop, filling each buffer in the packet until there
+ // are no more buffers or the data has all been copied.
+ //
+
+ while (BytesLeft > 0) {
+
+ //
+ // See how much data to read into this buffer.
+ //
+
+ if ((BufferLength - BufferOffset) > BytesLeft) {
+
+ BytesNow = BytesLeft;
+
+ } else {
+
+ BytesNow = (BufferLength - BufferOffset);
+
+ }
+
+
+ //
+ // See if the data for this buffer wraps around the end
+ // of the receive buffers (if so filling this buffer
+ // will use two iterations of the loop).
+ //
+
+ if (CurrentCardLoc + BytesNow > Adapt->ReceiveStop) {
+
+ BytesNow = Adapt->ReceiveStop - CurrentCardLoc;
+
+ }
+
+
+ //
+ // Copy up the data.
+ //
+
+ if ((Adapt->board_id & MICROCHANNEL) &&
+ (!(Adapt->board_id & NIC_690_BIT))) {
+
+
+ //
+ // Then we have a bogon card which can only handle evenly
+ // aligned WORD transfers... do it by hand.
+ //
+
+ ULONG i, BytesToCopy, NumberToCopy;
+ UCHAR MissedBy;
+ PUINT AdapterAddress;
+ UINT DataToTransfer;
+ UCHAR UNALIGNED *NdisBufRest;
+ UINT UNALIGNED *NdisBufAddressSave = BufferVA;
+
+ //
+ // Do first part to get the source aligned.
+ //
+
+ MissedBy = (UCHAR)(((ULONG)CurrentCardLoc) % sizeof(UINT));
+
+ AdapterAddress = (PUINT)(CurrentCardLoc - MissedBy);
+
+ WD_MOVE_SHARED_RAM_TO_DWORD(&DataToTransfer, AdapterAddress);
+
+ //
+ // Get first few bytes.
+ //
+
+ NdisBufRest = (UCHAR UNALIGNED *)BufferVA;
+
+ BytesToCopy = sizeof(UINT) - MissedBy;
+
+ if (BytesNow < BytesToCopy) {
+
+ BytesToCopy = BytesNow;
+
+ }
+
+ for (i = 0; i < BytesToCopy; i++) {
+
+ //
+ // Store new value.
+ //
+
+ *NdisBufRest = (UCHAR)(DataToTransfer >> ((MissedBy + i) * 8));
+
+ NdisBufRest++;
+
+ }
+
+
+ AdapterAddress++;
+
+
+
+
+ //
+ // Update location and bytes left to copy
+ //
+
+ BufferVA = (UINT UNALIGNED *)NdisBufRest;
+
+ BytesToCopy = BytesNow - BytesToCopy;
+
+ ASSERT((((ULONG)AdapterAddress) % sizeof(UINT)) == 0);
+
+ //
+ // Now copy Dwords across.
+ //
+
+ NumberToCopy = BytesToCopy / sizeof(UINT);
+
+ for (i=0; i < NumberToCopy; i++) {
+
+ WD_MOVE_SHARED_RAM_TO_DWORD(BufferVA, AdapterAddress);
+
+ AdapterAddress++;
+
+ BufferVA++;
+
+ }
+
+ if ((BytesToCopy % sizeof(UINT)) != 0){
+
+ //
+ // We have some residual to copy.
+ //
+
+ MissedBy = (UCHAR)(BytesToCopy % sizeof(UINT));
+
+ NdisBufRest = (UCHAR UNALIGNED *)BufferVA;
+
+ WD_MOVE_SHARED_RAM_TO_DWORD(&DataToTransfer, AdapterAddress);
+
+ for (i = 0; i < MissedBy; i++) {
+
+ *NdisBufRest = ((UCHAR)(DataToTransfer >> (i * 8)));
+
+ NdisBufRest++;
+
+ }
+
+ }
+
+ BufferVA = NdisBufAddressSave;
+
+ } else {
+
+ WD_MOVE_SHARED_RAM_TO_MEM((PUCHAR)BufferVA, CurrentCardLoc, BytesNow);
+
+ }
+
+ CurrentCardLoc += BytesNow;
+
+ BytesLeft -= BytesNow;
+
+ *Bytes_Transferred += BytesNow;
+
+
+ //
+ // Is the transfer done now?
+ //
+
+ if (BytesLeft == 0) {
+
+ break;
+
+ }
+
+
+ //
+ // Wrap around the end of the receive buffers?
+ //
+
+ if (CurrentCardLoc == Adapt->ReceiveStop) {
+
+ CurrentCardLoc = Adapt->ReceiveStart;
+
+ }
+
+
+ //
+ // Was the end of this packet buffer reached?
+ //
+
+ BufferVA = (UINT UNALIGNED *)(((UCHAR UNALIGNED *)BufferVA) + BytesNow);
+
+ BufferOffset += BytesNow;
+
+ if (BufferOffset == BufferLength) {
+
+ NdisGetNextBuffer(CurrentBuffer, &CurrentBuffer);
+
+ if (CurrentBuffer == (PNDIS_BUFFER)NULL) {
+
+ break;
+
+ }
+
+ NdisQueryBuffer(CurrentBuffer, (PVOID *)&BufferVA, &BufferLength);
+
+ BufferOffset = 0;
+
+ }
+
+ }
+
+ //
+ // Turn off 16 bit memory access
+ //
+
+ if (Adapt->board_id & SLOT_16BIT) {
+
+ IF_LMI_LOUD(DbgPrint("Writing 0x%x to LAAR\n",Adapt->LaarHold));
+
+ NdisWritePortUchar(Adapt->NdisAdapterHandle,
+ Adapt->io_base + LA_ADDRESS_REG,
+ Adapt->LaarHold
+ );
+ }
+
+
+ return SUCCESS;
+
+}
+
+extern
+LM_STATUS
+LM_Receive_Lookahead(
+ ULONG Byte_Count,
+ ULONG Offset,
+ PUCHAR Buffer,
+ Ptr_Adapter_Struc Adapt
+ )
+/*++
+
+Routine Description:
+
+ This routine will copy from the card into a single contiguous buffer.
+
+Arguments:
+
+ Byte_Count - The number of bytes to transfer.
+
+ Offset - Offset into the receive buffer from which to receive
+
+ Packet - The packet to put on the wire.
+
+ Adapt - A pointer to an LMI adapter structure.
+
+
+Return:
+
+ SUCCESS
+ OUT_OF_RESOURCES
+
+--*/
+{
+ UINT BytesLeft, BytesWanted, BytesNow;
+ PUCHAR CurrentCardLoc;
+ UINT UNALIGNED *BufferVA = (UINT UNALIGNED *)Buffer;
+
+ //
+ // See how much data there is to transfer.
+ //
+
+ if (Offset + Byte_Count > Adapt->PacketLen) {
+
+ BytesWanted = Adapt->PacketLen - Offset;
+
+ } else {
+
+ BytesWanted = Byte_Count;
+
+ }
+
+ BytesLeft = BytesWanted;
+
+
+ //
+ // Determine where the copying should start.
+ //
+
+ CurrentCardLoc = Adapt->IndicatingPacket;
+
+
+ //
+ // Enable 16 bit memory access if possible
+ //
+
+ if (Adapt->board_id & SLOT_16BIT) {
+
+ IF_LMI_LOUD(DbgPrint("Writing 0x%x to LAAR\n",Adapt->LaarHold | MEMORY_16BIT_ENABLE));
+
+ NdisWritePortUchar(Adapt->NdisAdapterHandle,
+ Adapt->io_base + LA_ADDRESS_REG,
+ (UCHAR)(Adapt->LaarHold | MEMORY_16BIT_ENABLE)
+ );
+
+ }
+
+
+ //
+ // Loop, filling each buffer in the packet until there
+ // are no more buffers or the data has all been copied.
+ //
+
+ while (BytesLeft > 0) {
+
+ BytesNow = BytesLeft;
+
+ //
+ // See if the data for this buffer wraps around the end
+ // of the receive buffers (if so filling this buffer
+ // will use two iterations of the loop).
+ //
+
+ if (CurrentCardLoc + BytesNow > Adapt->ReceiveStop) {
+
+ BytesNow = Adapt->ReceiveStop - CurrentCardLoc;
+
+ }
+
+
+ //
+ // Copy up the data.
+ //
+
+ if ((Adapt->board_id & MICROCHANNEL) &&
+ (!(Adapt->board_id & NIC_690_BIT))) {
+
+
+ //
+ // Then we have a bogon card which can only handle evenly
+ // aligned WORD transfers... do it by hand.
+ //
+
+ ULONG i, BytesToCopy, NumberToCopy;
+ UCHAR MissedBy;
+ PUINT AdapterAddress;
+ UINT DataToTransfer;
+ UCHAR UNALIGNED *NdisBufRest;
+ UINT UNALIGNED *NdisBufAddressSave = BufferVA;
+
+ //
+ // Do first part to get the source aligned.
+ //
+
+ MissedBy = (UCHAR)(((ULONG)CurrentCardLoc) % sizeof(UINT));
+
+ AdapterAddress = (PUINT)(CurrentCardLoc - MissedBy);
+
+ WD_MOVE_SHARED_RAM_TO_DWORD(&DataToTransfer, AdapterAddress);
+
+ //
+ // Get first few bytes.
+ //
+
+ NdisBufRest = (UCHAR UNALIGNED *)BufferVA;
+
+ BytesToCopy = sizeof(UINT) - MissedBy;
+
+ if (BytesNow < BytesToCopy) {
+
+ BytesToCopy = BytesNow;
+
+ }
+
+ for (i = 0; i < BytesToCopy; i++) {
+
+ //
+ // Store new value.
+ //
+
+ *NdisBufRest = (UCHAR)(DataToTransfer >> ((MissedBy + i) * 8));
+
+ NdisBufRest++;
+
+ }
+
+
+ AdapterAddress++;
+
+
+
+
+ //
+ // Update location and bytes left to copy
+ //
+
+ BufferVA = (UINT UNALIGNED *)NdisBufRest;
+
+ BytesToCopy = BytesNow - BytesToCopy;
+
+ ASSERT((((ULONG)AdapterAddress) % sizeof(UINT)) == 0);
+
+ //
+ // Now copy Dwords across.
+ //
+
+ NumberToCopy = BytesToCopy / sizeof(UINT);
+
+ for (i=0; i < NumberToCopy; i++) {
+
+ WD_MOVE_SHARED_RAM_TO_DWORD(BufferVA, AdapterAddress);
+
+ AdapterAddress++;
+
+ BufferVA++;
+
+ }
+
+ if ((BytesToCopy % sizeof(UINT)) != 0){
+
+ //
+ // We have some residual to copy.
+ //
+
+ MissedBy = (UCHAR)(BytesToCopy % sizeof(UINT));
+
+ NdisBufRest = (UCHAR UNALIGNED *)BufferVA;
+
+ WD_MOVE_SHARED_RAM_TO_DWORD(&DataToTransfer, AdapterAddress);
+
+ for (i = 0; i < MissedBy; i++) {
+
+ *NdisBufRest = ((UCHAR)(DataToTransfer >> (i * 8)));
+
+ NdisBufRest++;
+
+ }
+
+ }
+
+ BufferVA = NdisBufAddressSave;
+
+ } else {
+
+ WD_MOVE_SHARED_RAM_TO_MEM((PUCHAR)BufferVA, CurrentCardLoc, BytesNow);
+
+ }
+
+ CurrentCardLoc += BytesNow;
+
+ Buffer += BytesNow;
+
+ BytesLeft -= BytesNow;
+
+
+ //
+ // Is the transfer done now?
+ //
+
+ if (BytesLeft == 0) {
+
+ break;
+
+ }
+
+
+ //
+ // Wrap around the end of the receive buffers?
+ //
+
+ if (CurrentCardLoc == Adapt->ReceiveStop) {
+
+ CurrentCardLoc = Adapt->ReceiveStart;
+
+ }
+
+
+ }
+
+ //
+ // Turn off 16 bit memory access
+ //
+
+ if (Adapt->board_id & SLOT_16BIT) {
+
+ IF_LMI_LOUD(DbgPrint("Writing 0x%x to LAAR\n",Adapt->LaarHold));
+
+ NdisWritePortUchar(Adapt->NdisAdapterHandle,
+ Adapt->io_base + LA_ADDRESS_REG,
+ Adapt->LaarHold
+ );
+
+ }
+
+
+ return SUCCESS;
+
+}
+
+BOOLEAN
+SyncGetCurrent(
+ IN PVOID Context
+ )
+/*++
+
+Routine Description:
+
+ This function is used to synchronize with the interrupt, switching
+ to page 1 to get the current pointer and then switching back to page 0.
+
+Arguments:
+
+ see NDIS 3.0 spec.
+
+Notes:
+
+ returns TRUE on success, else FALSE.
+
+--*/
+{
+ Ptr_Adapter_Struc Adapt = (Ptr_Adapter_Struc)Context;
+
+ //
+ // Select Page 1
+ //
+
+ NdisWritePortUchar(Adapt->NdisAdapterHandle,
+ Adapt->io_base + COMMAND_REG,
+ REMOTE_ABORT_COMPLETE | PAGE_SELECT_1
+ );
+
+ //
+ // Get CURRENT buffer pointer
+ //
+
+ NdisReadPortUchar(Adapt->NdisAdapterHandle,
+ Adapt->io_base + CURRENT_BUFFER_REG,
+ &(Adapt->Current)
+ );
+
+ //
+ // Select Page 0
+ //
+
+ NdisWritePortUchar(Adapt->NdisAdapterHandle,
+ Adapt->io_base + COMMAND_REG,
+ REMOTE_ABORT_COMPLETE
+ );
+
+ return(TRUE);
+}
+
+BOOLEAN
+SyncSetAllMulticast(
+ IN PVOID Context
+ )
+/*++
+
+Routine Description:
+
+ This function is used to synchronize with the interrupt, switching
+ to page 1 to set the mulitcast filter then switching back to page 0.
+
+Arguments:
+
+ see NDIS 3.0 spec.
+
+Notes:
+
+ returns TRUE on success, else FALSE.
+
+--*/
+{
+ Ptr_Adapter_Struc Adapt = (Ptr_Adapter_Struc)Context;
+ UCHAR i;
+
+
+ //
+ // Select Page 1
+ //
+
+ NdisWritePortUchar(Adapt->NdisAdapterHandle,
+ Adapt->io_base + COMMAND_REG,
+ REMOTE_ABORT_COMPLETE | PAGE_SELECT_1
+ );
+
+ //
+ // Set Filter to accept all multicast packets and we let
+ // the filter package figure it all out. (690 does not
+ // have these registers, 8390 does.)
+ //
+
+ for (i = MULTICAST_ADDRESS_REG0; i <= MULTICAST_ADDRESS_REG7; i++) {
+
+ NdisWritePortUchar(Adapt->NdisAdapterHandle,
+ Adapt->io_base + i,
+ 0xFF
+ );
+
+ }
+
+
+ //
+ // Select Page 0
+ //
+
+ NdisWritePortUchar(Adapt->NdisAdapterHandle,
+ Adapt->io_base + COMMAND_REG,
+ REMOTE_ABORT_COMPLETE
+ );
+
+ return(TRUE);
+}
+
+
+BOOLEAN
+SyncClearMulticast(
+ IN PVOID Context
+ )
+/*++
+
+Routine Description:
+
+ This function is used to synchronize with the interrupt, switching
+ to page 1 to set the mulitcast filter then switching back to page 0.
+
+Arguments:
+
+ see NDIS 3.0 spec.
+
+Notes:
+
+ returns TRUE on success, else FALSE.
+
+--*/
+{
+ Ptr_Adapter_Struc Adapt = (Ptr_Adapter_Struc)Context;
+ UCHAR i;
+
+
+ //
+ // Select Page 1
+ //
+
+ NdisWritePortUchar(Adapt->NdisAdapterHandle,
+ Adapt->io_base + COMMAND_REG,
+ REMOTE_ABORT_COMPLETE | PAGE_SELECT_1
+ );
+
+ //
+ // Accept no mulitcast addresses.
+ //
+
+ for (i = MULTICAST_ADDRESS_REG0; i <= MULTICAST_ADDRESS_REG7; i++) {
+
+ NdisWritePortUchar(Adapt->NdisAdapterHandle,
+ Adapt->io_base + i,
+ 0x00
+ );
+
+ }
+
+
+ //
+ // Select Page 0
+ //
+
+ NdisWritePortUchar(Adapt->NdisAdapterHandle,
+ Adapt->io_base + COMMAND_REG,
+ REMOTE_ABORT_COMPLETE
+ );
+
+ return(TRUE);
+}
+
diff --git a/private/ntos/ndis/wd/makefile b/private/ntos/ndis/wd/makefile
new file mode 100644
index 000000000..6ee4f43fa
--- /dev/null
+++ b/private/ntos/ndis/wd/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/wd/sources b/private/ntos/ndis/wd/sources
new file mode 100644
index 000000000..02968a4f2
--- /dev/null
+++ b/private/ntos/ndis/wd/sources
@@ -0,0 +1,44 @@
+!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=smcisa
+TARGETPATH=\nt\public\sdk\lib
+TARGETTYPE=DRIVER
+
+TARGETLIBS=$(BASEDIR)\public\sdk\lib\*\ndis.lib
+
+INCLUDES=..\..\inc
+
+SOURCES=wd.c \
+ umi.c \
+ lmi.c \
+ wdlan.rc
+
+RELATIVE_DEPTH=..\..
+
+MSC_WARNING_LEVEL=/W3 /WX
+
diff --git a/private/ntos/ndis/wd/umi.c b/private/ntos/ndis/wd/umi.c
new file mode 100644
index 000000000..2fcf9ed2c
--- /dev/null
+++ b/private/ntos/ndis/wd/umi.c
@@ -0,0 +1,347 @@
+/*++
+
+Copyright (c) 1990 Microsoft Corporation
+
+Module Name:
+
+ umi.c
+
+Abstract:
+
+ Upper MAC Interface functions for the NDIS 3.0 Western Digital driver.
+
+Author:
+
+ Sean Selitrennikoff (seanse) 15-Jan-92
+
+Environment:
+
+ Kernel mode, FSD
+
+Revision History:
+
+
+--*/
+
+#include <ndis.h>
+#include <efilter.h>
+#include "wdlmi.h"
+#include "wdhrd.h"
+#include "wdsft.h"
+#include "wdumi.h"
+
+
+
+#if DBG
+
+extern UCHAR WdDebugLog[];
+extern UCHAR WdDebugLogPlace;
+
+#define IF_LOG(A) A
+
+extern
+VOID
+LOG (UCHAR A);
+
+#else
+
+#define IF_LOG(A)
+
+#endif
+
+
+LM_STATUS
+UM_Send_Complete(
+ LM_STATUS Status,
+ Ptr_Adapter_Struc Adapt
+ )
+/*++
+
+Routine Description:
+
+ This routine is called back when the packet on the front of
+ PacketsOnCard has been fully transmitted by the Lower MAC.
+
+
+ NOTE: The lock is held before the LM_ routines are called and
+ therefore held at the beginning of this call.
+
+Arguments:
+
+ Status - Status of the send.
+
+ Adapt - A pointer to an LMI adapter structure.
+
+Return:
+
+ SUCCESS
+ EVENTS_DISABLED
+
+--*/
+{
+
+ PWD_ADAPTER Adapter = PWD_ADAPTER_FROM_Ptr_Adapter_Struc(Adapt);
+ PWD_OPEN Open;
+ PNDIS_PACKET Packet;
+
+ //
+ // Remove packet from front of queue. If the complete queue is empty
+ // then we have nothing to complete. This shouldn't really happen but
+ // there is a window where it could.
+ //
+
+ IF_LOG(LOG('c'));
+
+ if ( (Packet = Adapter->PacketsOnCard) != NULL ) {
+
+ Adapter->WakeUpTimeout = FALSE;
+
+ Adapter->PacketsOnCard = RESERVED(Packet)->NextPacket;
+
+ if ( Adapter->PacketsOnCard == NULL ) {
+
+ Adapter->PacketsOnCardTail = NULL;
+
+ }
+
+ Open = RESERVED(Packet)->Open;
+
+ IF_LOUD( DbgPrint("Completing send for open 0x%lx\n",Open);)
+
+ if ( RESERVED(Packet)->Loopback ) {
+
+ //
+ // Put packet on loopback
+ //
+
+ if ( Adapter->LoopbackQueue == NULL ) {
+
+ Adapter->LoopbackQueue = Adapter->LoopbackQTail = Packet;
+
+ } else {
+
+ RESERVED(Adapter->LoopbackQTail)->NextPacket = Packet;
+
+ Adapter->LoopbackQTail = Packet;
+
+ }
+
+ RESERVED(Packet)->NextPacket = NULL;
+
+ } else {
+
+ IF_LOUD( DbgPrint("Not a loopback packet\n");)
+
+ //
+ // Complete send
+ //
+
+ if ( Status == SUCCESS ) {
+
+ Adapter->FramesXmitGood++;
+
+ } else {
+
+ Adapter->FramesXmitBad++;
+ }
+
+ NdisReleaseSpinLock(&Adapter->Lock);
+
+ NdisCompleteSend(Open->NdisBindingContext,
+ Packet,
+ (Status == SUCCESS ? NDIS_STATUS_SUCCESS
+ : NDIS_STATUS_FAILURE)
+ );
+
+ NdisAcquireSpinLock(&Adapter->Lock);
+
+ WdRemoveReference(Open);
+
+ }
+ }
+
+ //
+ // If there are any sends waiting and there is not a reset to be
+ // done, queue them up
+ //
+
+ if ( (Adapter->XmitQueue != NULL) && !(Adapter->ResetRequested) ) {
+
+ //
+ // Remove packet from front.
+ //
+
+ Packet = Adapter->XmitQueue;
+
+ Adapter->XmitQueue = RESERVED(Packet)->NextPacket;
+
+ if (Adapter->XmitQueue == NULL) {
+
+ Adapter->XmitQTail = NULL;
+
+ }
+
+ //
+ // Start packet send.
+ //
+
+ IF_LOG(LOG('t'));
+
+ Status = LM_Send(Packet, Adapt);
+
+ if (Status == OUT_OF_RESOURCES) {
+
+ IF_LOG(LOG('2'));
+
+ //
+ // Put packet back on xmit queue.
+ //
+
+ if (Adapter->XmitQueue != NULL) {
+
+ RESERVED(Packet)->NextPacket = Adapter->XmitQueue;
+
+ Adapter->XmitQueue = Packet;
+
+ } else {
+
+ Adapter->XmitQueue = Packet;
+
+ Adapter->XmitQTail = Packet;
+
+ }
+
+ } else if (Status == SUCCESS) {
+
+ //
+ // Put packet at end of card list.
+ //
+
+ IF_LOG(LOG('3'));
+
+ if (Adapter->PacketsOnCard == NULL) {
+
+ Adapter->PacketsOnCard = Adapter->PacketsOnCardTail = Packet;
+
+ } else {
+
+ RESERVED(Adapter->PacketsOnCardTail)->NextPacket = Packet;
+
+ Adapter->PacketsOnCardTail = Packet;
+
+ }
+
+ ASSERT(Adapter->PacketsOnCard != NULL);
+
+ RESERVED(Packet)->NextPacket = NULL;
+
+ }
+
+ }
+
+ IF_LOG(LOG('C'));
+
+ return(SUCCESS);
+}
+
+
+LM_STATUS
+UM_Receive_Packet(
+ ULONG PacketSize,
+ Ptr_Adapter_Struc Adapt
+ )
+/*++
+
+Routine Description:
+
+ This routine is called whenever the lower MAC receives a packet.
+
+
+Arguments:
+
+ PacketSize - Total size of the packet
+
+ Adapt - A pointer to an LMI adapter structure.
+
+Return:
+
+ SUCCESS
+ EVENTS_DISABLED
+
+--*/
+{
+ PWD_ADAPTER Adapter = PWD_ADAPTER_FROM_Ptr_Adapter_Struc(Adapt);
+ ULONG IndicateLen;
+
+ Adapter->WakeUpTimeout = FALSE;
+
+ //
+ // Setup for indication
+ //
+
+ Adapter->IndicatedAPacket = TRUE;
+
+ Adapter->IndicatingPacket = (PNDIS_PACKET)NULL;
+
+ IndicateLen = ((Adapter->MaxLookAhead + WD_HEADER_SIZE) > PacketSize ?
+ PacketSize :
+ Adapter->MaxLookAhead + WD_HEADER_SIZE
+ );
+
+ if (LM_Receive_Lookahead(
+ IndicateLen,
+ 0,
+ Adapter->LookAhead,
+ &(Adapter->LMAdapter)) != SUCCESS) {
+
+ return(SUCCESS);
+
+ }
+
+ //
+ // Indicate packet
+ //
+
+ Adapter->FramesRcvGood++;
+
+ NdisReleaseSpinLock(&Adapter->Lock);
+
+ if (PacketSize < WD_HEADER_SIZE) {
+
+ if (PacketSize >= ETH_LENGTH_OF_ADDRESS) {
+
+ //
+ // Runt packet
+ //
+
+ EthFilterIndicateReceive(
+ Adapt->FilterDB,
+ (NDIS_HANDLE)Adapter,
+ (PCHAR)Adapter->LookAhead,
+ Adapter->LookAhead,
+ PacketSize,
+ NULL,
+ 0,
+ 0
+ );
+
+ }
+
+ } else {
+
+ EthFilterIndicateReceive(
+ Adapt->FilterDB,
+ (NDIS_HANDLE)Adapter,
+ (PCHAR)Adapter->LookAhead,
+ Adapter->LookAhead,
+ WD_HEADER_SIZE,
+ Adapter->LookAhead + WD_HEADER_SIZE,
+ IndicateLen - WD_HEADER_SIZE,
+ PacketSize - WD_HEADER_SIZE
+ );
+ }
+
+ NdisAcquireSpinLock(&Adapter->Lock);
+
+ return(SUCCESS);
+}
diff --git a/private/ntos/ndis/wd/wd.c b/private/ntos/ndis/wd/wd.c
new file mode 100644
index 000000000..289770e76
--- /dev/null
+++ b/private/ntos/ndis/wd/wd.c
@@ -0,0 +1,4599 @@
+/*++
+
+Copyright (c) 1990 Microsoft Corporation
+
+Module Name:
+
+ wd.c
+
+Abstract:
+
+ This is the main file for the Western Digital
+ Ethernet controller. This driver conforms to the NDIS 3.1 interface.
+
+Author:
+
+ Sean Selitrennikoff (SeanSe) 15-Jan-1992
+
+Environment:
+
+ Kernel Mode - Or whatever is the equivalent on OS/2 and DOS.
+
+Revision History:
+
+
+--*/
+
+#include <ndis.h>
+#include <efilter.h>
+#include <wdhrd.h>
+#include <wdlmireg.h>
+#include <wdlmi.h>
+#include <wdsft.h>
+#include "keywords.h"
+
+#if DBG
+#define STATIC
+#else
+#define STATIC static
+#endif
+
+static UCHAR WdBroadcastAddress[] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
+
+#if DBG
+
+
+#define LOGSIZE 512
+
+extern UCHAR WdDebugLog[LOGSIZE] = {0};
+extern UINT WdDebugLogPlace = 0;
+
+
+extern
+VOID
+LOG (UCHAR A) {
+ WdDebugLog[WdDebugLogPlace++] = A;
+ WdDebugLog[(WdDebugLogPlace + 4) % LOGSIZE] = '\0';
+ if (WdDebugLogPlace >= LOGSIZE) WdDebugLogPlace = 0;
+}
+
+
+ULONG WdDebugFlag= WD_DEBUG_LOG; // WD_DEBUG_LOG | WD_DEBUG_LOUD | WD_DEBUG_VERY_LOUD;
+
+#define IF_LOG(A) A
+
+#else
+
+#define IF_LOG(A)
+
+#endif
+
+
+//
+// This constant is used for places where NdisAllocateMemory
+// needs to be called and the HighestAcceptableAddress does
+// not matter.
+//
+
+NDIS_PHYSICAL_ADDRESS HighestAcceptableMax =
+ NDIS_PHYSICAL_ADDRESS_CONST(-1,-1);
+
+
+
+//
+// The global MAC block.
+//
+
+extern MAC_BLOCK WdMacBlock={0};
+
+
+
+//
+// If you add to this, make sure to add the
+// a case in WdFillInGlobalData() and in
+// WdQueryGlobalStatistics() if global
+// information only or
+// WdQueryProtocolStatistics() if it is
+// protocol queriable information.
+//
+UINT WdGlobalSupportedOids[] = {
+ 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
+ };
+
+//
+// If you add to this, make sure to add the
+// a case in WdQueryGlobalStatistics() and in
+// WdQueryProtocolInformation()
+//
+UINT WdProtocolSupportedOids[] = {
+ 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_802_3_PERMANENT_ADDRESS,
+ OID_802_3_CURRENT_ADDRESS,
+ OID_802_3_MULTICAST_LIST,
+ OID_802_3_MAXIMUM_LIST_SIZE
+ };
+
+
+
+
+
+
+
+UINT
+WdCopyOver(
+ OUT PUCHAR Buf, // destination
+ IN PNDIS_PACKET Packet, // source packet
+ IN UINT Offset, // offset in packet
+ IN UINT Length // number of bytes to copy
+ );
+
+
+NTSTATUS
+DriverEntry(
+ IN PDRIVER_OBJECT DriverObject,
+ IN PUNICODE_STRING RegistryPath
+ );
+
+
+
+#pragma NDIS_INIT_FUNCTION(DriverEntry)
+
+NTSTATUS
+DriverEntry(
+ IN PDRIVER_OBJECT DriverObject,
+ IN PUNICODE_STRING RegistryPath
+ )
+/*++
+
+Routine Description:
+
+ This is the transfer address of the driver. It initializes
+ WdMacBlock and calls NdisInitializeWrapper() and
+ NdisRegisterMac().
+
+Arguments:
+
+Return Value:
+
+ Indicates the success or failure of the initialization.
+
+--*/
+
+{
+ PMAC_BLOCK NewMacP = &WdMacBlock;
+ NDIS_STATUS Status;
+ NDIS_HANDLE NdisWrapperHandle;
+
+#ifdef NDIS_NT
+ NDIS_STRING MacName = NDIS_STRING_CONST("Smc8000n");
+#endif
+
+#ifdef NDIS_WIN
+ NDIS_STRING MacName = NDIS_STRING_CONST("SMC8000W");
+#endif
+
+#if NDIS_WIN
+ UCHAR pIds[sizeof (EISA_MCA_ADAPTER_IDS) + 8 * sizeof (USHORT)];
+#endif
+
+#if NDIS_WIN
+ ((PEISA_MCA_ADAPTER_IDS)pIds)->nEisaAdapters=0;
+ ((PEISA_MCA_ADAPTER_IDS)pIds)->nMcaAdapters=9;
+
+ *((PUSHORT)(((PEISA_MCA_ADAPTER_IDS)pIds)->IdArray) + 0)=CNFG_ID_8003E;
+ *((PUSHORT)(((PEISA_MCA_ADAPTER_IDS)pIds)->IdArray) + 1)=CNFG_ID_8003S;
+ *((PUSHORT)(((PEISA_MCA_ADAPTER_IDS)pIds)->IdArray) + 2)=CNFG_ID_8003W;
+ *((PUSHORT)(((PEISA_MCA_ADAPTER_IDS)pIds)->IdArray) + 3)=CNFG_ID_BISTRO03E;
+ *((PUSHORT)(((PEISA_MCA_ADAPTER_IDS)pIds)->IdArray) + 4)=CNFG_ID_8013E;
+ *((PUSHORT)(((PEISA_MCA_ADAPTER_IDS)pIds)->IdArray) + 5)=CNFG_ID_8013W;
+ *((PUSHORT)(((PEISA_MCA_ADAPTER_IDS)pIds)->IdArray) + 6)=CNFG_ID_BISTRO13E;
+ *((PUSHORT)(((PEISA_MCA_ADAPTER_IDS)pIds)->IdArray) + 7)=CNFG_ID_BISTRO13W;
+
+
+ (PVOID) DriverObject = (PVOID) pIds;
+#endif
+
+ //
+ // Ensure that the MAC_RESERVED structure will fit in the
+ // MacReserved section of a packet.
+ //
+
+ ASSERT(sizeof(MAC_RESERVED) <= sizeof(((PNDIS_PACKET)NULL)->MacReserved));
+
+
+ //
+ // Pass the wrapper a pointer to the device object.
+ //
+
+ NdisInitializeWrapper(&NdisWrapperHandle,
+ DriverObject,
+ RegistryPath,
+ NULL
+ );
+
+ //
+ // Set up the driver object.
+ //
+
+ NewMacP->DriverObject = DriverObject;
+
+ NdisAllocateSpinLock(&NewMacP->SpinLock);
+
+ NewMacP->NdisWrapperHandle = NdisWrapperHandle;
+ NewMacP->Unloading = FALSE;
+ NewMacP->NumAdapters = 0;
+ NewMacP->AdapterQueue = (PWD_ADAPTER)NULL;
+
+
+ //
+ // Prepare to call NdisRegisterMac.
+ //
+
+ NewMacP->MacCharacteristics.MajorNdisVersion = WD_NDIS_MAJOR_VERSION;
+ NewMacP->MacCharacteristics.MinorNdisVersion = WD_NDIS_MINOR_VERSION;
+ NewMacP->MacCharacteristics.Reserved = 0;
+ NewMacP->MacCharacteristics.OpenAdapterHandler = WdOpenAdapter;
+ NewMacP->MacCharacteristics.CloseAdapterHandler = WdCloseAdapter;
+ NewMacP->MacCharacteristics.SendHandler = WdSend;
+ NewMacP->MacCharacteristics.TransferDataHandler = WdTransferData;
+ NewMacP->MacCharacteristics.ResetHandler = WdReset;
+ NewMacP->MacCharacteristics.RequestHandler = WdRequest;
+ NewMacP->MacCharacteristics.QueryGlobalStatisticsHandler =
+ WdQueryGlobalStatistics;
+ NewMacP->MacCharacteristics.UnloadMacHandler = WdUnload;
+ NewMacP->MacCharacteristics.AddAdapterHandler = WdAddAdapter;
+ NewMacP->MacCharacteristics.RemoveAdapterHandler = WdRemoveAdapter;
+
+ NewMacP->MacCharacteristics.Name = MacName;
+
+ NdisRegisterMac(&Status,
+ &NewMacP->NdisMacHandle,
+ NdisWrapperHandle,
+ (NDIS_HANDLE)&WdMacBlock,
+ &NewMacP->MacCharacteristics,
+ sizeof(NewMacP->MacCharacteristics));
+
+
+ if (Status != NDIS_STATUS_SUCCESS) {
+
+ //
+ // NdisRegisterMac failed.
+ //
+
+ NdisFreeSpinLock(&NewMacP->SpinLock);
+ NdisTerminateWrapper(NdisWrapperHandle, NULL);
+ IF_LOUD( DbgPrint( "NdisRegisterMac failed with code 0x%x\n", Status );)
+ return Status;
+ }
+
+
+ IF_LOUD( DbgPrint( "NdisRegisterMac succeeded\n" );)
+
+ IF_LOUD( DbgPrint("Adapter Initialization Complete\n");)
+
+ return Status;
+
+}
+
+
+
+#pragma NDIS_INIT_FUNCTION(WdAddAdapter)
+
+NDIS_STATUS
+WdAddAdapter(
+ IN NDIS_HANDLE MacMacContext,
+ IN NDIS_HANDLE ConfigurationHandle,
+ IN PNDIS_STRING AdapterName
+ )
+/*++
+Routine Description:
+
+ This is the Wd MacAddAdapter routine. The system calls this routine
+ to add support for a particular WD adapter. This routine extracts
+ configuration information from the configuration data base and registers
+ the adapter with NDIS.
+
+Arguments:
+
+ see NDIS 3.0 spec...
+
+Return Value:
+
+ NDIS_STATUS_SUCCESS - Adapter was successfully added.
+ NDIS_STATUS_FAILURE - Adapter was not added, also MAC deregistered.
+
+--*/
+{
+
+ LM_STATUS LmStatus;
+ NDIS_HANDLE ConfigHandle;
+ PNDIS_CONFIGURATION_PARAMETER ReturnedValue;
+ NDIS_STRING IOAddressStr = IOBASE;
+ NDIS_STRING MaxMulticastListStr = MAXMULTICASTLIST;
+ NDIS_STRING NetworkAddressStr = NETADDRESS;
+ NDIS_STRING BusTypeStr = NDIS_STRING_CONST("BusType");
+ NDIS_STRING MediaTypeStr = NDIS_STRING_CONST("MediaType");
+ NDIS_STRING MaxPacketSizeStr = NDIS_STRING_CONST("MaximumPacketSize");
+ NDIS_STRING InterruptStr = INTERRUPT;
+ NDIS_STRING MemoryBaseAddrStr = MEMMAPPEDBASEADDRESS;
+
+ ULONG ConfigErrorValue = 0;
+ BOOLEAN ConfigError = FALSE;
+
+ USHORT WdIoBaseAddr = DEFAULT_IOBASEADDR;
+ UCHAR WdBusType = 0; // AT bus, 1 == MCA;
+ UCHAR CurrentAddress[ETH_LENGTH_OF_ADDRESS] = {0x00};
+ PVOID NetAddress;
+ ULONG Length;
+ UINT MaxMulticastList = DEFAULT_MULTICASTLISTMAX;
+
+ PMAC_BLOCK NewMacP = &WdMacBlock;
+ NDIS_STATUS Status;
+ PWD_ADAPTER Adapter;
+ NDIS_ADAPTER_INFORMATION AdapterInformation; // needed to register adapter
+
+
+ UNREFERENCED_PARAMETER(MacMacContext);
+
+ NdisOpenConfiguration(
+ &Status,
+ &ConfigHandle,
+ ConfigurationHandle
+ );
+
+ if (Status != NDIS_STATUS_SUCCESS) {
+
+ return NDIS_STATUS_FAILURE;
+
+ }
+
+ //
+ // Read MaxMulticastList
+ //
+
+ NdisReadConfiguration(
+ &Status,
+ &ReturnedValue,
+ ConfigHandle,
+ &MaxMulticastListStr,
+ NdisParameterInteger
+ );
+
+ if (Status == NDIS_STATUS_SUCCESS) {
+
+ MaxMulticastList = ReturnedValue->ParameterData.IntegerData;
+
+ }
+
+ //
+ // Read Bus Type
+ //
+
+ NdisReadConfiguration(
+ &Status,
+ &ReturnedValue,
+ ConfigHandle,
+ &BusTypeStr,
+ NdisParameterHexInteger
+ );
+
+ if (Status == NDIS_STATUS_SUCCESS) {
+
+ if (ReturnedValue->ParameterData.IntegerData == NdisInterfaceMca) {
+
+ WdBusType = 1;
+
+ } else {
+
+ WdBusType = 0;
+
+ }
+
+ }
+
+
+ //
+ // Read Io Base Address (if Appropriate)
+ //
+
+ if (WdBusType != 1) {
+
+ //
+ // Read I/O Address
+ //
+
+ NdisReadConfiguration(
+ &Status,
+ &ReturnedValue,
+ ConfigHandle,
+ &IOAddressStr,
+ NdisParameterHexInteger
+ );
+
+ if (Status == NDIS_STATUS_SUCCESS) {
+
+ WdIoBaseAddr = (USHORT)(ReturnedValue->ParameterData.IntegerData);
+
+ }
+
+ }
+
+ //
+ // Read net address
+ //
+
+ NdisReadNetworkAddress(
+ &Status,
+ &NetAddress,
+ &Length,
+ ConfigHandle
+ );
+
+ if ((Length == ETH_LENGTH_OF_ADDRESS) && (Status == NDIS_STATUS_SUCCESS)) {
+
+ ETH_COPY_NETWORK_ADDRESS(
+ CurrentAddress,
+ NetAddress
+ );
+
+ }
+
+RegisterAdapter:
+
+ //
+ // Allocate memory for the adapter block now.
+ //
+
+ Status = NdisAllocateMemory( (PVOID *)&Adapter, sizeof(WD_ADAPTER), 0, HighestAcceptableMax);
+
+ if (Status != NDIS_STATUS_SUCCESS) {
+
+ ConfigError = TRUE;
+ ConfigErrorValue = NDIS_ERROR_CODE_OUT_OF_RESOURCES;
+
+ goto RegisterAdapter;
+
+ }
+
+
+ NdisZeroMemory(Adapter,sizeof(WD_ADAPTER));
+
+ if (!ConfigError && (WdBusType == 1)) {
+
+ if (LM_Get_Mca_Io_Base_Address(
+ &(Adapter->LMAdapter),
+ ConfigurationHandle,
+ &WdIoBaseAddr
+ )) {
+
+ WdIoBaseAddr = 0;
+ ConfigError = TRUE;
+ ConfigErrorValue = NDIS_ERROR_CODE_UNSUPPORTED_CONFIGURATION;
+
+ }
+
+ }
+
+ //
+ // The adapter is initialized, register it with NDIS.
+ // This must occur before interrupts are enabled since the
+ // InitializeInterrupt routine requires the NdisAdapterHandle
+ //
+
+ //
+ // Set up the AdapterInformation structure; zero it
+ // first in case it is extended later.
+ //
+
+ NdisZeroMemory (&AdapterInformation, sizeof(NDIS_ADAPTER_INFORMATION));
+ AdapterInformation.AdapterType = (WdBusType == 1)?
+ NdisInterfaceMca:
+ NdisInterfaceIsa;
+ AdapterInformation.NumberOfPortDescriptors = 1;
+ AdapterInformation.PortDescriptors[0].InitialPort = (ULONG)WdIoBaseAddr;
+ AdapterInformation.PortDescriptors[0].NumberOfPorts = 0x20;
+
+
+ Status = NdisRegisterAdapter(&Adapter->LMAdapter.NdisAdapterHandle,
+ WdMacBlock.NdisMacHandle,
+ (NDIS_HANDLE)Adapter,
+ ConfigurationHandle,
+ AdapterName,
+ &AdapterInformation
+ );
+
+ if (Status != NDIS_STATUS_SUCCESS) {
+
+ //
+ // NdisRegisterAdapter failed.
+ //
+
+ NdisCloseConfiguration(ConfigHandle);
+
+ NdisFreeMemory(Adapter, sizeof(WD_ADAPTER), 0);
+ return NDIS_STATUS_FAILURE;
+
+ }
+
+
+ if (ConfigError) {
+
+ //
+ // Log Error and exit.
+ //
+
+ NdisWriteErrorLogEntry(
+ Adapter->LMAdapter.NdisAdapterHandle,
+ ConfigErrorValue,
+ 1
+ );
+
+ NdisCloseConfiguration(ConfigHandle);
+
+ NdisDeregisterAdapter(Adapter->LMAdapter.NdisAdapterHandle);
+
+ NdisFreeMemory(Adapter, sizeof(WD_ADAPTER), 0);
+
+ return(NDIS_STATUS_FAILURE);
+
+ }
+
+ Adapter->LMAdapter.io_base = WdIoBaseAddr;
+ Adapter->LMAdapter.bus_type = WdBusType;
+
+ LmStatus = LM_Get_Config(&(Adapter->LMAdapter));
+
+ if (LmStatus == ADAPTER_NOT_FOUND) {
+
+ NdisWriteErrorLogEntry(
+ Adapter->LMAdapter.NdisAdapterHandle,
+ NDIS_ERROR_CODE_ADAPTER_NOT_FOUND,
+ 0
+ );
+
+ NdisCloseConfiguration(ConfigHandle);
+
+ NdisDeregisterAdapter(Adapter->LMAdapter.NdisAdapterHandle);
+ NdisFreeMemory(Adapter, sizeof(WD_ADAPTER), 0);
+
+ return(NDIS_STATUS_FAILURE);
+
+ }
+
+ if (LmStatus == ADAPTER_NO_CONFIG) {
+
+ //
+ // Read any information from the registry which might help
+ //
+
+
+ //
+ // Read Interrupt
+ //
+
+ NdisReadConfiguration(
+ &Status,
+ &ReturnedValue,
+ ConfigHandle,
+ &InterruptStr,
+ NdisParameterInteger
+ );
+
+ if (Status == NDIS_STATUS_SUCCESS) {
+
+ Adapter->LMAdapter.irq_value = (USHORT)(ReturnedValue->ParameterData.IntegerData);
+
+ }
+
+
+
+ //
+ // Read MemoryBaseAddress
+ //
+
+
+ NdisReadConfiguration(
+ &Status,
+ &ReturnedValue,
+ ConfigHandle,
+ &MemoryBaseAddrStr,
+ NdisParameterHexInteger
+ );
+
+ if (Status == NDIS_STATUS_SUCCESS) {
+
+#if NDIS_NT
+ Adapter->LMAdapter.ram_base = (ULONG)(ReturnedValue->ParameterData.IntegerData);
+#else
+ Adapter->LMAdapter.ram_base = (ULONG)((ReturnedValue->ParameterData.IntegerData) << 4);
+#endif
+
+ }
+
+
+ }
+
+ NdisCloseConfiguration(ConfigHandle);
+
+
+ if (WdRegisterAdapter(Adapter,
+ DEFAULT_NUMBUFFERS,
+ MaxMulticastList,
+ CurrentAddress
+ )
+ != NDIS_STATUS_SUCCESS) {
+
+
+
+ //
+ // WdRegisterAdapter failed.
+ //
+
+ NdisDeregisterAdapter(Adapter->LMAdapter.NdisAdapterHandle);
+ NdisFreeMemory(Adapter, sizeof(WD_ADAPTER), 0);
+ return NDIS_STATUS_FAILURE;
+ }
+
+
+
+ IF_LOUD( DbgPrint( "WdRegisterAdapter succeeded\n" );)
+
+
+ return NDIS_STATUS_SUCCESS;
+}
+
+
+
+#pragma NDIS_INIT_FUNCTION(WdRegisterAdapter)
+
+NDIS_STATUS
+WdRegisterAdapter(
+ IN PWD_ADAPTER Adapter,
+ IN UINT NumBuffers,
+ IN UINT MulticastListMax,
+ IN UCHAR NodeAddress[ETH_LENGTH_OF_ADDRESS]
+ )
+
+/*++
+
+
+Routine Description:
+
+ Called when a new adapter should be registered. It allocates space for
+ the adapter and open blocks, initializes the adapters block, and
+ calls NdisRegisterAdapter().
+
+Arguments:
+
+ Adapter - A pointer to the adapter structure.
+ NumBuffers - Number of transmit buffers.
+ MulticastListMax - Number of multicast list addresses allowed.
+ NodeAddress - Ethernet address for this adapter. if all 0x00 then the
+ permanent address on the card is used.
+
+Return Value:
+
+ Indicates the success or failure of the registration.
+
+--*/
+
+{
+ UINT i;
+ CHAR KernelInterrupt;
+ NDIS_PHYSICAL_ADDRESS PhysicalAddress;
+
+ NDIS_STATUS status; //general purpose return from NDIS calls
+
+
+ Adapter->MulticastListMax = MulticastListMax;
+
+ //
+ // check that NumBuffers <= MAX_XMIT_BUFS
+ //
+
+ if (NumBuffers > MAX_XMIT_BUFS) {
+
+ NdisWriteErrorLogEntry(
+ Adapter->LMAdapter.NdisAdapterHandle,
+ NDIS_ERROR_CODE_OUT_OF_RESOURCES,
+ 0
+ );
+
+ status = NDIS_STATUS_RESOURCES;
+
+ goto fail1;
+
+ }
+
+
+ Adapter->OpenQueue = (PWD_OPEN)NULL;
+
+ //
+ // Allocate the Spin lock.
+ //
+ NdisAllocateSpinLock(&Adapter->Lock);
+
+
+ //
+ // Initialize Transmit information
+ //
+
+ Adapter->DeferredDpc = (PVOID) WdInterruptDpc;
+
+ //
+ // Initialize References.
+ //
+
+ NdisInitializeTimer(&(Adapter->DeferredTimer),
+ Adapter->DeferredDpc,
+ Adapter);
+
+ //
+ // Link us on to the chain of adapters for this MAC.
+ //
+
+ Adapter->MacBlock = &WdMacBlock;
+ NdisAcquireSpinLock(&WdMacBlock.SpinLock);
+ Adapter->NextAdapter = WdMacBlock.AdapterQueue;
+ WdMacBlock.AdapterQueue = Adapter;
+ NdisReleaseSpinLock(&WdMacBlock.SpinLock);
+
+ //
+ // Set up the interrupt handlers.
+ //
+
+ KernelInterrupt = (CCHAR)(Adapter->LMAdapter.irq_value);
+
+ NdisInitializeInterrupt(&status, // status of call
+ &(Adapter->LMAdapter.NdisInterrupt), // interrupt info str
+ Adapter->LMAdapter.NdisAdapterHandle,
+ (PNDIS_INTERRUPT_SERVICE) WdInterruptHandler,
+ Adapter, // context for ISR, DPC
+ (PNDIS_DEFERRED_PROCESSING) WdInterruptDpc,
+ KernelInterrupt, // int #
+ KernelInterrupt, // IRQL
+ FALSE, // NOT shared
+ (Adapter->LMAdapter.bus_type == 0) ?
+ NdisInterruptLatched : // ATBus
+ NdisInterruptLevelSensitive // MCA
+ );
+
+
+ if (status != NDIS_STATUS_SUCCESS) {
+
+ NdisWriteErrorLogEntry(
+ Adapter->LMAdapter.NdisAdapterHandle,
+ NDIS_ERROR_CODE_INTERRUPT_CONNECT,
+ 0
+ );
+
+ goto fail3;
+ }
+
+ IF_LOUD( DbgPrint("Interrupt Connected\n");)
+
+ //
+ // Map the memory mapped portion of the card.
+ //
+ //
+
+ NdisSetPhysicalAddressHigh(PhysicalAddress, 0);
+ NdisSetPhysicalAddressLow(PhysicalAddress, (ULONG)(Adapter->LMAdapter.ram_base));
+
+ NdisMapIoSpace(&status,
+ &Adapter->LMAdapter.ram_access,
+ Adapter->LMAdapter.NdisAdapterHandle,
+ PhysicalAddress,
+ Adapter->LMAdapter.ram_size * 1024);
+
+ if (status != NDIS_STATUS_SUCCESS) {
+
+ NdisWriteErrorLogEntry(
+ Adapter->LMAdapter.NdisAdapterHandle,
+ NDIS_ERROR_CODE_RESOURCE_CONFLICT,
+ 0
+ );
+
+ goto failmap;
+
+ }
+
+
+ //
+ // Now Initialize the card.
+ //
+
+ //
+ // Set Relevant variables first...
+ //
+ // base_io and ram_size are set from LM_Get_Config.
+ //
+ //
+ //
+ // ram_access, node_address, max_packet_size, buffer_page_size,
+ // num_of_tx_buffs and receive_mask need to be set.
+ //
+
+ for (i = 0; i < 6 ; i ++) {
+
+ Adapter->LMAdapter.node_address[i] = NodeAddress[i];
+
+ }
+
+ Adapter->LMAdapter.max_packet_size = WD_MAX_PACKET_SIZE;
+ Adapter->LMAdapter.buffer_page_size= WD_BUFFER_PAGE_SIZE;
+ Adapter->LMAdapter.num_of_tx_buffs = (USHORT)NumBuffers;
+
+ Adapter->LMAdapter.ptr_rx_CRC_errors = &(Adapter->CrcErrors);
+ Adapter->LMAdapter.ptr_rx_too_big = &(Adapter->TooBig);
+ Adapter->LMAdapter.ptr_rx_lost_pkts = &(Adapter->MissedPackets);
+ Adapter->LMAdapter.ptr_rx_align_errors = &(Adapter->FrameAlignmentErrors);
+ Adapter->LMAdapter.ptr_rx_overruns = &(Adapter->Overruns);
+
+ Adapter->LMAdapter.ptr_tx_deferred = &(Adapter->FramesXmitDeferred);
+ Adapter->LMAdapter.ptr_tx_max_collisions = &(Adapter->FramesXmitBad);
+ Adapter->LMAdapter.ptr_tx_one_collision = &(Adapter->FramesXmitOneCollision);
+ Adapter->LMAdapter.ptr_tx_mult_collisions = &(Adapter->FramesXmitManyCollisions);
+ Adapter->LMAdapter.ptr_tx_ow_collision = &(Adapter->FramesXmitOverWrite);
+ Adapter->LMAdapter.ptr_tx_CD_heartbeat = &(Adapter->FramesXmitHeartbeat);
+ Adapter->LMAdapter.ptr_tx_underruns = &(Adapter->FramesXmitUnderruns);
+ Adapter->LMAdapter.FilterDB = NULL;
+
+ if (LM_Initialize_Adapter(&(Adapter->LMAdapter)) != SUCCESS){
+
+ //
+ // The Card could not be written to.
+ //
+
+ Adapter->HardwareFailure = TRUE;
+
+ NdisWriteErrorLogEntry(
+ Adapter->LMAdapter.NdisAdapterHandle,
+ NDIS_ERROR_CODE_HARDWARE_FAILURE,
+ 0
+ );
+
+ status = NDIS_STATUS_ADAPTER_NOT_FOUND;
+
+ goto fail6;
+ }
+
+
+ //
+ // Initialize Filter Database
+ //
+
+ if (!EthCreateFilter(MulticastListMax,
+ WdChangeMulticastAddresses,
+ WdChangeFilterClasses,
+ WdCloseAction,
+ Adapter->LMAdapter.node_address,
+ &Adapter->Lock,
+ &Adapter->LMAdapter.FilterDB
+ )) {
+
+ NdisWriteErrorLogEntry(
+ Adapter->LMAdapter.NdisAdapterHandle,
+ NDIS_ERROR_CODE_OUT_OF_RESOURCES,
+ 0
+ );
+
+ status = NDIS_STATUS_FAILURE;
+
+ goto fail6;
+
+ }
+
+ //
+ // Initialize the wake up timer to catch interrupts that
+ // don't complete. It fires continuously
+ // every 5 seconds, and we check if there are any
+ // uncompleted operations from the previous two-second
+ // period.
+ //
+
+ Adapter->WakeUpDpc = (PVOID)WdWakeUpDpc;
+
+ NdisInitializeTimer(&Adapter->WakeUpTimer,
+ (PVOID)(Adapter->WakeUpDpc),
+ Adapter );
+
+ NdisSetTimer(
+ &Adapter->WakeUpTimer,
+ 5000
+ );
+
+ //
+ // Initialization completed successfully.
+ //
+
+ IF_LOUD( { DbgPrint(" WdLan: [OK]\n");})
+
+ return NDIS_STATUS_SUCCESS;
+
+
+ //
+ // Code to unwind what has already been set up when a part of
+ // initialization fails, which is jumped into at various
+ // points based on where the failure occured. Jumping to
+ // a higher-numbered failure point will execute the code
+ // for that block and all lower-numbered ones.
+ //
+
+fail6:
+
+ NdisUnmapIoSpace(
+ Adapter->LMAdapter.NdisAdapterHandle,
+ Adapter->LMAdapter.ram_access,
+ Adapter->LMAdapter.ram_size * 1024);
+
+failmap:
+
+ NdisRemoveInterrupt(&(Adapter->LMAdapter.NdisInterrupt));
+
+ NdisAcquireSpinLock(&WdMacBlock.SpinLock);
+
+ //
+ // Take us out of the AdapterQueue.
+ //
+
+ if (WdMacBlock.AdapterQueue == Adapter) {
+
+ WdMacBlock.AdapterQueue = Adapter->NextAdapter;
+
+ } else {
+
+ PWD_ADAPTER TmpAdapter = WdMacBlock.AdapterQueue;
+
+ while (TmpAdapter->NextAdapter != Adapter) {
+
+ TmpAdapter = TmpAdapter->NextAdapter;
+
+ }
+
+ TmpAdapter->NextAdapter = TmpAdapter->NextAdapter->NextAdapter;
+ }
+
+ NdisReleaseSpinLock(&WdMacBlock.SpinLock);
+
+fail3:
+ NdisFreeSpinLock(&Adapter->Lock);
+
+fail1:
+
+ return status;
+}
+
+
+#pragma NDIS_PAGABLE_FUNCTION(WdOpenAdapter)
+
+
+NDIS_STATUS
+WdOpenAdapter(
+ OUT PNDIS_STATUS OpenErrorStatus,
+ OUT NDIS_HANDLE * MacBindingHandle,
+ OUT PUINT SelectedMediumIndex,
+ IN PNDIS_MEDIUM MediumArray,
+ IN UINT MediumArraySize,
+ IN NDIS_HANDLE NdisBindingContext,
+ IN NDIS_HANDLE MacAdapterContext,
+ IN UINT OpenOptions,
+ IN PSTRING AddressingInformation OPTIONAL
+ )
+
+/*++
+
+Routine Description:
+
+ NDIS function. It initializes the open block and links it in
+ the appropriate lists.
+
+Arguments:
+
+ See NDIS 3.0 spec.
+
+--*/
+
+{
+ PWD_ADAPTER Adapter = ((PWD_ADAPTER)MacAdapterContext);
+ PWD_OPEN NewOpen;
+ NDIS_STATUS Status;
+
+ //
+ // Don't use extended error or OpenOptions for Wd
+ //
+
+ UNREFERENCED_PARAMETER(OpenOptions);
+
+ *OpenErrorStatus=NDIS_STATUS_SUCCESS;
+
+ IF_LOUD( DbgPrint("In Open Adapter\n");)
+
+ //
+ // Scan the media list for our media type (802.3)
+ //
+
+ *SelectedMediumIndex = (UINT)(-1);
+
+ while (MediumArraySize > 0) {
+
+ if (MediumArray[--MediumArraySize] == NdisMedium802_3 ) {
+
+ *SelectedMediumIndex = MediumArraySize;
+
+ break;
+ }
+ }
+
+
+ if (*SelectedMediumIndex == -1) {
+
+ return NDIS_STATUS_UNSUPPORTED_MEDIA;
+
+ }
+
+ //
+ // Link this open to the appropriate lists.
+ //
+
+ if (Adapter->HardwareFailure) {
+
+ return(NDIS_STATUS_FAILURE);
+
+ }
+
+ //
+ // Allocate memory for the open.
+ //
+
+
+ Status = NdisAllocateMemory((PVOID *)&NewOpen, sizeof(WD_OPEN), 0, HighestAcceptableMax);
+
+ if (Status != NDIS_STATUS_SUCCESS) {
+
+ NdisWriteErrorLogEntry(
+ Adapter->LMAdapter.NdisAdapterHandle,
+ NDIS_ERROR_CODE_OUT_OF_RESOURCES,
+ 0
+ );
+
+ return(NDIS_STATUS_RESOURCES);
+
+ }
+
+ NdisAcquireSpinLock(&Adapter->Lock);
+
+ Adapter->References++;
+
+ //
+ // Link this open to the appropriate lists.
+ //
+
+ if (Adapter->OpenQueue == NULL) {
+
+ //
+ // The first open on this adapter.
+ //
+
+ if (LM_Open_Adapter(&(Adapter->LMAdapter)) != SUCCESS) {
+
+ IF_LOUD( DbgPrint("OpenFailed!\n");)
+
+ NdisReleaseSpinLock(&Adapter->Lock);
+
+ NdisWriteErrorLogEntry(
+ Adapter->LMAdapter.NdisAdapterHandle,
+ NDIS_ERROR_CODE_HARDWARE_FAILURE,
+ 0
+ );
+
+ return(NDIS_STATUS_FAILURE);
+
+ }
+
+ IF_LOUD( DbgPrint("OpenSuccess!\n");)
+
+ }
+
+ NewOpen->NextOpen = Adapter->OpenQueue;
+ Adapter->OpenQueue = NewOpen;
+
+ if (!EthNoteFilterOpenAdapter(
+ Adapter->LMAdapter.FilterDB,
+ NewOpen,
+ NdisBindingContext,
+ &NewOpen->NdisFilterHandle
+ )) {
+
+ Adapter->References--;
+
+ Adapter->OpenQueue = NewOpen->NextOpen;
+
+ NdisReleaseSpinLock(&Adapter->Lock);
+
+ NdisWriteErrorLogEntry(
+ Adapter->LMAdapter.NdisAdapterHandle,
+ NDIS_ERROR_CODE_OUT_OF_RESOURCES,
+ 0
+ );
+
+ return NDIS_STATUS_FAILURE;
+
+
+ }
+
+ //
+ // Set up the open block.
+ //
+
+ NewOpen->Adapter = Adapter;
+ NewOpen->MacBlock = Adapter->MacBlock;
+ NewOpen->NdisBindingContext = NdisBindingContext;
+ NewOpen->AddressingInformation = AddressingInformation;
+ NewOpen->Closing = FALSE;
+ NewOpen->LookAhead = WD_MAX_LOOKAHEAD;
+ NewOpen->ProtOptionFlags = 0;
+
+ Adapter->MaxLookAhead = WD_MAX_LOOKAHEAD;
+
+ NewOpen->ReferenceCount = 1;
+
+ *MacBindingHandle = (NDIS_HANDLE)NewOpen;
+
+ WD_DO_DEFERRED(Adapter);
+
+ IF_LOUD( DbgPrint("Out Open Adapter\n");)
+
+ return NDIS_STATUS_SUCCESS;
+}
+
+
+
+VOID
+WdAdjustMaxLookAhead(
+ IN PWD_ADAPTER Adapter
+ )
+/*++
+
+Routine Description:
+
+ This routine finds the open with the maximum lookahead value and
+ stores that in the adapter block.
+
+ NOTE: THIS ROUTINE MUST BE CALLED WITH THE SPINLOCK HELD.
+
+Arguments:
+
+ Adapter - A pointer to the adapter block.
+
+Returns:
+
+ None.
+
+--*/
+{
+ ULONG CurrentMax = 0;
+ PWD_OPEN CurrentOpen;
+
+ CurrentOpen = Adapter->OpenQueue;
+
+ while (CurrentOpen != NULL) {
+
+ if (CurrentOpen->LookAhead > CurrentMax) {
+
+ CurrentMax = CurrentOpen->LookAhead;
+
+ }
+
+ CurrentOpen = CurrentOpen->NextOpen;
+ }
+
+ if (CurrentMax == 0) {
+
+ CurrentMax = WD_MAX_LOOKAHEAD;
+
+ }
+
+ Adapter->MaxLookAhead = CurrentMax;
+
+}
+
+NDIS_STATUS
+WdCloseAdapter(
+ IN NDIS_HANDLE MacBindingHandle
+ )
+
+/*++
+
+Routine Description:
+
+ NDIS function. Unlinks the open block and frees it.
+
+Arguments:
+
+ See NDIS 3.0 spec.
+
+--*/
+
+{
+ PWD_OPEN Open = ((PWD_OPEN)MacBindingHandle);
+ PWD_ADAPTER Adapter = Open->Adapter;
+ PWD_OPEN TmpOpen;
+ NDIS_STATUS StatusToReturn;
+
+ NdisAcquireSpinLock(&Adapter->Lock);
+
+ if (Open->Closing) {
+
+ //
+ // The open is already being closed.
+ //
+
+ NdisReleaseSpinLock(&Adapter->Lock);
+
+ return NDIS_STATUS_CLOSING;
+ }
+
+ Adapter->References++;
+
+ Open->ReferenceCount++;
+
+ //
+ // Remove this open from the list for this adapter.
+ //
+
+ if (Open == Adapter->OpenQueue) {
+
+ Adapter->OpenQueue = Open->NextOpen;
+
+ } else {
+
+ TmpOpen = Adapter->OpenQueue;
+
+ while (TmpOpen->NextOpen != Open) {
+
+ TmpOpen = TmpOpen->NextOpen;
+
+ }
+
+ TmpOpen->NextOpen = Open->NextOpen;
+ }
+
+
+
+ //
+ // Remove from Filter package to block all receives.
+ //
+
+ StatusToReturn = EthDeleteFilterOpenAdapter(
+ Adapter->LMAdapter.FilterDB,
+ Open->NdisFilterHandle,
+ NULL
+ );
+
+ //
+ // If the status is successful that merely implies that
+ // we were able to delete the reference to the open binding
+ // from the filtering code. If we have a successful status
+ // at this point we still need to check whether the reference
+ // count to determine whether we can close.
+ //
+ //
+ // The delete filter routine can return a "special" status
+ // that indicates that there is a current NdisIndicateReceive
+ // on this binding. See below.
+ //
+
+ if (StatusToReturn == NDIS_STATUS_SUCCESS) {
+
+ //
+ // Check whether the reference count is two. If
+ // it is then we can get rid of the memory for
+ // this open.
+ //
+ // A count of two indicates one for this routine
+ // and one for the filter which we *know* we can
+ // get rid of.
+ //
+
+ if (Open->ReferenceCount != 2) {
+
+ //
+ // We are not the only reference to the open. Remove
+ // it from the open list and delete the memory.
+ //
+
+
+ Open->Closing = TRUE;
+
+ //
+ // Account for this routines reference to the open
+ // as well as reference because of the original open.
+ //
+
+ Open->ReferenceCount -= 2;
+
+ //
+ // Change the status to indicate that we will
+ // be closing this later.
+ //
+
+ StatusToReturn = NDIS_STATUS_PENDING;
+
+ } else {
+
+ Open->ReferenceCount -= 2;
+
+ }
+
+ } else if (StatusToReturn == NDIS_STATUS_PENDING) {
+
+ Open->Closing = TRUE;
+
+ //
+ // Account for this routines reference to the open
+ // as well as reference because of the original open.
+ //
+
+ Open->ReferenceCount -= 2;
+
+ } else if (StatusToReturn == NDIS_STATUS_CLOSING_INDICATING) {
+
+ //
+ // When we have this status it indicates that the filtering
+ // code was currently doing an NdisIndicateReceive. It
+ // would not be wise to delete the memory for the open at
+ // this point. The filtering code will call our close action
+ // routine upon return from NdisIndicateReceive and that
+ // action routine will decrement the reference count for
+ // the open.
+ //
+
+ Open->Closing = TRUE;
+
+ //
+ // This status is private to the filtering routine. Just
+ // tell the caller the the close is pending.
+ //
+
+ StatusToReturn = NDIS_STATUS_PENDING;
+
+ //
+ // Account for this routines reference to the open.
+ //
+
+ Open->ReferenceCount--;
+
+ } else {
+
+ //
+ // Account for this routines reference to the open.
+ //
+
+ Open->ReferenceCount--;
+
+ }
+
+ //
+ // See if this is the last reference to this open.
+ //
+
+ if (Open->ReferenceCount == 0) {
+
+ //
+ // Check if the MaxLookAhead needs adjustment.
+ //
+
+ if (Open->LookAhead == Adapter->MaxLookAhead) {
+
+ WdAdjustMaxLookAhead(Adapter);
+
+ }
+
+
+ if (Adapter->OpenQueue == NULL) {
+
+ //
+ // We can disable the card.
+ //
+
+ if (NdisSynchronizeWithInterrupt(
+ &(Adapter->LMAdapter.NdisInterrupt),
+ (PVOID)WdSyncCloseAdapter,
+ (PVOID)(&(Adapter->LMAdapter))
+ ) == FALSE) {
+
+ NdisWriteErrorLogEntry(
+ Adapter->LMAdapter.NdisAdapterHandle,
+ NDIS_ERROR_CODE_HARDWARE_FAILURE,
+ 0
+ );
+
+ IF_LOUD( DbgPrint("CloseAdapter FAILED!\n");)
+
+ } else {
+
+
+ IF_LOUD( DbgPrint("CloseAdapter Success!\n");)
+
+ }
+
+ }
+
+ } else {
+
+ //
+ // Will get removed when count drops to zero.
+ //
+
+ StatusToReturn = NDIS_STATUS_PENDING;
+
+ }
+
+
+ WD_DO_DEFERRED(Adapter);
+
+ return(StatusToReturn);
+
+}
+
+NDIS_STATUS
+WdRequest(
+ IN NDIS_HANDLE MacBindingHandle,
+ IN PNDIS_REQUEST NdisRequest
+ )
+
+/*++
+
+Routine Description:
+
+ This routine allows a protocol to query and set information
+ about the MAC.
+
+Arguments:
+
+ MacBindingHandle - The context value returned by the MAC when the
+ adapter was opened. In reality, it is a pointer to PWD_OPEN.
+
+ NdisRequest - A structure which contains the request type (Set or
+ Query), an array of operations to perform, and an array for holding
+ the results of the operations.
+
+Return Value:
+
+ The function value is the status of the operation.
+
+--*/
+
+{
+ NDIS_STATUS StatusToReturn = NDIS_STATUS_SUCCESS;
+
+ PWD_OPEN Open = (PWD_OPEN)(MacBindingHandle);
+ PWD_ADAPTER Adapter = (Open->Adapter);
+
+
+ IF_LOUD( DbgPrint("In Request\n");)
+
+ NdisAcquireSpinLock(&Adapter->Lock);
+
+ //
+ // Ensure that the open does not close while in this function.
+ //
+
+ Open->ReferenceCount++;
+
+ Adapter->References++;
+
+ //
+ // Process request
+ //
+
+ if (Open->Closing) {
+
+ NdisReleaseSpinLock(&Adapter->Lock);
+
+ StatusToReturn = NDIS_STATUS_CLOSING;
+
+ } else if (NdisRequest->RequestType == NdisRequestQueryInformation) {
+
+ NdisReleaseSpinLock(&Adapter->Lock);
+
+ StatusToReturn = WdQueryInformation(Adapter, Open, NdisRequest);
+
+ } else if (NdisRequest->RequestType == NdisRequestSetInformation) {
+
+ if (Adapter->HardwareFailure) {
+
+ NdisReleaseSpinLock(&Adapter->Lock);
+
+ StatusToReturn = NDIS_STATUS_FAILURE;
+
+ } else {
+
+ NdisReleaseSpinLock(&Adapter->Lock);
+
+ StatusToReturn = WdSetInformation(Adapter,Open,NdisRequest);
+
+ }
+
+ } else {
+
+ NdisReleaseSpinLock(&Adapter->Lock);
+
+ StatusToReturn = NDIS_STATUS_NOT_RECOGNIZED;
+
+ }
+
+ NdisAcquireSpinLock(&Adapter->Lock);
+
+ WdRemoveReference(Open);
+
+ WD_DO_DEFERRED(Adapter);
+
+ IF_LOUD( DbgPrint("Out Request\n");)
+
+ return(StatusToReturn);
+
+}
+
+NDIS_STATUS
+WdQueryProtocolInformation(
+ IN PWD_ADAPTER Adapter,
+ IN PWD_OPEN Open,
+ IN NDIS_OID Oid,
+ IN BOOLEAN GlobalMode,
+ IN PVOID InfoBuffer,
+ IN UINT BytesLeft,
+ OUT PUINT BytesNeeded,
+ OUT PUINT BytesWritten
+)
+
+/*++
+
+Routine Description:
+
+ The WdQueryProtocolInformation process a Query request for
+ NDIS_OIDs that are specific to a binding about the MAC. Note that
+ some of the OIDs that are specific to bindings are also queryable
+ on a global basis. Rather than recreate this code to handle the
+ global queries, I use a flag to indicate if this is a query for the
+ global data or the binding specific data.
+
+Arguments:
+
+ Adapter - a pointer to the adapter.
+
+ Open - a pointer to the open instance.
+
+ Oid - the NDIS_OID to process.
+
+ GlobalMode - Some of the binding specific information is also used
+ when querying global statistics. This is a flag to specify whether
+ to return the global value, or the binding specific value.
+
+ PlaceInInfoBuffer - a pointer into the NdisRequest->InformationBuffer
+ into which store the result of the query.
+
+ BytesLeft - the number of bytes left in the InformationBuffer.
+
+ BytesNeeded - If there is not enough room in the information buffer
+ then this will contain the number of bytes needed to complete the
+ request.
+
+ BytesWritten - a pointer to the number of bytes written into the
+ InformationBuffer.
+
+Return Value:
+
+ The function value is the status of the operation.
+
+--*/
+
+{
+ NDIS_MEDIUM Medium = NdisMedium802_3;
+ ULONG GenericULong;
+ USHORT GenericUShort;
+ UCHAR GenericArray[6];
+
+ NDIS_STATUS StatusToReturn = NDIS_STATUS_SUCCESS;
+
+ //
+ // Common variables for pointing to result of query
+ //
+
+ PVOID MoveSource = (PVOID)(&GenericULong);
+ ULONG MoveBytes = sizeof(ULONG);
+
+ NDIS_HARDWARE_STATUS HardwareStatus = NdisHardwareStatusReady;
+
+ //
+ // General Algorithm:
+ //
+ // Switch(Request)
+ // Get requested information
+ // Store results in a common variable.
+ // Copy result in common variable to result buffer.
+ //
+
+ //
+ // Make sure that ulong is 4 bytes. Else GenericULong must change
+ // to something of size 4.
+ //
+ ASSERT(sizeof(ULONG) == 4);
+
+
+ IF_LOUD( DbgPrint("In QueryProtocol\n");)
+
+ //
+ // Make sure no changes occur while processing.
+ //
+
+ NdisAcquireSpinLock(&Adapter->Lock);
+
+ //
+ // Switch on request type
+ //
+
+ switch (Oid) {
+
+ case OID_GEN_MAC_OPTIONS:
+
+ GenericULong = (ULONG)(NDIS_MAC_OPTION_TRANSFERS_NOT_PEND |
+ NDIS_MAC_OPTION_RECEIVE_SERIALIZED |
+ NDIS_MAC_OPTION_NO_LOOPBACK
+ );
+
+ break;
+
+ case OID_GEN_SUPPORTED_LIST:
+
+ if (!GlobalMode) {
+
+ MoveSource = (PVOID)(WdProtocolSupportedOids);
+ MoveBytes = sizeof(WdProtocolSupportedOids);
+
+ } else {
+
+ MoveSource = (PVOID)(WdGlobalSupportedOids);
+ MoveBytes = sizeof(WdGlobalSupportedOids);
+
+ }
+ break;
+
+ case OID_GEN_HARDWARE_STATUS:
+
+ if (Adapter->HardwareFailure) {
+
+ HardwareStatus = NdisHardwareStatusNotReady;
+
+ } else {
+
+ HardwareStatus = NdisHardwareStatusReady;
+
+ }
+
+ MoveSource = (PVOID)(&HardwareStatus);
+ MoveBytes = sizeof(NDIS_HARDWARE_STATUS);
+
+ break;
+
+ case OID_GEN_MEDIA_SUPPORTED:
+ case OID_GEN_MEDIA_IN_USE:
+
+ MoveSource = (PVOID) (&Medium);
+ MoveBytes = sizeof(NDIS_MEDIUM);
+ break;
+
+ case OID_GEN_MAXIMUM_LOOKAHEAD:
+
+ GenericULong = WD_MAX_LOOKAHEAD;
+
+ break;
+
+
+ case OID_GEN_MAXIMUM_FRAME_SIZE:
+
+ GenericULong = (ULONG)(WD_MAX_PACKET_SIZE - WD_HEADER_SIZE);
+
+ break;
+
+
+ case OID_GEN_MAXIMUM_TOTAL_SIZE:
+
+ GenericULong = (ULONG)(WD_MAX_PACKET_SIZE);
+
+ break;
+
+
+ case OID_GEN_LINK_SPEED:
+
+ GenericULong = (ULONG)(100000);
+
+ break;
+
+
+ case OID_GEN_TRANSMIT_BUFFER_SPACE:
+
+ GenericULong = (ULONG)(Adapter->LMAdapter.num_of_tx_buffs
+ * Adapter->LMAdapter.xmit_buf_size);
+
+ break;
+
+ case OID_GEN_RECEIVE_BUFFER_SPACE:
+
+ GenericULong = (ULONG)((Adapter->LMAdapter.ram_size * 1024) -
+ (Adapter->LMAdapter.num_of_tx_buffs
+ * Adapter->LMAdapter.xmit_buf_size));
+
+ break;
+
+ case OID_GEN_TRANSMIT_BLOCK_SIZE:
+
+ GenericULong = (ULONG)(Adapter->LMAdapter.buffer_page_size);
+
+ break;
+
+ case OID_GEN_RECEIVE_BLOCK_SIZE:
+
+ GenericULong = (ULONG)(Adapter->LMAdapter.buffer_page_size);
+
+ break;
+
+ case OID_GEN_VENDOR_ID:
+
+ NdisMoveMemory(
+ (PVOID)&GenericULong,
+ Adapter->LMAdapter.permanent_node_address,
+ 3
+ );
+ GenericULong &= 0xFFFFFF00;
+ MoveSource = (PVOID)(&GenericULong);
+ MoveBytes = sizeof(GenericULong);
+ break;
+
+ case OID_GEN_VENDOR_DESCRIPTION:
+
+ MoveSource = (PVOID)"SMC Adapter.";
+ MoveBytes = 13;
+
+ break;
+
+ case OID_GEN_DRIVER_VERSION:
+
+ GenericUShort = ((USHORT)WD_NDIS_MAJOR_VERSION << 8) |
+ WD_NDIS_MINOR_VERSION;
+
+ MoveSource = (PVOID)(&GenericUShort);
+ MoveBytes = sizeof(GenericUShort);
+ break;
+
+
+ case OID_GEN_CURRENT_PACKET_FILTER:
+
+ if (GlobalMode) {
+
+ UINT Filter;
+
+ Filter = ETH_QUERY_FILTER_CLASSES(Adapter->LMAdapter.FilterDB);
+
+ GenericULong = (ULONG)(Filter);
+
+ } else {
+
+ UINT Filter = 0;
+
+ Filter = ETH_QUERY_PACKET_FILTER(Adapter->LMAdapter.FilterDB,
+ Open->NdisFilterHandle);
+
+ GenericULong = (ULONG)(Filter);
+
+ }
+
+ break;
+
+ case OID_GEN_CURRENT_LOOKAHEAD:
+
+ if ( GlobalMode ) {
+
+ GenericULong = (ULONG)(Adapter->MaxLookAhead);
+
+ } else {
+
+ GenericULong = Open->LookAhead;
+
+ }
+
+ break;
+
+ case OID_802_3_PERMANENT_ADDRESS:
+
+ WD_MOVE_MEM((PCHAR)GenericArray,
+ Adapter->LMAdapter.permanent_node_address,
+ ETH_LENGTH_OF_ADDRESS);
+
+ MoveSource = (PVOID)(GenericArray);
+ MoveBytes = sizeof(Adapter->LMAdapter.permanent_node_address);
+ break;
+
+ case OID_802_3_CURRENT_ADDRESS:
+
+ WD_MOVE_MEM((PCHAR)GenericArray,
+ Adapter->LMAdapter.node_address,
+ ETH_LENGTH_OF_ADDRESS);
+
+ MoveSource = (PVOID)(GenericArray);
+ MoveBytes = sizeof(Adapter->LMAdapter.node_address);
+ break;
+
+ case OID_802_3_MULTICAST_LIST:
+
+ {
+ UINT NumAddresses;
+
+
+ if (GlobalMode) {
+
+ NumAddresses = ETH_NUMBER_OF_GLOBAL_FILTER_ADDRESSES(Adapter->LMAdapter.FilterDB);
+
+ if ((NumAddresses * ETH_LENGTH_OF_ADDRESS) > BytesLeft) {
+
+ *BytesNeeded = (NumAddresses * ETH_LENGTH_OF_ADDRESS);
+
+ StatusToReturn = NDIS_STATUS_INVALID_LENGTH;
+
+ break;
+
+ }
+
+ EthQueryGlobalFilterAddresses(
+ &StatusToReturn,
+ Adapter->LMAdapter.FilterDB,
+ BytesLeft,
+ &NumAddresses,
+ InfoBuffer
+ );
+
+ *BytesWritten = NumAddresses * ETH_LENGTH_OF_ADDRESS;
+
+ //
+ // Should not be an error since we held the spinlock
+ // nothing should have changed.
+ //
+
+ ASSERT(StatusToReturn == NDIS_STATUS_SUCCESS);
+
+ } else {
+
+ NumAddresses = EthNumberOfOpenFilterAddresses(
+ Adapter->LMAdapter.FilterDB,
+ Open->NdisFilterHandle
+ );
+
+ if ((NumAddresses * ETH_LENGTH_OF_ADDRESS) > BytesLeft) {
+
+ *BytesNeeded = (NumAddresses * ETH_LENGTH_OF_ADDRESS);
+
+ StatusToReturn = NDIS_STATUS_INVALID_LENGTH;
+
+ break;
+
+ }
+
+ EthQueryOpenFilterAddresses(
+ &StatusToReturn,
+ Adapter->LMAdapter.FilterDB,
+ Open->NdisFilterHandle,
+ BytesLeft,
+ &NumAddresses,
+ InfoBuffer
+ );
+
+ //
+ // Should not be an error since we held the spinlock
+ // nothing should have changed.
+ //
+
+ ASSERT(StatusToReturn == NDIS_STATUS_SUCCESS);
+
+ *BytesWritten = NumAddresses * ETH_LENGTH_OF_ADDRESS;
+
+ }
+
+ }
+
+
+
+ break;
+
+ case OID_802_3_MAXIMUM_LIST_SIZE:
+
+ GenericULong = (ULONG) (Adapter->MulticastListMax);
+
+ break;
+
+
+
+ default:
+
+ StatusToReturn = NDIS_STATUS_NOT_SUPPORTED;
+ break;
+ }
+
+ if ((StatusToReturn == NDIS_STATUS_SUCCESS) &&
+ (Oid != OID_802_3_MULTICAST_LIST)) {
+
+ if (MoveBytes > BytesLeft) {
+
+ //
+ // Not enough room in InformationBuffer. Punt
+ //
+
+ *BytesNeeded = MoveBytes - BytesLeft;
+
+ StatusToReturn = NDIS_STATUS_INVALID_LENGTH;
+
+ } else {
+
+ //
+ // Store result.
+ //
+
+ WD_MOVE_MEM(InfoBuffer, MoveSource, MoveBytes);
+
+ (*BytesWritten) += MoveBytes;
+
+ }
+ }
+
+ NdisReleaseSpinLock(&Adapter->Lock);
+
+ IF_LOUD( DbgPrint("Out QueryProtocol\n");)
+
+ return(StatusToReturn);
+}
+
+NDIS_STATUS
+WdQueryInformation(
+ IN PWD_ADAPTER Adapter,
+ IN PWD_OPEN Open,
+ IN PNDIS_REQUEST NdisRequest
+ )
+/*++
+
+Routine Description:
+
+ The WdQueryInformation is used by WdRequest to query information
+ about the MAC.
+
+Arguments:
+
+ Adapter - A pointer to the adapter.
+
+ Open - A pointer to a particular open instance.
+
+ NdisRequest - A structure which contains the request type (Query),
+ an array of operations to perform, and an array for holding
+ the results of the operations.
+
+Return Value:
+
+ The function value is the status of the operation.
+
+--*/
+
+{
+
+ UINT BytesWritten = 0;
+ UINT BytesNeeded = 0;
+ UINT BytesLeft = NdisRequest->DATA.QUERY_INFORMATION.InformationBufferLength;
+ PUCHAR InfoBuffer = (PUCHAR)(NdisRequest->DATA.QUERY_INFORMATION.InformationBuffer);
+
+ NDIS_STATUS StatusToReturn = NDIS_STATUS_SUCCESS;
+
+
+ IF_LOUD( DbgPrint("In QueryInfor\n");)
+
+ StatusToReturn = WdQueryProtocolInformation(
+ Adapter,
+ Open,
+ NdisRequest->DATA.QUERY_INFORMATION.Oid,
+ FALSE,
+ InfoBuffer,
+ BytesLeft,
+ &BytesNeeded,
+ &BytesWritten
+ );
+
+
+ NdisRequest->DATA.QUERY_INFORMATION.BytesWritten = BytesWritten;
+
+ NdisRequest->DATA.QUERY_INFORMATION.BytesNeeded = BytesNeeded;
+
+ IF_LOUD( DbgPrint("Out QueryInfor\n");)
+
+ return(StatusToReturn);
+}
+
+NDIS_STATUS
+WdSetInformation(
+ IN PWD_ADAPTER Adapter,
+ IN PWD_OPEN Open,
+ IN PNDIS_REQUEST NdisRequest
+ )
+/*++
+
+Routine Description:
+
+ The WdSetInformation is used by WdRequest to set information
+ about the MAC.
+
+Arguments:
+
+ Adapter - A pointer to the adapter.
+
+ Open - A pointer to an open instance.
+
+ NdisRequest - A structure which contains the request type (Set),
+ an array of operations to perform, and an array for holding
+ the results of the operations.
+
+Return Value:
+
+ The function value is the status of the operation.
+
+--*/
+
+{
+
+ //
+ // General Algorithm:
+ //
+ // Verify length
+ // Switch(Request)
+ // Process Request
+ //
+
+ UINT BytesRead = 0;
+ UINT BytesNeeded = 0;
+ UINT BytesLeft = NdisRequest->DATA.SET_INFORMATION.InformationBufferLength;
+ PUCHAR InfoBuffer = (PUCHAR)(NdisRequest->DATA.SET_INFORMATION.InformationBuffer);
+
+ //
+ // Variables for a particular request
+ //
+
+ NDIS_OID Oid;
+ UINT OidLength;
+
+ //
+ // Variables for holding the new values to be used.
+ //
+
+ ULONG LookAhead;
+ ULONG Filter;
+
+ NDIS_STATUS StatusToReturn = NDIS_STATUS_SUCCESS;
+
+
+ IF_LOUD( DbgPrint("In SetInfo\n");)
+
+
+
+ //
+ // Get Oid and Length of request
+ //
+
+ Oid = NdisRequest->DATA.SET_INFORMATION.Oid;
+
+ OidLength = BytesLeft;
+
+ switch (Oid) {
+
+
+ case OID_802_3_MULTICAST_LIST:
+
+ //
+ // Verify length
+ //
+
+ if ((OidLength % ETH_LENGTH_OF_ADDRESS) != 0){
+
+ StatusToReturn = NDIS_STATUS_INVALID_LENGTH;
+
+ NdisRequest->DATA.SET_INFORMATION.BytesRead = 0;
+ NdisRequest->DATA.SET_INFORMATION.BytesNeeded = 0;
+
+ break;
+
+ }
+
+ StatusToReturn = WdSetMulticastAddresses(
+ Adapter,
+ Open,
+ NdisRequest,
+ (UINT)(OidLength / ETH_LENGTH_OF_ADDRESS),
+ (PVOID)InfoBuffer
+ );
+ break;
+
+
+ case OID_GEN_CURRENT_PACKET_FILTER:
+
+ //
+ // Verify length
+ //
+
+ if (OidLength != 4 ) {
+
+ StatusToReturn = NDIS_STATUS_INVALID_LENGTH;
+
+ NdisRequest->DATA.SET_INFORMATION.BytesRead = 0;
+ NdisRequest->DATA.SET_INFORMATION.BytesNeeded = 0;
+
+ break;
+
+ }
+
+
+ WD_MOVE_MEM(&Filter, InfoBuffer, 4);
+
+ //
+ // Verify bits
+ //
+
+ if (Filter & (NDIS_PACKET_TYPE_SOURCE_ROUTING |
+ NDIS_PACKET_TYPE_SMT |
+ NDIS_PACKET_TYPE_MAC_FRAME |
+ NDIS_PACKET_TYPE_FUNCTIONAL |
+ NDIS_PACKET_TYPE_ALL_FUNCTIONAL |
+ NDIS_PACKET_TYPE_GROUP
+ )) {
+
+ StatusToReturn = NDIS_STATUS_NOT_SUPPORTED;
+
+ NdisRequest->DATA.SET_INFORMATION.BytesRead = 4;
+ NdisRequest->DATA.SET_INFORMATION.BytesNeeded = 0;
+
+ break;
+
+ }
+
+ StatusToReturn = WdSetPacketFilter(Adapter,
+ Open,
+ NdisRequest,
+ Filter
+ );
+
+
+
+ break;
+
+ case OID_GEN_CURRENT_LOOKAHEAD:
+
+ //
+ // Verify length
+ //
+
+ if (OidLength != 4) {
+
+ StatusToReturn = NDIS_STATUS_INVALID_LENGTH;
+
+ NdisRequest->DATA.SET_INFORMATION.BytesRead = 0;
+ NdisRequest->DATA.SET_INFORMATION.BytesNeeded = 0;
+
+ break;
+
+ }
+
+ WD_MOVE_MEM(&LookAhead, InfoBuffer, 4);
+
+ if (LookAhead <= (WD_MAX_LOOKAHEAD)) {
+
+ if (LookAhead > Adapter->MaxLookAhead) {
+
+ Adapter->MaxLookAhead = LookAhead;
+
+ Open->LookAhead = LookAhead;
+
+ } else {
+
+ if ((Open->LookAhead == Adapter->MaxLookAhead) &&
+ (LookAhead < Open->LookAhead)) {
+
+ Open->LookAhead = LookAhead;
+
+ WdAdjustMaxLookAhead(Adapter);
+
+ } else {
+
+ Open->LookAhead = LookAhead;
+
+ }
+
+ }
+
+
+ } else {
+
+ StatusToReturn = NDIS_STATUS_INVALID_LENGTH;
+
+ }
+
+ break;
+
+ case OID_GEN_PROTOCOL_OPTIONS:
+
+ //
+ // Verify length
+ //
+
+ if (OidLength != 4) {
+
+ StatusToReturn = NDIS_STATUS_INVALID_LENGTH;
+
+ NdisRequest->DATA.SET_INFORMATION.BytesRead = 0;
+ NdisRequest->DATA.SET_INFORMATION.BytesNeeded = 0;
+
+ break;
+
+ }
+
+ WD_MOVE_MEM(&Open->ProtOptionFlags, InfoBuffer, 4);
+ StatusToReturn = NDIS_STATUS_SUCCESS;
+
+ break;
+
+ default:
+
+ StatusToReturn = NDIS_STATUS_NOT_SUPPORTED;
+
+ NdisRequest->DATA.SET_INFORMATION.BytesRead = 0;
+ NdisRequest->DATA.SET_INFORMATION.BytesNeeded = 0;
+
+ break;
+
+ }
+
+
+ if (StatusToReturn == NDIS_STATUS_SUCCESS) {
+
+ NdisRequest->DATA.SET_INFORMATION.BytesRead = BytesLeft;
+ NdisRequest->DATA.SET_INFORMATION.BytesNeeded = 0;
+
+ }
+
+
+ IF_LOUD( DbgPrint("Out SetInfo\n");)
+
+ return(StatusToReturn);
+}
+
+
+STATIC
+NDIS_STATUS
+WdSetPacketFilter(
+ IN PWD_ADAPTER Adapter,
+ IN PWD_OPEN Open,
+ IN PNDIS_REQUEST NdisRequest,
+ IN UINT PacketFilter
+ )
+
+/*++
+
+Routine Description:
+
+ The WdSetPacketFilter request allows a protocol to control the types
+ of packets that it receives from the MAC.
+
+Arguments:
+
+ Adapter - A pointer to the adapter structure.
+
+ Open - A pointer to the open block giving the request.
+
+ NdisRequest - The NDIS_REQUEST with the set packet filter command in it.
+
+ PacketFilter - A bit mask that contains flags that correspond to specific
+ classes of received packets. If a particular bit is set in the mask,
+ then packet reception for that class of packet is enabled. If the
+ bit is clear, then packets that fall into that class are not received
+ by the client. A single exception to this rule is that if the promiscuous
+ bit is set, then the client receives all packets on the network, regardless
+ of the state of the other flags.
+
+Return Value:
+
+ The function value is the status of the operation.
+
+--*/
+
+{
+ //
+ // Keeps track of the *MAC's* status. The status will only be
+ // reset if the filter change action routine is called.
+ //
+ NDIS_STATUS StatusOfFilterChange = NDIS_STATUS_SUCCESS;
+
+ NdisAcquireSpinLock(&Adapter->Lock);
+
+ IF_LOUD( DbgPrint("In SetFilter\n");)
+
+ if (!Open->Closing) {
+
+ //
+ // Increment the open while it is going through the filtering
+ // routines.
+ //
+
+ Open->ReferenceCount++;
+
+ StatusOfFilterChange = EthFilterAdjust(
+ Adapter->LMAdapter.FilterDB,
+ Open->NdisFilterHandle,
+ NdisRequest,
+ PacketFilter,
+ TRUE
+ );
+
+ Open->ReferenceCount--;
+
+ } else {
+
+ StatusOfFilterChange = NDIS_STATUS_CLOSING;
+
+ }
+
+ NdisReleaseSpinLock(&Adapter->Lock);
+
+ IF_LOUD( DbgPrint("Out SetFilter\n");)
+
+ return StatusOfFilterChange;
+}
+
+
+
+
+STATIC
+NDIS_STATUS
+WdSetMulticastAddresses(
+ IN PWD_ADAPTER Adapter,
+ IN PWD_OPEN Open,
+ IN PNDIS_REQUEST NdisRequest,
+ IN UINT NumAddresses,
+ IN CHAR AddressList[][ETH_LENGTH_OF_ADDRESS]
+ )
+
+/*++
+
+Routine Description:
+
+ This function calls into the filter package in order to set the
+ multicast address list for the card to the specified list.
+
+Arguments:
+
+ Adapter - A pointer to the adapter block.
+
+ Open - A pointer to the open block submitting the request.
+
+ NdisRequest - The NDIS_REQUEST with the set multicast address list command
+ in it.
+
+ NumAddresses - A count of the number of addresses in the addressList.
+
+ AddressList - An array of multicast addresses that this open instance
+ wishes to accept.
+
+
+Return Value:
+
+ The function value is the status of the operation.
+
+--*/
+
+{
+
+ //
+ // Keeps track of the *MAC's* status. The status will only be
+ // reset if the filter change action routine is called.
+ //
+ NDIS_STATUS StatusOfFilterChange = NDIS_STATUS_SUCCESS;
+
+ IF_LOUD( DbgPrint("In SetMulticast\n");)
+
+ NdisAcquireSpinLock(&Adapter->Lock);
+
+ if (!Open->Closing) {
+
+ //
+ // Increment the open while it is going through the filtering
+ // routines.
+ //
+
+ Open->ReferenceCount++;
+
+ StatusOfFilterChange = EthChangeFilterAddresses(
+ Adapter->LMAdapter.FilterDB,
+ Open->NdisFilterHandle,
+ NdisRequest,
+ NumAddresses,
+ AddressList,
+ TRUE
+ );
+ Open->ReferenceCount--;
+
+ } else {
+
+ StatusOfFilterChange = NDIS_STATUS_CLOSING;
+
+ }
+
+ NdisReleaseSpinLock(&Adapter->Lock);
+
+ IF_LOUD( DbgPrint("Out SetMulticast\n");)
+
+ return StatusOfFilterChange;
+}
+
+
+
+NDIS_STATUS
+WdFillInGlobalData(
+ IN PWD_ADAPTER Adapter,
+ IN PNDIS_REQUEST NdisRequest
+ )
+
+/*++
+
+Routine Description:
+
+ This routine completes a GlobalStatistics request. It is critical that
+ if information is needed from the Adapter->* fields, they have been
+ updated before this routine is called.
+
+Arguments:
+
+ Adapter - A pointer to the Adapter.
+
+ NdisRequest - A structure which contains the request type (Global
+ Query), an array of operations to perform, and an array for holding
+ the results of the operations.
+
+Return Value:
+
+ The function value is the status of the operation.
+
+--*/
+{
+ //
+ // General Algorithm:
+ //
+ // Switch(Request)
+ // Get requested information
+ // Store results in a common variable.
+ // default:
+ // Try protocol query information
+ // If that fails, fail query.
+ //
+ // Copy result in common variable to result buffer.
+ // Finish processing
+
+ UINT BytesWritten = 0;
+ UINT BytesNeeded = 0;
+ UINT BytesLeft = NdisRequest->DATA.QUERY_INFORMATION.InformationBufferLength;
+ PUCHAR InfoBuffer = (PUCHAR)(NdisRequest->DATA.QUERY_INFORMATION.InformationBuffer);
+
+ NDIS_STATUS StatusToReturn = NDIS_STATUS_SUCCESS;
+
+ //
+ // This variable holds result of query
+ //
+
+ ULONG GenericULong;
+
+ //
+ // Make sure that long is 4 bytes. Else GenericULong must change
+ // to something of size 4.
+ //
+ ASSERT(sizeof(ULONG) == 4);
+
+
+ StatusToReturn = WdQueryProtocolInformation(
+ Adapter,
+ NULL,
+ NdisRequest->DATA.QUERY_INFORMATION.Oid,
+ TRUE,
+ InfoBuffer,
+ BytesLeft,
+ &BytesNeeded,
+ &BytesWritten
+ );
+
+
+ if (StatusToReturn == NDIS_STATUS_NOT_SUPPORTED) {
+
+ StatusToReturn = NDIS_STATUS_SUCCESS;
+
+ //
+ // Switch on request type
+ //
+
+ switch (NdisRequest->DATA.QUERY_INFORMATION.Oid) {
+
+ case OID_GEN_XMIT_OK:
+
+ GenericULong = (ULONG)(Adapter->FramesXmitGood);
+
+ break;
+
+ case OID_GEN_RCV_OK:
+
+ GenericULong = (ULONG)(Adapter->FramesRcvGood);
+
+ break;
+
+ case OID_GEN_XMIT_ERROR:
+
+ GenericULong = (ULONG)(Adapter->FramesXmitBad);
+
+ break;
+
+ case OID_GEN_RCV_ERROR:
+
+ GenericULong = (ULONG)(Adapter->CrcErrors);
+
+ break;
+
+ case OID_GEN_RCV_NO_BUFFER:
+
+ GenericULong = (ULONG)(Adapter->MissedPackets);
+
+ break;
+
+ case OID_802_3_RCV_ERROR_ALIGNMENT:
+
+ GenericULong = (ULONG)(Adapter->FrameAlignmentErrors);
+
+ break;
+
+ case OID_802_3_XMIT_ONE_COLLISION:
+
+ GenericULong = (ULONG)(Adapter->FramesXmitOneCollision);
+
+ break;
+
+ case OID_802_3_XMIT_MORE_COLLISIONS:
+
+ GenericULong = (ULONG)(Adapter->FramesXmitManyCollisions);
+
+ break;
+
+
+ default:
+
+ StatusToReturn = NDIS_STATUS_NOT_SUPPORTED;
+
+ break;
+
+ }
+
+
+ //
+ // Check to make sure there is enough room in the
+ // buffer to store the result.
+ //
+
+ if (BytesLeft >= sizeof(ULONG)) {
+
+ //
+ // Store the result.
+ //
+
+ WD_MOVE_MEM(
+ (PVOID)InfoBuffer,
+ (PVOID)(&GenericULong),
+ sizeof(ULONG)
+ );
+
+ BytesWritten += sizeof(ULONG);
+
+ }
+
+ }
+
+ NdisRequest->DATA.QUERY_INFORMATION.BytesWritten = BytesWritten;
+
+ NdisRequest->DATA.QUERY_INFORMATION.BytesNeeded = BytesNeeded;
+
+ return(StatusToReturn);
+}
+
+NDIS_STATUS
+WdQueryGlobalStatistics(
+ IN NDIS_HANDLE MacAdapterContext,
+ IN PNDIS_REQUEST NdisRequest
+ )
+
+/*++
+
+Routine Description:
+
+ The WdQueryGlobalStatistics is used by the protocol to query
+ global information about the MAC.
+
+Arguments:
+
+ MacAdapterContext - The value associated with the adapter that is being
+ opened when the MAC registered the adapter with NdisRegisterAdapter.
+
+ NdisRequest - A structure which contains the request type (Query),
+ an array of operations to perform, and an array for holding
+ the results of the operations.
+
+Return Value:
+
+ The function value is the status of the operation.
+
+--*/
+
+{
+
+ //
+ // General Algorithm:
+ //
+ //
+ // Check if a request is going to pend...
+ // If so, pend the entire operation.
+ //
+ // Else
+ // Fill in the request block.
+ //
+ //
+
+ PWD_ADAPTER Adapter = (PWD_ADAPTER)(MacAdapterContext);
+
+ NDIS_STATUS StatusToReturn = NDIS_STATUS_SUCCESS;
+
+ //
+ // Check if a request is valid and going to pend...
+ // If so, pend the entire operation.
+ //
+
+
+ //
+ // Switch on request type
+ //
+
+ switch (NdisRequest->DATA.QUERY_INFORMATION.Oid) {
+ case OID_GEN_SUPPORTED_LIST:
+ case OID_GEN_HARDWARE_STATUS:
+ case OID_GEN_MEDIA_SUPPORTED:
+ case OID_GEN_MEDIA_IN_USE:
+ case OID_GEN_MAXIMUM_LOOKAHEAD:
+ case OID_GEN_MAXIMUM_FRAME_SIZE:
+ case OID_GEN_MAXIMUM_TOTAL_SIZE:
+ case OID_GEN_MAC_OPTIONS:
+ case OID_GEN_LINK_SPEED:
+ case OID_GEN_TRANSMIT_BUFFER_SPACE:
+ case OID_GEN_RECEIVE_BUFFER_SPACE:
+ case OID_GEN_TRANSMIT_BLOCK_SIZE:
+ case OID_GEN_RECEIVE_BLOCK_SIZE:
+ case OID_GEN_VENDOR_ID:
+ case OID_GEN_VENDOR_DESCRIPTION:
+ case OID_GEN_DRIVER_VERSION:
+ case OID_GEN_CURRENT_PACKET_FILTER:
+ case OID_GEN_CURRENT_LOOKAHEAD:
+ case OID_GEN_XMIT_OK:
+ case OID_GEN_RCV_OK:
+ case OID_GEN_XMIT_ERROR:
+ case OID_GEN_RCV_ERROR:
+
+ break;
+
+ case OID_802_3_PERMANENT_ADDRESS:
+ case OID_802_3_CURRENT_ADDRESS:
+ case OID_GEN_RCV_NO_BUFFER:
+ case OID_802_3_MULTICAST_LIST:
+ case OID_802_3_MAXIMUM_LIST_SIZE:
+ case OID_802_3_RCV_ERROR_ALIGNMENT:
+ case OID_802_3_XMIT_ONE_COLLISION:
+ case OID_802_3_XMIT_MORE_COLLISIONS:
+
+ break;
+
+ default:
+
+ StatusToReturn = NDIS_STATUS_NOT_SUPPORTED;
+
+ break;
+ }
+
+ NdisInterlockedAddUlong(&Adapter->References, 1, &Adapter->Lock);
+
+ if (StatusToReturn == NDIS_STATUS_SUCCESS) {
+
+ StatusToReturn = WdFillInGlobalData(Adapter, NdisRequest);
+
+ }
+
+ NdisAcquireSpinLock(&Adapter->Lock);
+
+ WD_DO_DEFERRED(Adapter);
+
+ return(StatusToReturn);
+}
+
+
+VOID
+WdRemoveAdapter(
+ IN PVOID MacAdapterContext
+ )
+/*++
+
+Routine Description:
+
+ WdRemoveAdapter removes an adapter previously registered
+ with NdisRegisterAdapter.
+
+Arguments:
+
+ MacAdapterContext - The context value that the MAC passed
+ to NdisRegisterAdapter; actually as pointer to an
+ WD_ADAPTER.
+
+Return Value:
+
+ None.
+
+--*/
+{
+
+ PWD_ADAPTER Adapter;
+ BOOLEAN Canceled;
+
+ Adapter = PWD_ADAPTER_FROM_CONTEXT_HANDLE(MacAdapterContext);
+
+ LM_Free_Resources(&Adapter->LMAdapter);
+
+ ASSERT(Adapter->OpenQueue == (PWD_OPEN)NULL);
+
+ //
+ // There are no opens left, so remove ourselves.
+ //
+
+ NdisCancelTimer(&Adapter->WakeUpTimer, &Canceled);
+
+ if ( !Canceled ) {
+ NdisStallExecution(500000);
+ }
+
+ //
+ // Take us out of the AdapterQueue.
+ //
+
+ NdisAcquireSpinLock(&WdMacBlock.SpinLock);
+
+ Adapter->Removed = TRUE;
+
+ if (WdMacBlock.AdapterQueue == Adapter) {
+
+ WdMacBlock.AdapterQueue = Adapter->NextAdapter;
+
+ } else {
+
+ PWD_ADAPTER TmpAdaptP = WdMacBlock.AdapterQueue;
+
+ while (TmpAdaptP->NextAdapter != Adapter) {
+
+ TmpAdaptP = TmpAdaptP->NextAdapter;
+
+ }
+
+ TmpAdaptP->NextAdapter = TmpAdaptP->NextAdapter->NextAdapter;
+ }
+
+ NdisReleaseSpinLock(&WdMacBlock.SpinLock);
+
+ NdisRemoveInterrupt(&(Adapter->LMAdapter.NdisInterrupt));
+
+ NdisUnmapIoSpace(
+ Adapter->LMAdapter.NdisAdapterHandle,
+ Adapter->LMAdapter.ram_access,
+ Adapter->LMAdapter.ram_size * 1024);
+
+ EthDeleteFilter(Adapter->LMAdapter.FilterDB);
+
+ NdisDeregisterAdapter(Adapter->LMAdapter.NdisAdapterHandle);
+
+ NdisFreeSpinLock(&Adapter->Lock);
+
+ NdisFreeMemory(Adapter, sizeof(WD_ADAPTER), 0);
+
+ return;
+}
+
+VOID
+WdUnload(
+ IN NDIS_HANDLE MacMacContext
+ )
+
+/*++
+
+Routine Description:
+
+ WdUnload is called when the MAC is to unload itself.
+
+Arguments:
+
+ MacMacContext - actually a pointer to WdMacBlock.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ NDIS_STATUS InitStatus;
+
+ UNREFERENCED_PARAMETER(MacMacContext);
+
+ NdisDeregisterMac(
+ &InitStatus,
+ WdMacBlock.NdisMacHandle
+ );
+
+ NdisFreeSpinLock(&WdMacBlock.SpinLock);
+
+ NdisTerminateWrapper(
+ WdMacBlock.NdisWrapperHandle,
+ NULL
+ );
+
+ return;
+}
+
+NDIS_STATUS
+WdSend(
+ IN NDIS_HANDLE MacBindingHandle,
+ IN PNDIS_PACKET Packet
+ )
+/*++
+
+Routine Description:
+
+ NDIS function. Sends a packet on the wire
+
+Arguments:
+
+ See NDIS 3.0 spec.
+
+--*/
+
+{
+ PWD_OPEN Open = PWD_OPEN_FROM_BINDING_HANDLE(MacBindingHandle);
+ PWD_ADAPTER Adapter = Open->Adapter;
+ PMAC_RESERVED Reserved = RESERVED(Packet);
+ UINT PacketLength;
+ NDIS_STATUS Status;
+
+
+ //
+ // Check that the packet is not too short or too long.
+ //
+
+ NdisQueryPacket(Packet, NULL, NULL, NULL, &PacketLength);
+
+ if (PacketLength < (ETH_LENGTH_OF_ADDRESS*2) || PacketLength > 1514) {
+
+ return NDIS_STATUS_FAILURE;
+
+ }
+
+
+
+
+ if (Adapter->HardwareFailure) {
+
+ return(NDIS_STATUS_FAILURE);
+
+ }
+
+ if (Adapter->ResetInProgress) {
+
+ return(NDIS_STATUS_RESET_IN_PROGRESS);
+
+ }
+
+ //
+ // Ensure that the open won't close during this function.
+ //
+
+ if (Open->Closing) {
+
+ return NDIS_STATUS_CLOSING;
+
+ }
+
+ NdisAcquireSpinLock(&Adapter->Lock);
+
+ IF_LOG(LOG('s'));
+
+ Open->ReferenceCount++;
+
+ Adapter->References++;
+
+ //
+ // Set up the MacReserved section of the packet.
+ //
+
+ Reserved->Open = Open;
+
+ Reserved->NextPacket = (PNDIS_PACKET)NULL;
+
+
+
+
+ //
+ // Set Reserved->Loopback
+ //
+
+ WdSetLoopbackFlag(Adapter, Open, Packet);
+
+
+
+
+ IF_LOUD( DbgPrint("Sending a packet for Open 0x%lx\n", Reserved->Open);)
+
+
+ //
+ // We do not Open->ReferenceCount-- because that will be done when
+ // then send completes.
+ //
+
+
+ if (Reserved->Directed) {
+
+ //
+ // Put it directly on loopback queue.
+ //
+
+ IF_VERY_LOUD( DbgPrint("Putting Packet 0x%lx on Loopback queue\n",Packet);)
+
+ IF_LOG(LOG('l'));
+
+ if (Adapter->LoopbackQueue == NULL) {
+
+ Adapter->LoopbackQueue = Adapter->LoopbackQTail = Packet;
+
+ } else {
+
+ RESERVED(Adapter->LoopbackQTail)->NextPacket = Packet;
+
+ Adapter->LoopbackQTail = Packet;
+
+ }
+
+ Status = NDIS_STATUS_PENDING;
+
+ } else {
+
+ //
+ // Put Packet on queue to hit the wire.
+ //
+
+ if (Adapter->XmitQueue != NULL) {
+
+ IF_LOG(LOG('q'));
+
+ RESERVED(Adapter->XmitQTail)->NextPacket = Packet;
+
+ Adapter->XmitQTail = Packet;
+
+ Adapter->WakeUpTimeout = FALSE;
+
+ } else {
+
+ PNDIS_PACKET PreviousTail;
+
+ //
+ // We have to assume it will be sent. In case the send completes
+ // before we have time to add it.
+ //
+
+ ASSERT(Packet != NULL);
+
+ if (Adapter->PacketsOnCard == NULL) {
+
+ PreviousTail = NULL;
+
+ Adapter->PacketsOnCard = Adapter->PacketsOnCardTail = Packet;
+
+ } else {
+
+ PreviousTail = Adapter->PacketsOnCardTail;
+
+ RESERVED(Adapter->PacketsOnCardTail)->NextPacket = Packet;
+
+ Adapter->PacketsOnCardTail = Packet;
+
+ }
+
+ Adapter->WakeUpTimeout = FALSE;
+
+ IF_LOG(LOG('t'));
+
+ if (LM_Send(Packet, &Adapter->LMAdapter) == OUT_OF_RESOURCES) {
+
+ IF_LOG(LOG('Q'));
+
+ ASSERT(Packet != NULL);
+
+ //
+ // Remove it from list of packets on card and add it to xmit
+ // queue.
+ //
+
+ if (PreviousTail == NULL) {
+
+ Adapter->PacketsOnCard = Adapter->PacketsOnCardTail = NULL;
+
+ } else {
+
+ Adapter->PacketsOnCardTail = PreviousTail;
+
+ RESERVED(Adapter->PacketsOnCardTail)->NextPacket = NULL;
+
+ ASSERT(Adapter->PacketsOnCard != NULL);
+
+ }
+
+ Adapter->XmitQueue = Packet;
+
+ Adapter->XmitQTail = Packet;
+
+ Adapter->WakeUpTimeout = FALSE;
+
+ }
+
+ }
+
+ Status = NDIS_STATUS_PENDING;
+
+ }
+
+
+ WD_DO_DEFERRED(Adapter);
+
+ IF_LOG(LOG('S'));
+
+ return Status;
+
+}
+
+UINT
+WdCompareMemory(
+ IN PUCHAR String1,
+ IN PUCHAR String2,
+ IN UINT Length
+ )
+/*++
+
+Routine Description:
+
+ Determines if two arrays of bytes are equal.
+
+Arguments:
+
+ String1, String2 - the two arrays to check.
+
+ Length - the first length bytes to compare.
+
+Return Value:
+
+ 0 if equal, -1 if not.
+
+--*/
+{
+ UINT i;
+
+ for (i=0; i<Length; i++) {
+ if (String1[i] != String2[i]) {
+ return (UINT)(-1);
+ }
+ }
+ return 0;
+}
+
+VOID
+WdSetLoopbackFlag(
+ IN PWD_ADAPTER Adapter,
+ IN PWD_OPEN Open,
+ IN PNDIS_PACKET Packet
+ )
+
+/*++
+
+Routine Description:
+
+ Sets the loopback flag in the reserved section of the packet
+ to indicate if it should be looped back.
+
+Arguments:
+
+ Packet - the packet to check.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ PMAC_RESERVED Reserved = RESERVED(Packet);
+ UCHAR AddrBuf[ETH_LENGTH_OF_ADDRESS];
+ UINT Filter;
+
+
+ Reserved->Directed = FALSE;
+ Reserved->Loopback = FALSE;
+
+ //
+ // Check the destination address to see which filter to use.
+ //
+
+ WdCopyOver(AddrBuf, Packet, 0, ETH_LENGTH_OF_ADDRESS);
+
+ Filter = ETH_QUERY_FILTER_CLASSES(Adapter->LMAdapter.FilterDB);
+
+ if (WdAddressEqual(Adapter->LMAdapter.node_address, AddrBuf)) {
+
+ //
+ // Packet directed to this adapter.
+ //
+
+ Reserved->Directed = (BOOLEAN)(Filter & NDIS_PACKET_TYPE_DIRECTED);
+
+ }
+
+ if (Open->ProtOptionFlags & NDIS_PROT_OPTION_NO_LOOPBACK) {
+
+ Reserved->Loopback = FALSE;
+
+ } else if (Filter & NDIS_PACKET_TYPE_PROMISCUOUS) {
+
+ //
+ // Somebody is promiscuous, everything is looped back.
+ //
+
+ Reserved->Loopback = TRUE;
+
+ } else {
+
+ if (WdAddressEqual(WdBroadcastAddress, AddrBuf)) {
+
+ //
+ // Broadcast packet.
+ //
+
+ Reserved->Loopback = (BOOLEAN)(Filter & NDIS_PACKET_TYPE_BROADCAST);
+
+ } else if ((AddrBuf[0] & 1) != 0) {
+
+ //
+ // Multicast packet.
+ //
+
+ Reserved->Loopback = (BOOLEAN)(Filter &
+ (NDIS_PACKET_TYPE_MULTICAST |
+ NDIS_PACKET_TYPE_ALL_MULTICAST));
+
+ } else if (Reserved->Directed) {
+
+ Reserved->Loopback = TRUE;
+
+ } else {
+
+ //
+ // Packet directed to another adapter.
+ //
+
+ Reserved->Loopback = FALSE;
+ }
+
+ }
+
+}
+
+
+NDIS_STATUS
+WdReset(
+ IN NDIS_HANDLE MacBindingHandle
+ )
+
+/*++
+
+Routine Description:
+
+ NDIS function.
+
+Arguments:
+
+ See NDIS 3.0 spec.
+
+--*/
+
+{
+ PWD_OPEN Open = ((PWD_OPEN)MacBindingHandle);
+ PWD_ADAPTER Adapter = Open->Adapter;
+
+
+ if (Open->Closing) {
+
+ return(NDIS_STATUS_CLOSING);
+
+ }
+
+ if (Adapter->ResetRequested) {
+
+ return(NDIS_STATUS_SUCCESS);
+
+ }
+
+ NdisAcquireSpinLock(&Adapter->Lock);
+
+ IF_LOUD( DbgPrint("In WdReset\n");)
+
+ IF_LOG(LOG('r'));
+
+ //
+ // Ensure that the open does not close while in this function.
+ //
+
+ Open->ReferenceCount++;
+
+ Adapter->References++;
+
+
+ Adapter->ResetRequested = TRUE;
+
+ //
+ // Needed in case the reset pends somewhere along the line.
+ //
+
+ Adapter->ResetOpen = Open;
+
+ WD_DO_DEFERRED(Adapter);
+
+ IF_LOUD( DbgPrint("Out WdReset\n");)
+
+ return(NDIS_STATUS_PENDING);
+
+}
+
+STATIC
+NDIS_STATUS
+WdChangeMulticastAddresses(
+ IN UINT OldFilterCount,
+ IN CHAR OldAddresses[][ETH_LENGTH_OF_ADDRESS],
+ IN UINT NewFilterCount,
+ IN CHAR NewAddresses[][ETH_LENGTH_OF_ADDRESS],
+ IN NDIS_HANDLE MacBindingHandle,
+ IN PNDIS_REQUEST NdisRequest,
+ IN BOOLEAN Set
+ )
+
+/*++
+
+Routine Description:
+
+ Action routine that will get called when a particular filter
+ class is first used or last cleared.
+
+ NOTE: This routine assumes that it is called with the lock
+ acquired.
+
+Arguments:
+
+
+ OldFilterCount - The number of addresses that used to be on the card.
+
+ OldAddresses - A list of all the addresses that used to be on the card.
+
+ NewFilterCount - The number of addresses that should now be on the card.
+
+ NewAddresses - A list of addresses that should be put on the card.
+
+ MacBindingHandle - The context value returned by the MAC when the
+ adapter was opened. In reality, it is a pointer to WD_OPEN.
+
+ NdisRequest - The request which submitted the filter change.
+ Must use when completing this request with the NdisCompleteRequest
+ service, if the MAC completes this request asynchronously.
+
+ Set - If true the change resulted from a set, otherwise the
+ change resulted from a open closing.
+
+Return Value:
+
+ None.
+
+
+--*/
+
+{
+
+
+ PWD_ADAPTER Adapter = PWD_ADAPTER_FROM_BINDING_HANDLE(MacBindingHandle);
+
+ UNREFERENCED_PARAMETER(Set);
+ UNREFERENCED_PARAMETER(NdisRequest);
+ UNREFERENCED_PARAMETER(OldAddresses);
+ UNREFERENCED_PARAMETER(OldFilterCount);
+
+ if (LM_Set_Multi_Address(NewAddresses, NewFilterCount, &Adapter->LMAdapter)
+ != SUCCESS) {
+
+ return(NDIS_STATUS_FAILURE);
+
+ } else {
+
+ return(NDIS_STATUS_SUCCESS);
+
+ }
+
+}
+
+STATIC
+NDIS_STATUS
+WdChangeFilterClasses(
+ IN UINT OldFilterClasses,
+ IN UINT NewFilterClasses,
+ IN NDIS_HANDLE MacBindingHandle,
+ IN PNDIS_REQUEST NdisRequest,
+ IN BOOLEAN Set
+ )
+
+/*++
+
+Routine Description:
+
+ Action routine that will get called when an address is added to
+ the filter that wasn't referenced by any other open binding.
+
+ NOTE: This routine assumes that it is called with the lock
+ acquired.
+
+Arguments:
+
+ OldFilterClasses - A bit mask that is currently on the card telling
+ which packet types to accept.
+
+ NewFilterClasses - A bit mask that should be put on the card telling
+ which packet types to accept.
+
+ MacBindingHandle - The context value returned by the MAC when the
+ adapter was opened. In reality, it is a pointer to WD_OPEN.
+
+ NdisRequest - The NDIS_REQUEST which submitted the filter change command.
+
+ Set - A flag telling if the command is a result of a close or not.
+
+Return Value:
+
+ Status of the change (successful or pending).
+
+
+--*/
+
+{
+
+ PWD_ADAPTER Adapter = PWD_ADAPTER_FROM_BINDING_HANDLE(MacBindingHandle);
+
+ UNREFERENCED_PARAMETER(Set);
+ UNREFERENCED_PARAMETER(OldFilterClasses);
+ UNREFERENCED_PARAMETER(NewFilterClasses);
+ UNREFERENCED_PARAMETER(NdisRequest);
+
+
+ if (LM_Set_Receive_Mask(&(Adapter->LMAdapter)) != SUCCESS) {
+
+ return(NDIS_STATUS_FAILURE);
+
+ } else {
+
+ return(NDIS_STATUS_SUCCESS);
+
+ }
+
+}
+
+STATIC
+VOID
+WdCloseAction(
+ IN NDIS_HANDLE MacBindingHandle
+ )
+
+/*++
+
+Routine Description:
+
+ Action routine that will get called when a particular binding
+ was closed while it was indicating through NdisIndicateReceive
+
+ All this routine needs to do is to decrement the reference count
+ of the binding.
+
+ NOTE: This routine assumes that it is called with the lock acquired.
+
+Arguments:
+
+ MacBindingHandle - The context value returned by the MAC when the
+ adapter was opened. In reality, it is a pointer to WD_OPEN.
+
+Return Value:
+
+ None.
+
+
+--*/
+
+{
+
+ PWD_OPEN_FROM_BINDING_HANDLE(MacBindingHandle)->ReferenceCount--;
+
+}
+
+BOOLEAN
+WdInterruptHandler(
+ IN PVOID ServiceContext
+ )
+
+/*++
+
+Routine Description:
+
+ This is the interrupt handler which is registered with the operating
+ system. Only one interrupt is handled at one time, even if several
+ are pending (i.e. transmit complete and receive).
+
+Arguments:
+
+ ServiceContext - pointer to the adapter object
+
+Return Value:
+
+ TRUE, if the DPC is to be executed, otherwise FALSE.
+
+--*/
+
+{
+ PWD_ADAPTER Adapter = ((PWD_ADAPTER)ServiceContext);
+
+ IF_LOUD( DbgPrint("In WdISR\n");)
+
+ IF_LOG(LOG('i'));
+
+ //
+ // Force the INT signal from the chip low. When the
+ // interrupt is acknowledged interrupts will be unblocked,
+ // which will cause a rising edge on the interrupt line
+ // if there is another interrupt pending on the card.
+ //
+
+ IF_LOUD( DbgPrint( " blocking interrupts\n" );)
+
+ LM_Disable_Adapter(&Adapter->LMAdapter);
+
+ IF_LOG(LOG('I'));
+
+ return(TRUE);
+
+}
+
+VOID
+WdInterruptDpc(
+ IN PVOID SystemSpecific1,
+ IN PVOID InterruptContext,
+ IN PVOID SystemSpecific2,
+ IN PVOID SystemSpecific3
+ )
+/*++
+
+Routine Description:
+
+ This is the deffered processing routine for interrupts, it examines the
+ global 'InterruptReg' to determine what deffered processing is necessary
+ and dispatches control to the Rcv and Xmt handlers.
+
+Arguments:
+ SystemSpecific1, SystemSpecific2, SystemSpecific3 - not used
+ InterruptContext - a handle to the adapter block.
+
+Return Value:
+
+ NONE.
+
+--*/
+{
+ PWD_ADAPTER Adapter = ((PWD_ADAPTER)InterruptContext);
+ BOOLEAN RequeueRcv = FALSE;
+
+ UNREFERENCED_PARAMETER(SystemSpecific1);
+ UNREFERENCED_PARAMETER(SystemSpecific2);
+ UNREFERENCED_PARAMETER(SystemSpecific3);
+
+ IF_LOG(LOG('d'));
+
+
+ IF_LOUD( DbgPrint("==>IntDpc\n");)
+
+ NdisDprAcquireSpinLock(&Adapter->Lock);
+
+ if ( Adapter->ProcessingDpc ) {
+
+ NdisDprReleaseSpinLock(&Adapter->Lock);
+
+ return;
+ }
+
+ Adapter->ProcessingDpc = TRUE;
+ Adapter->References++;
+
+ do {
+
+ Adapter->WakeUpTimeout = FALSE;
+
+ RequeueRcv = WdReceiveEvents(Adapter);
+
+ WdTransmitEvents(Adapter);
+
+ //
+ // This causes any transmit that may have caused a tranmitted packet
+ // to loopback and indicate the packet.
+ //
+
+ } while ( Adapter->LoopbackQueue != (PNDIS_PACKET) NULL || RequeueRcv );
+
+ //
+ // We're done with this DPC.
+ //
+
+ Adapter->ProcessingDpc = FALSE;
+
+ //
+ // Reenable interrupts
+ //
+
+ Adapter->LMAdapter.InterruptMask = PACKET_RECEIVE_ENABLE |
+ PACKET_TRANSMIT_ENABLE |
+ RECEIVE_ERROR_ENABLE |
+ TRANSMIT_ERROR_ENABLE |
+ OVERWRITE_WARNING_ENABLE |
+ COUNTER_OVERFLOW_ENABLE;
+
+ NdisSynchronizeWithInterrupt(
+ &(Adapter->LMAdapter.NdisInterrupt),
+ LM_Enable_Adapter,
+ &Adapter->LMAdapter
+ );
+
+ WD_DO_DEFERRED(Adapter);
+
+ IF_LOUD( DbgPrint("<==IntDpc\n");)
+
+ IF_LOG(LOG('D'));
+
+}
+
+
+VOID
+WdIndicateLoopbackPacket(
+ IN PWD_ADAPTER Adapter,
+ IN PNDIS_PACKET Packet
+ )
+/*++
+
+Routine Description:
+
+ This routine indicates a packet to the current host.
+
+ NOTE: THIS ROUTINE MUST BE CALLED WITH THE SPINLOCK HELD.
+
+Arguments:
+
+ Adapter - Pointer to the adapter structure.
+
+ Packet - Pointer to the packet to indicate.
+
+Return Value:
+
+ NONE.
+
+--*/
+{
+ UINT IndicateLen;
+ UINT PacketLen;
+
+ //
+ // Store that we are indicating a loopback packet
+ //
+
+ Adapter->IndicatingPacket = Packet;
+ Adapter->IndicatedAPacket = TRUE;
+
+ //
+ // Indicate packet.
+ //
+
+ IF_LOUD( DbgPrint("Indicating loopback packet\n");)
+
+ //
+ // Indicate up to 252 bytes.
+ //
+
+ NdisQueryPacket(Packet, NULL, NULL, NULL, &PacketLen);
+
+ if (PacketLen >= ETH_LENGTH_OF_ADDRESS) {
+
+ IndicateLen = (PacketLen > (Adapter->MaxLookAhead + WD_HEADER_SIZE) ?
+ (Adapter->MaxLookAhead + WD_HEADER_SIZE) :
+ PacketLen
+ );
+
+ //
+ // Copy the lookahead data into a contiguous buffer.
+ //
+
+ WdCopyOver(Adapter->LookAhead,
+ Packet,
+ 0,
+ IndicateLen
+ );
+
+ NdisDprReleaseSpinLock(&Adapter->Lock);
+
+
+ //
+ // Indicate packet
+ //
+
+ if (PacketLen < WD_HEADER_SIZE) {
+
+ //
+ // Runt packet
+ //
+
+ EthFilterIndicateReceive(
+ Adapter->LMAdapter.FilterDB,
+ (NDIS_HANDLE)Adapter,
+ (PCHAR)Adapter->LookAhead,
+ Adapter->LookAhead,
+ PacketLen,
+ NULL,
+ 0,
+ 0
+ );
+
+ } else {
+
+ EthFilterIndicateReceive(
+ Adapter->LMAdapter.FilterDB,
+ (NDIS_HANDLE)Adapter,
+ (PCHAR)Adapter->LookAhead,
+ Adapter->LookAhead,
+ WD_HEADER_SIZE,
+ Adapter->LookAhead + WD_HEADER_SIZE,
+ IndicateLen - WD_HEADER_SIZE,
+ PacketLen - WD_HEADER_SIZE
+ );
+
+ }
+
+ NdisDprAcquireSpinLock(&Adapter->Lock);
+
+ }
+
+}
+
+
+BOOLEAN
+WdReceiveEvents(
+ IN PWD_ADAPTER Adapter
+ )
+/*++
+
+Routine Description:
+
+ This routine handles all Receive deferred processing, this includes any
+ packets that never went through the XmitQueue and need to be indicated
+ (Loopbacked), and all card events.
+
+ NOTE: THIS ROUTINE MUST BE CALLED WITH THE SPINLOCK HELD.
+
+ NOTE: The Adapter->ProcessingReceiveEvents MUST be set upon entry and
+ with the spinlock held.
+
+Arguments:
+
+ Context - a handle to the adapter block.
+
+Return Value:
+
+ Do we need to requeue this Rcv.
+
+--*/
+{
+ PNDIS_PACKET Packet;
+ PWD_OPEN TmpOpen;
+ NDIS_STATUS Status;
+ BOOLEAN RequeueRcv;
+
+ IF_LOG(LOG('e'));
+
+ RequeueRcv = (BOOLEAN)(LM_Service_Receive_Events(&Adapter->LMAdapter) ==
+ REQUEUE_LATER);
+
+ while (Adapter->LoopbackQueue != NULL) {
+
+ //
+ // Take packet off queue.
+ //
+
+ Packet = Adapter->LoopbackQueue;
+
+ if (Packet == Adapter->LoopbackQTail) {
+
+ Adapter->LoopbackQTail = NULL;
+
+ }
+
+ Adapter->LoopbackQueue = RESERVED(Packet)->NextPacket;
+
+ //
+ // Indicate the packet
+ //
+
+ WdIndicateLoopbackPacket(Adapter,Packet);
+
+
+ //
+ // Complete the packet send.
+ //
+
+ Adapter->FramesXmitGood++;
+
+ //
+ // Save this, since once we complete the send
+ // Reserved is no longer valid.
+ //
+
+ TmpOpen = RESERVED(Packet)->Open;
+
+ IF_VERY_LOUD( DbgPrint("Completing send for packet 0x%x\n",Packet);)
+
+ NdisDprReleaseSpinLock(&Adapter->Lock);
+
+ NdisCompleteSend(TmpOpen->NdisBindingContext,
+ Packet,
+ NDIS_STATUS_SUCCESS
+ );
+
+ NdisDprAcquireSpinLock(&Adapter->Lock);
+
+ WdRemoveReference(TmpOpen);
+
+ }
+
+ //
+ // If any indications done, then
+ //
+ // CompleteIndications();
+ //
+
+ if (Adapter->IndicatedAPacket) {
+
+ Adapter->IndicatedAPacket = FALSE;
+
+ NdisDprReleaseSpinLock(&Adapter->Lock);
+
+ EthFilterIndicateReceiveComplete(Adapter->LMAdapter.FilterDB);
+
+ NdisDprAcquireSpinLock(&Adapter->Lock);
+
+ }
+
+ if ((Adapter->ResetRequested) && (Adapter->References == 1)) {
+
+ PNDIS_PACKET Packet;
+ PWD_OPEN TmpOpen;
+
+ IF_LOG(LOG('R'));
+ IF_VERY_LOUD( DbgPrint("Starting Reset\n");)
+
+ Adapter->ResetInProgress = TRUE;
+
+ NdisSynchronizeWithInterrupt(
+ &(Adapter->LMAdapter.NdisInterrupt),
+ LM_Disable_Adapter,
+ &Adapter->LMAdapter
+ );
+
+ //
+ // Indicate Status to all opens
+ //
+
+ IF_VERY_LOUD( DbgPrint("Indicating status\n");)
+
+ TmpOpen = Adapter->OpenQueue;
+
+ while (TmpOpen != (PWD_OPEN)NULL) {
+
+ AddRefWhileHoldingSpinLock(Adapter, TmpOpen);
+
+ NdisDprReleaseSpinLock(&Adapter->Lock);
+
+ NdisIndicateStatus(TmpOpen->NdisBindingContext,
+ NDIS_STATUS_RESET_START,
+ NULL,
+ 0
+ );
+
+
+ NdisDprAcquireSpinLock(&Adapter->Lock);
+
+ WdRemoveReference(TmpOpen);
+
+ TmpOpen = TmpOpen->NextOpen;
+
+ }
+
+ //
+ // Reset the Card.
+ //
+
+ IF_VERY_LOUD( DbgPrint("Resetting the card\n");)
+
+ if (LM_Initialize_Adapter(&Adapter->LMAdapter) != SUCCESS) {
+
+ Adapter->HardwareFailure = TRUE;
+
+ NdisWriteErrorLogEntry(
+ Adapter->LMAdapter.NdisAdapterHandle,
+ NDIS_ERROR_CODE_HARDWARE_FAILURE,
+ 0
+ );
+
+ } else {
+
+ Adapter->HardwareFailure = FALSE;
+
+ }
+
+
+
+ //
+ // Put packets that were on the card on to the front of the xmit
+ // queue.
+ //
+
+ if (Adapter->PacketsOnCard != NULL) {
+
+ IF_VERY_LOUD( DbgPrint("Moving Packets On card\n");)
+
+ RESERVED(Adapter->PacketsOnCardTail)->NextPacket = Adapter->XmitQueue;
+
+ Adapter->XmitQueue = Adapter->PacketsOnCard;
+
+ Adapter->PacketsOnCard = Adapter->PacketsOnCardTail = NULL;
+
+ }
+
+
+ //
+ // Put packets on loopback queue on xmit queue
+ //
+
+ if (Adapter->LoopbackQueue != NULL) {
+
+ RESERVED(Adapter->LoopbackQTail)->NextPacket = Adapter->XmitQueue;
+
+ Adapter->XmitQueue = Adapter->LoopbackQueue;
+
+ }
+
+
+ //
+ // Wipe out loopback queue.
+ //
+
+ Adapter->LoopbackQueue = Adapter->LoopbackQTail = (PNDIS_PACKET)NULL;
+
+
+ //
+ // Abort all xmits
+ //
+
+ IF_VERY_LOUD( DbgPrint("Killing Xmits\n");)
+
+ while (Adapter->XmitQueue != NULL) {
+
+ Packet = Adapter->XmitQueue;
+
+ Adapter->XmitQueue = RESERVED(Packet)->NextPacket;
+
+ TmpOpen = RESERVED(Packet)->Open;
+
+ NdisDprReleaseSpinLock(&Adapter->Lock);
+
+ NdisCompleteSend(TmpOpen->NdisBindingContext,
+ Packet,
+ NDIS_STATUS_REQUEST_ABORTED
+ );
+
+ NdisDprAcquireSpinLock(&Adapter->Lock);
+
+ WdRemoveReference(TmpOpen);
+
+ }
+
+ Adapter->XmitQTail = NULL;
+
+ if (!Adapter->HardwareFailure) {
+
+ LM_Open_Adapter(&Adapter->LMAdapter);
+
+ }
+
+ Adapter->ResetInProgress = FALSE;
+
+ IF_VERY_LOUD( DbgPrint("Indicating Done\n");)
+
+ //
+ // Indicate Reset is done
+ //
+
+ //
+ // Indicate Status to all opens
+ //
+
+ IF_VERY_LOUD( DbgPrint("Indicating status\n");)
+
+ TmpOpen = Adapter->OpenQueue;
+
+ while (TmpOpen != (PWD_OPEN)NULL) {
+
+ AddRefWhileHoldingSpinLock(Adapter, TmpOpen);
+
+ NdisDprReleaseSpinLock(&Adapter->Lock);
+
+ if (Adapter->HardwareFailure) {
+
+ NdisIndicateStatus(TmpOpen->NdisBindingContext,
+ NDIS_STATUS_CLOSED,
+ NULL,
+ 0
+ );
+
+ }
+
+ Status = (Adapter->HardwareFailure) ?
+ NDIS_STATUS_FAILURE :
+ NDIS_STATUS_SUCCESS;
+
+
+ NdisIndicateStatus(TmpOpen->NdisBindingContext,
+ NDIS_STATUS_RESET_END,
+ &Status,
+ sizeof(Status)
+ );
+
+ NdisIndicateStatusComplete(TmpOpen->NdisBindingContext);
+
+ NdisDprAcquireSpinLock(&Adapter->Lock);
+
+ WdRemoveReference(TmpOpen);
+
+ TmpOpen = TmpOpen->NextOpen;
+
+ }
+
+ NdisDprReleaseSpinLock(&Adapter->Lock);
+
+ NdisCompleteReset(Adapter->ResetOpen->NdisBindingContext,
+ (Adapter->HardwareFailure) ?
+ NDIS_STATUS_FAILURE :
+ NDIS_STATUS_SUCCESS
+ );
+
+ NdisDprAcquireSpinLock(&Adapter->Lock);
+
+ WdRemoveReference(Adapter->ResetOpen);
+
+ //
+ // Reset the flag
+ //
+
+
+ IF_VERY_LOUD( DbgPrint("Restarting Adapter\n");)
+
+ Adapter->ResetRequested = FALSE;
+
+ LM_Open_Adapter(&Adapter->LMAdapter);
+
+ }
+
+#if DBG
+
+ else if (Adapter->ResetRequested) {
+
+ IF_LOUD( DbgPrint("No reset because count is... 0x%x\n", Adapter->References);)
+
+ }
+
+#endif
+
+ IF_LOG(LOG('E'));
+
+ return RequeueRcv;
+}
+
+
+VOID
+WdTransmitEvents(
+ IN PWD_ADAPTER Adapter
+ )
+/*++
+
+Routine Description:
+
+ This routine handles all transmit deferred processing.
+
+ NOTE : Called with lock held!!
+
+Arguments:
+
+ Adapter - pointer to the adapter structure.
+
+Return Value:
+
+ NONE.
+
+--*/
+{
+
+ if (Adapter->ResetInProgress) {
+
+ return;
+
+ }
+
+ IF_LOG(LOG('w'));
+
+ LM_Service_Transmit_Events(&Adapter->LMAdapter);
+
+ IF_LOG(LOG('W'));
+
+}
+
+UINT
+WdCopyOver(
+ OUT PUCHAR Buf, // destination
+ IN PNDIS_PACKET Packet, // source packet
+ IN UINT Offset, // offset in packet
+ IN UINT Length // number of bytes to copy
+ )
+
+/*++
+
+Routine Description:
+
+ Copies bytes from a packet into a buffer. Used to copy data
+ out of a packet during loopback indications.
+
+Arguments:
+
+ Buf - the destination buffer
+ Packet - the source packet
+ Offset - the offset in the packet to start copying at
+ Length - the number of bytes to copy
+
+Return Value:
+
+ The actual number of bytes copied; will be less than Length if
+ the packet length is less than Offset+Length.
+
+--*/
+
+{
+ PNDIS_BUFFER CurBuffer;
+ UINT BytesCopied;
+ PUCHAR BufVA;
+ UINT BufLen;
+ UINT ToCopy;
+ UINT CurOffset;
+
+
+ BytesCopied = 0;
+
+ //
+ // First find a spot Offset bytes into the packet.
+ //
+
+ CurOffset = 0;
+
+ NdisQueryPacket(Packet, NULL, NULL, &CurBuffer, NULL);
+
+ while (CurBuffer != (PNDIS_BUFFER)NULL) {
+
+ NdisQueryBuffer(CurBuffer, (PVOID *)&BufVA, &BufLen);
+
+ if (CurOffset + BufLen > Offset) {
+
+ break;
+
+ }
+
+ CurOffset += BufLen;
+
+ NdisGetNextBuffer(CurBuffer, &CurBuffer);
+
+ }
+
+
+ //
+ // See if the end of the packet has already been passed.
+ //
+
+ if (CurBuffer == (PNDIS_BUFFER)NULL) {
+
+ return 0;
+
+ }
+
+
+ //
+ // Now copy over Length bytes.
+ //
+
+ BufVA += (Offset - CurOffset);
+
+ BufLen -= (Offset - CurOffset);
+
+ for (;;) {
+
+ ToCopy = (BytesCopied+BufLen > Length) ? Length - BytesCopied : BufLen;
+
+ WD_MOVE_MEM(Buf+BytesCopied, BufVA, ToCopy);
+
+ BytesCopied += ToCopy;
+
+
+ if (BytesCopied == Length) {
+
+ return BytesCopied;
+
+ }
+
+ NdisGetNextBuffer(CurBuffer, &CurBuffer);
+
+ if (CurBuffer == (PNDIS_BUFFER)NULL) {
+
+ break;
+
+ }
+
+ NdisQueryBuffer(CurBuffer, (PVOID *)&BufVA, &BufLen);
+
+ }
+
+ return BytesCopied;
+
+}
+
+
+
+NDIS_STATUS
+WdTransferData(
+ IN NDIS_HANDLE MacBindingHandle,
+ IN NDIS_HANDLE MacReceiveContext,
+ IN UINT ByteOffset,
+ IN UINT BytesToTransfer,
+ OUT PNDIS_PACKET Packet,
+ OUT PUINT BytesTransferred
+ )
+
+/*++
+
+Routine Description:
+
+ NDIS function.
+
+Arguments:
+
+ see NDIS 3.0 spec.
+
+Notes:
+
+ - The MacReceiveContext will be a pointer to the open block for
+ the packet.
+ - The LoopbackPacket field in the adapter block will be NULL if this
+ is a call for a normal packet, otherwise it will be set to point
+ to the loopback packet.
+
+--*/
+{
+ PWD_OPEN Open = PWD_OPEN_FROM_BINDING_HANDLE(MacBindingHandle);
+ PWD_ADAPTER Adapter = Open->Adapter;
+ PNDIS_BUFFER CurrentBuffer;
+ PUCHAR BufferVA;
+ UINT BufferLength, Copied;
+ UINT CurrentOffset;
+
+ UNREFERENCED_PARAMETER(MacReceiveContext);
+
+ ByteOffset += WD_HEADER_SIZE;
+
+ if (Adapter->IndicatingPacket != NULL) {
+
+ IF_LOUD( DbgPrint("Transferring data for loopback packet\n");)
+
+ //
+ // It is a loopback packet
+ //
+
+ NdisQueryPacket(Packet, NULL, NULL, &CurrentBuffer, NULL);
+
+ CurrentOffset = ByteOffset;
+
+ while (CurrentBuffer != (PNDIS_BUFFER)NULL) {
+
+ NdisQueryBuffer(CurrentBuffer, (PVOID *)&BufferVA, &BufferLength);
+
+ NdisAcquireSpinLock(&Adapter->Lock);
+
+ Copied =
+ WdCopyOver(BufferVA,
+ Adapter->IndicatingPacket,
+ CurrentOffset,
+ BufferLength
+ );
+
+ NdisReleaseSpinLock(&Adapter->Lock);
+
+ CurrentOffset += Copied;
+
+ if (Copied < BufferLength) {
+
+ break;
+
+ }
+
+ NdisGetNextBuffer(CurrentBuffer, &CurrentBuffer);
+
+ }
+
+ //
+ // We are done, return.
+ //
+
+ *BytesTransferred = CurrentOffset - ByteOffset;
+
+ if ( *BytesTransferred > BytesToTransfer ) {
+
+ *BytesTransferred = BytesToTransfer;
+ }
+
+ return(NDIS_STATUS_SUCCESS);
+
+ } else if (Adapter->IndicatedAPacket) {
+
+ NdisAcquireSpinLock(&Adapter->Lock);
+
+ IF_LOUD( DbgPrint("Transferring data for card packet\n");)
+
+ if (LM_Receive_Copy(
+ BytesTransferred,
+ BytesToTransfer,
+ ByteOffset,
+ Packet,
+ &(Adapter->LMAdapter)) != SUCCESS) {
+
+ //
+ // Copy failed.
+ //
+
+ *BytesTransferred = 0;
+
+ NdisReleaseSpinLock(&Adapter->Lock);
+
+ return(NDIS_STATUS_FAILURE);
+
+ } else {
+
+ NdisReleaseSpinLock(&Adapter->Lock);
+
+ return(NDIS_STATUS_SUCCESS);
+
+ }
+
+ } else {
+
+ return(NDIS_STATUS_NOT_INDICATING);
+
+ }
+
+}
+
+BOOLEAN
+WdSyncCloseAdapter(
+ IN PVOID Context
+ )
+/*++
+
+Routine Description:
+
+ This function is used to synchronize with the lower MAC layer close
+ calls that may access the same areas of the LM that are accessed in
+ the ISR.
+
+Arguments:
+
+ see NDIS 3.0 spec.
+
+Notes:
+
+ returns TRUE on success, else FALSE.
+
+--*/
+{
+
+ if (LM_Close_Adapter((Ptr_Adapter_Struc)Context) == SUCCESS) {
+
+ return(TRUE);
+
+ } else {
+
+ return(FALSE);
+
+ }
+
+}
+
+
+VOID
+WdWakeUpDpc(
+ IN PVOID SystemSpecific1,
+ IN PVOID Context,
+ IN PVOID SystemSpecific2,
+ IN PVOID SystemSpecific3
+ )
+
+/*++
+
+Routine Description:
+
+ This DPC routine is queued every 5 seconds to check on the
+ queues. If an interrupt was not received
+ in the last 5 seconds and there should have been one,
+ then we abort all operations.
+
+Arguments:
+
+ Context - Really a pointer to the adapter.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ PWD_ADAPTER Adapter = (PWD_ADAPTER)Context;
+ PWD_OPEN TmpOpen;
+ PNDIS_PACKET TransmitPacket;
+ PMAC_RESERVED Reserved;
+
+ UNREFERENCED_PARAMETER(SystemSpecific1);
+ UNREFERENCED_PARAMETER(SystemSpecific2);
+ UNREFERENCED_PARAMETER(SystemSpecific3);
+
+ NdisAcquireSpinLock(&Adapter->Lock);
+
+ if ((Adapter->WakeUpTimeout) &&
+ Adapter->LMAdapter.TransmitInterruptPending) {
+
+ //
+ // We had a pending operation the last time we ran,
+ // and it has not been completed...we need to complete
+ // it now.
+
+ Adapter->WakeUpTimeout = FALSE;
+
+ Adapter->HardwareFailure = TRUE;
+
+ //
+ // Disable adapter
+ //
+ IF_LOG(LOG('*'));
+ LM_Disable_Adapter(&Adapter->LMAdapter);
+
+ if (Adapter->WakeUpErrorCount < 10) {
+
+ Adapter->WakeUpErrorCount++;
+
+ NdisWriteErrorLogEntry(
+ Adapter->LMAdapter.NdisAdapterHandle,
+ NDIS_ERROR_CODE_HARDWARE_FAILURE,
+ 0
+ );
+
+ }
+
+ while (Adapter->PacketsOnCard != NULL) {
+
+ TransmitPacket = Adapter->PacketsOnCard;
+
+ Reserved = RESERVED(TransmitPacket);
+
+ Adapter->PacketsOnCard = Reserved->NextPacket;
+
+ if (Adapter->PacketsOnCard == NULL) {
+
+ Adapter->PacketsOnCardTail = NULL;
+
+ }
+
+ TmpOpen = Reserved->Open;
+
+ NdisReleaseSpinLock(&Adapter->Lock);
+
+ NdisCompleteSend(
+ TmpOpen->NdisBindingContext,
+ TransmitPacket,
+ NDIS_STATUS_SUCCESS
+ );
+
+ NdisAcquireSpinLock(&Adapter->Lock);
+
+ TmpOpen->ReferenceCount--;
+
+ }
+
+ while (Adapter->XmitQueue != NULL) {
+
+ TransmitPacket = Adapter->XmitQueue;
+
+ Reserved = RESERVED(TransmitPacket);
+
+ //
+ // Remove the packet from the queue.
+ //
+
+ Adapter->XmitQueue = Reserved->NextPacket;
+
+ if (Adapter->XmitQueue == NULL) {
+
+ Adapter->XmitQTail = NULL;
+
+ }
+
+ TmpOpen = Reserved->Open;
+
+ NdisReleaseSpinLock(&Adapter->Lock);
+
+ NdisCompleteSend(
+ TmpOpen->NdisBindingContext,
+ TransmitPacket,
+ NDIS_STATUS_SUCCESS
+ );
+
+ NdisAcquireSpinLock(&Adapter->Lock);
+
+ TmpOpen->ReferenceCount--;
+
+ }
+
+ Adapter->WakeUpTimeout = FALSE;
+
+ Adapter->LMAdapter.TransmitInterruptPending = FALSE;
+
+ //
+ // reinitialize the card
+ //
+
+ if (LM_Initialize_Adapter(&Adapter->LMAdapter) != SUCCESS) {
+
+ Adapter->HardwareFailure = TRUE;
+
+ NdisWriteErrorLogEntry(
+ Adapter->LMAdapter.NdisAdapterHandle,
+ NDIS_ERROR_CODE_HARDWARE_FAILURE,
+ 0
+ );
+
+ } else {
+
+ Adapter->HardwareFailure = FALSE;
+
+ }
+
+ //
+ // reenable interrupts
+ //
+
+ LM_Enable_Adapter(&Adapter->LMAdapter);
+
+ NdisReleaseSpinLock(&Adapter->Lock);
+
+ } else {
+
+ if ((Adapter->PacketsOnCard != NULL) ||
+ (Adapter->XmitQueue != NULL)) {
+
+ Adapter->WakeUpTimeout = TRUE;
+
+ }
+
+ NdisReleaseSpinLock(&Adapter->Lock);
+
+
+ }
+
+ //
+ // Fire off another Dpc to execute after 5 seconds
+ //
+
+ NdisSetTimer(
+ &Adapter->WakeUpTimer,
+ 5000
+ );
+
+}
diff --git a/private/ntos/ndis/wd/wdhrd.h b/private/ntos/ndis/wd/wdhrd.h
new file mode 100644
index 000000000..6574d6e07
--- /dev/null
+++ b/private/ntos/ndis/wd/wdhrd.h
@@ -0,0 +1,915 @@
+/*++
+
+Copyright (c) 1990 Microsoft Corporation
+
+Module Name:
+
+ wdhrd.h
+
+Abstract:
+
+ The main program for an Western Digital MAC driver.
+
+Author:
+
+ Anthony V. Ercolano (tonye) creation-date 19-Jun-1990 (Driver model)
+
+ Orginal Elnkii code by AdamBa.
+
+ Modified for WD by SeanSe.
+
+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 _WDHARDWARE_
+#define _WDHARDWARE_
+
+
+
+// Adapter->IoBaseAddr
+//
+// must match the setting of I/O Base Address jumper on
+// the card. Choices are 0x300 and 0x280
+//
+
+#define DEFAULT_IOBASEADDR (USHORT)0x280
+
+
+
+// Adapter->MaxOpens
+//
+// the maximum number of protocols that may be bound to this
+// adapter at one time.
+
+#define DEFAULT_MAXOPENS 4
+
+
+
+// Adapter->MulticastListMax
+//
+// the maximum number of different multicast addresses that
+// may be specified to this adapter (the list is global for
+// all protocols).
+
+#define DEFAULT_MULTICASTLISTMAX 16
+
+
+//
+// The maximum packet transmittable.
+//
+
+#define WD_MAX_PACKET_SIZE 1514
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+//
+// Offsets from Adapter->IoPAddr of the ports used to access
+// the 8390 NIC registers.
+//
+// The names in parenthesis are the abbreviations by which
+// the registers are referred to in the 8390 data sheet.
+//
+// Some of the offsets appear more than once
+// because they have have relevant page 0 and page 1 values,
+// or they are different registers when read than they are
+// when written. The notation MSB indicates that only the
+// MSB can be set for this register, the LSB is assumed 0.
+//
+
+#define NIC_COMMAND 0x0 // (CR)
+#define NIC_PAGE_START 0x1 // (PSTART) MSB, write-only
+#define NIC_PHYS_ADDR 0x1 // (PAR0) page 1
+#define NIC_PAGE_STOP 0x2 // (PSTOP) MSB, write-only
+#define NIC_BOUNDARY 0x3 // (BNRY) MSB
+#define NIC_XMIT_START 0x4 // (TPSR) MSB, write-only
+#define NIC_XMIT_STATUS 0x4 // (TSR) read-only
+#define NIC_XMIT_COUNT_LSB 0x5 // (TBCR0) write-only
+#define NIC_XMIT_COUNT_MSB 0x6 // (TBCR1) write-only
+#define NIC_FIFO 0x6 // (FIFO) read-only
+#define NIC_INTR_STATUS 0x7 // (ISR)
+#define NIC_CURRENT 0x7 // (CURR) page 1
+#define NIC_MC_ADDR 0x8 // (MAR0) page 1
+#define NIC_RMT_COUNT_LSB 0xa // (RBCR0) write-only
+#define NIC_RMT_COUNT_MSB 0xb // (RBCR1) write-only
+#define NIC_RCV_CONFIG 0xc // (RCR) write-only
+#define NIC_RCV_STATUS 0xc // (RSR) read-only
+#define NIC_XMIT_CONFIG 0xd // (TCR) write-only
+#define NIC_FAE_ERR_CNTR 0xd // (CNTR0) read-only
+#define NIC_DATA_CONFIG 0xe // (DCR) write-only
+#define NIC_CRC_ERR_CNTR 0xe // (CNTR1) read-only
+#define NIC_INTR_MASK 0xf // (IMR) write-only
+#define NIC_MISSED_CNTR 0xf // (CNTR2) read-only
+
+
+//
+// Constants for the NIC_COMMAND register.
+//
+// Start/stop the card, start transmissions, and select
+// which page of registers was seen through the ports.
+//
+
+#define CR_STOP (UCHAR)0x01 // reset the card
+#define CR_START (UCHAR)0x02 // start the card
+#define CR_XMIT (UCHAR)0x04 // begin transmission
+#define CR_NO_DMA (UCHAR)0x20 // stop remote DMA
+
+#define CR_PS0 (UCHAR)0x40 // low bit of page number
+#define CR_PS1 (UCHAR)0x80 // high bit of page number
+#define CR_PAGE0 (UCHAR)0x00 // select page 0
+#define CR_PAGE1 CR_PS0 // select page 1
+#define CR_PAGE2 CR_PS1 // select page 2
+
+
+//
+// Constants for the NIC_XMIT_STATUS register.
+//
+// Indicate the result of a packet transmission.
+//
+
+#define TSR_XMIT_OK (UCHAR)0x01 // transmit with no errors
+#define TSR_COLLISION (UCHAR)0x04 // collided at least once
+#define TSR_ABORTED (UCHAR)0x08 // too many collisions
+#define TSR_NO_CARRIER (UCHAR)0x10 // carrier lost
+#define TSR_NO_CDH (UCHAR)0x40 // no collision detect heartbeat
+
+
+//
+// Constants for the NIC_INTR_STATUS register.
+//
+// Indicate the cause of an interrupt.
+//
+
+#define ISR_RCV (UCHAR)0x01 // packet received with no errors
+#define ISR_XMIT (UCHAR)0x02 // packet transmitted with no errors
+#define ISR_RCV_ERR (UCHAR)0x04 // error on packet reception
+#define ISR_XMIT_ERR (UCHAR)0x08 // error on packet transmission
+#define ISR_OVERFLOW (UCHAR)0x10 // receive buffer overflow
+#define ISR_COUNTER (UCHAR)0x20 // MSB set on tally counter
+#define ISR_RESET (UCHAR)0x80 // (not an interrupt) card is reset
+
+
+//
+// Constants for the NIC_RCV_CONFIG register.
+//
+// Configure what type of packets are received.
+//
+
+#define RCR_REJECT_ERR (UCHAR)0x00 // reject error packets
+#define RCR_BROADCAST (UCHAR)0x04 // receive broadcast packets
+#define RCR_MULTICAST (UCHAR)0x08 // receive multicast packets
+#define RCR_ALL_PHYS (UCHAR)0x10 // receive ALL directed packets
+
+
+//
+// Constants for the NIC_RCV_STATUS register.
+//
+// Indicate the status of a received packet.
+//
+// These are also used to interpret the status byte in the
+// packet header of a received packet.
+//
+
+#define RSR_PACKET_OK (UCHAR)0x01 // packet received with no errors
+#define RSR_CRC_ERROR (UCHAR)0x02 // packet received with CRC error
+#define RSR_MULTICAST (UCHAR)0x20 // packet received was multicast
+#define RSR_DISABLED (UCHAR)0x40 // received is disabled
+#define RSR_DEFERRING (UCHAR)0x80 // receiver is deferring
+
+
+//
+// Constants for the NIC_XMIT_CONFIG register.
+//
+// Configures how packets are transmitted.
+//
+
+#define TCR_NO_LOOPBACK (UCHAR)0x00 // normal operation
+#define TCR_LOOPBACK (UCHAR)0x02 // loopback (set when NIC is stopped)
+
+#define TCR_INHIBIT_CRC (UCHAR)0x01 // inhibit appending of CRC
+
+#define TCR_NIC_LBK (UCHAR)0x02 // loopback through the NIC
+#define TCR_SNI_LBK (UCHAR)0x04 // loopback through the SNI
+#define TCR_COAX_LBK (UCHAR)0x06 // loopback to the coax
+
+
+//
+// Constants for the NIC_DATA_CONFIG register.
+//
+// Set data transfer sizes.
+//
+
+#define DCR_BYTE_WIDE (UCHAR)0x00 // byte-wide DMA transfers
+#define DCR_WORD_WIDE (UCHAR)0x01 // word-wide DMA transfers
+
+#define DCR_LOOPBACK (UCHAR)0x00 // loopback mode (TCR must be set)
+#define DCR_NORMAL (UCHAR)0x08 // normal operation
+
+#define DCR_FIFO_8_BYTE (UCHAR)0x40 // 8-byte FIFO threshhold
+
+
+//
+// Constants for the NIC_INTR_MASK register.
+//
+// Configure which ISR settings actually cause interrupts.
+//
+
+#define IMR_RCV (UCHAR)0x01 // packet received with no errors
+#define IMR_XMIT (UCHAR)0x02 // packet transmitted with no errors
+#define IMR_RCV_ERR (UCHAR)0x04 // error on packet reception
+#define IMR_XMIT_ERR (UCHAR)0x08 // error on packet transmission
+#define IMR_OVERFLOW (UCHAR)0x10 // receive buffer overflow
+#define IMR_COUNTER (UCHAR)0x20 // MSB set on tally counter
+
+
+
+//
+// Offsets from Adapter->GaPAddr (which is Adapter->IoPAddr+0x400)
+// of the ports used to access the Elnkii Gate Array registers.
+//
+// The names in parenthesis are the abbreviations by which
+// the registers are referred to in the Elnkii Technical
+// Reference.
+//
+
+#define GA_PAGE_START 0x0 // (PSTR) MSB
+#define GA_PAGE_STOP 0x1 // (PSPR) MSB
+#define GA_DRQ_TIMER 0x2 // (DQTR)
+#define GA_IO_BASE 0x3 // (BCFR) read-only
+#define GA_MEM_BASE 0x4 // (PCFR) read-only
+#define GA_CONFIG 0x5 // (GACFR)
+#define GA_CONTROL 0x6 // (CTRL)
+#define GA_STATUS 0x7 // (STREG) read-only
+#define GA_INT_DMA_CONFIG 0x8 // (IDCFR)
+#define GA_DMA_ADDR_MSB 0x9 // (DAMSB)
+#define GA_DMA_ADDR_LSB 0xa // (DALSB)
+#define GA_REG_FILE_MSB 0xe // (RFMSB)
+#define GA_REG_FILE_LSB 0xf // (RFLSB)
+
+
+//
+// Constants for the GA_DRQ_TIMER register.
+//
+
+#define DQTR_16_BYTE (UCHAR)0x10 // 16-byte programmed I/O bursts
+#define DQTR_8_BYTE (UCHAR)0x08 // 8-byte programmed I/O bursts
+
+
+//
+// Constants for the GA_CONFIG register.
+//
+
+#define GACFR_TC_MASK (UCHAR)0x40 // block DMA complete interrupts
+#define GACFR_RAM_SEL (UCHAR)0x08 // allow memory-mapped mode
+#define GACFR_MEM_BANK1 (UCHAR)0x01 // select window for 8K buffer
+
+
+//
+// Constants for the GA_CONTROL register.
+//
+
+#define CTRL_START (UCHAR)0x80 // start the DMA controller
+#define CTRL_STOP (UCHAR)0x00 // stop the DMA controller
+
+#define CTRL_DIR_DOWN (UCHAR)0x40 // system->board transfers
+#define CTRL_DIR_UP (UCHAR)0x00 // board->system transfers
+
+#define CTRL_DB_SEL (UCHAR)0x20 // connect FIFOs serially
+
+#define CTRL_PROM_SEL (UCHAR)0x04 // window PROM into GaPAddr ports
+#define CTRL_GA_SEL (UCHAR)0x00 // window GA into GaPAddr ports
+
+#define CTRL_BNC (UCHAR)0x02 // internal tranceiver
+#define CTRL_DIX (UCHAR)0x00 // external tranceiver
+
+#define CTRL_RESET (UCHAR)0x01 // emulate power up reset
+
+
+//
+// Constants for the GA_STATUS register.
+//
+
+#define STREG_DP_READY (UCHAR)0x80 // ready for programmed I/O transfer
+#define STREG_UNDERFLOW (UCHAR)0x40 // register file underflow
+#define STREG_OVERFLOW (UCHAR)0x20 // register file overflow
+#define STREG_IN_PROG (UCHAR)0x08 // programmed I/O in progress
+
+
+
+
+//++
+//
+// VOID
+// CardStartXmit(
+// IN PELNKII_ADAPTER Adapter
+// )
+//
+// Routine Description:
+//
+// Starts a packet transmission. The transmit buffer number is
+// taken from Adapter->CurBufXmitting and the length of the packet
+// is taken from Adapter->PacketLens[Adapter->CurBufXmitting].
+// Calls SyncCardStartXmit.
+//
+// Arguments:
+//
+// Adapter - The adapter block.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+#define CardStartXmit(Adapter) \
+ NdisSynchronizeWithInterrupt(&(Adapter)->NdisInterrupt, \
+ SyncCardStartXmit, (PVOID)(Adapter))
+
+
+//++
+//
+// VOID
+// CardWriteMulticast(
+// IN PELNKII_ADAPTER Adapter,
+// IN UCHAR Byte
+// )
+//
+// Routine Description:
+//
+// Writes a single byte to the multicast address register bit mask.
+// Calls SyncCardWriteMulticast. Byte indicates which byte to
+// write (0-7); the actual value to write is taken from
+// Adapter->NicMulticastRegs[Byte].
+//
+// Arguments:
+//
+// Adapter - The adapter block.
+// Byte - Which multicast byte to write.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+#define CardWriteMulticast(Adapter, Byte) \
+ (Adapter)->ByteToWrite = Byte, \
+ NdisSynchronizeWithInterrupt(&(Adapter)->NdisInterrupt, \
+ SyncCardWriteMulticast, (PVOID)(Adapter))
+
+
+//++
+//
+// VOID
+// CardSetAllMulticast(
+// IN PELNKII_ADAPTER Adapter
+// )
+//
+// Routine Description:
+//
+// Enables every bit in the card multicast bit mask.
+// Calls SyncCardSetAllMulticast.
+//
+// Arguments:
+//
+// Adapter - The adapter block.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+#define CardSetAllMulticast(Adapter) \
+ NdisSynchronizeWithInterrupt(&(Adapter)->NdisInterrupt, \
+ SyncCardSetAllMulticast, (PVOID)(Adapter))
+
+
+//++
+//
+// VOID
+// CardCopyMulticastRegs(
+// IN PELNKII_ADAPTER Adapter
+// )
+//
+// Routine Description:
+//
+// Writes out the entire multicast bit mask to the card from
+// Adapter->NicMulticastRegs. Calls SyncCardCopyMulticastRegs.
+//
+// Arguments:
+//
+// Adapter - The adapter block.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+#define CardCopyMulticastRegs(Adapter) \
+ NdisSynchronizeWithInterrupt(&(Adapter)->NdisInterrupt, \
+ SyncCardCopyMulticastRegs, (PVOID)(Adapter))
+
+
+//++
+//
+// VOID
+// CardCopyPhysicalAddress(
+// IN PELNKII_ADAPTER Adapter
+// )
+//
+// Routine Description:
+//
+// Writes out the physical address to the card. The value is
+// read from Adapter->StationAddress. Calls SyncCardCopyPhysicalAddress.
+//
+// Arguments:
+//
+// Adapter - The adapter block.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+#define CardCopyPhysicalAddress(Adapter) \
+ NdisSynchronizeWithInterrupt(&(Adapter)->NdisInterrupt, \
+ SyncCardCopyPhysicalAddress, (PVOID)(Adapter))
+
+
+//++
+//
+// VOID
+// CardGetInterruptStatus(
+// IN PELNKII_ADAPTER Adapter,
+// OUT PUCHAR InterrupStatus
+// )
+//
+// Routine Description:
+//
+// Reads the interrupt status (ISR) register from the card. Only
+// called at IRQL INTERRUPT_LEVEL.
+//
+// Arguments:
+//
+// Adapter - The adapter block.
+//
+// InterruptStatus - Returns the value of ISR.
+//
+// Return Value:
+//
+//--
+
+#define CardGetInterruptStatus(Adapter,InterruptStatus) \
+ NdisReadPortUchar((Adapter)->NdisAdapterHandle, (Adapter)->IoPAddr+NIC_INTR_STATUS, (InterruptStatus))
+
+
+//++
+//
+// UCHAR
+// CardGetXmitStatus(
+// IN PELNKII_ADAPTER Adapter
+// )
+//
+// Routine Description:
+//
+// Reads the transmit status (TSR) register from the card.
+// Calls SyncCardGetXmitStatus.
+//
+// Arguments:
+//
+// Adapter - The adapter block.
+//
+// Return Value:
+//
+// The value of TSR.
+//
+//--
+
+#define CardGetXmitStatus(Adapter) \
+ NdisSynchronizeWithInterrupt(&(Adapter)->NdisInterrupt, \
+ SyncCardGetXmitStatus, (PVOID)(Adapter))
+
+
+//++
+//
+// UCHAR
+// CardGetCurrent(
+// IN PELNKII_ADAPTER Adapter
+// )
+//
+// Routine Description:
+//
+// Reads the current (CURR) register from the card.
+// Calls SyncCardGetCurrent.
+//
+// Arguments:
+//
+// Adapter - The adapter block.
+//
+// Return Value:
+//
+// The value of CURR.
+//
+//--
+
+#define CardGetCurrent(Adapter) \
+ NdisSynchronizeWithInterrupt(&(Adapter)->NdisInterrupt, \
+ SyncCardGetCurrent, (PVOID)(Adapter))
+
+
+//++
+//
+// VOID
+// CardSetBoundary(
+// IN PELNKII_ADAPTER Adapter
+// )
+//
+// Routine Description:
+//
+// Sets the boundary (BNRY) register on the card. The value used
+// is one before Adapter->NicNextPacket. Calls SyncCardSetBoundary.
+//
+// Arguments:
+//
+// Adapter - The adapter block.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+#define CardSetBoundary(Adapter) \
+ NdisSynchronizeWithInterrupt(&(Adapter)->NdisInterrupt, \
+ SyncCardSetBoundary, (PVOID)(Adapter))
+
+
+//++
+//
+// VOID
+// CardSetReceiveConfig(
+// IN PELNKII_ADAPTER Adapter
+// )
+//
+// Routine Description:
+//
+// Sets the receive configuration (RCR) register on the card.
+// The value used is Adapter->NicReceiveConfig. Calls
+// SyncCardSetReceiveConfig.
+//
+// Arguments:
+//
+// Adapter - The adapter block.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+#define CardSetReceiveConfig(Adapter) \
+ NdisSynchronizeWithInterrupt(&(Adapter)->NdisInterrupt, \
+ SyncCardSetReceiveConfig, (PVOID)(Adapter))
+
+
+//++
+//
+// VOID
+// CardBlockInterrupts(
+// IN PELNKII_ADAPTER Adapter
+// )
+//
+// Routine Description:
+//
+// Blocks all interrupts from the card by clearing the
+// interrupt mask (IMR) register. Only called from
+// IRQL INTERRUPT_LEVEL.
+//
+// Arguments:
+//
+// Adapter - The adapter block.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+#define CardBlockInterrupts(Adapter) \
+ NdisWritePortUchar((Adapter)->NdisAdapterHandle, (Adapter)->IoPAddr+NIC_INTR_MASK, 0)
+
+
+//++
+//
+// VOID
+// CardUnblockInterrupts(
+// IN PELNKII_ADAPTER Adapter
+// )
+//
+// Routine Description:
+//
+// Unblocks all interrupts from the card by setting the
+// interrupt mask (IMR) register. Only called from IRQL
+// INTERRUPT_LEVEL.
+//
+// Arguments:
+//
+// Adapter - The adapter block.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+#define CardUnblockInterrupts(Adapter) \
+ NdisWritePortUchar((Adapter)->NdisAdapterHandle, \
+ (Adapter)->IoPAddr+NIC_INTR_MASK, \
+ (Adapter)->NicInterruptMask)
+
+
+//++
+//
+// VOID
+// CardDisableReceiveInterrupt(
+// IN PELNKII_ADAPTER Adapter
+// )
+//
+// Routine Description:
+//
+// Turns off the receive bit in Adapter->NicInterruptMask.
+// This function is only called when CardBlockInterrupts have
+// been called; it ensures that receive interrupts are not
+// reenabled until CardEnableReceiveInterrupt is called, even
+// if CardUnblockInterrupts is called.
+//
+// Arguments:
+//
+// Adapter - The adapter block.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+#define CardDisableReceiveInterrupt(Adapter) \
+ (Adapter)->NicInterruptMask &= (UCHAR)~IMR_RCV
+
+
+//++
+//
+// VOID
+// CardEnableReceiveInterrupt(
+// IN PELNKII_ADAPTER Adapter
+// )
+//
+// Routine Description:
+//
+// Reenables receive interrupts by setting the receive bit ibn
+// Adapter->NicInterruptMask, and also writes the new value to
+// the card. Calls SyncCardSetInterruptMask.
+//
+// Arguments:
+//
+// Adapter - The adapter block.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+#define CardEnableReceiveInterrupt(Adapter) \
+ (Adapter)->NicInterruptMask |= (UCHAR)IMR_RCV, \
+ NdisSynchronizeWithInterrupt(&(Adapter)->NdisInterrupt, \
+ SyncCardSetInterruptMask, (PVOID)(Adapter))
+
+
+//++
+//
+// VOID
+// CardAcknowledgeReceiveInterrupt(
+// IN PELNKII_ADAPTER Adapter
+// )
+//
+// Routine Description:
+//
+// Acknowledges a receive interrupt by setting the bit in
+// the interrupt status (ISR) register. Calls
+// SyncCardAcknowledgeReceive.
+//
+// Arguments:
+//
+// Adapter - The adapter block.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+#define CardAcknowledgeReceiveInterrupt(Adapter) \
+ NdisSynchronizeWithInterrupt(&(Adapter)->NdisInterrupt, \
+ SyncCardAcknowledgeReceive, (PVOID)(Adapter))
+
+
+//++
+//
+// VOID
+// CardAcknowledgeOverflowInterrupt(
+// IN PELNKII_ADAPTER Adapter
+// )
+//
+// Routine Description:
+//
+// Acknowledges an overflow interrupt by setting the bit in
+// the interrupt status (ISR) register. Calls
+// SyncCardAcknowledgeOverflow.
+//
+// Arguments:
+//
+// Adapter - The adapter block.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+#define CardAcknowledgeOverflowInterrupt(Adapter) \
+ NdisSynchronizeWithInterrupt(&(Adapter)->NdisInterrupt, \
+ SyncCardAcknowledgeOverflow, (PVOID)(Adapter))
+
+
+//++
+//
+// VOID
+// CardAcknowledgeTransmitInterrupt(
+// IN PELNKII_ADAPTER Adapter
+// )
+//
+// Routine Description:
+//
+// Acknowledges a transmit interrupt by setting the bit in
+// the interrupt status (ISR) register. Calls
+// SyncCardAcknowledgeTransmit.
+//
+// Arguments:
+//
+// Adapter - The adapter block.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+#define CardAcknowledgeTransmitInterrupt(Adapter) \
+ NdisSynchronizeWithInterrupt(&(Adapter)->NdisInterrupt, \
+ SyncCardAcknowledgeTransmit, (PVOID)(Adapter))
+
+
+//++
+//
+// VOID
+// CardAcknowledgeCounterInterrupt(
+// IN PELNKII_ADAPTER Adapter
+// )
+//
+// Routine Description:
+//
+// Acknowledges a counter interrupt by setting the bit in
+// the interrupt status (ISR) register.
+//
+// Arguments:
+//
+// Adapter - The adapter block.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+#define CardAcknowledgeCounterInterrupt(Adapter) \
+ NdisWritePortUchar((Adapter)->NdisAdapterHandle, (Adapter)->IoPAddr+NIC_INTR_STATUS, ISR_COUNTER)
+
+
+//++
+//
+// VOID
+// CardAckAndGetCurrent(
+// IN PELNKII_ADAPTER Adapter
+// )
+//
+// Routine Description:
+//
+// Performs the function of CardAcknowledgeReceive followed by
+// CardGetCurrent (since the two are always called
+// one after the other). Calls SyncCardAckAndGetCurrent.
+//
+// Arguments:
+//
+// Adapter - The adapter block.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+#define CardAckAndGetCurrent(Adapter) \
+ NdisSynchronizeWithInterrupt(&(Adapter)->NdisInterrupt, \
+ SyncCardAckAndGetCurrent, (PVOID)(Adapter))
+
+
+//++
+//
+// VOID
+// CardGetXmitStatusAndAck(
+// IN PELNKII_ADAPTER Adapter
+// )
+//
+// Routine Description:
+//
+// Performs the function of CardGetXmitStatus followed by
+// CardAcknowledgeTransmit (since the two are always called
+// one after the other). Calls SyncCardGetXmitStatusAndAck.
+//
+// Arguments:
+//
+// Adapter - The adapter block.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+#define CardGetXmitStatusAndAck(Adapter) \
+ NdisSynchronizeWithInterrupt(&(Adapter)->NdisInterrupt, \
+ SyncCardGetXmitStatusAndAck, (PVOID)(Adapter))
+
+
+//++
+//
+// VOID
+// CardUpdateCounters(
+// IN PELNKII_ADAPTER Adapter
+// )
+//
+// Routine Description:
+//
+// Updates the values of the three counters (frame alignment
+// errors, CRC errors, and missed packets) by reading in their
+// current values from the card and adding them to the ones
+// stored in the Adapter structure. Calls SyncCardUpdateCounters.
+//
+// Arguments:
+//
+// Adapter - The adapter block.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+#define CardUpdateCounters(Adapter) \
+ NdisSynchronizeWithInterrupt(&(Adapter)->NdisInterrupt, \
+ SyncCardUpdateCounters, (PVOID)(Adapter))
+
+
+#endif // _ELNKIIHARDWARE_
diff --git a/private/ntos/ndis/wd/wdlan.rc b/private/ntos/ndis/wd/wdlan.rc
new file mode 100644
index 000000000..d4f7d4aa0
--- /dev/null
+++ b/private/ntos/ndis/wd/wdlan.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 "SMC/WD Ethernet network driver"
+#define VER_INTERNALNAME_STR "SMCISA.SYS"
+#define VER_ORIGINALFILENAME_STR "SMCISA.SYS"
+
+#include "common.ver"
+
diff --git a/private/ntos/ndis/wd/wdlmi.h b/private/ntos/ndis/wd/wdlmi.h
new file mode 100644
index 000000000..614cf0056
--- /dev/null
+++ b/private/ntos/ndis/wd/wdlmi.h
@@ -0,0 +1,865 @@
+/*++
+
+Copyright (c) 1990 Microsoft Corporation
+
+Module Name:
+
+ wdlmi.h
+
+Abstract:
+
+ Lower MAC Interface functions for the NDIS 3.0 Western Digital driver.
+
+Author:
+
+ Sean Selitrennikoff (seanse) 15-Jan-92
+
+Environment:
+
+ Kernel mode, FSD
+
+Revision History:
+
+
+--*/
+
+#if DBG
+
+#define LOG(A) LOG(A)
+
+#else
+
+#define LOG(A)
+
+#endif
+
+
+#define WD_ETHERNET 0x01
+
+
+//
+// A transmit buffer (usually 0 or 1).
+//
+
+typedef SHORT XMIT_BUF;
+
+
+
+//
+// Maximum number of transmit buffers on the card.
+//
+
+#define MAX_XMIT_BUFS 2
+
+
+
+
+//
+// The status of transmit buffers.
+//
+
+typedef enum { EMPTY, FILLING, FULL } BUFFER_STATUS;
+
+//
+// Result of WdIndicate[Loopback]Packet().
+//
+
+typedef enum { INDICATE_OK, SKIPPED, ABORT, CARD_BAD } INDICATE_STATUS;
+
+
+//
+// Stages in a reset.
+//
+
+typedef enum { NONE, MULTICAST_RESET, XMIT_STOPPED, BUFFERS_EMPTY } RESET_STAGE;
+
+
+
+
+typedef struct _CNFG_Adapter {
+ ULONG cnfg_bid; /* Board ID from GetBoardID */
+ ULONG cnfg_ram_base; /* 32-Bit Phys Address of Shared RAM */
+ ULONG cnfg_rom_base; /* 32-Bit Phys Address of Adapter ROM */
+ USHORT cnfg_bus; /* 0=AT...1=MCA */
+ USHORT cnfg_base_io; /* Adapter Base I/O Address */
+ USHORT cnfg_slot; /* Micro Channel Slot Number */
+ USHORT cnfg_ram_size; /* Shared RAM Size (# of 1KB blocks) */
+ USHORT cnfg_ram_usable; /* Amount of RAM that can be accessed at once */
+ USHORT cnfg_irq_line; /* Adapter IRQ Interrupt Line */
+ USHORT cnfg_rom_size; /* Adapter ROM Size (# of 1KB blocks) */
+ USHORT cnfg_mode_bits1; /* Mode bits for adapter (see below) */
+ USHORT cnfg_pos_id;
+ UCHAR cnfg_media_type; /* Media type */
+ UCHAR cnfg_bic_type; /* Board Interface Chip number */
+ UCHAR cnfg_nic_type; /* Network Interface Chip number */
+ NDIS_MCA_POS_DATA PosData;
+} CNFG_Adapter, *PCNFG_Adapter;
+
+
+
+typedef struct _ADAPTER_STRUC{
+
+ UCHAR bus_type; // 0 = ISA, 1 = MCA
+
+ UCHAR mc_slot_num; // MCA bus only
+
+ USHORT pos_id; // Adapter POS ID (Mca only)
+
+ USHORT io_base; // Adapter I/O Base
+
+ PUCHAR adapter_text_ptr; // See LM_Get_Config
+
+ USHORT irq_value; // IRQ line used by hardware
+
+ USHORT rom_size; // num of 1K blocks
+
+ ULONG rom_base; // physical address of ROM
+
+ PVOID rom_access; // Pointer into VM of rom_base
+
+ USHORT ram_size; // num of 1K blocks
+
+ ULONG ram_base; // physical address of RAM
+
+ PVOID ram_access; // Pointer into VM of ram_base
+
+ USHORT ram_usable; // num of 1K blocks that can be accessed at once
+
+ USHORT io_base_new; // new i/o base addr for LM_Put_Config
+
+ UCHAR node_address[6]; // network address
+
+ UCHAR permanent_node_address[6]; // network address burned into card.
+
+ UCHAR multi_address[6]; // multicase address
+
+ USHORT max_packet_size; // for this MAC driver
+
+ USHORT buffer_page_size; // size of adapters RAM TX/RX buffer pages.
+
+ USHORT num_of_tx_buffs; // TX bufss in adapter RAM
+
+ USHORT receive_lookahead_size;
+
+ USHORT receive_mask;
+
+ USHORT adapter_status;
+
+ USHORT media_type;
+
+ USHORT bic_type;
+
+ USHORT nic_type;
+
+ USHORT adapter_type;
+
+ NDIS_HANDLE NdisAdapterHandle;
+
+ NDIS_MCA_POS_DATA PosData;
+
+ //
+ // These counters must be initialized by the upper layer.
+ //
+
+
+ //
+ // Common counters...
+ //
+
+ PULONG ptr_rx_CRC_errors;
+
+ PULONG ptr_rx_lost_pkts;
+
+
+ //
+ // Ethernet specific counters. Must be initialized by upper layer.
+ //
+
+ PULONG ptr_rx_too_big;
+
+ PULONG ptr_rx_align_errors;
+
+ PULONG ptr_rx_overruns;
+
+ PULONG ptr_tx_deferred;
+
+ PULONG ptr_tx_max_collisions;
+
+ PULONG ptr_tx_one_collision;
+
+ PULONG ptr_tx_mult_collisions;
+
+ PULONG ptr_tx_ow_collision;
+
+ PULONG ptr_tx_CD_heartbeat;
+
+ PULONG ptr_tx_carrier_lost;
+
+ PULONG ptr_tx_underruns;
+
+
+
+
+ ULONG board_id;
+
+ USHORT mode_bits;
+
+ USHORT status_bits;
+
+ USHORT xmit_buf_size;
+
+ USHORT config_mode; // 1 == Store config in EEROM
+
+
+
+
+ UCHAR State;
+
+ BOOLEAN BufferOverflow; // does an overflow need to be handled
+
+ UCHAR InterruptMask;
+
+ BOOLEAN UMRequestedInterrupt; // Has LM_Interrupt() been called.
+
+
+
+ NDIS_INTERRUPT NdisInterrupt; // interrupt info used by wrapper
+
+ UCHAR Current;
+
+ //
+ // Transmit information.
+ //
+
+ XMIT_BUF NextBufToFill; // where to copy next packet to
+ XMIT_BUF NextBufToXmit; // valid if CurBufXmitting is -1
+ XMIT_BUF CurBufXmitting; // -1 if none is
+ BOOLEAN TransmitInterruptPending; // transmit interrupt and overwrite error?
+ UINT PacketLens[MAX_XMIT_BUFS];
+ BUFFER_STATUS BufferStatus[MAX_XMIT_BUFS];
+
+ PUCHAR ReceiveStart; // start of card receive area
+ PUCHAR ReceiveStop; // end of card receive area
+
+
+ //
+ // Loopback information
+ //
+
+ PNDIS_PACKET LoopbackQueue; // queue of packets to loop back
+ PNDIS_PACKET LoopbackQTail;
+ PNDIS_PACKET LoopbackPacket; // current one we are looping back
+
+ //
+ // Receive information
+ //
+
+ PUCHAR IndicatingPacket;
+ BOOLEAN OverWriteHandling; // Currently handling an overwrite
+ BOOLEAN OverWriteStartTransmit;
+ UCHAR StartBuffer; // Start buffer number to receive into
+ UCHAR LastBuffer; // Last buffer number + 1
+ UINT PacketLen;
+
+ //
+ // Interrupt Information
+ //
+
+ UCHAR LaarHold;
+
+ //
+ // Pointer to the filter database for the MAC.
+ //
+ PETH_FILTER FilterDB;
+
+}Adapter_Struc, *Ptr_Adapter_Struc;
+
+
+
+
+//
+// LMI Status and Return codes
+//
+
+typedef USHORT LM_STATUS;
+
+#define SUCCESS 0x0
+#define ADAPTER_AND_CONFIG 0x1 // Adapter found and config info gotten
+#define ADAPTER_NO_CONFIG 0x2 // Adapter found, no config info found
+#define NOT_MY_INTERRUPT 0x3 // No interrupt found in LM_Service_Events
+#define FRAME_REJECTED 0x4
+#define EVENTS_DISABLED 0x5 // Disables LM_Service_Events from reporting
+ // any further interrupts.
+#define OUT_OF_RESOURCES 0x6
+#define OPEN_FAILED 0x7
+#define HARDWARE_FAILED 0x8
+#define INITIALIZE_FAILED 0x9
+#define CLOSE_FAILED 0xA
+#define MAX_COLLISIONS 0xB
+#define FIFO_UNDERRUN 0xC
+#define BUFFER_TOO_SMALL 0xD
+#define ADAPTER_CLOSED 0xE
+#define FAILURE 0xF
+
+#define REQUEUE_LATER 0x12
+
+
+#define INVALID_FUNCTION 0x80
+#define INVALID_PARAMETER 0x81
+
+#define ADAPTER_NOT_FOUND 0xFFFF
+
+
+//
+// Valid states for the adapter
+//
+
+#define OPEN 0x1
+#define INITIALIZED 0x2
+#define CLOSED 0x3
+#define REMOVED 0x4
+
+
+//
+// Error code places
+//
+
+#define getBoardId 0x01
+#define cardGetConfig 0x02
+
+
+
+//
+// Media type masks (for LMAdapter.media_type)
+//
+
+
+#define MEDIA_S10 0x00 // Ethernet, TP
+#define MEDIA_AUI_UTP 0x01 // Ethernet, AUI
+#define MEDIA_BNC 0x02 // Ethernet, BNC
+#define MEDIA_UNKNOWN 0xFFFF
+
+
+
+//
+// BIC codes (for the bic_type field)
+//
+
+#define BIC_NO_CHIP 0x00
+#define BIC_583_CHIP 0x01
+#define BIC_584_CHIP 0x02
+#define BIC_585_CHIP 0x03
+#define BIC_593_CHIP 0x04
+#define BIC_594_CHIP 0x05
+#define BIC_790_CHIP 0x07
+
+
+//
+// NIC codes (for the nic_type field)
+//
+
+#define NIC_UNKNOWN_CHIP 0x00
+#define NIC_8390_CHIP 0x01
+#define NIC_690_CHIP 0x02
+#define NIC_825_CHIP 0x03
+#define NIC_790_CHIP 0x07
+
+//
+// Adapter type codes (for the adapter_type field)
+//
+
+#define BUS_UNKNOWN_TYPE 0x00
+#define BUS_ISA16_TYPE 0x01
+#define BUS_ISA8_TYPE 0x02
+#define BUS_MCA_TYPE 0x03
+#define BUS_EISA32M_TYPE 0x04
+#define BUS_EIST32S_TYPE 0x05
+
+
+
+
+//
+// UM_RingStatus_Change codes
+//
+
+
+#define SIGNAL_LOSS 0x14
+#define HARD_ERROR 0x15
+#define SOFT_ERROR 0x16
+#define TRANSMIT_BEACON 0x17
+#define LOBE_WIRE_FAULT 0x18
+#define AUTO_REMOVAL_ERROR_1 0x19
+#define REMOVE_RECEIVED 0x1A
+#define COUNTER_OVERFLOW 0x1B
+#define SINGLE_STATION 0x1C
+#define RING_RECOVERY 0x1D
+
+
+
+
+//++
+//
+// XMIT_BUF
+// NextBuf(
+// IN PWD_ADAPTER AdaptP,
+// IN XMIT_BUF XmitBuf
+// )
+//
+// Routine Description:
+//
+// NextBuf "increments" a transmit buffer number. The next
+// buffer is returned; the number goes back to 0 when it
+// reaches AdaptP->NumBuffers.
+//
+// Arguments:
+//
+// AdaptP - The adapter block.
+// XmitBuf - The current transmit buffer number.
+//
+// Return Value:
+//
+// The next transmit buffer number.
+//
+//--
+
+#define NextBuf(AdaptP, XmitBuf) \
+ ((XMIT_BUF)(((XmitBuf)+1)%(AdaptP)->NumBuffers))
+
+
+
+
+
+
+//
+// Function Definitions.
+//
+
+
+extern
+LM_STATUS
+LM_Send(
+ PNDIS_PACKET Packet,
+ Ptr_Adapter_Struc Adapter
+ );
+
+
+
+extern
+LM_STATUS
+LM_Interrupt_req(
+ Ptr_Adapter_Struc Adapter
+ );
+
+
+extern
+LM_STATUS
+LM_Service_Receive_Events(
+ Ptr_Adapter_Struc Adapter
+ );
+
+extern
+LM_STATUS
+LM_Service_Transmit_Events(
+ Ptr_Adapter_Struc Adapter
+ );
+
+
+extern
+LM_STATUS
+LM_Receive_Copy(
+ PULONG Bytes_Transferred,
+ ULONG Byte_Count,
+ ULONG Offset,
+ PNDIS_PACKET Packet,
+ Ptr_Adapter_Struc Adapter
+ );
+
+
+extern
+LM_STATUS
+LM_Receive_Lookahead(
+ ULONG Byte_Count,
+ ULONG Offset,
+ PUCHAR Buffer,
+ Ptr_Adapter_Struc Adapter
+ );
+
+extern
+LM_STATUS
+LM_Get_Mca_Io_Base_Address(
+ IN Ptr_Adapter_Struc Adapt,
+ IN NDIS_HANDLE ConfigurationHandle,
+ OUT USHORT *IoBaseAddress
+ );
+
+extern
+LM_STATUS
+LM_Get_Config(
+ Ptr_Adapter_Struc Adapter
+ );
+
+extern
+LM_STATUS
+LM_Free_Resources(
+ Ptr_Adapter_Struc Adapt
+ );
+
+extern
+LM_STATUS
+LM_Initialize_Adapter(
+ Ptr_Adapter_Struc Adapter
+ );
+
+
+extern
+LM_STATUS
+LM_Open_Adapter(
+ Ptr_Adapter_Struc Adapter
+ );
+
+
+extern
+LM_STATUS
+LM_Close_Adapter(
+ Ptr_Adapter_Struc Adapter
+ );
+
+
+extern
+LM_STATUS
+LM_Disable_Adapter(
+ Ptr_Adapter_Struc Adapter
+ );
+
+extern
+LM_STATUS
+LM_Disable_Adapter_Receives(
+ Ptr_Adapter_Struc Adapt
+ );
+
+extern
+LM_STATUS
+LM_Disable_Adapter_Transmits(
+ Ptr_Adapter_Struc Adapt
+ );
+
+extern
+LM_STATUS
+LM_Enable_Adapter(
+ Ptr_Adapter_Struc Adapter
+ );
+
+
+extern
+LM_STATUS
+LM_Enable_Adapter_Receives(
+ Ptr_Adapter_Struc Adapt
+ );
+
+extern
+LM_STATUS
+LM_Enable_Adapter_Transmits(
+ Ptr_Adapter_Struc Adapt
+ );
+
+#define LM_Set_Multi_Address(Addresses, Count, Adapter) (SUCCESS)
+
+
+extern
+LM_STATUS
+LM_Set_Receive_Mask(
+ Ptr_Adapter_Struc Adapter
+ );
+
+
+
+
+//
+//
+// Below here is LM Specific codes and structures..
+//
+//
+
+
+
+
+/******************************************************************************
+ Definitions for the field:
+ cnfg_mode_bits1
+******************************************************************************/
+
+
+#define INTERRUPT_STATUS_BIT 0x8000 /* PC Interrupt Line: 0 = Not Enabled */
+#define BOOT_STATUS_MASK 0x6000 /* Mask to isolate BOOT_STATUS */
+#define BOOT_INHIBIT 0x0000 /* BOOT_STATUS is 'inhibited' */
+#define BOOT_TYPE_1 0x2000 /* Unused BOOT_STATUS value */
+#define BOOT_TYPE_2 0x4000 /* Unused BOOT_STATUS value */
+#define BOOT_TYPE_3 0x6000 /* Unused BOOT_STATUS value */
+#define ZERO_WAIT_STATE_MASK 0x1800 /* Mask to isolate Wait State flags */
+#define ZERO_WAIT_STATE_8_BIT 0x1000 /* 0 = Disabled (Inserts Wait States) */
+#define ZERO_WAIT_STATE_16_BIT 0x0800 /* 0 = Disabled (Inserts Wait States) */
+#define BNC_INTERFACE 0x0400
+#define AUI_10BT_INTERFACE 0x0200
+#define STARLAN_10_INTERFACE 0x0100
+#define INTERFACE_TYPE_MASK 0x0700
+#define MANUAL_CRC 0x0010
+
+
+
+
+
+
+#define CNFG_ID_8003E 0x6FC0
+#define CNFG_ID_8003S 0x6FC1
+#define CNFG_ID_8003W 0x6FC2
+#define CNFG_ID_8013E 0x61C8
+#define CNFG_ID_8013W 0x61C9
+#define CNFG_ID_8115TRA 0x6FC6
+#define CNFG_ID_BISTRO03E 0xEFE5
+#define CNFG_ID_BISTRO13E 0xEFD5
+#define CNFG_ID_BISTRO13W 0xEFD4
+
+#define CNFG_MSR_583 MEMORY_SELECT_REG
+#define CNFG_ICR_583 INTERFACE_CONFIG_REG
+#define CNFG_IAR_583 IO_ADDRESS_REG
+#define CNFG_BIO_583 BIOS_ROM_ADDRESS_REG
+#define CNFG_IRR_583 INTERRUPT_REQUEST_REG
+#define CNFG_LAAR_584 LA_ADDRESS_REG
+#define CNFG_GP2 GENERAL_PURPOSE_REG2
+#define CNFG_LAAR_MASK LAAR_MASK
+#define CNFG_LAAR_ZWS LAAR_ZERO_WAIT_STATE
+#define CNFG_ICR_IR2_584 IR2
+#define CNFG_IRR_IRQS (INTERRUPT_REQUEST_BIT1 | INTERRUPT_REQUEST_BIT0)
+#define CNFG_IRR_IEN INTERRUPT_ENABLE
+#define CNFG_IRR_ZWS ZERO_WAIT_STATE_ENABLE
+#define CNFG_GP2_BOOT_NIBBLE 0xF
+
+#define CNFG_SIZE_8KB 8
+#define CNFG_SIZE_16KB 16
+#define CNFG_SIZE_32KB 32
+#define CNFG_SIZE_64KB 64
+
+#define ROM_DISABLE 0x0
+
+#define CNFG_SLOT_ENABLE_BIT 0x8
+
+#define CNFG_MEDIA_TYPE_MASK 0x07
+
+#define CNFG_INTERFACE_TYPE_MASK 0x700
+#define CNFG_POS_CONTROL_REG 0x96
+#define CNFG_POS_REG0 0x100
+#define CNFG_POS_REG1 0x101
+#define CNFG_POS_REG2 0x102
+#define CNFG_POS_REG3 0x103
+#define CNFG_POS_REG4 0x104
+#define CNFG_POS_REG5 0x105
+
+
+
+
+
+
+
+
+//
+//
+// General Register types
+//
+//
+
+#define WD_REG_0 0x00
+#define WD_REG_1 0x01
+#define WD_REG_2 0x02
+#define WD_REG_3 0x03
+#define WD_REG_4 0x04
+#define WD_REG_5 0x05
+#define WD_REG_6 0x06
+#define WD_REG_7 0x07
+
+#define WD_LAN_OFFSET 0x08
+
+#define WD_LAN_0 0x08
+#define WD_LAN_1 0x09
+#define WD_LAN_2 0x0A
+#define WD_LAN_3 0x0B
+#define WD_LAN_4 0x0C
+#define WD_LAN_5 0x0D
+
+#define WD_ID_BYTE 0x0E
+
+#define WD_CHKSUM 0x0F
+
+#define WD_MSB_583_BIT 0x08
+
+#define WD_SIXTEEN_BIT 0x01
+
+#define WD_BOARD_REV_MASK 0x1E
+
+//
+// Definitions for board Rev numbers greater than 1
+//
+
+#define WD_MEDIA_TYPE_BIT 0x01
+#define WD_SOFT_CONFIG_BIT 0x20
+#define WD_RAM_SIZE_BIT 0x40
+#define WD_BUS_TYPE_BIT 0x80
+
+
+//
+// Definitions for the 690 board
+//
+
+#define WD_690_CR 0x10 // command register
+
+#define WD_690_TXP 0x04 // transmit packet command
+#define WD_690_TCR 0x0D // transmit configuration register
+#define WD_690_TCR_TEST_VAL 0x18 // Value to test 8390 or 690
+
+#define WD_690_PS0 0x00 // Page Select 0
+#define WD_690_PS1 0x40 // Page Select 1
+#define WD_690_PS2 0x80 // Page Select 2
+#define WD_690_PSMASK 0x3F // For masking off the page select bits
+
+
+//
+// Definitions for the 584 board
+//
+
+#define WD_584_EEPROM_0 0x08
+#define WD_584_EEPROM_1 0x09
+#define WD_584_EEPROM_2 0x0A
+#define WD_584_EEPROM_3 0x0B
+#define WD_584_EEPROM_4 0x0C
+#define WD_584_EEPROM_5 0x0D
+#define WD_584_EEPROM_6 0x0E
+#define WD_584_EEPROM_7 0x0F
+
+#define WD_584_OTHER_BIT 0x02
+#define WD_584_ICR_MASK 0x0C
+#define WD_584_EAR_MASK 0x0F
+#define WD_584_ENGR_PAGE 0xA0
+#define WD_584_RLA 0x10
+#define WD_584_EA6 0x80
+#define WD_584_RECALL_DONE 0x10
+
+#define WD_584_ID_EEPROM_OVERRIDE 0x0000FFB0
+#define WD_584_EXTRA_EEPROM_OVERRIDE 0xFFD00000
+
+#define WD_584_EEPROM_MEDIA_MASK 0x07
+#define WD_584_STARLAN_TYPE 0x00
+#define WD_584_ETHERNET_TYPE 0x01
+#define WD_584_TP_TYPE 0x02
+#define WD_584_EW_TYPE 0x03
+
+#define WD_584_EEPROM_IRQ_MASK 0x18
+#define WD_584_PRIMARY_IRQ 0x00
+#define WD_584_ALT_IRQ_1 0x08
+#define WD_584_ALT_IRQ_2 0x10
+#define WD_584_ALT_IRQ_3 0x18
+
+#define WD_584_EEPROM_PAGING_MASK 0xC0
+#define WD_584_EEPROM_RAM_PAGING 0x40
+#define WD_584_EEPROM_ROM_PAGING 0x80
+
+#define WD_584_EEPROM_RAM_SIZE_MASK 0xE0
+#define WD_584_EEPROM_RAM_SIZE_RES1 0x00
+#define WD_584_EEPROM_RAM_SIZE_RES2 0x20
+#define WD_584_EEPROM_RAM_SIZE_8K 0x40
+#define WD_584_EEPROM_RAM_SIZE_16K 0x60
+#define WD_584_EEPROM_RAM_SIZE_32K 0x80
+#define WD_584_EEPROM_RAM_SIZE_64K 0xA0
+#define WD_584_EEPROM_RAM_SIZE_RES3 0xC0
+#define WD_584_EEPROM_RAM_SIZE_RES4 0xE0
+
+#define WD_584_EEPROM_BUS_TYPE_MASK 0x07
+#define WD_584_EEPROM_BUS_TYPE_AT 0x00
+#define WD_584_EEPROM_BUS_TYPE_MCA 0x01
+#define WD_584_EEPROM_BUS_TYPE_EISA 0x02
+
+#define WD_584_EEPROM_BUS_SIZE_MASK 0x18
+#define WD_584_EEPROM_BUS_SIZE_8BIT 0x00
+#define WD_584_EEPROM_BUS_SIZE_16BIT 0x08
+#define WD_584_EEPROM_BUS_SIZE_32BIT 0x10
+#define WD_584_EEPROM_BUS_SIZE_64BIT 0x18
+
+//
+// For the 594 Chip
+//
+
+
+
+//
+// BOARD ID MASK DEFINITIONS
+//
+// 32 Bits of information are returned by 'GetBoardID ()'.
+//
+// The low order 16 bits correspond to the Feature Bits which make
+// up a unique ID for a given class of boards.
+//
+// e.g. STARLAN MEDIA, INTERFACE_CHIP, MICROCHANNEL
+//
+// note: board ID should be ANDed with the STATIC_ID_MASK
+// before comparing to a specific board ID
+//
+//
+// The high order 16 bits correspond to the Extra Bits which do not
+// change the boards ID.
+//
+// e.g. INTERFACE_584_CHIP, 16 BIT SLOT, ALTERNATE IRQ
+//
+
+
+#define STARLAN_MEDIA 0x00000001 /* StarLAN */
+#define ETHERNET_MEDIA 0x00000002 /* Ethernet */
+#define TWISTED_PAIR_MEDIA 0x00000003 /* Twisted Pair */
+#define EW_MEDIA 0x00000004 /* Ethernet and Twisted Pair */
+#define TOKEN_MEDIA 0x00000005 /* Token Ring */
+
+#define MICROCHANNEL 0x00000008 /* MicroChannel Adapter */
+#define INTERFACE_CHIP 0x00000010 /* Soft Config Adapter */
+#define ADVANCED_FEATURES 0x00000020 /* Advance netw interface features */
+#define BOARD_16BIT 0x00000040 /* 16 bit capability */
+#define PAGED_RAM 0x00000080 /* Is there RAM paging? */
+#define PAGED_ROM 0x00000100 /* Is there ROM paging? */
+#define RAM_SIZE_UNKNOWN 0x00000000 /* 000 => Unknown RAM Size */
+#define RAM_SIZE_RESERVED_1 0x00010000 /* 001 => Reserved */
+#define RAM_SIZE_8K 0x00020000 /* 010 => 8k RAM */
+#define RAM_SIZE_16K 0x00030000 /* 011 => 16k RAM */
+#define RAM_SIZE_32K 0x00040000 /* 100 => 32k RAM */
+#define RAM_SIZE_64K 0x00050000 /* 101 => 64k RAM */
+#define RAM_SIZE_RESERVED_6 0x00060000 /* 110 => Reserved */
+#define RAM_SIZE_RESERVED_7 0x00070000 /* 111 => Reserved */
+#define SLOT_16BIT 0x00080000 /* 16 bit board - 16 bit slot */
+#define NIC_690_BIT 0x00100000 /* NIC is 690 */
+#define ALTERNATE_IRQ_BIT 0x00200000 /* Alternate IRQ is used */
+#define INTERFACE_5X3_CHIP 0x00000000 /* 0000 = 583 or 593 chips */
+#define INTERFACE_584_CHIP 0x00400000 /* 0100 = 584 chip */
+#define INTERFACE_594_CHIP 0x00800000 /* 1000 = 594 chip */
+
+#define MEDIA_MASK 0x00000007 /* Isolates Media Type */
+#define RAM_SIZE_MASK 0x00070000 /* Isolates RAM Size */
+#define STATIC_ID_MASK 0x0000FFFF /* Isolates Board ID */
+#define INTERFACE_CHIP_MASK 0x03C00000 /* Isolates Intfc Chip Type */
+
+/* Word definitions for board types */
+
+#define WD8003E ETHERNET_MEDIA
+#define WD8003EBT WD8003E /* functionally identical to WD8003E */
+#define WD8003S STARLAN_MEDIA
+#define WD8003SH WD8003S /* functionally identical to WD8003S */
+#define WD8003WT TWISTED_PAIR_MEDIA
+#define WD8003W (TWISTED_PAIR_MEDIA | INTERFACE_CHIP)
+#define WD8003EB (ETHERNET_MEDIA | INTERFACE_CHIP)
+#define WD8003EP WD8003EB /* with INTERFACE_584_CHIP */
+#define WD8003EW (EW_MEDIA | INTERFACE_CHIP)
+#define WD8003ETA (ETHERNET_MEDIA | MICROCHANNEL)
+#define WD8003STA (STARLAN_MEDIA | MICROCHANNEL)
+#define WD8003EA (ETHERNET_MEDIA | MICROCHANNEL | INTERFACE_CHIP)
+#define WD8003EPA WD8003EA /* with INTERFACE_594_CHIP */
+#define WD8003SHA (STARLAN_MEDIA | MICROCHANNEL | INTERFACE_CHIP)
+#define WD8003WA (TWISTED_PAIR_MEDIA | MICROCHANNEL | INTERFACE_CHIP)
+#define WD8003WPA WD8003WA /* with INTERFACE_594_CHIP */
+#define WD8013EBT (ETHERNET_MEDIA | BOARD_16BIT)
+#define WD8013EB (ETHERNET_MEDIA | BOARD_16BIT | INTERFACE_CHIP)
+#define WD8013W (TWISTED_PAIR_MEDIA | BOARD_16BIT | INTERFACE_CHIP)
+#define WD8013EW (EW_MEDIA | BOARD_16BIT | INTERFACE_CHIP)
diff --git a/private/ntos/ndis/wd/wdlmireg.h b/private/ntos/ndis/wd/wdlmireg.h
new file mode 100644
index 000000000..f20b345fb
--- /dev/null
+++ b/private/ntos/ndis/wd/wdlmireg.h
@@ -0,0 +1,424 @@
+/*++
+
+Copyright (c) 1990 Microsoft Corporation
+
+Module Name:
+
+ wdlmireg.h
+
+Abstract:
+
+ Register definitions and values for the many cards
+
+Author:
+
+ Sean Selitrennikoff (seanse) 15-Jan-92
+
+Environment:
+
+ Kernel mode, FSD
+
+Revision History:
+
+
+--*/
+
+
+
+
+//
+// Microchannel Bus registers
+//
+
+#define CHANNEL_SELECT_REG 0x96
+#define LSB_ID_POS_REG 0x100
+#define MSB_ID_POS_REG 0x101
+#define IO_BASE_POS_REG 0x102
+#define RAM_BASE_POS_REG 0x103
+#define BIOS_ROM_POS_REG 0x104
+#define IRQ_POS_REG 0x105
+
+
+
+//
+// Microchannel 83c593 Registers.
+//
+
+#define MEMORY_ENABLE_RESET_REG 0x00
+#define EEPROM_CONTROL_REG 0x01
+#define BOARD_ID_REG0 0x02
+#define BOARD_ID_REG1 0x03
+#define INTERRUPT_CONTROL_AND_STATUS_REG 0x04
+#define COMMUNICATION_CONTROL_REG 0x05
+#define FIFO_ENTRY_EXIT_REG 0x06
+#define GENERAL_PURPOSE_REG 0x07
+
+
+//
+// Microchannel 83c594 Registers
+
+#define REVISION_REG 0x07
+
+
+
+
+
+
+
+//
+// AT Bus Registers
+//
+
+//
+// 83c583 registers
+//
+
+#define BASE_REG 0x00
+#define MEMORY_SELECT_REG 0x00 // MSR
+#define INTERFACE_CONFIG_REG 0x01 // ICR
+#define BUS_SIZE_REG 0x01 // BSR (read only)
+#define IO_ADDRESS_REG 0x02 // IAR
+#define BIOS_ROM_ADDRESS_REG 0x03 // BIO (583, 584)
+#define EEPROM_ADDRESS_REG 0x03 // EAR (584)
+#define INTERRUPT_REQUEST_REG 0x04 // IRR
+#define GENERAL_PURPOSE_REG1 0x05 // GP1
+#define LA_ADDRESS_REG 0x05 // LAAR (write only)
+#define IO_DATA_LATCH_REG 0x06 // IOD (583)
+#define INITIALIZE_JUMPER_REG 0x06 // IJR (584)
+#define GENERAL_PURPOSE_REG2 0x07 // GP2
+#define LAN_ADDRESS_REG 0x08 // LAR
+#define LAN_ADDRESS_REG2 0x09 // LAR2
+#define LAN_ADDRESS_REG3 0x0A // LAR3
+#define LAN_ADDRESS_REG4 0x0B // LAR4
+#define LAN_ADDRESS_REG5 0x0C // LAR5
+#define LAN_ADDRESS_REG6 0x0D // LAR6
+#define LAN_ADDRESS_REG7 0x0E // LAR7
+#define LAN_ADDRESS_REG8 0x0F // LAR8
+
+
+//
+// 8390 Registers
+//
+
+#define OFF_8390_REG 0x10 // offset of the 8390 chip
+
+// page 0, reading
+
+#define COMMAND_REG OFF_8390_REG + 0x00
+#define DMA_ADDRESS_0_REG OFF_8390_REG + 0x01
+#define DMA_ADDRESS_1_REG OFF_8390_REG + 0x02
+#define BOUNDARY_REG OFF_8390_REG + 0x03
+#define TRANSMIT_STATUS_REG OFF_8390_REG + 0x04
+#define NUM_COLLISIONS_REG OFF_8390_REG + 0x05
+#define FIFO_REG OFF_8390_REG + 0x06
+#define INTERRUPT_STATUS_REG OFF_8390_REG + 0x07
+#define REMOTE_DMA_ADDRESS_0_REG OFF_8390_REG + 0x08
+#define REMOTE_DMA_ADDRESS_1_REG OFF_8390_REG + 0x09
+#define RECEIVE_STATUS_REG OFF_8390_REG + 0x0C
+#define ALIGNMENT_ERROR_REG OFF_8390_REG + 0x0D
+#define CRC_ERROR_REG OFF_8390_REG + 0x0E
+#define MISSED_PACKET_REG OFF_8390_REG + 0x0F
+
+// page 0, writing
+
+#define COMMAND_REG OFF_8390_REG + 0x00
+#define PAGE_START_REG OFF_8390_REG + 0x01
+#define PAGE_STOP_REG OFF_8390_REG + 0x02
+#define TRANSMIT_PAGE_START_REG OFF_8390_REG + 0x04
+#define TRANSMIT_BYTE_COUNT_REG0 OFF_8390_REG + 0x05
+#define TRANSMIT_BYTE_COUNT_REG1 OFF_8390_REG + 0x06
+#define REMOTE_START_ADDRESS_REG0 OFF_8390_REG + 0x08
+#define REMOTE_START_ADDRESS_REG1 OFF_8390_REG + 0x09
+#define REMOTE_BYTE_COUNT_REG0 OFF_8390_REG + 0x0A
+#define REMOTE_BYTE_COUNT_REG1 OFF_8390_REG + 0x0B
+#define RECEIVE_CONFIG_REG OFF_8390_REG + 0x0C
+#define TRANSMIT_CONFIG_REG OFF_8390_REG + 0x0D
+#define DATA_CONFIG_REG OFF_8390_REG + 0x0E
+#define INTERRUPT_MASK_REG OFF_8390_REG + 0x0F
+
+
+// page 1, reading and writing
+
+#define CONTROL_REG OFF_8390_REG + 0x00
+#define PHYSICAL_ADDRESS_REG0 OFF_8390_REG + 0x01
+#define PHYSICAL_ADDRESS_REG1 OFF_8390_REG + 0x02
+#define PHYSICAL_ADDRESS_REG2 OFF_8390_REG + 0x03
+#define PHYSICAL_ADDRESS_REG3 OFF_8390_REG + 0x04
+#define PHYSICAL_ADDRESS_REG4 OFF_8390_REG + 0x05
+#define PHYSICAL_ADDRESS_REG5 OFF_8390_REG + 0x06
+#define CURRENT_BUFFER_REG OFF_8390_REG + 0x07
+#define MULTICAST_ADDRESS_REG0 OFF_8390_REG + 0x08
+#define MULTICAST_ADDRESS_REG1 OFF_8390_REG + 0x09
+#define MULTICAST_ADDRESS_REG2 OFF_8390_REG + 0x0A
+#define MULTICAST_ADDRESS_REG3 OFF_8390_REG + 0x0B
+#define MULTICAST_ADDRESS_REG4 OFF_8390_REG + 0x0C
+#define MULTICAST_ADDRESS_REG5 OFF_8390_REG + 0x0D
+#define MULTICAST_ADDRESS_REG6 OFF_8390_REG + 0x0E
+#define MULTICAST_ADDRESS_REG7 OFF_8390_REG + 0x0F
+
+// page 2, reading and writing
+
+#define BLOCK_ADDRESS_REG OFF_8390_REG + 0x06
+#define ENHANCEMENT_REG OFF_8390_REG + 0x07
+
+
+
+
+
+
+
+
+//
+// Register Bit Definitions
+//
+
+
+
+
+
+//
+// Microchannel Registers
+//
+
+
+
+#define NUMBER_OF_CHANNELS 8
+
+
+#define DISABLE_BIOS 0x02
+#define DISABLE_SETUP 0x00
+#define SELECT_CHANNEL_1 0x08
+#define ADAPTER_ID_MSB 0x6F
+#define ADAPTER_ID_LSB0 0xC0
+#define ADAPTER_ID_LSB1 0xC1
+#define ADAPTER_ID_LSB2 0xC2
+#define ADAPTER_ID_LSB3 0xC3
+#define ADAPTER_ID_LSB4 0xC4
+#define ADAPTER_ID_LSB5 0xC5
+#define ADAPTER_ID_LSB6 0xC6
+
+//
+// BISTRO ID BYTES
+//
+
+#define BISTRO_ID_MSB 0xEF
+#define BISTRO_ID_LSB 0xE5
+#define ALT_BISTRO_ID_LSB 0xD5
+
+
+//
+// COMMUNICATION_CONTROL_REG
+//
+
+#define CCR_INTERRUPT_ENABLE 0x04
+
+
+
+
+
+
+//
+// AT bus Registers
+//
+
+//
+// MSR
+//
+
+#define RESET 0x80 // 1 == reset
+#define MEMORY_ENABLE 0x40 // 1 == enabled
+#define ADDRESS_BIT18 0x20 // Top bits for shared memory address
+#define ADDRESS_BIT17 0x10 // Assume bit 19 == 1
+#define ADDRESS_BIT16 0x08
+#define ADDRESS_BIT15 0x04
+#define ADDRESS_BIT14 0x02
+#define ADDRESS_BIT13 0x01
+
+
+//
+// ICR
+//
+
+#define STORE 0x80 // Store into EEProm
+#define RECALL 0x40 // Recall from EEProm
+#define RECALL_ALL_BUT_IO 0x20 // Recall all but IO and LAN Address
+#define RECALL_LAN 0x10 // Recall LAN Address
+#define MEMORY_SIZE 0x08 // Shared Memory size
+#define DMA_ENABLE 0x04 // DMA Enable (583)
+#define IR2 0x04 // IRQ index MSB (584)
+#define IO_PORT_ENABLE 0x02 // (583)
+#define OTHER 0x02 // (584)
+#define WORD_TRANSFER_SELECT 0x01
+
+
+
+//
+// BIO
+//
+
+#define BIOS_SIZE_BIT1 0x80
+#define BIOS_SIZE_BIT0 0x40
+#define BIOS_ROM_ADDRESS_BIT18 0x20
+#define BIOS_ROM_ADDRESS_BIT17 0x10
+#define BIOS_ROM_ADDRESS_BIT16 0x08
+#define BIOS_ROM_ADDRESS_BIT15 0x04
+#define BIOS_ROM_ADDRESS_BIT14 0x02
+#define W8003_INTERRUPT 0x01
+
+
+//
+// IRR
+//
+
+#define INTERRUPT_ENABLE 0x80
+#define INTERRUPT_REQUEST_BIT1 0x40
+#define INTERRUPT_REQUEST_BIT0 0x20
+#define ALTERNATE_MODE 0x10
+#define ALTERNATE_INTERRUPT 0x08
+#define BIOS_WAIT_STATE_BIT1 0x04
+#define BIOS_WAIT_STATE_BIT0 0x02
+#define ZERO_WAIT_STATE_ENABLE 0x01
+
+
+//
+// BSR
+//
+
+#define BUS_16_BIT 0x01
+
+
+//
+// LAAR
+//
+
+#define MEMORY_16BIT_ENABLE 0x80
+#define LAN_16BIT_ENABLE 0x40
+#define LAAR_ZERO_WAIT_STATE 0x20
+#define LAN_ADDRESS_BIT23 0x10
+#define LAN_ADDRESS_BIT22 0x08
+#define LAN_ADDRESS_BIT21 0x04
+#define LAN_ADDRESS_BIT20 0x02
+#define LAN_ADDRESS_BIT19 0x01
+
+#define LAAR_MASK 0x1F
+#define INIT_LAAR_VALUE 0x01 // To set bit 19 to 1
+
+
+//
+// 8390 Register Bit definitions
+//
+
+//
+// COMMAND_REG
+//
+
+#define STOP 0x01 // software reset
+#define START 0x02
+#define TRANSMIT_PACKET 0x04
+#define READ_0 0x08
+#define READ_1 0x10
+#define READ_2 0x20
+
+#define REMOTE_READ 0x08 // Remote DMA Command
+#define REMOTE_WRITE 0x10 // Remote DMA Command
+#define REMOTE_SEND_PACKET 0x18 // Remote DMA Command
+#define REMOTE_ABORT_COMPLETE 0x20 // Remote DMA Command
+
+#define PAGE_SELECT_0 0x00
+#define PAGE_SELECT_1 0x40
+#define PAGE_SELECT_2 0x80
+
+#define PAGE_SELECT_0_START 0x22
+#define PAGE_SELECT_1_START 0x62
+#define PAGE_SELECT_2_START 0xA2
+
+//
+// INTERRUPT_STATUS_REG
+//
+
+#define PACKET_RECEIVED_NO_ERROR 0x01
+#define PACKET_TRANSMITTED_NO_ERROR 0x02
+#define RECEIVE_ERROR 0x04
+#define TRANSMIT_ERROR 0x08
+#define OVERWRITE_WARNING 0x10
+#define ISR_COUNTER_OVERFLOW 0x20
+#define REMOTE_DMA_COMPLETE 0x40
+#define RESET_DONE 0x80
+
+
+
+//
+// INTERRUPT_MASK_REG
+//
+
+#define PACKET_RECEIVE_ENABLE 0x01
+#define PACKET_TRANSMIT_ENABLE 0x02
+#define RECEIVE_ERROR_ENABLE 0x04
+#define TRANSMIT_ERROR_ENABLE 0x08
+#define OVERWRITE_WARNING_ENABLE 0x10
+#define COUNTER_OVERFLOW_ENABLE 0x20
+#define REMOTE_DMA_COMPLETE_ENABLE 0x40
+
+
+//
+// DATA_CONFIG_REG
+//
+
+#define WORD_TRANSFER_SELECT 0x01
+#define BYTE_ORDER_SELECT 0x02
+#define LONG_ADDRESS_SELECT 0x04
+#define BURST_DMA_SELECT 0x08
+#define AUTO_INITIALIZE_REMOTE 0x10
+#define RECEIVE_FIFO_THRESHOLD_2 0x00
+#define RECEIVE_FIFO_THRESHOLD_4 0x20
+#define RECEIVE_FIFO_THRESHOLD_8 0x40
+#define RECEIVE_FIFO_THRESHOLD_12 0x80
+
+//
+// TRANSMIT_CONFIG_REG
+//
+
+#define MANUAL_CRC_GENERATION 0x01
+#define LOOPBACK_MODE1 0x02 // mode 1, no loopback
+#define LOOPBACK_MODE2 0x04 // mode 2, loopback
+#define LOOPBACK_MODE3 0x06 // mode 3, no loopback
+#define AUTO_TRANSMIT_DISABLE 0x08
+#define COLLISION_OFFSET_ENABLE 0x10
+
+//
+// TRANSMIT_STATUS_REG
+//
+
+#define TRANSMIT_NO_ERROR 0x01
+#define TRANSMIT_COLLISION 0x04
+#define TRANSMIT_ABORT 0x08
+#define TRANSMIT_LOST_CARRIER 0x10
+#define TRANSMIT_FIFO_UNDERRUN 0x20
+#define TRANSMIT_HEARTBEAT 0x40
+#define TRANSMIT_OUT_OF_WINDOW 0x80
+
+
+//
+// RECEIVE_CONFIG_REG
+//
+
+#define SAVE_ERROR_PACKETS 0x01
+#define SAVE_RUNT_PACKETS 0x02
+#define SAVE_BROADCAST_PACKETS 0x04
+#define SAVE_MULTICAST_PACKETS 0x08
+#define PROMISCUOUS_MODE 0x10
+#define MONITOR_MODE 0x20
+
+//
+// RECEIVE_STATUS_REG
+
+#define RECEIVE_NO_ERROR 0x01
+#define RECEIVE_CRC_ERROR 0x02
+#define RECEIVE_ALIGNMENT_ERROR 0x04
+#define RECEIVE_FIFO_UNDERRUN 0x08
+#define RECEIVE_MISSED_PACKET 0x10
+#define RECEIVE_PHYSICAL_ADDRESS 0x20
+#define RECEIVE_DISABLED 0x40
+#define RECEIVE_DEFERRING 0x80
+
+
diff --git a/private/ntos/ndis/wd/wdsft.h b/private/ntos/ndis/wd/wdsft.h
new file mode 100644
index 000000000..3ea3f8d17
--- /dev/null
+++ b/private/ntos/ndis/wd/wdsft.h
@@ -0,0 +1,852 @@
+/*++
+
+Copyright (c) 1990 Microsoft Corporation
+
+Module Name:
+
+ wdsft.h
+
+Abstract:
+
+ The main header for an Western Digital MAC driver.
+
+Author:
+
+ Anthony V. Ercolano (tonye) creation-date 19-Jun-1990 (Driver Model)
+
+ Sean Selitrennikoff (seanse) original WD code.
+
+Environment:
+
+ This driver is expected to work in DOS, OS2 and NT at the equivalent
+ of kernal mode.
+
+ Architecturally, there is an assumption in this driver that we are
+ on a little endian machine.
+
+Notes:
+
+ optional-notes
+
+Revision History:
+
+
+--*/
+
+#ifndef _WDSFT_
+#define _WDSFT_
+
+#define WD_NDIS_MAJOR_VERSION 3
+#define WD_NDIS_MINOR_VERSION 0
+
+//
+// This macro is used along with the flags to selectively
+// turn on debugging.
+//
+
+#if DBG
+
+#define IF_WDDEBUG(f) if (WdDebugFlag & (f))
+
+extern ULONG WdDebugFlag;
+
+#define WD_DEBUG_LOUD 0x00000001 // debugging info
+#define WD_DEBUG_VERY_LOUD 0x00000002 // excessive debugging info
+#define WD_DEBUG_LOG 0x00000004 // enable WdLog
+#define WD_DEBUG_CHECK_DUP_SENDS 0x00000008 // check for duplicate sends
+#define WD_DEBUG_TRACK_PACKET_LENS 0x00000010 // track directed packet lens
+#define WD_DEBUG_WORKAROUND1 0x00000020 // drop DFR/DIS packets
+#define WD_DEBUG_CARD_BAD 0x00000040 // dump data if CARD_BAD
+#define WD_DEBUG_CARD_TESTS 0x00000080 // print reason for failing
+
+
+
+//
+// Macro for deciding whether to dump lots of debugging information.
+//
+
+#define IF_LOUD(A) IF_WDDEBUG( WD_DEBUG_LOUD ) { A }
+#define IF_VERY_LOUD(A) IF_WDDEBUG( WD_DEBUG_VERY_LOUD ) { A }
+
+#else
+
+#define IF_LOUD(A)
+#define IF_VERY_LOUD(A)
+
+#endif
+
+
+//
+// Macros for services that differ between DOS and NT, we may consider adding these
+// into the NDIS spec.
+//
+
+
+//
+// controls the number of transmit buffers on the packet.
+// Choices are 1 or 2.
+//
+
+#define DEFAULT_NUMBUFFERS 2
+
+
+//
+// Macros for moving memory around
+//
+
+#define WD_MOVE_MEM(dest,src,size) NdisMoveMemory(dest,src,size)
+#define WD_MOVE_MEM_TO_SHARED_RAM(dest,src,size) NdisMoveToMappedMemory(dest,src,size)
+#define WD_MOVE_SHARED_RAM_TO_MEM(dest,src,size) NdisMoveFromMappedMemory(dest,src,size)
+
+#define WD_MOVE_DWORD_TO_SHARED_RAM(dest,src) NdisWriteRegisterUlong((PULONG)(dest),(ULONG)(src))
+#define WD_MOVE_SHARED_RAM_TO_DWORD(dest,src) NdisReadRegisterUlong((PULONG)(src),(PULONG)(dest))
+
+#define WD_MOVE_UCHAR_TO_SHARED_RAM(dest,src) NdisWriteRegisterUchar((PUCHAR)(dest),(UCHAR)(src))
+#define WD_MOVE_SHARED_RAM_TO_UCHAR(dest,src) NdisReadRegisterUchar((PUCHAR)(src),(PUCHAR)(dest))
+
+#define WD_MOVE_USHORT_TO_SHARED_RAM(dest,src) NdisWriteRegisterUshort((PUSHORT)(dest),(USHORT)(src))
+#define WD_MOVE_SHARED_RAM_TO_USHORT(dest,src) NdisReadRegisterUshort((PUSHORT)(src),(PUSHORT)(dest))
+
+
+
+
+//
+// A broadcast address (for comparing with other addresses).
+//
+
+extern UCHAR WdBroadcastAddress[];
+
+
+//
+// Number of bytes in an ethernet header
+//
+
+#define WD_HEADER_SIZE 14
+
+
+//
+// Number of bytes allowed in a lookahead (max)
+//
+
+#define WD_MAX_LOOKAHEAD (252 - WD_HEADER_SIZE)
+
+
+//
+// Buffer page size - WD MUST BE 256!!! Internal counters on the card
+// depend on it.
+//
+
+#define WD_BUFFER_PAGE_SIZE 256
+
+
+//
+// Only have one of these structures.
+//
+
+typedef struct _MAC_BLOCK {
+
+ //
+ // NDIS wrapper information.
+ //
+
+ NDIS_HANDLE NdisMacHandle; // returned from NdisRegisterMac
+ NDIS_HANDLE NdisWrapperHandle; // returned from NdisInitializeWrapper
+ NDIS_MAC_CHARACTERISTICS MacCharacteristics;
+
+ //
+ // Adapters registered for this MAC.
+ //
+
+ UINT NumAdapters;
+ struct _WD_ADAPTER * AdapterQueue;
+ NDIS_SPIN_LOCK SpinLock; // guards NumAdapter and AdapterQueue
+
+ //
+ // driver object.
+ //
+
+ PDRIVER_OBJECT DriverObject;
+
+ BOOLEAN Unloading;
+
+} MAC_BLOCK, * PMAC_BLOCK;
+
+
+
+
+
+
+//
+// One of these structures per adapter registered.
+//
+
+typedef struct _WD_ADAPTER {
+
+ //
+ // Adapter structure for LMI.
+ // This must occur first in the adapter structure.
+ //
+
+ Adapter_Struc LMAdapter;
+
+ //
+ // Spin lock for adapter structure
+ //
+ NDIS_SPIN_LOCK Lock;
+
+
+ //
+ // Links with our MAC.
+ //
+
+ PMAC_BLOCK MacBlock;
+ struct _WD_ADAPTER * NextAdapter; // used by MacBlock->OpenQueue
+
+ //
+ // Opens for this adapter.
+ //
+
+ struct _WD_OPEN * OpenQueue;
+
+
+ //
+ // Number of references to the adapter.
+ //
+ ULONG References;
+
+ UINT MulticastListMax;
+
+ //
+ // Transmit queue.
+ //
+
+ PNDIS_PACKET XmitQueue; // packets waiting to be transmitted
+ PNDIS_PACKET XmitQTail;
+
+ PNDIS_PACKET PacketsOnCard; // List of packets that the card is
+ // is currently transmitting
+ PNDIS_PACKET PacketsOnCardTail;
+
+ //
+ // Loopback queue;
+ //
+
+ PNDIS_PACKET LoopbackQueue; // directed packets waiting to be received
+ PNDIS_PACKET LoopbackQTail;
+ PNDIS_PACKET IndicatingPacket;
+ BOOLEAN IndicatedAPacket;
+
+ //
+ // These are for the current packet being indicated.
+ //
+
+ UCHAR PacketHeader[4]; // the NIC appended header
+ UINT PacketLen; // the overall length of the packet
+
+
+
+ //
+ // Statistics used by Set/QueryInformation.
+ //
+
+ ULONG FramesXmitGood; // Good Frames Transmitted
+ ULONG FramesRcvGood; // Good Frames Received
+
+ ULONG FramesXmitBad; // Bad Frames Transmitted
+ ULONG FramesXmitOneCollision; // Frames Transmitted with one collision
+ ULONG FramesXmitManyCollisions; // Frames Transmitted with > 1 collision
+ ULONG FramesXmitDeferred; // Frames where xmit was deferred
+ ULONG FramesXmitOverWrite; // Frames where xmit was overwritten
+ ULONG FramesXmitHeartbeat; // Frames lost heartbeat
+ ULONG FramesXmitUnderruns; // Frames where FIFO underran
+
+ ULONG FrameAlignmentErrors; // FAE errors counted
+ ULONG CrcErrors; // CRC errors counted
+ ULONG MissedPackets; // missed packet counted
+ ULONG TooBig; // received packets too large counted
+ ULONG Overruns; // received packets with FIFO overrun
+
+ //
+ // Reset information.
+ //
+
+ BOOLEAN HardwareFailure; // Did the hardware fail in some way
+ BOOLEAN ResetRequested; // TRUE if a reset is needed
+ BOOLEAN ResetInProgress; // TRUE if a reset is in progress
+ struct _WD_OPEN * ResetOpen; // who called WdReset
+
+ UINT ByteToWrite; // temp storage
+
+
+ //
+ // Look Ahead information.
+ //
+
+ ULONG MaxLookAhead;
+
+
+ //
+ // Handling deferred events
+ //
+
+ NDIS_TIMER DeferredTimer;
+ PVOID DeferredDpc;
+
+ UCHAR LookAhead[WD_MAX_LOOKAHEAD + WD_HEADER_SIZE];
+
+ BOOLEAN Removed;
+
+ //
+ // For handling missing interrupts (caused by user mis-configs)
+ //
+
+ PVOID WakeUpDpc;
+ NDIS_TIMER WakeUpTimer;
+ BOOLEAN WakeUpTimeout;
+ UCHAR WakeUpErrorCount;
+
+ BOOLEAN ProcessingDpc;
+} WD_ADAPTER, * PWD_ADAPTER;
+
+
+
+
+//
+// Given a MacBindingHandle this macro returns a pointer to the
+// WD_ADAPTER.
+//
+#define PWD_ADAPTER_FROM_BINDING_HANDLE(Handle) \
+ (((PWD_OPEN)(Handle))->Adapter)
+
+//
+// Given a MacContextHandle return the PWD_ADAPTER
+// it represents.
+//
+#define PWD_ADAPTER_FROM_CONTEXT_HANDLE(Handle) \
+ ((PWD_ADAPTER)(Handle))
+
+//
+// Given a pointer to a WD_ADAPTER return the
+// proper MacContextHandle.
+//
+#define CONTEXT_HANDLE_FROM_PWD_ADAPTER(Ptr) \
+ ((NDIS_HANDLE)(Ptr))
+
+
+//
+// Given a pointer to a WD_ADAPTER, return the
+// pointer to the LMAdapter.
+//
+#define Ptr_Adapter_Struc_FROM_PWD_ADAPTER(P)\
+ (&((P)->LMAdapter))
+
+//
+// Given a pointer to a LMAdapter, return the
+// pointer to the WD_ADAPTER.
+//
+#define PWD_ADAPTER_FROM_Ptr_Adapter_Struc(P)\
+ ((PWD_ADAPTER)(P))
+
+
+
+
+//
+// Macros to extract high and low bytes of a word.
+//
+
+#define MSB(Value) ((UCHAR)(((Value) >> 8) & 0xff))
+#define LSB(Value) ((UCHAR)((Value) & 0xff))
+
+
+//
+// One of these per open on an adapter.
+//
+
+typedef struct _WD_OPEN {
+
+ //
+ // NDIS wrapper information.
+ //
+
+ NDIS_HANDLE NdisBindingContext; // passed to MacOpenAdapter
+ PSTRING AddressingInformation; // not used currently
+
+ //
+ // Links to our adapter.
+ //
+
+ PWD_ADAPTER Adapter;
+ struct _WD_OPEN * NextOpen;
+
+ //
+ // Links to our MAC.
+ //
+
+ PMAC_BLOCK MacBlock; // faster than using AdapterBlock->MacBlock
+
+
+ //
+ // Handle of this adapter in the filter database.
+ //
+ NDIS_HANDLE NdisFilterHandle;
+
+ //
+ // Indication information
+ //
+
+ UINT LookAhead;
+
+ //
+ // Reset/Close information.
+ //
+
+ UINT ReferenceCount; // number of reasons this open can't close
+ BOOLEAN Closing; // is a close pending
+
+ NDIS_REQUEST CloseFilterRequest; // Holds Requests for pending close op
+ NDIS_REQUEST CloseAddressRequest;// Holds Requests for pending close op
+
+ UINT ProtOptionFlags;
+
+} WD_OPEN, * PWD_OPEN;
+
+
+//
+// This macro returns a pointer to a PWD_OPEN given a MacBindingHandle.
+//
+#define PWD_OPEN_FROM_BINDING_HANDLE(Handle) \
+ ((PWD_OPEN)(Handle))
+
+//
+// This macro returns a NDIS_HANDLE from a PWD_OPEN
+//
+#define BINDING_HANDLE_FROM_PWD_OPEN(Open) \
+ ((NDIS_HANDLE)(Open))
+
+
+
+
+
+//
+// What we map into the reserved section of a packet.
+// Cannot be more than 16 bytes (see ASSERT in wd.c).
+//
+
+typedef struct _MAC_RESERVED {
+ PNDIS_PACKET NextPacket; // used to link in the queues (4 bytes)
+ PWD_OPEN Open; // open that called WdSend (4 bytes)
+ BOOLEAN Loopback; // is this a loopback packet (1 byte)
+ BOOLEAN Directed; // is this a directed packet (1 byte)
+} MAC_RESERVED, * PMAC_RESERVED;
+
+
+//
+// These appear in the status field of MAC_RESERVED; they are
+// used because there is not enough room for a full NDIS_HANDLE.
+//
+
+#define RESERVED_SUCCESS ((USHORT)0)
+#define RESERVED_FAILURE ((USHORT)1)
+
+
+//
+// Retrieve the MAC_RESERVED structure from a packet.
+//
+
+#define RESERVED(Packet) ((PMAC_RESERVED)((Packet)->MacReserved))
+
+
+//
+// Procedures which log errors.
+//
+
+typedef enum _WD_PROC_ID {
+ openAdapter,
+ cardReset,
+ cardCopyDownPacket,
+ cardCopyDownBuffer,
+ cardCopyUp
+} WD_PROC_ID;
+
+
+#define WD_ERRMSG_CARD_SETUP (ULONG)0x01
+#define WD_ERRMSG_DATA_PORT_READY (ULONG)0x02
+#define WD_ERRMSG_MAX_OPENS (ULONG)0x03
+
+
+
+
+
+//
+// This macro will act a "epilogue" to every routine in the
+// *interface*. It will check whether any requests need
+// to defer their processing. It will also decrement the reference
+// count on the adapter. If the reference count is zero and there
+// is deferred work to do it will insert the interrupt processing
+// routine in the DPC queue.
+//
+// Note that we don't need to include checking for blocked receives
+// since blocked receives imply that there will eventually be an
+// interrupt.
+//
+// NOTE: This macro assumes that it is called with the lock acquired.
+//
+//
+#define WD_DO_DEFERRED(Adapter) \
+{ \
+ PWD_ADAPTER _A = (Adapter); \
+ _A->References--; \
+ if ((!_A->References) && \
+ ((_A->ResetRequested && (!_A->ProcessingDpc)) || \
+ ((_A->LoopbackQueue != NULL) && (!_A->ProcessingDpc)))) \
+ {\
+ NdisReleaseSpinLock(&_A->Lock); \
+ NdisSetTimer(&_A->DeferredTimer, 0);\
+ } else { \
+ NdisReleaseSpinLock(&_A->Lock); \
+ } \
+}
+
+
+
+
+//
+// Declarations for functions in wd.c.
+//
+
+NDIS_STATUS
+WdRegisterAdapter(
+ IN PWD_ADAPTER Adapter,
+ IN UINT NumBuffers,
+ IN UINT MulticastListMax,
+ IN UCHAR NodeAddress[ETH_LENGTH_OF_ADDRESS]
+ );
+
+
+BOOLEAN
+WdInterruptHandler(
+ IN PVOID ServiceContext // will be a pointer to the adapter block
+ );
+
+VOID
+WdInterruptDpc(
+ IN PVOID SystemSpecific1,
+ IN PVOID InterruptContext,
+ IN PVOID SystemSpecific2,
+ IN PVOID SystemSpecific3
+ );
+
+NDIS_STATUS
+WdOpenAdapter(
+ OUT PNDIS_STATUS OpenErrorStatus,
+ OUT NDIS_HANDLE * MacBindingHandle,
+ OUT PUINT SelectedMediumIndex,
+ IN PNDIS_MEDIUM MediumArray,
+ IN UINT MediumArraySize,
+ IN NDIS_HANDLE NdisBindingContext,
+ IN NDIS_HANDLE MacAdapterContext,
+ IN UINT OpenOptions,
+ IN PSTRING AddressingInformation OPTIONAL
+ );
+
+
+NDIS_STATUS
+WdCloseAdapter(
+ IN NDIS_HANDLE MacBindingHandle
+ );
+
+
+BOOLEAN
+WdAddReference(
+ IN PWD_OPEN OpenP
+ );
+
+
+#define WdRemoveReference(_Open) \
+{ \
+ PWD_ADAPTER _Adapter = _Open->Adapter; \
+ PWD_OPEN _TmpOpen = _Open; \
+ --_TmpOpen->ReferenceCount; \
+ if (_TmpOpen->ReferenceCount == 0) { \
+ if (_TmpOpen == _Adapter->OpenQueue) { \
+ _Adapter->OpenQueue = _TmpOpen->NextOpen; \
+ } else { \
+ _TmpOpen = _Adapter->OpenQueue; \
+ while (_TmpOpen->NextOpen != _Open) { \
+ _TmpOpen = _TmpOpen->NextOpen; \
+ } \
+ _TmpOpen->NextOpen = _Open->NextOpen; \
+ _TmpOpen = _Open; \
+ } \
+ if (_TmpOpen->LookAhead == _Adapter->MaxLookAhead) {\
+ WdAdjustMaxLookAhead(_Adapter); \
+ } \
+ NdisReleaseSpinLock(&_Adapter->Lock); \
+ NdisCompleteCloseAdapter (_TmpOpen->NdisBindingContext, NDIS_STATUS_SUCCESS); \
+ NdisFreeMemory(_TmpOpen, sizeof(WD_OPEN), 0); \
+ NdisAcquireSpinLock(&_Adapter->Lock); \
+ if (_Adapter->OpenQueue == NULL) { \
+ NdisSynchronizeWithInterrupt( \
+ &(_Adapter->LMAdapter.NdisInterrupt), \
+ (PVOID)WdSyncCloseAdapter, \
+ (PVOID)(&(_Adapter->LMAdapter)) \
+ ); \
+ } \
+ } \
+}
+
+VOID
+WdAdjustMaxLookAhead(
+ IN PWD_ADAPTER Adapter
+ );
+
+NDIS_STATUS
+WdReset(
+ IN NDIS_HANDLE MacBindingHandle
+ );
+
+NDIS_STATUS
+WdRequest(
+ IN NDIS_HANDLE MacBindingHandle,
+ IN PNDIS_REQUEST NdisRequest
+ );
+
+NDIS_STATUS
+WdQueryInformation(
+ IN PWD_ADAPTER Adapter,
+ IN PWD_OPEN Open,
+ IN PNDIS_REQUEST NdisRequest
+ );
+
+NDIS_STATUS
+WdSetInformation(
+ IN PWD_ADAPTER Adapter,
+ IN PWD_OPEN Open,
+ IN PNDIS_REQUEST NdisRequest
+ );
+
+NDIS_STATUS
+WdSetMulticastAddresses(
+ IN PWD_ADAPTER Adapter,
+ IN PWD_OPEN Open,
+ IN PNDIS_REQUEST NdisRequest,
+ IN UINT NumAddresses,
+ IN CHAR AddressList[][ETH_LENGTH_OF_ADDRESS]
+ );
+
+NDIS_STATUS
+WdSetPacketFilter(
+ IN PWD_ADAPTER Adapter,
+ IN PWD_OPEN Open,
+ IN PNDIS_REQUEST NdisRequest,
+ IN UINT PacketFilter
+ );
+
+NDIS_STATUS
+WdQueryGlobalStatistics(
+ IN NDIS_HANDLE MacBindingHandle,
+ IN PNDIS_REQUEST NdisRequest
+ );
+
+VOID
+WdUnload(
+ IN NDIS_HANDLE MacMacContext
+ );
+
+NDIS_STATUS
+WdAddAdapter(
+ IN NDIS_HANDLE NdisMacContext,
+ IN NDIS_HANDLE ConfigurationHandle,
+ IN PNDIS_STRING AdaptName
+ );
+
+VOID
+WdRemoveAdapter(
+ IN PVOID MacAdapterContext
+ );
+
+VOID
+WdInterruptDpc(
+ IN PVOID SystemSpecific1,
+ IN PVOID InterruptContext,
+ IN PVOID SystemSpecific2,
+ IN PVOID SystemSpecific3
+ );
+
+NDIS_STATUS
+WdChangeMulticastAddresses(
+ IN UINT OldFilterCount,
+ IN CHAR OldAddresses[][ETH_LENGTH_OF_ADDRESS],
+ IN UINT NewFilterCount,
+ IN CHAR NewAddresses[][ETH_LENGTH_OF_ADDRESS],
+ IN NDIS_HANDLE MacBindingHandle,
+ IN PNDIS_REQUEST NdisRequest,
+ IN BOOLEAN Set
+ );
+
+NDIS_STATUS
+WdChangeFilterClasses(
+ IN UINT OldFilterClasses,
+ IN UINT NewFilterClasses,
+ IN NDIS_HANDLE MacBindingHandle,
+ IN PNDIS_REQUEST NdisRequest,
+ IN BOOLEAN Set
+ );
+
+
+VOID
+WdCloseAction(
+ IN NDIS_HANDLE MacBindingHandle
+ );
+
+
+UINT
+WdPacketSize(
+ IN PNDIS_PACKET Packet
+ );
+
+
+INDICATE_STATUS
+WdIndicatePacket(
+ IN PWD_ADAPTER Adapter
+ );
+
+
+NDIS_STATUS
+WdTransferData(
+ IN NDIS_HANDLE MacBindingHandle,
+ IN NDIS_HANDLE MacReceiveContext,
+ IN UINT ByteOffset,
+ IN UINT BytesToTransfer,
+ OUT PNDIS_PACKET Packet,
+ OUT PUINT BytesTransferred
+ );
+
+
+BOOLEAN
+WdReceiveEvents(
+ IN PWD_ADAPTER Adapter
+ );
+
+BOOLEAN
+WdReceiveEventsDpc(
+ IN PVOID SystemSpecific1,
+ IN PVOID Context,
+ IN PVOID SystemSpecific2,
+ IN PVOID SystemSpecific3
+ );
+
+VOID
+WdTransmitEvents(
+ IN PWD_ADAPTER Adapter
+ );
+
+NDIS_STATUS
+WdSend(
+ IN NDIS_HANDLE MacBindingHandle,
+ IN PNDIS_PACKET Packet
+ );
+
+UINT
+WdCompareMemory(
+ IN PUCHAR String1,
+ IN PUCHAR String2,
+ IN UINT Length
+ );
+
+VOID
+WdSetLoopbackFlag(
+ IN PWD_ADAPTER Adapter,
+ IN PWD_OPEN Open,
+ IN OUT PNDIS_PACKET Packet
+ );
+
+VOID
+WdIndicateLoopbackPacket(
+ IN PWD_ADAPTER Adapter,
+ IN PNDIS_PACKET Packet
+ );
+
+BOOLEAN
+WdSyncCloseAdapter(
+ IN PVOID Context
+ );
+
+BOOLEAN
+WdSyncSend(
+ IN PVOID Context
+ );
+
+BOOLEAN
+WdSyncSetMulticastAddress(
+ IN PVOID Context
+ );
+
+VOID
+WdWakeUpDpc(
+ IN PVOID SystemSpecific1,
+ IN PVOID Context,
+ IN PVOID SystemSpecific2,
+ IN PVOID SystemSpecific3
+ );
+
+//++
+//
+// VOID
+// AddRefWhileHoldingSpinLock(
+// IN PWD_ADAPTER Adapter,
+// IN PWD_OPEN OpenP
+// )
+//
+// Routine Description:
+//
+// Adds a reference to an open. Similar to AddReference, but
+// called with Adapter->Lock held.
+//
+// Arguments:
+//
+// Adapter - The adapter block of OpenP.
+// OpenP - The open block that is being referenced.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+#define AddRefWhileHoldingSpinLock(Adapter, OpenP) { \
+ ++((OpenP)->ReferenceCount); \
+}
+
+
+
+//++
+//
+// BOOLEAN
+// WdAddressEqual(
+// IN UCHAR Address1[ETH_LENGTH_OF_ADDRESS],
+// IN UCHAR Address2[ETH_LENGTH_OF_ADDRESS]
+// )
+//
+// Routine Description:
+//
+// Compares two Ethernet addresses.
+//
+// Arguments:
+//
+// Address1 - The first address.
+// Address2 - The second address.
+//
+// Return Value:
+//
+// TRUE if the addresses are equal.
+// FALSE if they are not.
+//
+//--
+
+#define WdAddressEqual(Address1, Address2) \
+ ((Address1)[4] == (Address2)[4] && \
+ WdCompareMemory((Address1), (Address2), ETH_LENGTH_OF_ADDRESS) == 0)
+
+
+#endif // WdSFT
diff --git a/private/ntos/ndis/wd/wdumi.h b/private/ntos/ndis/wd/wdumi.h
new file mode 100644
index 000000000..60f752e73
--- /dev/null
+++ b/private/ntos/ndis/wd/wdumi.h
@@ -0,0 +1,45 @@
+/*++
+
+Copyright (c) 1990 Microsoft Corporation
+
+Module Name:
+
+ wdlmi.h
+
+Abstract:
+
+ Upper MAC Interface functions for the NDIS 3.0 Western Digital driver.
+
+Author:
+
+ Sean Selitrennikoff (seanse) 15-Jan-92
+n
+Environment:
+
+ Kernel mode, FSD
+
+Revision History:
+
+
+--*/
+
+
+
+#define UM_Delay(A) NdisStallExecution(A)
+
+#define UM_Interrupt(A) (SUCCESS)
+
+extern
+LM_STATUS
+UM_Send_Complete(
+ LM_STATUS Status,
+ Ptr_Adapter_Struc Adapt
+ );
+
+extern
+LM_STATUS
+UM_Receive_Packet(
+ ULONG PacketSize,
+ Ptr_Adapter_Struc Adapt
+ );
+