/*----------------------------------------------------------------------------*/ int main(void) { struct DeviceDriver device; struct Interface * const i2c = init(I2c, &i2cConfig); assert(i2c); deviceInit(&device, i2c, LED_PIN, DEVICE_ADDRESS); struct Timer * const timer = init(GpTimer, &timerConfig); assert(timer); timerSetOverflow(timer, 1000); bool event = false; timerSetCallback(timer, onTimerOverflow, &event); timerEnable(timer); while (1) { while (!event) barrier(); event = false; deviceWrite(&device); while (!event) barrier(); event = false; deviceRead(&device); } return 0; }
void Settings::_init() { errlHndl_t l_errl = NULL; size_t size = sizeof(iv_regValue); // Read / cache security switch setting from processor. l_errl = deviceRead(TARGETING::MASTER_PROCESSOR_CHIP_TARGET_SENTINEL, &iv_regValue, size, DEVICE_SCOM_ADDRESS(SECURITY_SWITCH_REGISTER)); // If this errors, we're in bad shape and shouldn't trust anything. assert(NULL == l_errl); }
/// @brief Platform-level implementation called by getRing() ReturnCode platGetRing(const Target<TARGET_TYPE_ALL>& i_target, const scanRingId_t i_address, variable_buffer& o_data, const RingMode i_ringMode) { FAPI_DBG(ENTER_MRK "platGetRing"); // Note: Trace is placed here in plat code because PPE doesn't support // trace in common fapi2_hw_access.H bool l_traceit = platIsScanTraceEnabled(); ReturnCode l_rc; errlHndl_t l_err = NULL; // Extract the component pointer TARGETING::Target* l_target = reinterpret_cast<TARGETING::Target*>(i_target.get()); // Grab the name of the target TARGETING::ATTR_FAPI_NAME_type l_targName = {0}; fapi2::toString(i_target, l_targName, sizeof(l_targName)); // Output buffer must be set to ring's len by user uint64_t l_ringLen = o_data.getBitLength(); uint64_t l_flag = platGetDDScanMode(i_ringMode); size_t l_size = o_data.getLength<uint8_t>(); l_err = deviceRead(l_target, o_data.pointer(), l_size, DEVICE_SCAN_ADDRESS(i_address, l_ringLen, l_flag)); if (l_err) { FAPI_ERR("platGetRing: deviceRead returns error!"); FAPI_ERR("fapiGetRing failed - Target %s, Addr %.16llX", l_targName, i_address); l_rc.setPlatDataPtr(reinterpret_cast<void *> (l_err)); } if (l_traceit) { uint64_t l_data = o_data.get<uint64_t>(); FAPI_SCAN("TRACE : GETRING : %s : %.16llX %.16llX", l_targName, i_address, l_data); } FAPI_DBG(EXIT_MRK "platGetRing"); return l_rc; }
//****************************************************************************** //todGetScom() //****************************************************************************** errlHndl_t todGetScom(const TARGETING::Target * i_target, const uint64_t i_address, fapi2::variable_buffer & o_data) { errlHndl_t l_err = NULL; // Perform SCOM read uint64_t l_data = 0; size_t l_size = sizeof(uint64_t); l_err = deviceRead((TARGETING::Target *)i_target, &l_data, l_size, DEVICE_SCOM_ADDRESS(i_address)); return l_err; }
uint64_t Daemon::readScratchReg() { size_t l_size = sizeof(uint64_t); uint64_t value = 0; errlHndl_t l_errl = deviceRead(TARGETING::MASTER_PROCESSOR_CHIP_TARGET_SENTINEL, &value, l_size, DEVICE_SCOM_ADDRESS(MB_SCRATCH_REGISTER_1)); if (l_errl) { errlCommit(l_errl, TRACE_COMP_ID); } return value; }
/** * @brief Performs a presence detect operation on a Processor Chip. * * This function does FSI presence detect and compares it to the Module * VPD that is present, following the pre-defined prototype for a * device-driver framework function. * * @param[in] i_opType Operation type, see DeviceFW::OperationType * in driverif.H * @param[in] i_target Presence detect target * @param[in/out] io_buffer Read: Pointer to output data storage * Write: Pointer to input data storage * @param[in/out] io_buflen Input: size of io_buffer (in bytes, always 1) * Output: Success = 1, Failure = 0 * @param[in] i_accessType DeviceFW::AccessType enum (userif.H) * @param[in] i_args This is an argument list for DD framework. * In this function, there are no arguments. * @return errlHndl_t */ errlHndl_t procPresenceDetect(DeviceFW::OperationType i_opType, TARGETING::Target* i_target, void* io_buffer, size_t& io_buflen, int64_t i_accessType, va_list i_args) { errlHndl_t l_errl = NULL; uint32_t l_saved_plid = 0; if (unlikely(io_buflen < sizeof(bool))) { TRACFCOMP(g_trac_fsi, ERR_MRK "FSI::procPresenceDetect> Invalid data length: %d", io_buflen); /*@ * @errortype * @moduleid FSI::MOD_FSIPRES_PROCPRESENCEDETECT * @reasoncode FSI::RC_INVALID_LENGTH * @userdata1 Data Length * @devdesc presenceDetect> Invalid data length (!= 1 bytes) */ l_errl = new ERRORLOG::ErrlEntry(ERRORLOG::ERRL_SEV_UNRECOVERABLE, FSI::MOD_FSIPRES_PROCPRESENCEDETECT, FSI::RC_INVALID_LENGTH, TO_UINT64(io_buflen), true /*SW error*/); io_buflen = 0; return l_errl; } // First look for FSI presence bits bool fsi_present = false; TARGETING::Target* l_masterChip = NULL; TARGETING::targetService().masterProcChipTargetHandle(l_masterChip); if ((i_target == TARGETING::MASTER_PROCESSOR_CHIP_TARGET_SENTINEL) || (i_target == l_masterChip)) { fsi_present = true; } else { fsi_present = isSlavePresent(i_target); } // Next look for valid Module VPD bool check_for_mvpd = true; #ifdef CONFIG_MVPD_READ_FROM_HW check_for_mvpd = fsi_present; #endif // CONFIG_MVPD_READ_FROM_HW bool mvpd_present = false; size_t theSize = 0; if ( check_for_mvpd ) { l_errl = deviceRead( i_target, NULL, theSize, DEVICE_MVPD_ADDRESS( MVPD::CP00, MVPD::VD ) ); if( l_errl ) { if( fsi_present ) { // Save this plid to use later l_saved_plid = l_errl->plid(); // commit this log because we expected to have VPD errlCommit( l_errl, FSI_COMP_ID ); } else { // just delete this delete l_errl; } } if( theSize > 0 ) { uint8_t theData[theSize]; l_errl = deviceRead( i_target, theData, theSize, DEVICE_MVPD_ADDRESS( MVPD::CP00, MVPD::VD ) ); if( l_errl ) { if( fsi_present ) { // Save this plid to use later l_saved_plid = l_errl->plid(); // commit this log because we expected to have VPD errlCommit( l_errl, FSI_COMP_ID ); } else { // just delete this delete l_errl; } } else { mvpd_present = true; } } } // Finally compare the 2 methods if( fsi_present != mvpd_present ) { TRACFCOMP(g_trac_fsi, ERR_MRK "FSI::procPresenceDetect> FSI (=%d) and MVPD (=%d) do not agree for %.8X", fsi_present, mvpd_present, TARGETING::get_huid(i_target)); /*@ * @errortype * @moduleid FSI::MOD_FSIPRES_PROCPRESENCEDETECT * @reasoncode FSI::RC_FSI_MVPD_MISMATCH * @userdata1 HUID of processor * @userdata2[0:31] FSI Presence * @userdata2[32:63] MVPD Presence * @devdesc presenceDetect> FSI and MVPD do not agree */ l_errl = new ERRORLOG::ErrlEntry(ERRORLOG::ERRL_SEV_UNRECOVERABLE, FSI::MOD_FSIPRES_PROCPRESENCEDETECT, FSI::RC_FSI_MVPD_MISMATCH, TARGETING::get_huid(i_target), TWO_UINT32_TO_UINT64( fsi_present, mvpd_present)); // Callout the processor l_errl->addHwCallout( i_target, HWAS::SRCI_PRIORITY_LOW, HWAS::NO_DECONFIG, HWAS::GARD_NULL ); // if there is a saved PLID, apply it to this error log if (l_saved_plid) { l_errl->plid(l_saved_plid); } // Add FFDC for the target to an error log getFsiFFDC( FFDC_PRESENCE_FAIL, l_errl, i_target); // Add FSI and VPD trace l_errl->collectTrace("FSI"); l_errl->collectTrace("VPD"); // commit this log and move on errlCommit( l_errl, FSI_COMP_ID ); } bool present = fsi_present && mvpd_present; memcpy(io_buffer, &present, sizeof(present)); io_buflen = sizeof(present); return NULL; }
/// @brief Platform-level implementation called by modifyRing() ReturnCode platModifyRing(const Target<TARGET_TYPE_ALL>& i_target, const scanRingId_t i_address, const variable_buffer& i_data, const ChipOpModifyMode i_modifyMode, const RingMode i_ringMode) { FAPI_DBG(ENTER_MRK "platModifyRing"); // TODO RTC:152489 - story to finish this modifyRing FAPI_ERR("platModifyRing: not supported yet"); assert(0,"platModifyRing not supported yet."); ReturnCode l_rc; errlHndl_t l_err = NULL; variable_buffer l_current_data(i_data); // Note: Trace is placed here in plat code because PPE doesn't support // trace in common fapi2_hw_access.H bool l_traceit = platIsScanTraceEnabled(); // Grab the name of the target TARGETING::ATTR_FAPI_NAME_type l_targName = {0}; fapi2::toString(i_target, l_targName, sizeof(l_targName)); do { // Extract the component pointer TARGETING::Target* l_target = reinterpret_cast<TARGETING::Target*>(i_target.get()); // -------------------- // Read current value // -------------------- uint64_t l_ringLen = l_current_data.getBitLength(); uint64_t l_flag = platGetDDScanMode(i_ringMode); size_t l_size = l_current_data.getLength<uint8_t>(); l_err = deviceRead(l_target, l_current_data.pointer(), l_size, DEVICE_SCAN_ADDRESS(i_address, l_ringLen, l_flag)); if (l_err) { FAPI_ERR("platModifyRing: deviceRead returns error!"); FAPI_ERR("platModifyRing failed - Target %s, Addr %.16llX", l_targName, i_address); // Add the error log pointer as data to the ReturnCode l_rc.setPlatDataPtr(reinterpret_cast<void *> (l_err)); // break out if read fails break; } // ---------------------- // Applying modification // ---------------------- /* TODO-RTC:151261 - re-enable when variable_buffer operations supported if (fapi2::CHIP_OP_MODIFY_MODE_OR == i_modifyMode) { l_current_data |= i_data; } else if (fapi2::CHIP_OP_MODIFY_MODE_AND == i_modifyMode) { l_current_data &= i_data; } else { l_current_data ^= i_data; } */ // ------------------------- // Write back updated data // ------------------------- l_err = deviceWrite(l_target, l_current_data.pointer(), l_size, DEVICE_SCAN_ADDRESS(i_address, l_ringLen, l_flag)); if (l_err) { FAPI_ERR("platModifyRing: deviceWrite returns error!"); FAPI_ERR("platModifyRing failed - Target %s, Addr %.16llX", l_targName, i_address); // Add the error log pointer as data to the ReturnCode l_rc.setPlatDataPtr(reinterpret_cast<void *> (l_err)); break; } } while (0); if (l_traceit) { uint64_t l_data = l_current_data.get<uint64_t>(); FAPI_SCAN("TRACE : MODIFYRING : %s : %.16llX %.16llX", l_targName, i_address, l_data); } FAPI_DBG(EXIT_MRK "platModifyRing"); return l_rc; }
/// @brief Platform-level implementation called by getScom() ReturnCode platGetScom(const Target<TARGET_TYPE_ALL>& i_target, const uint64_t i_address, buffer<uint64_t>& o_data) { ReturnCode l_rc; errlHndl_t l_err = NULL; FAPI_DBG(ENTER_MRK "platGetScom"); // Note: Trace is placed here in plat code because PPE doesn't support // trace in common fapi2_hw_access.H bool l_traceit = platIsScanTraceEnabled(); // Extract the component pointer TARGETING::Target* l_target = reinterpret_cast<TARGETING::Target*>(i_target.get()); // Grab the name of the target TARGETING::ATTR_FAPI_NAME_type l_targName = {0}; fapi2::toString(i_target, l_targName, sizeof(l_targName)); // Perform SCOM read size_t l_size = sizeof(uint64_t); l_err = deviceRead(l_target, &o_data(), l_size, DEVICE_SCOM_ADDRESS(i_address, opMode)); //If an error occured durring the device read and a pib_err_mask is set, // then we will check if the err matches the mask, if it does we // ignore the error if(l_err && (pib_err_mask != 0x00)) { checkPibMask(l_err); } if (l_err) { if(opMode & fapi2::IGNORE_HW_ERROR) { delete l_err; l_err = nullptr; } else { FAPI_ERR("platGetScom: deviceRead returns error!"); FAPI_ERR("fapiGetScom failed - Target %s, Addr %.16llX", l_targName, i_address); l_rc.setPlatDataPtr(reinterpret_cast<void *> (l_err)); } } if (l_traceit) { uint64_t l_data = (uint64_t)o_data; FAPI_SCAN("TRACE : GETSCOM : %s : %.16llX %.16llX", l_targName, i_address, l_data); } FAPI_DBG(EXIT_MRK "platGetScom"); return l_rc; }
/// @brief Platform-level implementation of modifyCfamRegister() ReturnCode platModifyCfamRegister(const Target<TARGET_TYPE_ALL>& i_target, const uint32_t i_address, const buffer<uint32_t> i_data, const ChipOpModifyMode i_modifyMode) { FAPI_DBG(ENTER_MRK "platModifyCfamRegister"); ReturnCode l_rc; errlHndl_t l_err = NULL; bool l_traceit = platIsScanTraceEnabled(); const char* l_modeString = platModeString(i_modifyMode); // Grab the name of the target TARGETING::ATTR_FAPI_NAME_type l_targName = {0}; fapi2::toString(i_target, l_targName, sizeof(l_targName)); do { // Can't access cfam engine on master processor l_err = verifyCfamAccessTarget(i_target,i_address); if (l_err) { FAPI_ERR("platModifyCfamRegister: verifyCfamAccessTarget returns error!"); l_rc.setPlatDataPtr(reinterpret_cast<void *> (l_err)); break; } // Extract the component pointer TARGETING::Target* l_target = reinterpret_cast<TARGETING::Target*>(i_target.get()); // Get the chip target if l_target is not a chip TARGETING::Target* l_myChipTarget = NULL; l_err = getCfamChipTarget(l_target, l_myChipTarget); if (l_err) { FAPI_ERR("platModifyCfamRegister: getCfamChipTarget returns error!"); l_rc.setPlatDataPtr(reinterpret_cast<void *> (l_err)); break; } // Read current value // Address needs to be multiply by 4 because register addresses are word // offsets but the FSI addresses are byte offsets. // However, we need to preserve the engine's offset of 0x0C00 and 0x1000 uint64_t l_addr = ((i_address & CFAM_ADDRESS_MASK) << 2) | (i_address & CFAM_ENGINE_OFFSET); buffer<uint32_t> l_data = 0; size_t l_size = sizeof(uint32_t); l_err = deviceRead(l_myChipTarget, &l_data(), l_size, DEVICE_FSI_ADDRESS(l_addr)); if (l_err) { FAPI_ERR("platModifyCfamRegister: deviceRead returns error!"); l_rc.setPlatDataPtr(reinterpret_cast<void *> (l_err)); break; } // Applying modification platProcess32BitModifyMode(i_modifyMode, i_data, l_data); // Write back l_err = deviceWrite(l_target, &l_data(), l_size, DEVICE_FSI_ADDRESS(l_addr)); if (l_err) { FAPI_ERR("platModifyCfamRegister: deviceWrite returns error!"); l_rc.setPlatDataPtr(reinterpret_cast<void *> (l_err)); break; } } while (0); if (l_rc != fapi2::FAPI2_RC_SUCCESS) { FAPI_ERR("platModifyCfamRegister failed - Target %s, Addr %.8X", l_targName, i_address); } if( l_traceit ) { uint32_t l_data = (uint32_t)i_data; FAPI_SCAN( "TRACE : MODCFAMREG : %s : %.8X %.8X %s", l_targName, i_address, l_data, l_modeString ); } FAPI_DBG(EXIT_MRK "platModifyCfamRegister"); return l_rc; }
/// @brief Platform-level implementation called by getCfamRegister() ReturnCode platGetCfamRegister(const Target<TARGET_TYPE_ALL>& i_target, const uint32_t i_address, buffer<uint32_t>& o_data) { FAPI_DBG(ENTER_MRK "platGetCfamRegister"); ReturnCode l_rc; errlHndl_t l_err = NULL; bool l_traceit = platIsScanTraceEnabled(); // Grab the name of the target TARGETING::ATTR_FAPI_NAME_type l_targName = {0}; fapi2::toString(i_target, l_targName, sizeof(l_targName)); do { // Extract the target pointer TARGETING::Target* l_target = reinterpret_cast<TARGETING::Target*>(i_target.get()); // Get the chip target if l_target is not a chip TARGETING::Target* l_myChipTarget = NULL; l_err = getCfamChipTarget(l_target, l_myChipTarget); if (l_err) { FAPI_ERR("platGetCfamRegister: getCfamChipTarget returns error!"); FAPI_ERR("fapiGetCfamRegister failed - Target %s, Addr %.8X", l_targName, i_address); l_rc.setPlatDataPtr(reinterpret_cast<void *> (l_err)); break; } // Can't access cfam engine on master processor l_err = verifyCfamAccessTarget(i_target,i_address); if (l_err) { FAPI_ERR("platGetCfamRegister: verifyCfamAccessTarget returns error!"); l_rc.setPlatDataPtr(reinterpret_cast<void *> (l_err)); break; } // Perform CFAM read via FSI // Address needs to be multiply by 4 because register addresses are // word offsets but the FSI addresses are byte offsets. // However, we need to preserve the engine's offset in the top byte uint64_t l_addr = ((i_address & CFAM_ADDRESS_MASK) << 2) | (i_address & CFAM_ENGINE_OFFSET); size_t l_size = sizeof(uint32_t); l_err = deviceRead(l_myChipTarget, &o_data(), l_size, DEVICE_FSI_ADDRESS(l_addr)); if (l_err) { FAPI_ERR("platGetCfamRegister: deviceRead returns error!"); l_rc.setPlatDataPtr(reinterpret_cast<void *> (l_err)); break; } } while(0); if (l_rc != fapi2::FAPI2_RC_SUCCESS) { FAPI_ERR("fapiGetCfamRegister failed - Target %s, Addr %.8X", l_targName, i_address); } if( l_traceit ) { uint32_t l_data = (uint32_t)o_data; FAPI_SCAN( "TRACE : GETCFAMREG : %s : %.8X %.8X", l_targName, i_address, l_data); } FAPI_DBG(EXIT_MRK "platGetCfamRegister"); return l_rc; }
/// @brief Platform-level implementation called by putScomUnderMask() ReturnCode platPutScomUnderMask(const Target<TARGET_TYPE_ALL>& i_target, const uint64_t i_address, const buffer<uint64_t> i_data, const buffer<uint64_t> i_mask) { ReturnCode l_rc; errlHndl_t l_err = NULL; FAPI_DBG(ENTER_MRK "platPutScomUnderMask"); // Note: Trace is placed here in plat code because PPE doesn't support // trace in common fapi2_hw_access.H bool l_traceit = platIsScanTraceEnabled(); // Grab the name of the target TARGETING::ATTR_FAPI_NAME_type l_targName = {0}; fapi2::toString(i_target, l_targName, sizeof(l_targName)); do { // Extract the component pointer TARGETING::Target* l_target = reinterpret_cast<TARGETING::Target*>(i_target.get()); // Get current value from HW uint64_t l_data = 0; size_t l_size = sizeof(uint64_t); l_err = deviceRead(l_target, &l_data, l_size, DEVICE_SCOM_ADDRESS(i_address,opMode)); if (l_err && !(opMode & fapi2::IGNORE_HW_ERROR)) { FAPI_ERR("platPutScomUnderMask: deviceRead returns error!"); l_rc.setPlatDataPtr(reinterpret_cast<void *> (l_err)); break; } else if(l_err) { delete l_err; l_err = nullptr; break; } // Calculate new value to write to reg uint64_t l_inMaskInverted = ~i_mask; // Write mask inverted uint64_t l_newMask = (i_data & i_mask); // Retain set data bits // l_data = current data set bits l_data &= l_inMaskInverted; // l_data = current data set bit + set mask bits l_data |= l_newMask; // Write new value l_err = deviceWrite(l_target, &l_data, l_size, DEVICE_SCOM_ADDRESS(i_address,opMode)); if (l_err && !(opMode & fapi2::IGNORE_HW_ERROR)) { FAPI_ERR("platPutScomUnderMask: deviceWrite returns error!"); l_rc.setPlatDataPtr(reinterpret_cast<void *> (l_err)); break; } else if (l_err) { delete l_err; l_err = nullptr; break; } } while (0); if(l_err && (pib_err_mask != 0x00)) { checkPibMask(l_err); } if (l_rc != fapi2::FAPI2_RC_SUCCESS) { FAPI_ERR("platPutScomUnderMask failed - Target %s, Addr %.16llX", l_targName, i_address); } if( l_traceit ) { uint64_t l_data = i_data; uint64_t l_mask = i_mask; FAPI_SCAN( "TRACE : PUTSCOMMASK : %s : %.16llX %.16llX %.16llX", l_targName, i_address, l_data, l_mask); } FAPI_DBG(EXIT_MRK "platPutScomUnderMask"); return l_rc; }
// ------------------------------------------------------------------ // dimmPresenceDetect // ------------------------------------------------------------------ errlHndl_t dimmPresenceDetect( DeviceFW::OperationType i_opType, TARGETING::Target * i_target, void * io_buffer, size_t & io_buflen, int64_t i_accessType, va_list i_args ) { errlHndl_t err = NULL; bool present = false; size_t presentSz = sizeof(present); TRACSSCOMP( g_trac_spd, ENTER_MRK"dimmPresenceDetect()" ); do { // Check to be sure that the buffer is big enough. if( !(io_buflen >= sizeof(bool)) ) { TRACFCOMP( g_trac_spd, ERR_MRK"dimmPresenceDetect() - Invalid Data Length: %d", io_buflen ); /*@ * @errortype * @reasoncode VPD::VPD_INSUFFICIENT_BUFFER_SIZE * @severity ERRORLOG::ERRL_SEV_UNRECOVERABLE * @moduleid VPD::VPD_SPD_PRESENCE_DETECT * @userdata1 Buffer Length * @userdata2 <UNUSED> * @devdesc Buffer for checking Presence Detect * was not the correct size. */ err = new ERRORLOG::ErrlEntry( ERRORLOG::ERRL_SEV_UNRECOVERABLE, VPD::VPD_SPD_PRESENCE_DETECT, VPD::VPD_INSUFFICIENT_BUFFER_SIZE, TO_UINT64(io_buflen), 0x0, true /*Add HB Software Callout*/); err->collectTrace( "SPD", 256); break; } // Is the target present #ifdef CONFIG_DJVPD_READ_FROM_HW // Check if the parent MBA/MEMBUF is present. If it is not then // no reason to check the DIMM which would otherwise generate // tons of FSI errors. We can't just check if parent MBA // is functional because DIMM presence detect is called before // the parent MBA/MEMBUF is set as present/functional. TARGETING::TargetHandleList membufList; TARGETING::PredicateCTM membufPred( TARGETING::CLASS_CHIP, TARGETING::TYPE_MEMBUF ); TARGETING::targetService().getAssociated( membufList, i_target, TARGETING::TargetService::PARENT_BY_AFFINITY, TARGETING::TargetService::ALL, &membufPred); bool parentPresent = false; const TARGETING::TargetHandle_t membufTarget = *(membufList.begin()); err = deviceRead(membufTarget, &parentPresent, presentSz, DEVICE_PRESENT_ADDRESS()); if (err) { TRACFCOMP( g_trac_spd, "Error reading parent MEMBUF present: huid 0x%X DIMM huid 0x%X", TARGETING::get_huid(membufTarget), TARGETING::get_huid(i_target) ); break; } if (!parentPresent) { present = false; // Invalidate the SPD in PNOR err = VPD::invalidatePnorCache(i_target); if (err) { TRACFCOMP( g_trac_spd, "Error invalidating SPD in PNOR" ); } break; } #endif present = spdPresent( i_target ); if( present == false ) { TRACUCOMP( g_trac_spd, INFO_MRK"Dimm was found to be NOT present." ); } else { TRACUCOMP( g_trac_spd, INFO_MRK"Dimm was found to be present." ); } #if defined(CONFIG_DJVPD_READ_FROM_HW) && defined(CONFIG_DJVPD_READ_FROM_PNOR) if( present ) { // Check if the VPD data in the PNOR matches the SEEPROM err = VPD::ensureCacheIsInSync( i_target ); if( err ) { present = false; TRACFCOMP(g_trac_spd,ERR_MRK "dimmPresenceDetectt> Error during ensureCacheIsInSync (SPD)" ); break; } } else { // SPD is not present, invalidate the SPD in PNOR err = VPD::invalidatePnorCache(i_target); if (err) { TRACFCOMP( g_trac_spd, "Error invalidating SPD in PNOR" ); } } #endif if( present && !err ) { //Fsp sets PN/SN so if there is none, do it here if(!INITSERVICE::spBaseServicesEnabled()) { //populate serial and part number attributes SPD::setPartAndSerialNumberAttributes( i_target ); } // Read ATTR_CLEAR_DIMM_SPD_ENABLE attribute TARGETING::Target* l_sys = NULL; TARGETING::targetService().getTopLevelTarget(l_sys); TARGETING::ATTR_CLEAR_DIMM_SPD_ENABLE_type l_clearSPD = l_sys->getAttr<TARGETING::ATTR_CLEAR_DIMM_SPD_ENABLE>(); // If SPD clear is enabled then write 0's into magic word for // DIMM_BAD_DQ_DATA keyword // Note: If there's an error from performing the clearing, // just log the error and continue. if (l_clearSPD) { size_t l_size = 0; // Do a read to get the DIMM_BAD_DQ_DATA keyword size err = deviceRead(i_target, NULL, l_size, DEVICE_SPD_ADDRESS( DIMM_BAD_DQ_DATA )); if (err) { TRACFCOMP(g_trac_spd, "dimmPresenceDetect - " "Error reading DIMM_BAD_DQ_DATA keyword size"); errlCommit( err, VPD_COMP_ID ); } else { // Clear the data TRACFCOMP( g_trac_spd, "Clearing out BAD_DQ_DATA SPD on " "DIMM HUID 0x%X", TARGETING::get_huid(i_target)); uint8_t * l_data = static_cast<uint8_t*>(malloc( l_size )); memset(l_data, 0, l_size); err = deviceWrite(i_target, l_data, l_size, DEVICE_SPD_ADDRESS( DIMM_BAD_DQ_DATA )); if (err) { TRACFCOMP( g_trac_spd, "Error trying to clear SPD on " "DIMM HUID 0x%X", TARGETING::get_huid(i_target)); errlCommit( err, VPD_COMP_ID ); } // Free the memory if (NULL != l_data) { free(l_data); } } } } // copy present value into output buffer so caller can read it memcpy( io_buffer, &present, presentSz ); io_buflen = presentSz; } while( 0 ); TRACSSCOMP( g_trac_spd, EXIT_MRK"dimmPresenceDetect()" ); return err; } // end dimmPresenceDetect
// ------------------------------------------------------------------ // dimmPresenceDetect // ------------------------------------------------------------------ errlHndl_t dimmPresenceDetect( DeviceFW::OperationType i_opType, TARGETING::Target * i_target, void * io_buffer, size_t & io_buflen, int64_t i_accessType, va_list i_args ) { errlHndl_t err = NULL; bool present = false; size_t presentSz = sizeof(present); TRACSSCOMP( g_trac_spd, ENTER_MRK"dimmPresenceDetect() " "DIMM HUID 0x%X", TARGETING::get_huid(i_target)); do { // Check to be sure that the buffer is big enough. if( !(io_buflen >= sizeof(bool)) ) { TRACFCOMP( g_trac_spd, ERR_MRK"dimmPresenceDetect() " "Invalid Data Length: %d", io_buflen ); /*@ * @errortype * @reasoncode VPD::VPD_INSUFFICIENT_BUFFER_SIZE * @severity ERRORLOG::ERRL_SEV_UNRECOVERABLE * @moduleid VPD::VPD_SPD_PRESENCE_DETECT * @userdata1 Buffer Length * @userdata2 <UNUSED> * @devdesc Buffer for checking Presence Detect * was not the correct size. */ err = new ERRORLOG::ErrlEntry( ERRORLOG::ERRL_SEV_UNRECOVERABLE, VPD::VPD_SPD_PRESENCE_DETECT, VPD::VPD_INSUFFICIENT_BUFFER_SIZE, TO_UINT64(io_buflen), 0x0, true /*Add HB Software Callout*/); err->collectTrace( "SPD", 256); break; } // Is the target present? #ifdef CONFIG_DJVPD_READ_FROM_HW // Check if the i2c master is present. // If it is not then no reason to check the DIMM which would // otherwise generate tons of FSI errors. // We can't just check if parent MCA or MBA // is functional because DIMM presence detect is called before // the parent MCS/MCA or MBA/MEMBUF is set as present/functional. bool l_i2cMasterPresent = false; do { // get eeprom vpd primary info TARGETING::EepromVpdPrimaryInfo eepromData; if( !(i_target-> tryGetAttr<TARGETING::ATTR_EEPROM_VPD_PRIMARY_INFO> ( eepromData ) ) ) { TRACFCOMP( g_trac_spd, ERR_MRK"dimmPresenceDetect() " "Error: no eeprom vpd primary info" ); break; } // find i2c master target TARGETING::TargetService& tS = TARGETING::targetService(); bool exists = false; tS.exists( eepromData.i2cMasterPath, exists ); if( !exists ) { TRACFCOMP( g_trac_spd, ERR_MRK"dimmPresenceDetect() " "i2cMasterPath attribute path doesn't exist"); break; } // Since it exists, convert to a target TARGETING::Target * l_i2cMasterTarget = tS.toTarget( eepromData.i2cMasterPath ); if( NULL == l_i2cMasterTarget ) { TRACFCOMP( g_trac_spd, ERR_MRK"dimmPresenceDetect() " "i2cMasterPath target is NULL"); break; } TRACSSCOMP( g_trac_spd, "dimmPresenceDetect() " "i2c master HUID 0x%X", TARGETING::get_huid(l_i2cMasterTarget)); // Check if present TARGETING::Target* masterProcTarget = NULL; TARGETING::targetService().masterProcChipTargetHandle( masterProcTarget ); // Master proc is taken as always present. Validate other targets. if (l_i2cMasterTarget != masterProcTarget) { l_i2cMasterPresent = FSI::isSlavePresent(l_i2cMasterTarget); if( !l_i2cMasterPresent ) { TRACFCOMP( g_trac_spd, ERR_MRK"dimmPresenceDetect() " "isSlavePresent failed"); break; } } l_i2cMasterPresent = true; } while (0); if (!l_i2cMasterPresent) { present = false; // Invalidate the SPD in PNOR err = VPD::invalidatePnorCache(i_target); if (err) { TRACFCOMP( g_trac_spd, ERR_MRK"dimmPresenceDetect() " "Error invalidating SPD in PNOR" ); } break; } #endif present = spdPresent( i_target ); if( present == false ) { TRACUCOMP( g_trac_spd, INFO_MRK"dimmPresenceDetect() " "Dimm was found to be NOT present." ); } else { TRACUCOMP( g_trac_spd, INFO_MRK"dimmPresenceDetect() " "Dimm was found to be present." ); } #if defined(CONFIG_DJVPD_READ_FROM_HW) && defined(CONFIG_DJVPD_READ_FROM_PNOR) if( present ) { // Check if the VPD data in the PNOR matches the SEEPROM err = VPD::ensureCacheIsInSync( i_target ); if( err ) { present = false; TRACFCOMP( g_trac_spd, ERR_MRK"dimmPresenceDetect() " "Error during ensureCacheIsInSync (SPD)" ); break; } } else { // SPD is not present, invalidate the SPD in PNOR err = VPD::invalidatePnorCache(i_target); if (err) { TRACFCOMP( g_trac_spd, ERR_MRK"dimmPresenceDetect() " "Error invalidating SPD in PNOR" ); } } #endif if( present && !err ) { //Fsp sets PN/SN so if there is none, do it here if(!INITSERVICE::spBaseServicesEnabled()) { //populate serial and part number attributes SPD::setPartAndSerialNumberAttributes( i_target ); } // Read ATTR_CLEAR_DIMM_SPD_ENABLE attribute TARGETING::Target* l_sys = NULL; TARGETING::targetService().getTopLevelTarget(l_sys); TARGETING::ATTR_CLEAR_DIMM_SPD_ENABLE_type l_clearSPD = l_sys->getAttr<TARGETING::ATTR_CLEAR_DIMM_SPD_ENABLE>(); // If SPD clear is enabled then write 0's into magic word for // DIMM_BAD_DQ_DATA keyword // Note: If there's an error from performing the clearing, // just log the error and continue. if (l_clearSPD) { size_t l_size = 0; // Do a read to get the DIMM_BAD_DQ_DATA keyword size err = deviceRead(i_target, NULL, l_size, DEVICE_SPD_ADDRESS( DIMM_BAD_DQ_DATA )); if (err) { TRACFCOMP( g_trac_spd, ERR_MRK"dimmPresenceDetect() " "Error reading DIMM_BAD_DQ_DATA keyword size"); errlCommit( err, VPD_COMP_ID ); } else { // Clear the data TRACFCOMP( g_trac_spd, "Clearing out BAD_DQ_DATA SPD on " "DIMM HUID 0x%X", TARGETING::get_huid(i_target)); uint8_t * l_data = static_cast<uint8_t*>(malloc( l_size )); memset(l_data, 0, l_size); err = deviceWrite(i_target, l_data, l_size, DEVICE_SPD_ADDRESS( DIMM_BAD_DQ_DATA )); if (err) { TRACFCOMP(g_trac_spd, ERR_MRK"dimmPresenceDetect() " "Error trying to clear SPD on DIMM HUID 0x%X", TARGETING::get_huid(i_target)); errlCommit( err, VPD_COMP_ID ); } // Free the memory if (NULL != l_data) { free(l_data); } } } } // copy present value into output buffer so caller can read it memcpy( io_buffer, &present, presentSz ); io_buflen = presentSz; } while( 0 ); TRACSSCOMP( g_trac_spd, EXIT_MRK"dimmPresenceDetect()" ); return err; } // end dimmPresenceDetect