diff options
Diffstat (limited to 'private/ntos/ndis/wd')
-rw-r--r-- | private/ntos/ndis/wd/keywords.h | 54 | ||||
-rw-r--r-- | private/ntos/ndis/wd/lmi.c | 5854 | ||||
-rw-r--r-- | private/ntos/ndis/wd/makefile | 6 | ||||
-rw-r--r-- | private/ntos/ndis/wd/sources | 44 | ||||
-rw-r--r-- | private/ntos/ndis/wd/umi.c | 347 | ||||
-rw-r--r-- | private/ntos/ndis/wd/wd.c | 4599 | ||||
-rw-r--r-- | private/ntos/ndis/wd/wdhrd.h | 915 | ||||
-rw-r--r-- | private/ntos/ndis/wd/wdlan.rc | 39 | ||||
-rw-r--r-- | private/ntos/ndis/wd/wdlmi.h | 865 | ||||
-rw-r--r-- | private/ntos/ndis/wd/wdlmireg.h | 424 | ||||
-rw-r--r-- | private/ntos/ndis/wd/wdsft.h | 852 | ||||
-rw-r--r-- | private/ntos/ndis/wd/wdumi.h | 45 |
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 + ); + |