// Initialize the memory task data void memory_init() { if(G_mem_monitoring_allowed) { // Check if memory task is running (default task is for NIMBUS) const task_id_t mem_task = TASK_ID_DIMM_SM; if(!rtl_task_is_runnable(mem_task)) { if (MEM_TYPE_NIMBUS == G_sysConfigData.mem_type) { // Init DIMM state manager IPC request memory_nimbus_init(); } else { // TODO CUMULUS NOT SUPPORTED YET IN PHASE1 #if 0 TRAC_INFO("memory_init: calling centaur_init()"); centaur_init(); //no rc, handles errors internally #endif TRAC_ERR("memory_init: invalid memory type 0x%02X", G_sysConfigData.mem_type); /* * @errortype * @moduleid DIMM_MID_MEMORY_INIT * @reasoncode MEMORY_INIT_FAILED * @userdata1 memory type * @userdata2 0 * @devdesc Invalid memory type detected */ errlHndl_t err = createErrl(DIMM_MID_MEMORY_INIT, MEMORY_INIT_FAILED, OCC_NO_EXTENDED_RC, ERRL_SEV_PREDICTIVE, NULL, DEFAULT_TRACE_SIZE, G_sysConfigData.mem_type, 0); REQUEST_RESET(err); } // check if the init resulted in a reset if(isSafeStateRequested()) { TRAC_ERR("memory_init: OCC is being reset, memory init failed (type=0x%02X)", G_sysConfigData.mem_type); } else { // Initialization was successful. Set task flags to allow memory // tasks to run and also prevent from doing initialization again. G_task_table[mem_task].flags = MEMORY_DATA_RTL_FLAGS; //G_task_table[TASK_ID_CENTAUR_CONTROL].flags = MEMORY_CONTROL_RTL_FLAGS; } } } } // end memory_init()
// Function Specification // // Name: proc_check_for_sapphire_updates // // Description: Checks if the sapphire table needs an update // and updates if necessary. // // End Function Specification void proc_check_for_sapphire_updates() { uint8_t l_latest_throttle_reason; //If safe state is requested then that overrides anything from amec if(isSafeStateRequested()) { l_latest_throttle_reason = OCC_RESET; } else { l_latest_throttle_reason = G_amec_kvm_throt_reason; } //If the throttle reason changed, update it in the HOMER if(G_sapphire_table.config.throttle != l_latest_throttle_reason) { TRAC_INFO("proc_check_for_sapphire_updates: throttle reason changed to %d", l_latest_throttle_reason); G_sapphire_table.config.throttle = l_latest_throttle_reason; G_sapphire_table.config.version = 0x02; // default 0x02 G_sapphire_table.config.valid = 0x01; //default 0x01 populate_sapphire_tbl_to_mem(); } }
// Function Specification // // Name: Dcom_thread_routine // // Description: Purpose of this task is to handle messages passed from // Master to Slave and vice versa. // // Nothing in this thread should be time-critical, but should // happen more often than the 1-second that other threads run // at. // // This thread currently runs ~1ms, based on the RTL loop of // 250us. // // FWIW -- It is pointless to set this thread to run any more // often than the length of the RTL loop, since it is acting // on data passed back and forth via that loop. // // End Function Specification void Dcom_thread_routine(void *arg) { OCC_STATE l_newOccState = 0; OCC_MODE l_newOccMode = 0; SsxTimer l_timeout_timer; errlHndl_t l_errlHndl = NULL; // -------------------------------------------------- // Create a timer that pops every 10 seconds to wake up // this thread, in case a semaphore never gets posted. // TODO: Is this really needed? // -------------------------------------------------- ssx_timer_create(&l_timeout_timer, (SsxTimerCallback) ssx_semaphore_post, (void *) &G_dcomThreadWakeupSem); ssx_timer_schedule(&l_timeout_timer, SSX_SECONDS(10), SSX_SECONDS(10)); for(;;) { // -------------------------------------------------- // Wait on Semaphore until we get new data over DCOM // (signalled by sem_post() or timeout occurs. // Sem timeout is designed to be the slowest // interval we will attempt to run this thread at. // -------------------------------------------------- // Wait for sem_post before we run through this thread. ssx_semaphore_pend(&G_dcomThreadWakeupSem, SSX_WAIT_FOREVER); // -------------------------------------------------- // Counter to ensure thread is running (can wrap) // -------------------------------------------------- G_dcom_thread_counter++; // -------------------------------------------------- // Check if we need to update the sapphire table // -------------------------------------------------- if(G_sysConfigData.system_type.kvm) { proc_check_for_sapphire_updates(); } // -------------------------------------------------- // Set Mode and State Based on Master // -------------------------------------------------- l_newOccState = (G_occ_master_state == CURRENT_STATE()) ? OCC_STATE_NOCHANGE : G_occ_master_state; if(G_sysConfigData.system_type.kvm) { l_newOccMode = (G_occ_master_mode == G_occ_external_req_mode_kvm ) ? OCC_MODE_NOCHANGE : G_occ_master_mode; } else { l_newOccMode = (G_occ_master_mode == CURRENT_MODE() ) ? OCC_MODE_NOCHANGE : G_occ_master_mode; } // Override State if SAFE state is requested l_newOccState = ( isSafeStateRequested() ) ? OCC_STATE_SAFE : l_newOccState; // Override State if we are in SAFE state already l_newOccState = ( OCC_STATE_SAFE == CURRENT_STATE() ) ? OCC_STATE_NOCHANGE : l_newOccState; if( (OCC_STATE_NOCHANGE != l_newOccState) || (OCC_MODE_NOCHANGE != l_newOccMode) ) { // If we're active, then we should always process the mode change first // If we're not active, then we should always process the state change first if(OCC_STATE_ACTIVE == CURRENT_STATE()) { // Set the new mode l_errlHndl = SMGR_set_mode(l_newOccMode, 0 /* TODO V/F */ ); if(l_errlHndl) { commitErrl(&l_errlHndl); } // Set the new state l_errlHndl = SMGR_set_state(l_newOccState); if(l_errlHndl) { commitErrl(&l_errlHndl); } } else { // Set the new state l_errlHndl = SMGR_set_state(l_newOccState); if(l_errlHndl) { commitErrl(&l_errlHndl); } // Set the new mode l_errlHndl = SMGR_set_mode(l_newOccMode, 0 /* TODO V/F */ ); if(l_errlHndl) { commitErrl(&l_errlHndl); } } } // -------------------------------------------------- // DCM PStates // \_ can do sem_post to increment through state machine // -------------------------------------------------- if(OCC_STATE_SAFE != CURRENT_STATE()) { proc_gpsm_dcm_sync_enable_pstates_smh(); } // -------------------------------------------------- // SSX Sleep // -------------------------------------------------- // Even if semaphores are continually posted, there is no reason // for us to run this thread any more often than once every 250us // so we don't starve any other thread ssx_sleep(SSX_MICROSECONDS(250)); } }
// Function Specification // // Name: task_dcom_parse_occfwmsg // // Description: Purpose of this task is to handle and acknowledge // fw messages passed from Master to Slave and vice versa. // // End Function Specification void task_dcom_parse_occfwmsg(task_t *i_self) { if(G_occ_role == OCC_MASTER) { // Local slave index counter uint32_t l_slv_idx = 0; // Loop and collect occ data for each slave occ for(; l_slv_idx < MAX_OCCS; l_slv_idx++) { // Verify all slave are in correct state and mode G_dcom_slv_outbox_rx[l_slv_idx].occ_fw_mailbox[0] = CURRENT_STATE(); if(G_sysConfigData.system_type.kvm ) { G_dcom_slv_outbox_rx[l_slv_idx].occ_fw_mailbox[1] = G_occ_external_req_mode_kvm; } else { G_dcom_slv_outbox_rx[l_slv_idx].occ_fw_mailbox[1] = CURRENT_MODE(); } // Acknowledge all slave event flags G_slave_event_flags_ack[l_slv_idx] = G_dcom_slv_outbox_rx[l_slv_idx].occ_fw_mailbox[3]; // Clear master event flags if slave has acknowledged them and the event has cleared G_master_event_flags &= ~G_dcom_slv_outbox_rx[l_slv_idx].occ_fw_mailbox[2]; } }//End master role check // Check if master has changed state and mode and update if changed // so that we can handle it in a thread. if( (G_occ_master_state != G_dcom_slv_inbox_rx.occ_fw_mailbox[0]) || (G_occ_master_mode != G_dcom_slv_inbox_rx.occ_fw_mailbox[1]) ) { if( ! isSafeStateRequested() ) { G_occ_master_state = G_dcom_slv_inbox_rx.occ_fw_mailbox[0]; G_occ_master_mode = G_dcom_slv_inbox_rx.occ_fw_mailbox[1]; ssx_semaphore_post(&G_dcomThreadWakeupSem); } } // If we are master, we don't want to update based on // the data sent to us, because it corrupts the 'golden' data // If we are in standby, we don't want to update because // the data may not have been set up yet, and would be set to zero. if(OCC_MASTER != G_occ_role ) { // Update the system mode frequencies if they have changed int l_mode = 0; bool l_change = FALSE; bool l_all_zero = TRUE; // Check if all values are zero for(l_mode = 0; l_mode<OCC_MODE_COUNT; l_mode++) { if( (0 != G_dcom_slv_inbox_rx.sys_mode_freq.table[l_mode]) ) { l_all_zero = FALSE; break; } } extern data_cnfg_t * G_data_cnfg; if( l_all_zero == FALSE) { for(l_mode =0; l_mode<OCC_MODE_COUNT; l_mode++) { // Don't trust a frequency of 0x0000 if( (0 != G_dcom_slv_inbox_rx.sys_mode_freq.table[l_mode]) ) { if(G_sysConfigData.sys_mode_freq.table[l_mode] != G_dcom_slv_inbox_rx.sys_mode_freq.table[l_mode]) { TRAC_INFO("New Frequency for Mode %d: Old: %d MHz -> New: %d MHz",l_mode, G_sysConfigData.sys_mode_freq.table[l_mode], G_dcom_slv_inbox_rx.sys_mode_freq.table[l_mode]); // Update mode frequency G_sysConfigData.sys_mode_freq.table[l_mode] = G_dcom_slv_inbox_rx.sys_mode_freq.table[l_mode]; l_change = TRUE; } } } if(l_change) { // Update "update count" for debug purposes G_sysConfigData.sys_mode_freq.update_count = G_dcom_slv_inbox_rx.sys_mode_freq.update_count; // Change Data Request Mask to indicate we got this data extern data_cnfg_t * G_data_cnfg; G_data_cnfg->data_mask |= DATA_MASK_FREQ_PRESENT; // Notify AMEC that the frequencies have changed AMEC_data_change(DATA_MASK_FREQ_PRESENT); } } else { // Clear Data Request Mask and data G_data_cnfg->data_mask &= (~DATA_MASK_FREQ_PRESENT); memset(&G_sysConfigData.sys_mode_freq.table[0], 0, sizeof(G_sysConfigData.sys_mode_freq.table)); } } // Copy mnfg parameters into g_amec structure g_amec->foverride_enable = G_dcom_slv_inbox_rx.foverride_enable; g_amec->foverride = G_dcom_slv_inbox_rx.foverride; // Copy IPS parameters sent by Master OCC g_amec->slv_ips_freq_request = G_dcom_slv_inbox_rx.ips_freq_request; // Copy DPS tunable parameters sent by Master OCC if required if(G_dcom_slv_inbox_rx.tunable_param_overwrite) { AMEC_part_overwrite_dps_parameters(); if(G_dcom_slv_inbox_rx.tunable_param_overwrite == 1) { g_amec->slv_dps_param_overwrite = TRUE; } else { g_amec->slv_dps_param_overwrite = FALSE; } } // Copy soft frequency boundaries sent by Master OCC g_amec->part_config.part_list[0].soft_fmin = G_dcom_slv_inbox_rx.soft_fmin; g_amec->part_config.part_list[0].soft_fmax = G_dcom_slv_inbox_rx.soft_fmax; // acknowledge all masters event flags G_master_event_flags_ack = G_dcom_slv_inbox_rx.occ_fw_mailbox[2]; // clear slave event flags if master has acknowledged them and the event has cleared G_slave_event_flags = (G_slave_event_flags & (~(G_dcom_slv_inbox_rx.occ_fw_mailbox[3]))); }