📄 miilib.c
字号:
{
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
* to configure auto-negotiation process.
*
* RETURNS: OK or ERROR.
*/
STATUS miiAnCheck
(
PHY_INFO * pPhyInfo, /* pointer to PHY_INFO structure */
UINT8 phyAddr /* address of a PHY */
)
{
UINT8 regAddr; /* PHY register */
UINT16 phyPrtn; /* PHY partner ability register value */
UINT16 phyExp; /* PHY expansion register value */
int retVal; /* convenient holder for return value */
/*
* The sysClkRate could have changed since the link was lost.
* Ensure that pPhyInfo->phyMaxDelay is at lease 5 seconds.
*/
if (pPhyInfo->phyMaxDelay < (sysClkRateGet() * 5))
{
/* Set max delay porportionally */
pPhyInfo->phyMaxDelay = sysClkRateGet() * 5;
}
/* run a check on the status bits of basic registers only */
retVal = miiBasicCheck (pPhyInfo, phyAddr);
if (retVal != OK)
return (retVal);
/* we know the auto-negotiation process has finished */
regAddr = MII_AN_EXP_REG;
MII_READ (phyAddr, regAddr, &phyExp, retVal);
if (retVal != OK)
return (ERROR);
/* check for faults detected by the parallel function */
if ((phyExp & MII_EXP_FAULT) == MII_EXP_FAULT)
{
MII_LOG (MII_DBG_ANY, ("miiAnCheck: fault expStat=0x%x\n"),
phyExp, 0, 0, 0, 0, 0);
/*
* Don't fail here as some PHY devices don't support this register,
* but seem to return 0xffff when it is read (jgn - 5/8/00)
*/
/* return (ERROR); */
}
/* check for remote faults */
regAddr = MII_AN_PRTN_REG;
MII_READ (phyAddr, regAddr, &phyPrtn, retVal);
if (retVal != OK)
return (ERROR);
if ((phyPrtn & MII_BP_FAULT) == MII_BP_FAULT)
{
MII_LOG (MII_DBG_ANY, ("miiAnCheck partner stat=0x%x\n"),
phyPrtn, 0, 0, 0, 0, 0);
return (ERROR);
}
if (miiPhyUpdate (pPhyInfo, phyAddr) == ERROR)
{
MII_LOG (MII_DBG_ANY, "miiPhyUpdate error\n",0,0,0,0,0,0);
return (ERROR);
}
MII_LOG (MII_DBG_ANY, ("miiAnCheck OK\n"),
0, 0, 0, 0, 0, 0);
return (OK);
}
/*******************************************************************************
*
* miiModeForce - force an operating mode for the PHY
*
* This routine forces an operating mode for the PHY whose address is
* specified in the parameter <phyAddr>. It also calls miiBasicCheck()
* to ensure a valid link has been established.
*
* RETURNS: OK or ERROR.
*/
LOCAL STATUS miiModeForce
(
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 */
int retVal; /* convenient holder for return value */
MII_LOG (MII_DBG_ANY, ("miiModeForce \n"),
0, 0, 0, 0, 0, 0);
/*
* force as a high priority as possible operating
* mode, not overlooking what the user dictated.
*/
data = MII_CR_NORM_EN;
if (MII_PHY_FLAGS_ARE_SET (MII_PHY_100))
{
data |= MII_CR_100;
}
if (MII_PHY_FLAGS_ARE_SET (MII_PHY_FD))
{
data |= MII_CR_FDX;
}
pPhyInfo->miiRegs.phyCtrl = data;
regAddr = MII_CTRL_REG;
/* try to establish the link */
MII_WRITE (phyAddr, regAddr, data, retVal);
if (retVal != OK)
return (ERROR);
/* run a check on the status bits of basic registers only */
if (miiBasicCheck (pPhyInfo, phyAddr) != OK)
return (ERROR);
/* handle some flags */
if (miiFlagsHandle (pPhyInfo, phyAddr) != OK)
return (ERROR);
return (OK);
}
/*******************************************************************************
*
* miiDefForce - force a default operating mode for the PHY
*
* This routine forces a default operating mode for the PHY whose address is
* specified in the parameter <phyAddr>. It also calls miiBasicCheck()
* to ensure a valid link has been established.
*
* RETURNS: OK or ERROR.
*
* ERRNO: S_miiLib_PHY_NO_ABLE
*
*/
LOCAL STATUS miiDefForce
(
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 */
int retVal; /* convenient holder for return value */
UINT16 phyStatus; /* holder for the PHY status */
MII_LOG (MII_DBG_ANY, ("miiDefForce \n"),
0, 0, 0, 0, 0, 0);
/* translate user settings */
data = miiDefLookupTbl [(pPhyInfo->phyDefMode)];
/* find out what abilities the PHY features */
regAddr = MII_STAT_REG;
MII_READ (phyAddr, regAddr, &phyStatus, retVal);
if (retVal == ERROR)
return (ERROR);
if (data & MII_CR_100)
{
if (!(phyStatus & (MII_SR_TX_HALF_DPX
| MII_SR_TX_FULL_DPX
| MII_SR_T4)))
{
errnoSet (S_miiLib_PHY_NO_ABLE);
return (ERROR);
}
MII_PHY_FLAGS_SET (MII_PHY_100);
}
else
{
if (!(phyStatus & (MII_SR_10T_HALF_DPX
| MII_SR_10T_FULL_DPX)))
{
errnoSet (S_miiLib_PHY_NO_ABLE);
return (ERROR);
}
MII_PHY_FLAGS_CLEAR (MII_PHY_100);
}
if (data & MII_CR_FDX)
{
if (!(phyStatus & (MII_SR_10T_FULL_DPX
| MII_SR_TX_FULL_DPX)))
{
errnoSet (S_miiLib_PHY_NO_ABLE);
return (ERROR);
}
MII_PHY_FLAGS_SET (MII_PHY_FD);
}
else
{
if (!(phyStatus & (MII_SR_10T_HALF_DPX
| MII_SR_TX_HALF_DPX)))
{
errnoSet (S_miiLib_PHY_NO_ABLE);
return (ERROR);
}
MII_PHY_FLAGS_CLEAR (MII_PHY_FD);
}
pPhyInfo->miiRegs.phyCtrl = data;
regAddr = MII_CTRL_REG;
/* force this specific operating mode, but do not check the link */
MII_WRITE (phyAddr, regAddr, data, retVal);
/* handle some flags */
if (miiFlagsHandle (pPhyInfo, phyAddr) != OK)
return (ERROR);
return (OK);
}
/**************************************************************************
*
* miiAbilFlagSet - set some ability flags
*
* This routine sets some ability flags for a later use.
*
* RETURNS: OK, always.
*/
LOCAL STATUS miiAbilFlagSet
(
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 phyExtStat; /* holder for the PHY Extended status */
int retVal; /* convenient holder for return value */
/* find out what abilities the PHY features */
regAddr = MII_STAT_REG;
MII_READ (phyAddr, regAddr, &phyStatus, retVal);
if (retVal == ERROR)
return (ERROR);
/* handle phy flags */
if (!(phyStatus & (MII_SR_TX_HALF_DPX
| MII_SR_TX_FULL_DPX
| MII_SR_T4)))
{
MII_PHY_FLAGS_CLEAR (MII_PHY_100);
}
if (!(phyStatus & (MII_SR_10T_FULL_DPX
| MII_SR_TX_FULL_DPX)))
{
MII_PHY_FLAGS_CLEAR (MII_PHY_FD);
}
if (!(phyStatus & (MII_SR_10T_HALF_DPX
| MII_SR_10T_FULL_DPX)))
{
MII_PHY_FLAGS_CLEAR (MII_PHY_10);
}
if (!(phyStatus & (MII_SR_TX_HALF_DPX
| MII_SR_10T_HALF_DPX)))
{
MII_PHY_FLAGS_CLEAR (MII_PHY_HD);
}
if (!(phyStatus & MII_SR_AUTO_SEL))
{
MII_LOG (MII_DBG_ANY, ("miiAbilFlagSet phy not
auto neg capable\n"),
0, 0, 0, 0, 0, 0);
MII_PHY_FLAGS_CLEAR (MII_PHY_AUTO);
}
if (pPhyInfo->phyFlags & MII_PHY_GMII_TYPE)
{
regAddr = MII_EXT_STAT_REG;
MII_READ (phyAddr, regAddr, &phyExtStat, retVal);
if (retVal != OK)
return (ERROR);
/* mask off 1000T FD if PHY not supported */
if (!(phyExtStat & MII_EXT_STAT_1000T_HD))
MII_PHY_FLAGS_CLEAR (MII_PHY_1000T_HD);
/* mask off 1000T HD if PHY not supported */
if (!(phyExtStat & MII_EXT_STAT_1000T_FD))
MII_PHY_FLAGS_CLEAR (MII_PHY_1000T_FD);
}
return (OK);
}
/**************************************************************************
*
* miiPhyOptFuncMultiSet - set pointers to MII optional registers handlers
*
* This routine sets the function pointers in <pPhyInfo->optRegsFunc> to the
* MII optional, PHY-specific registers handler. The handler will be executed
* before the PHY's technology abilities are negotiated. If a system employees
* more than on type of network device requiring a PHY-specific registers
* handler use this routine instead of miiPhyOptFuncSet() to ensure device
* specific handlers and to avoid overwritting one's with the other's.
*
* PROTECTION DOMAINS
* (VxAE) This function can only be called from within the kernel protection
* domain. The argument optRegsFunc MUST be a pointer to function in the kernel
* protection domain.
*
* RETURNS: N/A.
*/
void miiPhyOptFuncMultiSet
(
PHY_INFO * pPhyInfo, /* device specific pPhyInfo pointer */
FUNCPTR optRegsFunc /* function pointer */
)
{
if (optRegsFunc != NULL)
pPhyInfo->pPhyOptRegsRtn = optRegsFunc;
else
pPhyInfo->pPhyOptRegsRtn = NULL;
}
/**************************************************************************
*
* miiPhyOptFuncSet - set the pointer to the MII optional registers handler
*
* This routine sets the function pointer in <optRegsFunc> to the MII
* optional, PHY-specific registers handler. The handler will be executed
* before the PHY's technology abilities are negotiated.
*
* PROTECTION DOMAINS
* (VxAE) This function can only be called from within the kernel protection
* domain. The argument optRegsFunc MUST be a pointer to function in the kernel
* protection domain.
*
* RETURNS: N/A.
*/
void miiPhyOptFuncSet
(
FUNCPTR optRegsFunc /* function pointer */
)
{
if (optRegsFunc != NULL)
pPhyOptRegsRtn = optRegsFunc;
else
pPhyOptRegsRtn = NULL;
}
/**************************************************************************
*
* miiPhyMonitorStart - monitor all the PHYs to detect a status change
*
* This routine monitors all the PHYs to detect a status change.
*
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -