blob: f662690a7ac44e7b8920513ca762b7365eec4cab [file] [log] [blame]
#include <stdexcept>
#include <array>
#include <sbe_chipOp_handler.hpp>
namespace openpower
{
namespace sbe
{
namespace internal
{
/*! \union sbeRespHeader_t
* Defines the breakup of the SBE FIFO chip operation response header.
*/
union sbeRespHeader_t
{
uint32_t commandWord; /**<Entire 32 bit command word */
struct
{
uint8_t command: 8; /**<command value for which response is obtained */
uint8_t commandClass: 8; /**< Class of the command */
uint16_t magic: 16; /**< Magic code obtained in the response */
};
} __attribute__((packed));
constexpr uint16_t MAGIC_CODE = 0xC0DE;
constexpr auto SBE_OPERATION_SUCCESSFUL = 0;
constexpr auto LENGTH_OF_DISTANCE_HEADER_IN_WORDS = 0x1;
constexpr auto LENGTH_OF_RESP_HEADER_IN_WORDS = 0x2;
constexpr auto SBEI_SBE_RESPONSE_SIZE_IN_WORDS = ((sizeof(sbeRespHeader_t) + \
sizeof(sbe_word_t)) / 4);
constexpr auto DISTANCE_TO_RESP_CODE = 0x1;
std::vector<sbe_word_t> write(const char* devPath,
const sbe_word_t* cmdBuffer,
size_t cmdBufLen,
size_t respBufLen)
{
//TODO: Add support for reading and writing from the FIFO device
std::vector<sbe_word_t> response(respBufLen);
return response;
}
std::vector<sbe_word_t> parseResponse(
const std::vector<sbe_word_t>& sbeDataBuf)
{
//Number of 32-bit words obtained from the SBE
size_t lengthObtained = sbeDataBuf.size();
//Fetch the SBE header and SBE chiop primary and secondary status
//Last value in the buffer will have the offset for the SBE header
size_t distanceToStatusHeader = sbeDataBuf[sbeDataBuf.size() - 1];
if (lengthObtained < distanceToStatusHeader)
{
//TODO:use elog infrastructure
std::ostringstream errMsg;
errMsg << "Distance to SBE status header value " <<
distanceToStatusHeader << " is greater then total lenght of "
"response buffer " << lengthObtained;
throw std::runtime_error(errMsg.str().c_str());
}
//Fetch the response header contents
sbeRespHeader_t l_respHeader{};
auto iter = sbeDataBuf.begin();
std::advance(iter, (lengthObtained - distanceToStatusHeader));
l_respHeader.commandWord = *iter;
//Fetch the primary and secondary response code
std::advance(iter, DISTANCE_TO_RESP_CODE);
auto l_priSecResp = *iter;
//Validate the magic code obtained in the response
if (l_respHeader.magic != MAGIC_CODE)
{
//TODO:use elog infrastructure
std::ostringstream errMsg;
errMsg << "Invalid MAGIC keyword in the response header (" <<
l_respHeader.magic << "),expected keyword " << MAGIC_CODE;
throw std::runtime_error(errMsg.str().c_str());
}
//Validate the Primary and Secondary response value
if (l_priSecResp != SBE_OPERATION_SUCCESSFUL)
{
//Extract the SBE FFDC and throw it to the caller
size_t ffdcLen = (distanceToStatusHeader -
SBEI_SBE_RESPONSE_SIZE_IN_WORDS -
LENGTH_OF_DISTANCE_HEADER_IN_WORDS);
if (ffdcLen)
{
std::vector<sbe_word_t> ffdcData(ffdcLen);
//Fetch the offset of FFDC data
auto ffdcOffset = (lengthObtained - distanceToStatusHeader) +
LENGTH_OF_RESP_HEADER_IN_WORDS;
std::copy_n((sbeDataBuf.begin() + ffdcOffset), ffdcLen,
ffdcData.begin());
}
//TODO:use elog infrastructure to return the SBE and Hardware procedure
//FFDC container back to the caller.
std::ostringstream errMsg;
errMsg << "Chip operation failed with SBE response code:" << l_priSecResp
<< ".Length of FFDC data of obtained:" << ffdcLen;
throw std::runtime_error(errMsg.str().c_str());
}
return sbeDataBuf;
}
}
}
}