2020-09-30 17:12:29 +02:00

3156 lines
63 KiB
C
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*++
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