diff options
Diffstat (limited to '')
-rw-r--r-- | private/ntos/ndis/elnkii.new/card.c | 3155 |
1 files changed, 3155 insertions, 0 deletions
diff --git a/private/ntos/ndis/elnkii.new/card.c b/private/ntos/ndis/elnkii.new/card.c new file mode 100644 index 000000000..cbbfd6d60 --- /dev/null +++ b/private/ntos/ndis/elnkii.new/card.c @@ -0,0 +1,3155 @@ +/*++ + +Copyright (c) 1990 Microsoft Corporation + +Module Name: + + card.c + +Abstract: + + Card-specific functions for the NDIS 3.0 Etherlink II driver. + +Author: + + Adam Barr (adamba) 30-Jul-1990 + +Environment: + + Kernel mode, FSD + +Revision History: + + Adam Barr (adamba) 28-Aug-1990 + - moved the SyncXXX() functions to sync.c + + +--*/ + +#include <ndis.h> +#include "elnkhrd.h" +#include "elnksft.h" + + +// +// The amount of data to transfer in one programmed I/O burst +// (should be 8 or 16). +// + +#define DMA_BURST_SIZE 16 + +#if DBG +UCHAR PrevBurstSize = 0; +UCHAR PrevPrevBurstSize = 0; +#endif + + +// +// Array to hold multicast address list. +// + +CHAR Addresses[DEFAULT_MULTICASTLISTMAX][ETH_LENGTH_OF_ADDRESS] = {0}; + + + +#pragma NDIS_INIT_FUNCTION(CardGetMemBaseAddr) + +PUCHAR CardGetMemBaseAddr( + IN PELNKII_ADAPTER pAdapter, + OUT PBOOLEAN pfCardPresent, + OUT PBOOLEAN pfIoBaseCorrect +) + +/*++ + +Routine Description: + + Checks that the I/O base address is correct and returns + the memory base address. For cards that are not set up + for memory mapped mode, it will only check the I/O base + address, and return NULL if it is not correct. + +Arguments: + + pAdapter - pointer to the adapter block. + + CardPresent - Returns FALSE if the card does not appear + to be present in the machine. + + IoBaseCorrect - Returns TRUE if the jumper matches the + configured I/O base address. + +Return Value: + + The memory base address for memory mapped systems. + +--*/ + +{ + static PVOID IoBases[] = { (PVOID)0x2e0, (PVOID)0x2a0, + (PVOID)0x280, (PVOID)0x250, + (PVOID)0x350, (PVOID)0x330, + (PVOID)0x310, (PVOID)0x300 }; + static PVOID MemBases[] = { (PVOID)0xc8000, (PVOID)0xcc000, + (PVOID)0xd8000, (PVOID)0xdc000 }; + UCHAR BaseConfig; + UCHAR Tmp; + UCHAR MemConfig; + + + // + // Read in the Base Configuration Register. + // + NdisRawReadPortUchar(pAdapter->MappedGaBaseAddr + GA_IO_BASE, &Tmp); + + // + // Make sure that only one bit in Tmp is on. + // + if ((Tmp != 0) && ((Tmp & (Tmp - 1)) == 0)) + { + *pfCardPresent = TRUE; + } + else + { + *pfCardPresent = FALSE; + + return(NULL); + } + + // + // Make sure the correct bit is on for pAdapter->IoBaseAddr. + // + BaseConfig = 0; + + while (!(Tmp & 1)) + { + Tmp >>= 1; + + ++BaseConfig; + + if (BaseConfig == 8) + return(NULL); + } + + if (IoBases[BaseConfig] != pAdapter->IoBaseAddr) + { + // + // Probably the jumper is wrong. + // + *pfIoBaseCorrect = FALSE; + + return(NULL); + + } + else + { + *pfIoBaseCorrect = TRUE; + } + + // + // For non-memory-mapped cards, there is nothing else to check. + // + if (!pAdapter->MemMapped) + return(NULL); + + // + // Now read in the PROM configuration register. + // + NdisRawReadPortUchar(pAdapter->MappedGaBaseAddr + GA_MEM_BASE, &Tmp); + + // + // See which bit is on, minus 4. + // + MemConfig = 0; + + while (!(Tmp & 0x10)) + { + Tmp >>= 1; + + ++MemConfig; + + if (MemConfig == 4) + return(NULL); + } + + // + // Based on the bit, look up MemBaseAddr in the table. + // + pAdapter->MemMapped = TRUE; + + return(MemBases[MemConfig]); +} + + +#pragma NDIS_INIT_FUNCTION(CardReadEthernetAddress) + +VOID CardReadEthernetAddress( + IN PELNKII_ADAPTER pAdapter +) + +/*++ + +Routine Description: + + Reads in the Ethernet address from the Etherlink II PROM. + +Arguments: + + pAdapter - pointer to the adapter block. + +Return Value: + + The address is stored in pAdapter->PermanentAddress, and StationAddress if it + is currently zero. + +--*/ + +{ + UINT i; + + // + // Window the PROM into the NIC ports. + // + NdisRawWritePortUchar( + pAdapter->MappedGaBaseAddr + GA_CONTROL, + CTRL_PROM_SEL | CTRL_BNC + ); + + // + // Read in the station address. + // + for (i = 0; i < ETH_LENGTH_OF_ADDRESS; i++) + { + NdisRawReadPortUchar( + pAdapter->MappedIoBaseAddr + i, + &pAdapter->PermanentAddress[i] + ); + } + + IF_LOUD( DbgPrint(" [ %x-%x-%x-%x-%x-%x ]\n", + pAdapter->PermanentAddress[0], + pAdapter->PermanentAddress[1], + pAdapter->PermanentAddress[2], + pAdapter->PermanentAddress[3], + pAdapter->PermanentAddress[4], + pAdapter->PermanentAddress[5]);) + + // + // Window the NIC registers into the NIC ports. + // + + NdisRawWritePortUchar( + pAdapter->MappedGaBaseAddr + GA_CONTROL, + CTRL_GA_SEL | CTRL_BNC + ); + + if + ( + (pAdapter->StationAddress[0] == 0x00) && + (pAdapter->StationAddress[1] == 0x00) && + (pAdapter->StationAddress[2] == 0x00) && + (pAdapter->StationAddress[3] == 0x00) && + (pAdapter->StationAddress[4] == 0x00) && + (pAdapter->StationAddress[5] == 0x00) + ) + { + pAdapter->StationAddress[0] = pAdapter->PermanentAddress[0]; + pAdapter->StationAddress[1] = pAdapter->PermanentAddress[1]; + pAdapter->StationAddress[2] = pAdapter->PermanentAddress[2]; + pAdapter->StationAddress[3] = pAdapter->PermanentAddress[3]; + pAdapter->StationAddress[4] = pAdapter->PermanentAddress[4]; + pAdapter->StationAddress[5] = pAdapter->PermanentAddress[5]; + } +} + + +BOOLEAN CardSetup( + IN PELNKII_ADAPTER pAdapter +) + +/*++ + +Routine Description: + + Sets up the card, using the sequence given in the Etherlink II + technical reference. + +Arguments: + + pAdapter - pointer to the adapter block, which must be initialized. + +Return Value: + + TRUE if successful. + +--*/ + +{ + UINT i; + UINT Filter; + UCHAR IntConfig; + UCHAR Tmp; + + // + // First set up the Gate Array. + // + + // + // Toggle the reset bit. + // + NdisRawWritePortUchar( + pAdapter->MappedGaBaseAddr + GA_CONTROL, + CTRL_RESET | CTRL_BNC + ); + NdisRawWritePortUchar(pAdapter->MappedGaBaseAddr + GA_CONTROL, 0x00); + NdisRawWritePortUchar(pAdapter->MappedGaBaseAddr + GA_CONTROL, CTRL_BNC); + + // + // Set up the bits in the Control Register that don't change. + // + pAdapter->GaControlBits = pAdapter->ExternalTransceiver ? + CTRL_DIX : CTRL_BNC; + + if (DMA_BURST_SIZE == 16) + pAdapter->GaControlBits |= CTRL_DB_SEL; + + NdisRawWritePortUchar( + pAdapter->MappedGaBaseAddr + GA_CONTROL, + pAdapter->GaControlBits + ); + + // + // Set Page Start and Page Stop to match the NIC registers. + // + NdisRawWritePortUchar( + pAdapter->MappedGaBaseAddr + GA_PAGE_START, + pAdapter->NicPageStart + ); + NdisRawWritePortUchar( + pAdapter->MappedGaBaseAddr + GA_PAGE_STOP, + pAdapter->NicPageStop + ); + + // + // Select which interrupt to use. + // + IntConfig = 0x04; // set bit in position 2 + IntConfig <<= pAdapter->InterruptNumber; // move it to 4 through 7 + NdisRawWritePortUchar( + pAdapter->MappedGaBaseAddr + GA_INT_DMA_CONFIG, + IntConfig + ); + + // + // Choose between 8- and 16-byte programmed I/O bursts. + // + if (DMA_BURST_SIZE == 8) + { + NdisRawWritePortUchar( + pAdapter->MappedGaBaseAddr + GA_DRQ_TIMER, + DQTR_8_BYTE + ); + } + else + { + NdisRawWritePortUchar( + pAdapter->MappedGaBaseAddr + GA_DRQ_TIMER, + DQTR_16_BYTE + ); + } + + // + // Initialize these to a correct value for an 8K card. + // + NdisRawWritePortUchar(pAdapter->MappedGaBaseAddr + GA_DMA_ADDR_MSB, 0x20); + NdisRawWritePortUchar(pAdapter->MappedGaBaseAddr + GA_DMA_ADDR_LSB, 0x00); + + // + // Set up the Configuration register. + // + if (pAdapter->MemMapped) + { + NdisRawWritePortUchar( + pAdapter->MappedGaBaseAddr + GA_CONFIG, + GACFR_TC_MASK | GACFR_RAM_SEL | GACFR_MEM_BANK1 + ); + } + else + { + NdisRawWritePortUchar + ( + pAdapter->MappedGaBaseAddr + GA_CONFIG, + GACFR_TC_MASK + ); + } + + // + // Now set up NIC registers. + // + + // + // Write to and read from CR to make sure it is there. + // + NdisRawWritePortUchar( + pAdapter->MappedIoBaseAddr + NIC_COMMAND, + CR_STOP | CR_NO_DMA | CR_PAGE0 + ); + + NdisRawReadPortUchar(pAdapter->MappedIoBaseAddr + NIC_COMMAND, &Tmp); + + if (Tmp != (CR_STOP | CR_NO_DMA | CR_PAGE0)) + return(FALSE); + + // + // Set up the registers in the correct sequence. + // + NdisRawWritePortUchar( + pAdapter->MappedIoBaseAddr + NIC_DATA_CONFIG, + DCR_BYTE_WIDE | DCR_NORMAL | DCR_FIFO_8_BYTE + ); + + NdisRawWritePortUchar(pAdapter->MappedIoBaseAddr + NIC_RMT_COUNT_MSB, 0); + NdisRawWritePortUchar(pAdapter->MappedIoBaseAddr + NIC_RMT_COUNT_LSB, 0); + + NdisRawWritePortUchar( + pAdapter->MappedIoBaseAddr + NIC_RCV_CONFIG, + pAdapter->NicReceiveConfig + ); + + NdisRawWritePortUchar( + pAdapter->MappedIoBaseAddr + NIC_XMIT_CONFIG, + TCR_LOOPBACK + ); + + NdisRawWritePortUchar( + pAdapter->MappedIoBaseAddr + NIC_BOUNDARY, + pAdapter->NicPageStart + ); + + NdisRawWritePortUchar( + pAdapter->MappedIoBaseAddr + NIC_PAGE_START, + pAdapter->NicPageStart + ); + + NdisRawWritePortUchar( + pAdapter->MappedIoBaseAddr + NIC_PAGE_STOP, + pAdapter->NicPageStop + ); + + pAdapter->Current = pAdapter->NicPageStart + (UCHAR)1; + pAdapter->NicNextPacket = pAdapter->NicPageStart + (UCHAR)1; + pAdapter->BufferOverflow = FALSE; + + // + // Clear all + // + NdisRawWritePortUchar( + pAdapter->MappedIoBaseAddr + NIC_INTR_STATUS, + 0xff + ); + + NdisRawWritePortUchar( + pAdapter->MappedIoBaseAddr + NIC_INTR_MASK, + pAdapter->NicInterruptMask + ); + + + // + // Move to page 1 to write the station address and + // multicast registers. + // + NdisRawWritePortUchar( + pAdapter->MappedIoBaseAddr + NIC_COMMAND, + CR_STOP | CR_NO_DMA | CR_PAGE1 + ); + + for (i = 0; i < ETH_LENGTH_OF_ADDRESS; i++) + { + NdisRawWritePortUchar( + pAdapter->MappedIoBaseAddr + (NIC_PHYS_ADDR+i), + pAdapter->StationAddress[i] + ); + } + + Filter = pAdapter->PacketFilter; + + for (i = 0; i < 8; i++) + { + NdisRawWritePortUchar( + pAdapter->MappedIoBaseAddr + (NIC_MC_ADDR+i), + (UCHAR)((Filter & NDIS_PACKET_TYPE_ALL_MULTICAST) ? + 0xff : pAdapter->NicMulticastRegs[i]) + ); + } + + NdisRawWritePortUchar( + pAdapter->MappedIoBaseAddr + NIC_CURRENT, + pAdapter->Current + ); + + + // + // move back to page 0 and start the card... + // + NdisRawWritePortUchar( + pAdapter->MappedIoBaseAddr+NIC_COMMAND, + CR_STOP | CR_NO_DMA | CR_PAGE0 + ); + + NdisRawWritePortUchar( + pAdapter->MappedIoBaseAddr+NIC_COMMAND, + CR_START | CR_NO_DMA | CR_PAGE0 + ); + + // + // ... but it is still in loopback mode. + // + return(TRUE); +} + +BOOLEAN SyncCardStop( + IN PVOID SynchronizeContext +) + +/*++ + +Routine Description: + + Sets the NIC_COMMAND register to stop the card. + +Arguments: + + SynchronizeContext - pointer to the adapter block + +Return Value: + + Ignored. + +--*/ + +{ + PELNKII_ADAPTER pAdapter = ((PELNKII_ADAPTER)SynchronizeContext); + + NdisRawWritePortUchar( + pAdapter->MappedIoBaseAddr + NIC_COMMAND, + CR_STOP | CR_NO_DMA + ); + + return(FALSE); +} + + + +VOID CardStop( + IN PELNKII_ADAPTER pAdapter +) + +/*++ + +Routine Description: + + Stops the card. + +Arguments: + + pAdapter - pointer to the adapter block + +Return Value: + + None. + +--*/ + +{ + UINT i; + UCHAR Tmp; + + // + // Turn on the STOP bit in the Command register. + // + NdisMSynchronizeWithInterrupt( + &pAdapter->Interrupt, + SyncCardStop, + pAdapter + ); + + // + // Clear the Remote Byte Count register so that ISR_RESET + // will come on. + // + NdisRawWritePortUchar(pAdapter->MappedIoBaseAddr + NIC_RMT_COUNT_MSB, 0); + NdisRawWritePortUchar(pAdapter->MappedIoBaseAddr + NIC_RMT_COUNT_LSB, 0); + + + // + // Wait for ISR_RESET, but only for 1.6 milliseconds (as + // described in the March 1991 8390 addendum), since that + // is the maximum time for a software reset to occur. + // + // + for (i = 0; i < 4; i++) + { + NdisRawReadPortUchar(pAdapter->MappedIoBaseAddr + NIC_INTR_STATUS, &Tmp); + if (Tmp & ISR_RESET) + break; + + NdisStallExecution(500); + } + + if (i == 4) + { + IF_LOUD( DbgPrint("RESET\n");) + IF_LOG( ElnkiiLog('R');) + } + + + // + // Put the card in loopback mode, then start it. + // + NdisRawWritePortUchar( + pAdapter->MappedIoBaseAddr + NIC_XMIT_CONFIG, + TCR_LOOPBACK + ); + + NdisRawWritePortUchar( + pAdapter->MappedIoBaseAddr + NIC_COMMAND, + CR_START | CR_NO_DMA + ); + + // + // At this point the card is still in loopback mode. + // +} + + +BOOLEAN CardReset( + IN PELNKII_ADAPTER pAdapter +) + +/*++ + +Routine Description: + + Resets the card. + +Arguments: + + pAdapter - pointer to the adapter block + +Return Value: + + TRUE if everything is OK. + +--*/ + +{ + // + // Stop the chip. + // + CardStop(pAdapter); + + // + // CardSetup() does a software reset. + // + if (!CardSetup(pAdapter)) + { + NdisWriteErrorLogEntry( + pAdapter->MiniportAdapterHandle, + NDIS_ERROR_CODE_HARDWARE_FAILURE, + 2, + cardReset, + ELNKII_ERRMSG_CARD_SETUP + ); + + return(FALSE); + } + + // + // Start the chip. + // + CardStart(pAdapter); + + return(TRUE); +} + +#pragma NDIS_INIT_FUNCTION(DelayComplete) + +VOID DelayComplete( + IN PVOID SystemSpecific1, + IN PVOID TimerExpired, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3 + ) +{ + UNREFERENCED_PARAMETER(SystemSpecific1); + UNREFERENCED_PARAMETER(SystemSpecific2); + UNREFERENCED_PARAMETER(SystemSpecific3); + + *((BOOLEAN *)TimerExpired)=TRUE; +} + + + +#pragma NDIS_INIT_FUNCTION(CardTest) + +BOOLEAN CardTest( + IN PELNKII_ADAPTER pAdapter +) + +/*++ + +Routine Description: + + Tests the card. Follows the tests described in section 12 of + the 8390 Data Sheet. + +Arguments: + + pAdapter - pointer to the adapter block, which must be initialized + and set up. + +Return Value: + + TRUE if everything is OK. + +--*/ + +{ +#define TEST_LEN 60 +#define MAGIC_NUM 0x92 + + UINT FirstTest; + UINT SecondTest; + UINT i; + UCHAR TSRResult; + UCHAR RSRResult; + UCHAR CrcBuf[4]; + BOOLEAN FinalResult = TRUE; + UCHAR TestSrcBuf[256]; + UCHAR TestDestBuf[256]; + PUCHAR CurTestLoc; + UCHAR Tmp; + + static NDIS_MINIPORT_TIMER Timer = {0}; + BOOLEAN TimerExpired = FALSE; + + BOOLEAN dummy; //for return from NdisMCancelTimer + + // + // These arrays are indexed by FirstTest. + // + + static UCHAR TCRValues[3] = { TCR_NIC_LBK, TCR_SNI_LBK, TCR_COAX_LBK }; + static UCHAR TSRCDHWanted[3] = { TSR_NO_CDH, TSR_NO_CDH, 0x00 }; + static UCHAR TSRCRSWanted[3] = { TSR_NO_CARRIER, 0x00, 0x00 }; + static UCHAR FIFOWanted[4] = { LSB(TEST_LEN+4), MSB(TEST_LEN+4), + MSB(TEST_LEN+4), MAGIC_NUM }; + + + // + // These arrays are indexed by SecondTest. + // + + static BOOLEAN GoodCrc[3] = { TRUE, FALSE, FALSE }; + static BOOLEAN GoodAddress[3] = { TRUE, TRUE, FALSE }; + static UCHAR RSRWanted[3] = { RSR_PACKET_OK, RSR_CRC_ERROR, RSR_PACKET_OK }; + + static UCHAR TestPacket[TEST_LEN] = {0}; // a dummy packet. + static UCHAR NullAddress[ETH_LENGTH_OF_ADDRESS] = { 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00 }; + + + // + // First construct TestPacket. + // + + ELNKII_MOVE_MEM(TestPacket, pAdapter->StationAddress, ETH_LENGTH_OF_ADDRESS); + ELNKII_MOVE_MEM(TestPacket+ETH_LENGTH_OF_ADDRESS, pAdapter->StationAddress, ETH_LENGTH_OF_ADDRESS); + TestPacket[2*ETH_LENGTH_OF_ADDRESS] = 0x00; + TestPacket[2*ETH_LENGTH_OF_ADDRESS+1] = 0x00; + TestPacket[TEST_LEN-1] = MAGIC_NUM; + + + // + // Set up the DCR for loopback operation. + // + + NdisRawWritePortUchar(pAdapter->MappedIoBaseAddr+NIC_DATA_CONFIG, + DCR_BYTE_WIDE | DCR_LOOPBACK | DCR_FIFO_8_BYTE); + + + // + // Set the RCR to reject all packets. + // + + NdisRawWritePortUchar(pAdapter->MappedIoBaseAddr+NIC_RCV_CONFIG, 0x00); + + + // + // First round of tests -- different loopback modes + // + + for (FirstTest = 0; FirstTest < 2; ++FirstTest) { + + // + // Stop the card. + // + NdisRawWritePortUchar(pAdapter->MappedIoBaseAddr+NIC_COMMAND, + CR_STOP | CR_NO_DMA | CR_PAGE0); + + + // + // Set up the TCR for the appropriate loopback mode. + // + + NdisRawWritePortUchar(pAdapter->MappedIoBaseAddr+NIC_XMIT_CONFIG, 0x00); + NdisRawWritePortUchar(pAdapter->MappedIoBaseAddr+NIC_XMIT_CONFIG, TCRValues[FirstTest]); + + + // + // Restart the card. + // + + NdisRawWritePortUchar(pAdapter->MappedIoBaseAddr+NIC_COMMAND, + CR_START | CR_NO_DMA | CR_PAGE0); + + + // + // Now copy down TestPacket and start the transmission. + // + + CardCopyDownBuffer(pAdapter, TestPacket, 0, 0, TEST_LEN); + + NdisRawWritePortUchar(pAdapter->MappedIoBaseAddr+NIC_XMIT_START, pAdapter->NicXmitStart); + NdisRawWritePortUchar(pAdapter->MappedIoBaseAddr+NIC_XMIT_COUNT_MSB, MSB(TEST_LEN)); + NdisRawWritePortUchar(pAdapter->MappedIoBaseAddr+NIC_XMIT_COUNT_LSB, LSB(TEST_LEN)); + NdisRawWritePortUchar(pAdapter->MappedIoBaseAddr+NIC_COMMAND, + CR_START | CR_XMIT | CR_NO_DMA); + + + // + // Wait for the transmission to complete, for about a second. + // + + { + UINT i; + i=0; + NdisRawReadPortUchar( + pAdapter->MappedIoBaseAddr + NIC_INTR_STATUS, &Tmp); + while (!(Tmp & (ISR_XMIT | ISR_XMIT_ERR))) { + + if (++i > 100) { + IF_TEST( DbgPrint("F%d: TEST reset timed out\n", FirstTest);) + FinalResult = FALSE; + goto FinishTest; + } + + NdisStallExecution(11000); + NdisRawReadPortUchar(pAdapter->MappedIoBaseAddr+NIC_INTR_STATUS, &Tmp); + } + } + + // + // WAIT FOR CHIP TO STABILIZE + // Write to and read from CR to make sure it is there. + // Bug#4267 - WFW + // + + { + UINT i; + for (i = 0; i < 2000; ++i) { + NdisRawWritePortUchar(pAdapter->MappedIoBaseAddr+NIC_COMMAND, CR_STOP | CR_NO_DMA | CR_PAGE0); + NdisRawReadPortUchar(pAdapter->MappedIoBaseAddr+NIC_COMMAND, &Tmp); + if (Tmp != (CR_STOP | CR_NO_DMA | CR_PAGE0)) { + NdisStallExecution(1000); + } else { + break; + } + } + } + + + // + // Acknowledge the interrupt. + // + + NdisRawWritePortUchar(pAdapter->MappedIoBaseAddr+NIC_INTR_STATUS, + ISR_XMIT | ISR_XMIT_ERR); + + + // + // Check that the CRS and CDH bits are set correctly. + // + + NdisRawReadPortUchar(pAdapter->MappedIoBaseAddr+NIC_XMIT_STATUS, &TSRResult); + + if ((TSRResult & TSR_NO_CARRIER) != TSRCRSWanted[FirstTest]) { + + IF_TEST(DbgPrint("F%d: Incorrect CRS value: %x\n", FirstTest, TSRResult);) + + FinalResult = FALSE; + + goto FinishTest; + + } + + if ((TSRResult & TSR_NO_CDH) != TSRCDHWanted[FirstTest]) { + + // + // the spec says CDH won't go on for TCR_COAX_LBK, but it does + // + + if (TCRValues[FirstTest] != TCR_COAX_LBK) { + + IF_TEST( DbgPrint("F%d: Incorrect CDH value: %x\n", FirstTest,TSRResult);) + + FinalResult = FALSE; + + goto FinishTest; + + } + + } + + + // + // For the Loopback to Coax test the RSR and FIFO + // can't be trusted, so skip them. + // + + if (TCRValues[FirstTest] == TCR_COAX_LBK) { + + continue; + + } + + + // + // Check that the CRC error happened (it should). + // + + NdisRawReadPortUchar(pAdapter->MappedIoBaseAddr+NIC_RCV_STATUS, &RSRResult); + + if (!(RSRResult & RSR_CRC_ERROR)) { + + IF_TEST( DbgPrint("F%d: No CRC error: %x\n", FirstTest, RSRResult);) + + FinalResult = FALSE; + + goto FinishTest; + + } + + + // + // Check that the right values are in the FIFO. + // + + for (i=0; i<4; i++) { + + NdisRawReadPortUchar(pAdapter->MappedIoBaseAddr+NIC_FIFO, &Tmp); + if (Tmp != FIFOWanted[i]) { + + IF_TEST( DbgPrint("F%d: Bad FIFO value: %d\n", FirstTest, i);) + + FinalResult = FALSE; + + goto FinishTest; + + } + + } + + + // + // Flush the rest of the FIFO. + // + + for (i=0; i<4; i++) { + + NdisRawReadPortUchar(pAdapter->MappedIoBaseAddr+NIC_FIFO, &Tmp); + + } + + } + + + // + // Stop the card. + // + + NdisRawWritePortUchar(pAdapter->MappedIoBaseAddr+NIC_COMMAND, + CR_STOP | CR_NO_DMA | CR_PAGE0); + + + // + // Set the TCR for internal loopback. + // + + NdisRawWritePortUchar(pAdapter->MappedIoBaseAddr+NIC_XMIT_CONFIG, 0x00); + NdisRawWritePortUchar(pAdapter->MappedIoBaseAddr+NIC_XMIT_CONFIG, + TCR_INHIBIT_CRC | TCR_NIC_LBK); + + // + // Restart the card. + // + + NdisRawWritePortUchar(pAdapter->MappedIoBaseAddr+NIC_COMMAND, + CR_START | CR_NO_DMA | CR_PAGE0); + + + + // + // Second round of tests -- CRC and Address recognition logic + // + + for (SecondTest = 0; SecondTest < 3; ++SecondTest) { + + // + // See if the destination address should be valid. + // + + if (GoodAddress[SecondTest]) { + + ELNKII_MOVE_MEM(TestPacket, pAdapter->StationAddress, ETH_LENGTH_OF_ADDRESS); + + } else { + + ELNKII_MOVE_MEM(TestPacket, NullAddress, ETH_LENGTH_OF_ADDRESS); + + } + + + // + // Copy down TestPacket. + // + + CardCopyDownBuffer(pAdapter, TestPacket, 0, 0, TEST_LEN); + + + // + // Copy down a good or bad CRC, as needed. + // + + CardGetPacketCrc(TestPacket, TEST_LEN, CrcBuf); + + if (!GoodCrc[SecondTest]) { + + CrcBuf[0] = (UCHAR)(CrcBuf[0] ^ 0xff); // intentionally make it bad + + } + + CardCopyDownBuffer(pAdapter, CrcBuf, 0, TEST_LEN, 4); + + + // + // Start the transmission. + // + + NdisRawWritePortUchar(pAdapter->MappedIoBaseAddr+NIC_XMIT_START, pAdapter->NicXmitStart); + NdisRawWritePortUchar(pAdapter->MappedIoBaseAddr+NIC_XMIT_COUNT_MSB, MSB(TEST_LEN+4)); + NdisRawWritePortUchar(pAdapter->MappedIoBaseAddr+NIC_XMIT_COUNT_LSB, LSB(TEST_LEN+4)); + NdisRawWritePortUchar(pAdapter->MappedIoBaseAddr+NIC_COMMAND, + CR_START | CR_XMIT | CR_NO_DMA); + + + // + // Wait for the transmission to complete, for about a second. + // + + TimerExpired=FALSE; + + NdisMInitializeTimer( + &Timer, + pAdapter->MiniportAdapterHandle, + DelayComplete, + &TimerExpired + ); + + NdisMSetTimer(&Timer, 1000); + + NdisRawReadPortUchar(pAdapter->MappedIoBaseAddr+NIC_INTR_STATUS, &Tmp); + while (!(Tmp & (ISR_XMIT | ISR_XMIT_ERR))) { + + if (TimerExpired) { + + IF_TEST( DbgPrint("F%d: TEST reset timed out\n", FirstTest);) + + FinalResult = FALSE; + + goto FinishTest; + + } + + NdisRawReadPortUchar(pAdapter->MappedIoBaseAddr+NIC_INTR_STATUS, &Tmp); + + } + + // + //MUST Cancel the unexpired timer + // + + NdisMCancelTimer(&Timer, &dummy); + + // + // Acknowledge the interrupt. + // + + NdisRawWritePortUchar(pAdapter->MappedIoBaseAddr+NIC_INTR_STATUS, + ISR_XMIT | ISR_XMIT_ERR); + + + // + // Check that RSR is as expected. + // + + NdisRawReadPortUchar(pAdapter->MappedIoBaseAddr+NIC_RCV_STATUS, &RSRResult); + + if ((UCHAR)(RSRResult & (RSR_PACKET_OK | RSR_CRC_ERROR)) != + RSRWanted[SecondTest]) { + + IF_TEST( DbgPrint("S%d: Bad RSR: wanted %x got %x\n", SecondTest, + RSRWanted[SecondTest], RSRResult);) + + FinalResult = FALSE; + + goto FinishTest; + + } + + } + + + + // + // Third round of tests - copying data to and from the card. + // + + // + // First put data in the buffer. + // + + for (i=0; i<256; i++) { + + TestSrcBuf[i] = (UCHAR)(256-i); + + } + + // + // Loop through all the card memory in 256-byte pieces. + // + + for (CurTestLoc = 0; CurTestLoc < (PUCHAR)0x2000; CurTestLoc += 256) { + + // + // Copy the data down (have to play around with buffer + // numbers and offsets to put it in the right place). + // + + CardCopyDownBuffer(pAdapter, TestSrcBuf, + (XMIT_BUF)((ULONG)CurTestLoc / TX_BUF_SIZE), + (ULONG)CurTestLoc % TX_BUF_SIZE, 256); + + // + // Clear the destination buffer and read it back. + // + + for (i=0; i<256; i++) { + + TestDestBuf[i] = 77; + + } + + CardCopyUp(pAdapter, TestDestBuf, + pAdapter->XmitStart + (ULONG)CurTestLoc, 256); + + // + // Make sure that the data matches. + // + + for (i=0; i<256; i++) { + + if (TestSrcBuf[i] != TestDestBuf[i]) { + + IF_TEST( DbgPrint("T: Bad data at %lx\n", (ULONG)(CurTestLoc+i));) + + FinalResult = FALSE; + + goto FinishTest; + + } + + } + + } + + + + // + // FinishTest: jump here to exit the tests cleanly. + // + +FinishTest: + + // + // Stop the card. + // + + NdisRawWritePortUchar(pAdapter->MappedIoBaseAddr+NIC_COMMAND, + CR_STOP | CR_NO_DMA | CR_PAGE0); + + + // + // Restore DCR, RCR, and TCR. + // + + NdisRawWritePortUchar(pAdapter->MappedIoBaseAddr+NIC_DATA_CONFIG, + DCR_BYTE_WIDE | DCR_NORMAL | DCR_FIFO_8_BYTE); + + // + // (clear these two to be safe) + // + + NdisRawWritePortUchar(pAdapter->MappedIoBaseAddr+NIC_RMT_COUNT_MSB, 0); + NdisRawWritePortUchar(pAdapter->MappedIoBaseAddr+NIC_RMT_COUNT_LSB, 0); + NdisRawWritePortUchar(pAdapter->MappedIoBaseAddr+NIC_RCV_CONFIG, pAdapter->NicReceiveConfig); + NdisRawWritePortUchar(pAdapter->MappedIoBaseAddr+NIC_XMIT_CONFIG, TCR_LOOPBACK); + + // + // The reconfiguring of the config registers can cause the xmit to complete + // if the test was a failure. Therefore, we pause here to allow the xmit + // to complete so that we can ACK it below - leaving the card in a valid state. + // + + NdisStallExecution(50000); + + // + // Acknowledge any interrupts that are floating around. + // + + NdisRawWritePortUchar(pAdapter->MappedIoBaseAddr+NIC_INTR_STATUS, 0xff); + + + // + // Start the card, but stay in loopback mode. + // + + NdisRawWritePortUchar(pAdapter->MappedIoBaseAddr+NIC_COMMAND, + CR_START | CR_NO_DMA | CR_PAGE0); + + + + return FinalResult; +} + + + + +BOOLEAN CardCopyDownPacket( + IN PELNKII_ADAPTER pAdapter, + IN PNDIS_PACKET Packet, + IN XMIT_BUF XmitBufferNum, + OUT UINT *Length +) + +/*++ + +Routine Description: + + Copies the packet Packet down starting at the beginning of + transmit buffer XmitBufferNum, fills in Length to be the + length of the packet. It uses memory mapping or programmed + I/O as appropriate. + +Arguments: + + pAdapter - pointer to the adapter block + Packet - the packet to copy down + XmitBufferNum - the transmit buffer number + +Return Value: + + Length - the length of the data in the packet in bytes. + TRUE if the transfer completed with no problems. + +--*/ + +{ + PUCHAR CurAddress; + PUCHAR BufAddress; + UINT CurLength; + UINT Len; + PNDIS_BUFFER CurBuffer; + UINT TmpLen; + UINT BurstSize; + UCHAR GaStatus; + + // + // Is the card memory mapped? + // + if (pAdapter->MemMapped) + { + // + // Memory mapped, just copy each buffer over. + // + NdisQueryPacket(Packet, NULL, NULL, &CurBuffer, NULL); + + CurAddress = pAdapter->XmitStart + XmitBufferNum * TX_BUF_SIZE; + + CurLength = 0; + + while (CurBuffer) + { + NdisQueryBuffer(CurBuffer, (PVOID *)&BufAddress, &Len); + + ELNKII_MOVE_MEM_TO_SHARED_RAM(CurAddress, BufAddress, Len); + + CurAddress += Len; + + CurLength += Len; + + NdisGetNextBuffer(CurBuffer, &CurBuffer); + } + + *Length = CurLength; + } + else + { + // + // Programmed I/O, have to transfer the data. + // + NdisQueryPacket(Packet, NULL, NULL, &CurBuffer, NULL); + + CurAddress = (PUCHAR)0x2000 + XmitBufferNum * TX_BUF_SIZE; + + CurLength = 0; + + while (CurBuffer) + { + NdisQueryBuffer(CurBuffer, (PVOID *)&BufAddress, &Len); + + if (Len == 0) + { + NdisGetNextBuffer(CurBuffer, &CurBuffer); + continue; + } + + // + // Set up the Gate Array for programmed I/O transfer. + // + NdisRawWritePortUchar( + pAdapter->MappedGaBaseAddr + GA_DMA_ADDR_MSB, + MSB((ULONG)CurAddress) + ); + + NdisRawWritePortUchar( + pAdapter->MappedGaBaseAddr + GA_DMA_ADDR_LSB, + LSB((ULONG)CurAddress) + ); + + NdisRawWritePortUchar( + pAdapter->MappedGaBaseAddr + GA_CONTROL, + (UCHAR)((CTRL_START | CTRL_DIR_DOWN) | pAdapter->GaControlBits) + ); + + + // + // First transfer multiples of DMA_BURST_SIZE. + // + TmpLen = Len; + BurstSize = DMA_BURST_SIZE; + + while (TmpLen >= BurstSize) + { + if ((ULONG)BufAddress & 0x01) + { + NdisRawWritePortBufferUchar( + pAdapter->MappedGaBaseAddr + GA_REG_FILE_MSB, + (PUCHAR)BufAddress, + BurstSize + ); + } + else + { + NdisRawWritePortBufferUshort( + pAdapter->MappedGaBaseAddr + GA_REG_FILE_MSB, + (PUSHORT)BufAddress, + BurstSize / 2 + ); + } + + + TmpLen -= BurstSize; + + BufAddress += BurstSize; + + // + // Wait for the Gate Array FIFO to be ready. + // + do + { + NdisRawReadPortUchar(pAdapter->MappedGaBaseAddr+GA_STATUS, &GaStatus); + + if (GaStatus & (STREG_UNDERFLOW | STREG_OVERFLOW)) + { +#if DBG + DbgPrint("DATA PORT READY ERROR IN ELNKII - CCDP\n"); + DbgPrint("\tStatus = 0x%x, BurstSize = 0x%x, PrevBurstSize = 0x%x\n", + GaStatus, BurstSize, PrevBurstSize); +#endif + + NdisWriteErrorLogEntry( + pAdapter->MiniportAdapterHandle, + NDIS_ERROR_CODE_DRIVER_FAILURE, + 2, + cardCopyDownPacket, + ELNKII_ERRMSG_DATA_PORT_READY + ); + + return(FALSE); + } + + } while (!(GaStatus & STREG_DP_READY)); + +#if DBG + PrevBurstSize = (UCHAR)BurstSize; +#endif + } + + // + // Now copy the last bit as UCHARs. + // + NdisRawWritePortBufferUchar( + pAdapter->MappedGaBaseAddr + GA_REG_FILE_MSB, + BufAddress, + TmpLen + ); + + do + { + NdisRawReadPortUchar( + pAdapter->MappedGaBaseAddr + GA_STATUS, + &GaStatus + ); + + if (GaStatus & (STREG_UNDERFLOW | STREG_OVERFLOW)) + { +#if DBG + DbgPrint("DATA PORT READY ERROR IN ELNKII - CCDPII\n"); + DbgPrint("\tStatus = 0x%x, BurstSize = 0x%x, PrevBurstSize = 0x%x\n", + GaStatus, BurstSize, PrevBurstSize); +#endif + + NdisWriteErrorLogEntry( + pAdapter->MiniportAdapterHandle, + NDIS_ERROR_CODE_DRIVER_FAILURE, + 2, + cardCopyDownPacket, + ELNKII_ERRMSG_DATA_PORT_READY + ); + + return FALSE; + } + + } while (!(GaStatus & STREG_DP_READY)); + + +#if DBG + PrevBurstSize = (UCHAR)TmpLen; +#endif + + // + // Done, turn off the start bit... + // + NdisRawWritePortUchar( + pAdapter->MappedGaBaseAddr + GA_CONTROL, + (UCHAR)(CTRL_STOP | pAdapter->GaControlBits) + ); + + // + // ... and wait for DMA_IN_PROGRESS to go off, + // indicating end of flush. + // + do + { + NdisRawReadPortUchar( + pAdapter->MappedGaBaseAddr + GA_STATUS, + &GaStatus + ); + } while (GaStatus & STREG_IN_PROG); + + CurAddress += Len; + + CurLength += Len; + + NdisGetNextBuffer(CurBuffer, &CurBuffer); + } + + *Length = CurLength; + } + + return(TRUE); +} + + +BOOLEAN CardCopyDownBuffer( + IN PELNKII_ADAPTER pAdapter, + IN PUCHAR SourceBuffer, + IN XMIT_BUF XmitBufferNum, + IN UINT Offset, + IN UINT Length +) + +/*++ + +Routine Description: + + Copies down one character buffer (rather than an + entire packet), starting at offset Offset, for Length + bytes. It uses memory mapping or programmed I/O as + appropriate. This function is used for blanking the padding + at the end of short packets and also for loopback testing. + +Arguments: + + pAdapter - pointer to the adapter block + SourceBuffer - the source data to be copied down + XmitBufferNum - the transmit buffer number + Offset - the offset from the start of the transmit buffer + Length - the number of bytes to blank out + +Return Value: + + Length - the length of the data in the packet in bytes. + TRUE if the transfer completed with no problems. + +--*/ + +{ + PUCHAR CurAddress; + UINT TmpLen; + UINT ThisTime; + UCHAR GaStatus; + + if (pAdapter->MemMapped) + { + // + // Memory mapped, just copy over SourceBuffer. + // + CurAddress = pAdapter->XmitStart + XmitBufferNum * TX_BUF_SIZE + Offset; + + ELNKII_MOVE_MEM_TO_SHARED_RAM(CurAddress, SourceBuffer, Length); + } + else + { + // + // Programmed I/O, have to transfer the data. + // + CurAddress = (PUCHAR)0x2000 + XmitBufferNum*TX_BUF_SIZE + Offset; + + // + // Set up the Gate Array for programmed I/O transfer. + // + NdisRawWritePortUchar( + pAdapter->MappedGaBaseAddr + GA_DMA_ADDR_MSB, + MSB((ULONG)CurAddress) + ); + + NdisRawWritePortUchar( + pAdapter->MappedGaBaseAddr + GA_DMA_ADDR_LSB, + LSB((ULONG)CurAddress) + ); + + NdisRawWritePortUchar( + pAdapter->MappedGaBaseAddr + GA_CONTROL, + (UCHAR)((CTRL_START | CTRL_DIR_DOWN) | pAdapter->GaControlBits) + ); + + // + // Copy the data down in DMA_BURST_SIZE bursts. + // + TmpLen = Length; + + while (TmpLen > 0) + { + ThisTime = (TmpLen >= DMA_BURST_SIZE) ? DMA_BURST_SIZE : TmpLen; + + NdisRawWritePortBufferUchar( + pAdapter->MappedGaBaseAddr + GA_REG_FILE_MSB, + SourceBuffer, + ThisTime + ); + + TmpLen -= ThisTime; + + SourceBuffer += ThisTime; + + // + // Wait for the Gate Array FIFO to be ready. + // + do + { + NdisRawReadPortUchar( + pAdapter->MappedGaBaseAddr + GA_STATUS, + &GaStatus + ); + + if (GaStatus & (STREG_UNDERFLOW | STREG_OVERFLOW)) + { +#if DBG + DbgPrint("DATA PORT READY ERROR IN ELNKII - CCDB\n"); + DbgPrint( + "\tStatus = 0x%x, BurstSize = 0x%x, " + "PrevBurstSize = 0x%x\n", + GaStatus, + ThisTime, + PrevBurstSize + ); +#endif + + NdisWriteErrorLogEntry( + pAdapter->MiniportAdapterHandle, + NDIS_ERROR_CODE_DRIVER_FAILURE, + 2, + cardCopyDownBuffer, + ELNKII_ERRMSG_DATA_PORT_READY + ); + + return(FALSE); + } + } while (!(GaStatus & STREG_DP_READY)); + +#if DBG + PrevBurstSize = (UCHAR)ThisTime; +#endif + } + + // + // Done, turn off the start bit.. + // + NdisRawWritePortUchar( + pAdapter->MappedGaBaseAddr + GA_CONTROL, + (UCHAR)(CTRL_STOP | pAdapter->GaControlBits) + ); + + // + // ... and wait for DMA_IN_PROGRESS to go off, + // indicating end of flush. + // + + do + { + NdisRawReadPortUchar( + pAdapter->MappedGaBaseAddr + GA_STATUS, + &GaStatus + ); + } while (GaStatus & STREG_IN_PROG); + } + +#if DBG + IF_ELNKIIDEBUG( ELNKII_DEBUG_TRACK_PACKET_LENS ) + { + if (Offset == 18 && Length == 42) + { + UINT i; + + for (i = 0; i < 20; i++) + { + SourceBuffer[i] = ' '; + } + } + } +#endif + + return(TRUE); +} + + + + +BOOLEAN CardCopyUp( + IN PELNKII_ADAPTER pAdapter, + IN PUCHAR Target, + IN PUCHAR Source, + IN UINT Length +) + +/*++ + +Routine Description: + + Copies data from the card to memory. It uses memory mapping + or programmed I/O as appropriate. + +Arguments: + + pAdapter - pointer to the adapter block + Target - the target address + Source - the source address (on the card) + Length - the number of bytes to copy + +Return Value: + + TRUE if the transfer completed with no problems. + +--*/ + +{ + UINT TmpLen; + UINT BurstSize; + UCHAR GaStatus; + + if (Length == 0) + return(TRUE); + + if (pAdapter->MemMapped) + { + // + // Memory mapped, just copy the data over. + // + ELNKII_MOVE_SHARED_RAM_TO_MEM(Target, Source, Length); + } + else + { + // + // Programmed I/O, have to transfer the data. + // + + // + // Adjust the address to be a card address. + // + Source -= ((ULONG)pAdapter->XmitStart - 0x2000); + + // + // Set up the Gate Array for programmed I/O transfer. + // + NdisRawWritePortUchar( + pAdapter->MappedGaBaseAddr + GA_DMA_ADDR_MSB, + MSB((ULONG)Source) + ); + NdisRawWritePortUchar( + pAdapter->MappedGaBaseAddr + GA_DMA_ADDR_LSB, + LSB((ULONG)Source) + ); + NdisRawWritePortUchar( + pAdapter->MappedGaBaseAddr + GA_CONTROL, + (UCHAR)((CTRL_START | CTRL_DIR_UP) | pAdapter->GaControlBits) + ); + + + // + // First copy multiples of DMA_BURST_SIZE as USHORTs. + // + TmpLen = Length; + BurstSize = DMA_BURST_SIZE; + + // + // Before doing this, transfer one byte if needed to + // align on a USHORT boundary. + // + while (TmpLen >= BurstSize) + { + // + // First wait for the Gate Array FIFO to be ready. + // + do + { + NdisRawReadPortUchar( + pAdapter->MappedGaBaseAddr + GA_STATUS, + &GaStatus + ); + + if (GaStatus & (STREG_UNDERFLOW | STREG_OVERFLOW)) + { +#if DBG + DbgPrint("DATA PORT READY ERROR IN ELNKII - CCU\n"); + DbgPrint( + "\tStatus = 0x%x, BurstSize = 0x%x, " + "PrevBurstSize = 0x%x\n", + GaStatus, + PrevBurstSize, + PrevPrevBurstSize + ); +#endif + + NdisWriteErrorLogEntry( + pAdapter->MiniportAdapterHandle, + NDIS_ERROR_CODE_DRIVER_FAILURE, + 2, + cardCopyUp, + ELNKII_ERRMSG_DATA_PORT_READY + ); + + return(FALSE); + } + } while (!(GaStatus & STREG_DP_READY)); + + + if ((ULONG)Target & 0x01) + { + // + // This is the first burst, and it starts on + // an odd boundary. + // + NdisRawReadPortBufferUchar( + pAdapter->MappedGaBaseAddr + GA_REG_FILE_MSB, + (PUCHAR)Target, + BurstSize + ); + + TmpLen -= BurstSize; + Target += BurstSize; + +#if DBG + PrevPrevBurstSize = PrevBurstSize; + PrevBurstSize = (UCHAR)BurstSize; +#endif + } + else + { + NdisRawReadPortBufferUshort( + pAdapter->MappedGaBaseAddr + GA_REG_FILE_MSB, + (PUSHORT)Target, + BurstSize / 2 + ); + + TmpLen -= BurstSize; + Target += BurstSize; + + +#if DBG + PrevPrevBurstSize = PrevBurstSize; + PrevBurstSize = (UCHAR)BurstSize; +#endif + } + } + + // + // Now copy the last bit of data as UCHARs. + // + do + { + NdisRawReadPortUchar( + pAdapter->MappedGaBaseAddr + GA_STATUS, + &GaStatus + ); + + if (GaStatus & (STREG_UNDERFLOW | STREG_OVERFLOW)) + { +#if DBG + DbgPrint("DATA PORT READY ERROR IN ELNKII - CCUII\n"); + DbgPrint( + "\tStatus = 0x%x, BurstSize = 0x%x, " + "PrevBurstSize = 0x%x\n", + GaStatus, + BurstSize, + PrevBurstSize + ); +#endif + + NdisWriteErrorLogEntry( + pAdapter->MiniportAdapterHandle, + NDIS_ERROR_CODE_DRIVER_FAILURE, + 2, + cardCopyUp, + ELNKII_ERRMSG_DATA_PORT_READY + ); + + return(FALSE); + } + } while (!(GaStatus & STREG_DP_READY)); + + NdisRawReadPortBufferUchar( + pAdapter->MappedGaBaseAddr + GA_REG_FILE_MSB, + Target, + TmpLen + ); + + // + // Done, turn off the start bit. + // + NdisRawWritePortUchar( + pAdapter->MappedGaBaseAddr + GA_CONTROL, + (UCHAR)(CTRL_STOP | pAdapter->GaControlBits) + ); + } + + return(TRUE); +} + +ULONG +CardComputeCrc( + IN PUCHAR Buffer, + IN UINT Length + ) + +/*++ + +Routine Description: + + Runs the AUTODIN II CRC algorithm on buffer Buffer of + length Length. + +Arguments: + + Buffer - the input buffer + Length - the length of Buffer + +Return Value: + + The 32-bit CRC value. + +Note: + + This is adapted from the comments in the assembly language + version in _GENREQ.ASM of the DWB NE1000/2000 driver. + +--*/ + +{ + ULONG Crc; + ULONG Carry; + UINT i; + UINT j; + UCHAR CurByte; + + Crc = 0xffffffff; + + for (i = 0; i < Length; i++) + { + CurByte = Buffer[i]; + + for (j = 0; j < 8; j++) + { + Carry = ((Crc & 0x80000000) ? 1 : 0) ^ (CurByte & 0x01); + + Crc <<= 1; + + CurByte >>= 1; + + if (Carry) + Crc = (Crc ^ 0x04c11db6) | Carry; + + } + } + + return(Crc); +} + + +#pragma NDIS_INIT_FUNCTION(CardGetPacketCrc) + +VOID CardGetPacketCrc( + IN PUCHAR Buffer, + IN UINT Length, + OUT UCHAR Crc[4] +) + +/*++ + +Routine Description: + + For a given Buffer, computes the packet CRC for it. + It uses CardComputeCrc to determine the CRC value, then + inverts the order and value of all the bits (I don't + know why this is necessary). + +Arguments: + + Buffer - the input buffer + Length - the length of Buffer + +Return Value: + + The CRC will be stored in Crc. + +--*/ + +{ + static UCHAR InvertBits[16] = { 0x0, 0x8, 0x4, 0xc, + 0x2, 0xa, 0x6, 0xe, + 0x1, 0x9, 0x5, 0xd, + 0x3, 0xb, 0x7, 0xf }; + ULONG CrcValue; + UCHAR Tmp; + UINT i; + + // + // First compute the CRC. + // + CrcValue = CardComputeCrc(Buffer, Length); + + + // + // Now invert the bits in the result. + // + for (i = 0; i < 4; i++) + { + Tmp = ((PUCHAR)&CrcValue)[3-i]; + + Crc[i] = (UCHAR)((InvertBits[Tmp >> 4] + + (InvertBits[Tmp & 0xf] << 4)) ^ 0xff); + } +} + + +VOID +CardGetMulticastBit( + IN UCHAR Address[ETH_LENGTH_OF_ADDRESS], + OUT UCHAR * Byte, + OUT UCHAR * Value + ) + +/*++ + +Routine Description: + + For a given multicast address, returns the byte and bit in + the card multicast registers that it hashes to. Calls + CardComputeCrc() to determine the CRC value. + +Arguments: + + Address - the address + Byte - the byte that it hashes to + Value - will have a 1 in the relevant bit + +Return Value: + + None. + +--*/ + +{ + ULONG Crc; + UINT BitNumber; + + // + // First compute the CRC. + // + Crc = CardComputeCrc(Address, ETH_LENGTH_OF_ADDRESS); + + + // + // The bit number is now in the 6 most significant bits of CRC. + // + BitNumber = (UINT)((Crc >> 26) & 0x3f); + + *Byte = (UCHAR)(BitNumber / 8); + *Value = (UCHAR)((UCHAR)1 << (BitNumber % 8)); +} + +VOID CardFillMulticastRegs( + IN PELNKII_ADAPTER pAdapter +) + +/*++ + +Routine Description: + + Erases and refills the card multicast registers. Used when + an address has been deleted and all bits must be recomputed. + +Arguments: + + pAdapter - pointer to the adapter block + +Return Value: + + None. + +--*/ + +{ + UINT i; + UCHAR Byte; + UCHAR Bit; + + // + // First turn all bits off. + // + for (i = 0; i < 8; i++) + pAdapter->NicMulticastRegs[i] = 0; + + // + // Now turn on the bit for each address in the multicast list. + // + for ( ; i > 0; ) + { + i--; + + CardGetMulticastBit(Addresses[i], &Byte, &Bit); + + pAdapter->NicMulticastRegs[Byte] |= Bit; + } +} + + +VOID CardStartXmit( + IN PELNKII_ADAPTER pAdapter +) + +/*++ + +Routine Description: + + Sets the NIC_COMMAND register to start a transmission. + The transmit buffer number is taken from pAdapter->CurBufXmitting + and the length from pAdapter->PacketLens[pAdapter->CurBufXmitting]. + +Arguments: + + pAdapter - pointer to the adapter block + +Return Value: + + TRUE if the power has failed. + +--*/ + +{ + XMIT_BUF XmitBufferNum = pAdapter->CurBufXmitting; + UINT Length = pAdapter->PacketLens[XmitBufferNum]; + UCHAR Tmp; + + // + // Prepare the NIC registers for transmission. + // + NdisRawWritePortUchar( + pAdapter->MappedIoBaseAddr + NIC_XMIT_START, + (UCHAR)(pAdapter->NicXmitStart + (UCHAR)(XmitBufferNum * BUFS_PER_TX)) + ); + + // + // Pad the length to 60 (plus CRC will be 64) if needed. + // + + if (Length < 60) + Length = 60; + + NdisRawWritePortUchar( + pAdapter->MappedIoBaseAddr + NIC_XMIT_COUNT_MSB, + MSB(Length) + ); + NdisRawWritePortUchar( + pAdapter->MappedIoBaseAddr + NIC_XMIT_COUNT_LSB, + LSB(Length) + ); + + // + // Start transmission, check for power failure first. + // + NdisRawReadPortUchar(pAdapter->MappedIoBaseAddr + NIC_COMMAND, &Tmp); + NdisRawWritePortUchar( + pAdapter->MappedIoBaseAddr + NIC_COMMAND, + CR_START | CR_XMIT | CR_NO_DMA + ); + + IF_LOG( ElnkiiLog('x');) +} + + +BOOLEAN SyncCardGetXmitStatus( + IN PVOID SynchronizeContext +) + +/*++ + +Routine Description: + + Gets the value of the "transmit status" NIC register and stores + it in pAdapter->XmitStatus. + +Arguments: + + SynchronizeContext - pointer to the adapter block + +Return Value: + + None. + +--*/ + +{ + PELNKII_ADAPTER pAdapter = (PELNKII_ADAPTER)SynchronizeContext; + + NdisRawReadPortUchar( + pAdapter->MappedIoBaseAddr + NIC_XMIT_STATUS, + &pAdapter->XmitStatus + ); + + return(FALSE); +} + + +BOOLEAN SyncCardGetCurrent( + IN PVOID SynchronizeContext +) + +/*++ + +Routine Description: + + Gets the value of the CURRENT NIC register and stores + it in pAdapter->Current. + +Arguments: + + SynchronizeContext - pointer to the adapter block + +Return Value: + + None. + +--*/ + +{ + PELNKII_ADAPTER pAdapter = ((PELNKII_ADAPTER)SynchronizeContext); + + // + // Have to go to page 1 to read this register. + // + NdisRawWritePortUchar( + pAdapter->MappedIoBaseAddr + NIC_COMMAND, + CR_START | CR_NO_DMA | CR_PAGE1 + ); + + NdisRawReadPortUchar( + pAdapter->MappedIoBaseAddr + NIC_CURRENT, + &pAdapter->Current + ); + + NdisRawWritePortUchar( + pAdapter->MappedIoBaseAddr + NIC_COMMAND, + CR_START | CR_NO_DMA | CR_PAGE0 + ); + + return(FALSE); +} + +VOID CardSetBoundary( + IN PELNKII_ADAPTER pAdapter +) + +/*++ + +Routine Description: + + Sets the value of the "boundary" NIC register to one behind + pAdapter->NicNextPacket, to prevent packets from being received + on top of un-indicated ones. + +Arguments: + + pAdapter - pointer to the adapter block + +Return Value: + + None. + +--*/ + +{ + // + // Have to be careful with "one behind NicNextPacket" when + // NicNextPacket is the first buffer in receive area. + // + if (pAdapter->NicNextPacket == pAdapter->NicPageStart) + { + NdisRawWritePortUchar( + pAdapter->MappedIoBaseAddr + NIC_BOUNDARY, + (UCHAR)(pAdapter->NicPageStop - (UCHAR)1) + ); + } + else + { + NdisRawWritePortUchar( + pAdapter->MappedIoBaseAddr + NIC_BOUNDARY, + (UCHAR)(pAdapter->NicNextPacket - (UCHAR)1) + ); + } +} + + +BOOLEAN SyncCardSetReceiveConfig( + IN PELNKII_ADAPTER pAdapter +) + +/*++ + +Routine Description: + + Sets the value of the "receive configuration" NIC register to + the value of pAdapter->NicReceiveConfig. + +Arguments: + + SynchronizeContext - pointer to the adapter block + +Return Value: + + None. + +--*/ + +{ + NdisRawWritePortUchar( + pAdapter->MappedIoBaseAddr + NIC_RCV_CONFIG, + pAdapter->NicReceiveConfig + ); + + return(FALSE); +} + + +BOOLEAN SyncCardSetAllMulticast( + IN PELNKII_ADAPTER pAdapter +) + +/*++ + +Routine Description: + + Turns on all the bits in the multicast register. Used when + the card must receive all multicast packets. + +Arguments: + + SynchronizeContext - pointer to the adapter block + +Return Value: + + None. + +--*/ + +{ + UINT i; + + // + // Have to move to page 1 to set these registers. + // + NdisRawWritePortUchar( + pAdapter->MappedIoBaseAddr + NIC_COMMAND, + CR_START | CR_NO_DMA | CR_PAGE1 + ); + + for (i = 0; i < 8; i++) + { + NdisRawWritePortUchar( + pAdapter->MappedIoBaseAddr + (NIC_MC_ADDR + i), + 0xff + ); + } + + NdisRawWritePortUchar( + pAdapter->MappedIoBaseAddr + NIC_COMMAND, + CR_START | CR_NO_DMA | CR_PAGE0 + ); + + return(FALSE); +} + + +BOOLEAN SyncCardCopyMulticastRegs( + IN PELNKII_ADAPTER pAdapter +) + +/*++ + +Routine Description: + + Sets the eight bytes in the card multicast registers. + +Arguments: + + SynchronizeContext - pointer to the adapter block + +Return Value: + + None. + +--*/ + +{ + UINT i; + + // + // Have to move to page 1 to set these registers. + // + NdisRawWritePortUchar( + pAdapter->MappedIoBaseAddr + NIC_COMMAND, + CR_START | CR_NO_DMA | CR_PAGE1 + ); + + for (i = 0; i < 8; i++) + { + NdisRawWritePortUchar( + pAdapter->MappedIoBaseAddr + (NIC_MC_ADDR + i), + pAdapter->NicMulticastRegs[i] + ); + } + + NdisRawWritePortUchar( + pAdapter->MappedIoBaseAddr + NIC_COMMAND, + CR_START | CR_NO_DMA | CR_PAGE0 + ); + + return(FALSE); + +} + +BOOLEAN +SyncCardSetInterruptMask( + IN PVOID SynchronizeContext + ) + +/*++ + +Routine Description: + + Sets the "interrupt mask" register of the NIC to the value of + pAdapter->NicInterruptMask. + +Arguments: + + SynchronizeContext - pointer to the adapter block + +Return Value: + + None. + +--*/ + +{ + PELNKII_ADAPTER pAdapter = ((PELNKII_ADAPTER)SynchronizeContext); + + NdisRawWritePortUchar( + pAdapter->MappedIoBaseAddr + NIC_INTR_MASK, + pAdapter->NicInterruptMask + ); + + return(FALSE); +} + + +BOOLEAN SyncCardAcknowledgeReceive( + IN PVOID SynchronizeContext +) + +/*++ + +Routine Description: + + Sets the "packet received" bit in the NIC interrupt status register, + which re-enables interrupts of that type. + +Arguments: + + SynchronizeContext - pointer to the adapter block + +Return Value: + + None. + +--*/ + +{ + PELNKII_ADAPTER pAdapter = ((PELNKII_ADAPTER)SynchronizeContext); + + NdisRawWritePortUchar( + pAdapter->MappedIoBaseAddr + NIC_INTR_STATUS, + ISR_RCV + ); + + // + // Interrupts were previously blocked in the interrupt handler. + // + NdisRawWritePortUchar( + pAdapter->MappedIoBaseAddr + NIC_INTR_MASK, + pAdapter->NicInterruptMask + ); + + return(FALSE); +} + + +BOOLEAN SyncCardAcknowledgeOverflow( + IN PVOID SynchronizeContext +) + +/*++ + +Routine Description: + + Sets the "buffer overflow" bit in the NIC interrupt status register, + which re-enables interrupts of that type. + +Arguments: + + SynchronizeContext - pointer to the adapter block + +Return Value: + + None. + +--*/ + +{ + PELNKII_ADAPTER pAdapter = ((PELNKII_ADAPTER)SynchronizeContext); + UCHAR InterruptStatus; + + CardGetInterruptStatus(pAdapter, &InterruptStatus); + + if (InterruptStatus & ISR_RCV_ERR) + SyncCardUpdateCounters(pAdapter); + + NdisRawWritePortUchar( + pAdapter->MappedIoBaseAddr + NIC_INTR_STATUS, + ISR_OVERFLOW + ); + + return(FALSE); +} + + +BOOLEAN SyncCardAcknowledgeTransmit( + IN PVOID SynchronizeContext +) + +/*++ + +Routine Description: + + Sets the "packet transmitted" bit in the NIC interrupt status register, + which re-enables interrupts of that type. + +Arguments: + + SynchronizeContext - pointer to the adapter block + +Return Value: + + None. + +--*/ + +{ + PELNKII_ADAPTER pAdapter = ((PELNKII_ADAPTER)SynchronizeContext); + + NdisRawWritePortUchar( + pAdapter->MappedIoBaseAddr + NIC_INTR_STATUS, + ISR_XMIT | ISR_XMIT_ERR + ); + + // + // Interrupts were previously blocked in the interrupt handler. + // + NdisRawWritePortUchar( + pAdapter->MappedIoBaseAddr + NIC_INTR_MASK, + pAdapter->NicInterruptMask + ); + + return(FALSE); +} + + +BOOLEAN SyncCardAckAndGetCurrent( + IN PVOID SynchronizeContext + ) + +/*++ + +Routine Description: + + Performs the functions of SyncCardAcknowledgeReceive followed by + SyncCardGetCurrent (since the two are always called + one after the other). + +Arguments: + + SynchronizeContext - pointer to the adapter block + +Return Value: + + None. + +--*/ + +{ + PELNKII_ADAPTER pAdapter = ((PELNKII_ADAPTER)SynchronizeContext); + + // + // SyncCardAcknowledgeReceive. + // + +#ifdef i386 + + __asm cli + +#endif + + NdisRawWritePortUchar( + pAdapter->MappedIoBaseAddr + NIC_INTR_STATUS, + ISR_RCV + ); + + NdisRawWritePortUchar( + pAdapter->MappedIoBaseAddr + NIC_INTR_MASK, + pAdapter->NicInterruptMask + ); + +#ifdef i386 + + __asm sti + +#endif + + // + // SyncCardGetCurrent. + // + NdisRawWritePortUchar( + pAdapter->MappedIoBaseAddr + NIC_COMMAND, + CR_START | CR_NO_DMA | CR_PAGE1 + ); + + NdisRawReadPortUchar( + pAdapter->MappedIoBaseAddr + NIC_CURRENT, + &pAdapter->Current + ); + + NdisRawWritePortUchar( + pAdapter->MappedIoBaseAddr + NIC_COMMAND, + CR_START | CR_NO_DMA | CR_PAGE0 + ); + + return(FALSE); +} + + +BOOLEAN SyncCardGetXmitStatusAndAck( + IN PVOID SynchronizeContext +) + +/*++ + +Routine Description: + + Performs the functions of SyncCardGetXmitStatus followed by + SyncCardAcknowledgeTransmit (since the two are always + called one after the other). + +Arguments: + + SynchronizeContext - pointer to the adapter block + +Return Value: + + None. + +--*/ + +{ + PELNKII_ADAPTER pAdapter = ((PELNKII_ADAPTER)SynchronizeContext); + + // + // SyncCardGetXmitStatus. + // + NdisRawReadPortUchar( + pAdapter->MappedIoBaseAddr + NIC_XMIT_STATUS, + &pAdapter->XmitStatus + ); + + // + // SyncCardAcknowledgeTransmit. + // + NdisRawWritePortUchar( + pAdapter->MappedIoBaseAddr + NIC_INTR_STATUS, + ISR_XMIT | ISR_XMIT_ERR + ); + + NdisRawWritePortUchar( + pAdapter->MappedIoBaseAddr + NIC_INTR_MASK, + pAdapter->NicInterruptMask + ); + + return(FALSE); +} + + +BOOLEAN SyncCardUpdateCounters( + IN PVOID SynchronizeContext +) + +/*++ + +Routine Description: + + Updates the values of the three counters (frame alignment errors, + CRC errors, and missed packets). + +Arguments: + + SynchronizeContext - pointer to the adapter block + +Return Value: + + None. + +--*/ + +{ + PELNKII_ADAPTER pAdapter = ((PELNKII_ADAPTER)SynchronizeContext); + UCHAR Tmp; + + NdisRawReadPortUchar(pAdapter->MappedIoBaseAddr + NIC_FAE_ERR_CNTR, &Tmp); + pAdapter->FrameAlignmentErrors += Tmp; + + NdisRawReadPortUchar(pAdapter->MappedIoBaseAddr + NIC_CRC_ERR_CNTR, &Tmp); + pAdapter->CrcErrors += Tmp; + + NdisRawReadPortUchar(pAdapter->MappedIoBaseAddr + NIC_MISSED_CNTR, &Tmp); + pAdapter->MissedPackets += Tmp; + + return(FALSE); +} + +BOOLEAN SyncCardHandleOverflow( + IN PVOID SynchronizeContext +) + +/*++ + +Routine Description: + + Sets all the flags for dealing with a receive overflow, stops the card + and acknowledges all outstanding interrupts. + +Arguments: + + SynchronizeContext - pointer to the adapter block + +Return Value: + + None. + +--*/ + +{ + PELNKII_ADAPTER pAdapter = (PELNKII_ADAPTER)SynchronizeContext; + UCHAR InterruptStatus; + + IF_LOG( ElnkiiLog('F');) + + // + // This is a copy of CardStop(). This is changed in minor ways since + // we are already synchornized with interrupts. + // + + // + // Turn on the STOP bit in the Command register. + // + SyncCardStop(pAdapter); + + // + // Wait for ISR_RESET, but only for 1.6 milliseconds (as + // described in the March 1991 8390 addendum), since that + // is the maximum time for a software reset to occur. + // + // + NdisStallExecution(2000); + + // + // Save whether we were transmitting to avoid a timing problem + // where an indication resulted in a send. + // + if (!(pAdapter->InterruptStatus & (ISR_XMIT | ISR_XMIT_ERR))) + { + CardGetInterruptStatus(pAdapter, &InterruptStatus); + if (!(InterruptStatus & (ISR_XMIT | ISR_XMIT_ERR))) + { + pAdapter->OverflowRestartXmitDpc = pAdapter->TransmitInterruptPending; + + IF_LOUD(DbgPrint("ORXD=%x\n", pAdapter->OverflowRestartXmitDpc);) + } + } + + // + // Clear the Remote Byte Count register so that ISR_RESET + // will come on. + // + NdisRawWritePortUchar(pAdapter->MappedIoBaseAddr + NIC_RMT_COUNT_MSB, 0); + NdisRawWritePortUchar(pAdapter->MappedIoBaseAddr + NIC_RMT_COUNT_LSB, 0); + + // + // According to National Semiconductor, the next check is necessary + // See Step 5. of the overflow process + // + // NOTE: The setting of variables to check if the transmit has completed + // cannot be done here because anything in the ISR has already been ack'ed + // inside the main DPC. Thus, the setting of the variables, described in + // the Handbook was moved to the main DPC. + // + // Continued: If you did the check here, you will doubly transmit most + // packets that happened to be on the card when the overflow occurred. + // + + // + // Put the card in loopback mode, then start it. + // + NdisRawWritePortUchar( + pAdapter->MappedIoBaseAddr + NIC_XMIT_CONFIG, + TCR_LOOPBACK + ); + + // + // Start the card. This does not Undo the loopback mode. + // + NdisRawWritePortUchar( + pAdapter->MappedIoBaseAddr + NIC_COMMAND, + CR_START | CR_NO_DMA + ); + + return(FALSE); +} + + + +#if DBG +// +// Following function is for debug stuff. +// +VOID ElnkiiDisplayStatus( + PELNKII_ADAPTER pAdapter +) +{ + // + // NIC registers that we can read. + // + UCHAR NicXmitStatus; // NIC_XMIT_STATUS + UCHAR NicFifo; // NIC_FIFO + UCHAR NicInterruptStatus; // NIC_INTR_STATUS + UCHAR NicCurrent; // NIC_CURRENT + UCHAR NicReceiveStatus; // NIC_RCV_STATUS + UCHAR NicFrameErrorCounter; // NIC_FAE_ERR_CNTR + UCHAR NicCrcErrorCounter; // NIC_CRC_ERR_CNTR + UCHAR NicMissedCounter; // NIC_MISSED_CNTR + + // + // Gate-Array registers that we can read. + // + UCHAR GaPageStart; // GA_PAGE_START + UCHAR GaPageStop; // GA_PAGE_STOP + UCHAR GaDrqTimer; // GA_DRQ_TIMER + UCHAR GaIoBase; // GA_IO_BASE + UCHAR GaMemoryBase; // GA_MEM_BASE + UCHAR GaConfig; // GA_CONFIG + UCHAR GaControl; // GA_CONTROL + UCHAR GaStatus; // GA_STATUS + UCHAR GaIntDmaConfig; // GA_INT_DMA_CONFIG + UCHAR GaDmaAddressMsb; // GA_DMA_ADDR_MSB + UCHAR GaDmaAddressLsb; // GA_DMA_ADDR_LSB + UCHAR GaRegFileAccessMsb; // GA_REG_FILE_MSB + UCHAR GaRegFileAccessLsb; // GA_REG_FILE_LSB + + // + // Get the NIC xmit status + // + NdisRawReadPortUchar( + pAdapter->MappedIoBaseAddr + NIC_XMIT_STATUS, + &NicXmitStatus + ); + + // + // Display NIC status information. + // + DbgPrint( + "NIC_XMIT_STATUS: TSR_XMIT_OK - %x\n" + " TSR_COLLISION - %x\n" + " TSR_ABORTED - %x\n" + " TSR_NO_CARRIER - %x\n" + " TSR_NO_CDH - %x\n", + NicXmitStatus & TSR_XMIT_OK, + NicXmitStatus & TSR_COLLISION, + NicXmitStatus & TSR_ABORTED, + NicXmitStatus & TSR_NO_CARRIER, + NicXmitStatus & TSR_NO_CDH + ); + + // + // Get the nic fifo + // + NdisRawReadPortUchar( + pAdapter->MappedIoBaseAddr + NIC_FIFO, + &NicFifo + ); + + DbgPrint("NIC_FIFO: %x\n", NicFifo); + + // + // Get the nic interrupt status + // + NdisRawReadPortUchar( + pAdapter->MappedIoBaseAddr + NIC_INTR_STATUS, + &NicInterruptStatus + ); + + DbgPrint( + "NIC_INTR_STATUS: ISR_EMPTY - %x\n" + " ISR_RCV - %x\n" + " ISR_XMIT - %x\n" + " ISR_RCV_ERR - %x\n" + " ISR_XMIT_ERR - %x\n" + " ISR_OVERFLOW - %x\n" + " ISR_COUNTER - %x\n" + " ISR_RESET - %x\n", + NicInterruptStatus & ISR_EMPTY, + NicInterruptStatus & ISR_RCV, + NicInterruptStatus & ISR_XMIT, + NicInterruptStatus & ISR_RCV_ERR, + NicInterruptStatus & ISR_XMIT_ERR, + NicInterruptStatus & ISR_OVERFLOW, + NicInterruptStatus & ISR_COUNTER, + NicInterruptStatus & ISR_RESET + ); + + + // + // Get the nic current + // + NdisRawReadPortUchar( + pAdapter->MappedIoBaseAddr + NIC_CURRENT, + &NicCurrent + ); + + DbgPrint("NIC_CURRENT: %x\n", NicCurrent); + + // + // Get the nic receive status + // + NdisRawReadPortUchar( + pAdapter->MappedIoBaseAddr + NIC_RCV_STATUS, + &NicReceiveStatus + ); + + + DbgPrint( + "NIC_RCV_STATUS: RSR_PACKET_OK - %x\n" + " RSR_CRC_ERROR - %x\n" + " RSR_MULTICAST - %x\n" + " RSR_DISABLED - %x\n", + " RSR_DEFERRING - %x\n", + NicReceiveStatus & RSR_PACKET_OK, + NicReceiveStatus & RSR_CRC_ERROR, + NicReceiveStatus & RSR_MULTICAST, + NicReceiveStatus & RSR_DISABLED, + NicReceiveStatus & RSR_DEFERRING + ); + + // + // Get the nic frame error counter + // + NdisRawReadPortUchar( + pAdapter->MappedIoBaseAddr + NIC_FAE_ERR_CNTR, + &NicFrameErrorCounter + ); + + DbgPrint("NIC_FAE_ERR_CNTR: %x\n", NicFrameErrorCounter); + + // + // Get the nic crc error counter + // + NdisRawReadPortUchar( + pAdapter->MappedIoBaseAddr + NIC_CRC_ERR_CNTR, + &NicCrcErrorCounter + ); + + DbgPrint("NIC_CRC_ERR_CNTR: %x\n", NicCrcErrorCounter); + + // + // Get the nic missed counter + // + NdisRawReadPortUchar( + pAdapter->MappedIoBaseAddr + NIC_MISSED_CNTR, + &NicMissedCounter + ); + + DbgPrint("NIC_MISSED_CNTR: %x\n", NicMissedCounter); + + // + // Get the GA page start. + // + NdisRawReadPortUchar( + pAdapter->MappedIoBaseAddr + GA_PAGE_START, + &GaPageStart + ); + + DbgPrint("GA_PAGE_START: %x\n", GaPageStart); + + + // + // Get the GA page stop. + // + NdisRawReadPortUchar( + pAdapter->MappedIoBaseAddr + GA_PAGE_STOP, + &GaPageStop + ); + + DbgPrint("GA_PAGE_STOP: %x\n", GaPageStop); + + // + // Get the GA drq timer + // + NdisRawReadPortUchar( + pAdapter->MappedIoBaseAddr + GA_DRQ_TIMER, + &GaDrqTimer + ); + + DbgPrint( + "GA_DRQ_TIMER: DQTR_16_BYTE - %x\n" + " DQTR_8_BYTE - %x\n", + GaDrqTimer == DQTR_16_BYTE, + GaDrqTimer == DQTR_8_BYTE + ); + + // + // Get the GA io base + // + NdisRawReadPortUchar( + pAdapter->MappedIoBaseAddr + GA_IO_BASE, + &GaIoBase + ); + + DbgPrint("GA_IO_BASE: %x\n", GaIoBase); + + // + // Get the GA memory base + // + NdisRawReadPortUchar( + pAdapter->MappedIoBaseAddr + GA_MEM_BASE, + &GaMemoryBase + ); + + DbgPrint("GA_MEM_BASE: %x\n", GaMemoryBase); + + // + // Get the GA config + // + NdisRawReadPortUchar( + pAdapter->MappedIoBaseAddr + GA_CONFIG, + &GaConfig + ); + + DbgPrint( + "GA_CONFIG: GACFR_TC_MASK - %x\n" + " GACFR_RAM_SEL - %x\n" + " GACFR_MEM_BANK1 - %x\n", + GaConfig & GACFR_TC_MASK, + GaConfig & GACFR_RAM_SEL, + GaConfig & GACFR_MEM_BANK1 + ); + + // + // Get the GA control + // + NdisRawReadPortUchar( + pAdapter->MappedIoBaseAddr + GA_CONTROL, + &GaControl + ); + + DbgPrint( + "GA_CONTROL: CTRL_START - %x\n" + " CTRL_STOP - %x\n" + " CTRL_DIR_DOWN - %x\n" + " CTRL_DIR_UP - %x\n" + " CTRL_DB_SEL - %x\n" + " CTRL_PROM_SEL - %x\n" + " CTRL_GA_SEL - %x\n" + " CTRL_BNC - %x\n" + " CTRL_DIX - %x\n" + " CTRL_RESET - %x\n", + GaControl & CTRL_START, + !(GaControl & CTRL_STOP), + GaControl & CTRL_DIR_DOWN, + !(GaControl & CTRL_DIR_UP), + GaControl & CTRL_DB_SEL, + GaControl & CTRL_PROM_SEL, + !(GaControl & CTRL_PROM_SEL), + GaControl & CTRL_BNC, + !(GaControl & CTRL_DIX), + GaControl & CTRL_RESET + ); + + + // + // Get the GA status + // + NdisRawReadPortUchar( + pAdapter->MappedIoBaseAddr + GA_STATUS, + &GaStatus + ); + + DbgPrint( + "GA_STATUS: STREG_DP_READY - %x\n" + " STREG_UNDERFLOW - %x\n" + " STREG_OVERFLOW - %x\n" + " STREG_IN_PROG - %x\n", + GaStatus & STREG_DP_READY, + GaStatus & STREG_UNDERFLOW, + GaStatus & STREG_OVERFLOW, + GaStatus & STREG_IN_PROG + ); + + // + // Get the GA interrupt dma config + // + NdisRawReadPortUchar( + pAdapter->MappedIoBaseAddr + GA_INT_DMA_CONFIG, + &GaIntDmaConfig + ); + + DbgPrint("GA_INT_DMA_CONFIG: %x\n", GaIntDmaConfig); + + // + // Get the GA dma address msb + // + NdisRawReadPortUchar( + pAdapter->MappedIoBaseAddr + GA_DMA_ADDR_MSB, + &GaDmaAddressMsb + ); + + DbgPrint("GA_DMA_ADDR_MSB: %x\n", GaDmaAddressMsb); + + // + // Get the GA dma address lsb + // + NdisRawReadPortUchar( + pAdapter->MappedIoBaseAddr + GA_DMA_ADDR_LSB, + &GaDmaAddressLsb + ); + + DbgPrint("GA_DMA_ADDR_LSB: %x\n", GaDmaAddressLsb); + + // + // Get the GA register file access msb + // + NdisRawReadPortUchar( + pAdapter->MappedIoBaseAddr + GA_REG_FILE_MSB, + &GaRegFileAccessMsb + ); + + DbgPrint("GA_REG_FILE_MSB: %x\n", GaRegFileAccessMsb); + + // + // Get the GA register file access lsb + // + NdisRawReadPortUchar( + pAdapter->MappedIoBaseAddr + GA_REG_FILE_LSB, + &GaRegFileAccessLsb + ); + + DbgPrint("GA_REG_FILE_LSB: %x\n", GaRegFileAccessLsb); + +} + +#endif |