/** ReadMacTableEntries * \ingroup intDiagMATable * * \desc Output an MA Table entry as it appears in hardware and * in the memory-based cache. * * \param[in] sw is the switch on which to operate. * * \param[in] index is the index into the MA Table. * * \param[out] dmacEntry points to a structure to receive the decoded * destination MAC table entry. * * \param[out] smacEntry points to a structure to receive the decoded * source MAC table entry. * * \return None. * *****************************************************************************/ static fm_status ReadMacTableEntries(fm_int sw, fm_uint32 index, fm10000_maTableEntry * dmacEntry, fm10000_maTableEntry * smacEntry) { fm_switch * switchPtr; fm_uint32 words[FM10000_MA_TABLE_WIDTH]; fm_status status; switchPtr = GET_SWITCH_PTR(sw); /* Retrieve DMAC table entry. */ status = switchPtr->ReadUINT32Mult(sw, FM10000_MA_TABLE(0, index, 0), FM10000_MA_TABLE_WIDTH, words); if (status != FM_OK) { FM_LOG_PRINT("Error reading DMAC entry %u: %s\n", index, fmErrorMsg(status)); return status; } status = DecodeMacTableEntry(sw, dmacEntry, words); if (status != FM_OK) { FM_LOG_PRINT("Error decoding DMAC entry %u: %s\n", index, fmErrorMsg(status)); return status; } /* Retrieve SMAC table entry. */ status = switchPtr->ReadUINT32Mult(sw, FM10000_MA_TABLE(1, index, 0), FM10000_MA_TABLE_WIDTH, words); if (status != FM_OK) { FM_LOG_PRINT("Error reading SMAC entry %u: %s\n", index, fmErrorMsg(status)); return status; } status = DecodeMacTableEntry(sw, smacEntry, words); if (status != FM_OK) { FM_LOG_PRINT("Error decoding SMAC entry %u: %s\n", index, fmErrorMsg(status)); } return status; } /* end ReadMacTableEntries */
/** fmDbgPrintChipSnapshot * \ingroup diagReg * * \chips FM2000, FM3000, FM4000, FM6000, FM10000 * * \desc Display a snapshot of the switch's configuration (the * register file) taken with a prior call to * fmDbgTakeChipSnapshot. * * \param[in] snapshot is the snapshot number specified in a prior call * to fmDbgTakeChipSnapshot. * * \param[in] showZeroValues should be TRUE to print registers with a * zero value or FALSE to only print registers with non-zero * values (this is useful to avoid printing thousands of * unused VID and FID table entries). * * \return None. * *****************************************************************************/ void fmDbgPrintChipSnapshot(fm_int snapshot, fm_bool showZeroValues) { fmDbgFulcrumSnapshot * pSnapshot; fm_int index; fmDbgFulcrumRegisterSnapshot *pRegister; if (snapshot < 0 || snapshot >= FM_DBG_MAX_SNAPSHOTS) { FM_LOG_PRINT("snapshot number must be between 0 and %d inclusive\n", FM_DBG_MAX_SNAPSHOTS - 1); return; } pSnapshot = fmRootDebug->fmDbgSnapshots[snapshot]; if (pSnapshot == NULL) { FM_LOG_PRINT("snapshot %d is unused\n", snapshot); return; } if (pSnapshot->regCount == 0) { FM_LOG_PRINT("snapshot %d is empty\n", snapshot); return; } pRegister = pSnapshot->registers; FM_LOG_PRINT("Snapshot %d was taken from switch %d at timestamp " "%" FM_FORMAT_64 "u.%06" FM_FORMAT_64 "u with %d registers\n", snapshot, pSnapshot->sw, pSnapshot->timestamp.sec, pSnapshot->timestamp.usec, pSnapshot->regCount); for (index = 0 ; index < pSnapshot->regCount ; index++, pRegister++) { if ( (pRegister->regValue1 != 0) || (pRegister->regValue2 != 0) || (showZeroValues == TRUE) ) { fmDbgPrintRegValue(pSnapshot->sw, pRegister->regId, pRegister->regAddress, pRegister->regSize, pRegister->isStatReg, pRegister->regValue1, pRegister->regValue2, 0); } } } /* end fmDbgPrintChipSnapshot */
/** fmDbgTakeChipSnapshot * \ingroup diagReg * * \chips FM2000, FM3000, FM4000, FM6000, FM10000 * * \desc Record a snapshot of the switch's configuration (the * register file). * * \param[in] sw is the switch on which to operate. * * \param[in] snapshot is an arbitrary snapshot number (0 - 31) by * which to recall the snapshot later. The snapshot number * is global across all switches in the system. * * \return None. * *****************************************************************************/ void fmDbgTakeChipSnapshot(fm_int sw, fm_int snapshot) { fmDbgFulcrumSnapshot *pSnapshot; fm_switch * switchPtr; if (snapshot < 0 || snapshot >= FM_DBG_MAX_SNAPSHOTS) { FM_LOG_PRINT("snapshot number must be between 0 and %d inclusive\n", FM_DBG_MAX_SNAPSHOTS - 1); return; } PROTECT_SWITCH(sw); switchPtr = fmRootApi->fmSwitchStateTable[sw]; if (switchPtr == NULL) { UNPROTECT_SWITCH(sw); FM_LOG_PRINT("Invalid switch number %d, snapshot %d\n", sw, snapshot); return; } if (fmRootDebug->fmDbgSnapshots[snapshot] != NULL) { FREE(fmRootDebug->fmDbgSnapshots[snapshot]); } pSnapshot = (fmDbgFulcrumSnapshot *) ALLOC( sizeof(fmDbgFulcrumSnapshot) ); fmRootDebug->fmDbgSnapshots[snapshot] = pSnapshot; if (pSnapshot == NULL) { UNPROTECT_SWITCH(sw); FM_LOG_PRINT("can't allocate memory for snapshot %d\n", snapshot); return; } memset( pSnapshot, 0, sizeof(fmDbgFulcrumSnapshot) ); pSnapshot->sw = sw; fmGetTime(&pSnapshot->timestamp); FM_API_CALL_FAMILY_VOID(switchPtr->DbgTakeChipSnapshot, sw, pSnapshot, fmDbgSaveRegValueInSnapshot); UNPROTECT_SWITCH(sw); } /* end fmDbgTakeChipSnapshot */
/** fmDbgDeleteChipSnapshot * \ingroup diagReg * * \chips FM2000, FM3000, FM4000, FM6000, FM10000 * * \desc Discard a snapshot of the switch's configuration (the * register file) taken with a prior call to * fmDbgTakeChipSnapshot. * * \param[in] snapshot is the snapshot number specified in a prior call * to fmDbgTakeChipSnapshot. * * \return None. * *****************************************************************************/ void fmDbgDeleteChipSnapshot(fm_int snapshot) { if (snapshot < 0 || snapshot >= FM_DBG_MAX_SNAPSHOTS) { FM_LOG_PRINT("snapshot number must be between 0 and %d inclusive\n", FM_DBG_MAX_SNAPSHOTS - 1); return; } if (fmRootDebug->fmDbgSnapshots[snapshot] != NULL) { FREE(fmRootDebug->fmDbgSnapshots[snapshot]); fmRootDebug->fmDbgSnapshots[snapshot] = NULL; FM_LOG_PRINT("Snapshot %d deleted\n", snapshot); } else { FM_LOG_PRINT("Snapshot %d was unused: no action taken\n", snapshot); } } /* end fmDbgDeleteChipSnapshot */
/** fm10000DbgDumpPortMap * \ingroup intDiagPorts * * \desc Display detailed port mapping if there exists an API * call to specific hardware. Otherwise default to * simple fmDbgDumpPortMap function. * * \param[in] sw is the switch whose port map is to be displayed. * * \param[in] port is the port number to be displayed. If the port * value is out of its range, then the entire range will * be displayed. * * \param[in] portType indicates which type port parameter refers to: * 0 - logical port. * 1 - physical port. * 2 - epl port. * * \return FM_OK if successful * \return FM_ERR_INVALID_PORT if port is invalid * *****************************************************************************/ fm_status fm10000DbgDumpPortMap(fm_int sw, fm_int port, fm_int portType) { fm_int logPort; fm_int physPort; fm_int cpi; fm_int filterPhysPort = -1; fm_int filterEpl = -1; fm_status err = FM_OK; fm_switch *switchPtr = GET_SWITCH_PTR(sw); FM_LOG_PRINT("LogPort PhysPort FabricPort EPL/PEP Lane SERDES SBUS Type polarity\n"); switch (portType) { case FM_PORT_DUMP_TYPE_PHYSICAL: filterPhysPort = port; break; case FM_PORT_DUMP_TYPE_EPL: filterEpl = port; break; default: break; } /* end switch (portType) */ for (cpi = 0 ; cpi < switchPtr->numCardinalPorts ; cpi++) { fmMapCardinalPort(sw, cpi, &logPort, &physPort); if ((port != -1) && (logPort != port) && (filterPhysPort == -1) && (filterEpl == -1)) { continue; } err = fm10000DbgDumpLogicalPortMapping(sw, logPort, filterPhysPort, filterEpl); } return err; } /* end fm10000DbgDumpPortMap */
/** fm10000DbgDumpSerDes * \ingroup intSerdes * * \desc Dump debug info for a given SERDES. * * \param[in] sw is the switch on which to operate. * * \param[in] serDes is the SERDES number. * * \param[in] cmd is the command to execude.. * * \return FM_OK if successful. * \return Other ''Status Codes'' as appropriate in case of failure. * *****************************************************************************/ fm_status fm10000DbgDumpSerDes(fm_int sw, fm_int serDes, fm_text cmd) { fm_status err; fm10000_serdes *serdesPtr; fm10000_switch *switchExt; switchExt = GET_SWITCH_EXT(sw); serdesPtr = &switchExt->serdesXServices; err = FM_ERR_UNSUPPORTED; if (cmd == NULL) { err = FM_ERR_INVALID_ARGUMENT; } else if (serdesPtr->magicNumber != FM10000_SERDES_STRUCT_MAGIG_NUMBER) { err = FM_ERR_UNINITIALIZED; } else if (STR_EQ(cmd, "status")) { if (serdesPtr->dbgDumpStatus == NULL) { return FM_ERR_UNSUPPORTED; } err = serdesPtr->dbgDumpStatus(sw,serDes); } else if (STR_EQ(cmd, "imageVersion")) { if (serdesPtr->dbgDumpSpicoSbmVersions == NULL) { return FM_ERR_UNSUPPORTED; } err = serdesPtr->dbgDumpSpicoSbmVersions(sw,serDes); } else if (STR_EQ(cmd, "serdesRegs")) { if (serdesPtr->dbgDumpRegisters == NULL) { return FM_ERR_UNSUPPORTED; } err = serdesPtr->dbgDumpRegisters(sw,serDes); } else if (STR_EQ(cmd, "krStatus")) { if (serdesPtr->dbgDumpKrStatus == NULL) { return FM_ERR_UNSUPPORTED; } err = serdesPtr->dbgDumpKrStatus(sw,serDes); } else if (STR_EQ(cmd, "dfeStatus")) { if (serdesPtr->dbgDumpDfeStatus == NULL) { return FM_ERR_UNSUPPORTED; } err = serdesPtr->dbgDumpDfeStatus(sw,serDes, FALSE); } else if (STR_EQ(cmd, "dfeStatusDetailed")) { if (serdesPtr->dbgDumpDfeStatus == NULL) { return FM_ERR_UNSUPPORTED; } err = serdesPtr->dbgDumpDfeStatus(sw,serDes, TRUE); } else if (STR_EQ(cmd, "resetStats")) { if (serdesPtr->dbgResetStats == NULL) { return FM_ERR_UNSUPPORTED; } err = serdesPtr->dbgResetStats(sw,serDes); } else { err = FM_ERR_INVALID_ARGUMENT; FM_LOG_PRINT("Valid serdes dump commands:\n" " status, imageVersion, serdesRegs, krStatus, and dfeStatus\n"); } return err; }
/* fmPlatformCfgDump * \ingroup intPlatform * * \desc Dump platform configuration. * * \return NONE. * *****************************************************************************/ void fmPlatformCfgDump(void) { fm_platformCfg * platCfg; fm_platformCfgLib * libCfg; fm_platformCfgPort * portCfg; fm_platformCfgLane * laneCfg; fm_platformCfgSwitch *swCfg; fm_platformCfgPhy * phyCfg; fm_gn2412LaneCfg * phyLaneCfg; fm_int swIdx; fm_int portIdx; fm_int epl; fm_int lane; fm_int phyIdx; fm_char tmpStr[MAX_BUF_SIZE+1]; platCfg = FM_PLAT_GET_CFG; PRINT_VALUE("debug", platCfg->debug); PRINT_VALUE("numSwitches", FM_PLAT_NUM_SW); PRINT_STRING("platformName", platCfg->name); PRINT_STRING("fileLockName", platCfg->fileLockName); #ifdef FM_SUPPORT_SWAG PRINT_STRING("topology", GetStrMap( platCfg->topology, swagTopology, FM_NENTRIES(swagTopology), FALSE, tmpStr, sizeof(tmpStr) ) ); #endif for (swIdx = 0 ; swIdx < FM_PLAT_NUM_SW ; swIdx++) { /* Logical switch is the same as swIdx */ FM_LOG_PRINT("################################ SW#%d ################################\n", swIdx); swCfg = FM_PLAT_GET_SWITCH_CFG(swIdx); PRINT_VALUE(" swIdx", swCfg->swIdx); PRINT_VALUE(" switchNumber", swCfg->swNum); PRINT_VALUE(" numPorts", swCfg->numPorts); PRINT_VALUE(" maxLogicalPortValue", swCfg->maxLogicalPortValue); PRINT_VALUE(" ledPollPeriodMsec", swCfg->ledPollPeriodMsec); PRINT_STRING(" ledBlinkMode", GetStrMap( swCfg->ledBlinkMode, ledBlinkModeMap, FM_NENTRIES(ledBlinkModeMap), FALSE, tmpStr, sizeof(tmpStr) ) ); PRINT_VALUE(" xcvrPollPeriodMsec", swCfg->xcvrPollPeriodMsec); PRINT_VALUE(" intrPollPeriodMsec", swCfg->intrPollPeriodMsec); PRINT_STRING(" uioDevName", swCfg->uioDevName); PRINT_STRING(" netDevName", swCfg->netDevName); PRINT_STRING(" devMemOffset", swCfg->devMemOffset); PRINT_VALUE(" gpioPortIntr", swCfg->gpioPortIntr); PRINT_VALUE(" gpioI2cReset", swCfg->gpioI2cReset); PRINT_VALUE(" gpioFlashWP", swCfg->gpioFlashWP); PRINT_VALUE(" enablePhyDeEmphasis", swCfg->enablePhyDeEmphasis); PRINT_VALUE(" vrm.useDefVoltages", swCfg->vrm.useDefVoltages); PRINT_VALUE(" VDDS.hwResourceId", swCfg->vrm.hwResourceId[FM_PLAT_VRM_VDDS]); PRINT_VALUE(" VDDF.hwResourceId", swCfg->vrm.hwResourceId[FM_PLAT_VRM_VDDF]); PRINT_VALUE(" AVDD.hwResourceId", swCfg->vrm.hwResourceId[FM_PLAT_VRM_AVDD]); PRINT_VALUE(" fhClock", swCfg->fhClock); #ifdef FM_SUPPORT_SWAG PRINT_STRING(" switchRole", GetStrMap( swCfg->switchRole, swagRole, FM_NENTRIES(swagRole), FALSE, tmpStr, sizeof(tmpStr) ) ); #endif for (portIdx = 0 ; portIdx < FM_PLAT_NUM_PORT(swIdx) ; portIdx++) { portCfg = FM_PLAT_GET_PORT_CFG(swIdx, portIdx); FM_LOG_PRINT("==============Port Index %d============\n", portIdx); PRINT_VALUE(" logicalPort", portCfg->port); PRINT_VALUE(" hwResourceId", portCfg->hwResourceId); PRINT_VALUE(" physPort", portCfg->physPort); PRINT_VALUE(" epl", portCfg->epl); PRINT_VALUE(" lane[0]", portCfg->lane[0]); PRINT_VALUE(" lane[1]", portCfg->lane[1]); PRINT_VALUE(" lane[2]", portCfg->lane[2]); PRINT_VALUE(" lane[3]", portCfg->lane[3]); PRINT_VALUE(" pep", portCfg->pep); PRINT_VALUE(" tunnel", portCfg->tunnel); PRINT_VALUE(" loopback", portCfg->loopback); PRINT_VALUE(" speed", portCfg->speed); PRINT_VALUE(" autodetect", portCfg->autodetect); PRINT_STRING( " ethMode", GetStrMap( portCfg->ethMode, ethModeMap, FM_NENTRIES(ethModeMap), TRUE, tmpStr, sizeof(tmpStr) ) ); PRINT_STRING( " portType", GetStrMap( portCfg->portType, portTypeMap, FM_NENTRIES(portTypeMap), FALSE, tmpStr, sizeof(tmpStr) ) ); PRINT_STRING( " intfType", GetStrMap( portCfg->intfType, intfTypeMap, FM_NENTRIES(intfTypeMap), FALSE, tmpStr, sizeof(tmpStr) ) ); PRINT_STRING( " capability", GetStrBitMap( portCfg->cap, portCapMap, FM_NENTRIES(portCapMap), tmpStr, sizeof(tmpStr) ) ); PRINT_STRING(" dfeMode", GetStrMap(portCfg->dfeMode, dfeModeMap, FM_NENTRIES(dfeModeMap), FALSE, tmpStr, sizeof(tmpStr) ) ); PRINT_STRING( " an73Ability", GetStrBitMap( portCfg->an73Ability, an73AbilityMap, FM_NENTRIES(an73AbilityMap), tmpStr, sizeof(tmpStr) ) ); PRINT_VALUE(" phyNum", portCfg->phyNum); PRINT_VALUE(" phyPort", portCfg->phyPort); #ifdef FM_SUPPORT_SWAG PRINT_STRING(" swagLinkType", GetStrMap( portCfg->swagLink.type, swagLinkType, FM_NENTRIES(swagLinkType), FALSE, tmpStr, sizeof(tmpStr) ) ); if (portCfg->swagLink.type == FM_SWAG_LINK_INTERNAL) { FM_LOG_PRINT(" SWAG port %d <--> SWAG port %d\n", portCfg->swagLink.logicalPort, portCfg->swagLink.partnerLogicalPort); FM_LOG_PRINT(" SW %d, port %d <--> SW %d, port %d\n", portCfg->swagLink.swId, portCfg->swagLink.swPort, portCfg->swagLink.partnerSwitch, portCfg->swagLink.partnerPort); } else if (portCfg->swagLink.type == FM_SWAG_LINK_EXTERNAL) { FM_LOG_PRINT(" SWAG port %d, SW %d, port %d\n", portCfg->swagLink.logicalPort, portCfg->swagLink.swId, portCfg->swagLink.swPort); } #endif FM_LOG_PRINT("\n"); } for (epl = 0 ; epl < FM_PLAT_NUM_EPL ; epl++) { FM_LOG_PRINT("#######################################\n"); FM_LOG_PRINT("# EPL %d #\n", epl); FM_LOG_PRINT("#######################################\n"); PRINT_VALUE(" laneToPortIdx[0]", swCfg->epls[epl].laneToPortIdx[0]); PRINT_VALUE(" laneToPortIdx[1]", swCfg->epls[epl].laneToPortIdx[1]); PRINT_VALUE(" laneToPortIdx[2]", swCfg->epls[epl].laneToPortIdx[2]); PRINT_VALUE(" laneToPortIdx[3]", swCfg->epls[epl].laneToPortIdx[3]); for (lane = 0 ; lane < FM_PLAT_LANES_PER_EPL ; lane++) { FM_LOG_PRINT("============ EPL %d, lane %d ============\n", epl, lane); laneCfg = &swCfg->epls[epl].lane[lane]; PRINT_STRING(" lanePolarity", GetStrMap(laneCfg->lanePolarity, lanePolarityMap, FM_NENTRIES(lanePolarityMap), FALSE, tmpStr, sizeof(tmpStr))); PRINT_STRING(" rxTermination", GetStrMap(laneCfg->rxTermination, rxTerminationMap, FM_NENTRIES(rxTerminationMap), FALSE, tmpStr, sizeof(tmpStr))); PRINT_VALUE(" preCursor1GCopper", laneCfg->copper[BPS_1G].preCursor); PRINT_VALUE(" preCursor10GCopper", laneCfg->copper[BPS_10G].preCursor); PRINT_VALUE(" preCursor25GCopper", laneCfg->copper[BPS_25G].preCursor); PRINT_VALUE(" preCursor1GOptical", laneCfg->optical[BPS_1G].preCursor); PRINT_VALUE(" preCursor10GOptical", laneCfg->optical[BPS_10G].preCursor); PRINT_VALUE(" preCursor25GOptical", laneCfg->optical[BPS_25G].preCursor); PRINT_VALUE(" cursor1GCopper", laneCfg->copper[BPS_1G].cursor); PRINT_VALUE(" cursor10GCopper", laneCfg->copper[BPS_10G].cursor); PRINT_VALUE(" cursor25GCopper", laneCfg->copper[BPS_25G].cursor); PRINT_VALUE(" cursor1GOptical", laneCfg->optical[BPS_1G].cursor); PRINT_VALUE(" cursor10GOptical", laneCfg->optical[BPS_10G].cursor); PRINT_VALUE(" cursor25GOptical", laneCfg->optical[BPS_25G].cursor); PRINT_VALUE(" postCursor1GCopper", laneCfg->copper[BPS_1G].postCursor); PRINT_VALUE(" postCursor10GCopper", laneCfg->copper[BPS_10G].postCursor); PRINT_VALUE(" postCursor25GCopper", laneCfg->copper[BPS_25G].postCursor); PRINT_VALUE(" postCursor1GOptical", laneCfg->optical[BPS_1G].postCursor); PRINT_VALUE(" postCursor10GOptical", laneCfg->optical[BPS_10G].postCursor); PRINT_VALUE(" postCursor25GOptical", laneCfg->optical[BPS_25G].postCursor); FM_LOG_PRINT("\n"); } FM_LOG_PRINT("\n"); } for ( phyIdx = 0 ; phyIdx < FM_PLAT_NUM_PHY(swIdx) ; phyIdx++ ) { phyCfg = FM_PLAT_GET_PHY_CFG(swIdx, phyIdx); FM_LOG_PRINT("==============PHY Index %d============\n", phyIdx); PRINT_STRING(" model", GetStrMap( phyCfg->model, phyModelMap, FM_NENTRIES(phyModelMap), FALSE, tmpStr, sizeof(tmpStr) ) ); PRINT_VALUE(" addr", phyCfg->addr); PRINT_VALUE(" hwResourceId", phyCfg->hwResourceId); if ( phyCfg->model == FM_PLAT_PHY_GN2412 ) { for ( lane = 0 ; lane < FM_GN2412_NUM_LANES ; lane++ ) { phyLaneCfg = &phyCfg->gn2412Lane[lane]; FM_LOG_PRINT(" ======== GN2412 %d, lane %d ========\n", phyIdx, lane); PRINT_VALUE(" appMode", phyLaneCfg->appMode); PRINT_VALUE(" polarity", phyLaneCfg->polarity); PRINT_VALUE(" preTap", phyLaneCfg->preTap); PRINT_VALUE(" attenuation", phyLaneCfg->attenuation); PRINT_VALUE(" postTap", phyLaneCfg->postTap); } } FM_LOG_PRINT("\n"); } FM_LOG_PRINT(" Shared Library Config:\n"); libCfg = FM_PLAT_GET_LIBS_CFG(swIdx); PRINT_STRING(" sharedLibraryName", libCfg->libName); PRINT_STRING(" disableFuncIntf", GetStrBitMap( libCfg->disableFuncIntf, disableFuncIntfMap, FM_NENTRIES(disableFuncIntfMap), tmpStr, sizeof(tmpStr) ) ); PRINT_VALUE(" tlvCfgBufSize", libCfg->tlvCfgBufSize); PRINT_VALUE(" tlvCfgLen", libCfg->tlvCfgLen); FM_LOG_PRINT("#######################################################################\n\n"); } return; } /* end fmPlatformCfgDump */
/** fmDbgDumpParityErrorEvent * \ingroup intParity * * \desc Dumps a parity error event structure. * * \param[in] sw is the switch on which to operate. * * \param[in] parityEvent points to the parity event object. * * \return None * *****************************************************************************/ void fmDbgDumpParityErrorEvent(fm_int sw, fm_eventParityError * parityEvent) { fm_int i; FM_LOG_PRINT("\nParity event on switch %d:\n", sw); FM_LOG_PRINT(" Error Type : %s\n", fmParityErrTypeToText(parityEvent->errType)); FM_LOG_PRINT(" Severity : %s\n", fmParitySeverityToText(parityEvent->paritySeverity)); FM_LOG_PRINT(" Status : %s\n", fmParityStatusToText(parityEvent->parityStatus)); FM_LOG_PRINT(" Memory Area : %s\n", fmParityMemAreaToText(parityEvent->memoryArea)); switch ( parityEvent->errType ) { case FM_PARITY_ERRTYPE_CACHE_MISMATCH: FM_LOG_PRINT(" Base Addr : %08x\n", parityEvent->baseAddr); break; case FM_PARITY_ERRTYPE_SRAM_CORRECTED: case FM_PARITY_ERRTYPE_SRAM_UNCORRECTABLE: FM_LOG_PRINT(" SRAM Number : %d\n", parityEvent->sramNo); break; default: break; } if ( parityEvent->numIndices != 0 ) { FM_LOG_PRINT(" Indices :"); for ( i = 0 ; i < (fm_int)parityEvent->numIndices ; i++ ) { FM_LOG_PRINT(" %d", parityEvent->tableIndices[i]); } FM_LOG_PRINT("\n"); } if ( parityEvent->numValidData != 0 ) { FM_LOG_PRINT(" Bad Data :"); for ( i = (fm_int)parityEvent->numValidData - 1 ; i >= 0 ; i-- ) { FM_LOG_PRINT(" %08x", parityEvent->badData[i]); } FM_LOG_PRINT("\n"); FM_LOG_PRINT(" Good Data :"); for ( i = (fm_int)parityEvent->numValidData - 1 ; i >= 0 ; i-- ) { FM_LOG_PRINT(" %08x", parityEvent->cachedData[i]); } FM_LOG_PRINT("\n"); } if ( parityEvent->numErrors != 0 ) { FM_LOG_PRINT(" Error Count : %d\n", parityEvent->numErrors); } } /* end fmDbgDumpParityErrorEvent */
/** fm10000DbgDumpSFlows * \ingroup intSflow * * \desc Dumps information about the SFLOW subsystem. * * \param[in] sw is the switch on which to operate. * * \return FM_OK if successful. * *****************************************************************************/ fm_status fm10000DbgDumpSFlows(fm_int sw) { fm10000_sflowEntry *sflowEntry; fm_int sflowId; fm_text typeText; fm_int portList[48]; fm_int numPorts; VALIDATE_AND_PROTECT_SWITCH(sw); FM_LOG_PRINT("\n"); FM_LOG_PRINT("Id MirId sflowType vlanID ports\n"); FM_LOG_PRINT("-- ---- --------- ------ --------------------\n"); for (sflowId = 0 ; sflowId < FM10000_MAX_SFLOWS ; ++sflowId) { sflowEntry = GetSflowEntry(sw, sflowId); if (!sflowEntry || !sflowEntry->isValid) { continue; } switch (sflowEntry->sflowType) { case FM_SFLOW_TYPE_INGRESS: typeText = "ingress"; break; case FM_SFLOW_TYPE_EGRESS: typeText = "egress"; break; default: typeText = "unknown"; break; } FM_LOG_PRINT("%2d %4d %-9s ", sflowId, sflowEntry->mirrorId, typeText); if (sflowEntry->vlanID == FM_SFLOW_VLAN_ANY) { FM_LOG_PRINT("%5s ", "ANY"); } else { FM_LOG_PRINT("%5u ", sflowEntry->vlanID); } fm10000GetSFlowPortList(sw, sflowId, &numPorts, portList, 48); fmDbgPrintPortList(sw, numPorts, portList); FM_LOG_PRINT("\n"); } /* end for (sflowId = 0 ; sflowId < FM10000_MAX_SFLOWS ; ++sflowId) */ UNPROTECT_SWITCH(sw); return FM_OK; } /* end fm10000DbgDumpSFlows */
/** fm10000DbgDumpLogicalPortMapping * \ingroup intDiagPorts * * \desc Display detailed port mapping information. * * \param[in] sw is the switch whose port map is to be displayed. * * \param[in] logPort is the port number to be displayed. * * \param[in] filterPhysPort specifies only ports matching to * physical port to be displayed. * * \param[in] filterEpl specifies only ports matching to * EPL port to be displayed. * * \return FM_OK if successful * *****************************************************************************/ fm_status fm10000DbgDumpLogicalPortMapping(fm_int sw, fm_int logPort, fm_int filterPhysPort, fm_int filterEpl) { fm10000_port *portExt; fm_int physPort; fm_int fabricPort; fm_int tmp; fm_int eplPep; /* EPL or PEP */ fm_int channel; fm_int laneNum; /* As argument to port attribute function */ fm_int laneCount; /* Number of lanes for the port */ fm_int serdes; fm_int ethMode; fm_uint32 rxPolarity; fm_uint32 txPolarity; fm_uint sbusAddr; fm_serdesRing ring; fm_status status = FM_OK; fm_char logPortStr[MAX_STR_LEN]; fm_char eplPepStr[MAX_STR_LEN]; fm_char serdesStr[MAX_STR_LEN]; fm_char fabPortStr[MAX_STR_LEN]; fm_char physPortStr[MAX_STR_LEN]; fm_char channelStr[MAX_STR_LEN]; fm_char sbusStr[MAX_STR_LEN]; fm_char modeStr[MAX_STR_LEN]; fm_char polarityStr[MAX_STR_LEN]; if (!fmIsCardinalPort(sw, logPort)) { /* Ignore it */ return FM_OK; } FM_SNPRINTF_S(logPortStr, MAX_STR_LEN, "%s", "--"); FM_SNPRINTF_S(eplPepStr, MAX_STR_LEN, "%s", "--"); FM_SNPRINTF_S(serdesStr, MAX_STR_LEN, "%s", "--"); FM_SNPRINTF_S(fabPortStr, MAX_STR_LEN, "%s", "--"); FM_SNPRINTF_S(physPortStr, MAX_STR_LEN, "%s", "--"); FM_SNPRINTF_S(channelStr, MAX_STR_LEN, "%s", "--"); FM_SNPRINTF_S(sbusStr, MAX_STR_LEN, "%s", "--"); FM_SNPRINTF_S(modeStr, MAX_STR_LEN, "%s", "----------"); FM_SNPRINTF_S(polarityStr, MAX_STR_LEN, "%s", "----"); status = fmPlatformMapLogicalPortToPhysical(sw, logPort, &sw, &physPort); FM_LOG_ABORT_ON_ERR(FM_LOG_CAT_DEBUG, status); if (filterPhysPort > 0 && filterPhysPort != physPort) { return FM_OK; } if (status == FM_OK) { FM_SNPRINTF_S(physPortStr, MAX_STR_LEN, "%d", physPort); } FM_SNPRINTF_S(logPortStr, MAX_STR_LEN, "%d", logPort); status = fm10000MapPhysicalPortToEplChannel(sw, physPort, &eplPep, &channel); /* Could fail here */ if (filterEpl > 0 && status && filterEpl != eplPep) { return FM_OK; } if (status) { status = fm10000MapLogicalPortToPep(sw, logPort, &eplPep); } if (status == FM_OK) { FM_SNPRINTF_S(eplPepStr, MAX_STR_LEN, "%d", eplPep); } else { eplPep = -1; } status = fm10000MapPhysicalPortToFabricPort(sw, physPort, &fabricPort); if (status == FM_OK) { FM_SNPRINTF_S(fabPortStr, MAX_STR_LEN, "%d", fabricPort); } status = fm10000GetNumLanes(sw, logPort, &laneCount); FM_LOG_ABORT_ON_ERR(FM_LOG_CAT_DEBUG, status); status = fm10000GetPortAttribute(sw, logPort, FM_PORT_ACTIVE_MAC, FM_PORT_LANE_NA, FM_PORT_ETHERNET_INTERFACE_MODE, ðMode); if (status != FM_OK) { ethMode = FM_ETH_MODE_DISABLED; } status = fm10000GetPortModeName(sw, logPort, modeStr, MAX_STR_LEN); FM_LOG_ABORT_ON_ERR(FM_LOG_CAT_DEBUG, status); for (laneNum = 0; laneNum < laneCount; laneNum++) { if (eplPep >= 0) { status = fm10000MapPortLaneToSerdes(sw, logPort, laneNum, &serdes); if (status == FM_OK) { FM_SNPRINTF_S(serdesStr, MAX_STR_LEN, "%d", serdes); status = fm10000MapSerdesToSbus(sw, serdes, &sbusAddr, &ring); if (status == FM_OK) { FM_SNPRINTF_S(sbusStr, MAX_STR_LEN, "%02x", sbusAddr); } status = fm10000MapSerdesToEplLane(sw, serdes, &tmp, &channel); if (status == FM_OK) { FM_SNPRINTF_S(channelStr, MAX_STR_LEN, "%d", channel); } } status = fm10000GetPortAttribute(sw, logPort, FM_PORT_ACTIVE_MAC, laneNum, FM_PORT_RX_LANE_POLARITY, &rxPolarity); status = fm10000GetPortAttribute(sw, logPort, FM_PORT_ACTIVE_MAC, laneNum, FM_PORT_TX_LANE_POLARITY, &txPolarity); if (rxPolarity && txPolarity) { FM_SNPRINTF_S(polarityStr, MAX_STR_LEN, "%s", "RXTX"); } else if (rxPolarity) { FM_SNPRINTF_S(polarityStr, MAX_STR_LEN, "%s", "RX"); } else if (txPolarity) { FM_SNPRINTF_S(polarityStr, MAX_STR_LEN, "%s", "TX"); } else { FM_SNPRINTF_S(polarityStr, MAX_STR_LEN, "%s", "NONE");; } } portExt = GET_PORT_EXT(sw, logPort); if (laneCount > 1) { FM_SNPRINTF_S(logPortStr, MAX_STR_LEN, "%d.%d", logPort, laneNum); if (laneNum > 0) { /* Not applicable for lane > 0 */ FM_SNPRINTF_S(eplPepStr, MAX_STR_LEN, "%s", "--"); FM_SNPRINTF_S(fabPortStr, MAX_STR_LEN, "%s", "--"); FM_SNPRINTF_S(physPortStr, MAX_STR_LEN, "%s", "--"); FM_SNPRINTF_S(modeStr, MAX_STR_LEN, "%s", "----------"); } } FM_LOG_PRINT("%-4s %8s %8s %8s %7s %5s %5s %15s %8s\n", logPortStr, physPortStr, fabPortStr, eplPepStr, channelStr, serdesStr, sbusStr, modeStr, polarityStr); } return FM_OK; ABORT: return status; } /* end fm10000DbgDumpLogicalPortMapping */
/** fm10000DbgDumpMACTableEntry * \ingroup intDiagMATable * * \desc Display a specific entry in the switch's MAC Address Table * and the memory-based copy of the table entry. * * \param[in] sw is the switch on which to operate. * * \param[in] address is the MAC address of the entry to display. * * \param[in] vlan is the VLAN ID of the entry to display. * * \return None. * *****************************************************************************/ void fm10000DbgDumpMACTableEntry(fm_int sw, fm_macaddr address, fm_uint16 vlan) { fm_internalMacAddrEntry cacheEntry; fm10000_maTableEntry dmacEntry; fm10000_maTableEntry smacEntry; fm_switch * switchPtr; fm_uint16 indexes[FM10000_MAC_ADDR_BANK_COUNT]; fm_uint32 hashIndex; fm_status status; fm_int bankId; fm_uint16 learningFID; fm_bool found; switchPtr = GET_SWITCH_PTR(sw); FM_LOG_PRINT("\n"); status = fm10000GetLearningFID(sw, vlan, &learningFID); if (status != FM_OK) { return; } status = fm10000ComputeAddressIndex(sw, address, learningFID, 0, indexes); if (status != FM_OK) { return; } found = FALSE; for (bankId = switchPtr->macTableBankCount - 1 ; bankId >= 0 ; bankId--) { hashIndex = indexes[bankId]; FM_TAKE_L2_LOCK(sw); cacheEntry = switchPtr->maTable[hashIndex]; FM_DROP_L2_LOCK(sw); if ( (cacheEntry.state != FM_MAC_ENTRY_STATE_INVALID) && (cacheEntry.macAddress == address) && (cacheEntry.vlanID == learningFID) ) { /* Found the requested entry. */ found = TRUE; break; } } if (found) { status = ReadMacTableEntries(sw, hashIndex, &dmacEntry, &smacEntry); if (status == FM_OK) { DumpMacTableEntry(hashIndex, &cacheEntry, &dmacEntry, &smacEntry); } } else { FM_LOG_PRINT("Entry not found for macAddress %012llx vlan %u (fid %u).\n", address, vlan, learningFID); } } /* end fm10000DbgDumpMACTableEntry */
/** fm10000DbgDumpMACTable * \ingroup intDiagMATable * * \desc Display a given number of entries or count the number of * entries in the switch's MAC Address Table and the * memory-based copy of the table. * * \param[in] sw is the switch on which to operate. * * \param[in] numEntries is the number of entries to display. Specify * 0 for the first 10 entries only. Specify -1 to just count * the number of entries in the table without displaying them. * * \return None. * *****************************************************************************/ void fm10000DbgDumpMACTable(fm_int sw, fm_int numEntries) { fm_switch * switchPtr; fm_internalMacAddrEntry cacheEntry; fm10000_maTableEntry dmacEntry; fm10000_maTableEntry smacEntry; fm_status status; fm_int index; fm_int entriesReported; fm_bool countOnly; switchPtr = GET_SWITCH_PTR(sw); entriesReported = 0; countOnly = FALSE; if (numEntries < 0) { countOnly = TRUE; numEntries = switchPtr->macTableSize; } else if (numEntries == 0) { numEntries = 10; } for (index = 0 ; index < switchPtr->macTableSize ; ++index) { /* Get cache entry. */ FM_TAKE_L2_LOCK(sw); cacheEntry = switchPtr->maTable[index]; FM_DROP_L2_LOCK(sw); /* Retrieve MAC table entries. */ status = ReadMacTableEntries(sw, index, &dmacEntry, &smacEntry); if (status != FM_OK) { return; } if (dmacEntry.valid || smacEntry.valid || cacheEntry.state != FM_MAC_ENTRY_STATE_INVALID) { if (!countOnly) { DumpMacTableEntry(index, &cacheEntry, &dmacEntry, &smacEntry); } if (++entriesReported >= numEntries) { break; } } /* end if (dmacEntry.valid) */ } /* end for (index = 0 ; index < switchPtr->macTableSize ; ++index) */ FM_LOG_PRINT("%d %s %s\n", entriesReported, (entriesReported == 1) ? "entry" : "entries", (countOnly) ? "in table" : "listed"); } /* end fm10000DbgDumpMACTable */
/** DumpMacTableEntry * \ingroup intDiagMATable * * \desc Output an MA Table entry as it appears in hardware and * in the memory-based cache. * * \param[in] index is the index into the MA Table. * * \param[in] cacheEntry points to a copy of the memory-based cache * entry. * * \param[in] dmacEntry points to a structure containing the decoded * destination MAC table entry. * * \param[in] smacEntry points to a structure containing the decoded * source MAC table entry. * * \return None. * *****************************************************************************/ static void DumpMacTableEntry(fm_int index, fm_internalMacAddrEntry * cacheEntry, fm10000_maTableEntry * dmacEntry, fm10000_maTableEntry * smacEntry) { char dmacVal[32]; char smacVal[32]; char cacheVal[32]; FM_LOG_PRINT("MA_TABLE[%d]:\n\n", index); #define HDR_FMT "%-14s %-18s %-18s %s\n" #define STR_FMT "%-14s : %-18s %-18s %s\n" #define DEC_FMT "%-14s : %-18d %-18d %d\n" #define FILL_VAL "--" FM_LOG_PRINT(HDR_FMT, "", "CACHE ENTRY", "DMAC ENTRY", "SMAC ENTRY"); FM_LOG_PRINT(STR_FMT, "State", fmEntryStateToText(cacheEntry->state), (dmacEntry->valid) ? "Valid" : "Invalid", (smacEntry->valid) ? "Valid" : "Invalid"); FM_SNPRINTF_S(cacheVal, sizeof(cacheVal), "%012llx", cacheEntry->macAddress); FM_SNPRINTF_S(dmacVal, sizeof(dmacVal), "%012llx", dmacEntry->macAddress); FM_SNPRINTF_S(smacVal, sizeof(smacVal), "%012llx", smacEntry->macAddress); FM_LOG_PRINT(STR_FMT, "MAC Address", cacheVal, dmacVal, smacVal); FM_LOG_PRINT(DEC_FMT, "FID", cacheEntry->vlanID, dmacEntry->fid, smacEntry->fid); FM_LOG_PRINT(STR_FMT, "Address Type", fmAddressTypeToText(cacheEntry->addrType), FILL_VAL, FILL_VAL); FM_SNPRINTF_S(cacheVal, sizeof(cacheVal), "%s", FILL_VAL); FM_SNPRINTF_S(dmacVal, sizeof(dmacVal), "0x%04x", dmacEntry->glort); FM_SNPRINTF_S(smacVal, sizeof(smacVal), "0x%04x", smacEntry->glort); FM_LOG_PRINT(STR_FMT, "Glort", cacheVal, dmacVal, smacVal); FM_LOG_PRINT(DEC_FMT, "Port", cacheEntry->port, dmacEntry->port, smacEntry->port); FM_LOG_PRINT(DEC_FMT, "Trigger", cacheEntry->trigger, dmacEntry->trigger, smacEntry->trigger); FM_LOG_PRINT(STR_FMT, "Secure", FM_BOOLSTRING(FM_IS_ADDR_TYPE_SECURE(cacheEntry->addrType)), FM_BOOLSTRING(dmacEntry->secure), FM_BOOLSTRING(smacEntry->secure)); FM_LOG_PRINT("\n"); } /* end DumpMacTableEntry */
/* _fmPlatformFm10000I2cWriteRead * \ingroup intPlatformfm10000I2c * * \desc Write to then immediately read from an I2C device with * handling max response bytes using switch as I2C master. * * \param[in] handle is the memory pointer to the switch. * * \param[in] device is the I2C device address (0x00 - 0x7F). * * \param[in,out] data points to an array from which data is written and * into which data is read. * * \param[in] wl is the number of bytes to write. * * \param[in] rl is the number of bytes to read. * * \return FM_OK if successful. * \return Other ''Status Codes'' as appropriate in case of * failure. * *****************************************************************************/ static fm_status _fmPlatformFm10000I2cWriteRead(fm_uintptr handle, fm_uint device, fm_byte *data, fm_uint wl, fm_uint rl) { fm_status status; fm_uint32 regValue; fm_uint i; fm_uint j; fm_bool isTimeout; struct timeval startTime; fm_uint32 *memPtr; fm_uint32 tmp; if (i2cDebug & 0x4) { FM_LOG_PRINT("fmPlatformfm10000I2cWriteRead " "handle=%p device=0x%x wl=%d rl=%d\n", (void*)handle, device, wl, rl); } memPtr = (fm_uint32*)handle; if (rl > I2C_MAX_LEN) { FM_LOG_EXIT(FM_LOG_CAT_PLATFORM, FM_ERR_INVALID_ARGUMENT); } if (wl > I2C_MAX_LEN) { FM_LOG_EXIT(FM_LOG_CAT_PLATFORM, FM_ERR_INVALID_ARGUMENT); } if (data == NULL) { FM_LOG_EXIT(FM_LOG_CAT_PLATFORM, FM_ERR_INVALID_ARGUMENT); } for (i = 0 ; i < (wl+3)/4 ; i++) { regValue = 0; for (j = 0 ; j < 4 ; j++) { if ((i*4 + j) < wl) { regValue |= (data[i*4 + j] << ((3 - j)*8)); } } status = WriteSwitchMemMap(memPtr, FM10000_I2C_DATA(i), regValue); FM_LOG_EXIT_ON_ERR(FM_LOG_CAT_PLATFORM, status); if (i2cDebug & 0x4) { FM_LOG_PRINT("WRITEDATA#%d : 0x%08x\n",i, regValue); } } regValue = 0; FM_SET_FIELD(regValue, FM10000_I2C_CTRL, Addr, (device << 1)); FM_SET_FIELD(regValue, FM10000_I2C_CTRL, Command, 0); FM_SET_FIELD(regValue, FM10000_I2C_CTRL, LengthW, wl); FM_SET_FIELD(regValue, FM10000_I2C_CTRL, LengthR, rl); if (i2cDebug & 0x4) { FM_LOG_PRINT("WRITE: eg 0x%08x Cmd %d wl %d rl %d " "Comp %x LenSent %d intr %d\n", regValue, FM_GET_FIELD(regValue, FM10000_I2C_CTRL, Command), FM_GET_FIELD(regValue, FM10000_I2C_CTRL, LengthW), FM_GET_FIELD(regValue, FM10000_I2C_CTRL, LengthR), FM_GET_FIELD(regValue, FM10000_I2C_CTRL, CommandCompleted), FM_GET_FIELD(regValue, FM10000_I2C_CTRL, LengthSent), FM_GET_BIT(regValue, FM10000_I2C_CTRL, InterruptPending)); } status = WriteSwitchMemMap(memPtr, FM10000_I2C_CTRL, regValue); FM_LOG_EXIT_ON_ERR(FM_LOG_CAT_PLATFORM, status); status = ReadSwitchMemMap(memPtr, FM10000_I2C_CTRL, &tmp); FM_LOG_EXIT_ON_ERR(FM_LOG_CAT_PLATFORM, status); if (i2cDebug & 0x4) { FM_LOG_PRINT("READ: %d reg 0x%08x Cmd %d wl %d rl %d " "Comp %x LenSent %d intr %d\n", status, tmp, FM_GET_FIELD(tmp, FM10000_I2C_CTRL, Command), FM_GET_FIELD(tmp, FM10000_I2C_CTRL, LengthW), FM_GET_FIELD(tmp, FM10000_I2C_CTRL, LengthR), FM_GET_FIELD(tmp, FM10000_I2C_CTRL, CommandCompleted), FM_GET_FIELD(tmp, FM10000_I2C_CTRL, LengthSent), FM_GET_BIT(tmp, FM10000_I2C_CTRL, InterruptPending)); } /* Now change command to start the transaction */ if (rl == 0) { /* Write only allow write of 0 length */ FM_SET_FIELD(regValue, FM10000_I2C_CTRL, Command, 1); } else if ((wl > 0) && (rl > 0)) { /* Write Read */ FM_SET_FIELD(regValue, FM10000_I2C_CTRL, Command, 2); } else { /* Read */ FM_SET_FIELD(regValue, FM10000_I2C_CTRL, Command, 3); } if (i2cDebug & 0x4) { FM_LOG_PRINT("WRITE2: reg 0x%08x Cmd %d wl %d rl %d " "Comp %x LenSent %d intr %d\n", regValue, FM_GET_FIELD(regValue, FM10000_I2C_CTRL, Command), FM_GET_FIELD(regValue, FM10000_I2C_CTRL, LengthW), FM_GET_FIELD(regValue, FM10000_I2C_CTRL, LengthR), FM_GET_FIELD(regValue, FM10000_I2C_CTRL, CommandCompleted), FM_GET_FIELD(regValue, FM10000_I2C_CTRL, LengthSent), FM_GET_BIT(regValue, FM10000_I2C_CTRL, InterruptPending)); } status = WriteSwitchMemMap(memPtr, FM10000_I2C_CTRL, regValue); FM_LOG_EXIT_ON_ERR(FM_LOG_CAT_PLATFORM, status); status = ReadSwitchMemMap(memPtr, FM10000_I2C_CTRL, ®Value); FM_LOG_EXIT_ON_ERR(FM_LOG_CAT_PLATFORM, status); if (i2cDebug & 0x4) { FM_LOG_PRINT("READ2: %d reg 0x%08x Cmd %d wl %d rl %d " "Comp %x LenSent %d intr %d\n", status, regValue, FM_GET_FIELD(regValue, FM10000_I2C_CTRL, Command), FM_GET_FIELD(regValue, FM10000_I2C_CTRL, LengthW), FM_GET_FIELD(regValue, FM10000_I2C_CTRL, LengthR), FM_GET_FIELD(regValue, FM10000_I2C_CTRL, CommandCompleted), FM_GET_FIELD(regValue, FM10000_I2C_CTRL, LengthSent), FM_GET_BIT(regValue, FM10000_I2C_CTRL, InterruptPending)); } /* Poll to check for command done */ gettimeofday(&startTime, NULL); isTimeout = FALSE; do { usleep(10000); if (isTimeout) { FM_LOG_ERROR( FM_LOG_CAT_PLATFORM, "Dev=0x%02x: Timeout (%d msec) waiting " "for I2C_CTRL(0x%x).CommandCompleted!=0. 0x%02x\n", device, I2C_TIMEOUT, FM10000_I2C_CTRL, FM_GET_FIELD(regValue, FM10000_I2C_CTRL, CommandCompleted)); FM_LOG_EXIT(FM_LOG_CAT_PLATFORM, FM_ERR_I2C_NO_RESPONSE); } /* Variable isTimeout is used to improve the timeout detecting */ if (GetTimeIntervalMsec(&startTime, NULL) > I2C_TIMEOUT) { isTimeout = TRUE; } status = ReadSwitchMemMap(memPtr, FM10000_I2C_CTRL, ®Value); if (i2cDebug & 0x4) { FM_LOG_PRINT( "STATUS: %d reg 0x%08x cmd %d wl %d rl %d " "Comp %x LenSent %d intr %d\n", status, regValue, FM_GET_FIELD(regValue, FM10000_I2C_CTRL, Command), FM_GET_FIELD(regValue, FM10000_I2C_CTRL, LengthW), FM_GET_FIELD(regValue, FM10000_I2C_CTRL, LengthR), FM_GET_FIELD(regValue, FM10000_I2C_CTRL, CommandCompleted), FM_GET_FIELD(regValue, FM10000_I2C_CTRL, LengthSent), FM_GET_BIT(regValue, FM10000_I2C_CTRL, InterruptPending)); } if (status) break; } while (FM_GET_FIELD(regValue, FM10000_I2C_CTRL, CommandCompleted) == 0); if (FM_GET_FIELD(regValue, FM10000_I2C_CTRL, CommandCompleted) != 1) { if (FM_GET_FIELD(regValue, FM10000_I2C_CTRL, CommandCompleted) == 3) { if (i2cDebug & 0x4) { FM_LOG_PRINT("No ACK received for address 0x%02x\n", device); } } else { FM_LOG_ERROR(FM_LOG_CAT_PLATFORM, "Dev=0x%02x: I2C Command completed with error 0x%x. " "I2C_CTRL(0x%x)=0x%x\n", device, FM_GET_FIELD(regValue, FM10000_I2C_CTRL, CommandCompleted), FM10000_I2C_CTRL, regValue); } FM_LOG_EXIT(FM_LOG_CAT_PLATFORM, FM_ERR_I2C_NO_RESPONSE); } for (i = 0 ; i < (rl+3)/4 ; i++) { status = ReadSwitchMemMap(memPtr, FM10000_I2C_DATA(i), ®Value); FM_LOG_EXIT_ON_ERR(FM_LOG_CAT_PLATFORM, status); if (i2cDebug & 0x4) { FM_LOG_PRINT("READDATA#%d : 0x%08x\n",i, regValue); } for (j = 0 ; j < 4 ; j++) { if ((i*4 + j) < rl) { data[i*4 + j] = (regValue >> ((3 - j)*8)) & 0xFF; } } }
/** fm6000DbgDumpVid * \ingroup intDiagMisc * * \desc Dumps VID table for a switch. * * \param[in] sw is the switch on which to operate. * * \return FM_OK on success. * *****************************************************************************/ fm_status fm10000DbgDumpVid(int sw) { int vid; fm_uint64 vidEntryLow; fm_uint32 vidEntryHigh; fm_status status; fm_uint vcnt; fm_bool reflect; fm_int fid1, fid2; fm_bool fid2_ivl; char members[600]; int memberCount; int physPort; int logPort; fm_int cpi; int portMembership; fm_uint32 portTag; char tempBuf[10]; fm_bool trapIGMP; fm_bool trapARP; fm_switch *switchPtr; fm_vlanEntry *vtentry; fm10000_vlanEntry vtentryExt; FM_LOG_ENTRY(FM_LOG_CAT_VLAN, "sw=%d\n", sw); switchPtr = GET_SWITCH_PTR(sw); FM_LOG_PRINT("%4s %19s %7s %6s %6s %8s %6s %6s %6s %s\n", "Vid#", "Entry", "Reflect", "Vcnt", "FID1", "FID2_IVL", "FID2", "IGMP", "ARP", "Membership/Tagging"); for (vid = 0 ; vid < 4096 ; vid++) { vtentry = GET_VLAN_PTR(sw, vid); if (!vtentry->valid) continue; FM_TAKE_L2_LOCK(sw); FM_MEMCPY_S(&vtentryExt, sizeof(vtentryExt), (fm10000_vlanEntry *) GET_VLAN_EXT(sw, vid), sizeof(fm10000_vlanEntry)); FM_DROP_L2_LOCK(sw); vidEntryLow = (((fm_uint64) vtentryExt.member.maskWord[1]) << 32) | vtentryExt.member.maskWord[0]; vidEntryHigh = vtentryExt.member.maskWord[2]; vcnt = vtentryExt.statIndex; status = fmGetVlanAttribute(sw, vid, FM_VLAN_REFLECT, &reflect); /* Successful? */ FM_LOG_EXIT_ON_ERR(FM_LOG_CAT_VLAN, status); status = fmGetVlanAttribute(sw, vid, FM_VLAN_IGMP_TRAPPING, &trapIGMP); /* Successful? */ FM_LOG_EXIT_ON_ERR(FM_LOG_CAT_VLAN, status); #if 0 status = fmGetVlanAttribute(sw, vid, FM_VLAN_ARP_TRAPPING, &trapARP); /* Successful? */ FM_LOG_EXIT_ON_ERR(FM_LOG_CAT_VLAN, status); #else trapARP = FALSE; #endif switch (switchPtr->stpMode) { case FM_SPANNING_TREE_SHARED: fid1 = 0; break; case FM_SPANNING_TREE_MULTIPLE: status = fmFindInstanceForVlan(sw, vid, &fid1); FM_LOG_EXIT_ON_ERR(FM_LOG_CAT_VLAN, status); break; default: fid1 =-1; break; } #if 0 status = fmGetVlanAttribute(sw, vid, FM_VLAN_FID2_IVL, &fid2_ivl); /* Successful? */ if ( status != FM_OK ) { /* no, return the error code*/ return status; } #else fid2_ivl = -1; #endif #if 0 status = fmGetVlanAttribute(sw, vid, FM6000_INGRESS_VID2_FID, &fid2); /* Successful? */ if ( status != FM_OK ) { /* no, return the error code*/ return status; } #else fid2 = -1; #endif members[0] = 0; memberCount = 0; /* Enumerate cardinal ports. */ for (cpi = 0 ; cpi < switchPtr->numCardinalPorts ; cpi++) { /* Get logical and physical port numbers. */ fmMapCardinalPortInternal(switchPtr, cpi, &logPort, &physPort); portMembership = FM_PORTMASK_GET_BIT(&vtentryExt.member, physPort); portTag = FM_PORTMASK_GET_BIT(&vtentryExt.tag, physPort); if (portMembership) { if ((memberCount > 0) && ((memberCount % 13) == 0)) { fmStringAppend(members, "\n " " ", sizeof(members)); } FM_SNPRINTF_S(tempBuf, sizeof(tempBuf), " %2d%c", logPort, (portTag) ? 'T' : ' '); fmStringAppend(members, tempBuf, sizeof(members)); memberCount++; } } FM_LOG_PRINT("%4d %03x%016llx %7d %6d %6d %8d %6d %6s %6s %s\n", vid, vidEntryHigh, vidEntryLow, reflect, vcnt, fid1, fid2_ivl, fid2, trapIGMP ? "trap" : "notrap", trapARP ? "trap" : "notrap", members); } return FM_OK; } /* end fm10000DbgDumpVid */
/** fmDbgCompareChipSnapshots * \ingroup diagReg * * \chips FM2000, FM3000, FM4000, FM6000, FM10000 * * \desc Display a comparison between two or more snapshots of the * switch's configuration (the register file) taken with prior * calls to fmDbgTakeChipSnapshot. * * \param[in] snapshotMask contains the bit mask of snapshots to compare, * where snapshot 0 is the least-significant bit, snapshot 1 * is the next bit, etc. A -1 will cause all snapshots to be * compared, ignoring unused snapshot numbers. * * \return None. * *****************************************************************************/ void fmDbgCompareChipSnapshots(fm_uint snapshotMask) { fmDbgFulcrumSnapshot * pSnaps[FM_DBG_MAX_SNAPSHOTS]; fm_int snapshotNumbers[FM_DBG_MAX_SNAPSHOTS]; fmDbgFulcrumRegisterSnapshot *pReg0 = NULL; fmDbgFulcrumRegisterSnapshot *pRegX; fm_int snap; fm_int index; fm_bool different; fm_int activeCount; fm_bool abort = FALSE; fm_char regName[MAX_REG_NAME_LENGTH]; fm_char curReg1[20]; fm_char curReg2[20]; fm_char tempBuf[40]; fm_char outputBuffer1[1000]; fm_char outputBuffer2[1000]; fm_bool isPort; fm_int index0Ptr; fm_int index1Ptr; fm_int index2Ptr; memset( pSnaps, 0, sizeof(pSnaps) ); /* count the active snapshots */ index = 0; for (snap = 0 ; snap < FM_DBG_MAX_SNAPSHOTS ; snap++) { if ( (fmRootDebug->fmDbgSnapshots[snap] != NULL) && (fmRootDebug->fmDbgSnapshots[snap]->regCount > 0) && ( snapshotMask & (1 << snap) ) ) { pSnaps[index] = fmRootDebug->fmDbgSnapshots[snap]; snapshotNumbers[index] = snap; index++; } } activeCount = index; if (activeCount == 0) { FM_LOG_PRINT("No active snapshots were found using mask %08X\n", snapshotMask); return; } if (activeCount == 1) { FM_LOG_PRINT("Only one active snapshot was found using mask %08X\n", snapshotMask); return; } /* compare snapshot information and registers */ for (index = -4 ; index < pSnaps[0]->regCount ; index++) { if (abort) { break; } different = FALSE; /* compare snapshot 0 against all other snapshots */ for (snap = 1 ; snap < activeCount ; snap++) { if (index < 0) { switch (index) { case - 4: /* snapshot numbers */ different = TRUE; break; case - 3: /* switch number */ if (pSnaps[0]->sw != pSnaps[snap]->sw) { different = TRUE; break; } break; case - 2: /* timestamp */ if ( (pSnaps[0]->timestamp.sec != pSnaps[snap]-> timestamp.sec) || (pSnaps[0]->timestamp.usec != pSnaps[snap]-> timestamp.usec) ) { different = TRUE; break; } break; case - 1: /* register count */ if (pSnaps[0]->regCount != pSnaps[snap]->regCount) { different = TRUE; break; } break; } /* end switch (index) */ } else { pReg0 = &pSnaps[0]->registers[index]; pRegX = &pSnaps[snap]->registers[index]; if (pReg0->regAddress != pRegX->regAddress) { FM_LOG_PRINT("ERROR! Snapshot register tables do not match!\n" " index = %d, address 0 = %08X, " "address %d = %08X\n", index, pReg0->regAddress, snap, pRegX->regAddress); abort = TRUE; break; } if (pReg0->regSize != pRegX->regSize) { FM_LOG_PRINT("ERROR! Snapshot register sizes do not match!\n" " index = %d, address = %08X, size 0 = %d, " "size %d = %d\n", index, pReg0->regAddress, pReg0->regSize, snap, pRegX->regSize); abort = TRUE; break; } if ( (pReg0->regValue1 != pRegX->regValue1) || (pReg0->regValue2 != pRegX->regValue2) ) { different = TRUE; break; } } } if (abort) { break; } if (different) { if (index < 0) { switch (index) { case - 4: /* snapshot numbers */ fmStringCopy(regName, "Snapshot Number", sizeof(regName)); break; case - 3: /* switch number */ fmStringCopy(regName, "Switch Number", sizeof(regName)); break; case - 2: /* timestamp */ fmStringCopy(regName, "Timestamp", sizeof(regName)); break; case - 1: /* register count */ fmStringCopy(regName, "Register Count", sizeof(regName)); break; } /* end switch (index) */ } else { fmDbgGetRegisterName(pSnaps[0]->sw, pReg0->regId, pReg0->regAddress, regName, MAX_REG_NAME_LENGTH, &isPort, &index0Ptr, &index1Ptr, &index2Ptr, TRUE, FALSE); } outputBuffer1[0] = 0; outputBuffer2[0] = 0; for (snap = 0 ; snap < activeCount ; snap++) { curReg1[0] = 0; curReg2[0] = 0; if (index < 0) { switch (index) { case -4: /* Snapshot # */ FM_SNPRINTF_S(curReg1, sizeof(curReg1), "%d", snapshotNumbers[snap]); break; case -3: /* switch number */ FM_SNPRINTF_S(curReg1, sizeof(curReg1), "%d", pSnaps[snap]->sw); break; case -2: /* timestamp */ FM_SNPRINTF_S(curReg1, sizeof(curReg1), "%" FM_FORMAT_64 "u.%06" FM_FORMAT_64 "u", pSnaps[snap]->timestamp.sec, pSnaps[snap]->timestamp.usec); break; case -1: /* register count */ FM_SNPRINTF_S(curReg1, sizeof(curReg1), "%d", pSnaps[snap]->regCount); break; } /* end switch (index) */ } else { pRegX = &pSnaps[snap]->registers[index]; switch (pRegX->regSize) { case 1: FM_SNPRINTF_S(curReg1, sizeof(curReg1), "%08X", (fm_uint32) pRegX->regValue1); break; case 2: if (pRegX->isStatReg) { FM_SNPRINTF_S(curReg1, sizeof(curReg1), "%" FM_FORMAT_64 "u", pRegX->regValue1); } else { FM_SNPRINTF_S(curReg1, sizeof(curReg1), "%016" FM_FORMAT_64 "X", pRegX->regValue1); } break; case 3: FM_SNPRINTF_S(curReg1, sizeof(curReg1), "%016" FM_FORMAT_64 "X", pRegX->regValue1); FM_SNPRINTF_S(curReg2, sizeof(curReg2), "%08X", (fm_uint32) pRegX->regValue2); break; case 4: FM_SNPRINTF_S(curReg1, sizeof(curReg1), "%016" FM_FORMAT_64 "X", pRegX->regValue1); FM_SNPRINTF_S(curReg2, sizeof(curReg2), "%016" FM_FORMAT_64 "X", pRegX->regValue2); break; } /* end switch (pRegX->regSize) */ } FM_SNPRINTF_S(tempBuf, sizeof(tempBuf), "%20s", curReg1); fmStringAppend(outputBuffer1, tempBuf, sizeof(outputBuffer1)); if (curReg2[0] != 0) { FM_SNPRINTF_S(tempBuf, sizeof(tempBuf), "%20s", curReg2); fmStringAppend(outputBuffer2, tempBuf, sizeof(outputBuffer2)); } } FM_LOG_PRINT("%-40s %s\n", regName, outputBuffer1); if (outputBuffer2[0] != 0) { FM_LOG_PRINT("%40s %s\n", " ", outputBuffer2); } } } } /* end fmDbgCompareChipSnapshots */
/** fmLoadPortRemapTable * \ingroup intSwitch * * \desc Load a new port mapping table from a given file. * * \param[in] filename is the file name. * * \param[in] portTable is ptr to table where to store port read from file * * \param[in] origTable is ptr to the original port mapping table * * \param[in] maxport is number of entries in portTable * * \return FM_OK or FM_FAIL if unable to read table from file * *****************************************************************************/ fm_status fmLoadPortRemapTable(fm_char *filename, fm_int *portTable, fm_int *origTable, fm_int maxport) { FILE *fp; fm_char *pch; fm_char line[200]; fm_int i; fm_int j; fm_int portNum; fm_char * context; fm_uint s1max; fm_uint lineLeft; if ((fp = fopen(filename,"r")) == NULL) { FM_LOG_PRINT("cannot open file %s \n", filename); return(FM_FAIL); } /* Display the original port mapping table. */ FM_CLEAR(line); lineLeft = sizeof(line); FM_SPRINTF_S(line, lineLeft, "\noriginalTable[%d,", origTable[0]); i = strlen(line); lineLeft -= i; pch = &line[i]; for (i = 1 ; i < maxport ; i++) { FM_SPRINTF_S(pch, lineLeft, "%d,",origTable[i]); j = strlen(pch); lineLeft -= j; pch += j; } /* Reposition back to the trailing comma, then overwrite it */ --pch; *pch = ']'; FM_LOG_PRINT("%s\n", line); while ( fgets(line,200,fp) != NULL ) { if (strstr(line,"mappingTable") != NULL) { FM_LOG_PRINT("%s\n", line); if ((pch = strchr(line,'[')) != NULL) { i = 0; context = NULL; s1max = RSIZE_MAX - 1; pch = FM_STRTOK_S(++pch, &s1max, " ,", &context); while (pch != NULL && i < maxport) { portNum = atoi(pch); if (portNum >= 0 && portNum < maxport) { portTable[i++] = portNum; pch = FM_STRTOK_S(NULL, &s1max, " ,]", &context); } else { FM_LOG_PRINT("*** Invalid port number %d ***\n",portNum); fclose(fp); return(FM_FAIL); } } } } } fclose(fp); return FM_OK; } /* end fmLoadPortRemapTable */
/** PerformPurge * \ingroup intMacMaint * * \desc Initiates an MA table purge operation. * * \param[in] sw is the switch on which to operate. * * \return FM_OK if successful. * *****************************************************************************/ static fm_status PerformPurge(fm_int sw) { fm_switch * switchPtr; fm_bool l2Locked; fm_int numSkipped; fm_event * eventPtr; fm_uint32 numUpdates; fm_int entryIndex; fm_status err; fm_internalMacAddrEntry * cachePtr; fm_internalMacAddrEntry oldEntry; FM_LOG_ENTRY(FM_LOG_CAT_EVENT_MAC_MAINT, "sw=%d\n", sw); switchPtr = GET_SWITCH_PTR(sw); l2Locked = FALSE; numSkipped = 0; eventPtr = NULL; numUpdates = 0; /*************************************************** * Preallocate an event buffer. **************************************************/ /* NOTE: This call will block if the number of free event * buffers drops below the acceptable threshold. */ eventPtr = fmAllocateEvent(sw, FM_EVID_HIGH_TABLE_UPDATE, FM_EVENT_TABLE_UPDATE, FM_EVENT_PRIORITY_LOW); if (eventPtr == NULL) { fmDbgDiagCountIncr(sw, FM_CTR_MAC_EVENT_ALLOC_ERR, 1); FM_LOG_ERROR(FM_LOG_CAT_EVENT_MAC_MAINT, "out of event buffers\n"); } /*************************************************** * Iterate over MAC table cache. **************************************************/ for ( entryIndex = 0 ; entryIndex < switchPtr->macTableSize ; ++entryIndex ) { if (!l2Locked) { FM_TAKE_L2_LOCK(sw); l2Locked = TRUE; numSkipped = 0; } cachePtr = &switchPtr->maTable[entryIndex]; /*************************************************** * Determine whether to purge this entry. **************************************************/ if (!MeetsPurgeCriteria(sw, cachePtr)) { ++numSkipped; if (numSkipped >= SKIP_THRESHOLD) { FM_DROP_L2_LOCK(sw); l2Locked = FALSE; } continue; } if (FM_IS_TEST_TRACE_ADDRESS(cachePtr->macAddress)) { FM_LOG_PRINT("fm10000HandlePurgeRequest(%d): " "purging mac address " FM_FORMAT_ADDR "/%u\n", sw, cachePtr->macAddress, cachePtr->vlanID); } /*************************************************** * Remove entry from MAC table. **************************************************/ /* Make a copy of the cache entry before we invalidate it. * We'll need it to generate the AGED event. */ oldEntry = *cachePtr; /* Invalidate cache and hardware entry. */ err = fm10000InvalidateEntryAtIndex(sw, entryIndex); if (err != FM_OK) { FM_LOG_ERROR(FM_LOG_CAT_EVENT_MAC_MAINT, "Error purging MA table entry: sw=%d index=%d\n", sw, entryIndex); } /*************************************************** * Generate an AGED event. **************************************************/ /* Relinquish lock before generating event. */ FM_DROP_L2_LOCK(sw); l2Locked = FALSE; fmGenerateUpdateForEvent(sw, &fmRootApi->eventThread, FM_EVENT_ENTRY_AGED, FM_MAC_REASON_PURGE_AGED, entryIndex, &oldEntry, &numUpdates, &eventPtr); fmDbgDiagCountIncr(sw, FM_CTR_MAC_PURGE_AGED, 1); } /* end for ( entryIndex = 0 ; ... ) */ if (l2Locked) { FM_DROP_L2_LOCK(sw); } if (numUpdates != 0) { fmSendMacUpdateEvent(sw, &fmRootApi->eventThread, &numUpdates, &eventPtr, FALSE); } if (eventPtr != NULL) { fmReleaseEvent(eventPtr); } err = FinishPurge(sw); FM_LOG_EXIT(FM_LOG_CAT_EVENT_MAC_MAINT, err); } /* end PerformPurge */
/** fmDbgPrintPortList * \ingroup intSflow * * \desc Prints a port set as a list of comma-separated ranges. * * \param[in] sw is the switch on which to operate. * * \param[in] numPorts is the number of ports in the array. * * \param[in] portList is the array which contains the list of ports. * * \return FM_OK if successful. * \return FM_OK if successful. * *****************************************************************************/ static fm_status fmDbgPrintPortList(fm_int sw, fm_int numPorts, fm_int *portList) { fm_switch * switchPtr; fm_int cpi; fm_int port; fm_int lastPort; fm_bool inSet; fm_int i; enum { EMPTY, FIRST, RANGE, GAP } state; switchPtr = GET_SWITCH_PTR(sw); lastPort = -1; state = EMPTY; for (cpi = 0 ; cpi < switchPtr->numCardinalPorts ; ++cpi) { port = GET_LOGICAL_PORT(sw, cpi); inSet = FALSE; for (i = 0; i < numPorts; i++) { if (portList[i] == port) { inSet = TRUE; } } switch (state) { case EMPTY: /* The output set is empty. */ if (inSet) { FM_LOG_PRINT("%d", port); state = FIRST; } break; case FIRST: /* We've processed the first port in a sequence. */ if (inSet) { lastPort = port; state = RANGE; } else { state = GAP; } break; case RANGE: /* We're processing a range in the port list. */ if (inSet) { lastPort = port; } else { FM_LOG_PRINT("..%d", lastPort); state = GAP; } break; case GAP: /* We're processing a gap in the port list. */ if (inSet) { FM_LOG_PRINT(",%d", port); state = FIRST; } break; } /* end switch (state) */ } /* end for (cpi = 0 ; cpi < switchPtr->numCardinalPorts ; ++cpi) */ if (state == RANGE) { FM_LOG_PRINT("..%d", lastPort); } return FM_OK; } /* end fmDbgPrintPortList */