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

📄 csl_mdio.c

📁 合众达的一个例程
💻 C
📖 第 1 页 / 共 2 页
字号:
        switch( pd->phyState )
        {
        case PHYSTATE_MDIOINIT:
CheckTimeout:
            /* Here we just check timeout and try to find a PHY */
            if( pd->phyStateTicks >= PhyStateTimeout[pd->phyState] )
            {
                // Try the next PHY if anything but a MDIOINIT condition
                if( pd->phyState != PHYSTATE_MDIOINIT )
                    if( ++pd->phyAddr == 32 )
                        pd->phyAddr = 0;
                ltmp1 = MDIO_RGET( ALIVE );
                for( tmp1=0; tmp1<32; tmp1++ )
                {
                    if( ltmp1 & (1<<pd->phyAddr) )
                    {
                        if( MDIO_initPHY( pd, pd->phyAddr ) )
                            break;
                    }

                    if( ++pd->phyAddr == 32 )
                        pd->phyAddr = 0;
                }

                // If we didn't find a PHY, try again
                if( tmp1 == 32 )
                {
                    pd->phyAddr       = 0;
                    pd->phyState      = PHYSTATE_MDIOINIT;
                    pd->phyStateTicks = 0;
                    RetVal = MDIO_EVENT_PHYERROR;
                }
            }
            break;

        case PHYSTATE_NWAYSTART:
            /*
            // Here we started NWAY. We check to see if NWAY is done.
            // If not done and timeout occured, we find another PHY.
            */

            /* Read the CONTROL reg to verify "restart" isn't set */
            PHYREG_read( PHYREG_CONTROL, pd->phyAddr );
            PHYREG_waitResultsAck( tmp1, ack );
            if( !ack )
            {
                mdioInitStateMachine();
                break;
            }
            if( tmp1 & PHYREG_CONTROL_AUTORESTART )
                goto CheckTimeout;

            /* Flush latched "link status" from the STATUS reg */
            PHYREG_read( PHYREG_STATUS, pd->phyAddr );
            PHYREG_wait();

            pd->phyState = PHYSTATE_NWAYWAIT;

            /* Fallthrough */

        case PHYSTATE_NWAYWAIT:
            /*
            // Here we are waiting for NWAY to complete.
            */

            /* Read the STATUS reg to check for "complete" */
            PHYREG_read( PHYREG_STATUS, pd->phyAddr );
            PHYREG_waitResultsAck( tmp1, ack );
            if( !ack )
            {
                mdioInitStateMachine();
                break;
            }
            if( !(tmp1 & PHYREG_STATUS_AUTOCOMPLETE) )
                goto CheckTimeout;

            /* We can now check the negotiation results */
            PHYREG_read( PHYREG_ADVERTISE, pd->phyAddr );
            PHYREG_waitResults( tmp1 );
            PHYREG_read( PHYREG_PARTNER, pd->phyAddr );
            PHYREG_waitResults( tmp2 );

            /* Use the "best" results */
            tmp2 &= tmp1;
            if( tmp2 & PHYREG_ADVERTISE_FD100 )
                pd->PendingStatus = MDIO_LINKSTATUS_FD100;
            else if( tmp2 & PHYREG_ADVERTISE_HD100 )
                pd->PendingStatus = MDIO_LINKSTATUS_HD100;
            else if( tmp2 & PHYREG_ADVERTISE_FD10 )
                pd->PendingStatus = MDIO_LINKSTATUS_FD10;
            else if( tmp2 & PHYREG_ADVERTISE_HD10 )
                pd->PendingStatus = MDIO_LINKSTATUS_HD10;
            /*
            // If we get here the negotiation failed
            // We just use HD 100 or 10 - the best we think we can do
            */
            else if( tmp1 & PHYREG_ADVERTISE_HD100 )
                pd->PendingStatus = MDIO_LINKSTATUS_HD100;
            else
                pd->PendingStatus = MDIO_LINKSTATUS_HD10;

            pd->phyState = PHYSTATE_LINKWAIT;

            /* Fallthrough */

        case PHYSTATE_LINKWAIT:
            /*
            // Here we are waiting for LINK
            */

            /* Read the STATUS reg to check for "link" */
            PHYREG_read( PHYREG_STATUS, pd->phyAddr );
            PHYREG_waitResultsAck( tmp1, ack );
            if( !ack )
            {
                mdioInitStateMachine();
                break;
            }
            if( !(tmp1 & PHYREG_STATUS_LINKSTATUS) )
                goto CheckTimeout;

            /* Make sure we're linked in the MDIO module as well */
            ltmp1 = MDIO_RGET( LINK );
            if( !(ltmp1&(1<<pd->phyAddr)) )
                goto CheckTimeout;

            /* Start monitoring this PHY */
            MDIO_RSET( USERPHYSEL0, pd->phyAddr );

            /* Clear the link change flag so we can detect a "re-link" later */
            MDIO_RSET( LINKINTRAW, 1 );

            /* Setup our linked state */
            pd->phyState   = PHYSTATE_LINKED;
            pd->LinkStatus = pd->PendingStatus;
            RetVal = MDIO_EVENT_LINKUP;

            break;
        }
    }

    return( RetVal );
}


/*-----------------------------------------------------------------------*\
* MDIO_initPHY()
*
* Force a switch to the specified PHY, and start the negotiation process.
*
* Returns 1 if the PHY selection completed OK, else 0
\*-----------------------------------------------------------------------*/
uint MDIO_initPHY( Handle hMDIO, volatile uint phyAddr )
{
    MDIO_Device *pd = (MDIO_Device *)hMDIO;
    Uint16         tmp1,tmp2;
    Uint32         ltmp1;
    uint           i;

    /* Switch the PHY */
    pd->phyAddr = phyAddr;

    /* There will be no link when we're done with this PHY */
    pd->LinkStatus = MDIO_LINKSTATUS_NOLINK;

    /* Shutdown all other PHYs */
    ltmp1 = MDIO_RGET( ALIVE );
    for( i=0; ltmp1; i++,ltmp1>>=1 )
    {
        if( (ltmp1 & 1) && (i != phyAddr) )
        {
            PHYREG_write( PHYREG_CONTROL, i, PHYREG_CONTROL_ISOLATE |
                                             PHYREG_CONTROL_POWERDOWN );
            PHYREG_wait();
        }
    }

    /* Reset the PHY we plan to use */
    PHYREG_write( PHYREG_CONTROL, phyAddr, PHYREG_CONTROL_RESET );
    PHYREG_wait();

    /* Wait for reset to go low (but not forever) */
    for( i=0; i<5000; i++ )
    {
        PHYREG_read( PHYREG_CONTROL, phyAddr );
        PHYREG_waitResults( tmp1 );
        if( !(tmp1 & PHYREG_CONTROL_RESET) )
            break;
    }
    if( i == 5000 )
        return(0);

    /* Read the STATUS reg to check autonegotiation capability */
    PHYREG_read( PHYREG_STATUS, phyAddr );
    PHYREG_waitResults( tmp1 );

    /* See if we auto-neg or not */
    if( (pd->ModeFlags & MDIO_MODEFLG_AUTONEG) &&
                                     (tmp1 & PHYREG_STATUS_AUTOCAPABLE) )
    {
        /* We will use NWAY */

        /* Shift down the capability bits */
        tmp1 >>= 6;

        /* Mask with the capabilities */
        tmp1 &= ( PHYREG_ADVERTISE_FD100 | PHYREG_ADVERTISE_HD100 |
                  PHYREG_ADVERTISE_FD10 | PHYREG_ADVERTISE_HD10 );

        /* Set Ethernet message bit */
        tmp1 |= PHYREG_ADVERTISE_MSG;

        /* Write out advertisement */
        PHYREG_write( PHYREG_ADVERTISE, phyAddr, tmp1 );
        PHYREG_wait();

        /* Start NWAY */
        PHYREG_write( PHYREG_CONTROL, phyAddr, PHYREG_CONTROL_AUTONEGEN );
        PHYREG_wait();

        PHYREG_write( PHYREG_CONTROL, phyAddr,
                      PHYREG_CONTROL_AUTONEGEN|PHYREG_CONTROL_AUTORESTART );
        PHYREG_wait();

        /* Setup current state */
        pd->ModeFlags |= MDIO_MODEFLG_NWAYACTIVE;
        pd->phyState = PHYSTATE_NWAYSTART;
        pd->phyStateTicks = 0;  /* Reset timeout */
    }
    else
    {
        /* We will use a fixed configuration */

        /* Shift down the capability bits */
        tmp1 >>= 10;

        /* Mask with possible modes */
        tmp1 &= ( MDIO_MODEFLG_HD10 | MDIO_MODEFLG_FD10 |
                  MDIO_MODEFLG_HD100 | MDIO_MODEFLG_FD100 );

        /* Mask with what the User wants to allow */
        tmp1 &= pd->ModeFlags;

        /* If nothing if left, move on */
        if( !tmp1 )
            return(0);

        /* Setup Control word and pending status */
        if( tmp1 & MDIO_MODEFLG_FD100 )
        {
            tmp2 = PHYREG_CONTROL_SPEED100 | PHYREG_CONTROL_DUPLEXFULL;
            pd->PendingStatus = MDIO_LINKSTATUS_FD100;
        }
        else if( tmp1 & MDIO_MODEFLG_HD100 )
        {
            tmp2 = PHYREG_CONTROL_SPEED100;
            pd->PendingStatus = MDIO_LINKSTATUS_HD100;
        }
        else if( tmp1 & MDIO_MODEFLG_FD10 )
        {
            tmp2 = PHYREG_CONTROL_DUPLEXFULL;
            pd->PendingStatus = MDIO_LINKSTATUS_FD10;
        }
        else
        {
            tmp2 = 0;
            pd->PendingStatus = MDIO_LINKSTATUS_HD10;
        }

        /* Add in loopback if user wanted it */
        if( pd->ModeFlags & MDIO_MODEFLG_LOOPBACK )
            tmp2 |= PHYREG_CONTROL_LOOPBACK;

        /* Configure PHY */
        PHYREG_write( PHYREG_CONTROL, phyAddr, tmp2 );
        PHYREG_wait();

        /* Setup current state */
        pd->ModeFlags &= ~MDIO_MODEFLG_NWAYACTIVE;
        pd->phyState = PHYSTATE_LINKWAIT;
        pd->phyStateTicks = 0;  /* Reset timeout */
    }

    return(1);
}


/*-----------------------------------------------------------------------*\
* MDIO_phyRegRead()
*
* Raw data read of a PHY register.
*
* Returns 1 if the PHY ACK'd the read, else 0
\*-----------------------------------------------------------------------*/
uint MDIO_phyRegRead( volatile uint phyIdx, volatile uint phyReg, Uint16 *pData )
{
    uint data,ack;

    PHYREG_read( phyReg, phyIdx );
    PHYREG_waitResultsAck( data, ack );
    if( !ack )
        return(0);
    if( pData )
        *pData = data;
    return(1);
}


/*-----------------------------------------------------------------------*\
* MDIO_phyRegWrite()
*
* Raw data write of a PHY register.
*
* Returns 1 if the PHY ACK'd the write, else 0
\*-----------------------------------------------------------------------*/
uint MDIO_phyRegWrite( volatile uint phyIdx, volatile uint phyReg, Uint16 data )
{
    uint ack;

    PHYREG_write( phyReg, phyIdx, data );
    PHYREG_waitResultsAck( data, ack );
    if( !ack )
        return(0);
    return(1);
}

#endif /* MDIO_SUPPORT */
/******************************************************************************\
* End of mdio.c
\******************************************************************************/

⌨️ 快捷键说明

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