📄 miilib.c
字号:
/********************************************************************************* 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 */ 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); } return (OK); }/**************************************************************************** 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.** 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.** RETURNS: OK or ERROR.*/ LOCAL STATUS miiPhyMonitorStart ( ) { netJobAdd ((FUNCPTR) miiPhyMonitor, (int) NULL, 0, 0, 0, 0); return (OK); }/**************************************************************************** miiPhyMonitor - monitor all the PHYs to detect a link down event** This routine monitors all the PHYs to detect a link down event.** RETURNS: OK or ERROR.*/ LOCAL STATUS miiPhyMonitor ( ) { UINT16 phyStatus; /* holder for the PHY status */ int retVal = OK; /* convenient holder for return value */ PHY_INFO * pPhyInfo; /* PHY info pointer */ MII_PHY_NODE * pMiiPhyNode = NULL; /* pointer to phy node */ /* protect it from other MII routines */ MII_SEM_TAKE (WAIT_FOREVER); /* loop through all the PHYs */ for (pMiiPhyNode = (MII_PHY_NODE *) lstFirst (&miiList); pMiiPhyNode != NULL; pMiiPhyNode = (MII_PHY_NODE *) lstNext ((NODE *) pMiiPhyNode)) { pPhyInfo = pMiiPhyNode->pPhyInfo; if ((pPhyInfo != NULL) && (MII_PHY_FLAGS_ARE_SET (MII_PHY_INIT)) && (MII_PHY_FLAGS_ARE_SET (MII_PHY_MONITOR))) { MII_READ (pPhyInfo->phyAddr, MII_STAT_REG, &phyStatus, retVal); if (retVal == ERROR) goto miiMonitorExit; MII_READ (pPhyInfo->phyAddr, MII_STAT_REG, &phyStatus, retVal); if (retVal == ERROR) goto miiMonitorExit; /* is the PHY's status link changed? */ if ((pPhyInfo->miiRegs.phyStatus & MII_SR_LINK_STATUS) != (phyStatus & MII_SR_LINK_STATUS)) { MII_LOG (MII_DBG_ANY, ("miiPhyMonitor link down stat=0x%x\n"), phyStatus, 0, 0, 0, 0, 0); /* let the driver know */ if (pPhyInfo->phyLinkDownRtn != NULL) netJobAdd ((FUNCPTR) (pPhyInfo->phyLinkDownRtn), (int) (pPhyInfo->pDrvCtrl), 0, 0, 0, 0); /* record the state so we don't repeatedly tell the driver */ pPhyInfo->miiRegs.phyStatus = phyStatus; } } }miiMonitorExit: MII_SEM_GIVE (); if ((wdStart ((WDOG_ID) miiWd, (MII_MONITOR_DELAY * sysClkRateGet ()), (FUNCPTR) miiPhyMonitorStart, (int) 0)) == ERROR) return (ERROR); return (retVal); }/**************************************************************************** miiLibInit - initialize the MII library** This routine initializes the MII library.** RETURNS: OK or ERROR.*/ STATUS miiLibInit ( ) { if (miiLibInitialized) return (OK); /* Create the mutex semaphore */ miiMutex = semMCreate (SEM_Q_PRIORITY | SEM_DELETE_SAFE | SEM_INVERSION_SAFE); /* create the watchdog, do not start it */ if ((miiWd = wdCreate ()) == NULL) return (ERROR); /* initialize the linked list */ lstInit (&miiList); miiLibInitialized = TRUE; MII_LOG (MII_DBG_ANY, ("miiLibInit end\n"), 0, 0, 0, 0, 0, 0); return (OK); }/**************************************************************************** miiLibUnInit - uninitialize the MII library** This routine uninitializes the MII library. Previously allocated resources* are reclaimed back to the system.** RETURNS: OK or ERROR.*/ STATUS miiLibUnInit ( ) { if (!miiLibInitialized) return (OK); /* are there any PHYs still being used? */ if (miiList.count > 0) return (ERROR); /* delete the watchdog */ if (wdDelete (miiWd) == ERROR) return (ERROR); /* delete the mutex @@@ should we take it first? */ if (semDelete (miiMutex) == ERROR) return (ERROR); miiLibInitialized = FALSE; return (OK); }/**************************************************************************** miiPhyListAdd - add a PHY to the MII linked list** This routine adds the PHY specified in <pPhyInfo> to the MII linked list.** RETURNS: OK or ERROR.*/ LOCAL STATUS miiPhyListAdd ( PHY_INFO * pPhyInfo /* pointer to PHY_INFO structure */ ) { MII_PHY_NODE * pMiiPhyNode = NULL; /* pointer to phy node */ MII_LOG (MII_DBG_ANY, ("miiPhyListAdd start \n"), 0, 0, 0, 0, 0, 0); /* allocate memory for this node, and populate it */ pMiiPhyNode = (MII_PHY_NODE *) calloc (1, sizeof (MII_PHY_NODE)); pMiiPhyNode->pPhyInfo = pPhyInfo; /* protect it from other MII routines */ MII_SEM_TAKE (WAIT_FOREVER); /* add it to the list */ lstAdd (&miiList, (NODE *) pMiiPhyNode); /* we're done, release the mutex */ MII_SEM_GIVE (); /* record this node */ pPhyInfo->pMiiPhyNode = pMiiPhyNode; if ((wdStart (miiWd, MII_MONITOR_DELAY * sysClkRateGet (), (FUNCPTR) miiPhyMonitorStart, (int) 0)) == ERROR) return (ERROR); MII_LOG (MII_DBG_ANY, ("miiPhyListAdd end \n"), 0, 0, 0, 0, 0, 0); return (OK); }#ifdef MII_DBG/**************************************************************************** miiShow - show routine for MII library** This is a show routine for the MII library** RETURNS: OK, always.*/ void miiShow ( PHY_INFO * pPhyInfo /* pointer to PHY_INFO structure */ ) { MII_LOG (MII_DBG_ANY, ("miiShow phyCtrl=0x%x phyStat =0x%x phyAds=0x%x phyPrtn=0x%x phyExp=0x%x phyNpt=0x%x\n"), pPhyInfo->miiRegs.phyCtrl, pPhyInfo->miiRegs.phyStatus, pPhyInfo->miiRegs.phyAds, pPhyInfo->miiRegs.phyPrtn, pPhyInfo->miiRegs.phyExp, pPhyInfo->miiRegs.phyNext); MII_LOG (MII_DBG_ANY, ("miiShow phyAddr=0x%x phyFlags=0x%x phySpeed=%d phyMode=%s\n pDrvCtrl=0x%x \n"), pPhyInfo->phyAddr, pPhyInfo->phyFlags, pPhyInfo->phySpeed, pPhyInfo->phyMode, pPhyInfo->pDrvCtrl, 0); } /**************************************************************************** miiRegsGet - get the contents of MII registers** This routine gets the contents of the first <regNum> MII registers,* and, if <buff> is not NULL, copies them to the space pointed to* by <buff>.** RETURNS: OK, or ERROR if could not perform the read.*/ STATUS miiRegsGet ( PHY_INFO * pPhyInfo, /* pointer to PHY_INFO structure */ UINT regNum, /* number of registers to display */ UCHAR * buff /* where to read registers to */ ) { int retVal; /* convenient holder for return value */ int i; /* a counter */ if (buff == NULL) return (OK); regNum = (regNum > MII_MAX_REG_NUM) ? MII_MAX_REG_NUM : regNum; /* Read all the registers the user specified */ for (i = 0; i < regNum; i++) { MII_READ (pPhyInfo->phyAddr, i, (UINT16 *) &buff [2 * i], retVal); if (retVal != OK) return (ERROR); } return (OK); }#endif /* MII_DBG */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -