/******************************************************************************* * gprtGetSerdesMode * * DESCRIPTION: * This routine reads Serdes Interface Mode. * * INPUTS: * port - The physical SERDES device address(4/5) * * OUTPUTS: * mode - Serdes Interface Mode * * RETURNS: * GT_OK - on success * GT_FAIL - on error * * COMMENTS: * logical port number is supported only for the devices made production * before 2009. * (Serdes devices: 88E6131, 88E6122, 88E6108, 88E6161, 88E6165, 88E6352 and 88E320 family) * *******************************************************************************/ GT_STATUS gprtGetSerdesMode ( IN GT_QD_DEV *dev, IN GT_LPORT port, IN GT_SERDES_MODE *mode ) { GT_U16 u16Data; /* The register's read data. */ GT_U8 hwPort, serdesPort; /* the physical port number */ GT_U8 pageNum = _getSerdesPageNumber(dev); GT_PHY_INFO serdesInfo; DBG_INFO(("gprtGetSerdesMode Called.\n")); if(!IS_IN_DEV_GROUP(dev,DEV_SERDES_CORE)) { return GT_NOT_SUPPORTED; } /* check if input is logical port number */ hwPort = GT_LPORT_2_PORT(port); serdesPort = hwPort; GT_GET_SERDES_PORT(dev,&serdesPort); gtSemTake(dev,dev->phyRegsSem,OS_WAIT_FOREVER); /* check if the port is configurable */ if((serdesInfo.phyId=GT_GET_PHY_ID(dev,hwPort)) == GT_INVALID_PHY) { gtSemGive(dev,dev->phyRegsSem); return GT_NOT_SUPPORTED; } if(driverFindPhyInformation(dev,hwPort,&serdesInfo) != GT_OK) { DBG_INFO(("Unknown PHY device.\n")); gtSemGive(dev,dev->phyRegsSem); return GT_FAIL; } /* Get Serdes Register. */ if(hwReadPagedPhyReg(dev,serdesPort,pageNum, 16,serdesInfo.anyPage,&u16Data) != GT_OK) { DBG_INFO(("Failed.\n")); gtSemGive(dev,dev->phyRegsSem); return GT_FAIL; } *mode = u16Data&0x3; gtSemGive(dev,dev->phyRegsSem); return GT_OK; }
GT_STATUS gprtGetSerdesPowerDownSt ( IN GT_QD_DEV *dev, IN GT_LPORT port, OUT GT_BOOL *state ) { GT_STATUS retVal; /* Functions return value. */ GT_U8 hwPort, serdesPort; /* the physical port number */ GT_U16 u16Data; GT_U8 pageNum = _getSerdesPageNumber(dev); GT_PHY_INFO serdesInfo; DBG_INFO(("gprtGetSerdesPowerDownSt Called.\n")); /* translate LPORT to hardware port */ hwPort = GT_LPORT_2_PHY(port); serdesPort = hwPort; GT_GET_SERDES_PORT(dev,&serdesPort); gtSemTake(dev,dev->phyRegsSem,OS_WAIT_FOREVER); /* check if the port is configurable */ if((serdesInfo.phyId=GT_GET_PHY_ID(dev,hwPort)) == GT_INVALID_PHY) { gtSemGive(dev,dev->phyRegsSem); return GT_NOT_SUPPORTED; } if(driverFindPhyInformation(dev,hwPort,&serdesInfo) != GT_OK) { DBG_INFO(("Unknown PHY device.\n")); gtSemGive(dev,dev->phyRegsSem); return GT_FAIL; } /* check if the port is configurable */ if(!IS_CONFIGURABLE_PHY(dev,hwPort)) { gtSemGive(dev,dev->phyRegsSem); return GT_NOT_SUPPORTED; } if((retVal=hwGetPagedPhyRegField(dev,serdesPort, pageNum,QD_SERDES_CONTROL_REG,11,1,serdesInfo.anyPage,&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; }
/******************************************************************************* * gprtSetSerdesReg * * DESCRIPTION: * This routine writes Phy Serdes 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 gprtSetSerdesReg ( IN GT_QD_DEV *dev, IN GT_LPORT port, IN GT_U32 regAddr, IN GT_U16 data ) { GT_U8 hwPort, serdesPort; /* the physical port number */ GT_U8 pageNum = _getSerdesPageNumber(dev); GT_PHY_INFO serdesInfo; DBG_INFO(("gprtSetSerdesReg Called.\n")); if(!IS_IN_DEV_GROUP(dev,DEV_SERDES_UP_PORT)) { return GT_NOT_SUPPORTED; } /* hwPort = GT_LPORT_2_PHY(port); */ hwPort = qdLong2Char(port); serdesPort = hwPort; GT_GET_SERDES_PORT(dev,&serdesPort); gtSemTake(dev,dev->phyRegsSem,OS_WAIT_FOREVER); /* check if the port is configurable */ if((serdesInfo.phyId=GT_GET_PHY_ID(dev,hwPort)) == GT_INVALID_PHY) { gtSemGive(dev,dev->phyRegsSem); return GT_NOT_SUPPORTED; } if(driverFindPhyInformation(dev,hwPort,&serdesInfo) != GT_OK) { DBG_INFO(("Unknown PHY device.\n")); gtSemGive(dev,dev->phyRegsSem); return GT_FAIL; } /* Write to Serdes Register */ if(hwWritePagedPhyReg(dev,serdesPort,pageNum, (GT_U8)regAddr,serdesInfo.anyPage,data) != GT_OK) { DBG_INFO(("Failed.\n")); gtSemGive(dev,dev->phyRegsSem); return GT_FAIL; } gtSemGive(dev,dev->phyRegsSem); return GT_OK; }
GT_STATUS gprtSetSerdesLoopback ( IN GT_QD_DEV *dev, IN GT_LPORT port, IN GT_BOOL enable ) { GT_STATUS retVal; /* Functions return value. */ GT_U8 hwPort, serdesPort; /* the physical port number */ GT_U16 u16Data; GT_PHY_INFO serdesInfo; GT_U8 pageNum = _getSerdesPageNumber(dev); DBG_INFO(("gprtSetSerdesLoopback Called.\n")); /* translate LPORT to hardware port */ hwPort = GT_LPORT_2_PHY(port); serdesPort = hwPort; GT_GET_SERDES_PORT(dev,&serdesPort); gtSemTake(dev,dev->phyRegsSem,OS_WAIT_FOREVER); /* check if the port is configurable */ if((serdesInfo.phyId=GT_GET_PHY_ID(dev,hwPort)) == GT_INVALID_PHY) { gtSemGive(dev,dev->phyRegsSem); return GT_NOT_SUPPORTED; } if(driverFindPhyInformation(dev,hwPort,&serdesInfo) != GT_OK) { DBG_INFO(("Unknown SERDES device.\n")); gtSemGive(dev,dev->phyRegsSem); return GT_FAIL; } BOOL_2_BIT(enable,u16Data); /* Write to Phy Control Register. */ retVal = hwSetPagedPhyRegField(dev,serdesPort, pageNum,QD_SERDES_CONTROL_REG,14,1,serdesInfo.anyPage,u16Data); if(retVal != GT_OK) { DBG_INFO(("Failed.\n")); } else { DBG_INFO(("OK.\n")); } gtSemGive(dev,dev->phyRegsSem); return retVal; }
GT_STATUS gprtSerdesReset ( IN GT_QD_DEV *dev, IN GT_LPORT port ) { GT_STATUS retVal; /* Functions return value. */ GT_U8 hwPort, serdesPort; /* the physical port number */ GT_PHY_INFO serdesInfo; DBG_INFO(("gprtSerdesReset Called.\n")); /* translate LPORT to hardware port */ hwPort = GT_LPORT_2_PHY(port); serdesPort = hwPort; GT_GET_SERDES_PORT(dev,&serdesPort); gtSemTake(dev,dev->phyRegsSem,OS_WAIT_FOREVER); /* check if the port is configurable */ if((serdesInfo.phyId=GT_GET_PHY_ID(dev,hwPort)) == GT_INVALID_PHY) { gtSemGive(dev,dev->phyRegsSem); return GT_NOT_SUPPORTED; } if(driverFindPhyInformation(dev,hwPort,&serdesInfo) != GT_OK) { DBG_INFO(("Unknown SERDES device.\n")); gtSemGive(dev,dev->phyRegsSem); return GT_FAIL; } /* set Auto Negotiation AD Register */ retVal = serdesSetAutoMode(dev,hwPort,&serdesInfo,SPEED_AUTO_DUPLEX_AUTO); if(retVal != GT_OK) { DBG_INFO(("Failed.\n")); } else { DBG_INFO(("OK.\n")); } gtSemGive(dev,dev->phyRegsSem); return retVal; }
/******************************************************************************* * gsysSetQoSWeight * * DESCRIPTION: * Programmable Round Robin Weights. * Each port has 4/8 output Queues. Queue 3/7 has the highest priority and * Queue 0 has the lowest priority. When a scheduling mode of port is * configured as Weighted Round Robin queuing mode, the access sequece of the * Queue is 3,2,3,1,3,2,3,0,3,2,3,1,3,2,3 by default. * (Queue is 7,6,5,7,1,6,7,4 by default. That is after 6390.) * This sequence can be configured with this API. * * INPUTS: * weight - access sequence of the queue * * OUTPUTS: * None. * * RETURNS: * GT_OK - on success * GT_FAIL - on error * GT_NOT_SUPPORTED - if current device does not support this feature. * * COMMENTS: * None * *******************************************************************************/ GT_STATUS gsysSetQoSWeight ( IN GT_QD_DEV *dev, IN GT_QoS_WEIGHT *weight ) { GT_STATUS retVal; /* Functions return value. */ GT_U16 data; GT_U32 len, i; int length_loc, entry_num; DBG_INFO(("gsysSetQoSWeight Called.\n")); /* Check if Switch supports this feature. */ if (!IS_IN_DEV_GROUP(dev,DEV_QoS_WEIGHT)) { DBG_INFO(("GT_NOT_SUPPORTED\n")); return GT_NOT_SUPPORTED; } if (IS_IN_DEV_GROUP(dev,DEV_QoS_WEIGHT_1)) { length_loc = 0x40; entry_num = 2; } else { length_loc = 0x20; entry_num = 4; } if (weight->len > 128) { DBG_INFO(("GT_BAD_PARAM\n")); return GT_BAD_PARAM; } gtSemTake(dev,dev->tblRegsSem,OS_WAIT_FOREVER); len = weight->len/entry_num; /* program QoS Weight Table, 4/2 sequences at a time */ for(i=0; i<len; i++) { /* Wait until the QoS Weight Table is ready. */ #ifdef GT_RMGMT_ACCESS { HW_DEV_REG_ACCESS regAccess; regAccess.entries = 2; regAccess.rw_reg_list[0].cmd = HW_REG_WAIT_TILL_0; regAccess.rw_reg_list[0].addr = CALC_SMI_DEV_ADDR(dev, 0, GLOBAL2_REG_ACCESS); regAccess.rw_reg_list[0].reg = QD_REG_QOS_WEIGHT; regAccess.rw_reg_list[0].data = 15; regAccess.rw_reg_list[1].cmd = HW_REG_WRITE; regAccess.rw_reg_list[1].addr = CALC_SMI_DEV_ADDR(dev, 0, GLOBAL2_REG_ACCESS); regAccess.rw_reg_list[1].reg = QD_REG_QOS_WEIGHT; if (IS_IN_DEV_GROUP(dev,DEV_QoS_WEIGHT_1)) { data = (GT_U16)((1 << 15) | (i << 8) | (weight->queue[i*2] & 0x7) | ((weight->queue[i*2+1] & 0x7) << 4); } else { data = (GT_U16)((1 << 15) | (i << 8) | (weight->queue[i*4] & 0x3) | ((weight->queue[i*4+1] & 0x3) << 2) | ((weight->queue[i*4+2] & 0x3) << 4) | ((weight->queue[i*4+3] & 0x3) << 6)); } regAccess.rw_reg_list[1].data = data; retVal = hwAccessMultiRegs(dev, ®Access); if(retVal != GT_OK) { gtSemGive(dev,dev->tblRegsSem); return retVal; } } #else data = 1; while(data == 1) { retVal = hwGetGlobal2RegField(dev,QD_REG_QOS_WEIGHT,15,1,&data); if(retVal != GT_OK) { gtSemGive(dev,dev->tblRegsSem); return retVal; } } if (IS_IN_DEV_GROUP(dev,DEV_QoS_WEIGHT_1)) { data = (GT_U16)((1 << 15) | (i << 8) | (weight->queue[i*2] & 0x7) | ((weight->queue[i*2+1] & 0x7) << 4)); } else { data = (GT_U16)((1 << 15) | (i << 8) | (weight->queue[i*4] & 0x3) | ((weight->queue[i*4+1] & 0x3) << 2) | ((weight->queue[i*4+2] & 0x3) << 4) | ((weight->queue[i*4+3] & 0x3) << 6)); } retVal = hwWriteGlobal2Reg(dev, QD_REG_QOS_WEIGHT, data); if(retVal != GT_OK) { DBG_INFO(("Failed.\n")); gtSemGive(dev,dev->tblRegsSem); return retVal; } #endif }
/******************************************************************************* * gprtGetSerdesReg * * DESCRIPTION: * This routine reads Phy Serdes 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 gprtGetSerdesReg ( IN GT_QD_DEV *dev, IN GT_LPORT port, IN GT_U32 regAddr, OUT GT_U16 *data ) { GT_U8 hwPort, serdesPort; /* the physical port number */ GT_U8 pageNum = _getSerdesPageNumber(dev); GT_PHY_INFO serdesInfo; DBG_INFO(("gprtGetSerdesReg Called.\n")); if(!IS_IN_DEV_GROUP(dev,DEV_SERDES_UP_PORT)) { return GT_NOT_SUPPORTED; } /* check if input is logical port number */ /* hwPort = GT_LPORT_2_PORT(port); GT_GET_SERDES_PORT(dev,&hwPort); */ hwPort = qdLong2Char(port); serdesPort = hwPort; GT_GET_SERDES_PORT(dev,&serdesPort); if(hwPort > dev->maxPhyNum) { /* check if input is physical serdes address */ if(dev->validSerdesVec & (1<<port)) { hwPort = (GT_U8)port; } else return GT_NOT_SUPPORTED; } //printf("===GT_GET_SERDES_PORT serdesPort = %d ,hwPort = %d\r\n",serdesPort,hwPort); gtSemTake(dev,dev->phyRegsSem,OS_WAIT_FOREVER); /* check if the port is configurable */ if((serdesInfo.phyId=GT_GET_PHY_ID(dev,hwPort)) == GT_INVALID_PHY) { gtSemGive(dev,dev->phyRegsSem); return GT_NOT_SUPPORTED; } if(driverFindPhyInformation(dev,hwPort,&serdesInfo) != GT_OK) { DBG_INFO(("Unknown PHY device.\n")); gtSemGive(dev,dev->phyRegsSem); return GT_FAIL; } /* Get Serdes Register. */ /* Write to Serdes Register */ //printf("===hwReadPagedPhyReg serdesPort= %d, pageNum = %d,regAddr = %x,serdesInfo.anyPage = %d \r\n",serdesPort,pageNum,(GT_U8)regAddr,serdesInfo.anyPage); if(hwReadPagedPhyReg(dev,serdesPort,pageNum,(GT_U8)regAddr,serdesInfo.anyPage,data) != GT_OK) { DBG_INFO(("Failed.\n")); gtSemGive(dev,dev->phyRegsSem); return GT_FAIL; } gtSemGive(dev,dev->phyRegsSem); return GT_OK; }
GT_STATUS gprtSetSerdesPause ( IN GT_QD_DEV *dev, IN GT_LPORT port, IN GT_PHY_PAUSE_MODE state ) { GT_U8 hwPort, serdesPort; /* the physical port number */ GT_U16 u16Data,regStart; GT_STATUS retVal = GT_OK; GT_PHY_INFO serdesInfo; GT_U8 pageNum = _getSerdesPageNumber(dev); GT_SERDES_MODE serdes_mode; DBG_INFO(("serdesSetPause Called.\n")); /* translate LPORT to hardware port */ hwPort = GT_LPORT_2_PHY(port); serdesPort = hwPort; GT_GET_SERDES_PORT(dev,&serdesPort); gtSemTake(dev,dev->phyRegsSem,OS_WAIT_FOREVER); /* check if the port is configurable */ if((serdesInfo.phyId=GT_GET_PHY_ID(dev,hwPort)) == GT_INVALID_PHY) { gtSemGive(dev,dev->phyRegsSem); return GT_NOT_SUPPORTED; } if(driverFindPhyInformation(dev,hwPort,&serdesInfo) != GT_OK) { DBG_INFO(("Unknown PHY device.\n")); gtSemGive(dev,dev->phyRegsSem); return GT_FAIL; } if((retVal=gprtGetSerdesMode(dev,serdesPort, &serdes_mode)) != GT_OK) { DBG_INFO(("Not able to get Serdes mode(port:%d).\n",serdes_mode)); gtSemGive(dev,dev->phyRegsSem); return GT_FAIL; } if(serdes_mode != PHY_SERDES_1000X) { gtSemGive(dev,dev->phyRegsSem); return GT_NOT_SUPPORTED; } regStart = 7; if(state & GT_PHY_ASYMMETRIC_PAUSE) { if(driverFindPhyInformation(dev,hwPort,&serdesInfo) != GT_OK) { DBG_INFO(("Unknown SERDES device.\n")); gtSemGive(dev,dev->phyRegsSem); return GT_FAIL; } if (!(serdesInfo.flag & GT_PHY_GIGABIT)) { DBG_INFO(("Not Supported\n")); gtSemGive(dev,dev->phyRegsSem); return GT_BAD_PARAM; } } u16Data = state; /* Write to Phy AutoNegotiation Advertisement Register. */ if((retVal=hwSetPagedPhyRegField(dev,serdesPort, pageNum,QD_SERDES_AUTONEGO_AD_REG,(GT_U8)regStart,2,serdesInfo.anyPage,u16Data)) != GT_OK) { DBG_INFO(("Not able to write Serdes Reg(port:%d,offset:%d).\n",serdesPort,QD_SERDES_AUTONEGO_AD_REG)); gtSemGive(dev,dev->phyRegsSem); return GT_FAIL; } /* Restart Auto Negotiation */ if((retVal=hwSetPagedPhyRegField(dev,serdesPort, pageNum,QD_SERDES_CONTROL_REG,9,1,serdesInfo.anyPage,1)) != GT_OK) { DBG_INFO(("Not able to write Serdes Reg(port:%d,offset:%d,data:%#x).\n",serdesPort,QD_SERDES_AUTONEGO_AD_REG,serdesInfo.anyPage,u16Data)); gtSemGive(dev,dev->phyRegsSem); return GT_FAIL; } gtSemGive(dev,dev->phyRegsSem); return retVal; }
/******************************************************************************* * gprtSetSerdesDuplexMode * * 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 gprtSetSerdesDuplexMode ( IN GT_QD_DEV *dev, IN GT_LPORT port, IN GT_BOOL dMode ) { GT_U8 hwPort, serdesPort; /* the physical port number */ GT_U16 u16Data; GT_STATUS retVal; GT_U8 pageNum = _getSerdesPageNumber(dev); GT_PHY_INFO serdesInfo; DBG_INFO(("gprtSetSerdesDuplexMode Called.\n")); /* translate LPORT to hardware port */ hwPort = GT_LPORT_2_PHY(port); serdesPort = hwPort; GT_GET_SERDES_PORT(dev,&serdesPort); gtSemTake(dev,dev->phyRegsSem,OS_WAIT_FOREVER); /* check if the port is configurable */ if((serdesInfo.phyId=GT_GET_PHY_ID(dev,hwPort)) == GT_INVALID_PHY) { gtSemGive(dev,dev->phyRegsSem); return GT_NOT_SUPPORTED; } if(driverFindPhyInformation(dev,hwPort,&serdesInfo) != GT_OK) { DBG_INFO(("Unknown PHY device.\n")); gtSemGive(dev,dev->phyRegsSem); return GT_FAIL; } /* check if the port is configurable */ if(!IS_CONFIGURABLE_PHY(dev,hwPort)) { gtSemGive(dev,dev->phyRegsSem); return GT_NOT_SUPPORTED; } if(hwReadPagedPhyReg(dev,serdesPort,pageNum,QD_SERDES_CONTROL_REG,serdesInfo.anyPage,&u16Data) != GT_OK) { DBG_INFO(("Not able to read Serdes Reg(port:%d,offset:%d).\n",serdesPort,QD_SERDES_CONTROL_REG)); gtSemGive(dev,dev->phyRegsSem); return GT_FAIL; } if(dMode) { u16Data = (u16Data & (QD_SERDES_LOOPBACK | QD_SERDES_SPEED | QD_SERDES_SPEED_MSB)) | QD_SERDES_DUPLEX; } else { u16Data = u16Data & (QD_SERDES_LOOPBACK | QD_SERDES_SPEED | QD_SERDES_SPEED_MSB); } DBG_INFO(("Write to serdes(%d) register: regAddr 0x%x, data %#x", serdesPort,QD_SERDES_CONTROL_REG,u16Data)); /* Write to Phy Control Register. */ retVal = hwSerdesReset(dev,serdesPort,pageNum, u16Data); gtSemGive(dev,dev->phyRegsSem); return retVal; }
GT_STATUS gprtSetSerdesSpeed ( IN GT_QD_DEV *dev, IN GT_LPORT port, IN GT_PHY_SPEED speed ) { GT_U8 hwPort, serdesPort; /* the physical port number */ GT_U16 u16Data; GT_PHY_INFO serdesInfo; GT_STATUS retVal; GT_U8 pageNum = _getSerdesPageNumber(dev); DBG_INFO(("gprtSetSerdesSpeed Called.\n")); /* translate LPORT to hardware port */ hwPort = GT_LPORT_2_PHY(port); serdesPort = hwPort; GT_GET_SERDES_PORT(dev,&serdesPort); gtSemTake(dev,dev->phyRegsSem,OS_WAIT_FOREVER); /* check if the port is configurable */ if((serdesInfo.phyId=GT_GET_PHY_ID(dev,hwPort)) == GT_INVALID_PHY) { gtSemGive(dev,dev->phyRegsSem); return GT_NOT_SUPPORTED; } if(driverFindPhyInformation(dev,hwPort,&serdesInfo) != GT_OK) { DBG_INFO(("Unknown SERDES device.\n")); gtSemGive(dev,dev->phyRegsSem); return GT_FAIL; } if(hwReadPagedPhyReg(dev,serdesPort,pageNum,QD_SERDES_CONTROL_REG,serdesInfo.anyPage,&u16Data) != GT_OK) { DBG_INFO(("Not able to read Serdes Reg(port:%d,offset:%d).\n",serdesPort,QD_SERDES_CONTROL_REG)); gtSemGive(dev,dev->phyRegsSem); return GT_FAIL; } switch(speed) { case PHY_SPEED_10_MBPS: if ((serdesInfo.flag & GT_PHY_GIGABIT) && !(serdesInfo.flag & GT_PHY_COPPER)) { gtSemGive(dev,dev->phyRegsSem); return GT_BAD_PARAM; } u16Data = u16Data & (QD_SERDES_LOOPBACK | QD_SERDES_DUPLEX); break; case PHY_SPEED_100_MBPS: u16Data = (u16Data & (QD_SERDES_LOOPBACK | QD_SERDES_DUPLEX)) | QD_SERDES_SPEED; break; case PHY_SPEED_1000_MBPS: if (!(serdesInfo.flag & GT_PHY_GIGABIT)) { gtSemGive(dev,dev->phyRegsSem); return GT_BAD_PARAM; } u16Data = (u16Data & (QD_SERDES_LOOPBACK | QD_SERDES_DUPLEX)) | QD_SERDES_SPEED_MSB; break; default: gtSemGive(dev,dev->phyRegsSem); return GT_FAIL; } DBG_INFO(("Write to serdes(%d) register: regAddr 0x%x, data %#x", serdesPort,QD_SERDES_CONTROL_REG,u16Data)); retVal = hwSerdesReset(dev,serdesPort,pageNum, u16Data); gtSemGive(dev,dev->phyRegsSem); return retVal; }
static GT_STATUS statsOperationPerform ( IN GT_QD_DEV *dev, IN GT_STATS_OPERATION statsOp, IN GT_U8 port, IN GT_STATS_COUNTERS counter, OUT GT_VOID *statsData ) { GT_STATUS retVal; /* Functions return value. */ GT_U16 data,histoData; /* Data to be set into the */ /* register. */ GT_U32 statsCounter; GT_U32 lastCounter; GT_U16 portNum; gtSemTake(dev,dev->statsRegsSem,OS_WAIT_FOREVER); if (!((IS_IN_DEV_GROUP(dev,DEV_GIGABIT_SWITCH)) || (IS_IN_DEV_GROUP(dev,DEV_RMON_REALTIME_SUPPORT)))) { if (IS_IN_DEV_GROUP(dev,DEV_MELODY_SWITCH)) lastCounter = (GT_U32)STATS2_Late; else lastCounter = (GT_U32)STATS_OutDiscards; } else { lastCounter = (GT_U32)STATS2_Late; } if (IS_IN_DEV_GROUP(dev,DEV_RMON_PORT_BITS)) { portNum = (port + 1) << 5; } else { portNum = (GT_U16)port; } /* Wait until the stats in ready. */ #ifdef GT_RMGMT_ACCESS { HW_DEV_REG_ACCESS regAccess; regAccess.entries = 2; regAccess.rw_reg_list[0].cmd = HW_REG_WAIT_TILL_0; regAccess.rw_reg_list[0].addr = CALC_SMI_DEV_ADDR(dev, 0, GLOBAL_REG_ACCESS); regAccess.rw_reg_list[0].reg = QD_REG_STATS_OPERATION; regAccess.rw_reg_list[0].data = 15; regAccess.rw_reg_list[1].cmd = HW_REG_READ; regAccess.rw_reg_list[1].addr = CALC_SMI_DEV_ADDR(dev, 0, GLOBAL_REG_ACCESS); regAccess.rw_reg_list[1].reg = QD_REG_STATS_OPERATION; regAccess.rw_reg_list[1].data = 0; retVal = hwAccessMultiRegs(dev, ®Access); if(retVal != GT_OK) { gtSemGive(dev,dev->statsRegsSem); return retVal; } histoData = qdLong2Short(regAccess.rw_reg_list[1].data); } #else data = 1; while(data == 1) { retVal = hwGetGlobalRegField(dev,QD_REG_STATS_OPERATION,15,1,&data); if(retVal != GT_OK) { gtSemGive(dev,dev->statsRegsSem); return retVal; } } /* Get the Histogram mode bit. */ retVal = hwReadGlobalReg(dev,QD_REG_STATS_OPERATION,&histoData); if(retVal != GT_OK) { gtSemGive(dev,dev->statsRegsSem); return retVal; } #endif histoData &= 0xC00; /* Set the STAT Operation register */ switch (statsOp) { case STATS_FLUSH_ALL: data = (1 << 15) | (GT_STATS_FLUSH_ALL << 12) | histoData; retVal = hwWriteGlobalReg(dev,QD_REG_STATS_OPERATION,data); gtSemGive(dev,dev->statsRegsSem); return retVal; case STATS_FLUSH_PORT: data = (1 << 15) | (GT_STATS_FLUSH_PORT << 12) | portNum | histoData; retVal = hwWriteGlobalReg(dev,QD_REG_STATS_OPERATION,data); gtSemGive(dev,dev->statsRegsSem); return retVal; case STATS_READ_COUNTER: retVal = statsCapture(dev,port); if(retVal != GT_OK) { gtSemGive(dev,dev->statsRegsSem); return retVal; } retVal = statsReadCounter(dev,counter,(GT_U32*)statsData); if(retVal != GT_OK) { gtSemGive(dev,dev->statsRegsSem); return retVal; } break; case STATS_READ_REALTIME_COUNTER: retVal = statsReadRealtimeCounter(dev,port,counter,(GT_U32*)statsData); if(retVal != GT_OK) { gtSemGive(dev,dev->statsRegsSem); return retVal; } break; case STATS_READ_ALL: retVal = statsCapture(dev,port); if(retVal != GT_OK) { gtSemGive(dev,dev->statsRegsSem); return retVal; } for(statsCounter=0; statsCounter<=lastCounter; statsCounter++) { retVal = statsReadCounter(dev,statsCounter,((GT_U32*)statsData + statsCounter)); if(retVal != GT_OK) { gtSemGive(dev,dev->statsRegsSem); return retVal; } } break; default: gtSemGive(dev,dev->statsRegsSem); return GT_FAIL; } gtSemGive(dev,dev->statsRegsSem); return GT_OK; }
static GT_STATUS stuOperationPerform ( IN GT_QD_DEV *dev, IN GT_STU_OPERATION stuOp, INOUT GT_U8 *valid, INOUT GT_STU_ENTRY *entry ) { GT_STATUS retVal; /* Functions return value. */ GT_U16 data; /* Data to be set into the */ /* register. */ gtSemTake(dev,dev->vtuRegsSem,OS_WAIT_FOREVER); /* Wait until the VTU in ready. */ data = 1; while(data == 1) { retVal = hwGetGlobalRegField(dev,QD_REG_VTU_OPERATION,15,1,&data); if(retVal != GT_OK) { gtSemGive(dev,dev->vtuRegsSem); return retVal; } } /* Set the VTU data register if Load operation is required. */ if (stuOp == LOAD_PURGE_STU_ENTRY) { if (*valid == 1) { /* set the Port State for all the ports */ retVal = stuSetSTUData(dev,entry); if(retVal != GT_OK) { gtSemGive(dev,dev->vtuRegsSem); return retVal; } /* Set the valid bit (QD_REG_VTU_VID_REG) */ data= *valid << 12 ; retVal = hwWriteGlobalReg(dev,(GT_U8)(QD_REG_VTU_VID_REG),data); if(retVal != GT_OK) { gtSemGive(dev,dev->vtuRegsSem); return retVal; } } else { /* Clear the valid bit (QD_REG_VTU_VID_REG) */ data= 0 ; retVal = hwWriteGlobalReg(dev,(GT_U8)(QD_REG_VTU_VID_REG),data); if(retVal != GT_OK) { gtSemGive(dev,dev->vtuRegsSem); return retVal; } } } /* Set the SID register (QD_REG_STU_SID_REG) */ data= (entry->sid) & 0x3F; retVal = hwWriteGlobalReg(dev,(GT_U8)(QD_REG_STU_SID_REG),data); if(retVal != GT_OK) { gtSemGive(dev,dev->vtuRegsSem); return retVal; } /* Start the STU Operation by defining the stuOp and VTUBusy */ data = (1 << 15) | (stuOp << 12); retVal = hwWriteGlobalReg(dev,QD_REG_VTU_OPERATION,data); if(retVal != GT_OK) { gtSemGive(dev,dev->vtuRegsSem); return retVal; } /* If the operation is a get next operation wait for the response */ if(stuOp == GET_NEXT_STU_ENTRY) { /* Wait until the STU in ready. */ data = 1; while(data == 1) { retVal = hwGetGlobalRegField(dev,QD_REG_VTU_OPERATION,15,1,&data); if(retVal != GT_OK) { gtSemGive(dev,dev->vtuRegsSem); return retVal; } } /****************** get the valid bit *******************/ retVal = hwGetGlobalRegField(dev,QD_REG_VTU_VID_REG,12,1,&data); if(retVal != GT_OK) { gtSemGive(dev,dev->vtuRegsSem); return retVal; } *valid = (GT_U8)data; /****************** get the sid *******************/ retVal = hwReadGlobalReg(dev,QD_REG_STU_SID_REG,&data); if(retVal != GT_OK) { gtSemGive(dev,dev->vtuRegsSem); return retVal; } /* the sid is bits 0-5 */ entry->sid = data & 0x3F; if (*valid) { /* get the Port State for all the ports */ retVal = stuGetSTUData(dev,entry); if(retVal != GT_OK) { gtSemGive(dev,dev->vtuRegsSem); return retVal; } } /* entry is valid */ } /* end of get next entry */ gtSemGive(dev,dev->vtuRegsSem); return GT_OK; }
/******************************************************************************* * gvctGetCableStatus_mad * * DESCRIPTION: * This routine perform the virtual cable test for the requested port, * and returns the the status per MDI pair. * * INPUTS: * port - logical port number. * * OUTPUTS: * cableStatus - the port copper cable status. * cableLen - the port copper cable length. * * RETURNS: * GT_OK - on success * GT_FAIL - on error * * COMMENTS: * Internal Gigabit Phys in 88E6165 family and 88E6351 family devices * are not supported by this API. For those devices, gvctGetAdvCableDiag * API can be used, instead. * *******************************************************************************/ GT_STATUS gvctGetCableDiag_mad ( IN GT_QD_DEV *dev, IN GT_LPORT port, OUT GT_CABLE_STATUS *cableStatus ) { GT_STATUS status=GT_OK; GT_U8 hwPort; GT_BOOL ppuEn; GT_PHY_INFO phyInfo; DBG_INFO(("gvctGetCableDiag_mad 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_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 ( mdDiagGetCableStatus(&(dev->mad_dev),port, (MAD_CABLE_STATUS*)cableStatus) != MAD_OK) { DBG_INFO(("Failed to run mdDiagGetCableStatus.\n")); gtSemGive(dev,dev->phyRegsSem); return GT_FALSE; } 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; }