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

📄 miilib.c

📁 操作系统vxworks平台下end设备的驱动程序,支持多种芯片,支持多种cpu
💻 C
📖 第 1 页 / 共 5 页
字号:
	/* 	 * 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 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 */    UINT16	ix = 0;		/* a counter */    int		retVal;		/* convenient holder for return value */    int         maxDelay;       /* maximum delay tick or count */    int         delayUnit;      /* delay unit/tick per call phyDelayRtn */     int         delayCount;     /* delay number/tick */    /* let's check the PHY status for completion */    regAddr = MII_STAT_REG;    /*      * the old algorithm assumes the delay routine is taskDelay(), which     * is not appropriate. However, for backward compatibility reason,      * the old algorithm is still kept if the delay function is taskDelay().     */       if (pPhyInfo->phyDelayRtn == (FUNCPTR) taskDelay)       {       maxDelay = pPhyInfo->phyMaxDelay * pPhyInfo->phyDelayParm;       delayUnit = sysClkRateGet ();       delayCount = delayUnit;       }    else       {       maxDelay = pPhyInfo->phyMaxDelay;       delayUnit = pPhyInfo->phyDelayParm;       delayCount = 1;       }    /* spin until it is done */    do      {       MII_SYS_DELAY (delayUnit);       ix += delayCount;          if (ix >= maxDelay)           {           MII_LOG (MII_DBG_ANY, ("miiBasicCheck fail\n"),                                             0, 0, 0, 0, 0, 0);           return (ERROR);           }       MII_READ (phyAddr, regAddr, &phyStatus, retVal);       if (retVal != OK)           return (ERROR);      } while ((phyStatus & MII_SR_LINK_STATUS) != MII_SR_LINK_STATUS);    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 */    )    {    /* check speed ... */     if (MII_PHY_FLAGS_ARE_SET (MII_PHY_1000T_FD) ||         MII_PHY_FLAGS_ARE_SET (MII_PHY_1000T_HD))        pPhyInfo->phySpeed = MII_1000MBS;    else 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);    }/********************************************************************************* miiPhyUpdate - update the phyInfo structure to the latest PHY status** This routine updates the phyInfo structure to the latest PHY status.** RETURNS: OK or ERROR.*/LOCAL STATUS miiPhyUpdate    (    PHY_INFO *  pPhyInfo,       /* pointer to PHY_INFO structure */    UINT8	phyAddr		/* address of a PHY */    )    {    UINT16	phyStatus;	/* holder for the PHY status */    UINT16	phyAds;		/* PHY advertisement register value */    UINT16	phyPrtn;	/* PHY partner ability register value */    UINT16	phyExp;		/* PHY expansion register value */    UINT16  phyMstSlaCtrl; /* PHY Master-slave Control value */    UINT16  phyMstSlaStat; /* PHY Master-slave Status value */    UINT16	negAbility;	/* abilities after negotiation */    int		retVal;		/* convenient holder for return value */    MII_READ (phyAddr, MII_STAT_REG, &phyStatus, retVal);    if (retVal == ERROR)	return (ERROR);    /* does the PHY support the extended registers set? */    if (!(phyStatus & MII_SR_EXT_CAP))	return (OK);    MII_READ (phyAddr, MII_AN_ADS_REG, &phyAds, retVal);    if (retVal == ERROR)	return (ERROR);    MII_READ (phyAddr, MII_AN_PRTN_REG, &phyPrtn, retVal);    if (retVal == ERROR)	return (ERROR);    MII_READ (phyAddr, MII_AN_EXP_REG, &phyExp, retVal);    if (retVal == ERROR)	return (ERROR);    /* flow control configuration */    /* MII defines symmetric PAUSE ability */    if ((!(phyAds & MII_ANAR_PAUSE)) || (!(phyPrtn & MII_TECH_PAUSE)))        pPhyInfo->phyFlags &= ~(MII_PHY_TX_FLOW_CTRL | MII_PHY_RX_FLOW_CTRL);     else        pPhyInfo->phyFlags |= (MII_PHY_TX_FLOW_CTRL | MII_PHY_RX_FLOW_CTRL);     if (pPhyInfo->phyFlags & MII_PHY_GMII_TYPE)        {        /* GMII also defines asymmetric PAUSE ability */        /* Advertises transmitter but no receiver */        if (((phyAds & MII_ANAR_PAUSE_MASK) == MII_ANAR_ASM_PAUSE) &&             ((phyPrtn & MII_TECH_PAUSE_MASK) == MII_TECH_PAUSE_MASK))            {            pPhyInfo->phyFlags |= MII_PHY_TX_FLOW_CTRL;            }        /* Advertises receiver but no transmitter */        else if (((phyAds & MII_ANAR_PAUSE_MASK) == MII_ANAR_PAUSE_MASK) &&            ((phyPrtn & MII_TECH_PAUSE_MASK) == MII_TECH_ASM_PAUSE))            {            pPhyInfo->phyFlags |= MII_PHY_RX_FLOW_CTRL;            }        /* no flow control */        else if ((!(phyAds & MII_ANAR_PAUSE)) || (!(phyPrtn & MII_TECH_PAUSE)))            {            pPhyInfo->phyFlags &= ~(MII_PHY_TX_FLOW_CTRL |                                        MII_PHY_RX_FLOW_CTRL);            }        /* TX and RX flow control */        else            {            pPhyInfo->phyFlags |= (MII_PHY_TX_FLOW_CTRL | MII_PHY_RX_FLOW_CTRL);            }        }    /* find out the max common abilities */    if (pPhyInfo->phyFlags & MII_PHY_GMII_TYPE)        {        /* search for 1000T capbility */        /* get MASTER-SLAVE control register */        MII_READ (phyAddr, MII_MASSLA_CTRL_REG, &phyMstSlaCtrl, retVal);        if (retVal == ERROR)            return (ERROR);        /* get MASTER-SLAVE status register */        MII_READ (phyAddr, MII_MASSLA_STAT_REG, &phyMstSlaStat, retVal);        if (retVal == ERROR)            return (ERROR);        MII_READ (phyAddr, MII_MASSLA_STAT_REG, &phyMstSlaStat, retVal);        if (retVal == ERROR)            return (ERROR);        if ((phyMstSlaStat & MII_MASSLA_STAT_LP1000T_FD) &&             (phyMstSlaCtrl & MII_MASSLA_CTRL_1000T_FD))            {            /* 1000T FD supported */                         MII_PHY_FLAGS_SET (MII_PHY_FD);            goto exitPhyUpdate;            }        else if ((phyMstSlaStat & MII_MASSLA_STAT_LP1000T_HD) &&                  (phyMstSlaCtrl & MII_MASSLA_CTRL_1000T_HD))            {               /* 1000T HD supported */                             MII_PHY_FLAGS_SET (MII_PHY_HD);            MII_PHY_FLAGS_CLEAR (MII_PHY_1000T_FD);            goto exitPhyUpdate;            }        else            {            /* 1000T not supported, go check other abilities */            MII_PHY_FLAGS_CLEAR (MII_PHY_1000T_FD);             MII_PHY_FLAGS_CLEAR (MII_PHY_1000T_HD);            }        }    negAbility = phyPrtn & phyAds & MII_ADS_TECH_MASK;    MII_LOG (MII_DBG_ANY, ("miiPhyUpdate phyAds=0x%x			   phyPrtn=0x%x common=0x%x phyExp=0x%x\n"),			   phyAds, 			   phyPrtn, 			   negAbility, 			   phyExp, 0, 0);    if (negAbility & MII_TECH_100BASE_TX_FD)	{	}    else if ((negAbility & MII_TECH_100BASE_TX) ||	 (negAbility & MII_TECH_100BASE_T4))	{	MII_PHY_FLAGS_CLEAR (MII_PHY_FD);	}    else if (negAbility & MII_TECH_10BASE_FD)	{	MII_PHY_FLAGS_CLEAR (MII_PHY_100); 	}    else if (negAbility & MII_TECH_10BASE_T)	{	MII_PHY_FLAGS_CLEAR (MII_PHY_FD);	MII_PHY_FLAGS_CLEAR (MII_PHY_100); 	}    else	{	MII_LOG (MII_DBG_ANY, ("miiPhyUpdate fail!\n"),			       0, 0, 0, 0, 0, 0);	return (ERROR);	}    /* store the current registers values */exitPhyUpdate:    pPhyInfo->miiRegs.phyStatus = phyStatus;    pPhyInfo->miiRegs.phyAds = phyAds;    pPhyInfo->miiRegs.phyPrtn = phyPrtn;    pPhyInfo->miiRegs.phyExp = phyExp;    if (pPhyInfo->phyFlags & MII_PHY_GMII_TYPE)        {            pPhyInfo->miiGRegs.phyMSStatus = phyMstSlaStat;        pPhyInfo->miiGRegs.phyMSCtrl = phyMstSlaCtrl;        }    /* handle some flags */    if (miiFlagsHandle (pPhyInfo, phyAddr) != OK)	return (ERROR);    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.** NOTE: * In case the cable is pulled out and reconnect to the same/different * hub/switch again. PHY probably starts a new auto-negotiation process and * get different negotiation results. User should call this routine to check * link status and update phyFlags. pPhyInfo should include a valid * PHY bus number (phyAddr), and include the phyFlags that was used last time 

⌨️ 快捷键说明

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