16b492fbfSDeepak Kodihalli #include <memory>
202ba9eccSDeepak Kodihalli #include <algorithm>
338b08d79SVishwanatha Subbanna #include <fcntl.h>
467d50ad6SVishwanatha Subbanna #include <errno.h>
502ba9eccSDeepak Kodihalli #include <phosphor-logging/log.hpp>
69bb065b8SVishwanatha Subbanna #include <phosphor-logging/elog.hpp>
7*ee4d83dfSVishwanatha Subbanna #include <org/open_power/OCC/Device/error.hpp>
86b492fbfSDeepak Kodihalli #include "occ_pass_through.hpp"
99bb065b8SVishwanatha Subbanna #include "elog-errors.hpp"
106b492fbfSDeepak Kodihalli namespace open_power
116b492fbfSDeepak Kodihalli {
126b492fbfSDeepak Kodihalli namespace occ
136b492fbfSDeepak Kodihalli {
146b492fbfSDeepak Kodihalli 
156b492fbfSDeepak Kodihalli PassThrough::PassThrough(
166b492fbfSDeepak Kodihalli     sdbusplus::bus::bus& bus,
176b492fbfSDeepak Kodihalli     const char* path) :
186b492fbfSDeepak Kodihalli     Iface(bus, path),
1938b08d79SVishwanatha Subbanna     path(path),
2038b08d79SVishwanatha Subbanna     fd(openDevice())
216b492fbfSDeepak Kodihalli {
2238b08d79SVishwanatha Subbanna     // Nothing to do.
2338b08d79SVishwanatha Subbanna }
2438b08d79SVishwanatha Subbanna 
2538b08d79SVishwanatha Subbanna int PassThrough::openDevice()
2638b08d79SVishwanatha Subbanna {
279bb065b8SVishwanatha Subbanna     using namespace phosphor::logging;
28*ee4d83dfSVishwanatha Subbanna     using namespace sdbusplus::org::open_power::OCC::Device::Error;
299bb065b8SVishwanatha Subbanna 
3038b08d79SVishwanatha Subbanna     // Device instance number starts from 1.
31afd21a65SVishwanatha Subbanna     devicePath.append(std::to_string((this->path.back() - '0') + 1));
3238b08d79SVishwanatha Subbanna 
3338b08d79SVishwanatha Subbanna     int fd = open(devicePath.c_str(), O_RDWR | O_NONBLOCK);
3438b08d79SVishwanatha Subbanna     if (fd < 0)
3538b08d79SVishwanatha Subbanna     {
369bb065b8SVishwanatha Subbanna         // This would log and terminate since its not handled.
379bb065b8SVishwanatha Subbanna         elog<OpenFailure>(
38*ee4d83dfSVishwanatha Subbanna             phosphor::logging::org::open_power::OCC::Device::
399bb065b8SVishwanatha Subbanna                 OpenFailure::CALLOUT_ERRNO(errno),
40*ee4d83dfSVishwanatha Subbanna             phosphor::logging::org::open_power::OCC::Device::
419bb065b8SVishwanatha Subbanna                 OpenFailure::CALLOUT_DEVICE_PATH(devicePath.c_str()));
4238b08d79SVishwanatha Subbanna     }
4338b08d79SVishwanatha Subbanna     return fd;
446b492fbfSDeepak Kodihalli }
456b492fbfSDeepak Kodihalli 
466b492fbfSDeepak Kodihalli std::vector<int32_t> PassThrough::send(std::vector<int32_t> command)
476b492fbfSDeepak Kodihalli {
4867d50ad6SVishwanatha Subbanna     using namespace phosphor::logging;
49*ee4d83dfSVishwanatha Subbanna     using namespace sdbusplus::org::open_power::OCC::Device::Error;
5067d50ad6SVishwanatha Subbanna 
5167d50ad6SVishwanatha Subbanna     std::vector<int32_t> response {};
5267d50ad6SVishwanatha Subbanna 
537d700e26SVishwanatha Subbanna     // OCC only understands [bytes] so need array of bytes. Doing this
547d700e26SVishwanatha Subbanna     // because rest-server currently treats all int* as 32 bit integer.
557d700e26SVishwanatha Subbanna     std::vector<uint8_t> cmdInBytes;
567d700e26SVishwanatha Subbanna     cmdInBytes.resize(command.size());
577d700e26SVishwanatha Subbanna 
587d700e26SVishwanatha Subbanna     // Populate uint8_t version of vector.
597d700e26SVishwanatha Subbanna     std::transform(command.begin(), command.end(), cmdInBytes.begin(),
607d700e26SVishwanatha Subbanna             [](decltype(cmdInBytes)::value_type x){return x;});
617d700e26SVishwanatha Subbanna 
627d700e26SVishwanatha Subbanna     ssize_t size = cmdInBytes.size() * sizeof(decltype(cmdInBytes)::value_type);
637d700e26SVishwanatha Subbanna     auto rc = write((fd)(), cmdInBytes.data(), size);
6467d50ad6SVishwanatha Subbanna     if (rc < 0 || (rc != size))
6567d50ad6SVishwanatha Subbanna     {
669bb065b8SVishwanatha Subbanna         // This would log and terminate since its not handled.
679bb065b8SVishwanatha Subbanna         elog<WriteFailure>(
68*ee4d83dfSVishwanatha Subbanna             phosphor::logging::org::open_power::OCC::Device::
699bb065b8SVishwanatha Subbanna                 WriteFailure::CALLOUT_ERRNO(errno),
70*ee4d83dfSVishwanatha Subbanna             phosphor::logging::org::open_power::OCC::Device::
719bb065b8SVishwanatha Subbanna                 WriteFailure::CALLOUT_DEVICE_PATH(devicePath.c_str()));
726b492fbfSDeepak Kodihalli     }
736b492fbfSDeepak Kodihalli 
7467d50ad6SVishwanatha Subbanna     // Now read the response. This would be the content of occ-sram
7567d50ad6SVishwanatha Subbanna     while(1)
7667d50ad6SVishwanatha Subbanna     {
777d700e26SVishwanatha Subbanna         uint8_t data {};
7867d50ad6SVishwanatha Subbanna         auto len = read((fd)(), &data, sizeof(data));
7967d50ad6SVishwanatha Subbanna         if (len > 0)
8067d50ad6SVishwanatha Subbanna         {
8167d50ad6SVishwanatha Subbanna             response.emplace_back(data);
8267d50ad6SVishwanatha Subbanna         }
8367d50ad6SVishwanatha Subbanna         else if (len < 0 && errno == EAGAIN)
8467d50ad6SVishwanatha Subbanna         {
859bb065b8SVishwanatha Subbanna             // We may have data coming still.
869bb065b8SVishwanatha Subbanna             // This driver does not need a sleep for a retry.
8767d50ad6SVishwanatha Subbanna             continue;
8867d50ad6SVishwanatha Subbanna         }
8967d50ad6SVishwanatha Subbanna         else if (len == 0)
9067d50ad6SVishwanatha Subbanna         {
9167d50ad6SVishwanatha Subbanna             // We have read all that we can.
9267d50ad6SVishwanatha Subbanna             break;
9367d50ad6SVishwanatha Subbanna         }
9467d50ad6SVishwanatha Subbanna         else
9567d50ad6SVishwanatha Subbanna         {
969bb065b8SVishwanatha Subbanna             // This would log and terminate since its not handled.
979bb065b8SVishwanatha Subbanna             elog<ReadFailure>(
98*ee4d83dfSVishwanatha Subbanna                 phosphor::logging::org::open_power::OCC::Device::
999bb065b8SVishwanatha Subbanna                     ReadFailure::CALLOUT_ERRNO(errno),
100*ee4d83dfSVishwanatha Subbanna                 phosphor::logging::org::open_power::OCC::Device::
1019bb065b8SVishwanatha Subbanna                     ReadFailure::CALLOUT_DEVICE_PATH(devicePath.c_str()));
10267d50ad6SVishwanatha Subbanna         }
10367d50ad6SVishwanatha Subbanna     }
10467d50ad6SVishwanatha Subbanna 
10567d50ad6SVishwanatha Subbanna     return response;
10667d50ad6SVishwanatha Subbanna }
10767d50ad6SVishwanatha Subbanna 
1086b492fbfSDeepak Kodihalli } // namespace occ
1096b492fbfSDeepak Kodihalli } // namespace open_power
110