⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 e100bexcard.cpp

📁 nmE100bex网卡驱动程序
💻 CPP
📖 第 1 页 / 共 4 页
字号:
    // 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 + -