📄 miilib.c
字号:
) { 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); } /* 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) { if (pPhyInfo->phyFlags & MII_PHY_GMII_TYPE) { pPhyInfo->phyLinkMethod = MII_PHY_LINK_AUTO; } 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) { if (pPhyInfo->phyFlags & MII_PHY_GMII_TYPE) { pPhyInfo->phyLinkMethod = MII_PHY_LINK_FORCE; } goto miiPhyOk; } return (ERROR);miiPhyOk: /* store this PHY and return */ pPhyInfo->phyAddr = phyAddr; MII_PHY_FLAGS_SET (MII_PHY_INIT); return (OK);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -