diff options
author | Adam <you@example.com> | 2020-05-17 05:51:50 +0200 |
---|---|---|
committer | Adam <you@example.com> | 2020-05-17 05:51:50 +0200 |
commit | e611b132f9b8abe35b362e5870b74bce94a1e58e (patch) | |
tree | a5781d2ec0e085eeca33cf350cf878f2efea6fe5 /private/ntos/ndis/wd/lmi.c | |
download | NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.gz NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.bz2 NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.lz NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.xz NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.zst NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.zip |
Diffstat (limited to 'private/ntos/ndis/wd/lmi.c')
-rw-r--r-- | private/ntos/ndis/wd/lmi.c | 5854 |
1 files changed, 5854 insertions, 0 deletions
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); +} + |