// Function Specification // // Name: cmdh_mnfg_read_pstate_table // // Description: This function handles the manufacturing command to read // the generated Pstate table from main memory 3K blocks at a time // // End Function Specification uint8_t cmdh_mnfg_read_pstate_table(const cmdh_fsp_cmd_t * i_cmd_ptr, cmdh_fsp_rsp_t * o_rsp_ptr) { uint8_t l_rc = ERRL_RC_SUCCESS; uint16_t l_datalength = 0; uint16_t l_resp_data_length = 0; uint32_t block_offset = 0; uint32_t main_mem_address = 0; int l_ssxrc = SSX_OK; mnfg_read_pstate_table_cmd_t *l_cmd_ptr = (mnfg_read_pstate_table_cmd_t*) i_cmd_ptr; do { // Check command packet data length l_datalength = CMDH_DATALEN_FIELD_UINT16(i_cmd_ptr); if(l_datalength != (sizeof(mnfg_read_pstate_table_cmd_t) - sizeof(cmdh_fsp_cmd_header_t))) { TRAC_ERR("cmdh_mnfg_read_pstate_table: incorrect data length. exp[%d] act[%d]", (sizeof(mnfg_read_pstate_table_cmd_t) - sizeof(cmdh_fsp_cmd_header_t)), l_datalength); l_rc = ERRL_RC_INVALID_CMD_LEN; break; } // Process request if(l_cmd_ptr->request == MFG_PSTATE_READ_REQUEST_QUERY) { memcpy(&o_rsp_ptr->data[0], &G_pgpe_header.generated_pstate_table_homer_offset, 4); memcpy(&o_rsp_ptr->data[4], &G_pgpe_header.generated_pstate_table_length, 4); l_resp_data_length = MFG_PSTATE_READ_QUERY_RSP_SIZE; TRAC_INFO("cmdh_mnfg_read_pstate_table: Query table memory offset[0x%08x] table length[%d]", G_pgpe_header.generated_pstate_table_homer_offset, G_pgpe_header.generated_pstate_table_length); break; } // Calculate the starting main memory address for block to read block_offset = MFG_PSTATE_READ_MAX_RSP_SIZE * l_cmd_ptr->request; if(block_offset > G_pgpe_header.generated_pstate_table_length) { TRAC_ERR("cmdh_mnfg_read_pstate_table: Block request %d out of range. Pstate Table size %d", l_cmd_ptr->request, G_pgpe_header.generated_pstate_table_length); l_rc = ERRL_RC_INVALID_DATA; break; } main_mem_address = G_pgpe_header.generated_pstate_table_homer_offset + block_offset; // Copy Pstate table from main memory to SRAM // Set up a copy request l_ssxrc = bce_request_create(&G_mfg_pba_request, // block copy object &G_pba_bcde_queue, // mainstore to sram copy engine main_mem_address, // mainstore address (uint32_t)&G_mfg_read_pstate_table, // sram starting address sizeof(mfg_read_pstate_table_t), // size of copy SSX_SECONDS(1), // timeout NULL, // no call back NULL, // no call back arguments ASYNC_REQUEST_BLOCKING); // blocking request if(l_ssxrc != SSX_OK) { TRAC_ERR("cmdh_mnfg_read_pstate_table: BCDE request create failure rc=[%08X]", -l_ssxrc); l_rc = ERRL_RC_INTERNAL_FAIL; break; } // Do actual copying l_ssxrc = bce_request_schedule(&G_mfg_pba_request); if(l_ssxrc != SSX_OK) { TRAC_ERR("cmdh_mnfg_read_pstate_table: BCE request schedule failure rc=[%08X]", -l_ssxrc); l_rc = ERRL_RC_INTERNAL_FAIL; break; } // Determine the rsp data length l_resp_data_length = MFG_PSTATE_READ_MAX_RSP_SIZE; if((block_offset + MFG_PSTATE_READ_MAX_RSP_SIZE) > G_pgpe_header.generated_pstate_table_length) { l_resp_data_length = G_pgpe_header.generated_pstate_table_length - block_offset; } // Copy to response buffer memcpy(o_rsp_ptr->data, &G_mfg_read_pstate_table, l_resp_data_length); TRAC_INFO("cmdh_mnfg_read_pstate_table: Read from main memory[0x%08x] block offset[%d] length[%d]", main_mem_address, block_offset, l_resp_data_length); }while(0); // Populate the response data header G_rsp_status = l_rc; o_rsp_ptr->data_length[0] = ((uint8_t *)&l_resp_data_length)[0]; o_rsp_ptr->data_length[1] = ((uint8_t *)&l_resp_data_length)[1]; return l_rc; }
// 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: apss_initialize // // Description: Completes all APSS initialization including GPIOs, altitude and // mode // // End Function Specification errlHndl_t apss_initialize() { errlHndl_t l_err = NULL; PoreFlex request; // Setup the GPIO init structure to pass to the GPE program G_gpe_apss_initialize_gpio_args.error.error = 0; G_gpe_apss_initialize_gpio_args.error.ffdc = 0; G_gpe_apss_initialize_gpio_args.config0.direction = G_gpio_config[0].direction; G_gpe_apss_initialize_gpio_args.config0.drive = G_gpio_config[0].drive; G_gpe_apss_initialize_gpio_args.config0.interrupt = G_gpio_config[0].interrupt; G_gpe_apss_initialize_gpio_args.config1.direction = G_gpio_config[1].direction; G_gpe_apss_initialize_gpio_args.config1.drive = G_gpio_config[1].drive; G_gpe_apss_initialize_gpio_args.config1.interrupt = G_gpio_config[1].interrupt; // Create/schedule GPE_apss_initialize_gpio and wait for it to complete (BLOCKING) TRAC_INFO("Creating request for GPE_apss_initialize_gpio"); pore_flex_create(&request, // request &G_pore_gpe0_queue, // queue (void*)GPE_apss_initialize_gpio, // GPE entry_point (uint32_t)&G_gpe_apss_initialize_gpio_args,// GPE argument_ptr SSX_SECONDS(5), // timeout NULL, // callback NULL, // callback arg ASYNC_REQUEST_BLOCKING); // options // Schedule the request to be executed pore_flex_schedule(&request); // Check for a timeout, will create the error log later // NOTE: As of 2013/07/16, simics will still fail here on a OCC reset if(ASYNC_REQUEST_STATE_TIMED_OUT == request.request.completion_state) { // For whatever reason, we hit a timeout. It could be either // that the HW did not work, or the request didn't ever make // it to the front of the queue. // Let's log an error, and include the FFDC data if it was // generated. TRAC_ERR("Timeout communicating with PORE-GPE for APSS Init"); } TRAC_INFO("GPE_apss_initialize_gpio completed w/rc=0x%08x\n", request.request.completion_state); // Only continue if completed without errors... if (ASYNC_REQUEST_STATE_COMPLETE == request.request.completion_state) { // Setup the composite mode structure to pass to the GPE program G_gpe_apss_set_composite_mode_args.error.error = 0; G_gpe_apss_set_composite_mode_args.error.ffdc = 0; G_gpe_apss_set_composite_mode_args.config.numAdcChannelsToRead = G_apss_composite_config.numAdcChannelsToRead; G_gpe_apss_set_composite_mode_args.config.numGpioPortsToRead = G_apss_composite_config.numGpioPortsToRead; // Create/schedule GPE_apss_set_composite_mode and wait for it to complete (BLOCKING) TRAC_INFO("Creating request for GPE_apss_set_composite_mode"); pore_flex_create(&request, // request &G_pore_gpe0_queue, // queue (void*)GPE_apss_set_composite_mode, // GPE entry_point (uint32_t)&G_gpe_apss_set_composite_mode_args,// GPE argument_ptr SSX_SECONDS(5), // timeout NULL, // callback NULL, // callback arg ASYNC_REQUEST_BLOCKING); // options pore_flex_schedule(&request); // Check for a timeout, will create the error log later if(ASYNC_REQUEST_STATE_TIMED_OUT == request.request.completion_state) { // For whatever reason, we hit a timeout. It could be either // that the HW did not work, or the request didn't ever make // it to the front of the queue. // Let's log an error, and include the FFDC data if it was // generated. TRAC_ERR("Timeout communicating with PORE-GPE for APSS Init"); } TRAC_INFO("GPE_apss_set_composite_mode completed w/rc=0x%08x", request.request.completion_state); if (ASYNC_REQUEST_STATE_COMPLETE != request.request.completion_state) { /* * @errortype * @moduleid PSS_MID_APSS_INIT * @reasoncode INTERNAL_FAILURE * @userdata1 GPE returned rc code * @userdata2 GPE returned abort code * @userdata4 ERC_PSS_COMPOSITE_MODE_FAIL * @devdesc Failure from GPE for setting composite mode on * APSS */ l_err = createErrl(PSS_MID_APSS_INIT, // i_modId, INTERNAL_FAILURE, // i_reasonCode, ERC_PSS_COMPOSITE_MODE_FAIL, // extended reason code ERRL_SEV_UNRECOVERABLE, // i_severity NULL, // i_trace, 0x0000, // i_traceSz, request.request.completion_state, // i_userData1, request.request.abort_state); // i_userData2 addUsrDtlsToErrl(l_err, (uint8_t*)&G_gpe_apss_set_composite_mode_args, sizeof(G_gpe_apss_set_composite_mode_args), ERRL_STRUCT_VERSION_1, ERRL_USR_DTL_TRACE_DATA); // Returning an error log will cause us to go to safe // state so we can report error to FSP } TRAC_INFO("apss_initialize: Creating request G_meas_start_request."); //Create the request for measure start. Scheduling will happen in apss.c pore_flex_create(&G_meas_start_request, &G_pore_gpe0_queue, // queue (void*)GPE_apss_start_pwr_meas_read, // entry_point (uint32_t)&G_gpe_start_pwr_meas_read_args, // entry_point arg SSX_WAIT_FOREVER, // no timeout NULL, // callback NULL, // callback arg ASYNC_CALLBACK_IMMEDIATE); // options TRAC_INFO("apss_initialize: Creating request G_meas_cont_request."); //Create the request for measure continue. Scheduling will happen in apss.c pore_flex_create(&G_meas_cont_request, &G_pore_gpe0_queue, // request (void*)GPE_apss_continue_pwr_meas_read, // entry_point (uint32_t)&G_gpe_continue_pwr_meas_read_args, // entry_point arg SSX_WAIT_FOREVER, // no timeout NULL, // callback NULL, // callback arg ASYNC_CALLBACK_IMMEDIATE); // options TRAC_INFO("apss_initialize: Creating request G_meas_complete_request."); //Create the request for measure complete. Scheduling will happen in apss.c pore_flex_create(&G_meas_complete_request, &G_pore_gpe0_queue, // queue (void*)GPE_apss_complete_pwr_meas_read, // entry_point (uint32_t)&G_gpe_complete_pwr_meas_read_args,// entry_point arg SSX_WAIT_FOREVER, // no timeout (AsyncRequestCallback)reformat_meas_data, // callback, (void*)NULL, // callback arg ASYNC_CALLBACK_IMMEDIATE); // options } else { /* * @errortype * @moduleid PSS_MID_APSS_INIT * @reasoncode INTERNAL_FAILURE * @userdata1 GPE returned rc code * @userdata2 GPE returned abort code * @userdata4 ERC_PSS_GPIO_INIT_FAIL * @devdesc Failure from GPE for gpio initialization on APSS */ l_err = createErrl(PSS_MID_APSS_INIT, // i_modId, INTERNAL_FAILURE, // i_reasonCode, ERC_PSS_GPIO_INIT_FAIL, // extended reason code ERRL_SEV_UNRECOVERABLE, // i_severity NULL, // tracDesc_t i_trace, 0x0000, // i_traceSz, request.request.completion_state, // i_userData1, request.request.abort_state); // i_userData2 addUsrDtlsToErrl(l_err, (uint8_t*)&G_gpe_apss_initialize_gpio_args, sizeof(G_gpe_apss_initialize_gpio_args), ERRL_STRUCT_VERSION_1, ERRL_USR_DTL_TRACE_DATA); // Returning an error log will cause us to go to safe // state so we can report error to FSP } return l_err; }
// Function Specification // // Name: cmdh_snapshot_sync // // Description: Resets the snapshot buffer array and starts a new snapshot buffer from time 0. // // End Function Specification errlHndl_t cmdh_snapshot_sync(const cmdh_fsp_cmd_t * i_cmd_ptr, cmdh_fsp_rsp_t * o_rsp_ptr) { cmdh_snapshot_sync_query_t *l_cmd_ptr = (cmdh_snapshot_sync_query_t *) i_cmd_ptr; cmdh_snapshot_sync_resp_t *l_resp_ptr = (cmdh_snapshot_sync_resp_t *) o_rsp_ptr; errlHndl_t l_err = NULL; uint8_t l_query_sz = 0; ERRL_RC l_rc = 0; do { l_query_sz = CMDH_DATALEN_FIELD_UINT16(i_cmd_ptr); // Verify query data size if(l_query_sz != CMDH_SNAPSHOT_SYNC_DATA_SIZE) { TRAC_ERR("cmdh_snapshot_sync: Received an invalid packet size. Expecting 1 byte, received:%i", l_query_sz); l_rc = ERRL_RC_INVALID_CMD_LEN; break; } l_cmd_ptr = (cmdh_snapshot_sync_query_t *)i_cmd_ptr; // Check received packet version if (CMDH_SNAPSHOT_SYNC_VERSION != l_cmd_ptr->version) { TRAC_ERR("cmdh_snapshot_sync: Version %i cmd is not supported.", l_cmd_ptr->version); l_rc = ERRL_RC_INVALID_DATA; break; } // Set the global reset flag, that will cause all saved data to be cleared in the // next callback that is done every 30 seconds via a timer. g_cmdh_snapshot_reset = TRUE; // Reset current index to stop any possible calls from tmgt to get snapshot buffers. g_cmdh_snapshot_cur_index = CMDH_SNAPSHOT_DEFAULT_CUR_INDEX; // Reset timer and start counting from now. This will cause a call to the snapshot_callback // function below which will reset the other globals based on the fact that g_cmdh_snapshot_reset // is set to true. l_rc = ssx_timer_schedule(&G_snapshotTimer, 0, SSX_SECONDS(30)); if (l_rc != SSX_OK) { TRAC_ERR("cmdh_snapshot_sync: reseting the snapshot timer failed."); break; } TRAC_INFO("cmdh_snapshot_sync: Snapshot buffer has been reset!"); l_resp_ptr->data_length[0] = 0; l_resp_ptr->data_length[1] = 0; G_rsp_status = 0; }while(FALSE); if (l_rc) { // Build Error Response packet cmdh_build_errl_rsp(i_cmd_ptr, o_rsp_ptr, l_rc, &l_err); } return(l_err); }