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

📄 miilib.c

📁 au1500开发的应用程序
💻 C
📖 第 1 页 / 共 5 页
字号:
    )
    {
    /* 
     * start the auto-negotiation process,
     * unless the user dictated the contrary. 
     */

    if (pPhyInfo->phyFlags & MII_PHY_AUTO)
	if (miiAutoNegotiate (pPhyInfo, phyAddr) == OK)
	    {
            if (pPhyInfo->phyFlags & MII_PHY_GMII_TYPE)
                {
                pPhyInfo->phyLinkMethod = MII_PHY_LINK_AUTO;
	        }
            goto miiPhyOk;
            }

    /* 
     * the auto-negotiation process did not succeed 
     * in establishing a valid link: try to do it
     * manually, enabling as many high priority abilities
     * as possible.
     */

    if (miiModeForce (pPhyInfo, phyAddr) == OK)
        {
        if (pPhyInfo->phyFlags & MII_PHY_GMII_TYPE)
            {
            pPhyInfo->phyLinkMethod = MII_PHY_LINK_FORCE;
            }
         goto miiPhyOk;
         }

    return (ERROR);

miiPhyOk:
    /* store this PHY and return */

    pPhyInfo->phyAddr = phyAddr;
    MII_PHY_FLAGS_SET (MII_PHY_INIT);
    return (OK);
    }

/*******************************************************************************
*
* miiPhyLinkSet - set the link for a PHY
*
* This routine sets the link for the PHY pointed to by <pPhyInfo>. To do
* so, it calls miiPhyBestModeSet (). Upon success it returns OK.
* Otherwise, it checks whether other PHYs are on the bus, and attempts at
* establishing a link for them starting from the first and scanning the 
* whole range. In case of failure, ERROR is returned.
*
* SEE ALSO: miiPhyBestModeSet ().
* 
* RETURNS: OK or ERROR.
*
* ERRNO: S_miiLib_PHY_LINK_DOWN
*
*/

LOCAL STATUS miiPhyLinkSet
    (
    PHY_INFO *  pPhyInfo        /* pointer to PHY_INFO structure */
    )
    {
    UINT16	ix;		/* a counter */
    UINT8	phyAddr;	/* address of a PHY */
    UINT32	phyFlags;	/* default PHY's flags */

    /* store the default phy's flags */

    phyFlags = pPhyInfo->phyFlags;

    for (ix = 0; ix < MII_MAX_PHY_NUM; ix++)
	{
	phyAddr = (ix + pPhyInfo->phyAddr) % MII_MAX_PHY_NUM;

	MII_LOG (MII_DBG_ANY, ("miiPhyLinkSet phyAddr=0x%x \n"),
			       phyAddr, 0, 0, 0, 0, 0);

	if (* ((BOOL *) pPhyInfo->miiPhyPresent + phyAddr) == FALSE)
	    continue;

	/* add this PHY to the linked list */

	if (miiPhyListAdd (pPhyInfo) == ERROR)
	    return (ERROR);

	MII_LOG (MII_DBG_ANY, ("miiPhyLinkSet phyAddr=0x%x pres=0x%x \n"),
			       phyAddr, 
			       (* ((BOOL *) pPhyInfo->miiPhyPresent + phyAddr)),
			       0, 0, 0, 0);

	/* find out the PHY's abilities and set flags accordingly */

	if (miiAbilFlagSet (pPhyInfo, phyAddr) != OK)
	    return (ERROR);

        /* we need this phyAddr before we call pPhyOptRegsRtn */

        pPhyInfo->phyAddr = phyAddr;

	/* 
	 * check with the BSP if we need to do something else before
	 * we try and establish the link 
	 */

        if (pPhyInfo->pPhyOptRegsRtn != NULL)
            (* pPhyInfo->pPhyOptRegsRtn) (pPhyInfo);
        else
	    if (pPhyOptRegsRtn != NULL)
	        (* pPhyOptRegsRtn) (pPhyInfo);

        /* initialize phyLinkMethod */

        if (pPhyInfo->phyFlags & MII_PHY_GMII_TYPE)
            {
            pPhyInfo->phyLinkMethod = MII_PHY_LINK_UNKNOWN;
            } 

	/* establist the link */

	if (miiPhyBestModeSet (pPhyInfo, phyAddr) == OK)
	    {
	    return (OK);
	    }

	/* restore the default flags, miiAbilFlagSet may have changed them */

	pPhyInfo->phyFlags = phyFlags;
	}

    /* set errno, since we did not establish a valid link */

    errnoSet (S_miiLib_PHY_LINK_DOWN);

    return (ERROR);
    }

/*******************************************************************************
*
* miiPhyDefModeSet - set the default operating mode for a PHY
*
* This routine sets the default operating mode for a PHY looking at the 
* parameters in <pPhyInfo>. It calls miiDefForce () for each PHY found.
*
* SEE ALSO: miiDefForce ().
* 
* RETURNS: OK or ERROR.
*
*/

LOCAL STATUS miiPhyDefModeSet
    (
    PHY_INFO *  pPhyInfo        /* pointer to PHY_INFO structure */
    )
    {
    UINT16	ix;		/* a counter */
    int		retVal;		/* holder for return value */
    UINT8	phyAddr;	/* address of a PHY */

    /* try to establish a default operating mode, do not check the link! */

    for (ix = 0; ix < MII_MAX_PHY_NUM; ix++)
	{
	phyAddr = (ix + pPhyInfo->phyAddr) % MII_MAX_PHY_NUM;

	/* check the PHY is there */

	if (* ((BOOL *) pPhyInfo->miiPhyPresent + phyAddr) == FALSE)
	    continue;

	/* 
	 * Force default parameters: field phyDefMode in the PHY info 
	 * structure. Return OK even if the link is not up.
	 */

	retVal = miiDefForce (pPhyInfo, phyAddr);
	if (retVal == OK) 
	    {
	    /* store this PHY and return */

	    pPhyInfo->phyAddr = phyAddr;
	    MII_PHY_FLAGS_SET (MII_PHY_INIT);

	    return (OK);
	    }

	/* if the PHY does not have the default abilities... */

	if (errno == S_miiLib_PHY_NO_ABLE)
	    {
	    if (ix == (MII_MAX_PHY_NUM - 1))
		return (ERROR);

	    errno = 0;
	    continue;
	    }
	}

    return (ERROR);
    }

/*******************************************************************************
*
* miiAutoNegotiate - run the auto-negotiation process
*
* This routine runs the auto-negotiation process for the PHY whose
* address is specified in the parameter <phyAddr>, without enabling the 
* next page function. It also calls miiAnCheck() to ensure
* a valid link has been established.
*
* RETURNS: OK or ERROR.
*/

LOCAL STATUS miiAutoNegotiate
    (
    PHY_INFO *  pPhyInfo,  /* pointer to PHY_INFO structure */
    UINT8	phyAddr        /* address of a PHY */
    )
    {
    UINT8	regAddr;       /* PHY register */
    UINT16	phyAds;        /* holder for the PHY ads register value */
    UINT16	status;        /* PHY auto-negotiation status */
    UINT16	ix;            /* a counter */
    int		retVal;        /* holder for return value */
    UINT16	phyStat;       /* PHY auto-negotiation status */
    UINT16  phyMstSlaCtrl; /* PHY Mater-slave Control */
    UINT16  phyExtStat;    /* PHY extented status */

    /* save phyFlags for phyAutoNegotiateFlags */

    if (pPhyInfo->phyFlags & MII_PHY_GMII_TYPE)
        {
        pPhyInfo->phyAutoNegotiateFlags = pPhyInfo->phyFlags; 
        }

    /* Read ANER to clear status from previous operations */
  
    regAddr = MII_AN_EXP_REG;
    MII_READ (phyAddr, regAddr, &status, retVal);
    if (retVal != OK)
	return (ERROR);

    /* 
     * copy the abilities in ANSR to ANAR. This is necessary because
     * according to the 802.3 standard, the technology ability
     * field in ANAR "is set based on the value in the MII status
     * register or equivalent". What does "equivalent" mean?
     */
 
    regAddr = MII_AN_ADS_REG;

    MII_READ (phyAddr, regAddr, &phyAds, retVal);
    if (retVal != OK)
	return (ERROR);

    MII_LOG (MII_DBG_ANY, ("miiAutoNegotiate phyAds=0x%x expStat=0x%x \n"),
			   phyAds, status, 0, 0, 0, 0);

    regAddr = MII_STAT_REG;
    MII_READ (phyAddr, regAddr, &phyStat, retVal);
    if (retVal != OK)
        return (ERROR);
 
    MII_FROM_ANSR_TO_ANAR (phyStat, phyAds);

    /* also disable the next page function */

    phyAds &= (~MII_NP_NP);

    MII_LOG (MII_DBG_ANY, ("miiAutoNegotiate write to ANAR=0x%x\n"),
                           phyAds, 0, 0, 0, 0, 0);
 
    /* configure flow control */

    /* MII defines symmetric PAUSE ability */ 

    if ((MII_PHY_FLAGS_ARE_SET (MII_PHY_TX_FLOW_CTRL)) &&
                (MII_PHY_FLAGS_ARE_SET (MII_PHY_RX_FLOW_CTRL)))
        phyAds |= MII_ANAR_PAUSE;
    else
        phyAds &= ~MII_ANAR_PAUSE;

    if (pPhyInfo->phyFlags & MII_PHY_GMII_TYPE)
        {

        /* GMII also defines asymmetric PAUSE ability */

        if (!(MII_PHY_FLAGS_ARE_SET (MII_PHY_TX_FLOW_CTRL)) &&
                !(MII_PHY_FLAGS_ARE_SET (MII_PHY_RX_FLOW_CTRL)))
             {
             /* not flow control */

             phyAds &= ~MII_ANAR_ASM_PAUSE;
             phyAds &= ~MII_ANAR_PAUSE;
             }
         else if ((MII_PHY_FLAGS_ARE_SET (MII_PHY_TX_FLOW_CTRL)) && 
                    !(MII_PHY_FLAGS_ARE_SET (MII_PHY_RX_FLOW_CTRL)))
             {
             /* TX flow control */

             phyAds |= MII_ANAR_ASM_PAUSE;
             phyAds &= ~MII_ANAR_PAUSE;
             }
         else    
             {
             /* RX flow control */

             phyAds |= MII_ANAR_ASM_PAUSE;
             phyAds |= MII_ANAR_PAUSE;
             }
         }

    /* write ANAR */

    regAddr = MII_AN_ADS_REG;
    MII_WRITE (phyAddr, regAddr, phyAds, retVal);
    if (retVal != OK)
	return (ERROR);
 
    /* store the current registers values */

    pPhyInfo->miiRegs.phyAds = phyAds;
    
    if (pPhyInfo->phyFlags & MII_PHY_GMII_TYPE)
        {
        /* get Master-Slave Control (MSC) Register */

        regAddr =  MII_MASSLA_CTRL_REG;
        MII_READ (phyAddr, regAddr, &phyMstSlaCtrl, retVal);
        if (retVal != OK)
            return (ERROR);

        /* get extended status register */

        regAddr = MII_EXT_STAT_REG;
        MII_READ (phyAddr, regAddr, &phyExtStat, retVal);
        if (retVal != OK)
            return (ERROR);
     
        /* set MSC register value based on PHY ability on EXTS */
   
        phyMstSlaCtrl = (phyExtStat & MII_EXT_STAT_1000T_HD) ?
                        (phyMstSlaCtrl | MII_MASSLA_CTRL_1000T_HD) :
                        (phyMstSlaCtrl & ~MII_MASSLA_CTRL_1000T_HD);

        phyMstSlaCtrl = (phyExtStat & MII_EXT_STAT_1000T_FD) ?
                        (phyMstSlaCtrl | MII_MASSLA_CTRL_1000T_FD) :
                        (phyMstSlaCtrl & ~MII_MASSLA_CTRL_1000T_FD);                         
          
        /* write MSC register value */

        regAddr = MII_MASSLA_CTRL_REG;
        MII_WRITE (phyAddr, regAddr, phyMstSlaCtrl, retVal);
        if (retVal != OK)
            return (ERROR);

        /* store the current registers values */

        pPhyInfo->miiGRegs.phyMSCtrl = phyMstSlaCtrl;
        }

    /* 
     * start the auto-negotiation process, possibly
     * following the order the user dictated.
     */

    for (ix = 0; ; ix++)
	{
	if (MII_PHY_FLAGS_ARE_SET (MII_PHY_TBL))
	    {
	    if (pPhyInfo->phyAnOrderTbl == NULL)
		{
		MII_LOG (MII_DBG_ANY, ("miiAutoNegotiate no auto-neg table\n"),
				       0, 0, 0, 0, 0, 0);

		return (ERROR);
		}

	    /* check we're not at the end of the user table */

	    if (*((INT16*) pPhyInfo->phyAnOrderTbl + ix) == -1)
		return (ERROR);

	    /* just negotiate one ability at a time */

	    phyAds &= ~MII_ADS_TECH_MASK;

	    /* translate user settings */

	    phyAds |= *((INT16*) pPhyInfo->phyAnOrderTbl + ix);

	    /* check the PHY has the desidered ability */

	    if (!(phyAds & pPhyInfo->miiRegs.phyAds))
		continue;
	    }
	else
	    {
	    /* check the PHY flags and possibly mask some abilities off */

	    if (!(MII_PHY_FLAGS_ARE_SET (MII_PHY_FD)))
		phyAds &= ~(MII_TECH_10BASE_FD | MII_TECH_100BASE_TX_FD);

	    if (!(MII_PHY_FLAGS_ARE_SET (MII_PHY_HD)))
		phyAds &= ~(MII_TECH_10BASE_T | MII_TECH_100BASE_TX 
			    | MII_TECH_100BASE_T4);

	    if (!(MII_PHY_FLAGS_ARE_SET (MII_PHY_100)))
		phyAds &= ~(MII_TECH_100BASE_TX | MII_TECH_100BASE_TX_FD
			    | MII_TECH_100BASE_T4);

	    if (!(MII_PHY_FLAGS_ARE_SET (MII_PHY_10)))
		phyAds &= ~(MII_TECH_10BASE_T | MII_TECH_10BASE_FD);

	    /* store the current registers values */

	    pPhyInfo->miiRegs.phyAds = phyAds;

	    if (pPhyInfo->phyFlags & MII_PHY_GMII_TYPE)
	        {

	        /* check phyFlags with 1000T FD mode */

	        if (!(MII_PHY_FLAGS_ARE_SET (MII_PHY_1000T_FD)))
	            phyMstSlaCtrl &= ~MII_MASSLA_CTRL_1000T_FD;

	        /* check phyFlags with 1000T HD mode */

	        if (!(MII_PHY_FLAGS_ARE_SET (MII_PHY_1000T_HD)))
	            phyMstSlaCtrl &= ~MII_MASSLA_CTRL_1000T_HD;

	       /* store the current registers values */

	        pPhyInfo->miiGRegs.phyMSCtrl = phyMstSlaCtrl;;

	        MII_LOG (MII_DBG_ANY, ("miiAutoNegotiate phyMSCtrl=0x%x\n"),
					   phyMstSlaCtrl, 0, 0, 0, 0, 0);
	        }

	    MII_LOG (MII_DBG_ANY, ("miiAutoNegotiate phyAds=0x%x\n"),
				   phyAds, 0, 0, 0, 0, 0);
	    }

	/* set the ANAR accordingly */

⌨️ 快捷键说明

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