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

📄 net_phy.c

📁 DM9161A的网卡物理层芯片的驱动
💻 C
字号:
/*
*********************************************************************************************************
*                                              uC/TCP-IP
*                                      The Embedded TCP/IP Suite
*
*                          (c) Copyright 2003-2006; Micrium, Inc.; Weston, FL
*
*               All rights reserved.  Protected by international copyright laws.
*
*               uC/TCP-IP is provided in source form for FREE evaluation, for educational
*               use or peaceful research.  If you plan on using uC/TCP-IP in a commercial
*               product you need to contact Micrium to properly license its use in your
*               product.  We provide ALL the source code for your convenience and to help
*               you experience uC/TCP-IP.  The fact that the source code is provided does
*               NOT mean that you can use it without paying a licensing fee.
*
*               Network Interface Card (NIC) port files provided, as is, for FREE and do
*               NOT require any additional licensing or licensing fee.
*
*               Knowledge of the source code may NOT be used to develop a similar product.
*
*               Please help us continue to provide the Embedded community with the finest
*               software available.  Your honesty is greatly appreciated.
*********************************************************************************************************
*/

/*
*********************************************************************************************************
*
*                                        NETWORK PHYSICAL LAYER
*
*                                              DM9161AE
*
* Filename      : net_phy.c
* Version       : V1.87
* Programmer(s) : EHS
*********************************************************************************************************
* Note(s)       : (1) Supports DM9161AE '3.3V Dual-Speed Fast Ethernet Transceiver' as described in
*
*                         Corporation (INTEL; http://www.intel.com)
*                         (a) DM9161AE       (DM9161AE; Revision 249414-002)
*********************************************************************************************************
*/

/*
*********************************************************************************************************
*                                            INCLUDE FILES
*********************************************************************************************************
*/

#include  <net.h>
#include  <net_phy.h>
#include  <net_phy_def.h>


/*
*********************************************************************************************************
*                                         NetNIC_PhyInit()
*
* Description : Initialize phyter (ethernet link controller)
*               This instance configures the Davicom DM9161AE PHY
*
* Argument(s) : none.
*
* Return(s)   : 1 for OK, 0 for error
*
* Caller(s)   : AT91SAM7X256_EMAC_Init
*
* Note(s)     : Assumes the MDI port as already been enabled for the PHY.
*             : This is performed in net_nic.c, AT91SAM7X256_EMAC_Init().
*********************************************************************************************************
*/

void  NetNIC_PhyInit (NET_ERR *perr)
{
    CPU_INT16U reg_val;
    NET_ERR    AutoNeg_Err;


    reg_val     = 0;                                                 /* Init reg_val & void it to prevent a compiler     */
    (void)reg_val;                                                   /* warning since its not referenced in MII Mode     */

#ifndef RMII
    reg_val     =  NetNIC_PhyRegRd(AT91C_PHY_ADDR, MII_BMCR, perr);  /* Read the Basic Mode Control Register (twice)     */

    if (*perr  != NET_PHY_ERR_NONE) {
        return;
    }

    reg_val     =  NetNIC_PhyRegRd(AT91C_PHY_ADDR, MII_BMCR, perr);  /* Read the Basic Mode Control Register (twice)     */

    if (*perr  != NET_PHY_ERR_NONE) {
        return;
    }

    reg_val     &= ~BMCR_ISOLATE;                                    /* Mask off 'Disconnect from MII bit (BMCR_ISOLATE) */
    NetNIC_PhyRegWr(AT91C_PHY_ADDR, MII_BMCR, reg_val, perr);        /* Put the PHY into MII mode                        */

    if (*perr   != NET_PHY_ERR_NONE) {
        return;
    }
#endif

    NetNIC_PhyAutoNeg(&AutoNeg_Err);                                 /* Perform auto-negotiation                         */

    if (*perr == NET_PHY_ERR_NONE) {                                 /* If there are no errors enabling PHY interrupts.. */
        *perr    = AutoNeg_Err;                                      /* set the return error to that of AutoNegotiation  */
    }                                                                /* This is done because the AutoNegotiation Error   */
}                                                                    /* is not fatal and does not return upon discovery  */
                                                                     /* AutoNegotiation errors occur if the link is down */

/*
*********************************************************************************************************
*                                        NetNIC_PhyAutoNeg()
*
* Description : Do link auto-negotiation
*
* Argument(s) : none.
*
* Return(s)   : 1 = no error, 0 = error
*
* Caller(s)   : NetNIC_PhyInit.
*
* Note(s)     : none.
*********************************************************************************************************
*/

void  NetNIC_PhyAutoNeg (NET_ERR *perr)
{
    CPU_INT16U   i;
    CPU_INT16U   reg_val;
    CPU_BOOLEAN  link;


    i               = DM9161AE_INIT_AUTO_NEG_RETRIES;                   /* Set the # of retries before declaring a timeout  */
    link            = NetNIC_PhyLinkState(perr);                        /* Get the current link state. 1=linked, 0=no link  */

    if (*perr      != NET_PHY_ERR_NONE) {
        link        = DEF_OFF;                                          /* If we could not obtain the link state, try again */
    }

    if (link == DEF_OFF) {
        reg_val     = NetNIC_PhyRegRd(AT91C_PHY_ADDR, MII_BMCR, perr);  /* Get current control register value               */
        reg_val    |= DEF_BIT_09;                                       /* Set the auto-negotiation start bit               */

        NetNIC_PhyRegWr(AT91C_PHY_ADDR, MII_BMCR, reg_val, perr);       /* Initiate auto-negotiation                        */

        do {                                                            /* Do while auto-neg incomplete, or retries expired */
            DM9161AE_DlyAutoNegAck();                                   /* Wait for a while auto-neg to proceed (net_bsp.c) */
            reg_val = NetNIC_PhyRegRd(AT91C_PHY_ADDR, MII_BMSR, perr);  /* Read the Basic Mode Status Register              */
            reg_val = NetNIC_PhyRegRd(AT91C_PHY_ADDR, MII_BMSR, perr);  /* Read the Basic Mode Status Register              */
            i--;
        } while (((reg_val & BMSR_LSTATUS) == 0) && (i > 0));           /* While link not established and retries remain    */
    }

    if (i == 0) {                                                       /* If we are out of retries...                      */
        *perr       = NET_PHY_ERR_AUTONEG_TIMEOUT;                      /* Return a timeout error                           */
    } else {
        *perr       = NET_PHY_ERR_NONE;                                 /* Link up and retries remain                       */
    }
}


/*
*********************************************************************************************************
*                                    NetNIC_PhyAutoNegState()
*
* Description : Returns state of auto-negotiation
*               This instance probe the Davicom DM9161AE '3.3V Dual-Speed Fast Ethernet Transceiver'
*
* Argument(s) : none.
*
* Return(s)   : State of auto-negociation (DEF_OFF = not completed, DEF_ON = completed).
*
* Caller(s)   : NetNIC_PhyInit.
*
* Note(s)     : If any error is encountered while reading the PHY, this function
*               will return Auto Negotiation State = DEF_OFF (incomplete).
*********************************************************************************************************
*/

CPU_BOOLEAN  NetNIC_PhyAutoNegState (NET_ERR *perr)
{
    CPU_INT32U  reg_val;


    reg_val = NetNIC_PhyRegRd(AT91C_PHY_ADDR, MII_BMSR, perr);
    reg_val = NetNIC_PhyRegRd(AT91C_PHY_ADDR, MII_BMSR, perr);

    if (*perr   != NET_PHY_ERR_NONE) {
        reg_val  = 0;
    }

    if ((reg_val & BMSR_ANEGCOMPLETE) == BMSR_ANEGCOMPLETE) {   /* DM9161AE register 0x01: Basic Status Register #1      */
        return (DEF_ON);                                        /* BIT 5 Signal the result of the auto negotiation       */
    } else {                                                    /* 1 = complete, 0 = incomplete                          */
        return (DEF_OFF);
    }
}


/*
*********************************************************************************************************
*                                     NetNIC_PhyLinkState()
*
* Description : Returns state of ethernet link
*               This instance probe the Davicom DM9161AE '3.3V Dual-Speed Fast Ethernet Transceiver'
*
* Argument(s) : none.
*
* Return(s)   : State of ethernet link (DEF_OFF = link down, DEF_ON = link up).
*
* Caller(s)   : NetNIC_PhyISR_Handler.
*
* Note(s)     : If any error is encountered while reading the PHY, this function
*               will return link state = DEF_OFF.
*********************************************************************************************************
*/

CPU_BOOLEAN  NetNIC_PhyLinkState (NET_ERR *perr)
{
    CPU_INT16U  reg_val;
                                                                /* DM9161AE register 0x01: Basic Status Register #1      */
                                                                /* BIT 2 , Link Status, 1 = linked, 0 = not linked.      */
    reg_val      = NetNIC_PhyRegRd(AT91C_PHY_ADDR, MII_BMSR, perr);
    reg_val      = NetNIC_PhyRegRd(AT91C_PHY_ADDR, MII_BMSR, perr);

    if (*perr   != NET_PHY_ERR_NONE) {
        reg_val  = 0;
    }

    reg_val     &= BMSR_LSTATUS;

    if (reg_val == BMSR_LSTATUS) {
        return (DEF_ON);
    } else {
        return (DEF_OFF);
    }
}


/*
*********************************************************************************************************
*                                     NetPHY_GetLinkSpeed()
*
* Description : Returns the speed of the current Ethernet link
*               This probes the Davicom DM9161AE '3.3V Dual-Speed Fast Ethernet Transceiver'
*
* Argument(s) : none.
*
* Return(s)   : 0 = No Link, 10 = 10mbps, 100 = 100mbps
*
* Caller(s)   : AT91SAM7X256_EMAC_Init()
*
* Note(s)     : none.
*********************************************************************************************************
*/

CPU_INT32S NetPHY_GetLinkSpeed (NET_ERR *perr)
{
	CPU_INT32U bmsr;
    CPU_INT32U bmcr;
    CPU_INT32U lpa;


    bmsr = NetNIC_PhyRegRd(AT91C_PHY_ADDR, MII_BMSR, perr);     /* Get Link Status from PHY status reg. Requires 2 reads */
	bmsr = NetNIC_PhyRegRd(AT91C_PHY_ADDR, MII_BMSR, perr);     /* Get Link Status from PHY status reg. Requires 2 reads */

    if ((bmsr & BMSR_LSTATUS) == 0) {
        return (NET_PHY_SPD_0);                                 /* No link                                               */
    }

	bmcr = NetNIC_PhyRegRd(AT91C_PHY_ADDR, MII_BMCR, perr);     /* Read the PHY Control Register                         */
	
    if ((bmcr & BMCR_ANENABLE) == BMCR_ANENABLE) {		        /* If AutoNegotiation is enabled                         */
        if ((bmsr & BMSR_ANEGCOMPLETE) == 0) {                  /* If AutoNegotiation is not complete                    */
			return (NET_PHY_SPD_0);       					    /* AutoNegotitation in progress                          */
        }

		lpa = NetNIC_PhyRegRd(AT91C_PHY_ADDR, MII_LPA, perr);   /* Read the Link Partner Ability Register                */

        if (((lpa & LPA_100FULL) == LPA_100FULL) || ((lpa & LPA_100HALF) == LPA_100HALF)) {
			return (NET_PHY_SPD_100);
        } else {
			return (NET_PHY_SPD_10);
        }
	} else {                                                    /* Auto-negotiation not enabled, get speed from BMCR     */
        if ((bmcr & BMCR_SPEED100) == BMCR_SPEED100) {
            return (NET_PHY_SPD_100);
        } else {
            return (NET_PHY_SPD_10);
        }
	}
}


/*
*********************************************************************************************************
*                                     NetPHY_GetDuplex()
*
* Description : Returns the duplex mode of the current Ethernet link
*               This probes the Davicom DM9161AE '3.3V Dual-Speed Fast Ethernet Transceiver'
*
* Argument(s) : none.
*
* Return(s)   : 0 = Unknown (Auto-Neg in progress), 1 = Half Duplex, 2 = Full Duplex
*
* Caller(s)   : AT91SAM7X256_EMAC_Init()
*
* Note(s)     : none.
*********************************************************************************************************
*/

CPU_INT32S NetPHY_GetLinkDuplex (NET_ERR *perr)
{
    CPU_INT32U bmcr;
    CPU_INT32U bmsr;
    CPU_INT32U lpa;


    bmsr = NetNIC_PhyRegRd(AT91C_PHY_ADDR, MII_BMSR, perr);     /* Get Link Status from PHY status reg. Requires 2 reads */
	bmsr = NetNIC_PhyRegRd(AT91C_PHY_ADDR, MII_BMSR, perr);     /* Get Link Status from PHY status reg. Requires 2 reads */


    if ((bmsr & BMSR_LSTATUS) == 0) {
        return (NET_PHY_DUPLEX_UNKNOWN);                        /* No link, return 'Duplex Uknown'                       */
    }

	bmcr = NetNIC_PhyRegRd(AT91C_PHY_ADDR, MII_BMCR, perr);     /* Read the PHY Control Register                         */
	
    if ((bmcr & BMCR_ANENABLE) == BMCR_ANENABLE) {		        /* If AutoNegotiation is enabled                         */
        if ((bmsr & BMSR_ANEGCOMPLETE) == 0) {                  /* If AutoNegotiation is not complete                    */
			return (NET_PHY_DUPLEX_UNKNOWN);      			    /* AutoNegotitation in progress                          */
        }

		lpa = NetNIC_PhyRegRd(AT91C_PHY_ADDR, MII_LPA, perr);   /* Read the Link Partner Ability Register                */

        if (((lpa & LPA_100FULL) == LPA_100FULL) || ((lpa & LPA_10FULL) == LPA_10FULL)) {
			return (NET_PHY_DUPLEX_FULL);
        } else {
            return (NET_PHY_DUPLEX_HALF);
        }
	} else {                                                    /* Auto-negotiation not enabled, get duplex from BMCR    */
        if ((bmcr & BMCR_FULLDPLX) == BMCR_FULLDPLX) {
            return (NET_PHY_DUPLEX_FULL);
        } else {
            return (NET_PHY_DUPLEX_HALF);
        }
	}
}


⌨️ 快捷键说明

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