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>
79bb065b8SVishwanatha Subbanna #include <org/open_power/OCC/PassThrough/error.hpp>
86b492fbfSDeepak Kodihalli #include "occ_pass_through.hpp"
96b492fbfSDeepak Kodihalli #include "occ_finder.hpp"
109bb065b8SVishwanatha Subbanna #include "elog-errors.hpp"
116b492fbfSDeepak Kodihalli namespace open_power
126b492fbfSDeepak Kodihalli {
136b492fbfSDeepak Kodihalli namespace occ
146b492fbfSDeepak Kodihalli {
156b492fbfSDeepak Kodihalli namespace pass_through
166b492fbfSDeepak Kodihalli {
176b492fbfSDeepak Kodihalli 
186b492fbfSDeepak Kodihalli void run()
196b492fbfSDeepak Kodihalli {
206b492fbfSDeepak Kodihalli     auto bus = sdbusplus::bus::new_default();
216b492fbfSDeepak Kodihalli     sdbusplus::server::manager::manager objManager(bus,
226b492fbfSDeepak Kodihalli                                                    OCC_PASS_THROUGH_ROOT);
236b492fbfSDeepak Kodihalli 
246b492fbfSDeepak Kodihalli     std::vector<std::unique_ptr<PassThrough>> objects;
256b492fbfSDeepak Kodihalli     auto occs = open_power::occ::finder::get();
266b492fbfSDeepak Kodihalli 
276b492fbfSDeepak Kodihalli     for (const auto& occ : occs)
286b492fbfSDeepak Kodihalli     {
296b492fbfSDeepak Kodihalli         auto occPassThrough = object(occ);
306b492fbfSDeepak Kodihalli         objects.emplace_back(
316b492fbfSDeepak Kodihalli             std::make_unique<PassThrough>(bus, occPassThrough.c_str()));
326b492fbfSDeepak Kodihalli     }
336b492fbfSDeepak Kodihalli     bus.request_name(OCC_PASS_THROUGH_BUSNAME);
346b492fbfSDeepak Kodihalli 
356b492fbfSDeepak Kodihalli     while (true)
366b492fbfSDeepak Kodihalli     {
376b492fbfSDeepak Kodihalli         bus.process_discard();
386b492fbfSDeepak Kodihalli         bus.wait();
396b492fbfSDeepak Kodihalli     }
406b492fbfSDeepak Kodihalli }
416b492fbfSDeepak Kodihalli 
426b492fbfSDeepak Kodihalli PassThrough::PassThrough(
436b492fbfSDeepak Kodihalli     sdbusplus::bus::bus& bus,
446b492fbfSDeepak Kodihalli     const char* path) :
456b492fbfSDeepak Kodihalli     Iface(bus, path),
4638b08d79SVishwanatha Subbanna     path(path),
4738b08d79SVishwanatha Subbanna     fd(openDevice())
486b492fbfSDeepak Kodihalli {
4938b08d79SVishwanatha Subbanna     // Nothing to do.
5038b08d79SVishwanatha Subbanna }
5138b08d79SVishwanatha Subbanna 
5238b08d79SVishwanatha Subbanna int PassThrough::openDevice()
5338b08d79SVishwanatha Subbanna {
549bb065b8SVishwanatha Subbanna     using namespace phosphor::logging;
559bb065b8SVishwanatha Subbanna     using namespace sdbusplus::org::open_power::OCC::PassThrough::Error;
569bb065b8SVishwanatha Subbanna 
5738b08d79SVishwanatha Subbanna     // Device instance number starts from 1.
58afd21a65SVishwanatha Subbanna     devicePath.append(std::to_string((this->path.back() - '0') + 1));
5938b08d79SVishwanatha Subbanna 
6038b08d79SVishwanatha Subbanna     int fd = open(devicePath.c_str(), O_RDWR | O_NONBLOCK);
6138b08d79SVishwanatha Subbanna     if (fd < 0)
6238b08d79SVishwanatha Subbanna     {
639bb065b8SVishwanatha Subbanna         // This would log and terminate since its not handled.
649bb065b8SVishwanatha Subbanna         elog<OpenFailure>(
659bb065b8SVishwanatha Subbanna             phosphor::logging::org::open_power::OCC::PassThrough::
669bb065b8SVishwanatha Subbanna                 OpenFailure::CALLOUT_ERRNO(errno),
679bb065b8SVishwanatha Subbanna             phosphor::logging::org::open_power::OCC::PassThrough::
689bb065b8SVishwanatha Subbanna                 OpenFailure::CALLOUT_DEVICE_PATH(devicePath.c_str()));
6938b08d79SVishwanatha Subbanna     }
7038b08d79SVishwanatha Subbanna     return fd;
716b492fbfSDeepak Kodihalli }
726b492fbfSDeepak Kodihalli 
736b492fbfSDeepak Kodihalli std::vector<int32_t> PassThrough::send(std::vector<int32_t> command)
746b492fbfSDeepak Kodihalli {
7567d50ad6SVishwanatha Subbanna     using namespace phosphor::logging;
769bb065b8SVishwanatha Subbanna     using namespace sdbusplus::org::open_power::OCC::PassThrough::Error;
7767d50ad6SVishwanatha Subbanna 
7867d50ad6SVishwanatha Subbanna     std::vector<int32_t> response {};
7967d50ad6SVishwanatha Subbanna 
80*7d700e26SVishwanatha Subbanna     // OCC only understands [bytes] so need array of bytes. Doing this
81*7d700e26SVishwanatha Subbanna     // because rest-server currently treats all int* as 32 bit integer.
82*7d700e26SVishwanatha Subbanna     std::vector<uint8_t> cmdInBytes;
83*7d700e26SVishwanatha Subbanna     cmdInBytes.resize(command.size());
84*7d700e26SVishwanatha Subbanna 
85*7d700e26SVishwanatha Subbanna     // Populate uint8_t version of vector.
86*7d700e26SVishwanatha Subbanna     std::transform(command.begin(), command.end(), cmdInBytes.begin(),
87*7d700e26SVishwanatha Subbanna             [](decltype(cmdInBytes)::value_type x){return x;});
88*7d700e26SVishwanatha Subbanna 
89*7d700e26SVishwanatha Subbanna     ssize_t size = cmdInBytes.size() * sizeof(decltype(cmdInBytes)::value_type);
90*7d700e26SVishwanatha Subbanna     auto rc = write((fd)(), cmdInBytes.data(), size);
9167d50ad6SVishwanatha Subbanna     if (rc < 0 || (rc != size))
9267d50ad6SVishwanatha Subbanna     {
939bb065b8SVishwanatha Subbanna         // This would log and terminate since its not handled.
949bb065b8SVishwanatha Subbanna         elog<WriteFailure>(
959bb065b8SVishwanatha Subbanna             phosphor::logging::org::open_power::OCC::PassThrough::
969bb065b8SVishwanatha Subbanna                 WriteFailure::CALLOUT_ERRNO(errno),
979bb065b8SVishwanatha Subbanna             phosphor::logging::org::open_power::OCC::PassThrough::
989bb065b8SVishwanatha Subbanna                 WriteFailure::CALLOUT_DEVICE_PATH(devicePath.c_str()));
996b492fbfSDeepak Kodihalli     }
1006b492fbfSDeepak Kodihalli 
10167d50ad6SVishwanatha Subbanna     // Now read the response. This would be the content of occ-sram
10267d50ad6SVishwanatha Subbanna     while(1)
10367d50ad6SVishwanatha Subbanna     {
104*7d700e26SVishwanatha Subbanna         uint8_t data {};
10567d50ad6SVishwanatha Subbanna         auto len = read((fd)(), &data, sizeof(data));
10667d50ad6SVishwanatha Subbanna         if (len > 0)
10767d50ad6SVishwanatha Subbanna         {
10867d50ad6SVishwanatha Subbanna             response.emplace_back(data);
10967d50ad6SVishwanatha Subbanna         }
11067d50ad6SVishwanatha Subbanna         else if (len < 0 && errno == EAGAIN)
11167d50ad6SVishwanatha Subbanna         {
1129bb065b8SVishwanatha Subbanna             // We may have data coming still.
1139bb065b8SVishwanatha Subbanna             // This driver does not need a sleep for a retry.
11467d50ad6SVishwanatha Subbanna             continue;
11567d50ad6SVishwanatha Subbanna         }
11667d50ad6SVishwanatha Subbanna         else if (len == 0)
11767d50ad6SVishwanatha Subbanna         {
11867d50ad6SVishwanatha Subbanna             // We have read all that we can.
11967d50ad6SVishwanatha Subbanna             break;
12067d50ad6SVishwanatha Subbanna         }
12167d50ad6SVishwanatha Subbanna         else
12267d50ad6SVishwanatha Subbanna         {
1239bb065b8SVishwanatha Subbanna             // This would log and terminate since its not handled.
1249bb065b8SVishwanatha Subbanna             elog<ReadFailure>(
1259bb065b8SVishwanatha Subbanna                 phosphor::logging::org::open_power::OCC::PassThrough::
1269bb065b8SVishwanatha Subbanna                     ReadFailure::CALLOUT_ERRNO(errno),
1279bb065b8SVishwanatha Subbanna                 phosphor::logging::org::open_power::OCC::PassThrough::
1289bb065b8SVishwanatha Subbanna                     ReadFailure::CALLOUT_DEVICE_PATH(devicePath.c_str()));
12967d50ad6SVishwanatha Subbanna         }
13067d50ad6SVishwanatha Subbanna     }
13167d50ad6SVishwanatha Subbanna 
13267d50ad6SVishwanatha Subbanna     return response;
13367d50ad6SVishwanatha Subbanna }
13467d50ad6SVishwanatha Subbanna 
1356b492fbfSDeepak Kodihalli } // namespace pass_through
1366b492fbfSDeepak Kodihalli } // namespace occ
1376b492fbfSDeepak Kodihalli } // namespace open_power
138