| #include <Copyright.h>
|
| /*******************************************************************************
|
| * gtAdvVct.c
|
| *
|
| * DESCRIPTION:
|
| * API for Marvell Virtual Cable Tester.
|
| *
|
| * DEPENDENCIES:
|
| * None.
|
| *
|
| * FILE REVISION NUMBER:
|
| * $Revision: 1 $
|
| *******************************************************************************/
|
| #include <msApi.h>
|
| #include <gtVct.h>
|
| #include <gtDrvConfig.h>
|
| #include <gtDrvSwRegs.h>
|
| #include <gtHwCntl.h>
|
| #include <gtSem.h>
|
|
|
| #define GT_LOOKUP_TABLE_ENTRY 128 /* 73 */
|
|
|
| #define GT_ADV_VCT_ACCEPTABLE_SHORT_CABLE 11
|
|
|
| static GT_U8 tbl_1181[GT_LOOKUP_TABLE_ENTRY] =
|
| { 2, 4, 8, 14, 18, 20, 25, 30, 33, 36,
|
| 39, 42, 46, 48, 51, 54, 57, 59, 62, 64,
|
| 66, 69, 71, 73, 75, 77, 80, 81, 83, 85,
|
| 87, 88, 90, 93, 95, 97, 98,100,101,103,
|
| 104,106,106,107,109,110,111,113,114,115,
|
| 116,118,119,120,121,122,124,125,126,127,
|
| 128,129,130,131,132,133,134,135,136,137,
|
| 138,139,140};
|
|
|
| static GT_U8 tbl_1111[GT_LOOKUP_TABLE_ENTRY] =
|
| { 0, 2, 4, 5, 6, 9, 13, 17, 20, 23,
|
| 27, 30, 33, 35, 38, 41, 43, 46, 48, 51,
|
| 53, 55, 58, 60, 62, 64, 66, 68, 70, 72,
|
| 73, 75, 77, 79, 80, 82, 84, 85, 87, 88,
|
| 90, 91, 93, 94, 96, 97, 98,100,101,102,
|
| 104,105,106,107,109,110,111,112,113,114,
|
| 116,117,118,119,120,121,122,123,124,125,
|
| 126,127,128,129,130,131,132,133,134,134};
|
|
|
| static GT_U8 tbl_1112[GT_LOOKUP_TABLE_ENTRY] = /* from 17*/
|
| { 0, 4, 8, 11, 14, 18, 21, 24, 28, 31,
|
| 34, 37, 39, 42, 44, 47, 49, 52, 54, 56,
|
| 58, 60, 62, 64, 66, 68, 70, 72, 74, 75,
|
| 77, 79, 80, 82, 83, 85, 87, 88, 89, 91,
|
| 92, 94, 95, 96, 98, 99,100,101,103,104,
|
| 105,106,107,108,109,111,112,113,114,115,
|
| 116,117,118,119,120,121,122,123,124,124,
|
| 125,126,127,128,129,130,131,131,132,133,
|
| 134,135,135,136,137,138,139,139,140,141,
|
| 142,142,143,144,144,145,146,147,147,148};
|
|
|
| static GT_U8 tbl_1116[GT_LOOKUP_TABLE_ENTRY] = /* from 16*/
|
| { 2, 4, 8, 14, 18, 20, 25, 30, 33, 36,
|
| 39, 42, 46, 48, 51, 54, 57, 59, 62, 64,
|
| 66, 69, 71, 73, 75, 77, 80, 81, 83, 85,
|
| 87, 88, 90, 93, 95, 97, 98, 100, 101, 103,
|
| 104,106,106,107,109,110,111,113,114,115,
|
| 116,118,119,120,121,122,124,125,126,127,
|
| 128,129,130,131,132,133,134,135,136,137,
|
| 138,139,140};
|
|
|
| static GT_U8 tbl_1240[GT_LOOKUP_TABLE_ENTRY] =
|
| { 1, 2, 5, 10, 13, 15, 18, 22, 26, 30, |
| 33, 35, 38, 40, 43, 45, 48, 51, 53, 55, |
| 58, 60, 63, 65, 68, 69, 70, 71, 73, 75, |
| 77, 79, 80, 81, 82, 83, 85, 87, 88, 90, |
| 91, 92, 93, 95, 97, 98,100,101,102,103, |
| 105,106,107,108,109,110,111,112,113,114, |
| 115,116,117,118,119,120,121,122,123,124, |
| 125,126,127,128,129,130};
|
|
|
|
|
| /*******************************************************************************
|
| * getDetailedAdvVCTResult
|
| *
|
| * DESCRIPTION:
|
| * This routine differenciate Open/Short from Impedance mismatch.
|
| *
|
| * INPUTS:
|
| * amp - amplitude
|
| * len - distance to fault
|
| * vctResult - test result
|
| * (Impedance mismatch, either > 115 ohms, or < 85 ohms)
|
| *
|
| * OUTPUTS:
|
| *
|
| * RETURNS:
|
| * GT_ADV_VCT_STATUS
|
| *
|
| * COMMENTS:
|
| * This routine assumes test result is not normal nor cross pair short.
|
| *
|
| *******************************************************************************/
|
| static
|
| GT_ADV_VCT_STATUS getDetailedAdvVCTResult
|
| (
|
| IN GT_U32 devType,
|
| IN GT_U32 amp,
|
| IN GT_U32 len,
|
| IN GT_ADV_VCT_STATUS result
|
| )
|
| {
|
| GT_ADV_VCT_STATUS vctResult;
|
| GT_BOOL update = GT_FALSE;
|
|
|
| DBG_INFO(("getDetailedAdvVCTResult Called.\n"));
|
| |
| if (devType == GT_PHY_ADV_VCT_TYPE2)
|
| {
|
| if(len < 10)
|
| {
|
| if(amp > 54) /* 90 x 0.6 */
|
| update = GT_TRUE;
|
| }
|
| else if(len < 50)
|
| {
|
| if(amp > 42) /* 70 x 0.6 */
|
| update = GT_TRUE;
|
| }
|
| else if(len < 110)
|
| {
|
| if(amp > 30) /* 50 x 0.6 */
|
| update = GT_TRUE;
|
| }
|
| else if(len < 140)
|
| {
|
| if(amp > 24) /* 40 x 0.6 */
|
| update = GT_TRUE;
|
| }
|
| else
|
| {
|
| if(amp > 18) /* 30 x 0.6 */
|
| update = GT_TRUE;
|
| }
|
| }
|
| else
|
| {
|
| if(len < 10)
|
| {
|
| if(amp > 90)
|
| update = GT_TRUE;
|
| }
|
| else if(len < 50)
|
| {
|
| if(amp > 70)
|
| update = GT_TRUE;
|
| }
|
| else if(len < 110)
|
| {
|
| if(amp > 50)
|
| update = GT_TRUE;
|
| }
|
| else if(len < 140)
|
| {
|
| if(amp > 40)
|
| update = GT_TRUE;
|
| }
|
| else
|
| {
|
| if(amp > 30)
|
| update = GT_TRUE;
|
| }
|
| }
|
|
|
|
|
| switch (result)
|
| {
|
| case GT_ADV_VCT_IMP_GREATER_THAN_115:
|
| if(update)
|
| vctResult = GT_ADV_VCT_OPEN;
|
| else
|
| vctResult = result;
|
| break;
|
| case GT_ADV_VCT_IMP_LESS_THAN_85:
|
| if(update)
|
| vctResult = GT_ADV_VCT_SHORT;
|
| else
|
| vctResult = result;
|
| break;
|
| default:
|
| vctResult = result;
|
| break;
|
| }
|
|
|
| return vctResult;
|
| }
|
|
|
| /*******************************************************************************
|
| * analizeAdvVCTResult
|
| *
|
| * DESCRIPTION:
|
| * This routine analize the Advanced VCT result.
|
| *
|
| * INPUTS:
|
| * channel - channel number where test was run
|
| * crossChannelReg - register values after the test is completed
|
| * mode - use formula for normal cable case
|
| *
|
| * OUTPUTS:
|
| * cableStatus - analized test result.
|
| *
|
| * RETURNS:
|
| * -1, or distance to fault
|
| *
|
| * COMMENTS:
|
| * None.
|
| *
|
| *******************************************************************************/
|
| static
|
| GT_16 analizeAdvVCTNoCrosspairResult
|
| (
|
| IN GT_U32 devType,
|
| IN int channel,
|
| IN GT_U16 *crossChannelReg,
|
| IN GT_BOOL isShort,
|
| OUT GT_ADV_CABLE_STATUS *cableStatus
|
| )
|
| {
|
| int len;
|
| GT_16 dist2fault;
|
| GT_ADV_VCT_STATUS vctResult = GT_ADV_VCT_NORMAL;
|
|
|
| DBG_INFO(("analizeAdvVCTNoCrosspairResult Called.\n"));
|
| DBG_INFO(("analizeAdvVCTNoCrosspairResult chan %d reg data %x\n", channel, crossChannelReg[channel]));
|
|
|
| dist2fault = -1;
|
|
|
| /* check if test is failed */
|
| if(IS_VCT_FAILED(crossChannelReg[channel]))
|
| {
|
| cableStatus->cableStatus[channel] = GT_ADV_VCT_FAIL;
|
| return dist2fault;
|
| }
|
|
|
| /* Check if fault detected */
|
| if(IS_ZERO_AMPLITUDE(crossChannelReg[channel]))
|
| {
|
| cableStatus->cableStatus[channel] = GT_ADV_VCT_NORMAL;
|
| return dist2fault;
|
| }
|
|
|
| /* find out test result by reading Amplitude */
|
| if(IS_POSITIVE_AMPLITUDE(crossChannelReg[channel]))
|
| {
|
| vctResult = GT_ADV_VCT_IMP_GREATER_THAN_115;
|
| }
|
| else
|
| {
|
| vctResult = GT_ADV_VCT_IMP_LESS_THAN_85;
|
| }
|
|
|
| /*
|
| * now, calculate the distance for GT_ADV_VCT_IMP_GREATER_THAN_115 and
|
| * GT_ADV_VCT_IMP_LESS_THAN_85
|
| */
|
| switch (vctResult)
|
| {
|
| case GT_ADV_VCT_IMP_GREATER_THAN_115:
|
| case GT_ADV_VCT_IMP_LESS_THAN_85:
|
| if(!isShort)
|
| {
|
| len = (int)GT_ADV_VCT_CALC(crossChannelReg[channel] & 0xFF);
|
| }
|
| else
|
| {
|
| len = (int)GT_ADV_VCT_CALC_SHORT(crossChannelReg[channel] & 0xFF);
|
| }
|
| DBG_INFO(("@@@@ no cross len %d\n", len));
|
| |
| if (len < 0)
|
| len = 0;
|
| cableStatus->u[channel].dist2fault = (GT_16)len;
|
| vctResult = getDetailedAdvVCTResult( |
| devType, |
| GET_AMPLITUDE(crossChannelReg[channel]),
|
| len,
|
| vctResult);
|
| dist2fault = (GT_16)len;
|
| break;
|
| default:
|
| break;
|
| }
|
|
|
| cableStatus->cableStatus[channel] = vctResult;
|
|
|
| return dist2fault;
|
| }
|
|
|
|
|
| static
|
| GT_16 analizeAdvVCTResult
|
| (
|
| IN GT_U32 devType,
|
| IN int channel,
|
| IN GT_U16 *crossChannelReg,
|
| IN GT_BOOL isShort,
|
| OUT GT_ADV_CABLE_STATUS *cableStatus
|
| )
|
| {
|
| int i, len;
|
| GT_16 dist2fault;
|
| GT_ADV_VCT_STATUS vctResult = GT_ADV_VCT_NORMAL;
|
|
|
| DBG_INFO(("analizeAdvVCTResult(Crosspair) chan %d reg data %x\n", channel, crossChannelReg[channel]));
|
| DBG_INFO(("analizeAdvVCTResult Called.\n"));
|
|
|
| dist2fault = -1;
|
|
|
| /* check if test is failed */
|
| for (i=0; i<GT_MDI_PAIR_NUM; i++)
|
| {
|
| if(IS_VCT_FAILED(crossChannelReg[i]))
|
| {
|
| cableStatus->cableStatus[channel] = GT_ADV_VCT_FAIL;
|
| return dist2fault;
|
| }
|
| }
|
|
|
| /* find out test result by reading Amplitude */
|
| for (i=0; i<GT_MDI_PAIR_NUM; i++)
|
| {
|
| if (i == channel)
|
| {
|
| if(!IS_ZERO_AMPLITUDE(crossChannelReg[i]))
|
| {
|
| if(IS_POSITIVE_AMPLITUDE(crossChannelReg[i]))
|
| {
|
| vctResult = GT_ADV_VCT_IMP_GREATER_THAN_115;
|
| }
|
| else
|
| {
|
| vctResult = GT_ADV_VCT_IMP_LESS_THAN_85;
|
| }
|
| }
|
| continue;
|
| }
|
|
|
| if(IS_ZERO_AMPLITUDE(crossChannelReg[i]))
|
| continue;
|
|
|
| vctResult = GT_ADV_VCT_CROSS_PAIR_SHORT;
|
| break;
|
| }
|
|
|
| /* if it is cross pair short, check the distance for each channel */
|
| if(vctResult == GT_ADV_VCT_CROSS_PAIR_SHORT)
|
| {
|
| cableStatus->cableStatus[channel] = GT_ADV_VCT_CROSS_PAIR_SHORT;
|
| for (i=0; i<GT_MDI_PAIR_NUM; i++)
|
| {
|
| if(IS_ZERO_AMPLITUDE(crossChannelReg[i]))
|
| {
|
| cableStatus->u[channel].crossShort.channel[i] = GT_FALSE;
|
| cableStatus->u[channel].crossShort.dist2fault[i] = 0;
|
| continue;
|
| }
|
|
|
| cableStatus->u[channel].crossShort.channel[i] = GT_TRUE;
|
| if(!isShort)
|
| len = (int)GT_ADV_VCT_CALC(crossChannelReg[i] & 0xFF);
|
| else
|
| len = (int)GT_ADV_VCT_CALC_SHORT(crossChannelReg[i] & 0xFF);
|
| DBG_INFO(("@@@@ len %d\n", len));
|
| |
| if (len < 0)
|
| len = 0;
|
| cableStatus->u[channel].crossShort.dist2fault[i] = (GT_16)len;
|
| dist2fault = (GT_16)len;
|
| }
|
|
|
| return dist2fault;
|
| }
|
|
|
| /*
|
| * now, calculate the distance for GT_ADV_VCT_IMP_GREATER_THAN_115 and
|
| * GT_ADV_VCT_IMP_LESS_THAN_85
|
| */
|
| switch (vctResult)
|
| {
|
| case GT_ADV_VCT_IMP_GREATER_THAN_115:
|
| case GT_ADV_VCT_IMP_LESS_THAN_85:
|
| if(isShort)
|
| len = (int)GT_ADV_VCT_CALC(crossChannelReg[channel] & 0xFF);
|
| else
|
| len = (int)GT_ADV_VCT_CALC_SHORT(crossChannelReg[channel] & 0xFF);
|
| if (len < 0)
|
| len = 0;
|
| cableStatus->u[channel].dist2fault = (GT_16)len;
|
| vctResult = getDetailedAdvVCTResult(
|
| devType,
|
| GET_AMPLITUDE(crossChannelReg[channel]),
|
| len,
|
| vctResult);
|
| dist2fault = (GT_16)len;
|
| break;
|
| default:
|
| break;
|
| }
|
|
|
| cableStatus->cableStatus[channel] = vctResult;
|
|
|
| return dist2fault;
|
| }
|
|
|
|
|
| /*******************************************************************************
|
| * runAdvCableTest_1181
|
| *
|
| * DESCRIPTION:
|
| * This routine performs the advanced virtual cable test for the PHY with
|
| * multiple page mode and returns the the status per MDIP/N.
|
| *
|
| * INPUTS:
|
| * port - logical port number.
|
| * mode - GT_TRUE, if short cable detect is required
|
| * GT_FALSE, otherwise
|
| *
|
| * OUTPUTS:
|
| * cableStatus - the port copper cable status.
|
| * tooShort - if known distance to fault is too short
|
| *
|
| * RETURNS:
|
| * GT_OK - on success
|
| * GT_FAIL - on error
|
| *
|
| * COMMENTS:
|
| * None.
|
| *
|
| *******************************************************************************/
|
| static
|
| GT_STATUS runAdvCableTest_1181
|
| (
|
| IN GT_QD_DEV *dev,
|
| IN GT_U8 hwPort,
|
| IN GT_PHY_INFO *phyInfo,
|
| IN GT_BOOL mode,
|
| OUT GT_ADV_CABLE_STATUS *cableStatus,
|
| OUT GT_BOOL *tooShort
|
| )
|
| {
|
| GT_STATUS retVal;
|
| GT_U16 u16Data;
|
| GT_U16 crossChannelReg[GT_MDI_PAIR_NUM];
|
| int i,j;
|
| GT_16 dist2fault;
|
|
|
| VCT_REGISTER regList[GT_MDI_PAIR_NUM][GT_MDI_PAIR_NUM] = {
|
| {{8,16},{8,17},{8,18},{8,19}}, /* channel 0 */
|
| {{8,24},{8,25},{8,26},{8,27}}, /* channel 1 */
|
| {{9,16},{9,17},{9,18},{9,19}}, /* channel 2 */
|
| {{9,24},{9,25},{9,26},{9,27}} /* channel 3 */
|
| };
|
|
|
| DBG_INFO(("runAdvCableTest_1181 Called.\n"));
|
|
|
| if (mode)
|
| *tooShort = GT_FALSE;
|
|
|
| /*
|
| * start Advanced Virtual Cable Tester
|
| */
|
| if((retVal = hwSetPagedPhyRegField(
|
| dev,hwPort,8,QD_REG_ADV_VCT_CONTROL_8,15,1,phyInfo->anyPage,1)) != GT_OK)
|
| {
|
| DBG_INFO(("Writing to paged phy reg failed.\n"));
|
| return retVal;
|
| }
|
|
|
| /*
|
| * loop until test completion and result is valid
|
| */
|
| do
|
| {
|
| if((retVal = hwReadPagedPhyReg(
|
| dev,hwPort,8,QD_REG_ADV_VCT_CONTROL_8,phyInfo->anyPage,&u16Data)) != GT_OK)
|
| {
|
| DBG_INFO(("Reading from paged phy reg failed.\n"));
|
| return retVal;
|
| }
|
| } while(u16Data & 0x8000);
|
|
|
| DBG_INFO(("Page 8 of Reg20 after test : %0#x.\n", u16Data));
|
|
|
| for (i=0; i<GT_MDI_PAIR_NUM; i++)
|
| {
|
| /*
|
| * read the test result for the cross pair against selected MDI Pair
|
| */
|
| for (j=0; j<GT_MDI_PAIR_NUM; j++)
|
| {
|
| if((retVal = hwReadPagedPhyReg(
|
| dev,hwPort,
|
| regList[i][j].page,
|
| regList[i][j].regOffset, |
| phyInfo->anyPage,
|
| &crossChannelReg[j])) != GT_OK)
|
| {
|
| DBG_INFO(("Reading from paged phy reg failed.\n"));
|
| return retVal;
|
| }
|
| }
|
|
|
| /*
|
| * analyze the test result for RX Pair
|
| */
|
| dist2fault = analizeAdvVCTResult(phyInfo->vctType, i, crossChannelReg, mode, cableStatus);
|
|
|
| if(mode)
|
| {
|
| if ((dist2fault>=0) && (dist2fault<GT_ADV_VCT_ACCEPTABLE_SHORT_CABLE))
|
| {
|
| DBG_INFO(("Distance to Fault is too Short. So, rerun after changing pulse width\n"));
|
| *tooShort = GT_TRUE;
|
| break;
|
| }
|
| }
|
| }
|
|
|
| return GT_OK;
|
| }
|
|
|
| |
| |
| /*******************************************************************************
|
| * getAdvCableStatus_1181
|
| *
|
| * DESCRIPTION:
|
| * This routine performs the virtual cable test for the PHY with
|
| * multiple page mode and returns the the status per MDIP/N.
|
| *
|
| * INPUTS:
|
| * port - logical port number.
|
| * mode - advance VCT mode (either First Peak or Maximum Peak)
|
| *
|
| * OUTPUTS:
|
| * cableStatus - the port copper cable status.
|
| *
|
| * RETURNS:
|
| * GT_OK - on success
|
| * GT_FAIL - on error
|
| *
|
| * COMMENTS:
|
| * None.
|
| *
|
| *******************************************************************************/
|
| static
|
| GT_STATUS getAdvCableStatus_1181
|
| (
|
| IN GT_QD_DEV *dev,
|
| IN GT_U8 hwPort,
|
| IN GT_PHY_INFO *phyInfo,
|
| IN GT_ADV_VCT_MODE mode,
|
| OUT GT_ADV_CABLE_STATUS *cableStatus
|
| )
|
| {
|
| GT_STATUS retVal;
|
| GT_U16 orgPulse, u16Data;
|
| GT_BOOL flag, tooShort;
|
|
|
| flag = GT_TRUE;
|
|
|
| /*
|
| * set Adv VCT Mode
|
| */
|
| switch (mode.mode)
|
| {
|
| case GT_ADV_VCT_FIRST_PEAK:
|
| break;
|
| case GT_ADV_VCT_MAX_PEAK:
|
| break;
|
| default:
|
| DBG_INFO(("Unknown Advanced VCT Mode.\n"));
|
| return GT_BAD_PARAM;
|
| }
|
|
|
| u16Data = (mode.mode<<6) | (mode.peakDetHyst) | (mode.sampleAvg<<8);
|
| if((retVal = hwSetPagedPhyRegField(
|
| dev,hwPort,8,QD_REG_ADV_VCT_CONTROL_8,0,11,phyInfo->anyPage,u16Data)) != GT_OK)
|
| {
|
| DBG_INFO(("Writing to paged phy reg failed.\n"));
|
| return retVal;
|
| }
|
|
|
| if (flag)
|
| {
|
| /* save original Pulse Width */
|
| if((retVal = hwGetPagedPhyRegField(
|
| dev,hwPort,9,23,10,2,phyInfo->anyPage,&orgPulse)) != GT_OK)
|
| {
|
| DBG_INFO(("Reading paged phy reg failed.\n"));
|
| return retVal;
|
| }
|
|
|
| /* set the Pulse Width with default value */
|
| if (orgPulse != 0)
|
| {
|
| if((retVal = hwSetPagedPhyRegField(
|
| dev,hwPort,9,23,10,2,phyInfo->anyPage,0)) != GT_OK)
|
| {
|
| DBG_INFO(("Writing to paged phy reg failed.\n"));
|
| return retVal;
|
| }
|
| }
|
| }
|
|
|
| if((retVal=runAdvCableTest_1181(dev,hwPort,phyInfo,flag,cableStatus,&tooShort)) != GT_OK)
|
| {
|
| DBG_INFO(("Running advanced VCT failed.\n"));
|
| return retVal;
|
| }
|
|
|
| if (flag)
|
| {
|
| if(tooShort)
|
| {
|
| /* set the Pulse Width with minimum width */
|
| if((retVal = hwSetPagedPhyRegField(
|
| dev,hwPort,9,23,10,2,phyInfo->anyPage,3)) != GT_OK)
|
| {
|
| DBG_INFO(("Writing to paged phy reg failed.\n"));
|
| return retVal;
|
| }
|
|
|
| /* run the Adv VCT again */
|
| if((retVal=runAdvCableTest_1181(dev,hwPort,phyInfo,GT_FALSE,cableStatus,&tooShort)) != GT_OK)
|
| {
|
| DBG_INFO(("Running advanced VCT failed.\n"));
|
| return retVal;
|
| }
|
|
|
| }
|
|
|
| /* set the Pulse Width back to the original value */
|
| if((retVal = hwSetPagedPhyRegField(
|
| dev,hwPort,9,23,10,2,phyInfo->anyPage,orgPulse)) != GT_OK)
|
| {
|
| DBG_INFO(("Writing to paged phy reg failed.\n"));
|
| return retVal;
|
| }
|
|
|
| }
|
|
|
| return GT_OK;
|
| }
|
| |
|
|
| static
|
| GT_STATUS runAdvCableTest_1116_set
|
| (
|
| IN GT_QD_DEV *dev,
|
| IN GT_U8 hwPort,
|
| IN GT_PHY_INFO *phyInfo,
|
| IN GT_32 channel,
|
| IN GT_ADV_VCT_TRANS_CHAN_SEL crosspair
|
| )
|
| {
|
| GT_STATUS retVal;
|
|
|
| DBG_INFO(("runAdvCableTest_1116_set Called.\n"));
|
| |
| /*
|
| * start Advanced Virtual Cable Tester
|
| */
|
| if((retVal = hwSetPagedPhyRegField(
|
| dev,hwPort,5,QD_REG_ADV_VCT_CONTROL_5,15,1,phyInfo->anyPage,1)) != GT_OK)
|
| {
|
| DBG_INFO(("Writing to paged phy reg failed.\n"));
|
| return retVal;
|
| }
|
|
|
| return GT_OK;
|
| }
|
|
|
| static
|
| GT_STATUS runAdvCableTest_1116_check
|
| (
|
| IN GT_QD_DEV *dev,
|
| IN GT_U8 hwPort,
|
| IN GT_PHY_INFO *phyInfo
|
| )
|
| {
|
| GT_STATUS retVal;
|
| GT_U16 u16Data;
|
| |
| /*
|
| * loop until test completion and result is valid
|
| */ |
| do {
|
| if((retVal = hwReadPagedPhyReg(
|
| dev,hwPort,5,QD_REG_ADV_VCT_CONTROL_5,phyInfo->anyPage,&u16Data)) != GT_OK)
|
| {
|
| DBG_INFO(("Reading from paged phy reg failed.\n"));
|
| return retVal;
|
| } |
| } while (u16Data & 0x8000); |
|
|
| return GT_OK;
|
| }
|
|
|
| static
|
| GT_STATUS runAdvCableTest_1116_get
|
| (
|
| IN GT_QD_DEV *dev,
|
| IN GT_U8 hwPort,
|
| IN GT_PHY_INFO *phyInfo,
|
| IN GT_ADV_VCT_TRANS_CHAN_SEL crosspair,
|
| IN GT_32 channel,
|
| OUT GT_ADV_CABLE_STATUS *cableStatus,
|
| OUT GT_BOOL *tooShort
|
| )
|
| {
|
| GT_STATUS retVal;
|
| GT_U16 u16Data;
|
| GT_U16 crossChannelReg[GT_MDI_PAIR_NUM];
|
| int j;
|
| GT_16 dist2fault;
|
| GT_BOOL mode;
|
| GT_BOOL localTooShort[GT_MDI_PAIR_NUM];
|
|
|
| VCT_REGISTER regList[GT_MDI_PAIR_NUM] = { {5,16},{5,17},{5,18},{5,19} };
|
| |
| mode = GT_TRUE;
|
|
|
| DBG_INFO(("runAdvCableTest_1116_get Called.\n"));
|
|
|
| if ((retVal = hwReadPagedPhyReg(
|
| dev,hwPort,5,QD_REG_ADV_VCT_CONTROL_5,phyInfo->anyPage,&u16Data)) != GT_OK)
|
| {
|
| DBG_INFO(("Reading from paged phy reg failed.\n"));
|
| return retVal;
|
| }
|
|
|
| DBG_INFO(("Page 5 of Reg23 after test : %0#x.\n", u16Data));
|
|
|
| /*
|
| * read the test result for the cross pair against selected MDI Pair
|
| */
|
| for (j=0; j<GT_MDI_PAIR_NUM; j++)
|
| {
|
| if((retVal = hwReadPagedPhyReg(
|
| dev,hwPort,
|
| regList[j].page,
|
| regList[j].regOffset, |
| phyInfo->anyPage,
|
| &crossChannelReg[j])) != GT_OK)
|
| {
|
| DBG_INFO(("Reading from paged phy reg failed.\n"));
|
| return retVal;
|
| }
|
| DBG_INFO(("@@@@@ reg channel %d is %x \n", j, crossChannelReg[j]));
|
| }
|
|
|
| /*
|
| * analyze the test result for RX Pair
|
| */
|
| for (j=0; j<GT_MDI_PAIR_NUM; j++)
|
| {
|
| if (crosspair!=GT_ADV_VCT_TCS_NO_CROSSPAIR)
|
| dist2fault = analizeAdvVCTResult(phyInfo->vctType, j, crossChannelReg, mode&(*tooShort), cableStatus);
|
| else
|
| dist2fault = analizeAdvVCTNoCrosspairResult(phyInfo->vctType, j, crossChannelReg, mode&(*tooShort), cableStatus);
|
|
|
| localTooShort[j]=GT_FALSE;
|
| if((mode)&&(*tooShort==GT_FALSE))
|
| {
|
| if ((dist2fault>=0) && (dist2fault<GT_ADV_VCT_ACCEPTABLE_SHORT_CABLE))
|
| {
|
| DBG_INFO(("@@@#@@@@ it is too short dist2fault %d\n", dist2fault));
|
| DBG_INFO(("Distance to Fault is too Short. So, rerun after changing pulse width\n"));
|
| localTooShort[j]=GT_TRUE;
|
| }
|
| }
|
| }
|
| |
| /* check and decide if length is too short */
|
| for (j=0; j<GT_MDI_PAIR_NUM; j++)
|
| {
|
| if (localTooShort[j]==GT_FALSE) break;
|
| }
|
|
|
| if (j==GT_MDI_PAIR_NUM)
|
| *tooShort = GT_TRUE;
|
|
|
| return GT_OK;
|
| }
|
|
|
| static
|
| GT_STATUS runAdvCableTest_1116
|
| (
|
| IN GT_QD_DEV *dev,
|
| IN GT_U8 hwPort,
|
| IN GT_PHY_INFO *phyInfo,
|
| IN GT_BOOL mode,
|
| IN GT_ADV_VCT_TRANS_CHAN_SEL crosspair,
|
| OUT GT_ADV_CABLE_STATUS *cableStatus,
|
| OUT GT_BOOL *tooShort
|
| )
|
| {
|
| GT_STATUS retVal;
|
| GT_32 channel;
|
|
|
| DBG_INFO(("runAdvCableTest_1116 Called.\n"));
|
|
|
| if (crosspair!=GT_ADV_VCT_TCS_NO_CROSSPAIR)
|
| {
|
| channel = crosspair - GT_ADV_VCT_TCS_CROSSPAIR_0;
|
| }
|
| else
|
| {
|
| channel = 0;
|
| }
|
| |
| /* Set transmit channel */
|
| if((retVal=runAdvCableTest_1116_set(dev,hwPort, phyInfo,channel, crosspair)) != GT_OK)
|
| {
|
| DBG_INFO(("Running advanced VCT failed.\n"));
|
| return retVal;
|
| }
|
|
|
| /*
|
| * check test completion
|
| */
|
| retVal = runAdvCableTest_1116_check(dev,hwPort,phyInfo); |
| if (retVal != GT_OK) |
| {
|
| DBG_INFO(("Running advanced VCT failed.\n"));
|
| return retVal;
|
| } |
|
|
| /*
|
| * read the test result for the cross pair against selected MDI Pair
|
| */
|
| retVal = runAdvCableTest_1116_get(dev, hwPort, phyInfo, crosspair,
|
| channel,cableStatus,(GT_BOOL *)tooShort);
|
| |
| if(retVal != GT_OK)
|
| {
|
| DBG_INFO(("Running advanced VCT get failed.\n"));
|
| }
|
| |
| return retVal;
|
| }
|
|
|
| static
|
| GT_STATUS getAdvCableStatus_1116
|
| (
|
| IN GT_QD_DEV *dev,
|
| IN GT_U8 hwPort,
|
| IN GT_PHY_INFO *phyInfo,
|
| IN GT_ADV_VCT_MODE mode,
|
| OUT GT_ADV_CABLE_STATUS *cableStatus
|
| )
|
| {
|
| GT_STATUS retVal;
|
| GT_U16 orgPulse, u16Data;
|
| GT_BOOL flag, tooShort;
|
| GT_ADV_VCT_TRANS_CHAN_SEL crosspair;
|
|
|
| flag = GT_TRUE;
|
| crosspair = mode.transChanSel;
|
|
|
| /*
|
| * Check Adv VCT Mode
|
| */
|
| switch (mode.mode)
|
| {
|
| case GT_ADV_VCT_FIRST_PEAK:
|
| case GT_ADV_VCT_MAX_PEAK:
|
| break;
|
| |
| default:
|
| DBG_INFO(("Unknown ADV VCT Mode.\n"));
|
| return GT_NOT_SUPPORTED;
|
| }
|
|
|
| if((retVal = hwGetPagedPhyRegField(
|
| dev,hwPort,5,QD_REG_ADV_VCT_CONTROL_5,0,13,phyInfo->anyPage,&u16Data)) != GT_OK)
|
| {
|
| DBG_INFO(("Reading paged phy reg failed.\n"));
|
| return retVal;
|
| }
|
| |
| u16Data |= ((mode.mode<<6) | (mode.transChanSel<<11));
|
| if (mode.peakDetHyst) u16Data |= (mode.peakDetHyst);
|
| if (mode.sampleAvg) u16Data |= (mode.sampleAvg<<8) ;
|
| |
| if((retVal = hwSetPagedPhyRegField(
|
| dev,hwPort,5,QD_REG_ADV_VCT_CONTROL_5,0,13,phyInfo->anyPage,u16Data)) != GT_OK)
|
| {
|
| DBG_INFO(("Writing to paged phy reg failed.\n"));
|
| return retVal;
|
| }
|
|
|
| if (flag)
|
| {
|
| /* save original Pulse Width */
|
| if((retVal = hwGetPagedPhyRegField(dev,hwPort,5,28,10,2,phyInfo->anyPage,&orgPulse)) != GT_OK)
|
| {
|
| DBG_INFO(("Reading paged phy reg failed.\n"));
|
| return retVal;
|
| }
|
|
|
| /* set the Pulse Width with default value */
|
| if (orgPulse != 0)
|
| {
|
| if((retVal = hwSetPagedPhyRegField(dev,hwPort,5,28,10,2,phyInfo->anyPage,0)) != GT_OK)
|
| {
|
| DBG_INFO(("Writing to paged phy reg failed.\n"));
|
| return retVal;
|
| }
|
| }
|
| tooShort=GT_FALSE;
|
| }
|
| |
| if((retVal=runAdvCableTest_1116(dev,hwPort,phyInfo,flag,crosspair,
|
| cableStatus,&tooShort)) != GT_OK)
|
| {
|
| DBG_INFO(("Running advanced VCT failed.\n"));
|
| return retVal;
|
| }
|
|
|
| if (flag)
|
| {
|
| if(tooShort)
|
| {
|
| /* set the Pulse Width with minimum width */
|
| if((retVal = hwSetPagedPhyRegField(
|
| dev,hwPort,5,28,10,2,phyInfo->anyPage,3)) != GT_OK)
|
| {
|
| DBG_INFO(("Writing to paged phy reg failed.\n"));
|
| return retVal;
|
| }
|
|
|
| /* run the Adv VCT again */
|
| if((retVal=runAdvCableTest_1116(dev,hwPort,phyInfo,GT_FALSE,crosspair,
|
| cableStatus,&tooShort)) != GT_OK)
|
| {
|
| DBG_INFO(("Running advanced VCT failed.\n"));
|
| return retVal;
|
| }
|
|
|
| }
|
|
|
| /* set the Pulse Width back to the original value */
|
| if((retVal = hwSetPagedPhyRegField(
|
| dev,hwPort,5,28,10,2,phyInfo->anyPage,orgPulse)) != GT_OK)
|
| {
|
| DBG_INFO(("Writing to paged phy reg failed.\n"));
|
| return retVal;
|
| }
|
|
|
| }
|
|
|
| return GT_OK;
|
| }
|
| |
| |
| /*******************************************************************************
|
| * gvctGetAdvCableStatus
|
| *
|
| * DESCRIPTION:
|
| * This routine perform the advanced virtual cable test for the requested
|
| * port and returns the the status per MDI pair.
|
| *
|
| * INPUTS:
|
| * port - logical port number.
|
| * mode - advance VCT mode (either First Peak or Maximum Peak)
|
| *
|
| * OUTPUTS:
|
| * cableStatus - the port copper cable status.
|
| *
|
| * RETURNS:
|
| * GT_OK - on success
|
| * GT_FAIL - on error
|
| *
|
| * COMMENTS:
|
| * Internal Gigabit Phys in 88E6165 family and 88E6351 family devices |
| * are supporting this API.
|
| *
|
| *******************************************************************************/
|
| GT_STATUS gvctGetAdvCableDiag
|
| (
|
| IN GT_QD_DEV *dev,
|
| IN GT_LPORT port,
|
| IN GT_ADV_VCT_MODE mode,
|
| OUT GT_ADV_CABLE_STATUS *cableStatus
|
| )
|
| {
|
| GT_STATUS status;
|
| GT_U8 hwPort;
|
| GT_U16 u16Data, org0;
|
| GT_BOOL ppuEn;
|
| GT_PHY_INFO phyInfo;
|
| GT_BOOL autoOn, autoNeg;
|
| GT_U16 pageReg; |
| int i;
|
|
|
| DBG_INFO(("gvctGetCableDiag Called.\n"));
|
| 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 VCT */
|
| 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_ADV_VCT_CAPABLE))
|
| {
|
| DBG_INFO(("Not Supported\n"));
|
| gtSemGive(dev,dev->phyRegsSem);
|
| return GT_NOT_SUPPORTED;
|
| }
|
|
|
| /* Need to disable PPUEn for safe. */
|
| if(gsysGetPPUEn(dev,&ppuEn) != GT_OK)
|
| {
|
| ppuEn = GT_FALSE;
|
| }
|
|
|
| if(ppuEn != GT_FALSE)
|
| {
|
| if((status= gsysSetPPUEn(dev,GT_FALSE)) != GT_OK)
|
| {
|
| DBG_INFO(("Not able to disable PPUEn.\n"));
|
| gtSemGive(dev,dev->phyRegsSem);
|
| return status;
|
| }
|
| gtDelay(250);
|
| }
|
|
|
| if(driverPagedAccessStart(dev,hwPort,phyInfo.pageType,&autoOn,&pageReg) != GT_OK)
|
| {
|
| gtSemGive(dev,dev->phyRegsSem);
|
| return GT_FAIL;
|
| }
|
|
|
| /*
|
| * If Fiber is used, simply return with test fail.
|
| */
|
| if(phyInfo.flag & GT_PHY_FIBER)
|
| {
|
| if((status= hwReadPagedPhyReg(dev,hwPort,1,17,phyInfo.anyPage,&u16Data)) != GT_OK)
|
| {
|
| return status;
|
| }
|
|
|
| if(u16Data & 0x400)
|
| {
|
| for (i=0; i<GT_MDI_PAIR_NUM; i++)
|
| {
|
| cableStatus->cableStatus[i] = GT_ADV_VCT_FAIL;
|
| }
|
| return GT_OK;
|
| }
|
| }
|
| |
| /*
|
| * Check the link
|
| */
|
| if((status= hwReadPagedPhyReg(dev,hwPort,0,17,phyInfo.anyPage,&u16Data)) != GT_OK)
|
| {
|
| DBG_INFO(("Not able to reset the Phy.\n"));
|
| return status;
|
| }
|
| |
| autoNeg = GT_FALSE; |
| org0 = 0; |
| if (!(u16Data & 0x400)) |
| { |
| /* link is down, so disable auto-neg if enabled */ |
| if((status= hwReadPagedPhyReg(dev,hwPort,0,0,phyInfo.anyPage,&u16Data)) != GT_OK)
|
| {
|
| DBG_INFO(("Not able to reset the Phy.\n"));
|
| return status;
|
| }
|
| |
| org0 = u16Data; |
| |
| if (u16Data & 0x1000) |
| { |
| u16Data = 0x140; |
| |
| /* link is down, so disable auto-neg if enabled */ |
| if((status= hwWritePagedPhyReg(dev,hwPort,0,0,phyInfo.anyPage,u16Data)) != GT_OK)
|
| {
|
| DBG_INFO(("Not able to reset the Phy.\n"));
|
| return status;
|
| }
|
| |
| if((status= hwPhyReset(dev,hwPort,0xFF)) != GT_OK)
|
| {
|
| DBG_INFO(("Not able to reset the Phy.\n"));
|
| return status;
|
| } |
| autoNeg = GT_TRUE; |
| } |
| } |
| |
| switch(phyInfo.vctType)
|
| {
|
| case GT_PHY_ADV_VCT_TYPE1:
|
| status = getAdvCableStatus_1181(dev,hwPort,&phyInfo,mode,cableStatus);
|
| break;
|
| case GT_PHY_ADV_VCT_TYPE2:
|
| status = getAdvCableStatus_1116(dev,hwPort,&phyInfo,mode,cableStatus);
|
| break;
|
| default:
|
| status = GT_FAIL;
|
| break;
|
| }
|
| |
| if (autoNeg) |
| { |
| if((status= hwPhyReset(dev,hwPort,org0)) != GT_OK)
|
| {
|
| DBG_INFO(("Not able to reset the Phy.\n"));
|
| goto cableDiagCleanup;
|
| return status;
|
| }
|
| } |
| |
| cableDiagCleanup:
|
|
|
| if(driverPagedAccessStop(dev,hwPort,phyInfo.pageType,autoOn,pageReg) != GT_OK)
|
| {
|
| gtSemGive(dev,dev->phyRegsSem);
|
| return GT_FAIL;
|
| }
|
|
|
| if(ppuEn != GT_FALSE)
|
| {
|
| if(gsysSetPPUEn(dev,ppuEn) != GT_OK)
|
| {
|
| DBG_INFO(("Not able to enable PPUEn.\n"));
|
| status = GT_FAIL;
|
| }
|
| }
|
|
|
| gtSemGive(dev,dev->phyRegsSem);
|
| return status;
|
| }
|
|
|
|
|
| /*******************************************************************************
|
| * dspLookup
|
| *
|
| * DESCRIPTION:
|
| * This routine returns cable length (meters) by reading DSP Lookup table.
|
| *
|
| * INPUTS:
|
| * regValue - register 21
|
| *
|
| * OUTPUTS:
|
| * cableLen - cable length (unit of meters).
|
| *
|
| * RETURNS:
|
| * GT_OK - on success
|
| * GT_FAIL - on error
|
| *
|
| * COMMENTS:
|
| * None.
|
| *
|
| *******************************************************************************/
|
| static
|
| GT_STATUS dspLookup
|
| (
|
| IN GT_PHY_INFO *phyInfo,
|
| IN GT_U16 regValue,
|
| OUT GT_32 *cableLen
|
| )
|
| {
|
| GT_U16 startEntry,tableEntry;
|
| GT_U8* tbl;
|
| switch(phyInfo->exStatusType)
|
| {
|
| case GT_PHY_EX_STATUS_TYPE1: /* 88E1111/88E1141/E1145 */
|
| startEntry = 18-1;
|
| tableEntry = 80;
|
| tbl = tbl_1111;
|
| break;
|
|
|
| case GT_PHY_EX_STATUS_TYPE2: /* 88E1112 */
|
| startEntry = 17;
|
| tableEntry = 100;
|
| tbl = tbl_1112;
|
| break;
|
|
|
| case GT_PHY_EX_STATUS_TYPE3: /* 88E1149 has no reference constans*/
|
| startEntry = 16;
|
| tableEntry = 73;
|
| tbl = tbl_1181;
|
| break;
|
|
|
| case GT_PHY_EX_STATUS_TYPE4: /* 88E1181 */
|
| startEntry = 16;
|
| tableEntry = 73;
|
| tbl = tbl_1181;
|
| break;
|
|
|
| case GT_PHY_EX_STATUS_TYPE5: /* 88E1116 88E1121 */
|
| startEntry = 16;
|
| tableEntry = 73;
|
| tbl = tbl_1116;
|
| break;
|
| |
| case GT_PHY_EX_STATUS_TYPE6: /* 88E6165 Internal Phy */ |
| if ((phyInfo->phyId & PHY_MODEL_MASK) == DEV_G65G) |
| startEntry = 18; |
| else
|
| startEntry = 21;
|
| tableEntry = 76;
|
| tbl = tbl_1240;
|
| break;
|
|
|
| default:
|
| return GT_NOT_SUPPORTED;
|
| }
|
|
|
| if (tbl == NULL)
|
| {
|
| *cableLen = -1;
|
| return GT_OK;
|
| }
|
|
|
| if (regValue < startEntry)
|
| {
|
| *cableLen = 0;
|
| return GT_OK;
|
| }
|
|
|
| if (regValue >= (tableEntry+startEntry-1))
|
| {
|
| regValue = tableEntry-1;
|
| }
|
| else
|
| {
|
| regValue -= startEntry;
|
| }
|
|
|
| *cableLen = (GT_32)tbl[regValue];
|
| return GT_OK;
|
| }
|
|
|
| /*******************************************************************************
|
| * getDSPDistance_1111
|
| *
|
| * DESCRIPTION:
|
| * This routine returns cable length (meters) from DSP method.
|
| * This routine is for the 88E1111 like devices.
|
| *
|
| * INPUTS:
|
| * mdi - pair of each MDI (0..3).
|
| *
|
| * OUTPUTS:
|
| * cableLen - cable length (unit of meters).
|
| *
|
| * RETURNS:
|
| * GT_OK - on success
|
| * GT_FAIL - on error
|
| *
|
| * COMMENTS:
|
| * None.
|
| *
|
| *******************************************************************************/
|
| static
|
| GT_STATUS getDSPDistance_1111
|
| (
|
| IN GT_QD_DEV *dev,
|
| IN GT_U8 hwPort,
|
| IN GT_PHY_INFO *phyInfo,
|
| IN GT_U32 mdi,
|
| OUT GT_32 *cableLen
|
| )
|
| {
|
| GT_U16 data, pageNum;
|
| GT_STATUS retVal;
|
|
|
| DBG_INFO(("getDSPDistance Called.\n"));
|
|
|
| pageNum = 0x8754 + (GT_U16)((mdi << 12)&0xf000);
|
|
|
| if((retVal = hwReadPagedPhyReg(dev,hwPort,(GT_U8)pageNum,31,phyInfo->anyPage,&data)) != GT_OK)
|
| {
|
| DBG_INFO(("Reading length of MDI pair failed.\n"));
|
| return retVal;
|
| }
|
|
|
| return dspLookup(phyInfo,data,cableLen);
|
| }
|
|
|
|
|
| /*******************************************************************************
|
| * getDSPDistance_1181
|
| *
|
| * DESCRIPTION:
|
| * This routine returns cable length (meters) from DSP method.
|
| * This routine is for the 88E1181 like devices.
|
| *
|
| * INPUTS:
|
| * mdi - pair of each MDI (0..3).
|
| *
|
| * OUTPUTS:
|
| * cableLen - cable length (unit of meters).
|
| *
|
| * RETURNS:
|
| * GT_OK - on success
|
| * GT_FAIL - on error
|
| *
|
| * COMMENTS:
|
| * None.
|
| *
|
| *******************************************************************************/
|
| static
|
| GT_STATUS getDSPDistance_1181
|
| (
|
| IN GT_QD_DEV *dev,
|
| IN GT_U8 hwPort,
|
| IN GT_PHY_INFO *phyInfo,
|
| IN GT_U32 mdi,
|
| OUT GT_32 *cableLen
|
| )
|
| {
|
| GT_U16 data, retryCount;
|
| GT_STATUS retVal;
|
|
|
| DBG_INFO(("getDSPDistance Called.\n"));
|
|
|
| /* Set the required bits for Cable length register */
|
| if((retVal = hwWritePagedPhyReg(dev,hwPort,0xff,19,phyInfo->anyPage,(GT_U16)(0x1018+(0xff&mdi)))) != GT_OK)
|
| {
|
| DBG_INFO(("Writing to paged phy reg failed.\n"));
|
| return retVal;
|
| }
|
|
|
| retryCount = 1000;
|
|
|
| do
|
| {
|
| if(retryCount == 0)
|
| {
|
| DBG_INFO(("Ready bit of Cable length resiter is not set.\n"));
|
| return GT_FAIL;
|
| }
|
|
|
| /* Check the ready bit of Cable length register */
|
| if((retVal = hwGetPagedPhyRegField(dev,hwPort,0xff,19,15,1,phyInfo->anyPage,&data)) != GT_OK)
|
| {
|
| DBG_INFO(("Writing to paged phy reg failed.\n"));
|
| return retVal;
|
| }
|
|
|
| retryCount--;
|
|
|
| } while(!data);
|
|
|
| /* read length of MDI pair */
|
| if((retVal = hwReadPagedPhyReg(dev,hwPort,0xff,21,phyInfo->anyPage,&data)) != GT_OK)
|
| {
|
| DBG_INFO(("Reading length of MDI pair failed.\n"));
|
| return retVal;
|
| }
|
|
|
| return dspLookup(phyInfo,data,cableLen);
|
| }
|
|
|
|
|
| /*******************************************************************************
|
| * getDSPDistance_1240
|
| *
|
| * DESCRIPTION:
|
| * This routine returns cable length (meters) from DSP method.
|
| * This routine is for the 88E1181 like devices.
|
| *
|
| * INPUTS:
|
| * mdi - pair of each MDI (0..3).
|
| *
|
| * OUTPUTS:
|
| * cableLen - cable length (unit of meters).
|
| *
|
| * RETURNS:
|
| * GT_OK - on success
|
| * GT_FAIL - on error
|
| *
|
| * COMMENTS:
|
| * None.
|
| *
|
| *******************************************************************************/
|
| static
|
| GT_STATUS getDSPDistance_1240
|
| (
|
| IN GT_QD_DEV *dev,
|
| IN GT_U8 hwPort,
|
| IN GT_PHY_INFO *phyInfo,
|
| IN GT_U32 mdi,
|
| OUT GT_32 *cableLen
|
| )
|
| {
|
| GT_U16 data, retryCount;
|
| GT_STATUS retVal;
|
|
|
| DBG_INFO(("getDSPDistance Called.\n"));
|
|
|
| /* Set the required bits for Cable length register */
|
| if((retVal = hwWritePagedPhyReg(dev,hwPort,0xff,16,phyInfo->anyPage,(GT_U16)(0x1118+(0xff&mdi)))) != GT_OK)
|
| {
|
| DBG_INFO(("Writing to paged phy reg failed.\n"));
|
| return retVal;
|
| }
|
|
|
| retryCount = 1000;
|
|
|
| do
|
| {
|
| if(retryCount == 0)
|
| {
|
| DBG_INFO(("Ready bit of Cable length resiter is not set.\n"));
|
| return GT_FAIL;
|
| }
|
|
|
| /* Check the ready bit of Cable length register */
|
| if((retVal = hwGetPagedPhyRegField(dev,hwPort,0xff,16,15,1,phyInfo->anyPage,&data)) != GT_OK)
|
| {
|
| DBG_INFO(("Writing to paged phy reg failed.\n"));
|
| return retVal;
|
| }
|
|
|
| retryCount--;
|
|
|
| } while(!data);
|
|
|
| /* read length of MDI pair */
|
| if((retVal = hwReadPagedPhyReg(dev,hwPort,0xff,18,phyInfo->anyPage,&data)) != GT_OK)
|
| {
|
| DBG_INFO(("Reading length of MDI pair failed.\n"));
|
| return retVal;
|
| }
|
|
|
| return dspLookup(phyInfo,data,cableLen);
|
| }
|
|
|
|
|
|
|
| /*******************************************************************************
|
| * getExStatus_28
|
| *
|
| * DESCRIPTION:
|
| * This routine retrieves Pair Skew, Pair Swap, and Pair Polarity
|
| * for 1000M phy with multiple page mode
|
| *
|
| * INPUTS:
|
| * dev - device context.
|
| * port - logical port number.
|
| *
|
| * OUTPUTS:
|
| * extendedStatus - extended cable status.
|
| *
|
| * RETURNS:
|
| * GT_OK - on success
|
| * GT_FAIL - on error
|
| *
|
| * COMMENTS:
|
| * None.
|
| *
|
| *******************************************************************************/
|
| static GT_STATUS getExStatus_28
|
| (
|
| IN GT_QD_DEV *dev,
|
| IN GT_U8 hwPort,
|
| IN GT_PHY_INFO *phyInfo,
|
| OUT GT_ADV_EXTENDED_STATUS *extendedStatus
|
| )
|
| {
|
| GT_STATUS retVal;
|
| GT_U16 u16Data, i;
|
|
|
| extendedStatus->isValid = GT_FALSE;
|
| /* DSP based cable length */
|
| for (i=0; i<GT_MDI_PAIR_NUM; i++)
|
| {
|
| if((retVal = getDSPDistance_1111(dev,hwPort,phyInfo,i,&extendedStatus->cableLen[i])) != GT_OK)
|
| {
|
| DBG_INFO(("getDSPDistance failed.\n"));
|
| return retVal;
|
| }
|
| }
|
|
|
|
|
| /*
|
| * get data from 28_5 register for pair swap
|
| */
|
| if((retVal = hwReadPagedPhyReg(
|
| dev,hwPort,5,28,phyInfo->anyPage,&u16Data)) != GT_OK)
|
| {
|
| DBG_INFO(("Reading from paged phy reg failed.\n"));
|
| return retVal;
|
| }
|
|
|
| /* if bit 6 is not set, it's not valid. */
|
| if (!(u16Data & 0x40))
|
| {
|
| DBG_INFO(("Valid Bit is not set (%0#x).\n", u16Data));
|
| return GT_OK;
|
| }
|
|
|
| extendedStatus->isValid = GT_TRUE;
|
|
|
| /* get Pair Polarity */
|
| for(i=0; i<GT_MDI_PAIR_NUM; i++)
|
| {
|
| switch((u16Data >> i) & 0x1)
|
| {
|
| case 0:
|
| extendedStatus->pairPolarity[i] = GT_POSITIVE;
|
| break;
|
| default:
|
| extendedStatus->pairPolarity[i] = GT_NEGATIVE;
|
| break;
|
| }
|
| }
|
|
|
| /* get Pair Swap for Channel A and B */
|
| if (u16Data & 0x10)
|
| {
|
| extendedStatus->pairSwap[0] = GT_CHANNEL_A;
|
| extendedStatus->pairSwap[1] = GT_CHANNEL_B;
|
| }
|
| else
|
| {
|
| extendedStatus->pairSwap[0] = GT_CHANNEL_B;
|
| extendedStatus->pairSwap[1] = GT_CHANNEL_A;
|
| }
|
|
|
| /* get Pair Swap for Channel C and D */
|
| if (u16Data & 0x20)
|
| {
|
| extendedStatus->pairSwap[2] = GT_CHANNEL_C;
|
| extendedStatus->pairSwap[3] = GT_CHANNEL_D;
|
| }
|
| else
|
| {
|
| extendedStatus->pairSwap[2] = GT_CHANNEL_D;
|
| extendedStatus->pairSwap[3] = GT_CHANNEL_C;
|
| }
|
|
|
| /*
|
| * get data from 28_4 register for pair skew
|
| */
|
| if((retVal = hwReadPagedPhyReg(
|
| dev,hwPort,4,28,phyInfo->anyPage,&u16Data)) != GT_OK)
|
| {
|
| DBG_INFO(("Reading from paged phy reg failed.\n"));
|
| return retVal;
|
| }
|
|
|
| /* get Pair Skew */
|
| for(i=0; i<GT_MDI_PAIR_NUM; i++)
|
| {
|
| extendedStatus->pairSkew[i] = ((u16Data >> i*4) & 0xF) * 8;
|
| }
|
|
|
| return GT_OK;
|
| }
|
|
|
|
|
| /*******************************************************************************
|
| * getExStatus
|
| *
|
| * DESCRIPTION:
|
| * This routine retrieves Pair Skew, Pair Swap, and Pair Polarity
|
| * for 1000M phy with multiple page mode
|
| *
|
| * INPUTS:
|
| * dev - device context.
|
| * port - logical port number.
|
| *
|
| * OUTPUTS:
|
| * extendedStatus - extended cable status.
|
| *
|
| * RETURNS:
|
| * GT_OK - on success
|
| * GT_FAIL - on error
|
| *
|
| * COMMENTS:
|
| * None.
|
| *
|
| *******************************************************************************/
|
| static GT_STATUS getExStatus
|
| (
|
| IN GT_QD_DEV *dev,
|
| IN GT_U8 hwPort,
|
| IN GT_PHY_INFO *phyInfo,
|
| OUT GT_ADV_EXTENDED_STATUS *extendedStatus
|
| )
|
| {
|
| GT_STATUS retVal;
|
| GT_U16 u16Data, i;
|
|
|
| extendedStatus->isValid = GT_FALSE;
|
| /* DSP based cable length */
|
| switch(phyInfo->exStatusType)
|
| {
|
| case GT_PHY_EX_STATUS_TYPE1:
|
| case GT_PHY_EX_STATUS_TYPE2:
|
| for (i=0; i<GT_MDI_PAIR_NUM; i++)
|
| {
|
| if((retVal = getDSPDistance_1111(dev,hwPort,phyInfo,i,&extendedStatus->cableLen[i])) != GT_OK)
|
| {
|
| DBG_INFO(("getDSPDistance failed.\n"));
|
| return retVal;
|
| }
|
| }
|
| break;
|
| case GT_PHY_EX_STATUS_TYPE3:
|
| case GT_PHY_EX_STATUS_TYPE4:
|
| case GT_PHY_EX_STATUS_TYPE5:
|
| for (i=0; i<GT_MDI_PAIR_NUM; i++)
|
| {
|
| if((retVal = getDSPDistance_1181(dev,hwPort,phyInfo,i,&extendedStatus->cableLen[i])) != GT_OK)
|
| {
|
| DBG_INFO(("getDSPDistance failed.\n"));
|
| return retVal;
|
| }
|
| }
|
| break;
|
|
|
| case GT_PHY_EX_STATUS_TYPE6:
|
| for (i=0; i<GT_MDI_PAIR_NUM; i++)
|
| {
|
| if((retVal = getDSPDistance_1240(dev,hwPort,phyInfo,i,&extendedStatus->cableLen[i])) != GT_OK)
|
| {
|
| DBG_INFO(("getDSPDistance failed.\n"));
|
| return retVal;
|
| }
|
| }
|
| break; |
|
|
| default:
|
| return GT_NOT_SUPPORTED;
|
| }
|
|
|
| /*
|
| * get data from 21_5 register for pair swap
|
| */
|
| if((retVal = hwReadPagedPhyReg(
|
| dev,hwPort,5,QD_REG_PAIR_SWAP_STATUS,phyInfo->anyPage,&u16Data)) != GT_OK)
|
| {
|
| DBG_INFO(("Reading from paged phy reg failed.\n"));
|
| return retVal;
|
| }
|
|
|
| /* if bit 6 is not set, it's not valid. */
|
| if (!(u16Data & 0x40))
|
| {
|
| DBG_INFO(("Valid Bit is not set (%0#x).\n", u16Data));
|
| return GT_OK;
|
| }
|
|
|
| extendedStatus->isValid = GT_TRUE;
|
|
|
| /* get Pair Polarity */
|
| for(i=0; i<GT_MDI_PAIR_NUM; i++)
|
| {
|
| switch((u16Data >> i) & 0x1)
|
| {
|
| case 0:
|
| extendedStatus->pairPolarity[i] = GT_POSITIVE;
|
| break;
|
| default:
|
| extendedStatus->pairPolarity[i] = GT_NEGATIVE;
|
| break;
|
| }
|
| }
|
|
|
| /* get Pair Swap for Channel A and B */
|
| if (u16Data & 0x10)
|
| {
|
| extendedStatus->pairSwap[0] = GT_CHANNEL_A;
|
| extendedStatus->pairSwap[1] = GT_CHANNEL_B;
|
| }
|
| else
|
| {
|
| extendedStatus->pairSwap[0] = GT_CHANNEL_B;
|
| extendedStatus->pairSwap[1] = GT_CHANNEL_A;
|
| }
|
|
|
| /* get Pair Swap for Channel C and D */
|
| if (u16Data & 0x20)
|
| {
|
| extendedStatus->pairSwap[2] = GT_CHANNEL_C;
|
| extendedStatus->pairSwap[3] = GT_CHANNEL_D;
|
| }
|
| else
|
| {
|
| extendedStatus->pairSwap[2] = GT_CHANNEL_D;
|
| extendedStatus->pairSwap[3] = GT_CHANNEL_C;
|
| }
|
|
|
| /*
|
| * get data from 20_5 register for pair skew
|
| */
|
| if((retVal = hwReadPagedPhyReg(
|
| dev,hwPort,5,QD_REG_PAIR_SKEW_STATUS,phyInfo->anyPage,&u16Data)) != GT_OK)
|
| {
|
| DBG_INFO(("Reading from paged phy reg failed.\n"));
|
| return retVal;
|
| }
|
|
|
| /* get Pair Skew */
|
| for(i=0; i<GT_MDI_PAIR_NUM; i++)
|
| {
|
| extendedStatus->pairSkew[i] = ((u16Data >> i*4) & 0xF) * 8;
|
| }
|
|
|
|
|
| return GT_OK;
|
| }
|
|
|
|
|
| /*******************************************************************************
|
| * gvctGetAdvExtendedStatus
|
| *
|
| * DESCRIPTION:
|
| * This routine retrieves extended cable status, such as Pair Poloarity,
|
| * Pair Swap, and Pair Skew. Note that this routine will be success only
|
| * if 1000Base-T Link is up.
|
| * Note: Since DSP based cable length in extended status is based on
|
| * constants from test results. At present, only E1181, E1111, and
|
| * E1112 are available.
|
| *
|
| * INPUTS:
|
| * dev - pointer to GT driver structure returned from mdLoadDriver
|
| * port - logical port number.
|
| *
|
| * OUTPUTS:
|
| * extendedStatus - the extended cable status.
|
| *
|
| * RETURNS:
|
| * GT_OK - on success
|
| * GT_FAIL - on error
|
| *
|
| * COMMENTS:
|
| * Supporting Device list:
|
| * 88E1111, 88E1112, 88E1141~6, 88E1149, and Internal Gigabit Phys |
| * in 88E6165 family and 88E6351 family devices |
| *
|
| *******************************************************************************/
|
| GT_STATUS gvctGetAdvExtendedStatus
|
| (
|
| IN GT_QD_DEV *dev,
|
| IN GT_LPORT port,
|
| OUT GT_ADV_EXTENDED_STATUS *extendedStatus
|
| )
|
| {
|
| GT_STATUS retVal;
|
| GT_U8 hwPort;
|
| GT_BOOL ppuEn;
|
| GT_PHY_INFO phyInfo;
|
| GT_BOOL autoOn;
|
| GT_U16 pageReg;
|
|
|
| DBG_INFO(("gvctGetAdvExtendedStatus Called.\n"));
|
| 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 VCT */
|
| 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_EX_CABLE_STATUS))
|
| {
|
| DBG_INFO(("Not Supported\n"));
|
| gtSemGive(dev,dev->phyRegsSem);
|
| return GT_NOT_SUPPORTED;
|
| }
|
|
|
| /* Need to disable PPUEn for safe. */
|
| if(gsysGetPPUEn(dev,&ppuEn) != GT_OK)
|
| {
|
| ppuEn = GT_FALSE;
|
| }
|
|
|
| if(ppuEn != GT_FALSE)
|
| {
|
| if((retVal = gsysSetPPUEn(dev,GT_FALSE)) != GT_OK)
|
| {
|
| DBG_INFO(("Not able to disable PPUEn.\n"));
|
| gtSemGive(dev,dev->phyRegsSem);
|
| return retVal;
|
| }
|
| gtDelay(250);
|
| }
|
|
|
| if(driverPagedAccessStart(dev,hwPort,phyInfo.pageType,&autoOn,&pageReg) != GT_OK)
|
| {
|
| gtSemGive(dev,dev->phyRegsSem);
|
| return GT_FAIL;
|
| }
|
|
|
| switch(phyInfo.exStatusType)
|
| {
|
| case GT_PHY_EX_STATUS_TYPE1:
|
| if((retVal = getExStatus_28(dev,hwPort,&phyInfo,extendedStatus)) != GT_OK)
|
| {
|
| DBG_INFO(("Getting Extanded Cable Status failed.\n"));
|
| break;
|
| }
|
| break;
|
|
|
| case GT_PHY_EX_STATUS_TYPE2:
|
| case GT_PHY_EX_STATUS_TYPE3:
|
| case GT_PHY_EX_STATUS_TYPE4:
|
| case GT_PHY_EX_STATUS_TYPE5:
|
| case GT_PHY_EX_STATUS_TYPE6:
|
| if((retVal = getExStatus(dev,hwPort,&phyInfo,extendedStatus)) != GT_OK)
|
| {
|
| DBG_INFO(("Getting Extanded Cable Status failed.\n"));
|
| break;
|
| }
|
|
|
| break;
|
| default:
|
| retVal = GT_NOT_SUPPORTED;
|
| }
|
|
|
| return retVal;
|
| }
|
|
|