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

📄 miilib.c

📁 Embedded Planet公司的ep8260单板计算机的BSP包(VxWorks)
💻 C
📖 第 1 页 / 共 4 页
字号:
/* miiLib.c - Media Independent Interface library */
 
/* Copyright 1989-1999 Wind River Systems, Inc. */
#include "copyright_wrs.h"

/*
modification history
--------------------
01d,28sep99,cn  changed miiProbe to better detect PHYs.
01c,13sep99,cn  fixed SPR# 28305. Also added show routines.
01b,16jun99,cn  implemented changes after code review.
01a,16mar99,cn  written from motFecEnd.c, 01c.
*/

/*
DESCRIPTION
This module implements a Media Independent Interface (MII) library. 

The MII is an inexpensive and easy-to-implement interconnection between
the Carrier Sense Multiple Access with Collision Detection (CSMA/CD)
media access controllers and the Physical Layer Entities (PHYs).

The purpose of this library is to provide Ethernet drivers in VxWorks
with a standardized, MII-compliant, easy-to-use interface to various PHYs.
In other words, using the services of this library, network drivers
will be able to scan the existing PHYs, run diagnostics, electrically
isolate a subset of them, negotiate their technology abilities with other
link-partners on the network, and ultimately initialize and configure a
specific PHY in a proper, MII-compliant fashion.

In order to initialize and configure a PHY, its MII management interface 
has to be used. This is made up of two lines: management data clock (MDC) 
and management data input/output (MDIO). The former provides the timing 
reference for transfer of information on the MDIO signal.  The latter is 
used to transfer control and status information between the PHY and the 
MAC controller. For this transfer to be successful, the information itself
has to be encoded into a frame format, and both the MDIO and MDC signals have
to comply with certain requirements as described in the 802.3u IEEE Standard.

Since no assumption can be made as to the specific MAC-to-MII
interface, this library expects the driver's writer to provide it with 
specialized read and write routines to access that interface. See EXTERNAL 
SUPPORT REQUIREMENTS below.

EXTERNAL INTERFACE
The only external routines are miiPhyInit () and miiPhyOptFuncSet ().
miiPhyInit () should be called with the address of a PHY_INFO sructure
as only parameter.
.CS
    STATUS    	miiPhyInit (PHY_INFO * pPhyInfo);
.CE

The routine miiPhyOptFuncSet () should have a valid function pointer
as only parameter.
.CS
    void    	miiPhyOptFuncSet (FUNCPTR optRegsFunc);
.CE

EXTERNAL SUPPORT REQUIREMENTS
.IP phyReadRtn ()
.CS
    STATUS    	phyReadRtn (DRV_CTRL * pDrvCtrl, UINT8 phyAddr, 
			    UINT8 phyReg, UINT16 * value);
.CE
This routine is expected to perform any driver-specific functions required
to read a 16-bit word from the <phyReg> register of the MII-compliant PHY
whose address is specified by <phyAddr>. Reading is performed through the
MII management interface.

.IP phyWriteRtn ()
.CS
    STATUS    	phyWriteRtn (DRV_CTRL * pDrvCtrl, UINT8 phyAddr, 
			     UINT8 phyReg, UINT16 value);
.CE
This routine is expected to perform any driver-specific functions required
to write a 16-bit word to the <phyReg> register of the MII-compliant PHY
whose address is specified by <phyAddr>. Writing is performed through the
MII management interface.

.IP phyDelayRtn ()
.CS
    STATUS    	phyDelayRtn (UINT32 phyDelayParm);
.CE
This routine is expected to cause a limited delay to the calling task,
no matter whether this is an active delay, or an inactive one.
miiPhyInit () calls this routine on several occasions throughout
the code with <phyDelayParm> as parameter. This represents the granularity 
of the delay itself, whereas the field <phyMaxDelay> in PHY_INFO is the
maximum allowed delay, in <phyDelayParm> units.

The user should be aware that some of these events may take as long as
2-3 seconds to be completed, and he should therefore tune this routine
and the parameter <phyMaxDelay> accordingly.

If the related field <phyDelayRtn> in the PHY_INFO structure is initialized 
to NULL, no delay is performed.

.LP
SEE ALSO: 
.I "IEEE 802.3u Standard"

INTERNAL
This library contains conditional compilation switch MII_END_DEBUG.
If defined, adds debug output routines.  Output is further
selectable at run-time via the miiDbg global variable.
*/

#include "vxWorks.h"
#include "errnoLib.h"
#include "stdio.h"
#include "stdlib.h"
#include "iosLib.h"
#include "net/mbuf.h"
#include "private/funcBindP.h"
#include "logLib.h"
#include "lstLib.h"
#include "miiLib.h"
#include "end.h"

/* defines */

/* Driver debug control */

#undef MII_DBG 

/* Driver debug control */

#ifdef MII_DBG
#define MII_DBG_ANY    		0xffff

UINT32		miiDbg = 0x0;
PHY_INFO	* phyInfoDbg = NULL;

#define MII_LOG(FLG, X0, X1, X2, X3, X4, X5, X6)			\
    {									\
    if (miiDbg & FLG)							\
	if (_func_logMsg != NULL)					\
	    _func_logMsg ((X0), (X1), (X2), (X3), (X4), (X5), (X6));	\
    }

#else /* MII_DBG */

#define MII_LOG(FLG, X0, X1, X2, X3, X4, X5, X6)

#endif /* MII_DBG */
 
#define   MII_PHY_CHECK_CABLE						\
    if (_func_logMsg != NULL)						\
	_func_logMsg ("miiPhyInit check cable connection \n",		\
		      0, 0, 0, 0, 0, 0)

/*
 * the table below is used to translate user settings
 * into MII-standard values for the control register.
 */
 
LOCAL UINT16 miiDefLookupTbl [] = {
                                  MII_CR_NORM_EN,
                                  MII_CR_FDX,
                                  MII_CR_100,
                                  (MII_CR_100 | MII_CR_FDX),
                                  MII_CR_100
                                  };
 
/* library flags */

#define MII_PHY_FLAGS_SET(setBits)					\
    (pPhyInfo->phyFlags |= (setBits))

#define MII_PHY_FLAGS_ARE_SET(setBits)					\
    (pPhyInfo->phyFlags & (setBits))

#define MII_PHY_FLAGS_GET(setBits)					\
    (pPhyInfo->phyFlags)

#define MII_PHY_FLAGS_CLEAR(clearBits)					\
    (pPhyInfo->phyFlags &= ~(clearBits))

#define MII_FROM_ANSR_TO_ANAR(statReg, adsReg)				\
    {									\
    phyStat &= MII_SR_ABIL_MASK;					\
    phyStat >>= 6;							\
    phyAds = phyStat + (phyAds & 0x7000) + (phyAds & MII_ADS_SEL_MASK); \
    }

/* globals */

/* locals */

LOCAL FUNCPTR pPhyOptRegsRtn = NULL;

/* forward function declarations */

LOCAL STATUS	miiDiag (PHY_INFO * pPhyInfo, UINT8 phyAddr);
LOCAL STATUS	miiPhyIsolate (PHY_INFO * pPhyInfo, UINT8 isoPhyAddr);
LOCAL STATUS	miiPhyFeatureSet (PHY_INFO * pPhyInfo);
LOCAL STATUS	miiPhyPwrDown (PHY_INFO * pPhyInfo, UINT8 phyAddr);
LOCAL STATUS	miiPhyBestModeSet (PHY_INFO * pPhyInfo);
LOCAL STATUS	miiPhyDefModeSet (PHY_INFO * pPhyInfo);
LOCAL STATUS	miiAutoNegotiate (PHY_INFO * pPhyInfo, UINT8 phyAddr);
LOCAL STATUS	miiAutoNegStart (PHY_INFO * pPhyInfo, UINT8 phyAddr);
LOCAL STATUS	miiModeForce (PHY_INFO * pPhyInfo, UINT8 phyAddr);
LOCAL STATUS	miiDefForce (PHY_INFO * pPhyInfo, UINT8 phyAddr);
LOCAL STATUS	miiAnCheck (PHY_INFO * pPhyInfo, UINT8 phyAddr);
LOCAL STATUS	miiFlagsHandle (PHY_INFO * pPhyInfo, UINT8 phyAddr);
LOCAL STATUS	miiProbe (PHY_INFO * pPhyInfo, UINT8 phyAddr);
LOCAL STATUS	miiAbilFlagSet (PHY_INFO * pPhyInfo, UINT8 phyAddr);

/**************************************************************************
*
* miiPhyInit - initialize and configure the PHY devices
*
* This routine scans, initializes and configures the PHY device described
* in <phyInfo>. Space for <phyInfo> is to be provided by the calling
* task.
*
* This routine is called from the driver's Start routine to
* perform media inialization and configuration. To access the PHY
* device through the MII-management interface, it uses the read and
* write routines which are provided by the driver itself
* in the fields  phyReadRtn(), phyWriteRtn() of the phyInfo structure.
* Before it attempts to use this routine, the driver has to properly 
* initialize some of the fields in the <phyInfo> structure, and optionally
* fill in others, as below:
* .CS
*
*    /@ fill in mandatory fields in phyInfo @/
* 
*    pDrvCtrl->phyInfo->pDrvCtrl = (void *) pDrvCtrl;
*    pDrvCtrl->phyInfo->phyWriteRtn = (FUNCPTR) xxxMiiWrite;
*    pDrvCtrl->phyInfo->phyReadRtn = (FUNCPTR) xxxMiiRead;
* 
*    /@ fill in some optional fields in phyInfo @/
* 
*    pDrvCtrl->phyInfo->phyFlags = 0;
*    pDrvCtrl->phyInfo->phyAddr = (UINT8) MII_PHY_DEF_ADDR;
*    pDrvCtrl->phyInfo->phyDefMode = (UINT8) PHY_10BASE_T;
*    pDrvCtrl->phyInfo->phyAnOrderTbl = (MII_AN_ORDER_TBL *)
*                                        &xxxPhyAnOrderTbl;
* 
*    /@ 
*     @ fill in some more optional fields in phyInfo: the delay stuff
*     @ we want this routine to use our xxxDelay () routine, with
*     @ the constant one as an argument, and the max delay we may
*     @ tolerate is the constant MII_PHY_DEF_DELAY, in xxxDelay units
*     @/
* 
*    pDrvCtrl->phyInfo->phyDelayRtn = (FUNCPTR) xxxDelay;
*    pDrvCtrl->phyInfo->phyMaxDelay = MII_PHY_DEF_DELAY;
*    pDrvCtrl->phyInfo->phyDelayParm = 1;
*
* .CE
*
* Some of the above fields may be overwritten by this routine, since 
* for instance, the logical address of the PHY actually used may differ
* from the user's initial setting. Likewise, the specific PHY being
* initialized, may not support all the technology abilities the user
* has allowed for its operations.
* 
* Before it attempts to bring the link up, this routine checks the
* phyFlags field in the phyInfo structure for PHY devices that need to be 
* electrically isolated by the MII interface. All the valid PHYs found are
* electrically isolated.
*
* The routine then scans for all possible PHY addresses in the range 0-31,
* checking for an MII-compliant PHY, and attempts to  establish a
* valid link for it. If none is found, ERROR is returned.
* Typically PHYs are scanned from address 0, but if the user specifies
* an alternative start PHY address via the parameter phyAddr in the 
* phyInfo structure, all (32) PHYs are scanned in order starting 
* with the specified PHY address, until a valid link is established.
*
* This routine offers two strategies to select a PHY and establish a
* valid link. The default strategy is to use the standard 802.3 style 
* auto-negotiation, where both link partners negotiate all their 
* technology abilities at the same time, and the highest common 
* denominator ability is chosen. Before the auto-negotiation
* is started, the next-page exchange mechanism is disabled.
*
* The user can prevent the PHY from negotiating certain abilities via 
* userFlags -- <MII_PHY_FD>, <MII_PHY_100>, <MII_PHY_HD>, and <MII_PHY_10>. 
* When <MII_PHY_FD> is not specified, full duplex will not be 
* negotiated; when <MII_PHY_HD> is not specified half duplex 
* will not be negotiated, when <MII_PHY_100> is not specified, 
* 100Mbps ability will not be negotiated; when <MII_PHY_10> is not 
* specified, 10Mbps ability will not be negotiated.
*
* When <MII_PHY_TBL> is set in the user flags, the BSP specific 
* table whose address is to be provided in the <phyAnOrderTbl>
* field of the <phyInfo> structure, is used to obtain the list, and 
* the order of technology abilities to be negotiated.
* The entries in this table are ordered such that entry 0 is the
* highest priority, entry 1 in next and so on. Entries in this table 
* may be repeated, and multiple technology abilities can
* be OR'd to create a single  entry. If a PHY cannot support a
* ability in an entry, that entry is ignored. 
*
* If no PHY provides a valid link, and if <MII_PHY_DEF_SET> is set in the
* phyFlags field of the PHY_INFO structure, the PHYs are scanned again in the
* same order, and the first PHY that supports the default abilities
* defined in the <phyDefMode> of the phyInfo structure will be selected, 
* regardless of the link status.
*
* RETURNS: OK or ERROR if the PHY could not be initialised,
*
*/

STATUS miiPhyInit
    (
    PHY_INFO *  pPhyInfo       /* pointer to PHY_INFO structure */
    )
    {
    int		retVal;		/* convenient holder for return value */

    /* sanity checks */

    if (pPhyInfo == NULL ||
	(pPhyInfo->phyReadRtn == NULL) ||
	(pPhyInfo->phyWriteRtn == NULL) ||
	(pPhyInfo->pDrvCtrl == NULL))
	{
	MII_LOG (MII_DBG_ANY, ("miiPhyInit... missing params \n"),
			       0, 0, 0, 0, 0, 0);
	return (ERROR);
	}

#ifdef MII_DBG
    phyInfoDbg = pPhyInfo;
#endif /* MII_DBG */

    /* 
     * set some features for all the PHYs (power down mode,
     * electrical isolation, etc.)
     */

    if (miiPhyFeatureSet (pPhyInfo) == ERROR)
	return (ERROR);

    /* set the mode for a PHY, return in case of success or fatal error */

    retVal = miiPhyBestModeSet (pPhyInfo);
    if (retVal == OK)
	return (OK);

    if (errno != S_miiLib_PHY_LINK_DOWN)
	return (ERROR);

    /* if we're here, none of the PHYs could be initialized */

    MII_PHY_CHECK_CABLE;

    if (!(MII_PHY_DEF_SET))
	return (ERROR);

    /* set the default mode for a PHY, do not check the link */

    return (miiPhyDefModeSet (pPhyInfo));
    } 

/**************************************************************************
*
* miiProbe - probe the PHY device
*
* This routine probes the PHY device by reading its control register.
*
* 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 */

    regAddr = MII_CTRL_REG;
    MII_READ (phyAddr, regAddr, &data, retVal);

    if (retVal == ERROR)
	return (ERROR);

    if (((data & MII_CR_DEF_0_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;

⌨️ 快捷键说明

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