📄 miilib.c
字号:
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); } /* 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); } 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 */ UINT16 ix = 0; /* a counter */ 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); /* 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); } 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 */ ) { /* * start the auto-negotiation process, * unless the user dictated the contrary. */ if (pPhyInfo->phyFlags & MII_PHY_AUTO) if (miiAutoNegotiate (pPhyInfo, phyAddr) == OK) { 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) { 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); /* * chek with the BSP if we need to do something else before * we try and establish the link */ if (pPhyOptRegsRtn != NULL) (* pPhyOptRegsRtn) (pPhyInfo); /* 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 */ /* Read ANER to clear status from previous operations */ regAddr = MII_AN_EXP_REG; MII_READ (phyAddr, regAddr, &status, retVal); if (retVal != OK) return (ERROR);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -