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

📄 miilib.c

📁 au1500开发的应用程序
💻 C
📖 第 1 页 / 共 5 页
字号:

/**************************************************************************
*
* miiPhyUnInit - uninitialize a PHY
*
* This routine uninitializes the PHY specified in <pPhyInfo>. It brings it
* in low-power mode, and electrically isolate it from the MII management 
* interface to which it is attached. In addition, it frees resources 
* previously allocated.
*
* RETURNS: OK, ERROR in case of fatal errors.
*
*/

STATUS miiPhyUnInit
    (
    PHY_INFO *  pPhyInfo       /* pointer to PHY_INFO structure */
    )
    {
    if (pPhyInfo == NULL)
	return (ERROR);

    MII_LOG (MII_DBG_ANY, ("miiPhyUnInit \n"),
			   0, 0, 0, 0, 0, 0);

    /* this counts also for isolate */
    if (miiProbe (pPhyInfo, pPhyInfo->phyAddr) == ERROR)
	return (ERROR);

    if (miiPhyPwrDown (pPhyInfo, pPhyInfo->phyAddr) == ERROR)
	return (ERROR);

    MII_PHY_FLAGS_CLEAR (MII_PHY_INIT);

    /* protect it from other MII routines */

    MII_SEM_TAKE (WAIT_FOREVER);

    lstDelete (&miiList, (NODE *) pPhyInfo->pMiiPhyNode);

    /* we're done, release the mutex */
    MII_SEM_GIVE ();

    /* free memory */
    free ((char *) pPhyInfo->pMiiPhyNode);
    free ((char *) pPhyInfo->miiPhyPresent);

    pPhyInfo->pMiiPhyNode = NULL;

    /* stop the monitor if necessary */
    if (miiList.count == 0)
	return (wdCancel (miiWd));

    return (OK);
    }

/**************************************************************************
*
* miiProbe - probe the PHY device
*
* This routine probes the PHY device by reading its control register.
* It also checks the PHY can be successfully electrically isolated from its
* MII interface.
*
* RETURNS: OK, ERROR in case of fatal errors.
*
* ERRNO: S_miiLib_PHY_NULL
*
*/

LOCAL STATUS miiProbe
    (
    PHY_INFO *  pPhyInfo,       /* pointer to PHY_INFO structure */
    UINT8	phyAddr		/* the PHY being read */
    )
    {
    UINT8	regAddr;	/* the PHY's register being read */
    UINT16	data;		/* data to be written to the PHY's reg */
    int		retVal;		/* convenient holder for return value */

    MII_LOG (MII_DBG_ANY, "miiProbe for addr %#x starts\n",phyAddr,0,0,0,0,0);

    regAddr = MII_CTRL_REG;
    MII_READ (phyAddr, regAddr, &data, retVal);

    if (retVal == ERROR)
	return (ERROR);

    /* check the reserved bits, and the ability to isolate the PHY */

    MII_LOG (MII_DBG_ANY, "miiProbe checking addr %#x\n",phyAddr,0,0,0,0,0);
    
    if (((data & MII_CR_RES_MASK) > 0x0) ||
        ((miiPhyIsolate (pPhyInfo, phyAddr) != OK)))
        {
	errnoSet (S_miiLib_PHY_NULL); 
	return (ERROR);
	}
    
    MII_LOG (MII_DBG_ANY, ("miiProbe... ends\n"),
			   0, 0, 0, 0, 0, 0);

    return (OK);
    }

/*******************************************************************************
*
* miiDiag - run some diagnostics
*
* This routine runs some diagnostics on the PHY whose address is 
* specified in the parameter <phyAddr>.
*
* RETURNS: OK or ERROR.
*/

LOCAL STATUS miiDiag
    (
    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	ix = 0;		/*  a counter */
    int		retVal;		/* convenient holder for return value */

    /* reset the PHY */

    regAddr = MII_CTRL_REG;
    data = MII_CR_RESET;

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

    while (ix++ < pPhyInfo->phyMaxDelay)
	{
	MII_SYS_DELAY (pPhyInfo->phyDelayParm);

	MII_READ (phyAddr, regAddr, &data, retVal);
	if (retVal == ERROR)
	    return (ERROR);

	if (!(data & MII_CR_RESET))
	    break;
	}

    if (ix >= pPhyInfo->phyMaxDelay)
	{
	MII_LOG (MII_DBG_ANY, ("miiDiag reset fail\n"),
			       0, 0, 0, 0, 0, 0);
	return (ERROR);
	}

    /* re-enable the chip */

    data = MII_CR_NORM_EN;

    MII_WRITE (phyAddr, regAddr, data, retVal);

    if (retVal != OK)
	{
	MII_LOG (MII_DBG_ANY, ("miiDiag write fail\n"),
			       0, 0, 0, 0, 0, 0);
	return (ERROR);
	}

#if !defined(PHY_RTL8201BL)

    /* check isolate bit is deasserted */

    ix = 0;
    while (ix++ < pPhyInfo->phyMaxDelay)
	{
	MII_SYS_DELAY (pPhyInfo->phyDelayParm);

	MII_READ (phyAddr, regAddr, &data, retVal);

	if (retVal != OK)
	    {
	    MII_LOG (MII_DBG_ANY, ("miiDiag read fail\n"),
				   0, 0, 0, 0, 0, 0);
	    return (ERROR);
	    }

	if (!(data & MII_CR_ISOLATE))
	    break;
	}

    if (ix >= pPhyInfo->phyMaxDelay)
	{
	MII_LOG (MII_DBG_ANY, ("miiDiag de-isolate fail\n"),
			       0, 0, 0, 0, 0, 0);
	return (ERROR);
	}

#endif /* !defined(PHY_RTL8201BL) */

    MII_LOG (MII_DBG_ANY, ("miiDiag... ends\n"),
			   0, 0, 0, 0, 0, 0);

    return (OK);
    }

/*******************************************************************************
*
* miiPhyIsolate - isolate the PHY device
*
* This routine isolates the PHY device whose address is specified in 
* the parameter <isoPhyAddr>.
*
* RETURNS: OK or ERROR.
*/

LOCAL STATUS miiPhyIsolate
    (
    PHY_INFO *  pPhyInfo,       /* pointer to PHY_INFO structure */
    UINT8	isoPhyAddr	/* address of a PHY to be isolated */
    )
    {
    UINT8	regAddr;	/* PHY register */
#if !defined(PHY_RTL8201BL)
    UINT16	ix = 0;		/*  a counter */
#endif /* !defined(PHY_RTL8201BL) */ 
    UINT16	data;		/* data to be written to the control reg */
    int		retVal;		/* convenient holder for return value */

    if (isoPhyAddr == MII_PHY_NULL)
	return (OK);

    data = MII_CR_ISOLATE;
    regAddr = MII_CTRL_REG;

    MII_WRITE (isoPhyAddr, regAddr, data, retVal);
    if (retVal != OK)
	return (ERROR);
    
#if !defined(PHY_RTL8201BL)

    /* check isolate bit is asserted */

    while (ix++ < pPhyInfo->phyMaxDelay)
	{
	MII_SYS_DELAY (pPhyInfo->phyDelayParm);

	MII_READ (isoPhyAddr, regAddr, &data, retVal);
	if (retVal != OK)
	    return (ERROR);

	if ((data & MII_CR_ISOLATE))
	    break;
	}

    if (ix >= pPhyInfo->phyMaxDelay)
	{
	MII_LOG (MII_DBG_ANY, ("miiPhyIsolate fail\n"),
			       0, 0, 0, 0, 0, 0);
	return (ERROR);
	}

#endif /* !defined(PHY_RTL8201BL) */    
    
    MII_LOG (MII_DBG_ANY, ("miiPhyIsolate... ends\n"),
			   0, 0, 0, 0, 0, 0);

    return (OK);
    }

/*******************************************************************************
*
* miiPhyPwrDown - put the PHY in power down mode
*
* This routine puts the PHY specified in <phyAddr> in power down mode.
*
* RETURNS: OK or ERROR.
*/

LOCAL STATUS miiPhyPwrDown
    (
    PHY_INFO *  pPhyInfo,      	/* pointer to PHY_INFO structure */
    UINT8 	phyAddr		/* phy to be put in power down mode */
    )
    {
    int		retVal;		/* convenient holder for return value */
    UINT8	regAddr;	/* PHY register */
    UINT16	data;		/* data to be written to the control reg */

    if (phyAddr == MII_PHY_NULL)
	return (OK);

    data = MII_CR_POWER_DOWN;
    regAddr = MII_CTRL_REG;

    MII_WRITE (phyAddr, regAddr, data, retVal);

    return (retVal);
    }

/*******************************************************************************
*
* miiPhyBusScan - scan the MII bus
*
* This routine scans the MII bus, in the search for an MII-compliant PHY.
* If it succeeds, and if the flag MII_ALL_BUS_SCAN is not set, it returns
* OK. Otherwise, it keeps scanning the bus and storing relevant information
* in the miiPhyPresent field of the structure referenced to by <pPhyInfo>.
* Other PHYs than the first one found, will be put in
* low-power mode and electrically isolated from the MII interface.
*
* SEE ALSO: miiAutoNegotiate (), miiModeForce ().
* 
* RETURNS: OK or ERROR.
*
*/

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

    if ((pPhyInfo->miiPhyPresent = (MII_PHY_BUS *) 
				   calloc (1, sizeof (MII_PHY_BUS)))
	== NULL)
	return (ERROR);

    /* 
     * there may be as many as 32 PHYs, with distinct logical addresses
     * Start with the one the user suggested and, in case of failure in 
     * probing the device, scan the whole range.
     */

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

	MII_LOG (MII_DBG_ANY,
		      ("miiPhyBusScan trying phyAddr=0x%x phyInfo=0x%x \n"),
		      phyAddr, pPhyInfo, 0, 0, 0, 0);

	/* check the PHY is there */

	retVal = miiProbe (pPhyInfo, phyAddr);

	/* deal with the error condition if possible */

	if (retVal == ERROR) 
	    {
	    if (errno != S_miiLib_PHY_NULL) 
		return (ERROR);
	    else
		{
		if (ix == (MII_MAX_PHY_NUM - 1))
		    return (ERROR);

		/* no PHY was found with this address: keep scanning */

		MII_LOG (MII_DBG_ANY, "No PHY at address %#x\n", phyAddr,
			 0,0,0,0,0);

		errno = 0;
		continue;
		}
	    }
	else
	    {
	    /* run some diagnostics */

	    if (miiDiag (pPhyInfo, phyAddr) != OK)
		{
		MII_LOG (MII_DBG_ANY, "miiDiag failed for addr %#x\n",
			 phyAddr,0,0,0,0,0);
		return (ERROR);
		}

	    /* record this information */

	    * ((BOOL *) pPhyInfo->miiPhyPresent + phyAddr) = TRUE;

	    /* should we scan the whole bus? */

	    if (!(MII_PHY_FLAGS_ARE_SET (MII_ALL_BUS_SCAN))) 
		{
		MII_LOG (MII_DBG_ANY, "Not scanning whole bus\n", 0,0,0,0,0,0);
		return (OK);
		}

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

    /* set optional features for the other PHYs */

    for (ix = 0; ix < MII_MAX_PHY_NUM; ix++)
	{
	/* check the PHY is there */

	if (* ((BOOL *) pPhyInfo->miiPhyPresent + phyAddr) == TRUE)
	    {
	    /* set it in power down mode */

	    if (MII_PHY_FLAGS_ARE_SET (MII_PHY_PWR_DOWN))
		{
		MII_LOG (MII_DBG_ANY, "Powering down PHY %#x\n", ix,
			 0,0,0,0,0);
		if (miiPhyPwrDown (pPhyInfo, ix) == ERROR)
		    return (ERROR);
		}

	    /* eletrically isolate it from the MII interface */

	    if (MII_PHY_FLAGS_ARE_SET (MII_PHY_ISO))
		{
		MII_LOG (MII_DBG_ANY, "miiPhyBusScan isolating phyAddr=0x%x\n",
				       ix, 0, 0, 0, 0, 0);
		if (miiPhyIsolate (pPhyInfo, ix) == ERROR)
		    return (ERROR);
		}
	    }

	}

    return (OK);
    }

/*******************************************************************************
*
* miiPhyBestModeSet - set the best operating mode for a PHY
*
* This routine sets the best operating mode for a PHY looking at the 
* parameters in <pPhyInfo>. It may call miiAutoNegotiate (), and/or 
* miiModeForce (). Upon success, it stores the <phyAddr> in the relevant
* field of the structure pointed to by <pPhyInfo>.
*
* SEE ALSO: miiAutoNegotiate (), miiModeForce ().
* 
* RETURNS: OK or ERROR.
*
*/

LOCAL STATUS miiPhyBestModeSet
    (
    PHY_INFO *  pPhyInfo,       /* pointer to PHY_INFO structure */
    UINT8 	phyAddr         /* PHY's address */

⌨️ 快捷键说明

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