diff options
author | mbroyles <mbroyles@us.ibm.com> | 2017-06-23 20:13:06 -0500 |
---|---|---|
committer | William A. Bryan <wilbryan@us.ibm.com> | 2017-06-30 16:10:39 -0400 |
commit | 82156a8c51a11cf1173c5c4064cad903339b07ed (patch) | |
tree | ac60f96955ed414bcf71cfcc58e68b09f8818c33 /src/occ_405/sensor | |
parent | cfb296e1b662022f9f0f86a0a566eae67196f414 (diff) | |
download | talos-occ-82156a8c51a11cf1173c5c4064cad903339b07ed.tar.gz talos-occ-82156a8c51a11cf1173c5c4064cad903339b07ed.zip |
Support new in-band command/response interface and clear sensor command
Change-Id: Ic53e27d851023d99440aa1bfbdf5307920af3397
RTC: 158812
Reviewed-on: http://ralgit01.raleigh.ibm.com/gerrit1/42512
Tested-by: FSP CI Jenkins <fsp-CI-jenkins+hostboot@us.ibm.com>
Reviewed-by: Shawn M. McCarney <shawnmm@us.ibm.com>
Reviewed-by: Christopher J. Cain <cjcain@us.ibm.com>
Reviewed-by: William A. Bryan <wilbryan@us.ibm.com>
Diffstat (limited to 'src/occ_405/sensor')
-rwxr-xr-x | src/occ_405/sensor/sensor.h | 21 | ||||
-rwxr-xr-x | src/occ_405/sensor/sensor_inband_cmd.c | 557 | ||||
-rw-r--r-- | src/occ_405/sensor/sensor_inband_cmd.h | 112 | ||||
-rw-r--r-- | src/occ_405/sensor/sensor_main_memory.h | 1 | ||||
-rwxr-xr-x | src/occ_405/sensor/sensor_service_codes.h | 6 |
5 files changed, 690 insertions, 7 deletions
diff --git a/src/occ_405/sensor/sensor.h b/src/occ_405/sensor/sensor.h index c28b0cd..3b301d9 100755 --- a/src/occ_405/sensor/sensor.h +++ b/src/occ_405/sensor/sensor.h @@ -75,6 +75,12 @@ typedef enum AMEC_SENSOR_TYPE_PERF = 0x0200, AMEC_SENSOR_TYPE_ALL = 0xffff, }AMEC_SENSOR_TYPE; +// Changes to sensor type bits would require changes to select sensor groups command +// Define the sensor types allowed to be selected via select sensor groups command +#define VALID_SET_SENSOR_GROUPS_MASK (AMEC_SENSOR_TYPE_GENERIC | AMEC_SENSOR_TYPE_CURRENT | \ + AMEC_SENSOR_TYPE_VOLTAGE | AMEC_SENSOR_TYPE_TEMP | AMEC_SENSOR_TYPE_UTIL | \ + AMEC_SENSOR_TYPE_TIME | AMEC_SENSOR_TYPE_FREQ | AMEC_SENSOR_TYPE_POWER | \ + AMEC_SENSOR_TYPE_PERF) // AMEC_SENSOR_LOC_INVALID can not be used to identify sensor location. // A bit vector mask is used to specify sensor locations that AMESTER is @@ -113,13 +119,16 @@ typedef enum // AMEC_SENSOR_CLEAR_ALL_MINMAX clears all min/max values in the sensor. typedef enum { - AMEC_SENSOR_CLEAR_SAMPLE_MINMAX = 0x0001, - AMEC_SENSOR_CLEAR_CSM_SAMPLE_MINMAX = 0x0002, - AMEC_SENSOR_CLEAR_PROFILER_SAMPLE_MINMAX = 0x0004, - AMEC_SENSOR_CLEAR_JOB_S_SAMPLE_MINMAX = 0x0008, - AMEC_SENSOR_CLEAR_ALL_MINMAX = 0xffff, + AMEC_SENSOR_CLEAR_SAMPLE_MINMAX = 0x01, + AMEC_SENSOR_CLEAR_CSM_SAMPLE_MINMAX = 0x10, + AMEC_SENSOR_CLEAR_PROFILER_SAMPLE_MINMAX = 0x20, + AMEC_SENSOR_CLEAR_JOB_S_SAMPLE_MINMAX = 0x40, + AMEC_SENSOR_CLEAR_ALL_MINMAX = 0xff, } AMEC_SENSOR_CLEAR_TYPE; - +// The bits for types must match the defined owners in the clear sensor data command +// Define the owners allowed to be cleared via clear sensor data command +#define VALID_CLEAR_SENSOR_OWNER_MASK (AMEC_SENSOR_CLEAR_CSM_SAMPLE_MINMAX | \ + AMEC_SENSOR_CLEAR_PROFILER_SAMPLE_MINMAX | AMEC_SENSOR_CLEAR_JOB_S_SAMPLE_MINMAX) /*****************************************************************************/ // Forward declaration as used in vectorSensor struct sensor; diff --git a/src/occ_405/sensor/sensor_inband_cmd.c b/src/occ_405/sensor/sensor_inband_cmd.c new file mode 100755 index 0000000..15a8967 --- /dev/null +++ b/src/occ_405/sensor/sensor_inband_cmd.c @@ -0,0 +1,557 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/occ_405/sensor/sensor_inband_cmd.c $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 2017,2017 */ +/* [+] International Business Machines Corp. */ +/* */ +/* */ +/* Licensed under the Apache License, Version 2.0 (the "License"); */ +/* you may not use this file except in compliance with the License. */ +/* You may obtain a copy of the License at */ +/* */ +/* http://www.apache.org/licenses/LICENSE-2.0 */ +/* */ +/* Unless required by applicable law or agreed to in writing, software */ +/* distributed under the License is distributed on an "AS IS" BASIS, */ +/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */ +/* implied. See the License for the specific language governing */ +/* permissions and limitations under the License. */ +/* */ +/* IBM_PROLOG_END_TAG */ + + +//****************************************************************************** +// Includes +//****************************************************************************** +#include <cmdh_fsp_cmds.h> +#include <sensor_inband_cmd.h> +#include <homer.h> +#include <occ_service_codes.h> +#include <sensor_service_codes.h> +#include <trac.h> +#include <occhw_async.h> +#include <common.h> + + +//****************************************************************************** +// Block Copy Engine (BCE) Defines/Globals +//****************************************************************************** + +// Buffer in SRAM to copy larger commands cmd/rsp buffer from/to main memory using the BCE +DMA_BUFFER(inband_max_cmd_t G_inband_cmd_max_data_bce_buff) = {{0}}; + +// Buffer in SRAM to copy smaller commands cmd/rsp buffer from/to main memory using the BCE +DMA_BUFFER(inband_min_cmd_t G_inband_cmd_min_data_bce_buff) = {{0}}; + +// BCE request structure. Used by BCE functions to schedule copy request. +BceRequest G_inband_cmd_bce_req; + +/** + * Specifies whether the BCE request was scheduled. If false, the request + * finished or has never been scheduled/initialized. + */ +bool G_inband_cmd_req_scheduled = false; + +// Number of tics passed waiting for BCE callback +uint8_t G_bce_callback_wait = 0; + +volatile uint8_t G_inband_occ_cmd_state = INBAND_OCC_CMD_NONE; +volatile uint8_t G_inband_occ_bce_saved_state = INBAND_OCC_CMD_NONE; + +//****************************************************************************** +// Functions +//****************************************************************************** + + +/** + * Logs an error caused by the Block Copy Engine. Does nothing if a BCE error + * has already been logged. + * + * Note that the required error log comment containing tags like 'userdata4' and + * 'devdesc' must be located by the call to this function. It is not located + * inside this function because the value of those tags varies. + * + * @param i_modId Module ID + * @param i_extReasonCode Extended reason code + * @param i_userData1 Userdata1 value + * @param i_userData2 Userdata2 value + */ +void inband_cmd_log_bce_error(uint16_t i_modId, uint16_t i_extReasonCode, + uint32_t i_userData1, uint32_t i_userData2) +{ + static bool L_error_logged = false; + if (!L_error_logged) + { + // Create and commit error + errlHndl_t l_errl = createErrl(i_modId, // Module ID + INBAND_CMD_ERROR, // Reason code + i_extReasonCode, // Extended reason code + ERRL_SEV_INFORMATIONAL, // Severity + NULL, // Trace Buffers + DEFAULT_TRACE_SIZE, // Trace Size + i_userData1, // Userdata1 + i_userData2); // Userdata2 + commitErrl(&l_errl); + L_error_logged = true; + } +} + + +/** + * Returns whether the global BCE request struct is idle and ready for re-use. + * Returns true immediately if the request was not scheduled. If the request + * was scheduled, checks to see if it has finished. + * + * @param i_caller_mod_id Module ID of calling function in case an error occurs + * @return True if BCE request is idle, false otherwise + */ +bool inband_cmd_is_bce_req_idle(uint16_t i_caller_mod_id) +{ + // Number of times we've waited for current request to finish + static uint8_t L_wait_count = 0; + + // If the request was not previously scheduled, then it is idle. This also + // handles the case where the request has not been initialized yet. + if (!G_inband_cmd_req_scheduled) + { + return true; + } + + // Request was scheduled; check if it finished and is now idle + if (async_request_is_idle(&G_inband_cmd_bce_req.request)) + { + // Request is now idle and ready for re-use + G_inband_cmd_req_scheduled = false; + + // If we were waiting for request to finish, trace and clear wait count + if (L_wait_count > 0) + { + TRAC_INFO("inband_cmd_is_bce_req_idle: " + "Request finished after waiting %u times: caller=0x%04X", + L_wait_count, i_caller_mod_id); + L_wait_count = 0; + } + return true; + } + + // Request was scheduled but has not finished. Increment wait count unless + // we are already at the max (to avoid overflow). + if (L_wait_count < UINT8_MAX) + { + ++L_wait_count; + } + + // If this is the first time we've waited for this request, trace it + if (L_wait_count == 1) + { + TRAC_INFO("inband_cmd_is_bce_req_idle: " + "Waiting for request to finish: caller=0x%04X", + i_caller_mod_id); + } + + // If this is the second time we've waited for this request, log BCE error + if (L_wait_count == 2) + { + /* @ + * @errortype + * @moduleid INBAND_CMD_IS_BCE_REQ_IDLE_MOD + * @reasoncode INBAND_CMD_ERROR + * @userdata1 Caller module ID + * @userdata2 0 + * @userdata4 ERC_GENERIC_TIMEOUT + * @devdesc BCE request not finished after waiting twice + */ + inband_cmd_log_bce_error(INBAND_CMD_IS_BCE_REQ_IDLE_MOD, ERC_GENERIC_TIMEOUT, + i_caller_mod_id, 0); + } + + // Return false since request is not idle + return false; +} + +/** + * inband_cmd_bce_callback + * + * Description: Callback function for G_inband_cmd_bce_req BCE request + * NO TRACING OR CALLING FUNCTIONS THAT TRACE ALLOWED + */ +void inband_cmd_bce_callback( void ) +{ + static bool L_processed_at_least_one_cmd = FALSE; + static uint8_t L_last_seq_num_processed = 0; + uint8_t seq_num = 0; + uint8_t cmd_flags = 0; + + // Decide what to do next for processing an in-band command for the BCE that finished + switch (G_inband_occ_cmd_state) + { + case INBAND_OCC_CMD_CHECK_FOR_CMD: + // check for command uses min bce data buffer + // If we processed at least one cmd it is not a new command if same seq number + cmd_flags = G_inband_cmd_min_data_bce_buff.header.flags; + seq_num = G_inband_cmd_min_data_bce_buff.header.seq; + if( ( (!L_processed_at_least_one_cmd) || + (L_processed_at_least_one_cmd && (seq_num != L_last_seq_num_processed)) ) && + ( (cmd_flags & IN_BAND_CMD_READY_MASK) == IN_BAND_CMD_READY_MASK) ) + { + // There is a command to process + G_inband_occ_cmd_state = INBAND_OCC_CMD_START; + // now that we have a cmd save seq num so we don't keep processing the same cmd + L_processed_at_least_one_cmd = TRUE; + L_last_seq_num_processed = seq_num; + } + else + { + // No command + G_inband_occ_cmd_state = INBAND_OCC_CMD_NONE; + } + break; + + case INBAND_OCC_CMD_RSP_READY: + // response is ready send interrupt + G_inband_occ_cmd_state = INBAND_OCC_CMD_RSP_INT; + break; + + default: + // Invalid state. Can't trace here set state to invalid to trace later + G_inband_occ_bce_saved_state = G_inband_occ_cmd_state; + G_inband_occ_cmd_state = INBAND_OCC_INVALID_BCE_CALLBACK; + break; + } +} + +/** + * Copies the specified number of bytes either to main mem or down from main mem + * for handling an inband command using the Block Copy Engine (BCE). + * + * @param i_main_mem_addr Main memory address for copy. Must be 128-byte aligned + * @param i_sram_addr SRAM address for copy. Must be 128-byte aligned + * @param i_byte_count Number of bytes to copy. Must be multiple of 128. + * Must be <= INBAND_OCC_CMD_BCE_BUF_SIZE. 0 bytes is not valid + * @param i_to_main_mem TRUE indicates copy is sram to main memory + * FALSE indicates copy is main memory to sram + * @param i_caller_mod_id Module ID of the calling function in case an error occurs + * @return True if BCE request was successfully scheduled, false otherwise + */ +bool inband_cmd_bce_copy(uint32_t i_main_mem_addr, uint32_t i_sram_addr, + size_t i_byte_count, bool i_to_main_mem, uint16_t i_caller_mod_id) +{ + int l_rc = 0; + + // Verify address and byte count are valid + static bool L_traced_param_error = false; + if (((i_main_mem_addr % 128) != 0) || ((i_sram_addr % 128) != 0) || + ((i_byte_count % 128) != 0) || (i_byte_count > INBAND_CMD_MAX_BCE_BUF_SIZE) || + (i_byte_count == 0) ) + { + if (!L_traced_param_error) + { + TRAC_ERR("inband_cmd_bce_copy: Input parameter error: " + "address=0x%08X SRAM=0x%08X length=%u caller=0x%04X", + i_main_mem_addr, i_sram_addr, i_byte_count, i_caller_mod_id); + L_traced_param_error = true; + } + return false; + } + + // Check if a copy request was previously scheduled and is not yet finished + static bool L_traced_sched_error = false; + if (!inband_cmd_is_bce_req_idle(i_caller_mod_id)) + { + if (!L_traced_sched_error) + { + TRAC_ERR("inband_cmd_bce_copy: Previous request not finished: caller=0x%04X", + i_caller_mod_id); + L_traced_sched_error = true; + } + return false; + } + + // Create BCE request based on if copy is up or down from main memory + if (i_to_main_mem) + { + l_rc = bce_request_create(&G_inband_cmd_bce_req, // Block copy request + &G_pba_bcue_queue, // SRAM up to mainstore + i_main_mem_addr, // Mainstore address + i_sram_addr, // SRAM start address + i_byte_count, // Size of copy + SSX_WAIT_FOREVER, // No timeout + (AsyncRequestCallback) inband_cmd_bce_callback, + NULL, // No call back args + ASYNC_CALLBACK_IMMEDIATE); + } + else + { + l_rc = bce_request_create(&G_inband_cmd_bce_req, // Block copy request + &G_pba_bcde_queue, // mainstore down to SRAM + i_main_mem_addr, // Mainstore address + i_sram_addr, // SRAM start address + i_byte_count, // Size of copy + SSX_WAIT_FOREVER, // No timeout + (AsyncRequestCallback) inband_cmd_bce_callback, + NULL, // No call back args + ASYNC_CALLBACK_IMMEDIATE); + } + + if (l_rc != SSX_OK) // fail to create BCE request? + { + TRAC_ERR("inband_cmd_bce_copy: Request create failure: rc=0x%08X caller=0x%04X", + -l_rc, i_caller_mod_id); + /* @ + * @errortype + * @moduleid INBAND_CMD_BCE_COPY_MOD + * @reasoncode INBAND_CMD_ERROR + * @userdata1 Return code from bce_request_create() + * @userdata2 Caller module ID + * @userdata4 ERC_BCE_REQUEST_CREATE_FAILURE + * @devdesc Failed to create BCE request + */ + inband_cmd_log_bce_error(INBAND_CMD_BCE_COPY_MOD, ERC_BCE_REQUEST_CREATE_FAILURE, + -l_rc, i_caller_mod_id); + return false; + } + + // Schedule BCE request + l_rc = bce_request_schedule(&G_inband_cmd_bce_req); + if (l_rc != SSX_OK) + { + TRAC_ERR("inband_cmd_bce_copy: Request schedule failure: rc=0x%08X caller=0x%04X", + -l_rc, i_caller_mod_id); + /* @ + * @errortype + * @moduleid INBAND_CMD_BCE_COPY_MOD + * @reasoncode INBAND_CMD_ERROR + * @userdata1 Return code from bce_request_schedule() + * @userdata2 Caller module ID + * @userdata4 ERC_BCE_REQUEST_SCHEDULE_FAILURE + * @devdesc Failed to schedule BCE request + */ + inband_cmd_log_bce_error(INBAND_CMD_BCE_COPY_MOD, ERC_BCE_REQUEST_SCHEDULE_FAILURE, + -l_rc, i_caller_mod_id); + return false; + } + + // Successfully scheduled request. Copy is not blocking, so need to check + // whether it finished later. Set flag indicating request is scheduled. + G_inband_cmd_req_scheduled = true; + return true; +} + + +// Function Specification +// +// Name: inband_command_check +// +// Description: Check for command from the inband interface +// +// End Function Specification +void inband_command_check(void) +{ + // Only check for a new command if not currently processing an inband command + if (G_inband_occ_cmd_state == INBAND_OCC_CMD_NONE) + { + // Create and Schedule BCE to read minimum bytes of OCC inband command buffer in HOMER + memset((void*)&G_inband_cmd_min_data_bce_buff, 0x00, sizeof(inband_min_cmd_t)); + bool i_to_main_mem = FALSE; // this request is main mem down to SRAM + G_inband_occ_cmd_state = INBAND_OCC_CMD_CHECK_FOR_CMD; + G_bce_callback_wait = 0; + if (inband_cmd_bce_copy(INBAND_OCC_CMD_ADDRESS_HOMER, (uint32_t)&G_inband_cmd_min_data_bce_buff, + INBAND_CMD_MIN_BCE_BUF_SIZE, i_to_main_mem, INBAND_CMD_CHECK_MOD)) + { + // Copy succeeded. The BCE callback will handle next + } + else + { + // copy failed try again next time + G_inband_occ_cmd_state = INBAND_OCC_CMD_NONE; + } + } +} + +// Function Specification +// +// Name: inband_command_handler +// +// Description: Command handler for inband commands this should only be called if +// it is already known that there is an in-band command in process +// This is checked to be called on every tick +// +// End Function Specification +void inband_command_handler(void) +{ + uint8_t l_reason_code = ERRL_RC_INTERNAL_FAIL; + uint16_t l_cmd_data_len = 0; + uint8_t l_seq_num = 0; + uint8_t l_cmd_type = 0xFF; + uint16_t l_rsp_data_length = 0; + uint16_t l_bce_copy_size = 0; + uint8_t l_bce_padding = 0; + bool l_to_main_mem = TRUE; // BCE requests from here are going SRAM to main memory + bool l_bce_scheduled = FALSE; + + // Decide what to do next for processing an in-band command + if(G_inband_occ_cmd_state == INBAND_OCC_CMD_START) + { + // We use the max buffer for response + memset((void*)&G_inband_cmd_max_data_bce_buff, 0x00, INBAND_CMD_MAX_BCE_BUF_SIZE); + + // When we check for command we used the minimum bce buffer + l_seq_num = G_inband_cmd_min_data_bce_buff.header.seq; + l_cmd_type = G_inband_cmd_min_data_bce_buff.header.cmd_type; + l_cmd_data_len = CONVERT_UINT8_ARRAY_UINT16(G_inband_cmd_min_data_bce_buff.header.data_length[0], + G_inband_cmd_min_data_bce_buff.header.data_length[1]); + + // if data is more than min we will need to do another BCE to read the rest of the cmd + if(l_cmd_data_len > INBAND_MIN_DATA_LENGTH) + { + // invalid command, currently no cmd supported is larger than min requiring 2nd BCE + l_reason_code = ERRL_RC_INVALID_CMD_LEN; + } + else + { + // Have the full command, process it based on command type. + // cmd data is in min data BCE buffer the rsp data will go in the max data BCE buffer + uint8_t* l_cmd_data_ptr = (uint8_t*) &G_inband_cmd_min_data_bce_buff.data; + uint8_t* l_rsp_data_ptr = (uint8_t*) &G_inband_cmd_max_data_bce_buff.data; + + switch(l_cmd_type) + { + case CMDH_CLEAR_SENSOR_DATA: + l_reason_code = cmdh_clear_sensor_data(l_cmd_data_len, + l_cmd_data_ptr, + INBAND_MAX_DATA_LENGTH, + &l_rsp_data_length, + l_rsp_data_ptr); + break; + + case CMDH_SET_PCAP_INBAND: + l_reason_code = cmdh_set_pcap_inband(l_cmd_data_len, + l_cmd_data_ptr, + INBAND_MAX_DATA_LENGTH, + &l_rsp_data_length, + l_rsp_data_ptr); + break; + + case CMDH_WRITE_PSR: + l_reason_code = cmdh_write_psr(l_cmd_data_len, + l_cmd_data_ptr, + INBAND_MAX_DATA_LENGTH, + &l_rsp_data_length, + l_rsp_data_ptr); + break; + + case CMDH_SELECT_SENSOR_GROUPS: + l_reason_code = cmdh_select_sensor_groups(l_cmd_data_len, + l_cmd_data_ptr, + INBAND_MAX_DATA_LENGTH, + &l_rsp_data_length, + l_rsp_data_ptr); + break; + + default: + l_reason_code = ERRL_RC_INVALID_CMD; + break; + } // end switch + } // end cmd process + + // fill in response header in G_inband_cmd_max_data_bce_buff + G_inband_cmd_max_data_bce_buff.header.flags = IN_BAND_RSP_READY_MASK; + G_inband_cmd_max_data_bce_buff.header.seq = l_seq_num; + G_inband_cmd_max_data_bce_buff.header.cmd_type = l_cmd_type; + G_inband_cmd_max_data_bce_buff.header.reserved_rc = l_reason_code; + G_inband_cmd_max_data_bce_buff.header.data_length[0] = ((uint8_t *)&l_rsp_data_length)[0]; + G_inband_cmd_max_data_bce_buff.header.data_length[1] = ((uint8_t *)&l_rsp_data_length)[1]; + + // Copy the response from SRAM to main memory + // Determine BCE copy size, must be factor of 128 + l_bce_copy_size = sizeof(inband_occ_cmd_header_t) + l_rsp_data_length; + l_bce_padding = l_bce_copy_size % 128; + if(l_bce_padding) + { + l_bce_copy_size += (128 - l_bce_padding); + } + + G_bce_callback_wait = 0; + G_inband_occ_cmd_state = INBAND_OCC_CMD_RSP_READY; + l_bce_scheduled = inband_cmd_bce_copy(INBAND_OCC_RSP_ADDRESS_HOMER, + (uint32_t)&G_inband_cmd_max_data_bce_buff, + l_bce_copy_size, + l_to_main_mem, + INBAND_CMD_HANDLER_MOD); + if (!l_bce_scheduled) + { + // failed to copy response + G_inband_occ_cmd_state = INBAND_OCC_CMD_NONE; + } + else + { + TRAC_INFO("inband_command_handler: Command 0x%02X with " + "seq_num 0x%02X finished with RC 0x%02X", + l_cmd_type, l_seq_num, l_reason_code); + } + + } // INBAND_OCC_CMD_START + + else if(G_inband_occ_cmd_state == INBAND_OCC_CMD_RSP_INT) + { + // Send interrupt to indciate response is ready in main mem + notify_host(INTR_REASON_OPAL_SHARED_MEM_CHANGE); + G_inband_occ_cmd_state = INBAND_OCC_CMD_NONE; + } + + else if( (G_inband_occ_cmd_state == INBAND_OCC_CMD_CHECK_FOR_CMD) || + (G_inband_occ_cmd_state == INBAND_OCC_CMD_RSP_READY) ) + { + // Waiting for BCE to finish, these states are handled by BCE callback + // if the callback is never called (BCE failure) for a max wait log error + G_bce_callback_wait++; + if(G_bce_callback_wait == MAX_TICS_INBAND_BCE_CALLBACK_WAIT) + { + TRAC_ERR("inband_command_handler: Timeout waiting for BCE callback cmd state 0x%02X", + G_inband_occ_cmd_state); + G_inband_occ_cmd_state = INBAND_OCC_CMD_NONE; + /* @ + * @errortype + * @moduleid INBAND_CMD_HANDLER_MOD + * @reasoncode INBAND_CMD_ERROR + * @userdata1 Inband command state + * @userdata2 Caller module ID + * @userdata4 ERC_BCE_REQ_CALLBACK_TIMEOUT + * @devdesc Timeout waiting for BCE callback + */ + inband_cmd_log_bce_error(INBAND_CMD_HANDLER_MOD, ERC_BCE_REQ_CALLBACK_TIMEOUT, + G_inband_occ_cmd_state, INBAND_CMD_HANDLER_MOD); + } + } + + else if(G_inband_occ_cmd_state == INBAND_OCC_INVALID_BCE_CALLBACK) + { + // BCE callback was called with invalid state, trace now and set state to none + static bool L_traced_bce_bad_state = FALSE; + if (!L_traced_bce_bad_state) + { + TRAC_ERR("inband_command_handler: inband_cmd_bce_callback detected invalid state %u", + G_inband_occ_bce_saved_state); + L_traced_bce_bad_state = TRUE; + } + G_inband_occ_cmd_state = INBAND_OCC_CMD_NONE; + G_inband_occ_bce_saved_state = INBAND_OCC_CMD_NONE; + } + + else + { + // Invalid state + static bool L_traced_bad_state = FALSE; + if (!L_traced_bad_state) + { + TRAC_ERR("inband_command_handler: Called with invalid state %u", + G_inband_occ_cmd_state); + L_traced_bad_state = TRUE; + } + G_inband_occ_cmd_state = INBAND_OCC_CMD_NONE; + } +} diff --git a/src/occ_405/sensor/sensor_inband_cmd.h b/src/occ_405/sensor/sensor_inband_cmd.h new file mode 100644 index 0000000..4e39f84 --- /dev/null +++ b/src/occ_405/sensor/sensor_inband_cmd.h @@ -0,0 +1,112 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/occ_405/sensor/sensor_inband_cmd.h $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 2017,2017 */ +/* [+] International Business Machines Corp. */ +/* */ +/* */ +/* Licensed under the Apache License, Version 2.0 (the "License"); */ +/* you may not use this file except in compliance with the License. */ +/* You may obtain a copy of the License at */ +/* */ +/* http://www.apache.org/licenses/LICENSE-2.0 */ +/* */ +/* Unless required by applicable law or agreed to in writing, software */ +/* distributed under the License is distributed on an "AS IS" BASIS, */ +/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */ +/* implied. See the License for the specific language governing */ +/* permissions and limitations under the License. */ +/* */ +/* IBM_PROLOG_END_TAG */ + +#ifndef _SENSOR_INBAND_CMD_H +#define _SENSOR_INBAND_CMD_H + +/** + * @file sensor_inband_cmd.h + * + * This file declares the functions and global variables for supporting the inband + * command protocol defined in the OCC Firmware Interface spec + * + */ + +//****************************************************************************** +// Defines/Structs/Globals +//****************************************************************************** + +// States of inband OCC command processing +typedef enum +{ + INBAND_OCC_CMD_NONE = 0x00, // No inband command in process + INBAND_OCC_CMD_CHECK_FOR_CMD = 0x01, // Check for cmd when BCE read finishes + INBAND_OCC_CMD_START = 0x02, // Start processing the command + INBAND_OCC_CMD_RSP_READY = 0x03, // Response ready + INBAND_OCC_CMD_RSP_INT = 0x04, // Send Response Interrupt + INBAND_OCC_INVALID_BCE_CALLBACK = 0x05, // BCE callback called with invalid OCC cmd state +} INBAND_OCC_CMD_STATE; + +// Current state of inband OCC command processing +extern volatile uint8_t G_inband_occ_cmd_state; +// Last state saved for error handling +extern volatile uint8_t G_inband_occ_bce_saved_state; + +#define MAX_TICS_INBAND_BCE_CALLBACK_WAIT 0x03 +#define IN_BAND_CMD_READY_MASK 0x80 +#define IN_BAND_RSP_IN_PROGRESS_MASK 0x02 +#define IN_BAND_RSP_READY_MASK 0x01 + +typedef struct __attribute__ ((packed)) +{ + uint8_t flags; + uint8_t seq; + uint8_t cmd_type; + uint8_t reserved_rc; // as a command reserved, as a response RC + uint8_t data_length[2]; +} inband_occ_cmd_header_t; + +// Data Size is Block Copy Engine dependent, 128 min to 4kB max +#define INBAND_CMD_MIN_BCE_BUF_SIZE 128 +#define INBAND_CMD_MAX_BCE_BUF_SIZE 4096 +#define INBAND_MAX_DATA_LENGTH INBAND_CMD_MAX_BCE_BUF_SIZE - sizeof(inband_occ_cmd_header_t) +#define INBAND_MIN_DATA_LENGTH INBAND_CMD_MIN_BCE_BUF_SIZE - sizeof(inband_occ_cmd_header_t) + +typedef struct __attribute__ ((packed)) +{ + inband_occ_cmd_header_t header; + // Data bytes + uint8_t data[INBAND_MIN_DATA_LENGTH]; +}inband_min_cmd_t; + +typedef struct __attribute__ ((packed)) +{ + inband_occ_cmd_header_t header; + // Data bytes + uint8_t data[INBAND_MAX_DATA_LENGTH]; +}inband_max_cmd_t; + +//****************************************************************************** +// Function Prototypes +//****************************************************************************** + +/** + * Check for a command from the inband command/response interface + * + * There are inband commands to select sensors to write to main memory and + * clear sensors min/max by user + * + * This function is called from amec_slv_common_tasks_post() + */ +void inband_command_check(void); + +/** + * Handle a command from the inband command/response interface + * + * This function is called from amec_slv_substate_6_x + */ +void inband_command_handler(void); + +#endif // _SENSOR_INBAND_CMD_H diff --git a/src/occ_405/sensor/sensor_main_memory.h b/src/occ_405/sensor/sensor_main_memory.h index f9cd29f..f989e13 100644 --- a/src/occ_405/sensor/sensor_main_memory.h +++ b/src/occ_405/sensor/sensor_main_memory.h @@ -302,5 +302,4 @@ void main_mem_sensors_update(void); */ void main_mem_sensors_set_enabled(AMEC_SENSOR_TYPE i_sensor_type, bool i_enabled); - #endif // _SENSOR_MAIN_MEMORY_H diff --git a/src/occ_405/sensor/sensor_service_codes.h b/src/occ_405/sensor/sensor_service_codes.h index 397a2d5..f511edf 100755 --- a/src/occ_405/sensor/sensor_service_codes.h +++ b/src/occ_405/sensor/sensor_service_codes.h @@ -44,6 +44,12 @@ enum occSensorModuleId MM_SENSORS_WRITE_NAMES_MOD = SNSR_COMP_ID | 0x16, MM_SENSORS_WRITE_READINGS_MOD = SNSR_COMP_ID | 0x17, MM_SENSORS_VALIDATE_READINGS_MOD = SNSR_COMP_ID | 0x18, + + // Inband commands + INBAND_CMD_IS_BCE_REQ_IDLE_MOD = SNSR_COMP_ID | 0x20, + INBAND_CMD_BCE_COPY_MOD = SNSR_COMP_ID | 0x21, + INBAND_CMD_HANDLER_MOD = SNSR_COMP_ID | 0x22, + INBAND_CMD_CHECK_MOD = SNSR_COMP_ID | 0x23, }; #endif /* #ifndef _SENSOR_SERVICE_CODES_H_ */ |