unsigned get_IEEE_phy_speed()

in portable/NetworkInterface/Zynq/x_emacpsif_physpeed.c [290:437]


    unsigned get_IEEE_phy_speed( XEmacPs * xemacpsp )
    {
        u16 temp;
        u16 control;
        u16 status;
        u16 partner_capabilities;

        #if XPAR_GIGE_PCS_PMA_CORE_PRESENT == 1
            u32 phy_addr = XPAR_PCSPMA_SGMII_PHYADDR;
        #else
            u32 phy_addr = detect_phy( xemacpsp );
        #endif
        FreeRTOS_printf( ( "Start PHY autonegotiation \n" ) );

        #if XPAR_GIGE_PCS_PMA_CORE_PRESENT == 1
        #else
            XEmacPs_PhyWrite( xemacpsp, phy_addr, IEEE_PAGE_ADDRESS_REGISTER, 2 );
            XEmacPs_PhyRead( xemacpsp, phy_addr, IEEE_CONTROL_REG_MAC, &control );
            control |= IEEE_RGMII_TXRX_CLOCK_DELAYED_MASK;
            XEmacPs_PhyWrite( xemacpsp, phy_addr, IEEE_CONTROL_REG_MAC, control );

            XEmacPs_PhyWrite( xemacpsp, phy_addr, IEEE_PAGE_ADDRESS_REGISTER, 0 );

            XEmacPs_PhyRead( xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG, &control );
            control |= IEEE_ASYMMETRIC_PAUSE_MASK;
            control |= IEEE_PAUSE_MASK;
            control |= ADVERTISE_100;
            control |= ADVERTISE_10;
            XEmacPs_PhyWrite( xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG, control );

            XEmacPs_PhyRead( xemacpsp, phy_addr, IEEE_1000_ADVERTISE_REG_OFFSET,
                             &control );
            control |= ADVERTISE_1000;
            XEmacPs_PhyWrite( xemacpsp, phy_addr, IEEE_1000_ADVERTISE_REG_OFFSET,
                              control );

            XEmacPs_PhyWrite( xemacpsp, phy_addr, IEEE_PAGE_ADDRESS_REGISTER, 0 );
            XEmacPs_PhyRead( xemacpsp, phy_addr, IEEE_COPPER_SPECIFIC_CONTROL_REG,
                             &control );
            control |= ( 7 << 12 ); /* max number of gigabit attempts */
            control |= ( 1 << 11 ); /* enable downshift */
            XEmacPs_PhyWrite( xemacpsp, phy_addr, IEEE_COPPER_SPECIFIC_CONTROL_REG,
                              control );
        #endif /* if XPAR_GIGE_PCS_PMA_CORE_PRESENT == 1 */
        XEmacPs_PhyRead( xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, &control );
        control |= IEEE_CTRL_AUTONEGOTIATE_ENABLE;
        control |= IEEE_STAT_AUTONEGOTIATE_RESTART;
        #if XPAR_GIGE_PCS_PMA_CORE_PRESENT == 1
            control &= IEEE_CTRL_ISOLATE_DISABLE;
        #endif

        XEmacPs_PhyWrite( xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, control );


        #if XPAR_GIGE_PCS_PMA_CORE_PRESENT == 1
        #else
            XEmacPs_PhyRead( xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, &control );
            control |= IEEE_CTRL_RESET_MASK;
            XEmacPs_PhyWrite( xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, control );

            while( 1 )
            {
                XEmacPs_PhyRead( xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, &control );

                if( control & IEEE_CTRL_RESET_MASK )
                {
                    continue;
                }
                else
                {
                    break;
                }
            }
        #endif /* if XPAR_GIGE_PCS_PMA_CORE_PRESENT == 1 */
        FreeRTOS_printf( ( "Waiting for PHY to complete autonegotiation.\n" ) );

        XEmacPs_PhyRead( xemacpsp, phy_addr, IEEE_STATUS_REG_OFFSET, &status );

        while( !( status & IEEE_STAT_AUTONEGOTIATE_COMPLETE ) )
        {
            vTaskDelay( MINIMUM_SLEEP_TIME );
            #if XPAR_GIGE_PCS_PMA_CORE_PRESENT == 1
            #else
                XEmacPs_PhyRead( xemacpsp, phy_addr, IEEE_COPPER_SPECIFIC_STATUS_REG_2,
                                 &temp );

                if( temp & IEEE_AUTONEG_ERROR_MASK )
                {
                    FreeRTOS_printf( ( "Auto negotiation error \n" ) );
                }
            #endif
            XEmacPs_PhyRead( xemacpsp, phy_addr, IEEE_STATUS_REG_OFFSET,
                             &status );
        }

        FreeRTOS_printf( ( "autonegotiation complete \n" ) );

        #if XPAR_GIGE_PCS_PMA_CORE_PRESENT == 1
        #else
            XEmacPs_PhyRead( xemacpsp, phy_addr, IEEE_SPECIFIC_STATUS_REG, &partner_capabilities );
        #endif

        #if XPAR_GIGE_PCS_PMA_CORE_PRESENT == 1
            FreeRTOS_printf( ( "Waiting for Link to be up; Polling for SGMII core Reg \n" ) );
            XEmacPs_PhyRead( xemacpsp, phy_addr, 5, &temp );

            while( !( temp & 0x8000 ) )
            {
                XEmacPs_PhyRead( xemacpsp, phy_addr, 5, &temp );
            }

            if( ( temp & 0x0C00 ) == 0x0800 )
            {
                XEmacPs_PhyRead( xemacpsp, phy_addr, 0, &temp );
                return 1000;
            }
            else if( ( temp & 0x0C00 ) == 0x0400 )
            {
                XEmacPs_PhyRead( xemacpsp, phy_addr, 0, &temp );
                return 100;
            }
            else if( ( temp & 0x0C00 ) == 0x0000 )
            {
                XEmacPs_PhyRead( xemacpsp, phy_addr, 0, &temp );
                return 10;
            }
            else
            {
                FreeRTOS_printf( ( "get_IEEE_phy_speed(): Invalid speed bit value, Deafulting to Speed = 10 Mbps\n" ) );
                XEmacPs_PhyRead( xemacpsp, phy_addr, 0, &temp );
                XEmacPs_PhyWrite( xemacpsp, phy_addr, 0, 0x0100 );
                return 10;
            }
        #else /* if XPAR_GIGE_PCS_PMA_CORE_PRESENT == 1 */
            if( ( ( partner_capabilities >> 14 ) & 3 ) == 2 ) /* 1000Mbps */
            {
                return 1000;
            }
            else if( ( ( partner_capabilities >> 14 ) & 3 ) == 1 ) /* 100Mbps */
            {
                return 100;
            }
            else /* 10Mbps */
            {
                return 10;
            }
        #endif /* if XPAR_GIGE_PCS_PMA_CORE_PRESENT == 1 */
    }