blob: b5d4fad19b596952cc3c6d66d47265bb743c2ea3 [file] [log] [blame]
#include <Copyright.h>
/********************************************************************************
* gtPhyCtrl.h
*
* DESCRIPTION:
* API definitions for PHY control facility.
*
* DEPENDENCIES:
* None.
*
* FILE REVISION NUMBER:
* $Revision: 10 $
*******************************************************************************/
#include <msApi.h>
#include <gtHwCntl.h>
#include <gtDrvConfig.h>
#include <gtDrvSwRegs.h>
#include <gtVct.h>
#include <gtSem.h>
#ifdef GT_USE_MAD
#include <madApi.h>
#include <madHwCntl.h>
#endif
/*
* This routine set Auto-Negotiation Ad Register for Copper
*/
static
GT_STATUS translateAutoMode
(
IN GT_PHY_INFO *phyInfo,
IN GT_PHY_AUTO_MODE mode,
OUT MAD_BOOL *autoEn,
OUT MAD_U32 *autoMode
)
{
MAD_BOOL autoNegoEn;
MAD_SPEED_MODE speedMode;
MAD_DUPLEX_MODE duplexMode;
switch(mode)
{
case SPEED_AUTO_DUPLEX_AUTO:
autoNegoEn = MAD_TRUE;
speedMode = MAD_SPEED_AUTO;
duplexMode = MAD_AUTO_DUPLEX;
case SPEED_1000_DUPLEX_AUTO:
autoNegoEn = MAD_TRUE;
speedMode = MAD_SPEED_1000M;
duplexMode = MAD_AUTO_DUPLEX;
break;
case SPEED_AUTO_DUPLEX_FULL:
autoNegoEn = MAD_TRUE;
speedMode = MAD_SPEED_AUTO;
duplexMode = MAD_FULL_DUPLEX;
break;
case SPEED_1000_DUPLEX_FULL:
autoNegoEn = MAD_FALSE;
speedMode = MAD_SPEED_1000M;
duplexMode = MAD_FULL_DUPLEX;
break;
case SPEED_1000_DUPLEX_HALF:
autoNegoEn = MAD_FALSE;
speedMode = MAD_SPEED_1000M;
duplexMode = MAD_HALF_DUPLEX;
break;
case SPEED_AUTO_DUPLEX_HALF:
autoNegoEn = MAD_TRUE;
speedMode = MAD_SPEED_AUTO;
duplexMode = MAD_HALF_DUPLEX;
break;
case SPEED_100_DUPLEX_AUTO:
autoNegoEn = MAD_FALSE;
speedMode = MAD_SPEED_100M;
duplexMode = MAD_FULL_DUPLEX;
break;
case SPEED_10_DUPLEX_AUTO:
autoNegoEn = MAD_TRUE;
speedMode = MAD_SPEED_10M;
duplexMode = MAD_AUTO_DUPLEX;
break;
case SPEED_100_DUPLEX_FULL:
autoNegoEn = MAD_FALSE;
speedMode = MAD_SPEED_100M;
duplexMode = MAD_FULL_DUPLEX;
break;
case SPEED_100_DUPLEX_HALF:
autoNegoEn = MAD_FALSE;
speedMode = MAD_SPEED_100M;
duplexMode = MAD_HALF_DUPLEX;
break;
case SPEED_10_DUPLEX_FULL:
autoNegoEn = MAD_FALSE;
speedMode = MAD_SPEED_10M;
duplexMode = MAD_FULL_DUPLEX;
break;
case SPEED_10_DUPLEX_HALF:
autoNegoEn = MAD_FALSE;
speedMode = MAD_SPEED_10M;
duplexMode = MAD_HALF_DUPLEX;
break;
default:
DBG_INFO(("Unknown Auto Mode (%d)\n",mode));
return GT_BAD_PARAM;
}
*autoEn = autoNegoEn;
if (mdGetAutoNegoMode(autoNegoEn, speedMode, duplexMode, autoMode) != MAD_OK)
return GT_FAIL;
return GT_OK;
}
/*
* This routine sets Auto Mode and Reset the phy
*/
static
GT_STATUS phySetAutoMode
(
IN GT_QD_DEV *dev,
IN GT_U8 hwPort,
IN GT_PHY_INFO *phyInfo,
IN GT_PHY_AUTO_MODE mode
)
{
MAD_STATUS status;
MAD_U32 autoMode;
MAD_BOOL autoEn;
DBG_INFO(("phySetAutoMode Called.\n"));
status = translateAutoMode(phyInfo,mode, &autoEn, &autoMode);
if(status != GT_OK)
{
return status;
}
if(phyInfo->flag & GT_PHY_COPPER)
{
if((mdCopperSetAutoNeg(&(dev->mad_dev),hwPort,autoEn, autoMode)) != MAD_OK)
{
return GT_FAIL;
}
}
else if(phyInfo->flag & GT_PHY_FIBER)
{
if((mdFiberSetAutoNeg(&(dev->mad_dev),hwPort,autoEn, autoMode)) != MAD_OK)
{
return GT_FAIL;
}
}
return GT_OK;
}
/*******************************************************************************
* gprtPhyReset_mad
*
* DESCRIPTION:
* This routine preforms PHY reset.
* After reset, phy will be in Autonegotiation mode.
*
* INPUTS:
* port - The logical port number, unless SERDES device is accessed
* The physical address, if SERDES device is accessed
*
* OUTPUTS:
* None.
*
* RETURNS:
* GT_OK - on success
* GT_FAIL - on error
* COMMENTS:
* data sheet register 0.15 - Reset
* data sheet register 0.13 - Speed
* data sheet register 0.12 - Autonegotiation
* data sheet register 0.8 - Duplex Mode
*******************************************************************************/
GT_STATUS gprtPhyReset_mad
(
IN GT_QD_DEV *dev,
IN GT_LPORT port
)
{
GT_STATUS retVal; /* Functions return value. */
GT_U8 hwPort; /* the physical port number */
GT_PHY_INFO phyInfo;
DBG_INFO(("gprtPhyReset Called.\n"));
/* translate LPORT to hardware port */
hwPort = GT_LPORT_2_PHY(port);
gtSemTake(dev,dev->phyRegsSem,OS_WAIT_FOREVER);
/* check if the port is configurable */
if((phyInfo.phyId=GT_GET_PHY_ID(dev,hwPort)) == GT_INVALID_PHY)
{
gtSemGive(dev,dev->phyRegsSem);
return GT_NOT_SUPPORTED;
}
if(driverFindPhyInformation(dev,hwPort,&phyInfo) != GT_OK)
{
DBG_INFO(("Unknown PHY device.\n"));
gtSemGive(dev,dev->phyRegsSem);
return GT_FAIL;
}
/* set Auto Negotiation AD Register */
retVal = phySetAutoMode(dev,hwPort,&phyInfo,SPEED_AUTO_DUPLEX_AUTO);
if(retVal != GT_OK)
{
DBG_INFO(("Failed.\n"));
}
else
{
DBG_INFO(("OK.\n"));
}
gtSemGive(dev,dev->phyRegsSem);
return retVal;
}
/*******************************************************************************
* gprtSetPortLoopback_mad
*
* DESCRIPTION:
* Enable/Disable Internal Port Loopback.
* For 10/100 Fast Ethernet PHY, speed of Loopback is determined as follows:
* If Auto-Negotiation is enabled, this routine disables Auto-Negotiation and
* forces speed to be 10Mbps.
* If Auto-Negotiation is disabled, the forced speed is used.
* Disabling Loopback simply clears bit 14 of control register(0.14). Therefore,
* it is recommended to call gprtSetPortAutoMode for PHY configuration after
* Loopback test.
* For 10/100/1000 Gigagbit Ethernet PHY, speed of Loopback is determined as follows:
* If Auto-Negotiation is enabled and Link is active, the current speed is used.
* If Auto-Negotiation is disabled, the forced speed is used.
* All other cases, default MAC Interface speed is used. Please refer to the data
* sheet for the information of the default MAC Interface speed.
*
*
* INPUTS:
* port - The logical port number, unless SERDES device is accessed
* The physical address, if SERDES device is accessed
* enable - If GT_TRUE, enable loopback mode
* If GT_FALSE, disable loopback mode
*
* OUTPUTS:
* None.
*
* RETURNS:
* GT_OK - on success
* GT_FAIL - on error
*
* COMMENTS:
* data sheet register 0.14 - Loop_back
*
*******************************************************************************/
GT_STATUS gprtSetPortLoopback_mad
(
IN GT_QD_DEV *dev,
IN GT_LPORT port,
IN GT_BOOL enable
)
{
GT_U8 hwPort; /* the physical port number */
GT_PHY_INFO phyInfo;
MAD_STATUS status;
DBG_INFO(("gprtSetPortLoopback_mad Called.\n"));
/* translate LPORT to hardware port */
hwPort = GT_LPORT_2_PHY(port);
gtSemTake(dev,dev->phyRegsSem,OS_WAIT_FOREVER);
/* check if the port is configurable */
if((phyInfo.phyId=GT_GET_PHY_ID(dev,hwPort)) == GT_INVALID_PHY)
{
gtSemGive(dev,dev->phyRegsSem);
return GT_NOT_SUPPORTED;
}
if(driverFindPhyInformation(dev,hwPort,&phyInfo) != GT_OK)
{
DBG_INFO(("Unknown PHY device.\n"));
gtSemGive(dev,dev->phyRegsSem);
return GT_FAIL;
}
if((status = mdDiagSetLineLoopback(&(dev->mad_dev),port,enable)) != MAD_OK)
{
DBG_INFO(("mdDiagSetLineLoopback failed.\n"));
gtSemGive(dev,dev->phyRegsSem);
return GT_FAIL;
}
gtSemGive(dev,dev->phyRegsSem);
return GT_OK;
}
/*******************************************************************************
* gprtSetPortSpeed_mad
*
* DESCRIPTION:
* Sets speed for a specific logical port. This function will keep the duplex
* mode and loopback mode to the previous value, but disable others, such as
* Autonegotiation.
*
* INPUTS:
* port - The logical port number, unless SERDES device is accessed
* The physical address, if SERDES device is accessed
* speed - port speed.
* PHY_SPEED_10_MBPS for 10Mbps
* PHY_SPEED_100_MBPS for 100Mbps
* PHY_SPEED_1000_MBPS for 1000Mbps
*
* OUTPUTS:
* None.
*
* RETURNS:
* GT_OK - on success
* GT_FAIL - on error
*
* COMMENTS:
* data sheet register 0.13 - Speed Selection (LSB)
* data sheet register 0.6 - Speed Selection (MSB)
*
*******************************************************************************/
GT_STATUS gprtSetPortSpeed_mad
(
IN GT_QD_DEV *dev,
IN GT_LPORT port,
IN GT_PHY_SPEED speed
)
{
GT_U8 hwPort; /* the physical port number */
GT_PHY_INFO phyInfo;
MAD_STATUS status;
MAD_U32 mspeed;
MAD_DUPLEX_MODE mDuplexmod;
DBG_INFO(("gprtSetPortSpeed_mad Called.\n"));
/* translate LPORT to hardware port */
hwPort = GT_LPORT_2_PHY(port);
gtSemTake(dev,dev->phyRegsSem,OS_WAIT_FOREVER);
/* check if the port is configurable */
if((phyInfo.phyId=GT_GET_PHY_ID(dev,hwPort)) == GT_INVALID_PHY)
{
gtSemGive(dev,dev->phyRegsSem);
return GT_NOT_SUPPORTED;
}
if(driverFindPhyInformation(dev,hwPort,&phyInfo) != GT_OK)
{
DBG_INFO(("Unknown PHY device.\n"));
gtSemGive(dev,dev->phyRegsSem);
return GT_FAIL;
}
switch (speed)
{
case PHY_SPEED_10_MBPS:
mspeed = 10;
break;
case PHY_SPEED_100_MBPS:
mspeed = 100;
break;
case PHY_SPEED_1000_MBPS:
default:
mspeed = 1000;
break;
}
if((status = mdGetDuplexStatus(&(dev->mad_dev),port,&mDuplexmod)) != MAD_OK)
{
DBG_INFO(("mdGetDuplexStatus failed.\n"));
gtSemGive(dev,dev->phyRegsSem);
return GT_FAIL;
}
if((status = mdCopperSetSpeedDuplex(&(dev->mad_dev),port,mspeed,((mDuplexmod)?MAD_TRUE:MAD_FALSE))) != MAD_OK)
{
DBG_INFO(("mdCopperSetSpeedDuplex failed.\n"));
gtSemGive(dev,dev->phyRegsSem);
return GT_FAIL;
}
gtSemGive(dev,dev->phyRegsSem);
return GT_OK;
}
/*******************************************************************************
* gprtPortAutoNegEnable_mad
*
* DESCRIPTION:
* Enable/disable an Auto-Negotiation.
* This routine simply sets Auto Negotiation bit (bit 12) of Control
* Register and reset the phy.
* For Speed and Duplex selection, please use gprtSetPortAutoMode.
*
* INPUTS:
* port - The logical port number, unless SERDES device is accessed
* The physical address, if SERDES device is accessed
* state - GT_TRUE for enable Auto-Negotiation,
* GT_FALSE otherwise
*
* OUTPUTS:
* None.
*
* RETURNS:
* GT_OK - on success
* GT_FAIL - on error
*
* COMMENTS:
* data sheet register 0.12 - Auto-Negotiation Enable
* data sheet register 4.8, 4.7, 4.6, 4.5 - Auto-Negotiation Advertisement
*
*******************************************************************************/
GT_STATUS gprtPortAutoNegEnable_mad
(
IN GT_QD_DEV *dev,
IN GT_LPORT port,
IN GT_BOOL state
)
{
GT_U8 hwPort; /* the physical port number */
MAD_STATUS retVal;
MAD_SPEED_MODE speedMode;
MAD_DUPLEX_MODE duplexMode;
MAD_BOOL autoNegoEn;
MAD_U32 autoMode;
DBG_INFO(("gprtPortAutoNegEnable_mad Called.\n"));
/* translate LPORT to hardware port */
hwPort = GT_LPORT_2_PHY(port);
gtSemTake(dev,dev->phyRegsSem,OS_WAIT_FOREVER);
/* check if the port is configurable */
if(!IS_CONFIGURABLE_PHY(dev,hwPort))
{
gtSemGive(dev,dev->phyRegsSem);
return GT_NOT_SUPPORTED;
}
if ((retVal=mdGetSpeedStatus(&(dev->mad_dev), hwPort, &speedMode))!=MAD_OK)
{
DBG_INFO(("mdGetSpeedStatus Failed.\n"));
gtSemGive(dev,dev->phyRegsSem);
return GT_FAIL;
}
if ((retVal=mdGetDuplexStatus(&(dev->mad_dev), hwPort, &duplexMode))!=MAD_OK)
{
DBG_INFO(("mdGetDuplexStatus Failed.\n"));
gtSemGive(dev,dev->phyRegsSem);
return GT_FAIL;
}
autoNegoEn = (state==GT_TRUE)?MAD_TRUE:MAD_FALSE;
if ((mdGetAutoNegoMode(autoNegoEn, speedMode, duplexMode, &autoMode)) != MAD_OK)
{
DBG_INFO(("mdGetAutoNegoMode Failed.\n"));
gtSemGive(dev,dev->phyRegsSem);
return GT_FAIL;
}
if ((retVal=mdCopperSetAutoNeg(&(dev->mad_dev), hwPort, autoNegoEn, autoMode))!=MAD_OK)
{
DBG_INFO(("mdCopperSetAutoNeg Failed.\n"));
gtSemGive(dev,dev->phyRegsSem);
return GT_FAIL;
}
gtSemGive(dev,dev->phyRegsSem);
return retVal;
}
/*******************************************************************************
* gprtPortPowerDown_mad
*
* DESCRIPTION:
* Enable/disable (power down) on specific logical port.
* Phy configuration remains unchanged after Power down.
*
* INPUTS:
* port - The logical port number, unless SERDES device is accessed
* The physical address, if SERDES device is accessed
* state - GT_TRUE: power down
* GT_FALSE: normal operation
*
* OUTPUTS:
* None.
*
* RETURNS:
* GT_OK - on success
* GT_FAIL - on error
*
* COMMENTS:
* data sheet register 0.11 - Power Down
*
*******************************************************************************/
GT_STATUS gprtPortPowerDown_mad
(
IN GT_QD_DEV *dev,
IN GT_LPORT port,
IN GT_BOOL state
)
{
GT_U8 hwPort; /* the physical port number */
MAD_STATUS retVal;
MAD_BOOL pwMode
DBG_INFO(("gprtPortPowerDown_mad Called.\n"));
/* translate LPORT to hardware port */
hwPort = GT_LPORT_2_PHY(port);
gtSemTake(dev,dev->phyRegsSem,OS_WAIT_FOREVER);
/* check if the port is configurable */
if(!IS_CONFIGURABLE_PHY(dev,hwPort))
{
gtSemGive(dev,dev->phyRegsSem);
return GT_NOT_SUPPORTED;
}
if (state==GT_TRUE)
pwMode = MAD_TRUE;
else
pwMode = MAD_FALSE;
if ((retVal=mdSysSetPhyEnable(&(dev->mad_dev), hwPort, pwMode))!=MAD_OK)
{
DBG_INFO(("mdSysSetPhyEnable Failed.\n"));
gtSemGive(dev,dev->phyRegsSem);
return GT_FAIL;
}
gtSemGive(dev,dev->phyRegsSem);
return GT_OK;
}
/*******************************************************************************
* gprtPortRestartAutoNeg_mad
*
* DESCRIPTION:
* Restart AutoNegotiation. If AutoNegotiation is not enabled, it'll enable
* it. Loopback and Power Down will be disabled by this routine.
*
* INPUTS:
* port - The logical port number, unless SERDES device is accessed
* The physical address, if SERDES device is accessed
*
* OUTPUTS:
* None.
*
* RETURNS:
* GT_OK - on success
* GT_FAIL - on error
*
* COMMENTS:
* data sheet register 0.9 - Restart Auto-Negotiation
*
*******************************************************************************/
GT_STATUS gprtPortRestartAutoNeg_mad
(
IN GT_QD_DEV *dev,
IN GT_LPORT port
)
{
GT_STATUS retVal;
GT_U8 hwPort; /* the physical port number */
GT_U16 u16Data;
MAD_U32 u32Data;
DBG_INFO(("gprtPortRestartAutoNeg_mad Called.\n"));
/* translate LPORT to hardware port */
hwPort = GT_LPORT_2_PHY(port);
gtSemTake(dev,dev->phyRegsSem,OS_WAIT_FOREVER);
/* check if the port is configurable */
if(!IS_CONFIGURABLE_PHY(dev,hwPort))
{
gtSemGive(dev,dev->phyRegsSem);
return GT_NOT_SUPPORTED;
}
if((retVal=mdSysGetPhyReg(&(dev->mad_dev),hwPort,QD_PHY_CONTROL_REG,&u32Data)) != MAD_OK)
{
DBG_INFO(("Not able to read Phy Reg(port:%d,offset:%d).\n",hwPort,QD_PHY_CONTROL_REG));
gtSemGive(dev,dev->phyRegsSem);
return GT_FAIL;
}
u16Data = u32Data;
u16Data &= (QD_PHY_DUPLEX | QD_PHY_SPEED);
u16Data |= (QD_PHY_RESTART_AUTONEGO | QD_PHY_AUTONEGO);
DBG_INFO(("Write to phy(%d) register: regAddr 0x%x, data %#x",
hwPort,QD_PHY_CONTROL_REG,u16Data));
/* Write to Phy Control Register. */
if((retVal=madHwPagedSetCtrlPara(&(dev->mad_dev),hwPort,0,u16Data)) != MAD_OK)
{
DBG_INFO(("CallmadHwPagedSetCtrlPara failed.\n"));
gtSemGive(dev,dev->phyRegsSem);
return GT_FAIL;
}
gtSemGive(dev,dev->phyRegsSem);
if(retVal != MAD_OK)
{
DBG_INFO(("Failed.\n"));
return GT_FAIL;
}
else
{
DBG_INFO(("OK.\n"));
}
return GT_OK;
}
/*******************************************************************************
* gprtSetPortDuplexMode_mad
*
* DESCRIPTION:
* Sets duplex mode for a specific logical port. This function will keep
* the speed and loopback mode to the previous value, but disable others,
* such as Autonegotiation.
*
* INPUTS:
* port - The logical port number, unless SERDES device is accessed
* The physical address, if SERDES device is accessed
* dMode - dulpex mode
*
* OUTPUTS:
* None.
*
* RETURNS:
* GT_OK - on success
* GT_FAIL - on error
*
* COMMENTS:
* data sheet register 0.8 - Duplex Mode
*
*******************************************************************************/
GT_STATUS gprtSetPortDuplexMode_mad
(
IN GT_QD_DEV *dev,
IN GT_LPORT port,
IN GT_BOOL dMode
)
{
GT_U8 hwPort; /* the physical port number */
GT_U16 u16Data;
GT_STATUS retVal;
MAD_U32 u32Data;
DBG_INFO(("gprtSetPortDuplexMode_mad Called.\n"));
/* translate LPORT to hardware port */
hwPort = GT_LPORT_2_PHY(port);
gtSemTake(dev,dev->phyRegsSem,OS_WAIT_FOREVER);
/* check if the port is configurable */
if(!IS_CONFIGURABLE_PHY(dev,hwPort))
{
gtSemGive(dev,dev->phyRegsSem);
return GT_NOT_SUPPORTED;
}
if((retVal=mdSysGetPhyReg(&(dev->mad_dev),hwPort,QD_PHY_CONTROL_REG,&u32Data)) != MAD_OK)
{
DBG_INFO(("Not able to read Phy Reg(port:%d,offset:%d).\n",hwPort,QD_PHY_CONTROL_REG));
gtSemGive(dev,dev->phyRegsSem);
return GT_FAIL;
}
u16Data = u32Data;
if(dMode)
{
u16Data = (u16Data & (QD_PHY_LOOPBACK | QD_PHY_SPEED | QD_PHY_SPEED_MSB)) | QD_PHY_DUPLEX;
}
else
{
u16Data = u16Data & (QD_PHY_LOOPBACK | QD_PHY_SPEED | QD_PHY_SPEED_MSB);
}
DBG_INFO(("Write to phy(%d) register: regAddr 0x%x, data %#x",
hwPort,QD_PHY_CONTROL_REG,u16Data));
/* Write to Phy Control Register. */
if((retVal=madHwPagedSetCtrlPara(&(dev->mad_dev),hwPort,0,u16Data)) != MAD_OK)
{
DBG_INFO(("CallmadHwPagedSetCtrlPara failed.\n"));
gtSemGive(dev,dev->phyRegsSem);
return GT_FAIL;
}
gtSemGive(dev,dev->phyRegsSem);
return GT_OK;
}
/*******************************************************************************
* gprtSetPortAutoMode_mad
*
* DESCRIPTION:
* This routine sets up the port with given Auto Mode.
* Supported mode is as follows:
* - Auto for both speed and duplex.
* - Auto for speed only and Full duplex.
* - Auto for speed only and Half duplex.
* - Auto for duplex only and speed 1000Mbps.
* - Auto for duplex only and speed 100Mbps.
* - Auto for duplex only and speed 10Mbps.
* - Speed 1000Mbps and Full duplex.
* - Speed 1000Mbps and Half duplex.
* - Speed 100Mbps and Full duplex.
* - Speed 100Mbps and Half duplex.
* - Speed 10Mbps and Full duplex.
* - Speed 10Mbps and Half duplex.
*
*
* INPUTS:
* port - The logical port number, unless SERDES device is accessed
* The physical address, if SERDES device is accessed
* mode - Auto Mode to be written
*
* OUTPUTS:
* None.
*
* RETURNS:
* GT_OK - on success
* GT_FAIL - on error
* GT_NOT_SUPPORTED - on device without copper
*
* COMMENTS:
* data sheet register 4.8, 4.7, 4.6, and 4.5 Autonegotiation Advertisement
* data sheet register 4.6, 4.5 Autonegotiation Advertisement for 1000BX
* data sheet register 9.9, 9.8 Autonegotiation Advertisement for 1000BT
*******************************************************************************/
GT_STATUS gprtSetPortAutoMode_mad
(
IN GT_QD_DEV *dev,
IN GT_LPORT port,
IN GT_PHY_AUTO_MODE mode
)
{
GT_STATUS retVal; /* Functions return value. */
GT_U8 hwPort; /* the physical port number */
GT_PHY_INFO phyInfo;
DBG_INFO(("gprtSetPortAutoMode_mad Called.\n"));
/* translate LPORT to hardware port */
hwPort = GT_LPORT_2_PHY(port);
retVal = GT_NOT_SUPPORTED;
gtSemTake(dev,dev->phyRegsSem,OS_WAIT_FOREVER);
/* check if the port is configurable */
if((phyInfo.phyId=GT_GET_PHY_ID(dev,hwPort)) == GT_INVALID_PHY)
{
gtSemGive(dev,dev->phyRegsSem);
return GT_NOT_SUPPORTED;
}
if(driverFindPhyInformation(dev,hwPort,&phyInfo) != GT_OK)
{
DBG_INFO(("Unknown PHY device.\n"));
gtSemGive(dev,dev->phyRegsSem);
return GT_FAIL;
}
retVal = phySetAutoMode(dev,hwPort,&phyInfo,mode);
gtSemGive(dev,dev->phyRegsSem);
return retVal;
}
/*******************************************************************************
* gprtSetPause_mad
*
* DESCRIPTION:
* This routine will set the pause bit in Autonegotiation Advertisement
* Register. And restart the autonegotiation.
*
* INPUTS:
* port - The logical port number, unless SERDES device is accessed
* The physical address, if SERDES device is accessed
* state - GT_PHY_PAUSE_MODE enum value.
* GT_PHY_NO_PAUSE - disable pause
* GT_PHY_PAUSE - support pause
* GT_PHY_ASYMMETRIC_PAUSE - support asymmetric pause
* GT_PHY_BOTH_PAUSE - support both pause and asymmetric pause
*
* OUTPUTS:
* None.
*
* RETURNS:
* GT_OK - on success
* GT_FAIL - on error
* COMMENTS:
* data sheet register 4.10 Autonegotiation Advertisement Register
*******************************************************************************/
GT_STATUS gprtSetPause_mad
(
IN GT_QD_DEV *dev,
IN GT_LPORT port,
IN GT_PHY_PAUSE_MODE state
)
{
GT_U8 hwPort; /* the physical port number */
GT_PHY_INFO phyInfo;
MAD_STATUS retVal;
MAD_BOOL autoNegoEn;
MAD_U32 autoMode
DBG_INFO(("phySetPause_mad Called.\n"));
/* translate LPORT to hardware port */
hwPort = GT_LPORT_2_PHY(port);
gtSemTake(dev,dev->phyRegsSem,OS_WAIT_FOREVER);
/* check if the port is configurable */
if((phyInfo.phyId=GT_GET_PHY_ID(dev,hwPort)) == GT_INVALID_PHY)
{
gtSemGive(dev,dev->phyRegsSem);
return GT_NOT_SUPPORTED;
}
if(state & GT_PHY_ASYMMETRIC_PAUSE)
{
if(driverFindPhyInformation(dev,hwPort,&phyInfo) != GT_OK)
{
DBG_INFO(("Unknown PHY device.\n"));
gtSemGive(dev,dev->phyRegsSem);
return GT_FAIL;
}
if (!(phyInfo.flag & GT_PHY_GIGABIT))
{
DBG_INFO(("Not Supported\n"));
gtSemGive(dev,dev->phyRegsSem);
return GT_BAD_PARAM;
}
}
if ((retVal=mdCopperGetAutoNeg(&(dev->mad_dev), hwPort, &autoNegoEn, &autoMode))!=MAD_OK)
{
DBG_INFO(("mdCopperSetAutoNeg Failed.\n"));
gtSemGive(dev,dev->phyRegsSem);
return GT_FAIL;
}
if (state==GT_TRUE)
autoMode |= MAD_AUTO_AD_ASYM_PAUSE;
else
autoMode &= ~MAD_AUTO_AD_ASYM_PAUSE;
if ((retVal=mdCopperSetAutoNeg(&(dev->mad_dev), hwPort, autoNegoEn, autoMode))!=MAD_OK)
{
DBG_INFO(("mdCopperSetAutoNeg Failed.\n"));
gtSemGive(dev,dev->phyRegsSem);
return GT_FAIL;
}
gtSemGive(dev,dev->phyRegsSem);
return retVal;
}
/*******************************************************************************
* gprtSetDTEDetect_mad
*
* DESCRIPTION:
* This routine enables/disables DTE.
*
* INPUTS:
* port - The logical port number
* mode - either GT_TRUE(for enable) or GT_FALSE(for disable)
*
* OUTPUTS:
* None.
*
* RETURNS:
* GT_OK - on success
* GT_FAIL - on error
*
* COMMENTS:
*
*******************************************************************************/
GT_STATUS gprtSetDTEDetect_mad
(
IN GT_QD_DEV *dev,
IN GT_LPORT port,
IN GT_BOOL state
)
{
GT_U8 hwPort; /* the physical port number */
GT_STATUS retVal = GT_OK;
GT_PHY_INFO phyInfo;
MAD_BOOL en;
DBG_INFO(("phySetDTE_mad Called.\n"));
/* translate LPORT to hardware port */
hwPort = GT_LPORT_2_PHY(port);
gtSemTake(dev,dev->phyRegsSem,OS_WAIT_FOREVER);
/* check if the port is configurable */
if((phyInfo.phyId=GT_GET_PHY_ID(dev,hwPort)) == GT_INVALID_PHY)
{
gtSemGive(dev,dev->phyRegsSem);
return GT_NOT_SUPPORTED;
}
/* check if the port supports DTE */
if(driverFindPhyInformation(dev,hwPort,&phyInfo) != GT_OK)
{
DBG_INFO(("Unknown PHY device.\n"));
gtSemGive(dev,dev->phyRegsSem);
return GT_FAIL;
}
if (!(phyInfo.flag & GT_PHY_DTE_CAPABLE))
{
DBG_INFO(("Not Supported\n"));
gtSemGive(dev,dev->phyRegsSem);
return GT_NOT_SUPPORTED;
}
if (state==GT_TRUE)
en = MAD_TRUE;
else
en = MAD_FALSE;
if(mdCopperSetDTEDetectEnable(&(dev->mad_dev),hwPort,en,0) != MAD_OK)
{
DBG_INFO(("Call mdCopperSetDTEDetectEnable failed.\n"));
gtSemGive(dev,dev->phyRegsSem);
return GT_FAIL;
}
gtSemGive(dev,dev->phyRegsSem);
return retVal;
}
/*******************************************************************************
* gprtGetDTEDetectStatus_mad
*
* DESCRIPTION:
* This routine gets DTE status.
*
* INPUTS:
* port - The logical port number
*
* OUTPUTS:
* status - GT_TRUE, if link partner needs DTE power.
* GT_FALSE, otherwise.
*
* RETURNS:
* GT_OK - on success
* GT_FAIL - on error
*
* COMMENTS:
*
*******************************************************************************/
GT_STATUS gprtGetDTEDetectStatus_mad
(
IN GT_QD_DEV *dev,
IN GT_LPORT port,
OUT GT_BOOL *state
)
{
GT_U8 hwPort; /* the physical port number */
GT_STATUS retVal = GT_OK;
GT_PHY_INFO phyInfo;
MAD_BOOL en;
MAD_U16 dropHys;
DBG_INFO(("gprtGetDTEStatus_mad Called.\n"));
/* translate LPORT to hardware port */
hwPort = GT_LPORT_2_PHY(port);
gtSemTake(dev,dev->phyRegsSem,OS_WAIT_FOREVER);
/* check if the port is configurable */
if((phyInfo.phyId=GT_GET_PHY_ID(dev,hwPort)) == GT_INVALID_PHY)
{
gtSemGive(dev,dev->phyRegsSem);
return GT_NOT_SUPPORTED;
}
/* check if the port supports DTE */
if(driverFindPhyInformation(dev,hwPort,&phyInfo) != GT_OK)
{
DBG_INFO(("Unknown PHY device.\n"));
gtSemGive(dev,dev->phyRegsSem);
return GT_FAIL;
}
if (!(phyInfo.flag & GT_PHY_DTE_CAPABLE))
{
DBG_INFO(("Not Supported\n"));
gtSemGive(dev,dev->phyRegsSem);
return GT_NOT_SUPPORTED;
}
if(mdCopperGetDTEDetectEnable(&(dev->mad_dev),hwPort,&en,&dropHys) != MAD_OK)
{
DBG_INFO(("Call mdCopperSetDTEDetectEnable failed.\n"));
gtSemGive(dev,dev->phyRegsSem);
return GT_FAIL;
}
if (en==MAD_TRUE)
*state = GT_TRUE;
else
*state = GT_FALSE;
gtSemGive(dev,dev->phyRegsSem);
return retVal;
}
/*******************************************************************************
* gprtSetDTEDetectDropWait_mad
*
* DESCRIPTION:
* Once the PHY no longer detects that the link partner filter, the PHY
* will wait a period of time before clearing the power over Ethernet
* detection status bit. The wait time is 5 seconds multiplied by the
* given value.
*
* INPUTS:
* port - The logical port number
* waitTime - 0 ~ 15 (unit of 4 sec.)
*
* OUTPUTS:
* None.
*
* RETURNS:
* GT_OK - on success
* GT_FAIL - on error
*
* COMMENTS:
*
*******************************************************************************/
GT_STATUS gprtSetDTEDetectDropWait_mad
(
IN GT_QD_DEV *dev,
IN GT_LPORT port,
IN GT_U16 waitTime
)
{
GT_U8 hwPort; /* the physical port number */
GT_STATUS retVal = GT_OK;
GT_PHY_INFO phyInfo;
MAD_BOOL en;
MAD_U16 dropHys;
DBG_INFO(("gprtSetDTEDropWait_mad Called.\n"));
/* translate LPORT to hardware port */
hwPort = GT_LPORT_2_PHY(port);
gtSemTake(dev,dev->phyRegsSem,OS_WAIT_FOREVER);
/* check if the port is configurable */
if((phyInfo.phyId=GT_GET_PHY_ID(dev,hwPort)) == GT_INVALID_PHY)
{
gtSemGive(dev,dev->phyRegsSem);
return GT_NOT_SUPPORTED;
}
/* check if the port supports DTE */
if(driverFindPhyInformation(dev,hwPort,&phyInfo) != GT_OK)
{
DBG_INFO(("Unknown PHY device.\n"));
gtSemGive(dev,dev->phyRegsSem);
return GT_FAIL;
}
if (!(phyInfo.flag & GT_PHY_DTE_CAPABLE))
{
DBG_INFO(("Not Supported\n"));
gtSemGive(dev,dev->phyRegsSem);
return GT_NOT_SUPPORTED;
}
if(mdCopperGetDTEDetectEnable(&(dev->mad_dev),hwPort,&en,&dropHys) != MAD_OK)
{
DBG_INFO(("Call mdCopperSetDTEDetectEnable failed.\n"));
gtSemGive(dev,dev->phyRegsSem);
return GT_FAIL;
}
dropHys = waitTime;
if(mdCopperSetDTEDetectEnable(&(dev->mad_dev),hwPort,en,dropHys) != MAD_OK)
{
DBG_INFO(("Call mdCopperSetDTEDetectEnable failed.\n"));
gtSemGive(dev,dev->phyRegsSem);
return GT_FAIL;
}
gtSemGive(dev,dev->phyRegsSem);
return retVal;
}
/*******************************************************************************
* gprtGetDTEDetectDropWait_mad
*
* DESCRIPTION:
* Once the PHY no longer detects that the link partner filter, the PHY
* will wait a period of time before clearing the power over Ethernet
* detection status bit. The wait time is 5 seconds multiplied by the
* returned value.
*
* INPUTS:
* port - The logical port number
*
* OUTPUTS:
* waitTime - 0 ~ 15 (unit of 4 sec.)
*
* RETURNS:
* GT_OK - on success
* GT_FAIL - on error
*
* COMMENTS:
*
*******************************************************************************/
GT_STATUS gprtGetDTEDetectDropWait_mad
(
IN GT_QD_DEV *dev,
IN GT_LPORT port,
OUT GT_U16 *waitTime
)
{
GT_U8 hwPort; /* the physical port number */
GT_STATUS retVal = GT_OK;
GT_PHY_INFO phyInfo;
MAD_BOOL en;
MAD_U16 dropHys;
DBG_INFO(("gprtSetDTEDropWait_mad Called.\n"));
/* translate LPORT to hardware port */
hwPort = GT_LPORT_2_PHY(port);
gtSemTake(dev,dev->phyRegsSem,OS_WAIT_FOREVER);
/* check if the port is configurable */
if((phyInfo.phyId=GT_GET_PHY_ID(dev,hwPort)) == GT_INVALID_PHY)
{
gtSemGive(dev,dev->phyRegsSem);
return GT_NOT_SUPPORTED;
}
if(driverFindPhyInformation(dev,hwPort,&phyInfo) != GT_OK)
{
DBG_INFO(("Unknown PHY device.\n"));
gtSemGive(dev,dev->phyRegsSem);
return GT_FAIL;
}
if (!(phyInfo.flag & GT_PHY_DTE_CAPABLE))
{
DBG_INFO(("Not Supported\n"));
gtSemGive(dev,dev->phyRegsSem);
return GT_NOT_SUPPORTED;
}
if(mdCopperGetDTEDetectEnable(&(dev->mad_dev),hwPort,&en,&dropHys) != MAD_OK)
{
DBG_INFO(("Call mdCopperSetDTEDetectEnable failed.\n"));
gtSemGive(dev,dev->phyRegsSem);
return GT_FAIL;
}
*waitTime = dropHys;
gtSemGive(dev,dev->phyRegsSem);
return retVal;
}
/*******************************************************************************
* gprtSetEnergyDetect_mad
*
* DESCRIPTION:
* Energy Detect power down mode enables or disables the PHY to wake up on
* its own by detecting activity on the CAT 5 cable.
*
* INPUTS:
* port - The logical port number
* mode - GT_EDETECT_MODE type
*
* OUTPUTS:
* None.
*
* RETURNS:
* GT_OK - on success
* GT_FAIL - on error
* GT_BAD_PARAM - if invalid parameter is given
* GT_NOT_SUPPORTED - if current device does not support this feature.
*
* COMMENTS:
*
*******************************************************************************/
GT_STATUS gprtSetEnergyDetect_mad
(
IN GT_QD_DEV *dev,
IN GT_LPORT port,
IN GT_EDETECT_MODE mode
)
{
GT_U8 hwPort; /* the physical port number */
GT_U16 u16Data;
GT_STATUS retVal = GT_OK;
GT_PHY_INFO phyInfo;
DBG_INFO(("gprtSetEnergyDetect_mad Called.\n"));
/* translate LPORT to hardware port */
hwPort = GT_LPORT_2_PHY(port);
gtSemTake(dev,dev->phyRegsSem,OS_WAIT_FOREVER);
/* check if the port is configurable */
if((phyInfo.phyId=GT_GET_PHY_ID(dev,hwPort)) == GT_INVALID_PHY)
{
gtSemGive(dev,dev->phyRegsSem);
return GT_NOT_SUPPORTED;
}
if(driverFindPhyInformation(dev,hwPort,&phyInfo) != GT_OK)
{
DBG_INFO(("Unknown PHY device.\n"));
gtSemGive(dev,dev->phyRegsSem);
return GT_FAIL;
}
if (phyInfo.flag & GT_PHY_SERDES_CORE)
{
DBG_INFO(("Not Supported.\n"));
gtSemGive(dev,dev->phyRegsSem);
return GT_NOT_SUPPORTED;
}
else if (phyInfo.flag & GT_PHY_GIGABIT)
{
/* check if the mode is valid */
switch (mode)
{
case GT_EDETECT_OFF:
u16Data = 0;
break;
case GT_EDETECT_SENSE_PULSE:
u16Data = 3;
break;
case GT_EDETECT_SENSE:
u16Data = 2;
break;
default:
DBG_INFO(("Invalid paramerter.\n"));
gtSemGive(dev,dev->phyRegsSem);
return GT_BAD_PARAM;
}
}
else /* it's a Fast Ethernet device */
{
/* check if the mode is valid */
switch (mode)
{
case GT_EDETECT_OFF:
u16Data = 0;
break;
case GT_EDETECT_SENSE_PULSE:
u16Data = 1;
break;
case GT_EDETECT_SENSE:
default:
DBG_INFO(("Invalid paramerter.\n"));
gtSemGive(dev,dev->phyRegsSem);
return GT_BAD_PARAM;
}
}
if(mdSysSetDetectPowerDownMode(&(dev->mad_dev),hwPort,u16Data) != MAD_OK)
{
DBG_INFO(("Call mdSysSetDetectPowerDownMode failed.\n"));
gtSemGive(dev,dev->phyRegsSem);
return GT_FAIL;
}
gtSemGive(dev,dev->phyRegsSem);
return retVal;
}
/*******************************************************************************
* gprtGetEnergyDetect_mad
*
* DESCRIPTION:
* Energy Detect power down mode enables or disables the PHY to wake up on
* its own by detecting activity on the CAT 5 cable.
*
* INPUTS:
* port - The logical port number
*
* OUTPUTS:
* mode - GT_EDETECT_MODE type
*
* RETURNS:
* GT_OK - on success
* GT_FAIL - on error
* GT_NOT_SUPPORTED - if current device does not support this feature.
*
* COMMENTS:
*
*******************************************************************************/
GT_STATUS gprtGetEnergyDetect_mad
(
IN GT_QD_DEV *dev,
IN GT_LPORT port,
OUT GT_EDETECT_MODE *mode
)
{
GT_U8 hwPort; /* the physical port number */
GT_U16 u16Data;
GT_STATUS retVal = GT_OK;
GT_PHY_INFO phyInfo;
DBG_INFO(("gprtGetEnergyDetect_mad Called.\n"));
/* translate LPORT to hardware port */
hwPort = GT_LPORT_2_PHY(port);
gtSemTake(dev,dev->phyRegsSem,OS_WAIT_FOREVER);
/* check if the port is configurable */
if((phyInfo.phyId=GT_GET_PHY_ID(dev,hwPort)) == GT_INVALID_PHY)
{
gtSemGive(dev,dev->phyRegsSem);
return GT_NOT_SUPPORTED;
}
if(driverFindPhyInformation(dev,hwPort,&phyInfo) != GT_OK)
{
DBG_INFO(("Unknown PHY device.\n"));
gtSemGive(dev,dev->phyRegsSem);
return GT_FAIL;
}
if(mdSysGetDetectPowerDownMode(&(dev->mad_dev),hwPort,&u16Data) != MAD_OK)
{
DBG_INFO(("Call mdSysSetDetectPowerDownMode failed.\n"));
gtSemGive(dev,dev->phyRegsSem);
return GT_FAIL;
}
if (phyInfo.flag & GT_PHY_SERDES_CORE)
{
DBG_INFO(("Not Supported.\n"));
gtSemGive(dev,dev->phyRegsSem);
return GT_NOT_SUPPORTED;
}
else if (phyInfo.flag & GT_PHY_GIGABIT)
{
/* read the mode */
switch (u16Data)
{
case 0:
case 1:
*mode = GT_EDETECT_OFF;
break;
case 2:
*mode = GT_EDETECT_SENSE;
break;
case 3:
*mode = GT_EDETECT_SENSE_PULSE;
break;
default:
DBG_INFO(("Unknown value (should not happen).\n"));
gtSemGive(dev,dev->phyRegsSem);
return GT_FAIL;
}
}
else /* it's a Fast Ethernet device */
{
switch (u16Data)
{
case 0:
*mode = GT_EDETECT_OFF;
break;
case 1:
*mode = GT_EDETECT_SENSE_PULSE;
break;
default:
DBG_INFO(("Unknown value (shouldn not happen).\n"));
gtSemGive(dev,dev->phyRegsSem);
return GT_FAIL;
}
}
gtSemGive(dev,dev->phyRegsSem);
return retVal;
}
/*******************************************************************************
* gprtSet1000TMasterMode_mad
*
* DESCRIPTION:
* This routine sets the ports 1000Base-T Master mode and restart the Auto
* negotiation.
*
* INPUTS:
* port - the logical port number.
* mode - GT_1000T_MASTER_SLAVE structure
* autoConfig - GT_TRUE for auto, GT_FALSE for manual setup.
* masterPrefer - GT_TRUE if Master configuration is preferred.
*
* OUTPUTS:
* None.
*
* RETURNS:
* GT_OK - on success
* GT_FAIL - on error
*
* COMMENTS:
*
*
* GalTis:
*
*******************************************************************************/
GT_STATUS gprtSet1000TMasterMode_mad
(
IN GT_QD_DEV *dev,
IN GT_LPORT port,
IN GT_1000T_MASTER_SLAVE *mode
)
{
GT_U8 hwPort; /* the physical port number */
GT_PHY_INFO phyInfo;
MAD_1000T_MASTER_SLAVE msmode
DBG_INFO(("gprtSet1000TMasterMode_mad Called.\n"));
/* translate LPORT to hardware port */
hwPort = GT_LPORT_2_PHY(port);
if (!IS_IN_DEV_GROUP(dev,DEV_GIGABIT_SWITCH))
{
return GT_NOT_SUPPORTED;
}
gtSemTake(dev,dev->phyRegsSem,OS_WAIT_FOREVER);
/* check if the port is configurable */
if((phyInfo.phyId=GT_GET_PHY_ID(dev,hwPort)) == GT_INVALID_PHY)
{
gtSemGive(dev,dev->phyRegsSem);
return GT_NOT_SUPPORTED;
}
if(driverFindPhyInformation(dev,hwPort,&phyInfo) != GT_OK)
{
DBG_INFO(("Unknown PHY device.\n"));
gtSemGive(dev,dev->phyRegsSem);
return GT_FAIL;
}
if (!(phyInfo.flag & GT_PHY_GIGABIT) || !(phyInfo.flag & GT_PHY_COPPER))
{
DBG_INFO(("Not Supported\n"));
gtSemGive(dev,dev->phyRegsSem);
return GT_NOT_SUPPORTED;
}
msmode.autoConfig = mode->autoConfig;
msmode.masterPrefer = mode->masterPrefer;
if(mdCopperSet1000TMasterMode(&(dev->mad_dev),hwPort,&msmode) != MAD_OK)
{
DBG_INFO(("Call mdSysSetDetectPowerDownMode failed.\n"));
gtSemGive(dev,dev->phyRegsSem);
return GT_FAIL;
}
gtSemGive(dev,dev->phyRegsSem);
return GT_OK;
}
/*******************************************************************************
* gprtGet1000TMasterMode_mad
*
* DESCRIPTION:
* This routine retrieves 1000Base-T Master Mode
*
* INPUTS:
* port - the logical port number.
*
* OUTPUTS:
* mode - GT_1000T_MASTER_SLAVE structure
* autoConfig - GT_TRUE for auto, GT_FALSE for manual setup.
* masterPrefer - GT_TRUE if Master configuration is preferred.
*
* RETURNS:
* GT_OK - on success
* GT_FAIL - on error
*
* COMMENTS:
*
*
* GalTis:
*
*******************************************************************************/
GT_STATUS gprtGet1000TMasterMode_mad
(
IN GT_QD_DEV *dev,
IN GT_LPORT port,
OUT GT_1000T_MASTER_SLAVE *mode
)
{
GT_U8 hwPort; /* the physical port number */
GT_PHY_INFO phyInfo;
MAD_1000T_MASTER_SLAVE msmode
DBG_INFO(("gprtGet1000TMasterMode_mad Called.\n"));
/* translate LPORT to hardware port */
hwPort = GT_LPORT_2_PHY(port);
if (!IS_IN_DEV_GROUP(dev,DEV_GIGABIT_SWITCH))
{
return GT_NOT_SUPPORTED;
}
gtSemTake(dev,dev->phyRegsSem,OS_WAIT_FOREVER);
/* check if the port is configurable */
if((phyInfo.phyId=GT_GET_PHY_ID(dev,hwPort)) == GT_INVALID_PHY)
{
gtSemGive(dev,dev->phyRegsSem);
return GT_NOT_SUPPORTED;
}
if(driverFindPhyInformation(dev,hwPort,&phyInfo) != GT_OK)
{
DBG_INFO(("Unknown PHY device.\n"));
gtSemGive(dev,dev->phyRegsSem);
return GT_FAIL;
}
if (!(phyInfo.flag & GT_PHY_GIGABIT) || !(phyInfo.flag & GT_PHY_COPPER))
{
DBG_INFO(("Not Supported\n"));
gtSemGive(dev,dev->phyRegsSem);
return GT_NOT_SUPPORTED;
}
if(mdCopperGet1000TMasterMode(&(dev->mad_dev),hwPort,&msmode) != MAD_OK)
{
DBG_INFO(("Call mdCopperGet1000TMasterMode failed.\n"));
gtSemGive(dev,dev->phyRegsSem);
return GT_FAIL;
}
mode->autoConfig = msmode.autoConfig;
mode->masterPrefer = msmode.masterPrefer;
gtSemGive(dev,dev->phyRegsSem);
return GT_OK;
}
/*******************************************************************************
* gprtGetPhyLinkStatus_mad
*
* DESCRIPTION:
* This routine retrieves the Link status.
*
* INPUTS:
* port - The logical port number, unless SERDES device is accessed
* The physical address, if SERDES device is accessed
*
* OUTPUTS:
* linkStatus - GT_FALSE if link is not established,
* GT_TRUE if link is established.
*
* RETURNS:
* GT_OK - on success
* GT_FAIL - on error
*
*
* COMMENTS:
*
*******************************************************************************/
GT_STATUS gprtGetPhyLinkStatus_mad
(
IN GT_QD_DEV *dev,
IN GT_LPORT port,
IN GT_BOOL *linkStatus
)
{
GT_U8 hwPort; /* the physical port number */
GT_PHY_INFO phyInfo;
OUT MAD_BOOL linkOn;
DBG_INFO(("gprtGetPhyLinkStatus_mad Called.\n"));
/* translate LPORT to hardware port */
hwPort = GT_LPORT_2_PHY(port);
gtSemTake(dev,dev->phyRegsSem,OS_WAIT_FOREVER);
/* check if the port is configurable */
if((phyInfo.phyId=GT_GET_PHY_ID(dev,hwPort)) == GT_INVALID_PHY)
{
gtSemGive(dev,dev->phyRegsSem);
return GT_NOT_SUPPORTED;
}
if(mdCopperGetLinkStatus(&(dev->mad_dev),hwPort,&linkOn) != MAD_OK)
{
DBG_INFO(("Call mdCopperGetLinkStatus failed.\n"));
gtSemGive(dev,dev->phyRegsSem);
return GT_FAIL;
}
*linkStatus = (linkOn==MAD_TRUE)?GT_TRUE:GT_FAIL;
gtSemGive(dev,dev->phyRegsSem);
return GT_OK;
}
/*******************************************************************************
* gprtSetPktGenEnable_mad
*
* DESCRIPTION:
* This routine enables or disables Packet Generator.
* Link should be established first prior to enabling the packet generator,
* and generator will generate packets at the speed of the established link.
* When enables packet generator, the following information should be
* provided:
* Payload Type: either Random or 5AA55AA5
* Packet Length: either 64 or 1514 bytes
* Error Packet: either Error packet or normal packet
*
* INPUTS:
* port - The logical port number, unless SERDES device is accessed
* The physical address, if SERDES device is accessed
* en - GT_TRUE to enable, GT_FALSE to disable
* pktInfo - packet information(GT_PG structure pointer), if en is GT_TRUE.
* ignored, if en is GT_FALSE
*
* OUTPUTS:
* None.
*
* RETURNS:
* GT_OK - on success
* GT_FAIL - on error
*
*
* COMMENTS:
*
*******************************************************************************/
GT_STATUS gprtSetPktGenEnable_mad
(
IN GT_QD_DEV *dev,
IN GT_LPORT port,
IN GT_BOOL en,
IN GT_PG *pktInfo
)
{
GT_U8 hwPort; /* the physical port number */
GT_PHY_INFO phyInfo;
MAD_U32 men;
MAD_PG mpktInfo;
DBG_INFO(("gprtSetPktGenEnable_mad Called.\n"));
/* translate LPORT to hardware port */
hwPort = GT_LPORT_2_PHY(port);
gtSemTake(dev,dev->phyRegsSem,OS_WAIT_FOREVER);
/* check if the port is configurable */
if((phyInfo.phyId=GT_GET_PHY_ID(dev,hwPort)) == GT_INVALID_PHY)
{
gtSemGive(dev,dev->phyRegsSem);
return GT_NOT_SUPPORTED;
}
if(driverFindPhyInformation(dev,hwPort,&phyInfo) != GT_OK)
{
DBG_INFO(("Unknown PHY device.\n"));
gtSemGive(dev,dev->phyRegsSem);
return GT_FAIL;
}
if(!(phyInfo.flag & GT_PHY_PKT_GENERATOR))
{
DBG_INFO(("Not Supported.\n"));
gtSemGive(dev,dev->phyRegsSem);
return GT_NOT_SUPPORTED;
}
mpktInfo.payload = pktInfo->payload;
mpktInfo.length = pktInfo->length;
mpktInfo.tx = pktInfo->tx;
if (en==GT_TRUE)
{
men =1;
mpktInfo.en_type = MAD_PG_EN_COPPER;
}
else
{
men =0;
mpktInfo.en_type = MAD_PG_DISABLE;
}
if(mdDiagSetPktGenEnable(&(dev->mad_dev),hwPort, men, &mpktInfo) != MAD_OK)
{
DBG_INFO(("Call mdSysSetDetectPowerDownMode failed.\n"));
gtSemGive(dev,dev->phyRegsSem);
return GT_FAIL;
}
gtSemGive(dev,dev->phyRegsSem);
return GT_OK;
}
/*******************************************************************************
* gprtGetSerdesMode_mad
*
* DESCRIPTION:
* This routine reads Serdes Interface Mode.
*
* INPUTS:
* port - The physical SERDES device address
* (logical port number is also supported for backward comparibility)
*
* OUTPUTS:
* mode - Serdes Interface Mode
*
* RETURNS:
* GT_OK - on success
* GT_FAIL - on error
*
* COMMENTS:
* logical port number is supported only for the devices made production
* before 2009. (88E6131, 88E6122, 88E6108, 88E6161, and 88E6165)
*
*******************************************************************************/
GT_STATUS gprtGetSerdesMode_mad
(
IN GT_QD_DEV *dev,
IN GT_LPORT port,
IN GT_SERDES_MODE *mode
)
{
GT_U16 u16Data; /* The register's read data. */
GT_U8 hwPort; /* the physical port number */
DBG_INFO(("gprtGetSerdesMode_mad Called.\n"));
if(!IS_IN_DEV_GROUP(dev,DEV_SERDES_CORE))
{
return GT_NOT_SUPPORTED;
}
/* check if input is logical port number */
hwPort = GT_LPORT_2_PORT(port);
GT_GET_SERDES_PORT(dev,&hwPort);
if(hwPort > dev->maxPhyNum)
{
/* check if input is physical serdes address */
if(dev->validSerdesVec & (1<<port))
{
hwPort = (GT_U8)port;
}
else
return GT_NOT_SUPPORTED;
}
gtSemTake(dev,dev->phyRegsSem,OS_WAIT_FOREVER);
/* Get Phy Register. */
if(hwGetPhyRegField(dev,hwPort,16,0,2,&u16Data) != GT_OK)
{
DBG_INFO(("Failed.\n"));
gtSemGive(dev,dev->phyRegsSem);
return GT_FAIL;
}
*mode = u16Data;
gtSemGive(dev,dev->phyRegsSem);
return GT_OK;
}
/*******************************************************************************
* gprtSetSerdesMode_mad
*
* DESCRIPTION:
* This routine sets Serdes Interface Mode.
*
* INPUTS:
* port - The physical SERDES device address
* (logical port number is also supported for backward comparibility)
* mode - Serdes Interface Mode
*
* OUTPUTS:
* None.
*
* RETURNS:
* GT_OK - on success
* GT_FAIL - on error
*
* COMMENTS:
* logical port number is supported only for the devices made production
* before 2009. (88E6131, 88E6122, 88E6108, 88E6161, and 88E6165)
*
*******************************************************************************/
GT_STATUS gprtSetSerdesMode_mad
(
IN GT_QD_DEV *dev,
IN GT_LPORT port,
IN GT_SERDES_MODE mode
)
{
GT_U16 u16Data; /* The register's read data. */
GT_U8 hwPort; /* the physical port number */
GT_STATUS retVal;
DBG_INFO(("gprtSetSerdesMode_mad Called.\n"));
if(!IS_IN_DEV_GROUP(dev,DEV_SERDES_CORE))
{
return GT_NOT_SUPPORTED;
}
/* check if input is logical port number */
hwPort = GT_LPORT_2_PORT(port);
GT_GET_SERDES_PORT(dev,&hwPort);
if(hwPort > dev->maxPhyNum)
{
/* check if input is physical serdes address */
if(dev->validSerdesVec & (1<<port))
{
hwPort = (GT_U8)port;
}
else
return GT_NOT_SUPPORTED;
}
gtSemTake(dev,dev->phyRegsSem,OS_WAIT_FOREVER);
u16Data = mode;
/* Get Phy Register. */
if(hwSetPhyRegField(dev,hwPort,16,0,2,u16Data) != GT_OK)
{
DBG_INFO(("Failed.\n"));
gtSemGive(dev,dev->phyRegsSem);
return GT_FAIL;
}
retVal = hwPhyReset(dev,hwPort,0xFF);
gtSemGive(dev,dev->phyRegsSem);
return retVal;
}
/*******************************************************************************
* gprtGetPhyReg_mad
*
* DESCRIPTION:
* This routine reads Phy Registers.
*
* INPUTS:
* port - The logical port number, unless SERDES device is accessed
* The physical address, if SERDES device is accessed
* regAddr - The register's address.
*
* OUTPUTS:
* data - The read register's data.
*
* RETURNS:
* GT_OK - on success
* GT_FAIL - on error
*
* COMMENTS:
* None.
*
* GalTis:
*
*******************************************************************************/
GT_STATUS gprtGetPhyReg_mad
(
IN GT_QD_DEV *dev,
IN GT_LPORT port,
IN GT_U32 regAddr,
OUT GT_U16 *data
)
{
MAD_U32 u32Data; /* The register's read data. */
GT_U8 hwPort; /* the physical port number */
DBG_INFO(("gprtGetPhyReg_mad Called.\n"));
hwPort = GT_LPORT_2_PHY(port);
/* hwPort = port; */
gtSemTake(dev,dev->phyRegsSem,OS_WAIT_FOREVER);
/* Get Phy Register. */
if(mdSysGetPhyReg(&(dev->mad_dev),hwPort,regAddr,&u32Data) != MAD_OK)
{
DBG_INFO(("Failed.\n"));
gtSemGive(dev,dev->phyRegsSem);
return GT_FAIL;
}
*data = u32Data;
gtSemGive(dev,dev->phyRegsSem);
return GT_OK;
}
/*******************************************************************************
* gprtSetPhyReg_mad
*
* DESCRIPTION:
* This routine writes Phy Registers.
*
* INPUTS:
* port - The logical port number, unless SERDES device is accessed
* The physical address, if SERDES device is accessed
* regAddr - The register's address.
*
* OUTPUTS:
* data - The read register's data.
*
* RETURNS:
* GT_OK - on success
* GT_FAIL - on error
*
* COMMENTS:
* None.
*
* GalTis:
*
*******************************************************************************/
GT_STATUS gprtSetPhyReg_mad
(
IN GT_QD_DEV *dev,
IN GT_LPORT port,
IN GT_U32 regAddr,
IN GT_U16 inData
)
{
GT_U8 hwPort; /* the physical port number */
MAD_U32 data = inData;
DBG_INFO(("gprtSetPhyReg_mad Called.\n"));
hwPort = GT_LPORT_2_PHY(port);
/* hwPort = port; */
gtSemTake(dev,dev->phyRegsSem,OS_WAIT_FOREVER);
/* Write to Phy Register */
if(mdSysSetPhyReg(&(dev->mad_dev),hwPort,regAddr,data) != MAD_OK)
{
DBG_INFO(("Failed.\n"));
gtSemGive(dev,dev->phyRegsSem);
return GT_FAIL;
}
gtSemGive(dev,dev->phyRegsSem);
return GT_OK;
}
/*******************************************************************************
* gprtGetPagedPhyReg_mad
*
* DESCRIPTION:
* This routine reads phy register of the given page
*
* INPUTS:
* port - logical port to be read
* regAddr - register offset to be read
* page - page number to be read
*
* OUTPUTS:
* data - value of the read register
*
* RETURNS:
* GT_OK - if read successed
* GT_FAIL - if read failed
*
* COMMENTS:
* None.
*
*******************************************************************************/
GT_STATUS gprtGetPagedPhyReg_mad
(
IN GT_QD_DEV *dev,
IN GT_U32 port,
IN GT_U32 regAddr,
IN GT_U32 page,
OUT GT_U16* data
)
{
GT_PHY_INFO phyInfo;
GT_U8 hwPort;
MAD_U32 u32Data;
hwPort = GT_LPORT_2_PHY(port);
gtSemTake(dev,dev->phyRegsSem,OS_WAIT_FOREVER);
/* check if the port is configurable */
if((phyInfo.phyId=GT_GET_PHY_ID(dev,hwPort)) == GT_INVALID_PHY)
{
gtSemGive(dev,dev->phyRegsSem);
return GT_NOT_SUPPORTED;
}
if(driverFindPhyInformation(dev,hwPort,&phyInfo) != GT_OK)
{
DBG_INFO(("Unknown PHY device.\n"));
gtSemGive(dev,dev->phyRegsSem);
return GT_FAIL;
}
if(mdSysGetPagedPhyReg(&(dev->mad_dev),hwPort,page, regAddr,&u32Data) != MAD_OK)
{
DBG_INFO(("Failed.\n"));
gtSemGive(dev,dev->phyRegsSem);
return GT_FAIL;
}
*data = u32Data;
gtSemGive(dev,dev->phyRegsSem);
return GT_OK;
}
/*******************************************************************************
* gprtSetPagedPhyReg_mad
*
* DESCRIPTION:
* This routine writes a value to phy register of the given page
*
* INPUTS:
* port - logical port to be read
* regAddr - register offset to be read
* page - page number to be read
* data - value of the read register
*
* OUTPUTS:
* None
*
* RETURNS:
* GT_OK - if read successed
* GT_FAIL - if read failed
*
* COMMENTS:
* None.
*
*******************************************************************************/
GT_STATUS gprtSetPagedPhyReg_mad
(
IN GT_QD_DEV *dev,
IN GT_U32 port,
IN GT_U32 regAddr,
IN GT_U32 page,
IN GT_U16 inData
)
{
GT_PHY_INFO phyInfo;
GT_U8 hwPort;
MAD_U32 data = inData;
hwPort = GT_LPORT_2_PHY(port);
gtSemTake(dev,dev->phyRegsSem,OS_WAIT_FOREVER);
/* check if the port is configurable */
if((phyInfo.phyId=GT_GET_PHY_ID(dev,hwPort)) == GT_INVALID_PHY)
{
gtSemGive(dev,dev->phyRegsSem);
return GT_NOT_SUPPORTED;
}
if(driverFindPhyInformation(dev,hwPort,&phyInfo) != GT_OK)
{
DBG_INFO(("Unknown PHY device.\n"));
gtSemGive(dev,dev->phyRegsSem);
return GT_FAIL;
}
if(mdSysSetPagedPhyReg(&(dev->mad_dev),hwPort,page, regAddr, data) != MAD_OK)
{
DBG_INFO(("Failed.\n"));
gtSemGive(dev,dev->phyRegsSem);
return GT_FAIL;
}
gtSemGive(dev,dev->phyRegsSem);
return GT_OK;
}