📄 e100bexcard.cpp
字号:
// Wait 500 milliseconds
StallExecution(500);
if (!SetNodeAddress(NodeAddress))
{
return FALSE;
}
return TRUE;
}
////////////////////////////////////////////////////////////////////
// E100bexCard::WaitScb
//
// This routine checks to see if the D100 has accepted a command.
// It does so by checking the command field in the SCB, which will
// be zeroed by the D100 upon accepting a command. The loop waits
// for up to 600 milliseconds for command acceptance.
//
// Parameters:
// None
// IRQL:
//
// Return Mode:
//
// Returns:
// TRUE if the SCB cleared within 600 milliseconds.
// FALSE if it didn't clear within 600 milliseconds
// NOTE:
//
inline BOOLEAN E100bexCard::WaitScb(void)
{
TRACE("Entered E100bexCard::WaitScb");
UINT count = 60000;
do
{
if (! (UCHAR) m_CSRStruc.ScbCommandLow )
{
return TRUE;
}
NdisStallExecution(10);
} while (count--);
// If we fall through, we have a problem.
TRACE("HARDWARE_NOT_RESPONDING\n");
return FALSE;
}
////////////////////////////////////////////////////////////////////
// E100bexCard::IssueScbCommand
//
// This routine will issue a command to the D100.
//
// Parameters:
// ScbCommandLow - The command that is to be issued
// WaitForSCB - A boolean value indicating whether or not a wait for SCB
// must be done before the command is issued to the chip
// IRQL:
//
// Return Mode:
// Synchronous
// Returns:
// TRUE if the command was issued to the chip successfully
// FALSE if the command was not issued to the chip
// NOTE:
//
inline BOOLEAN E100bexCard::IssueScbCommand(UCHAR ScbCommandLow, BOOLEAN WaitForScb)
{
TRACE("Entered E100bexCard::IssueScbCommand");
if (TRUE == WaitForScb)
{
if ( TRUE != WaitScb() )
{
TRACE("WaitScb failed\n");
return FALSE;
}
}
m_CSRStruc.ScbCommandLow = ScbCommandLow;
return TRUE;
}
////////////////////////////////////////////////////////////////////
// E100bexCard::SubmitCommandBlockAndWait
//
// This routine will submit a command block to be executed, and
// then it will wait for that command block to be executed. Since
// board ints will be disabled, we will ack the interrupt in
// this routine.
//
// Parameters:
// None
// IRQL:
//
// Return Mode:
//
// Returns:
// TRUE - If we successfully submitted and completed the command.
// FALSE - If we didn't successfully submit and complete the command.
// NOTE:
//
BOOLEAN E100bexCard::SubmitCommandBlockAndWait(void)
{
BOOLEAN Status;
// Points to the Non Tx Command Block.
volatile PNON_TRANSMIT_CB CommandBlock = m_NonTxCmdBlock;
TRACE("Entered E100bexCard::SubmitCommandBlockAndWait\n");
// Set the Command Block to be the last command block
CommandBlock->NonTxCb.Config.ConfigCBHeader.CbCommand |= CB_EL_BIT;
// Clear the status of the command block
CommandBlock->NonTxCb.Config.ConfigCBHeader.CbStatus = 0;
#if DBG
// Don't try to start the CU if the command unit is active.
if ((USHORT(m_CSRStruc.ScbStatus) & SCB_CUS_MASK) == SCB_CUS_ACTIVE)
{
TRACE("Scb %08x ScbStatus %04x\n", &m_CSRStruc, USHORT(m_CSRStruc.ScbStatus) );
ASSERT(0);
return FALSE;
}
#endif
// Start the command unit.
IssueScbCommand(SCB_CUC_START, FALSE);
// Wait for the SCB to clear, indicating the completion of the command.
if (WaitScb() == FALSE)
{
TRACE("WaitScb failed\n");
return FALSE;
}
// Wait for some status
UINT Delay = 300000;
while ((!(CommandBlock->NonTxCb.Config.ConfigCBHeader.CbStatus & CB_STATUS_COMPLETE)) && Delay)
{
NdisStallExecution(10);
Delay--;
}
if (!Delay)
{
TRACE("HARDWARE_NOT_RESPONDING\n");
return FALSE;
}
// Ack any interrupts
USHORT ScbStatus = USHORT(m_CSRStruc.ScbStatus);
if ( ScbStatus & SCB_ACK_MASK)
{
// Ack all pending interrupts now
m_CSRStruc.ScbStatus = (USHORT)(ScbStatus & SCB_ACK_MASK);
}
// Check the status of the command, and if the command failed return FALSE,
// otherwise return TRUE.
if (!(CommandBlock->NonTxCb.Config.ConfigCBHeader.CbStatus & CB_STATUS_OK))
{
TRACE("Command failed\n");
Status = FALSE;
}
else
{
Status = TRUE;
}
return Status;
}
////////////////////////////////////////////////////////////////////
// E100bexCard::Configure
//
// This routine will issue a configure command to the 82557.
// This command will be executed in polled mode. The
// Configuration parameters that are user configurable will
// have been set when the driver parsed the configuration
// parameters out of the registry.
//
// Parameters:
// None
// IRQL:
//
// Return Mode:
//
// Returns:
// TRUE - If the configure command was successfully issued and completed
// FALSE - If the configure command failed to complete properly
// NOTE:
//
BOOLEAN E100bexCard::Configure(void)
{
TRACE("E100bexCard::Configure");
m_PacketFilter = NDIS_PACKET_TYPE_DIRECTED | NDIS_PACKET_TYPE_MULTICAST ;
// Setup the non-transmit command block header for the configure command.
m_NonTxCmdBlockHdr->CbStatus = 0;
m_NonTxCmdBlockHdr->CbCommand = CB_CONFIGURE;
m_NonTxCmdBlockHdr->CbLinkPointer = DRIVER_NULL;
// Fill in the configure command data.
// First fill in the static (end user can't change) config bytes
m_NonTxCmdBlock->NonTxCb.Config.ConfigBytes[0] = CB_557_CFIG_DEFAULT_PARM0;
m_NonTxCmdBlock->NonTxCb.Config.ConfigBytes[2] = CB_557_CFIG_DEFAULT_PARM2;
m_NonTxCmdBlock->NonTxCb.Config.ConfigBytes[3] = CB_557_CFIG_DEFAULT_PARM3;
m_NonTxCmdBlock->NonTxCb.Config.ConfigBytes[6] = CB_557_CFIG_DEFAULT_PARM6;
m_NonTxCmdBlock->NonTxCb.Config.ConfigBytes[9] = CB_557_CFIG_DEFAULT_PARM9;
m_NonTxCmdBlock->NonTxCb.Config.ConfigBytes[10] = CB_557_CFIG_DEFAULT_PARM10;
m_NonTxCmdBlock->NonTxCb.Config.ConfigBytes[11] = CB_557_CFIG_DEFAULT_PARM11;
m_NonTxCmdBlock->NonTxCb.Config.ConfigBytes[12] = CB_557_CFIG_DEFAULT_PARM12;
m_NonTxCmdBlock->NonTxCb.Config.ConfigBytes[13] = CB_557_CFIG_DEFAULT_PARM13;
m_NonTxCmdBlock->NonTxCb.Config.ConfigBytes[14] = CB_557_CFIG_DEFAULT_PARM14;
m_NonTxCmdBlock->NonTxCb.Config.ConfigBytes[16] = CB_557_CFIG_DEFAULT_PARM16;
m_NonTxCmdBlock->NonTxCb.Config.ConfigBytes[17] = CB_557_CFIG_DEFAULT_PARM17;
m_NonTxCmdBlock->NonTxCb.Config.ConfigBytes[18] = CB_557_CFIG_DEFAULT_PARM18;
m_NonTxCmdBlock->NonTxCb.Config.ConfigBytes[20] = CB_557_CFIG_DEFAULT_PARM20;
m_NonTxCmdBlock->NonTxCb.Config.ConfigBytes[21] = CB_557_CFIG_DEFAULT_PARM21;
// Now fill in the rest of the configuration bytes (the bytes that contain
// user configurable parameters).
// Set the Tx and Rx Fifo limits
m_NonTxCmdBlock->NonTxCb.Config.ConfigBytes[1] =
(UCHAR) ((m_Ai.AiTxFifo << 4) | m_Ai.AiRxFifo);
if (m_Ai.MWIEnable)
{
m_NonTxCmdBlock->NonTxCb.Config.ConfigBytes[3] |= CB_CFIG_B3_MWI_ENABLE;
}
// Set the Tx and Rx DMA maximum byte count fields.
if ((m_Ai.AiRxDmaCount) || (m_Ai.AiTxDmaCount))
{
m_NonTxCmdBlock->NonTxCb.Config.ConfigBytes[4] =
m_Ai.AiRxDmaCount;
m_NonTxCmdBlock->NonTxCb.Config.ConfigBytes[5] =
(UCHAR) (m_Ai.AiTxDmaCount | CB_CFIG_DMBC_EN);
}
else
{
m_NonTxCmdBlock->NonTxCb.Config.ConfigBytes[4] =
CB_557_CFIG_DEFAULT_PARM4;
m_NonTxCmdBlock->NonTxCb.Config.ConfigBytes[5] =
CB_557_CFIG_DEFAULT_PARM5;
}
m_NonTxCmdBlock->NonTxCb.Config.ConfigBytes[7] =
(UCHAR) ((CB_557_CFIG_DEFAULT_PARM7 & (~CB_CFIG_URUN_RETRY)) |
(m_Ai.AiUnderrunRetry << 1)
);
// Setup for MII or 503 operation. The CRS+CDT bit should only be set
// when operating in 503 mode.
if ( m_Phy.GetPhyAddress() == 32)
{
m_NonTxCmdBlock->NonTxCb.Config.ConfigBytes[8] =
(CB_557_CFIG_DEFAULT_PARM8 & (~CB_CFIG_503_MII));
m_NonTxCmdBlock->NonTxCb.Config.ConfigBytes[15] =
(CB_557_CFIG_DEFAULT_PARM15 | CB_CFIG_CRS_OR_CDT);
}
else
{
m_NonTxCmdBlock->NonTxCb.Config.ConfigBytes[8] =
(CB_557_CFIG_DEFAULT_PARM8 | CB_CFIG_503_MII);
m_NonTxCmdBlock->NonTxCb.Config.ConfigBytes[15] =
(CB_557_CFIG_DEFAULT_PARM15 & (~CB_CFIG_CRS_OR_CDT));
}
// Setup Full duplex stuff
// If forced to half duplex
if (m_Ai.AiForceDpx == 1)
m_NonTxCmdBlock->NonTxCb.Config.ConfigBytes[19] =
(CB_557_CFIG_DEFAULT_PARM19 &
(~(CB_CFIG_FORCE_FDX| CB_CFIG_FDX_ENABLE)));
// If forced to full duplex
else if (m_Ai.AiForceDpx == 2)
m_NonTxCmdBlock->NonTxCb.Config.ConfigBytes[19] =
(CB_557_CFIG_DEFAULT_PARM19 | CB_CFIG_FORCE_FDX);
// If auto-duplex
else
{
// We must force full duplex on if we are using PHY 0, and we are
// supposed to run in FDX mode. We do this because the D100 has only
// one FDX# input pin, and that pin will be connected to PHY 1.
if ((m_Phy.GetPhyAddress() == 0) && (m_Phy.GetCurrentDuplexMode() == 2))
{
m_NonTxCmdBlock->NonTxCb.Config.ConfigBytes[19] =
(CB_557_CFIG_DEFAULT_PARM19 | CB_CFIG_FORCE_FDX);
}
else
{
m_NonTxCmdBlock->NonTxCb.Config.ConfigBytes[19] =
CB_557_CFIG_DEFAULT_PARM19;
}
}
//
// Store the current setting for BROADCAST/PROMISCUOS modes
m_OldParameterField = CB_557_CFIG_DEFAULT_PARM15;
// display the config info to the debugger
TRACE("Issuing Configure command\n");
TRACE("Config Block at virt addr %x, phys address %x\n",
&m_NonTxCmdBlockHdr->CbStatus, m_NonTxCmdBlockPhys);
for (UINT i=0; i < CB_CFIG_BYTE_COUNT; i++)
{
TRACE(" Config byte %x = %.2x\n", i, m_NonTxCmdBlock->NonTxCb.Config.ConfigBytes[i]);
}
// Wait for the SCB command word to clear before we set the general pointer
WaitScb();
ASSERT( 0 == (UCHAR) m_CSRStruc.ScbCommandLow) ;
m_CSRStruc.ScbGeneralPointer = m_NonTxCmdBlockPhys;
// Submit the configure command to the chip, and wait for it to complete.
if (!SubmitCommandBlockAndWait())
{
return FALSE;
}
else
{
return TRUE;
}
}
////////////////////////////////////////////////////////////////////
// E100bexCard::SetupIAAddress
//
// This routine will issue the IA setup command. This command
// will notify the 82557 (D100) of what its individual (node)
// address is. This command will be executed in polled mode.
//
// Parameters:
// None
// IRQL:
//
// Return Mode:
//
// Returns:
// TRUE - If the IA setup command was successfully issued and completed
// FALSE - If the IA setup command failed to complete properly
// NOTE:
//
BOOLEAN E100bexCard::SetNodeAddress(ETHERNET_ADDRESS NodeAddress)
{
TRACE("E100bexCard::SetupIAAddress\n");
// Individual Address Setup
m_NonTxCmdBlockHdr->CbStatus = 0;
m_NonTxCmdBlockHdr->CbCommand = CB_IA_ADDRESS;
m_NonTxCmdBlockHdr->CbLinkPointer = DRIVER_NULL;
// Copy in the station's individual address
for (UINT i = 0; i < ETH_LENGTH_OF_ADDRESS; i++)
{
m_NonTxCmdBlock->NonTxCb.Setup.IaAddress[i] = NodeAddress.m_bytes[i];
}
// Update the command list pointer. We don't need to do a WaitSCB here
// because this command is either issued immediately after a reset, or
// after another command that runs in polled mode. This guarantees that
// the low byte of the SCB command word will be clear. The only commands
// that don't run in polled mode are transmit and RU-start commands.
ASSERT( UCHAR(m_CSRStruc.ScbCommandLow) == 0);
m_CSRStruc.ScbGeneralPointer = m_NonTxCmdBlockPhys;
// Submit the IA configure command to the chip, and wait for it to complete.
if (FALSE == SubmitCommandBlockAndWait() )
{
TRACE("IA setup failed\n");
return FALSE;
}
else
{
return TRUE;
}
}
////////////////////////////////////////////////////////////////////
// E100bexCard::ClearAllCounters
//
// This routine will dump/reset all of the statistics.
//
// Parameters:
// None
// IRQL:
//
// Return Mode:
//
// NOTE:
//
VOID E100bexCard::ClearAllCounters()
{
TRACE("E100bexCard::ClearAllCounters\n");
// Load the dump counters pointer. Since this command is generated only
// after the IA setup has complete, we don't need to wait for the SCB
// command word to clear
ASSERT( UCHAR(m_CSRStruc.ScbCommandLow) == 0);
m_CSRStruc.ScbGeneralPointer = m_StatsCounterPhys;
// Issue the load dump counters address command
IssueScbCommand(SCB_CUC_DUMP_ADDR, FALSE);
// Now dump and reset all of the statistics
IssueScbCommand(SCB_CUC_DUMP_RST_STAT, TRUE);
// Now wait for the dump/reset to complete
for (UINT counter = 100000; counter != 0; counter--)
{
if (m_StatsCounters->CommandComplete == 0xA007)
{
break;
}
NdisStallExecution(20);
}
if (!counter)
{
TRACE("HARDWARE_NOT_RESPONDING\n");
return;
}
}
////////////////////////////////////////////////////////////////////
// E100bexCard::ReceiveUnitStarted
//
// This routine checks the status of the 82557's receive unit(RU),
// to see if it is started
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -