1 #include <stdexcept> 2 #include <array> 3 #include <sbe_chipOp_handler.hpp> 4 namespace openpower 5 { 6 namespace sbe 7 { 8 namespace internal 9 { 10 /*! \union sbeRespHeader_t 11 * Defines the breakup of the SBE FIFO chip operation response header. 12 */ 13 union sbeRespHeader_t 14 { 15 uint32_t commandWord; /**<Entire 32 bit command word */ 16 struct 17 { 18 uint8_t command: 8; /**<command value for which response is obtained */ 19 uint8_t commandClass: 8; /**< Class of the command */ 20 uint16_t magic: 16; /**< Magic code obtained in the response */ 21 }; 22 } __attribute__((packed)); 23 24 25 constexpr uint16_t MAGIC_CODE = 0xC0DE; 26 constexpr auto SBE_OPERATION_SUCCESSFUL = 0; 27 constexpr auto LENGTH_OF_DISTANCE_HEADER_IN_WORDS = 0x1; 28 constexpr auto LENGTH_OF_RESP_HEADER_IN_WORDS = 0x2; 29 constexpr auto SBEI_SBE_RESPONSE_SIZE_IN_WORDS = ((sizeof(sbeRespHeader_t) + \ 30 sizeof(sbe_word_t)) / 4); 31 constexpr auto DISTANCE_TO_RESP_CODE = 0x1; 32 33 std::vector<sbe_word_t> write(const char* devPath, 34 const sbe_word_t* cmdBuffer, 35 size_t cmdBufLen, 36 size_t respBufLen) 37 { 38 //TODO: Add support for reading and writing from the FIFO device 39 std::vector<sbe_word_t> response(respBufLen); 40 return response; 41 } 42 43 std::vector<sbe_word_t> parseResponse( 44 const std::vector<sbe_word_t>& sbeDataBuf) 45 { 46 47 //Number of 32-bit words obtained from the SBE 48 size_t lengthObtained = sbeDataBuf.size(); 49 50 //Fetch the SBE header and SBE chiop primary and secondary status 51 //Last value in the buffer will have the offset for the SBE header 52 size_t distanceToStatusHeader = sbeDataBuf[sbeDataBuf.size() - 1]; 53 54 if (lengthObtained < distanceToStatusHeader) 55 { 56 //TODO:use elog infrastructure 57 std::ostringstream errMsg; 58 errMsg << "Distance to SBE status header value " << 59 distanceToStatusHeader << " is greater then total lenght of " 60 "response buffer " << lengthObtained; 61 throw std::runtime_error(errMsg.str().c_str()); 62 } 63 64 //Fetch the response header contents 65 sbeRespHeader_t l_respHeader{}; 66 auto iter = sbeDataBuf.begin(); 67 std::advance(iter, (lengthObtained - distanceToStatusHeader)); 68 l_respHeader.commandWord = *iter; 69 70 //Fetch the primary and secondary response code 71 std::advance(iter, DISTANCE_TO_RESP_CODE); 72 auto l_priSecResp = *iter; 73 74 //Validate the magic code obtained in the response 75 if (l_respHeader.magic != MAGIC_CODE) 76 { 77 //TODO:use elog infrastructure 78 std::ostringstream errMsg; 79 errMsg << "Invalid MAGIC keyword in the response header (" << 80 l_respHeader.magic << "),expected keyword " << MAGIC_CODE; 81 throw std::runtime_error(errMsg.str().c_str()); 82 } 83 84 //Validate the Primary and Secondary response value 85 if (l_priSecResp != SBE_OPERATION_SUCCESSFUL) 86 { 87 //Extract the SBE FFDC and throw it to the caller 88 size_t ffdcLen = (distanceToStatusHeader - 89 SBEI_SBE_RESPONSE_SIZE_IN_WORDS - 90 LENGTH_OF_DISTANCE_HEADER_IN_WORDS); 91 if (ffdcLen) 92 { 93 std::vector<sbe_word_t> ffdcData(ffdcLen); 94 //Fetch the offset of FFDC data 95 auto ffdcOffset = (lengthObtained - distanceToStatusHeader) + 96 LENGTH_OF_RESP_HEADER_IN_WORDS; 97 std::copy_n((sbeDataBuf.begin() + ffdcOffset), ffdcLen, 98 ffdcData.begin()); 99 } 100 101 //TODO:use elog infrastructure to return the SBE and Hardware procedure 102 //FFDC container back to the caller. 103 std::ostringstream errMsg; 104 errMsg << "Chip operation failed with SBE response code:" << l_priSecResp 105 << ".Length of FFDC data of obtained:" << ffdcLen; 106 throw std::runtime_error(errMsg.str().c_str()); 107 } 108 return sbeDataBuf; 109 110 } 111 112 } 113 } 114 } 115 116 117