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

📄 routines.c

📁 e100bex网卡驱动程序
💻 C
📖 第 1 页 / 共 2 页
字号:
        // Copy the current multicast addresses to the command block
        for (i = 0;(i < Adapter->NumberOfMcAddresses) &&
            (i < MAX_MULTICAST_ADDRESSES); i++)
            for (j = 0; j < ETH_LENGTH_OF_ADDRESS; j++)
                *(McAddress++) = Adapter->PrivateMulticastBuffer[i][j];

            // Setup the command and status words of the command block
            SwTcb->Tcb->TxCbHeader.CbStatus = 0;
            SwTcb->Tcb->TxCbHeader.CbCommand = CB_S_BIT | CB_MULTICAST;

            // If CU is idle (very first command) then we must
            // setup the general pointer and issue a full CU-start
            if (Adapter->TransmitIdle)
            {
                TRACE2(Adapter, ("CU is idle -- First MC added to Active List\n"));

                QueuePushHead(&Adapter->ActiveChainList, &SwTcb->Link);

                // Wait for the SCB to clear before we set the general pointer
                WaitScb(Adapter);

                // Don't try to start the transmitter if the command unit is not
                // idle ((not idle) == (Cu-Suspended or Cu-Active)).
                if ((Adapter->CSRAddress->ScbStatus & SCB_CUS_MASK) != SCB_CUS_IDLE)
                {
                    TRACESTR(Adapter, ("CU Not IDLE\n"));
                    ASSERT(0);
                    NdisStallExecution(25);     // hack to wait 25us
                }

                Adapter->CSRAddress->ScbGeneralPointer = SwTcb->TcbPhys;

                D100IssueScbCommand(Adapter, SCB_CUC_START, FALSE);

                Adapter->TransmitIdle = FALSE;
                Adapter->ResumeWait = TRUE;


            }

            // If the CU has already been started, then append this
            // TCB onto the end of the transmit chain, and issue a CU-Resume.
            else
            {
                TRACE2(Adapter, ("adding MCB to Active chain\n"));
                QueuePutTail(&Adapter->ActiveChainList, &SwTcb->Link);

                // Clear the suspend bit on the previous packet.
                SwTcb->PreviousTcb->TxCbHeader.CbCommand &= ~CB_S_BIT;

                // We need to wait for the SCB to clear when inserting a non-
                // transmit command dynamically into the CBL (command block list).
                Adapter->ResumeWait = TRUE;

                // Issue a CU-Resume command to the device -- and wait for the
                // SCB command word to clear first.
                if (!D100IssueScbCommand(Adapter, SCB_CUC_RESUME, TRUE))
                {
                    TRACESTR(Adapter, ("CU-resume failed\n"));
                }

            }
    }
    DEBUGCHAR(Adapter,'b');

}


//-----------------------------------------------------------------------------
// Procedure:   D100IssueSelectiveReset
//
// Description: This routine will issue a selective reset, forcing the adapter
//              the CU and RU back into their idle states.  The receive unit
//              will then be re-enabled if it was previously enabled, because
//              an RNR interrupt will be generated when we abort the RU.
//
// Arguments:
//      Adapter - ptr to Adapter object instance
//
// Returns:
//      NOTHING
//-----------------------------------------------------------------------------

VOID
D100IssueSelectiveReset(
                        PD100_ADAPTER Adapter
                        )

{
    //    BOOLEAN     EnableInts = TRUE;
#if DBG
    UINT counter=0;
    USHORT x;
#endif
    UINT i;
    DEBUGFUNC("D100IssueSelectiveReset");
    TRACE2(Adapter, ("Entered D100IssueSelectiveReset\n"));

    INITSTR(("\n"));
    // Wait for the SCB to clear before we check the CU status.
    WaitScb(Adapter);

    // If we have issued any transmits, then the CU will either be active, or
    // in the suspended state.  If the CU is active, then we wait for it to be
    // suspended.  If the the CU is suspended, then we need to put the CU back
    // into the idle state by issuing a selective reset.
    if (Adapter->TransmitIdle == FALSE)
    {
        // Wait for suspended state
        for (i=1000; (i != 0) && (Adapter->CSRAddress->ScbStatus & SCB_CUS_MASK) == SCB_CUS_ACTIVE; i--)
            //        while ((Adapter->CSRAddress->ScbStatus & SCB_CUS_MASK) == SCB_CUS_ACTIVE)
        {
            TRACESTR(Adapter, ("CU active -- wait for it to suspend. ScbStatus=%04x\n",
                Adapter->CSRAddress->ScbStatus));
            NdisStallExecution(20);
        }
        if (!i)
        {
            HARDWARE_NOT_RESPONDING (Adapter);
            return;
        }

        // Check the current status of the receive unit
        if ((Adapter->CSRAddress->ScbStatus & SCB_RUS_MASK) != SCB_RUS_IDLE)
        {
            // Issue an RU abort.  Since an interrupt will be issued, the
            // RU will be started by the DPC.
            D100IssueScbCommand(Adapter, SCB_RUC_ABORT, TRUE);
        }

        // Issue a selective reset.
        TRACESTR(Adapter, ("CU suspended. ScbStatus=%04x Issue selective reset\n",
            Adapter->CSRAddress->ScbStatus));
        Adapter->CSRAddress->Port = PORT_SELECTIVE_RESET;

        // stall 20 us (only need 10) after a port sel-reset command
        NdisStallExecution(20);

        for (i=100; i != 0; i--)
        {
            if (Adapter->CSRAddress->Port == 0)
                break;
            NdisStallExecution(10);
        }
        if (!i)
        {
            HARDWARE_NOT_RESPONDING (Adapter);
            return;
        }

        // disable interrupts after issuing reset, because the int
        // line gets raised when reset completes.
        D100DisableInterrupt(Adapter);

        // Restore the transmit software flags.
        Adapter->TransmitIdle = TRUE;
        Adapter->ResumeWait = TRUE;

    }
}


//-----------------------------------------------------------------------------
// Procedure:   D100SubmitCommandBlockAndWait
//
// Description: 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.
//
// Arguments:
//      Adapter - ptr to Adapter object instance
//
// Returns:
//      TRUE - If we successfully submitted and completed the command.
//      FALSE - If we didn't successfully submit and complete the command.
//-----------------------------------------------------------------------------

BOOLEAN
D100SubmitCommandBlockAndWait(
                              IN PD100_ADAPTER Adapter
                              )

{
    UINT            Delay;
    BOOLEAN         Status;

    // Points to the Non Tx Command Block.
    volatile PNON_TRANSMIT_CB CommandBlock = Adapter->NonTxCmdBlock;

    DEBUGFUNC("D100SubmitCommandBlockAndWait");
    TRACE2(Adapter, ("Entered D100SubmitCommandBlockAndWait\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 ((Adapter->CSRAddress->ScbStatus & SCB_CUS_MASK) == SCB_CUS_ACTIVE)
    {
        TRACESTR(Adapter, ("Scb %08x ScbStatus %04x\n", Adapter->CSRAddress, Adapter->CSRAddress->ScbStatus));

        ASSERT(0);

        return (FALSE);
    }
#endif


    // Start the command unit.
    D100IssueScbCommand(Adapter, SCB_CUC_START, FALSE);

    // Wait for the SCB to clear, indicating the completion of the command.
    if (WaitScb(Adapter) == FALSE)
    {
        TRACESTR(Adapter, ("WaitScb failed\n"));

        D100LogError(Adapter, EVENT_6, NDIS_ERROR_CODE_TIMEOUT, 0);

        return (FALSE);
    }

    // Wait for some status
    Delay = 300000;
    while ((!(CommandBlock->NonTxCb.Config.ConfigCBHeader.CbStatus & CB_STATUS_COMPLETE)) && Delay)
    {
        NdisStallExecution(10);
        Delay--;
    }

    if (!Delay)
    {
        HARDWARE_NOT_RESPONDING (Adapter);
        return (FALSE);
    }

    // Ack any interrupts
    if (Adapter->CSRAddress->ScbStatus & SCB_ACK_MASK)
    {
        // Ack all pending interrupts now
        Adapter->CSRAddress->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))
    {
        TRACESTR(Adapter, ("Command failed\n"));
        Status = FALSE;
    }
    else
        Status = TRUE;

    return (Status);
}

//-----------------------------------------------------------------------------
// Procedure: GetConnectionStatus
//
// Description: This function returns the connection status that is
//              a required indication for PC 97 specification from MS
//              the value we are looking for is if there is link to the
//              wire or not.
//
// Arguments: IN Adapter structure pointer
//
// Returns:   NdisMediaStateConnected
//            NdisMediaStateDisconnected
//-----------------------------------------------------------------------------
NDIS_MEDIA_STATE
GetConnectionStatus( IN PD100_ADAPTER Adapter )
{
    USHORT  MdiStatusReg;

    // Read the status register at phy 1
    MdiRead(Adapter, MDI_STATUS_REG, Adapter->PhyAddress, &MdiStatusReg);
    MdiRead(Adapter, MDI_STATUS_REG, Adapter->PhyAddress, &MdiStatusReg);
    if (MdiStatusReg & MDI_SR_LINK_STATUS)
        return(NdisMediaStateConnected);
    else
        return(NdisMediaStateDisconnected);

}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -