| #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 <gtMad.h> |
| #endif |
| |
| #ifdef GT_USE_MAD |
| #include "gtPhyCtrl_mad.c" |
| #endif |
| /* |
| * This routine set Auto-Negotiation Ad Register for Fast Ethernet Phy |
| */ |
| static |
| GT_STATUS feSetAutoMode |
| ( |
| IN GT_QD_DEV *dev, |
| IN GT_U8 hwPort, |
| IN GT_PHY_INFO *phyInfo, |
| IN GT_PHY_AUTO_MODE mode |
| ) |
| { |
| GT_U16 u16Data; |
| |
| GT_UNUSED_PARAM(phyInfo); |
| |
| DBG_INFO(("feSetAutoMode Called.\n")); |
| |
| if(hwReadPhyReg(dev,hwPort,QD_PHY_AUTONEGO_AD_REG,&u16Data) != GT_OK) |
| { |
| DBG_INFO(("Not able to read Phy Reg(port:%d,offset:%d).\n",hwPort,QD_PHY_AUTONEGO_AD_REG)); |
| return GT_FAIL; |
| } |
| |
| /* Mask out all auto mode related bits. */ |
| u16Data &= ~QD_PHY_MODE_AUTO_AUTO; |
| |
| switch(mode) |
| { |
| case SPEED_AUTO_DUPLEX_AUTO: |
| u16Data |= QD_PHY_MODE_AUTO_AUTO; |
| break; |
| case SPEED_100_DUPLEX_AUTO: |
| u16Data |= QD_PHY_MODE_100_AUTO; |
| break; |
| case SPEED_10_DUPLEX_AUTO: |
| u16Data |= QD_PHY_MODE_10_AUTO; |
| break; |
| case SPEED_AUTO_DUPLEX_FULL: |
| u16Data |= QD_PHY_MODE_AUTO_FULL; |
| break; |
| case SPEED_AUTO_DUPLEX_HALF: |
| u16Data |= QD_PHY_MODE_AUTO_HALF; |
| break; |
| case SPEED_100_DUPLEX_FULL: |
| u16Data |= QD_PHY_100_FULL; |
| break; |
| case SPEED_100_DUPLEX_HALF: |
| u16Data |= QD_PHY_100_HALF; |
| break; |
| case SPEED_10_DUPLEX_FULL: |
| u16Data |= QD_PHY_10_FULL; |
| break; |
| case SPEED_10_DUPLEX_HALF: |
| u16Data |= QD_PHY_10_HALF; |
| break; |
| default: |
| DBG_INFO(("Unknown Auto Mode (%d)\n",mode)); |
| return GT_BAD_PARAM; |
| } |
| |
| /* Write to Phy AutoNegotiation Advertisement Register. */ |
| if(hwWritePhyReg(dev,hwPort,QD_PHY_AUTONEGO_AD_REG,u16Data) != GT_OK) |
| { |
| DBG_INFO(("Not able to write Phy Reg(port:%d,offset:%d,data:%#x).\n",hwPort,QD_PHY_AUTONEGO_AD_REG,u16Data)); |
| return GT_FAIL; |
| } |
| |
| return GT_OK; |
| } |
| |
| /* |
| * This routine get Auto-Negotiation Ad Register for Fast Ethernet Phy |
| */ |
| static |
| GT_STATUS feGetAutoMode |
| ( |
| IN GT_QD_DEV *dev, |
| IN GT_U8 hwPort, |
| IN GT_PHY_INFO *phyInfo, |
| OUT GT_PHY_AUTO_MODE *mode |
| ) |
| { |
| GT_U16 u16Data; |
| |
| GT_UNUSED_PARAM(phyInfo); |
| |
| DBG_INFO(("feGetAutoMode Called.\n")); |
| |
| if(hwReadPhyReg(dev,hwPort,QD_PHY_AUTONEGO_AD_REG,&u16Data) != GT_OK) |
| { |
| DBG_INFO(("Not able to read Phy Reg(port:%d,offset:%d).\n",hwPort,QD_PHY_AUTONEGO_AD_REG)); |
| return GT_FAIL; |
| } |
| |
| /* Pick out all auto mode related bits. */ |
| u16Data &= QD_PHY_MODE_AUTO_AUTO; |
| |
| switch(u16Data) |
| { |
| case QD_PHY_MODE_10_HALF: |
| *mode = SPEED_10_DUPLEX_HALF; |
| break; |
| case QD_PHY_MODE_10_FULL: |
| *mode = SPEED_10_DUPLEX_FULL; |
| break; |
| case QD_PHY_MODE_100_HALF: |
| *mode = SPEED_100_DUPLEX_HALF; |
| break; |
| case QD_PHY_MODE_100_FULL: |
| *mode = SPEED_100_DUPLEX_FULL; |
| break; |
| case QD_PHY_MODE_AUTO_HALF: |
| *mode = SPEED_AUTO_DUPLEX_HALF; |
| break; |
| case QD_PHY_MODE_AUTO_FULL: |
| *mode = SPEED_AUTO_DUPLEX_FULL; |
| break; |
| case QD_PHY_MODE_10_AUTO: |
| *mode = SPEED_10_DUPLEX_AUTO; |
| break; |
| case QD_PHY_MODE_100_AUTO: |
| *mode = SPEED_100_DUPLEX_AUTO; |
| break; |
| case QD_PHY_MODE_AUTO_AUTO: |
| *mode = SPEED_AUTO_DUPLEX_AUTO; |
| break; |
| default: |
| DBG_INFO(("Unknown Auto Mode (%d)\n", u16Data)); |
| *mode = SPEED_AUTO_DUPLEX_AUTO; |
| break; |
| } |
| |
| return GT_OK; |
| } |
| |
| /* |
| * This routine set Auto-Negotiation Advertisement Register for Copper |
| */ |
| static |
| GT_STATUS gigCopperSetAutoMode |
| ( |
| IN GT_QD_DEV *dev, |
| IN GT_U8 hwPort, |
| IN GT_PHY_INFO *phyInfo, |
| IN GT_PHY_AUTO_MODE mode |
| ) |
| { |
| GT_U16 u16Data,u16Data1; |
| |
| DBG_INFO(("gigCopperSetAutoMode Called.\n")); |
| |
| if(hwReadPagedPhyReg(dev,hwPort,0,QD_PHY_AUTONEGO_AD_REG,phyInfo->anyPage,&u16Data) != GT_OK) |
| { |
| DBG_INFO(("Not able to read Phy Reg(port:%d,offset:%d).\n",hwPort,QD_PHY_AUTONEGO_AD_REG)); |
| return GT_FAIL; |
| } |
| |
| /* Mask out all auto mode related bits. */ |
| u16Data &= ~QD_PHY_MODE_AUTO_AUTO; |
| |
| if(hwReadPagedPhyReg(dev,hwPort,0,QD_PHY_AUTONEGO_1000AD_REG,phyInfo->anyPage,&u16Data1) != GT_OK) |
| { |
| DBG_INFO(("Not able to read Phy Reg(port:%d,offset:%d).\n",hwPort,QD_PHY_AUTONEGO_AD_REG)); |
| return GT_FAIL; |
| } |
| |
| /* Mask out all auto mode related bits. */ |
| u16Data1 &= ~(QD_GIGPHY_1000T_FULL|QD_GIGPHY_1000T_HALF); |
| |
| switch(mode) |
| { |
| case SPEED_AUTO_DUPLEX_AUTO: |
| u16Data |= QD_PHY_MODE_AUTO_AUTO; |
| case SPEED_1000_DUPLEX_AUTO: |
| u16Data1 |= QD_GIGPHY_1000T_FULL|QD_GIGPHY_1000T_HALF; |
| break; |
| case SPEED_AUTO_DUPLEX_FULL: |
| u16Data |= QD_PHY_MODE_AUTO_FULL; |
| u16Data1 |= QD_GIGPHY_1000T_FULL; |
| break; |
| case SPEED_1000_DUPLEX_FULL: |
| u16Data1 |= QD_GIGPHY_1000T_FULL; |
| break; |
| case SPEED_1000_DUPLEX_HALF: |
| u16Data1 |= QD_GIGPHY_1000T_HALF; |
| break; |
| case SPEED_AUTO_DUPLEX_HALF: |
| u16Data |= QD_PHY_MODE_AUTO_HALF; |
| u16Data1 |= QD_GIGPHY_1000T_HALF; |
| break; |
| case SPEED_100_DUPLEX_AUTO: |
| u16Data |= QD_PHY_MODE_100_AUTO; |
| break; |
| case SPEED_10_DUPLEX_AUTO: |
| u16Data |= QD_PHY_MODE_10_AUTO; |
| break; |
| case SPEED_100_DUPLEX_FULL: |
| u16Data |= QD_PHY_100_FULL; |
| break; |
| case SPEED_100_DUPLEX_HALF: |
| u16Data |= QD_PHY_100_HALF; |
| break; |
| case SPEED_10_DUPLEX_FULL: |
| u16Data |= QD_PHY_10_FULL; |
| break; |
| case SPEED_10_DUPLEX_HALF: |
| u16Data |= QD_PHY_10_HALF; |
| break; |
| default: |
| DBG_INFO(("Unknown Auto Mode (%d)\n",mode)); |
| return GT_BAD_PARAM; |
| } |
| |
| /* Write to Phy AutoNegotiation Advertisement Register. */ |
| if(hwWritePagedPhyReg(dev,hwPort,0,QD_PHY_AUTONEGO_AD_REG,phyInfo->anyPage,u16Data) != GT_OK) |
| { |
| DBG_INFO(("Not able to write Phy Reg(port:%d,offset:%d,data:%#x).\n",hwPort,QD_PHY_AUTONEGO_AD_REG,u16Data)); |
| return GT_FAIL; |
| } |
| |
| /* Write to Phy AutoNegotiation 1000B Advertisement Register. */ |
| if(hwWritePagedPhyReg(dev,hwPort,0,QD_PHY_AUTONEGO_1000AD_REG,phyInfo->anyPage,u16Data1) != GT_OK) |
| { |
| DBG_INFO(("Not able to read Phy Reg(port:%d,offset:%d).\n",hwPort,QD_PHY_AUTONEGO_AD_REG)); |
| return GT_FAIL; |
| } |
| |
| return GT_OK; |
| } |
| |
| /* |
| * This routine get Auto-Negotiation Ad Register for Copper |
| */ |
| static |
| GT_STATUS gigCopperGetAutoMode |
| ( |
| IN GT_QD_DEV *dev, |
| IN GT_U8 hwPort, |
| IN GT_PHY_INFO *phyInfo, |
| IN GT_PHY_AUTO_MODE *mode |
| ) |
| { |
| GT_U16 u16Data, u16Data1; |
| GT_U32 u32Data; |
| |
| DBG_INFO(("gigCopperGetAutoMode Called.\n")); |
| |
| if(hwReadPagedPhyReg(dev,hwPort,0,QD_PHY_AUTONEGO_AD_REG,phyInfo->anyPage,&u16Data) != GT_OK) |
| { |
| DBG_INFO(("Not able to read Phy Reg(port:%d,offset:%d).\n",hwPort,QD_PHY_AUTONEGO_AD_REG)); |
| return GT_FAIL; |
| } |
| |
| /* Pick out all auto mode related bits. */ |
| u16Data &= QD_PHY_MODE_AUTO_AUTO; |
| |
| if(hwReadPagedPhyReg(dev,hwPort,0,QD_PHY_AUTONEGO_1000AD_REG,phyInfo->anyPage,&u16Data1) != GT_OK) |
| { |
| DBG_INFO(("Not able to read Phy Reg(port:%d,offset:%d).\n",hwPort,QD_PHY_AUTONEGO_AD_REG)); |
| return GT_FAIL; |
| } |
| |
| /* Pick out all auto mode related bits. */ |
| u16Data1 &= (QD_GIGPHY_1000T_FULL|QD_GIGPHY_1000T_HALF); |
| |
| u32Data = (u16Data&0xffff)|((u16Data1&0xffff)<<16); |
| |
| switch(u32Data) |
| { |
| case QD_PHY_MODE_10_HALF: |
| *mode = SPEED_10_DUPLEX_HALF; |
| break; |
| case QD_PHY_MODE_10_FULL: |
| *mode = SPEED_10_DUPLEX_FULL; |
| break; |
| case QD_PHY_MODE_100_HALF: |
| *mode = SPEED_100_DUPLEX_HALF; |
| break; |
| case QD_PHY_MODE_100_FULL: |
| *mode = SPEED_100_DUPLEX_FULL; |
| break; |
| case (QD_GIGPHY_1000T_HALF<<16): |
| *mode = SPEED_1000_DUPLEX_HALF; |
| break; |
| case (QD_GIGPHY_1000T_FULL<<16): |
| *mode = SPEED_1000_DUPLEX_FULL; |
| break; |
| case QD_PHY_MODE_AUTO_HALF|(QD_GIGPHY_1000T_HALF<<16): |
| *mode = SPEED_AUTO_DUPLEX_HALF; |
| break; |
| case QD_PHY_MODE_AUTO_FULL|(QD_GIGPHY_1000T_FULL<<16): |
| *mode = SPEED_AUTO_DUPLEX_FULL; |
| break; |
| case QD_PHY_MODE_10_AUTO: |
| *mode = SPEED_10_DUPLEX_AUTO; |
| break; |
| case QD_PHY_MODE_100_AUTO: |
| *mode = SPEED_100_DUPLEX_AUTO; |
| break; |
| case ((QD_GIGPHY_1000T_FULL|QD_GIGPHY_1000T_HALF)<<16): |
| *mode = SPEED_1000_DUPLEX_AUTO; |
| break; |
| case QD_PHY_MODE_AUTO_AUTO|((QD_GIGPHY_1000T_FULL|QD_GIGPHY_1000T_HALF)<<16): |
| *mode = SPEED_AUTO_DUPLEX_AUTO; |
| break; |
| default: |
| *mode = SPEED_AUTO_DUPLEX_AUTO; |
| DBG_INFO(("Unknown Auto Mode (%08x)\n", u32Data)); |
| break; |
| } |
| |
| return GT_OK; |
| } |
| |
| /* |
| * This routine set Auto-Negotiation Ad Register for Fiber |
| */ |
| static |
| GT_STATUS gigFiberSetAutoMode |
| ( |
| IN GT_QD_DEV *dev, |
| IN GT_U8 hwPort, |
| IN GT_PHY_INFO *phyInfo, |
| IN GT_PHY_AUTO_MODE mode |
| ) |
| { |
| GT_U16 u16Data; |
| |
| DBG_INFO(("gigPhySetAutoMode Called.\n")); |
| |
| if(hwReadPagedPhyReg(dev,hwPort,1,QD_PHY_AUTONEGO_AD_REG,phyInfo->anyPage,&u16Data) != GT_OK) |
| { |
| DBG_INFO(("Not able to read Phy Reg(port:%d,offset:%d).\n",hwPort,QD_PHY_AUTONEGO_AD_REG)); |
| return GT_FAIL; |
| } |
| |
| /* Mask out all auto mode related bits. */ |
| u16Data &= ~(QD_GIGPHY_1000X_FULL|QD_GIGPHY_1000X_HALF); |
| |
| switch(mode) |
| { |
| case SPEED_AUTO_DUPLEX_AUTO: |
| case SPEED_1000_DUPLEX_AUTO: |
| u16Data |= QD_GIGPHY_1000X_FULL|QD_GIGPHY_1000X_HALF; |
| break; |
| case SPEED_AUTO_DUPLEX_FULL: |
| case SPEED_1000_DUPLEX_FULL: |
| u16Data |= QD_GIGPHY_1000X_FULL; |
| break; |
| case SPEED_AUTO_DUPLEX_HALF: |
| case SPEED_1000_DUPLEX_HALF: |
| u16Data |= QD_GIGPHY_1000X_HALF; |
| break; |
| default: |
| DBG_INFO(("Unknown Auto Mode (%d)\n",mode)); |
| return GT_BAD_PARAM; |
| } |
| |
| /* Write to Phy AutoNegotiation Advertisement Register. */ |
| if(hwWritePagedPhyReg(dev,hwPort,1,QD_PHY_AUTONEGO_AD_REG,phyInfo->anyPage,u16Data) != GT_OK) |
| { |
| DBG_INFO(("Not able to write Phy Reg(port:%d,offset:%d,data:%#x).\n",hwPort,QD_PHY_AUTONEGO_AD_REG,u16Data)); |
| 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 |
| ) |
| { |
| GT_U16 u16Data; |
| GT_STATUS status; |
| GT_BOOL autoOn; |
| GT_U16 pageReg; |
| |
| DBG_INFO(("phySetAutoMode Called.\n")); |
| |
| if (!(phyInfo->flag & GT_PHY_GIGABIT)) |
| { |
| if((status=feSetAutoMode(dev,hwPort,phyInfo,mode)) != GT_OK) |
| { |
| return status; |
| } |
| |
| u16Data = QD_PHY_SPEED | QD_PHY_DUPLEX | QD_PHY_AUTONEGO; |
| |
| DBG_INFO(("Write to phy(%d) register: regAddr 0x%x, data %#x", |
| hwPort,QD_PHY_CONTROL_REG,u16Data)); |
| |
| /* soft reset */ |
| return hwPhyReset(dev,hwPort,u16Data); |
| } |
| |
| if(driverPagedAccessStart(dev,hwPort,phyInfo->pageType,&autoOn,&pageReg) != GT_OK) |
| { |
| return GT_FAIL; |
| } |
| |
| if(phyInfo->flag & GT_PHY_COPPER) |
| { |
| if((status=gigCopperSetAutoMode(dev,hwPort,phyInfo,mode)) != GT_OK) |
| { |
| return status; |
| } |
| |
| u16Data = 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(hwWritePagedPhyReg(dev,hwPort,0,QD_PHY_CONTROL_REG,phyInfo->anyPage,u16Data) != GT_OK) |
| return GT_FAIL; |
| } |
| else if(phyInfo->flag & GT_PHY_FIBER) |
| { |
| if((status=gigFiberSetAutoMode(dev,hwPort,phyInfo,mode)) != GT_OK) |
| { |
| return status; |
| } |
| u16Data = 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(hwWritePagedPhyReg(dev,hwPort,1,QD_PHY_CONTROL_REG,phyInfo->anyPage,u16Data) != GT_OK) |
| return GT_FAIL; |
| } |
| |
| if(driverPagedAccessStop(dev,hwPort,phyInfo->pageType,autoOn,pageReg) != GT_OK) |
| { |
| return GT_FAIL; |
| } |
| |
| return hwPhyReset(dev,hwPort,0xFF); |
| } |
| |
| /* |
| * This routine gets Auto Mode |
| */ |
| static |
| GT_STATUS phyGetAutoMode |
| ( |
| IN GT_QD_DEV *dev, |
| IN GT_U8 hwPort, |
| IN GT_PHY_INFO *phyInfo, |
| OUT GT_PHY_AUTO_MODE *mode |
| ) |
| { |
| GT_STATUS status; |
| GT_BOOL autoOn; |
| GT_U16 pageReg; |
| |
| DBG_INFO(("phyGetAutoMode Called.\n")); |
| |
| if (!(phyInfo->flag & GT_PHY_GIGABIT)) |
| { |
| if((status=feGetAutoMode(dev,hwPort,phyInfo,mode)) != GT_OK) |
| { |
| return status; |
| } |
| return status; |
| } |
| |
| if(driverPagedAccessStart(dev,hwPort,phyInfo->pageType,&autoOn,&pageReg) != GT_OK) |
| { |
| return GT_FAIL; |
| } |
| |
| if(phyInfo->flag & GT_PHY_COPPER) |
| { |
| if((status=gigCopperGetAutoMode(dev,hwPort,phyInfo,mode)) != GT_OK) |
| { |
| return status; |
| } |
| } |
| else if(phyInfo->flag & GT_PHY_FIBER) |
| { |
| return GT_NOT_SUPPORTED; |
| } |
| |
| if(driverPagedAccessStop(dev,hwPort,phyInfo->pageType,autoOn,pageReg) != GT_OK) |
| { |
| return GT_FAIL; |
| } |
| |
| return status; |
| } |
| |
| /******************************************************************************* |
| * gprtPhyReset |
| * |
| * 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 |
| ( |
| 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; |
| |
| #ifdef GT_USE_MAD |
| if (dev->use_mad==GT_TRUE) |
| return gprtPhyReset_mad(dev, port); |
| #endif |
| |
| 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 |
| * |
| * 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 |
| ( |
| IN GT_QD_DEV *dev, |
| IN GT_LPORT port, |
| IN GT_BOOL enable |
| ) |
| { |
| GT_STATUS retVal; /* Functions return value. */ |
| GT_U8 hwPort; /* the physical port number */ |
| GT_U16 u16Data; |
| GT_PHY_INFO phyInfo; |
| |
| #ifdef GT_USE_MAD |
| if (dev->use_mad==GT_TRUE) |
| return gprtSetPortLoopback_mad(dev, port, enable); |
| #endif |
| |
| DBG_INFO(("gprtSetPortLoopback 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(hwReadPhyReg(dev,hwPort,QD_PHY_CONTROL_REG,&u16Data) != GT_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; |
| } |
| |
| /* is this Fast Ethernet Phy? */ |
| if (!(phyInfo.flag & GT_PHY_GIGABIT)) |
| { |
| if(enable) |
| { |
| if(u16Data & QD_PHY_AUTONEGO) |
| { |
| /* disable Auto-Neg and force speed to be 10Mbps */ |
| u16Data = u16Data & QD_PHY_DUPLEX; |
| |
| if((retVal=hwPhyReset(dev,hwPort,u16Data)) != GT_OK) |
| { |
| DBG_INFO(("Softreset failed.\n")); |
| gtSemGive(dev,dev->phyRegsSem); |
| return retVal; |
| } |
| } |
| } |
| } |
| |
| BOOL_2_BIT(enable,u16Data); |
| |
| /* Write to Phy Control Register. */ |
| retVal = hwSetPhyRegField(dev,hwPort,QD_PHY_CONTROL_REG,14,1,u16Data); |
| if(retVal != GT_OK) |
| { |
| DBG_INFO(("Failed.\n")); |
| } |
| else |
| { |
| DBG_INFO(("OK.\n")); |
| } |
| gtSemGive(dev,dev->phyRegsSem); |
| return retVal; |
| } |
| |
| /******************************************************************************* |
| * gprtGetPortLoopback |
| * |
| * DESCRIPTION: |
| * Get Internal Port Loopback state. |
| * 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 |
| * |
| * OUTPUTS: |
| * enable - If GT_TRUE, loopback mode is enabled |
| * If GT_FALSE, loopback mode is disabled |
| * |
| * RETURNS: |
| * GT_OK - on success |
| * GT_FAIL - on error |
| * |
| * COMMENTS: |
| * data sheet register 0.14 - Loop_back |
| * |
| *******************************************************************************/ |
| GT_STATUS gprtGetPortLoopback |
| ( |
| IN GT_QD_DEV *dev, |
| IN GT_LPORT port, |
| OUT GT_BOOL *enable |
| ) |
| { |
| GT_STATUS retVal; /* Functions return value. */ |
| GT_U8 hwPort; /* the physical port number */ |
| GT_U16 u16Data; |
| GT_PHY_INFO phyInfo; |
| |
| DBG_INFO(("gprtGetPortLoopback 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; |
| } |
| |
| /*get loopback state*/ |
| retVal = hwGetPhyRegField(dev,hwPort,QD_PHY_CONTROL_REG,14,1,&u16Data); |
| if(retVal != GT_OK) |
| { |
| DBG_INFO(("Failed.\n")); |
| } |
| else |
| { |
| DBG_INFO(("OK.\n")); |
| BIT_2_BOOL(u16Data, *enable); |
| } |
| |
| return retVal; |
| } |
| |
| /******************************************************************************* |
| * gprtSetPortLineLoopback |
| * |
| * DESCRIPTION: |
| * Enable/Disable Port Line Loopback. |
| * |
| * 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 FE:28.4, GE:21_2.14 - Loop_back |
| * |
| *******************************************************************************/ |
| GT_STATUS gprtSetPortLineLoopback |
| ( |
| IN GT_QD_DEV *dev, |
| IN GT_LPORT port, |
| IN GT_BOOL enable |
| ) |
| { |
| GT_STATUS retVal; /* Functions return value. */ |
| GT_U8 hwPort; /* the physical port number */ |
| GT_U16 u16Data; |
| GT_PHY_INFO phyInfo; |
| GT_U16 pageReg; |
| |
| DBG_INFO(("gprtSetPortLineLoopback 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; |
| } |
| |
| BOOL_2_BIT(enable,u16Data); |
| |
| /* GE Phy */ |
| if ((phyInfo.flag & GT_PHY_GIGABIT)) |
| { |
| if(driverPagedAccessStart(dev,hwPort,phyInfo.pageType,0,&pageReg) != GT_OK) |
| { |
| return GT_FAIL; |
| } |
| /* Write to GE PHY MAC specific control register. */ |
| retVal = hwSetPagedPhyRegField(dev,hwPort, 2, QD_PHY_GE_LINE_LOOPBACK_REG,14,1,phyInfo.anyPage, u16Data); |
| |
| if(driverPagedAccessStop(dev,hwPort,phyInfo.pageType,0,pageReg) != GT_OK) |
| { |
| return GT_FAIL; |
| } |
| } |
| else /* FE Phy */ |
| { |
| /* Write to FE PHY specific control register. */ |
| retVal = hwSetPhyRegField(dev,hwPort,QD_PHY_FE_LINE_LOOPBACK_REG,4,1,u16Data); |
| } |
| |
| if(retVal != GT_OK) |
| { |
| DBG_INFO(("Failed.\n")); |
| } |
| else |
| { |
| DBG_INFO(("OK.\n")); |
| } |
| gtSemGive(dev,dev->phyRegsSem); |
| return retVal; |
| } |
| |
| /******************************************************************************* |
| * gprtGetPortLineLoopback |
| * |
| * DESCRIPTION: |
| * Get Port Line Loopback status. |
| * |
| * |
| * INPUTS: |
| * port - The logical port number, unless SERDES device is accessed |
| * The physical address, if SERDES device is accessed |
| * |
| * OUTPUTS: |
| * enable - If GT_TRUE, enable loopback mode |
| * If GT_FALSE, disable loopback mode* enable - If GT_TRUE, enable loopback mode |
| * If GT_FALSE, disable loopback mode |
| * |
| * RETURNS: |
| * GT_OK - on success |
| * GT_FAIL - on error |
| * |
| * COMMENTS: |
| * data sheet register FE:28.4, GE:21_2.14 - Loop_back |
| * |
| *******************************************************************************/ |
| GT_STATUS gprtGetPortLineLoopback |
| ( |
| IN GT_QD_DEV *dev, |
| IN GT_LPORT port, |
| OUT GT_BOOL *enable |
| ) |
| { |
| GT_STATUS retVal; /* Functions return value. */ |
| GT_U8 hwPort; /* the physical port number */ |
| GT_U16 u16Data; |
| GT_PHY_INFO phyInfo; |
| GT_U16 pageReg; |
| |
| DBG_INFO(("gprtGetPortLineLoopback 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; |
| } |
| |
| /* GE Phy */ |
| if ((phyInfo.flag & GT_PHY_GIGABIT)) |
| { |
| if(driverPagedAccessStart(dev,hwPort,phyInfo.pageType,0,&pageReg) != GT_OK) |
| { |
| return GT_FAIL; |
| } |
| /* Read to GE PHY MAC specific control register. */ |
| retVal = hwGetPagedPhyRegField(dev,hwPort, 2, QD_PHY_GE_LINE_LOOPBACK_REG,14,1,phyInfo.anyPage,&u16Data); |
| |
| if(driverPagedAccessStop(dev,hwPort,phyInfo.pageType,0,pageReg) != GT_OK) |
| { |
| return GT_FAIL; |
| } |
| } |
| else /* FE Phy */ |
| { |
| /* Read to FE PHY specific control register. */ |
| retVal = hwGetPhyRegField(dev,hwPort,QD_PHY_FE_LINE_LOOPBACK_REG,4,1,&u16Data); |
| } |
| |
| if(retVal != GT_OK) |
| { |
| DBG_INFO(("Failed.\n")); |
| } |
| else |
| { |
| DBG_INFO(("OK.\n")); |
| } |
| |
| BIT_2_BOOL(u16Data, *enable); |
| |
| gtSemGive(dev,dev->phyRegsSem); |
| return retVal; |
| } |
| |
| /******************************************************************************* |
| * gprtSetPortSpeed |
| * |
| * 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 |
| ( |
| IN GT_QD_DEV *dev, |
| IN GT_LPORT port, |
| IN GT_PHY_SPEED speed |
| ) |
| { |
| GT_U8 hwPort; /* the physical port number */ |
| GT_U16 u16Data; |
| GT_PHY_INFO phyInfo; |
| GT_STATUS retVal; |
| |
| #ifdef GT_USE_MAD |
| if (dev->use_mad==GT_TRUE) |
| return gprtSetPortSpeed_mad(dev, port, speed); |
| #endif |
| |
| DBG_INFO(("gprtSetPortSpeed 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(hwReadPhyReg(dev,hwPort,QD_PHY_CONTROL_REG,&u16Data) != GT_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; |
| } |
| |
| switch(speed) |
| { |
| case PHY_SPEED_10_MBPS: |
| if ((phyInfo.flag & GT_PHY_GIGABIT) && !(phyInfo.flag & GT_PHY_COPPER)) |
| { |
| gtSemGive(dev,dev->phyRegsSem); |
| return GT_BAD_PARAM; |
| } |
| u16Data = u16Data & (QD_PHY_LOOPBACK | QD_PHY_DUPLEX); |
| break; |
| case PHY_SPEED_100_MBPS: |
| u16Data = (u16Data & (QD_PHY_LOOPBACK | QD_PHY_DUPLEX)) | QD_PHY_SPEED; |
| break; |
| case PHY_SPEED_1000_MBPS: |
| if (!(phyInfo.flag & GT_PHY_GIGABIT)) |
| { |
| gtSemGive(dev,dev->phyRegsSem); |
| return GT_BAD_PARAM; |
| } |
| u16Data = (u16Data & (QD_PHY_LOOPBACK | QD_PHY_DUPLEX)) | QD_PHY_SPEED_MSB; |
| break; |
| default: |
| gtSemGive(dev,dev->phyRegsSem); |
| return GT_FAIL; |
| } |
| |
| DBG_INFO(("Write to phy(%d) register: regAddr 0x%x, data %#x", |
| hwPort,QD_PHY_CONTROL_REG,u16Data)); |
| |
| retVal = hwPhyReset(dev,hwPort,u16Data); |
| gtSemGive(dev,dev->phyRegsSem); |
| return retVal; |
| } |
| |
| |
| /******************************************************************************* |
| * gprtPortAutoNegEnable |
| * |
| * 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 |
| ( |
| IN GT_QD_DEV *dev, |
| IN GT_LPORT port, |
| IN GT_BOOL state |
| ) |
| { |
| GT_U8 hwPort; /* the physical port number */ |
| GT_U16 u16Data; |
| GT_STATUS retVal; |
| |
| #ifdef GT_USE_MAD |
| if (dev->use_mad==GT_TRUE) |
| return gprtPortAutoNegEnable_mad(dev, port, state); |
| #endif |
| |
| DBG_INFO(("gprtPortAutoNegEnable 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(hwReadPhyReg(dev,hwPort,QD_PHY_CONTROL_REG,&u16Data) != GT_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; |
| } |
| |
| if(state) |
| { |
| u16Data = (u16Data & (QD_PHY_SPEED | QD_PHY_DUPLEX)) | QD_PHY_AUTONEGO; |
| } |
| else |
| { |
| u16Data = u16Data & (QD_PHY_SPEED | QD_PHY_DUPLEX); |
| } |
| |
| |
| DBG_INFO(("Write to phy(%d) register: regAddr 0x%x, data %#x", |
| hwPort,QD_PHY_CONTROL_REG,u16Data)); |
| |
| retVal = hwPhyReset(dev,hwPort,u16Data); |
| gtSemGive(dev,dev->phyRegsSem); |
| return retVal; |
| } |
| |
| /******************************************************************************* |
| * gprtGetPortAutoNegState |
| * |
| * DESCRIPTION: |
| * Read the auto negotiation state of specific logical port. |
| * This routine simply reads Auto Negotiation bit (bit 12) of Control |
| * Register. |
| * |
| * INPUTS: |
| * port - The logical port number, unless SERDES device is accessed |
| * The physical address, if SERDES device is accessed |
| * |
| * OUTPUTS: |
| * state - GT_TRUE for enable Auto-Negotiation, |
| * GT_FALSE otherwise |
| * |
| * 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 gprtGetPortAutoNegState |
| ( |
| IN GT_QD_DEV *dev, |
| IN GT_LPORT port, |
| OUT GT_BOOL *state |
| ) |
| { |
| GT_U8 hwPort; /* the physical port number */ |
| GT_U16 u16Data; |
| GT_STATUS retVal; |
| |
| DBG_INFO(("gprtGetPortAutoNegState 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; |
| } |
| |
| /* read the auto negotiation state from bit 12 of PHY control register */ |
| if((retVal=hwGetPhyRegField(dev,hwPort,QD_PHY_CONTROL_REG,12,1,&u16Data)) != GT_OK) |
| { |
| DBG_INFO(("Failed.\n")); |
| gtSemGive(dev,dev->phyRegsSem); |
| return retVal; |
| } |
| |
| BIT_2_BOOL(u16Data, *state); |
| |
| gtSemGive(dev,dev->phyRegsSem); |
| return retVal; |
| } |
| |
| /******************************************************************************* |
| * gprtPortPowerDown |
| * |
| * 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 |
| ( |
| IN GT_QD_DEV *dev, |
| IN GT_LPORT port, |
| IN GT_BOOL state |
| ) |
| { |
| GT_STATUS retVal; /* Functions return value. */ |
| GT_U8 hwPort; /* the physical port number */ |
| GT_U16 u16Data; |
| |
| #ifdef GT_USE_MAD |
| if (dev->use_mad==GT_TRUE) |
| return gprtPortPowerDown_mad(dev, port, state); |
| #endif |
| |
| DBG_INFO(("gprtPortPowerDown 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; |
| } |
| |
| BOOL_2_BIT(state,u16Data); |
| |
| if((retVal=hwSetPhyRegField(dev,hwPort,QD_PHY_CONTROL_REG,11,1,u16Data)) != GT_OK) |
| { |
| DBG_INFO(("Failed.\n")); |
| gtSemGive(dev,dev->phyRegsSem); |
| return retVal; |
| } |
| |
| gtSemGive(dev,dev->phyRegsSem); |
| return GT_OK; |
| } |
| |
| /******************************************************************************* |
| * gprtGetPortPowerDown |
| * |
| * DESCRIPTION: |
| * Read Port state (power down/normal operation) on specific logical port. |
| * |
| * INPUTS: |
| * port - The logical port number, unless SERDES device is accessed |
| * The physical address, if SERDES device is accessed |
| * |
| * OUTPUTS: |
| * state - GT_TRUE: power down |
| * GT_FALSE: normal operation |
| * |
| * RETURNS: |
| * GT_OK - on success |
| * GT_FAIL - on error |
| * |
| * COMMENTS: |
| * data sheet register 0.11 - Power Down |
| * |
| *******************************************************************************/ |
| GT_STATUS gprtGetPortPowerDown |
| ( |
| IN GT_QD_DEV *dev, |
| IN GT_LPORT port, |
| OUT GT_BOOL *state |
| ) |
| { |
| GT_STATUS retVal; /* Functions return value. */ |
| GT_U8 hwPort; /* the physical port number */ |
| GT_U16 u16Data; |
| |
| #ifdef GT_USE_MAD |
| |
| #endif |
| |
| DBG_INFO(("gprtGetPortPowerDown Called.\n")); |
| |
| if(state == NULL) |
| { |
| DBG_INFO(("input pointer is NULL, return\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=hwGetPhyRegField(dev,hwPort,QD_PHY_CONTROL_REG,11,1,&u16Data)) != GT_OK) |
| { |
| DBG_INFO(("Failed.\n")); |
| gtSemGive(dev,dev->phyRegsSem); |
| return retVal; |
| } |
| |
| BIT_2_BOOL(u16Data, *state); |
| |
| gtSemGive(dev,dev->phyRegsSem); |
| return GT_OK; |
| } |
| |
| /******************************************************************************* |
| * gprtPortRestartAutoNeg |
| * |
| * 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 |
| ( |
| IN GT_QD_DEV *dev, |
| IN GT_LPORT port |
| ) |
| { |
| GT_STATUS retVal; |
| GT_U8 hwPort; /* the physical port number */ |
| GT_U16 u16Data; |
| |
| #ifdef GT_USE_MAD |
| if (dev->use_mad==GT_TRUE) |
| return gprtPortRestartAutoNeg_mad(dev, port); |
| #endif |
| |
| DBG_INFO(("gprtPortRestartAutoNeg 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(hwReadPhyReg(dev,hwPort,QD_PHY_CONTROL_REG,&u16Data) != GT_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 &= (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. */ |
| retVal = hwWritePhyReg(dev,hwPort,QD_PHY_CONTROL_REG,u16Data); |
| gtSemGive(dev,dev->phyRegsSem); |
| |
| if(retVal != GT_OK) |
| { |
| DBG_INFO(("Failed.\n")); |
| } |
| else |
| { |
| DBG_INFO(("OK.\n")); |
| } |
| return retVal; |
| } |
| |
| /******************************************************************************* |
| * gprtSetPortDuplexMode |
| * |
| * 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 |
| ( |
| 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; |
| |
| #ifdef GT_USE_MAD |
| if (dev->use_mad==GT_TRUE) |
| return gprtSetPortDuplexMode_mad(dev, port, dMode); |
| #endif |
| |
| DBG_INFO(("gprtSetPortDuplexMode 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(hwReadPhyReg(dev,hwPort,QD_PHY_CONTROL_REG,&u16Data) != GT_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; |
| } |
| |
| 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. */ |
| retVal = hwPhyReset(dev,hwPort,u16Data); |
| gtSemGive(dev,dev->phyRegsSem); |
| return retVal; |
| } |
| |
| |
| /******************************************************************************* |
| * gprtSetPortAutoMode |
| * |
| * 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 |
| ( |
| 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; |
| |
| #ifdef GT_USE_MAD |
| if (dev->use_mad==GT_TRUE) |
| return gprtSetPortAutoMode_mad(dev, port, mode); |
| #endif |
| |
| DBG_INFO(("gprtSetPortAutoMode 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; |
| |
| } |
| |
| /******************************************************************************* |
| * gprtGetPortAutoMode |
| * |
| * DESCRIPTION: |
| * This routine get Auto Mode of specific port. |
| * 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 |
| * |
| * OUTPUTS: |
| * mode - Auto Mode to be written |
| * |
| * 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 gprtGetPortAutoMode |
| ( |
| IN GT_QD_DEV *dev, |
| IN GT_LPORT port, |
| OUT GT_PHY_AUTO_MODE *mode |
| ) |
| { |
| GT_STATUS retVal; /* Functions return value. */ |
| GT_U8 hwPort; /* the physical port number */ |
| GT_PHY_INFO phyInfo; |
| |
| DBG_INFO(("gprtGetPortAutoMode 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) |
| { |
| DBG_INFO(("PHY device is not configurable.\n")); |
| 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 = phyGetAutoMode(dev,hwPort,&phyInfo,mode); |
| |
| gtSemGive(dev,dev->phyRegsSem); |
| return retVal; |
| |
| } |
| |
| /******************************************************************************* |
| * gprtSetPause |
| * |
| * 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 |
| ( |
| IN GT_QD_DEV *dev, |
| IN GT_LPORT port, |
| IN GT_PHY_PAUSE_MODE state |
| ) |
| { |
| GT_U8 hwPort; /* the physical port number */ |
| GT_U16 u16Data,regStart; |
| GT_STATUS retVal = GT_OK; |
| GT_PHY_INFO phyInfo; |
| |
| #ifdef GT_USE_MAD |
| if (dev->use_mad==GT_TRUE) |
| return gprtSetPause_mad(dev, port, state); |
| #endif |
| |
| DBG_INFO(("phySetPause 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; |
| } |
| |
| regStart = 10; |
| |
| 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(!(phyInfo.flag & GT_PHY_COPPER)) |
| { |
| regStart = 7; |
| } |
| |
| } |
| |
| u16Data = state; |
| |
| /* Write to Phy AutoNegotiation Advertisement Register. */ |
| if((retVal=hwSetPhyRegField(dev,hwPort,QD_PHY_AUTONEGO_AD_REG,(GT_U8)regStart,2,u16Data)) != GT_OK) |
| { |
| DBG_INFO(("Not able to write Phy Reg(port:%d,offset:%d).\n",hwPort,QD_PHY_AUTONEGO_AD_REG)); |
| gtSemGive(dev,dev->phyRegsSem); |
| return GT_FAIL; |
| } |
| |
| /* Restart Auto Negotiation */ |
| if((retVal=hwSetPhyRegField(dev,hwPort,QD_PHY_CONTROL_REG,9,1,1)) != GT_OK) |
| { |
| DBG_INFO(("Not able to write Phy Reg(port:%d,offset:%d,data:%#x).\n",hwPort,QD_PHY_AUTONEGO_AD_REG,u16Data)); |
| gtSemGive(dev,dev->phyRegsSem); |
| return GT_FAIL; |
| } |
| |
| gtSemGive(dev,dev->phyRegsSem); |
| return retVal; |
| } |
| |
| /******************************************************************************* |
| * gprtGetPause |
| * |
| * DESCRIPTION: |
| * This routine will get the pause bit in Autonegotiation Advertisement |
| * Register. |
| * |
| * INPUTS: |
| * port - The logical port number, unless SERDES device is accessed |
| * The physical address, if SERDES device is accessed |
| * |
| * |
| * OUTPUTS: |
| * 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 |
| * |
| * RETURNS: |
| * GT_OK - on success |
| * GT_FAIL - on error |
| * COMMENTS: |
| * data sheet register 4.10 Autonegotiation Advertisement Register |
| *******************************************************************************/ |
| GT_STATUS gprtGetPause |
| ( |
| IN GT_QD_DEV *dev, |
| IN GT_LPORT port, |
| OUT GT_PHY_PAUSE_MODE *state |
| ) |
| { |
| GT_U8 hwPort; /* the physical port number */ |
| GT_U16 u16Data; |
| GT_U16 regStart; |
| GT_STATUS retVal = GT_OK; |
| GT_PHY_INFO phyInfo; |
| |
| DBG_INFO(("gprtGetPause 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; |
| } |
| |
| regStart = 10; |
| |
| /* Read Phy AutoNegotiation Advertisement Register. */ |
| if((retVal=hwGetPhyRegField(dev,hwPort,QD_PHY_AUTONEGO_AD_REG,(GT_U8)regStart,2,&u16Data)) != GT_OK) |
| { |
| DBG_INFO(("Not able to write Phy Reg(port:%d,offset:%d).\n",hwPort,QD_PHY_AUTONEGO_AD_REG)); |
| gtSemGive(dev,dev->phyRegsSem); |
| return GT_FAIL; |
| } |
| |
| gtSemGive(dev,dev->phyRegsSem); |
| |
| *state = u16Data; |
| |
| return retVal; |
| } |
| |
| static |
| GT_STATUS dteWorkAround_Phy100M |
| ( |
| IN GT_QD_DEV *dev, |
| IN GT_U8 hwPort |
| ) |
| { |
| GT_STATUS status = GT_OK; |
| GT_U32 threshold[] = {0x000B,0x0000,0x8780,0x0000,0x8F80,0x0000, |
| 0x9780,0x0000,0x9F80,0x0000,0xA780,0x0000, |
| 0xAF80,0x0000,0xB780,0x0000,0xBF80,0x0000, |
| 0xC780,0x0000,0xCF80,0x0000,0xD780,0x0000, |
| 0xDF80,0x0000,0xE780,0x0000,0xEF80,0x0000, |
| 0xF780,0x0000,0xFF80,0x0000}; |
| int i, thresholdSize; |
| |
| /* force r125 clock */ |
| if((status= hwWritePhyReg(dev,hwPort,0x1D,0x0003)) != GT_OK) |
| { |
| return status; |
| } |
| if((status= hwWritePhyReg(dev,hwPort,0x1E,0x807f)) != GT_OK) |
| { |
| return status; |
| } |
| |
| /* write thresholds */ |
| if((status= hwWritePhyReg(dev,hwPort,0x1D,0x000B)) != GT_OK) |
| { |
| return status; |
| } |
| |
| thresholdSize = sizeof(threshold)/sizeof(GT_U32); |
| |
| for(i=0; i<thresholdSize; i++) |
| { |
| if((status= hwWritePhyReg(dev,hwPort,0x1E,(GT_U16)threshold[i])) != GT_OK) |
| { |
| return status; |
| } |
| } |
| |
| /* setting adc Masking */ |
| if((status= hwWritePhyReg(dev,hwPort,0x1D,0x0001)) != GT_OK) |
| { |
| return status; |
| } |
| if((status= hwWritePhyReg(dev,hwPort,0x1E,0x4000)) != GT_OK) |
| { |
| return status; |
| } |
| |
| /* setting noise level */ |
| if((status= hwWritePhyReg(dev,hwPort,0x1D,0x0005)) != GT_OK) |
| { |
| return status; |
| } |
| if((status= hwWritePhyReg(dev,hwPort,0x1E,0xA000)) != GT_OK) |
| { |
| return status; |
| } |
| |
| /* |
| offseting cable length measurement by 6.72m(2*4*0.84m) |
| set 30_10.14:11 to 0x1001 for cable length measure. |
| */ |
| if((status= hwWritePhyReg(dev,hwPort,0x1D,0x000a)) != GT_OK) |
| { |
| return status; |
| } |
| if((status= hwWritePhyReg(dev,hwPort,0x1E,0x4840)) != GT_OK) |
| { |
| return status; |
| } |
| |
| /* release force r125 clock */ |
| if((status= hwWritePhyReg(dev,hwPort,0x1D,0x0003)) != GT_OK) |
| { |
| return status; |
| } |
| if((status= hwWritePhyReg(dev,hwPort,0x1E,0x0000)) != GT_OK) |
| { |
| return status; |
| } |
| |
| |
| return status; |
| } |
| |
| static |
| GT_STATUS dteWorkAround_Phy1000M |
| ( |
| IN GT_QD_DEV *dev, |
| IN GT_U8 hwPort |
| ) |
| { |
| GT_STATUS status = GT_OK; |
| GT_U32 threshold[] = {0x0000,0x8780,0x0000,0x8F80,0x0000,0x9780, |
| 0x0000,0x9F80,0x0000,0xA780,0x0000,0xAF80, |
| 0x0000,0xB780,0x0000,0xBF80,0x0000,0xC780, |
| 0x0000,0xCF80,0x0000,0xD780,0x0000,0xDF80, |
| 0x0000,0xE780,0x0000,0xEF80,0x0000,0xF780, |
| 0x0000,0xFF80,0x0000}; |
| int i, thresholdSize; |
| |
| /* */ |
| if((status= hwWritePhyReg(dev,hwPort,0x1D,0x001B)) != GT_OK) |
| { |
| return status; |
| } |
| if((status= hwWritePhyReg(dev,hwPort,0x1E,0x43FF)) != GT_OK) |
| { |
| return status; |
| } |
| |
| /* */ |
| if((status= hwWritePhyReg(dev,hwPort,0x1D,0x001C)) != GT_OK) |
| { |
| return status; |
| } |
| if((status= hwWritePhyReg(dev,hwPort,0x1E,0x9999)) != GT_OK) |
| { |
| return status; |
| } |
| |
| /* */ |
| if((status= hwWritePhyReg(dev,hwPort,0x1D,0x001F)) != GT_OK) |
| { |
| return status; |
| } |
| if((status= hwWritePhyReg(dev,hwPort,0x1E,0xE00C)) != GT_OK) |
| { |
| return status; |
| } |
| |
| /* */ |
| if((status= hwWritePhyReg(dev,hwPort,0x1D,0x0018)) != GT_OK) |
| { |
| return status; |
| } |
| if((status= hwWritePhyReg(dev,hwPort,0x1E,0xFFA1)) != GT_OK) |
| { |
| return status; |
| } |
| |
| /* write thresholds */ |
| if((status= hwWritePhyReg(dev,hwPort,0x1D,0x0010)) != GT_OK) |
| { |
| return status; |
| } |
| |
| thresholdSize = sizeof(threshold)/sizeof(GT_U32); |
| |
| for(i=0; i<thresholdSize; i++) |
| { |
| if((status= hwWritePhyReg(dev,hwPort,0x1E,(GT_U16)threshold[i])) != GT_OK) |
| { |
| return status; |
| } |
| } |
| |
| return status; |
| } |
| |
| static |
| GT_STATUS feSetDTE |
| ( |
| IN GT_QD_DEV *dev, |
| IN GT_U8 hwPort, |
| IN GT_BOOL state |
| ) |
| { |
| GT_U16 u16Data; |
| GT_STATUS retVal = GT_OK; |
| |
| if((retVal = hwReadPhyReg(dev,hwPort,0x10,&u16Data)) != GT_OK) |
| { |
| return retVal; |
| } |
| |
| u16Data = state?(u16Data|0x8000):(u16Data&(~0x8000)); |
| |
| if((retVal = hwWritePhyReg(dev,hwPort,0x10,u16Data)) != GT_OK) |
| { |
| return retVal; |
| } |
| |
| /* soft reset */ |
| if((retVal = hwPhyReset(dev,hwPort,0xFF)) != GT_OK) |
| { |
| return retVal; |
| } |
| |
| return retVal; |
| } |
| |
| static |
| GT_STATUS gigSetDTE |
| ( |
| IN GT_QD_DEV *dev, |
| IN GT_U8 hwPort, |
| IN GT_BOOL state |
| ) |
| { |
| GT_U16 u16Data; |
| GT_STATUS retVal = GT_OK; |
| |
| if((retVal = hwReadPhyReg(dev,hwPort,20,&u16Data)) != GT_OK) |
| { |
| return retVal; |
| } |
| |
| u16Data = state?(u16Data|0x4):(u16Data&(~0x4)); |
| |
| if((retVal = hwWritePhyReg(dev,hwPort,20,u16Data)) != GT_OK) |
| { |
| return retVal; |
| } |
| |
| /* soft reset */ |
| if((retVal = hwPhyReset(dev,hwPort,0xFF)) != GT_OK) |
| { |
| return retVal; |
| } |
| |
| return retVal; |
| } |
| |
| static |
| GT_STATUS gigMPSetDTE |
| ( |
| IN GT_QD_DEV *dev, |
| IN GT_U8 hwPort, |
| IN GT_BOOL state |
| ) |
| { |
| GT_U16 u16Data; |
| GT_STATUS retVal = GT_OK; |
| |
| if((retVal = hwReadPagedPhyReg(dev,hwPort,0,26,0,&u16Data)) != GT_OK) |
| { |
| return retVal; |
| } |
| |
| u16Data = state?(u16Data|0x100):(u16Data&(~0x100)); |
| |
| if((retVal = hwWritePagedPhyReg(dev,hwPort,0,26,0,u16Data)) != GT_OK) |
| { |
| return retVal; |
| } |
| |
| /* soft reset */ |
| if((retVal = hwPhyReset(dev,hwPort,0xFF)) != GT_OK) |
| { |
| return retVal; |
| } |
| |
| return retVal; |
| } |
| |
| /******************************************************************************* |
| * gprtSetDTEDetect |
| * |
| * 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 |
| ( |
| 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; |
| GT_BOOL autoOn; |
| GT_U16 pageReg; |
| |
| #ifdef GT_USE_MAD |
| if (dev->use_mad==GT_TRUE) |
| return gprtSetDTEDetect_mad(dev, port, state); |
| #endif |
| |
| DBG_INFO(("phySetDTE 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; |
| } |
| |
| switch(phyInfo.dteType) |
| { |
| case GT_PHY_DTE_TYPE1: |
| /* FE Phy needs work-around */ |
| if((retVal = feSetDTE(dev,hwPort,state)) != GT_OK) |
| { |
| gtSemGive(dev,dev->phyRegsSem); |
| return retVal; |
| } |
| |
| if(state == GT_FALSE) |
| break; |
| |
| if((retVal = dteWorkAround_Phy100M(dev,hwPort)) != GT_OK) |
| { |
| gtSemGive(dev,dev->phyRegsSem); |
| return retVal; |
| } |
| break; |
| case GT_PHY_DTE_TYPE3: |
| /* Gigabit Phy with work-around required */ |
| if((retVal = gigSetDTE(dev,hwPort,state)) != GT_OK) |
| { |
| gtSemGive(dev,dev->phyRegsSem); |
| return retVal; |
| } |
| |
| if(state == GT_FALSE) |
| break; |
| |
| if((retVal = dteWorkAround_Phy1000M(dev,hwPort)) != GT_OK) |
| { |
| gtSemGive(dev,dev->phyRegsSem); |
| return retVal; |
| } |
| break; |
| |
| case GT_PHY_DTE_TYPE2: |
| /* no workaround required */ |
| if((retVal = gigSetDTE(dev,hwPort,state)) != GT_OK) |
| { |
| gtSemGive(dev,dev->phyRegsSem); |
| return retVal; |
| } |
| |
| break; |
| case GT_PHY_DTE_TYPE4: |
| /* no workaround required */ |
| if(driverPagedAccessStart(dev,hwPort,phyInfo.pageType,&autoOn,&pageReg) != GT_OK) |
| { |
| gtSemGive(dev,dev->phyRegsSem); |
| return GT_FAIL; |
| } |
| |
| if((retVal = gigMPSetDTE(dev,hwPort,state)) != GT_OK) |
| { |
| gtSemGive(dev,dev->phyRegsSem); |
| return retVal; |
| } |
| |
| if(driverPagedAccessStop(dev,hwPort,phyInfo.pageType,autoOn,pageReg) != GT_OK) |
| { |
| gtSemGive(dev,dev->phyRegsSem); |
| return GT_FAIL; |
| } |
| break; |
| case GT_PHY_DTE_TYPE5: |
| /* FE Phy */ |
| if((retVal = feSetDTE(dev,hwPort,state)) != GT_OK) |
| { |
| gtSemGive(dev,dev->phyRegsSem); |
| return retVal; |
| } |
| break; |
| |
| default: |
| gtSemGive(dev,dev->phyRegsSem); |
| return GT_NOT_SUPPORTED; |
| } |
| |
| gtSemGive(dev,dev->phyRegsSem); |
| return retVal; |
| } |
| |
| |
| /******************************************************************************* |
| * gprtGetDTEDetectStatus |
| * |
| * 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 |
| ( |
| IN GT_QD_DEV *dev, |
| IN GT_LPORT port, |
| OUT GT_BOOL *state |
| ) |
| { |
| GT_U8 hwPort; /* the physical port number */ |
| GT_U16 u16Data,pageReg; |
| GT_STATUS retVal = GT_OK; |
| GT_PHY_INFO phyInfo; |
| GT_BOOL autoOn; |
| |
| #ifdef GT_USE_MAD |
| if (dev->use_mad==GT_TRUE) |
| return gprtGetDTEDetectStatus_mad(dev, port, state); |
| #endif |
| |
| DBG_INFO(("gprtGetDTEStatus 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; |
| } |
| |
| switch(phyInfo.dteType) |
| { |
| case GT_PHY_DTE_TYPE1: |
| /* FE Phy needs work-around */ |
| if((retVal = hwReadPhyReg(dev,hwPort,17,&u16Data)) != GT_OK) |
| { |
| gtSemGive(dev,dev->phyRegsSem); |
| return retVal; |
| } |
| *state = (u16Data & 0x8000)?GT_TRUE:GT_FALSE; |
| |
| break; |
| case GT_PHY_DTE_TYPE2: |
| case GT_PHY_DTE_TYPE3: |
| if((retVal = hwReadPhyReg(dev,hwPort,27,&u16Data)) != GT_OK) |
| { |
| gtSemGive(dev,dev->phyRegsSem); |
| return retVal; |
| } |
| *state = (u16Data & 0x10)?GT_TRUE:GT_FALSE; |
| |
| break; |
| case GT_PHY_DTE_TYPE4: |
| if(driverPagedAccessStart(dev,hwPort,phyInfo.pageType,&autoOn,&pageReg) != GT_OK) |
| { |
| gtSemGive(dev,dev->phyRegsSem); |
| return GT_FAIL; |
| } |
| |
| if((retVal = hwReadPagedPhyReg(dev,hwPort,0,17,phyInfo.anyPage,&u16Data)) != GT_OK) |
| { |
| gtSemGive(dev,dev->phyRegsSem); |
| return retVal; |
| } |
| *state = (u16Data & 0x4)?GT_TRUE:GT_FALSE; |
| |
| if(driverPagedAccessStop(dev,hwPort,phyInfo.pageType,autoOn,pageReg) != GT_OK) |
| { |
| gtSemGive(dev,dev->phyRegsSem); |
| return GT_FAIL; |
| } |
| |
| break; |
| default: |
| gtSemGive(dev,dev->phyRegsSem); |
| return GT_NOT_SUPPORTED; |
| } |
| |
| gtSemGive(dev,dev->phyRegsSem); |
| return retVal; |
| } |
| |
| |
| /******************************************************************************* |
| * gprtSetDTEDetectDropWait |
| * |
| * 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 |
| ( |
| IN GT_QD_DEV *dev, |
| IN GT_LPORT port, |
| IN GT_U16 waitTime |
| ) |
| { |
| GT_U8 hwPort; /* the physical port number */ |
| GT_U16 u16Data; |
| GT_STATUS retVal = GT_OK; |
| GT_PHY_INFO phyInfo; |
| GT_BOOL autoOn; |
| GT_U16 pageReg; |
| |
| #ifdef GT_USE_MAD |
| if (dev->use_mad==GT_TRUE) |
| return gprtSetDTEDetectDropWait_mad(dev, port, waitTime); |
| #endif |
| |
| DBG_INFO(("gprtSetDTEDropWait 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; |
| } |
| |
| switch(phyInfo.dteType) |
| { |
| case GT_PHY_DTE_TYPE1: |
| if((retVal = hwReadPhyReg(dev,hwPort,22,&u16Data)) != GT_OK) |
| { |
| gtSemGive(dev,dev->phyRegsSem); |
| return retVal; |
| } |
| u16Data = (u16Data & ~(0xF<<12)) | ((waitTime & 0xF) << 12); |
| |
| if((retVal = hwWritePhyReg(dev,hwPort,22,u16Data)) != GT_OK) |
| { |
| gtSemGive(dev,dev->phyRegsSem); |
| return retVal; |
| } |
| break; |
| case GT_PHY_DTE_TYPE2: |
| case GT_PHY_DTE_TYPE3: |
| if((retVal = hwReadPhyReg(dev,hwPort,27,&u16Data)) != GT_OK) |
| { |
| gtSemGive(dev,dev->phyRegsSem); |
| return retVal; |
| } |
| u16Data = (u16Data & ~(0xF<<5)) | ((waitTime & 0xF) << 5); |
| |
| if((retVal = hwWritePhyReg(dev,hwPort,27,u16Data)) != GT_OK) |
| { |
| gtSemGive(dev,dev->phyRegsSem); |
| return retVal; |
| } |
| |
| break; |
| case GT_PHY_DTE_TYPE4: |
| if(driverPagedAccessStart(dev,hwPort,phyInfo.pageType,&autoOn,&pageReg) != GT_OK) |
| { |
| gtSemGive(dev,dev->phyRegsSem); |
| return GT_FAIL; |
| } |
| |
| if((retVal = hwReadPagedPhyReg(dev,hwPort,0,26,phyInfo.anyPage,&u16Data)) != GT_OK) |
| { |
| gtSemGive(dev,dev->phyRegsSem); |
| return retVal; |
| } |
| u16Data = (u16Data & ~(0xF<<4)) | ((waitTime & 0xF) << 4); |
| if((retVal = hwWritePagedPhyReg(dev,hwPort,0,26,phyInfo.anyPage,u16Data)) != GT_OK) |
| { |
| gtSemGive(dev,dev->phyRegsSem); |
| return retVal; |
| } |
| |
| if(driverPagedAccessStop(dev,hwPort,phyInfo.pageType,autoOn,pageReg) != GT_OK) |
| { |
| gtSemGive(dev,dev->phyRegsSem); |
| return GT_FAIL; |
| } |
| |
| break; |
| default: |
| gtSemGive(dev,dev->phyRegsSem); |
| return GT_NOT_SUPPORTED; |
| } |
| |
| gtSemGive(dev,dev->phyRegsSem); |
| return retVal; |
| } |
| |
| |
| /******************************************************************************* |
| * gprtGetDTEDetectDropWait |
| * |
| * 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 |
| ( |
| IN GT_QD_DEV *dev, |
| IN GT_LPORT port, |
| OUT GT_U16 *waitTime |
| ) |
| { |
| GT_U8 hwPort; /* the physical port number */ |
| GT_U16 u16Data; |
| GT_STATUS retVal = GT_OK; |
| GT_PHY_INFO phyInfo; |
| GT_BOOL autoOn; |
| GT_U16 pageReg; |
| |
| #ifdef GT_USE_MAD |
| if (dev->use_mad==GT_TRUE) |
| return gprtGetDTEDetectDropWait_mad(dev, port, waitTime); |
| #endif |
| |
| DBG_INFO(("gprtSetDTEDropWait 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; |
| } |
| |
| switch(phyInfo.dteType) |
| { |
| case GT_PHY_DTE_TYPE1: |
| if((retVal = hwReadPhyReg(dev,hwPort,22,&u16Data)) != GT_OK) |
| { |
| gtSemGive(dev,dev->phyRegsSem); |
| return retVal; |
| } |
| u16Data = (u16Data >> 12) & 0xF; |
| |
| break; |
| case GT_PHY_DTE_TYPE2: |
| case GT_PHY_DTE_TYPE3: |
| if((retVal = hwReadPhyReg(dev,hwPort,27,&u16Data)) != GT_OK) |
| { |
| gtSemGive(dev,dev->phyRegsSem); |
| return retVal; |
| } |
| u16Data = (u16Data >> 5) & 0xF; |
| |
| break; |
| case GT_PHY_DTE_TYPE4: |
| if(driverPagedAccessStart(dev,hwPort,phyInfo.pageType,&autoOn,&pageReg) != GT_OK) |
| { |
| gtSemGive(dev,dev->phyRegsSem); |
| return GT_FAIL; |
| } |
| |
| if((retVal = hwReadPagedPhyReg(dev,hwPort,0,26,phyInfo.anyPage,&u16Data)) != GT_OK) |
| { |
| gtSemGive(dev,dev->phyRegsSem); |
| return retVal; |
| } |
| u16Data = (u16Data >> 4) & 0xF; |
| |
| if(driverPagedAccessStop(dev,hwPort,phyInfo.pageType,autoOn,pageReg) != GT_OK) |
| { |
| gtSemGive(dev,dev->phyRegsSem); |
| return GT_FAIL; |
| } |
| break; |
| default: |
| gtSemGive(dev,dev->phyRegsSem); |
| return GT_NOT_SUPPORTED; |
| } |
| |
| *waitTime = u16Data; |
| |
| gtSemGive(dev,dev->phyRegsSem); |
| return retVal; |
| } |
| |
| |
| /******************************************************************************* |
| * gprtSetEnergyDetect |
| * |
| * 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 |
| ( |
| 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; |
| GT_BOOL autoOn; |
| GT_U16 pageReg; |
| |
| #ifdef GT_USE_MAD |
| if (dev->use_mad==GT_TRUE) |
| return gprtSetEnergyDetect_mad(dev, port, mode); |
| #endif |
| |
| DBG_INFO(("gprtSetEnergyDetect 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; |
| } |
| |
| if(driverPagedAccessStart(dev,hwPort,phyInfo.pageType,&autoOn,&pageReg) != GT_OK) |
| { |
| gtSemGive(dev,dev->phyRegsSem); |
| return GT_FAIL; |
| } |
| |
| if((retVal = hwSetPagedPhyRegField(dev,hwPort,0,0x10,8,2,phyInfo.anyPage,u16Data)) != GT_OK) |
| { |
| gtSemGive(dev,dev->phyRegsSem); |
| return retVal; |
| } |
| |
| if((retVal = hwPhyReset(dev,hwPort,0xFF)) != GT_OK) |
| { |
| gtSemGive(dev,dev->phyRegsSem); |
| return retVal; |
| } |
| |
| if(driverPagedAccessStop(dev,hwPort,phyInfo.pageType,autoOn,pageReg) != GT_OK) |
| { |
| gtSemGive(dev,dev->phyRegsSem); |
| return GT_FAIL; |
| } |
| } |
| 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((retVal = hwSetPhyRegField(dev,hwPort,0x10,14,1,u16Data)) != GT_OK) |
| { |
| gtSemGive(dev,dev->phyRegsSem); |
| return retVal; |
| } |
| } |
| |
| gtSemGive(dev,dev->phyRegsSem); |
| return retVal; |
| } |
| |
| |
| /******************************************************************************* |
| * gprtGetEnergyDetect |
| * |
| * 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 |
| ( |
| 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; |
| GT_BOOL autoOn; |
| GT_U16 pageReg; |
| |
| #ifdef GT_USE_MAD |
| if (dev->use_mad==GT_TRUE) |
| return gprtGetEnergyDetect_mad(dev, port, mode); |
| #endif |
| |
| DBG_INFO(("gprtGetEnergyDetect 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) |
| { |
| /* read the mode */ |
| |
| if(driverPagedAccessStart(dev,hwPort,phyInfo.pageType,&autoOn,&pageReg) != GT_OK) |
| { |
| gtSemGive(dev,dev->phyRegsSem); |
| return GT_FAIL; |
| } |
| |
| if((retVal = hwGetPagedPhyRegField(dev,hwPort,0,0x10,8,2,phyInfo.anyPage,&u16Data)) != GT_OK) |
| { |
| gtSemGive(dev,dev->phyRegsSem); |
| return retVal; |
| } |
| |
| if(driverPagedAccessStop(dev,hwPort,phyInfo.pageType,autoOn,pageReg) != GT_OK) |
| { |
| gtSemGive(dev,dev->phyRegsSem); |
| return GT_FAIL; |
| } |
| |
| 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 (shouldn't happen).\n")); |
| gtSemGive(dev,dev->phyRegsSem); |
| return GT_FAIL; |
| } |
| |
| } |
| else /* it's a Fast Ethernet device */ |
| { |
| /* read the mode */ |
| if((retVal = hwGetPhyRegField(dev,hwPort,0x10,14,1,&u16Data)) != GT_OK) |
| { |
| gtSemGive(dev,dev->phyRegsSem); |
| return retVal; |
| } |
| |
| switch (u16Data) |
| { |
| case 0: |
| *mode = GT_EDETECT_OFF; |
| break; |
| case 1: |
| *mode = GT_EDETECT_SENSE_PULSE; |
| break; |
| default: |
| DBG_INFO(("Unknown value (shouldn't happen).\n")); |
| gtSemGive(dev,dev->phyRegsSem); |
| return GT_FAIL; |
| } |
| |
| } |
| |
| |
| gtSemGive(dev,dev->phyRegsSem); |
| return retVal; |
| } |
| |
| |
| /******************************************************************************* |
| * gprtSet1000TMasterMode |
| * |
| * 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 |
| ( |
| IN GT_QD_DEV *dev, |
| IN GT_LPORT port, |
| IN GT_1000T_MASTER_SLAVE *mode |
| ) |
| { |
| GT_STATUS retVal; /* Functions return value. */ |
| GT_U8 hwPort; /* the physical port number */ |
| GT_U16 data; |
| GT_PHY_INFO phyInfo; |
| GT_BOOL autoOn; |
| GT_U16 pageReg; |
| |
| #ifdef GT_USE_MAD |
| if (dev->use_mad==GT_TRUE) |
| return gprtSet1000TMasterMode_mad(dev, port, mode); |
| #endif |
| |
| DBG_INFO(("gprtSet1000TMasterMode 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(mode->autoConfig == GT_TRUE) |
| { |
| if(mode->masterPrefer == GT_TRUE) |
| { |
| data = 0x1; |
| } |
| else |
| { |
| data = 0x0; |
| } |
| } |
| else |
| { |
| if(mode->masterPrefer == GT_TRUE) |
| { |
| data = 0x6; |
| } |
| else |
| { |
| data = 0x4; |
| } |
| } |
| |
| if(driverPagedAccessStart(dev,hwPort,phyInfo.pageType,&autoOn,&pageReg) != GT_OK) |
| { |
| gtSemGive(dev,dev->phyRegsSem); |
| return GT_FAIL; |
| } |
| |
| /* Set the Master Mode. */ |
| retVal = hwSetPagedPhyRegField(dev,hwPort,0,9,10,3,phyInfo.anyPage,data); |
| if(retVal != GT_OK) |
| { |
| DBG_INFO(("Failed.\n")); |
| gtSemGive(dev,dev->phyRegsSem); |
| return retVal; |
| } |
| else |
| { |
| DBG_INFO(("OK.\n")); |
| } |
| |
| /* Restart Auto Negotiation */ |
| if((retVal=hwSetPhyRegField(dev,hwPort,QD_PHY_CONTROL_REG,9,1,1)) != GT_OK) |
| { |
| DBG_INFO(("Not able to write Phy Reg(port:%d,offset:%d,data:%#x).\n",hwPort,QD_PHY_CONTROL_REG,1)); |
| gtSemGive(dev,dev->phyRegsSem); |
| return GT_FAIL; |
| } |
| |
| if(driverPagedAccessStop(dev,hwPort,phyInfo.pageType,autoOn,pageReg) != GT_OK) |
| { |
| gtSemGive(dev,dev->phyRegsSem); |
| return GT_FAIL; |
| } |
| |
| gtSemGive(dev,dev->phyRegsSem); |
| return retVal; |
| } |
| |
| |
| /******************************************************************************* |
| * gprtGet1000TMasterMode |
| * |
| * 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 |
| ( |
| IN GT_QD_DEV *dev, |
| IN GT_LPORT port, |
| OUT GT_1000T_MASTER_SLAVE *mode |
| ) |
| { |
| GT_STATUS retVal; /* Functions return value. */ |
| GT_U8 hwPort; /* the physical port number */ |
| GT_U16 data; |
| GT_PHY_INFO phyInfo; |
| GT_BOOL autoOn; |
| GT_U16 pageReg; |
| |
| #ifdef GT_USE_MAD |
| if (dev->use_mad==GT_TRUE) |
| return gprtGet1000TMasterMode_mad(dev, port, mode); |
| #endif |
| |
| DBG_INFO(("gprtGet1000TMasterMode 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(driverPagedAccessStart(dev,hwPort,phyInfo.pageType,&autoOn,&pageReg) != GT_OK) |
| { |
| gtSemGive(dev,dev->phyRegsSem); |
| return GT_FAIL; |
| } |
| |
| /* Set the Master Mode. */ |
| retVal = hwGetPagedPhyRegField(dev,hwPort,0,9,10,3,phyInfo.anyPage,&data); |
| if(retVal != GT_OK) |
| { |
| DBG_INFO(("Failed.\n")); |
| gtSemGive(dev,dev->phyRegsSem); |
| return retVal; |
| } |
| else |
| { |
| DBG_INFO(("OK.\n")); |
| } |
| |
| if(driverPagedAccessStop(dev,hwPort,phyInfo.pageType,autoOn,pageReg) != GT_OK) |
| { |
| gtSemGive(dev,dev->phyRegsSem); |
| return GT_FAIL; |
| } |
| |
| if(data & 0x4) /* Manual Mode */ |
| { |
| mode->autoConfig = GT_FALSE; |
| |
| if(data & 0x2) |
| { |
| mode->masterPrefer = GT_TRUE; |
| } |
| else |
| { |
| mode->masterPrefer = GT_FALSE; |
| } |
| } |
| else /* Auto Mode */ |
| { |
| mode->autoConfig = GT_TRUE; |
| |
| if(data & 0x1) |
| { |
| mode->masterPrefer = GT_TRUE; |
| } |
| else |
| { |
| mode->masterPrefer = GT_FALSE; |
| } |
| } |
| |
| gtSemGive(dev,dev->phyRegsSem); |
| return retVal; |
| } |
| |
| /******************************************************************************* |
| * gprtGetPhyLinkStatus |
| * |
| * 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 |
| ( |
| IN GT_QD_DEV *dev, |
| IN GT_LPORT port, |
| IN GT_BOOL *linkStatus |
| ) |
| { |
| |
| GT_STATUS retVal; /* Functions return value. */ |
| GT_U8 hwPort; /* the physical port number */ |
| GT_U16 u16Data; |
| GT_PHY_INFO phyInfo; |
| |
| #ifdef GT_USE_MAD |
| if (dev->use_mad==GT_TRUE) |
| return gprtGetPhyLinkStatus_mad(dev, port, linkStatus); |
| #endif |
| |
| DBG_INFO(("gprtGetPhyLinkStatus 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((retVal=hwGetPhyRegField(dev,hwPort,17,10,1,&u16Data)) != GT_OK) |
| { |
| gtSemGive(dev,dev->phyRegsSem); |
| return retVal; |
| } |
| |
| BIT_2_BOOL(u16Data,*linkStatus); |
| |
| gtSemGive(dev,dev->phyRegsSem); |
| return retVal; |
| } |
| |
| |
| /******************************************************************************* |
| * gprtSetPktGenEnable |
| * |
| * 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 |
| ( |
| IN GT_QD_DEV *dev, |
| IN GT_LPORT port, |
| IN GT_BOOL en, |
| IN GT_PG *pktInfo |
| ) |
| { |
| |
| GT_STATUS retVal; /* Functions return value. */ |
| GT_U8 hwPort; /* the physical port number */ |
| GT_U16 data; |
| GT_BOOL link; |
| GT_PHY_INFO phyInfo; |
| GT_U8 page,reg, offset, len; |
| GT_BOOL autoOn; |
| GT_U16 pageReg; |
| |
| #ifdef GT_USE_MAD |
| if (dev->use_mad==GT_TRUE) |
| return gprtSetPktGenEnable_mad(dev, port, en, pktInfo); |
| #endif |
| |
| DBG_INFO(("gprtSetPktGenEnable 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; |
| } |
| |
| switch (phyInfo.pktGenType) |
| { |
| case GT_PHY_PKTGEN_TYPE1: /* 30_18.5:2 */ |
| page = 18; |
| reg = 30; |
| offset = 2; |
| break; |
| case GT_PHY_PKTGEN_TYPE2: /* 16_6.3:0 */ |
| page = 6; |
| reg = 16; |
| offset = 0; |
| break; |
| case GT_PHY_PKTGEN_TYPE3: /* 25.3:0 */ |
| page = 0; |
| reg = 25; |
| offset = 0; |
| break; |
| default: |
| DBG_INFO(("Unknown PKTGEN Type.\n")); |
| gtSemGive(dev,dev->phyRegsSem); |
| return GT_FAIL; |
| } |
| |
| if (en) |
| { |
| if((retVal = gprtGetPhyLinkStatus(dev,port,&link)) != GT_OK) |
| { |
| gtSemGive(dev,dev->phyRegsSem); |
| return GT_FAIL; |
| } |
| |
| if (link == GT_FALSE) |
| { |
| DBG_INFO(("Link should be on to run Packet Generator.\n")); |
| gtSemGive(dev,dev->phyRegsSem); |
| return GT_FAIL; |
| } |
| |
| data = 0x8; |
| |
| if (pktInfo->payload == GT_PG_PAYLOAD_5AA5) |
| data |= 0x4; |
| |
| if (pktInfo->length == GT_PG_LENGTH_1514) |
| data |= 0x2; |
| |
| if (pktInfo->tx == GT_PG_TX_ERROR) |
| data |= 0x1; |
| |
| len = 4; |
| } |
| else |
| { |
| data = 0; |
| len = 1; |
| offset += 3; |
| } |
| |
| if(driverPagedAccessStart(dev,hwPort,phyInfo.pageType,&autoOn,&pageReg) != GT_OK) |
| { |
| gtSemGive(dev,dev->phyRegsSem); |
| return GT_FAIL; |
| } |
| |
| if((retVal=hwSetPagedPhyRegField(dev,hwPort, |
| page,reg,offset,len,phyInfo.anyPage,data)) != GT_OK) |
| { |
| gtSemGive(dev,dev->phyRegsSem); |
| return retVal; |
| } |
| |
| if(driverPagedAccessStop(dev,hwPort,phyInfo.pageType,autoOn,pageReg) != GT_OK) |
| { |
| gtSemGive(dev,dev->phyRegsSem); |
| return GT_FAIL; |
| } |
| |
| gtSemGive(dev,dev->phyRegsSem); |
| return retVal; |
| } |
| |
| |
| /******************************************************************************* |
| * gprtGetPhyReg |
| * |
| * DESCRIPTION: |
| * This routine reads Phy Registers. |
| * |
| * INPUTS: |
| * port - The logical port number, |
| * 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 |
| ( |
| IN GT_QD_DEV *dev, |
| IN GT_LPORT port, |
| IN GT_U32 regAddr, |
| OUT GT_U16 *data |
| ) |
| { |
| GT_U16 u16Data; /* The register's read data. */ |
| GT_U8 hwPort; /* the physical port number */ |
| |
| #ifdef GT_USE_MAD |
| if (dev->use_mad==GT_TRUE) |
| return gprtGetPhyReg_mad(dev, port, regAddr, data); |
| #endif |
| |
| DBG_INFO(("gprtGetPhyReg Called.\n")); |
| |
| /* hwPort = GT_LPORT_2_PHY(port); */ |
| hwPort = qdLong2Char(port); |
| |
| gtSemTake(dev,dev->phyRegsSem,OS_WAIT_FOREVER); |
| |
| /* Get Phy Register. */ |
| if(hwReadPhyReg(dev,hwPort,(GT_U8)regAddr,&u16Data) != GT_OK) |
| { |
| DBG_INFO(("Failed.\n")); |
| gtSemGive(dev,dev->phyRegsSem); |
| return GT_FAIL; |
| } |
| |
| *data = u16Data; |
| |
| gtSemGive(dev,dev->phyRegsSem); |
| return GT_OK; |
| } |
| |
| /******************************************************************************* |
| * gprtSetPhyReg |
| * |
| * DESCRIPTION: |
| * This routine writes Phy Registers. |
| * |
| * INPUTS: |
| * port - The logical port number, |
| * 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 |
| ( |
| IN GT_QD_DEV *dev, |
| IN GT_LPORT port, |
| IN GT_U32 regAddr, |
| IN GT_U16 data |
| ) |
| { |
| GT_U8 hwPort; /* the physical port number */ |
| |
| #ifdef GT_USE_MAD |
| if (dev->use_mad==GT_TRUE) |
| return gprtSetPhyReg_mad(dev, port, regAddr, data); |
| #endif |
| |
| DBG_INFO(("gprtSetPhyReg Called.\n")); |
| |
| /* hwPort = GT_LPORT_2_PHY(port); */ |
| hwPort = qdLong2Char(port); |
| |
| gtSemTake(dev,dev->phyRegsSem,OS_WAIT_FOREVER); |
| |
| /* Write to Phy Register */ |
| if(hwWritePhyReg(dev,hwPort,(GT_U8)regAddr,data) != GT_OK) |
| { |
| DBG_INFO(("Failed.\n")); |
| gtSemGive(dev,dev->phyRegsSem); |
| return GT_FAIL; |
| } |
| |
| gtSemGive(dev,dev->phyRegsSem); |
| return GT_OK; |
| } |
| |
| |
| |
| /******************************************************************************* |
| * gprtGetPagedPhyReg |
| * |
| * 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 |
| ( |
| 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_BOOL autoOn; |
| GT_U16 pageReg; |
| GT_U8 hwPort; |
| |
| #ifdef GT_USE_MAD |
| if (dev->use_mad==GT_TRUE) |
| return gprtGetPagedPhyReg_mad(dev, port, regAddr, page, data); |
| #endif |
| |
| 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(driverPagedAccessStart(dev,hwPort,phyInfo.pageType,&autoOn,&pageReg) != GT_OK) |
| { |
| gtSemGive(dev,dev->phyRegsSem); |
| return GT_FAIL; |
| } |
| |
| if(hwReadPagedPhyReg(dev,hwPort,(GT_U8)page, |
| (GT_U8)regAddr,0,data) != GT_OK) |
| { |
| gtSemGive(dev,dev->phyRegsSem); |
| return GT_FAIL; |
| } |
| |
| if(driverPagedAccessStop(dev,hwPort,phyInfo.pageType,autoOn,pageReg) != GT_OK) |
| { |
| gtSemGive(dev,dev->phyRegsSem); |
| return GT_FAIL; |
| } |
| |
| gtSemGive(dev,dev->phyRegsSem); |
| return GT_OK; |
| } |
| |
| /******************************************************************************* |
| * gprtSetPagedPhyReg |
| * |
| * 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 |
| ( |
| IN GT_QD_DEV *dev, |
| IN GT_U32 port, |
| IN GT_U32 regAddr, |
| IN GT_U32 page, |
| IN GT_U16 data |
| ) |
| { |
| GT_PHY_INFO phyInfo; |
| GT_BOOL autoOn; |
| GT_U16 pageReg; |
| GT_U8 hwPort; |
| |
| #ifdef GT_USE_MAD |
| if (dev->use_mad==GT_TRUE) |
| return gprtSetPagedPhyReg_mad(dev, port, regAddr, page, data); |
| #endif |
| |
| 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(driverPagedAccessStart(dev,hwPort,phyInfo.pageType,&autoOn,&pageReg) != GT_OK) |
| { |
| gtSemGive(dev,dev->phyRegsSem); |
| return GT_FAIL; |
| } |
| |
| if(hwWritePagedPhyReg(dev,hwPort,(GT_U8)page, |
| (GT_U8)regAddr,0,data) != GT_OK) |
| { |
| gtSemGive(dev,dev->phyRegsSem); |
| return GT_FAIL; |
| } |
| |
| if(driverPagedAccessStop(dev,hwPort,phyInfo.pageType,autoOn,pageReg) != GT_OK) |
| { |
| gtSemGive(dev,dev->phyRegsSem); |
| return GT_FAIL; |
| } |
| |
| gtSemGive(dev,dev->phyRegsSem); |
| return GT_OK; |
| } |