blob: 81a24b082f35eeffbc3b25e23ee932fe5ce00384 [file] [log] [blame]
Murulidhar Nataraju1adec022017-04-20 12:05:51 -05001#include <array>
Murulidhar Nataraju06a0c2c2017-07-11 08:55:33 -05002#include <errno.h>
3#include <fcntl.h>
4#include <unistd.h>
5#include <poll.h>
6#include <endian.h>
Murulidhar Nataraju1adec022017-04-20 12:05:51 -05007#include <sbe_chipOp_handler.hpp>
Murulidhar Nataraju06a0c2c2017-07-11 08:55:33 -05008#include <file.hpp>
Murulidhar Nataraju1adec022017-04-20 12:05:51 -05009namespace openpower
10{
11namespace sbe
12{
13namespace internal
14{
Murulidhar Nataraju1adec022017-04-20 12:05:51 -050015
16constexpr uint16_t MAGIC_CODE = 0xC0DE;
17constexpr auto SBE_OPERATION_SUCCESSFUL = 0;
18constexpr auto LENGTH_OF_DISTANCE_HEADER_IN_WORDS = 0x1;
19constexpr auto LENGTH_OF_RESP_HEADER_IN_WORDS = 0x2;
Murulidhar Nataraju1adec022017-04-20 12:05:51 -050020constexpr auto DISTANCE_TO_RESP_CODE = 0x1;
Murulidhar Nataraju06a0c2c2017-07-11 08:55:33 -050021constexpr auto MAX_FFDC_LEN_IN_WORDS = 5120;
22constexpr auto WORD_SIZE = 4;
23constexpr auto MAGIC_CODE_BITS = 16;
24std::vector<sbe_word_t> writeToFifo(const char* devPath,
25 const sbe_word_t* cmdBuffer,
26 size_t cmdBufLen,
27 size_t respBufLen)
Murulidhar Nataraju1adec022017-04-20 12:05:51 -050028{
Benjamin Herrenschmidt0dc29322018-05-17 15:25:47 +100029 ssize_t len = 0;
Murulidhar Nataraju06a0c2c2017-07-11 08:55:33 -050030 std::vector<sbe_word_t> response;
31 std::ostringstream errMsg;
32
33 //Open the device and obtain the file descriptor associated with it.
34 FileDescriptor fileFd(devPath, (O_RDWR | O_NONBLOCK));
35
36 //Wait for FIFO device and perform write operation
37 struct pollfd poll_fd = {};
38 poll_fd.fd = fileFd();
39 poll_fd.events = POLLOUT | POLLERR;
40
41 int rc = 0;
42 if ((rc = poll(&poll_fd, 1, -1)) < 0)
43 {
44 //TODO:use elog infrastructure
45 errMsg << "Waiting for FIFO device:" << devPath << "to write failed"
46 << "rc=" << rc << "errno=" << errno;
47 throw std::runtime_error(errMsg.str().c_str());
48 }
49 if (poll_fd.revents & POLLERR)
50 {
51 //TODO:use elog infrastructure
52 errMsg << "POLLERR while waiting for writeable FIFO,errno:" << errno;
53 throw std::runtime_error(errMsg.str().c_str());
54 }
55 auto bytesToWrite = (cmdBufLen * WORD_SIZE);
56 //Perform the write operation
57 len = write(fileFd(), cmdBuffer, bytesToWrite);
58 if (len < 0)
59 {
60 //TODO:use elog infrastructure
61 errMsg << "Failed to write to FIFO device:" << devPath << " Length "
62 "returned= " << len << " errno=" << errno;
63 throw std::runtime_error(errMsg.str().c_str());
64 }
65 //Wait for FIFO device and perform read operation
66 poll_fd.fd = fileFd();
67 poll_fd.events = POLLIN | POLLERR;
68 if ((rc = poll(&poll_fd, 1, -1) < 0))
69 {
70 //TODO:use elog infrastructure
71 errMsg << "Waiting for FIFO device:" << devPath << "to read failed"
72 << " rc=" << rc << " and errno=" << errno;
73 throw std::runtime_error(errMsg.str().c_str());
74 }
75 if (poll_fd.revents & POLLERR)
76 {
77 //TODO:use elog infrastructure
78 errMsg << "POLLERR while waiting for readable FIFO,errno:" << errno;
79 throw std::runtime_error(errMsg.str().c_str());
80 }
81 //Derive the total read length which should include the FFDC, which SBE
82 //returns in case of failure.
83 size_t totalReadLen = respBufLen + MAX_FFDC_LEN_IN_WORDS;
84 //Create a temporary buffer
85 std::vector<sbe_word_t> buffer(totalReadLen);
86
Benjamin Herrenschmidt0dc29322018-05-17 15:25:47 +100087 ssize_t bytesToRead = (totalReadLen * WORD_SIZE);
Murulidhar Nataraju06a0c2c2017-07-11 08:55:33 -050088 len = read(fileFd(), buffer.data(), bytesToRead);
89 if (len < 0)
90 {
91 //TODO:use elog infrastructure
92 errMsg << "Failed to read the FIFO device:" << devPath << "bytes read ="
93 << len << " errno=" << errno;
94 throw std::runtime_error(errMsg.str().c_str());
95 }
96 else if (len != bytesToRead)
97 {
98 //TODO:use elog infrastructure
99 errMsg << "Exepcted " << bytesToRead << " bytes to be read from FIFO"
100 " device:" << devPath << ", but bytes read are " << len <<
101 " errno= " << errno;
102 throw std::runtime_error(errMsg.str().c_str());
103 }
104
105 //Extract the valid number of words read.
106 for (auto i = 0; i < (rc / WORD_SIZE); ++i)
107 {
108 response.push_back(be32toh(buffer[i]));
109 }
110
111 //Closing of the file descriptor will be handled when the FileDescriptor
112 //object will go out of scope.
Murulidhar Nataraju1adec022017-04-20 12:05:51 -0500113 return response;
114}
115
Murulidhar Nataraju06a0c2c2017-07-11 08:55:33 -0500116void parseResponse(std::vector<sbe_word_t>& sbeDataBuf)
Murulidhar Nataraju1adec022017-04-20 12:05:51 -0500117{
Murulidhar Nataraju1adec022017-04-20 12:05:51 -0500118 //Number of 32-bit words obtained from the SBE
119 size_t lengthObtained = sbeDataBuf.size();
120
121 //Fetch the SBE header and SBE chiop primary and secondary status
122 //Last value in the buffer will have the offset for the SBE header
123 size_t distanceToStatusHeader = sbeDataBuf[sbeDataBuf.size() - 1];
124
125 if (lengthObtained < distanceToStatusHeader)
126 {
127 //TODO:use elog infrastructure
128 std::ostringstream errMsg;
129 errMsg << "Distance to SBE status header value " <<
Gunnar Mills12ef1d72018-04-08 15:01:59 -0500130 distanceToStatusHeader << " is greater then total length of "
Murulidhar Nataraju1adec022017-04-20 12:05:51 -0500131 "response buffer " << lengthObtained;
132 throw std::runtime_error(errMsg.str().c_str());
133 }
134
135 //Fetch the response header contents
Murulidhar Nataraju1adec022017-04-20 12:05:51 -0500136 auto iter = sbeDataBuf.begin();
137 std::advance(iter, (lengthObtained - distanceToStatusHeader));
Murulidhar Nataraju06a0c2c2017-07-11 08:55:33 -0500138
139 //First header word will have 2 bytes of MAGIC CODE followed by
140 //Command class and command type
141 //| MAGIC BYTES:0xCODE | COMMAND-CLASS | COMMAND-TYPE|
142 sbe_word_t l_magicCode = (*iter >> MAGIC_CODE_BITS);
Murulidhar Nataraju1adec022017-04-20 12:05:51 -0500143
144 //Fetch the primary and secondary response code
145 std::advance(iter, DISTANCE_TO_RESP_CODE);
146 auto l_priSecResp = *iter;
147
148 //Validate the magic code obtained in the response
Murulidhar Nataraju06a0c2c2017-07-11 08:55:33 -0500149 if (l_magicCode != MAGIC_CODE)
Murulidhar Nataraju1adec022017-04-20 12:05:51 -0500150 {
151 //TODO:use elog infrastructure
152 std::ostringstream errMsg;
153 errMsg << "Invalid MAGIC keyword in the response header (" <<
Murulidhar Nataraju06a0c2c2017-07-11 08:55:33 -0500154 l_magicCode << "),expected keyword " << MAGIC_CODE;
Murulidhar Nataraju1adec022017-04-20 12:05:51 -0500155 throw std::runtime_error(errMsg.str().c_str());
156 }
157
158 //Validate the Primary and Secondary response value
159 if (l_priSecResp != SBE_OPERATION_SUCCESSFUL)
160 {
161 //Extract the SBE FFDC and throw it to the caller
162 size_t ffdcLen = (distanceToStatusHeader -
Murulidhar Nataraju06a0c2c2017-07-11 08:55:33 -0500163 LENGTH_OF_RESP_HEADER_IN_WORDS -
Murulidhar Nataraju1adec022017-04-20 12:05:51 -0500164 LENGTH_OF_DISTANCE_HEADER_IN_WORDS);
165 if (ffdcLen)
166 {
167 std::vector<sbe_word_t> ffdcData(ffdcLen);
168 //Fetch the offset of FFDC data
169 auto ffdcOffset = (lengthObtained - distanceToStatusHeader) +
170 LENGTH_OF_RESP_HEADER_IN_WORDS;
171 std::copy_n((sbeDataBuf.begin() + ffdcOffset), ffdcLen,
172 ffdcData.begin());
173 }
174
175 //TODO:use elog infrastructure to return the SBE and Hardware procedure
176 //FFDC container back to the caller.
177 std::ostringstream errMsg;
178 errMsg << "Chip operation failed with SBE response code:" << l_priSecResp
179 << ".Length of FFDC data of obtained:" << ffdcLen;
180 throw std::runtime_error(errMsg.str().c_str());
181 }
Murulidhar Nataraju1adec022017-04-20 12:05:51 -0500182
Murulidhar Nataraju06a0c2c2017-07-11 08:55:33 -0500183 //In case of success, remove the response header content and send only the
184 //data.Response header will be towards the end of the buffer.
185 auto respLen = (lengthObtained - distanceToStatusHeader);
186 iter = sbeDataBuf.begin();
187 std::advance(iter,respLen);
188 sbeDataBuf.erase(iter, sbeDataBuf.end());
Murulidhar Nataraju1adec022017-04-20 12:05:51 -0500189}
190
191}
192}
193}