summaryrefslogtreecommitdiffstats
path: root/private/ntos/ndis/wd/lmi.c
diff options
context:
space:
mode:
authorAdam <you@example.com>2020-05-17 05:51:50 +0200
committerAdam <you@example.com>2020-05-17 05:51:50 +0200
commite611b132f9b8abe35b362e5870b74bce94a1e58e (patch)
treea5781d2ec0e085eeca33cf350cf878f2efea6fe5 /private/ntos/ndis/wd/lmi.c
downloadNT4.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.c5854
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);
+}
+