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

📄 miilib.c

📁 Embedded Planet公司的ep8260单板计算机的BSP包(VxWorks)
💻 C
📖 第 1 页 / 共 4 页
字号:
	    }
	}

    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 */

    /* 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);
 
    /* 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;
  
    /* 
     * 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))
	    {
	    /* check we're not at the end of the user table */

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

		return (ERROR);
		}

	    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;

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

	/* set the ANAR accordingly */

	regAddr = MII_AN_ADS_REG;

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

	/* 
	 * start the auto-negotiation process: return
	 * only in case of fatal error.
	 */

	retVal = miiAutoNegStart (pPhyInfo, phyAddr);

	/* 
	 * in case of fatal error, we return immediately; otherwise,
	 * we try to recover from the failure, if we're not using 
	 * the standard auto-negotiation process.
	 */

	if (retVal == ERROR)
	    {
	    if (errno != S_miiLib_PHY_AN_FAIL)
		return (ERROR);

	    else
		{
		if (!(MII_PHY_FLAGS_ARE_SET (MII_PHY_TBL)))
		    return (ERROR);
		else
		    {
		    /* let's try the next entry in the table */

		    errno = 0;
		    continue;
		    }
		}
	    }

	/* check the negotiation was successful */

	if (miiAnCheck (pPhyInfo, phyAddr) == OK)
	    return (OK);

	/* 
	 * we are here if the negotiation went wong:
	 * if the auto-negotiation order table was not 
	 * used, we return ERROR, as all the PHY abilities
	 * were negotiated at once.
	 */

	if (!(MII_PHY_FLAGS_ARE_SET (MII_PHY_TBL)))
	    return (ERROR);
	}

    return (OK);
    }

/*******************************************************************************
* miiAutoNegStart - start the auto-negotiation process
*
* This routine starts the auto-negotiation process for the PHY whose
* address is specified in the parameter <phyAddr>.
*
* RETURNS: OK or ERROR.
*
* ERRNO: S_miiLib_PHY_AN_FAIL
*
*/

LOCAL STATUS miiAutoNegStart
    (
    PHY_INFO *  pPhyInfo,       /* pointer to PHY_INFO structure */
    UINT8	phyAddr		/* address of a PHY */
    )
    {
    UINT16	data;		/* data to be written to the control reg */
    UINT8	regAddr;	/* PHY register */
    UINT16	phyStatus;	/* holder for the PHY status */
    UINT16	ix = 0;		/* a counter */
    int		retVal;		/* convenient holder for return value */

    regAddr = MII_STAT_REG;

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

    MII_LOG (MII_DBG_ANY, ("miiAutoNegStart phy=0x%x, reg=0x%x read status=0x%x\n"),
			   phyAddr, regAddr, phyStatus, 0, 0, 0);

    /* check the PHY has this ability */

    if ((phyStatus & MII_SR_AUTO_SEL) != MII_SR_AUTO_SEL)
	{
	MII_LOG (MII_DBG_ANY, ("miiAutoNegStart phy not 
			       auto neg capable\n"), 
			       0, 0, 0, 0, 0, 0);

	return (ERROR);
	}

    /* restart the auto-negotiation process */

    regAddr = MII_CTRL_REG;
    data = (MII_CR_RESTART | MII_CR_AUTO_EN);

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

    /* save status info */

    pPhyInfo->miiRegs.phyCtrl = data;

    /* let's check the PHY status for completion */

    regAddr = MII_STAT_REG;

    /* spin until it is done */

    do
	{
	MII_SYS_DELAY (pPhyInfo->phyDelayParm);

	if (ix++ == pPhyInfo->phyMaxDelay)
	    break;

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

	} while ((phyStatus & MII_SR_AUTO_NEG) != MII_SR_AUTO_NEG);

    MII_LOG (MII_DBG_ANY, ("miiAutoNegStart auto neg attempts=%d \n"),
			   ix, 0, 0, 0, 0, 0);

    if (ix >= pPhyInfo->phyMaxDelay)
	{
	MII_LOG (MII_DBG_ANY, ("miiAutoNegStart auto neg fail\n"),
			       0, 0, 0, 0, 0, 0);
	errnoSet (S_miiLib_PHY_AN_FAIL);
	return (ERROR);
	}
    else
	{
	MII_LOG (MII_DBG_ANY, ("miiAutoNegStart auto neg done phyStat=0x%x\n"),
			       phyStatus, 0, 0, 0, 0, 0);
	}

    return (OK);
    }

/*******************************************************************************
* miiBasicCheck - run a basic check on the PHY status register
*
* This routine runs a basic check on the PHY status register to
* ensure a valid link has been established and no faults have been 
* detected.
*
* RETURNS: OK or ERROR.
*
*/

LOCAL STATUS miiBasicCheck
    (
    PHY_INFO *  pPhyInfo,       /* pointer to PHY_INFO structure */
    UINT8	phyAddr		/* address of a PHY */
    )
    {
    UINT8	regAddr;	/* PHY register */
    UINT16	phyStatus;	/* holder for the PHY status */
    int		retVal;		/* convenient holder for return value */

    /* let's check the PHY status */

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

    if ((phyStatus & MII_SR_LINK_STATUS) != MII_SR_LINK_STATUS)
	{
	MII_LOG (MII_DBG_ANY, ("miiBasicCheck first time
			       phy stat=0x%x\n"),
			       phyStatus, 0, 0, 0, 0, 0);

	/* wait for a while */

	MII_SYS_DELAY (pPhyInfo->phyDelayParm);

	/* we need to read it twice, as this's a latched function */

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

	if ((phyStatus & MII_SR_LINK_STATUS) != MII_SR_LINK_STATUS)
	    {
	    MII_LOG (MII_DBG_ANY, ("miiBasicCheck phy stat=0x%x\n"),
				   phyStatus, 0, 0, 0, 0, 0);

	    return (ERROR);
	    }
	}

    MII_LOG (MII_DBG_ANY, ("miiBasicCheck Link up! status=0x%x\n"),
			   phyStatus, 0, 0, 0, 0, 0);

    /* check for remote fault condition, read twice */

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

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

    if ((phyStatus & MII_SR_REMOTE_FAULT) == MII_SR_REMOTE_FAULT)
	{
	MII_LOG (MII_DBG_ANY, ("miiBasicCheck remote fault\n"),
			       0, 0, 0, 0, 0, 0);
	return (ERROR);
	}

    /* store the current registers values */

    pPhyInfo->miiRegs.phyStatus = phyStatus;

    return (OK);
    }

/*******************************************************************************
* miiFlagsHandle - handle some flags
*
* This routine sets some fields in the PHY_INFO structure according to the
* values of the related flags.
*
* RETURNS: OK, always.
*/

LOCAL STATUS miiFlagsHandle
    (
    PHY_INFO *  pPhyInfo,       /* pointer to PHY_INFO structure */
    UINT8	phyAddr		/* address of a PHY */
    )
    {
    if (MII_PHY_FLAGS_ARE_SET (MII_PHY_100))
	pPhyInfo->phySpeed = MII_100MBS;
    else
	pPhyInfo->phySpeed = MII_10MBS;
 
    if (MII_PHY_FLAGS_ARE_SET (MII_PHY_FD))
	bcopy (MII_FDX_STR, (char *) pPhyInfo->phyMode, MII_FDX_LEN);
    else
	bcopy (MII_HDX_STR, (char *) pPhyInfo->phyMode, MII_HDX_LEN);
 
    MII_LOG (MII_DBG_ANY, ("miiFlagsHandle speed=%d mode=%s\n"),
			   pPhyInfo->phySpeed, 
			   (char *) pPhyInfo->phyMode, 0, 0, 0, 0);

    return (OK);
    }

/*******************************************************************************
* miiAnCheck - check the auto-negotiation process result
*
* This routine checks the auto-negotiation process has completed
* successfully and no faults have been detected by any of the PHYs 
* engaged in the process.
*
* RETURNS: OK or ERROR.
*/

LOCAL STATUS miiAnCheck
    (
    PHY_INFO *  pPhyInfo,       /* pointer to PHY_INFO structure */
    UINT8	phyAddr		/* address of a PHY */
    )
    {
    UINT8	regAddr;	/* PHY register */
    UINT16	phyAds;		/* PHY advertisement register value */
    UINT16	phyPrtn;	/* PHY partner ability register value */
    UINT16	phyExp;		/* PHY expansion register value */
    UINT16	negAbility;	/* abilities after negotiation */

⌨️ 快捷键说明

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