13e5422edSVishwanatha Subbanna #include "config.h"
294df8c90SGunnar Mills 
394df8c90SGunnar Mills #include "occ_pass_through.hpp"
494df8c90SGunnar Mills 
594df8c90SGunnar Mills #include "elog-errors.hpp"
694df8c90SGunnar Mills 
794df8c90SGunnar Mills #include <errno.h>
894df8c90SGunnar Mills #include <fcntl.h>
9a8857c50SChris Cain #include <fmt/core.h>
1094df8c90SGunnar Mills #include <unistd.h>
1194df8c90SGunnar Mills 
1294df8c90SGunnar Mills #include <org/open_power/OCC/Device/error.hpp>
1394df8c90SGunnar Mills #include <phosphor-logging/elog.hpp>
1494df8c90SGunnar Mills #include <phosphor-logging/log.hpp>
15b5ca1015SGeorge Liu 
16b5ca1015SGeorge Liu #include <algorithm>
17b5ca1015SGeorge Liu #include <memory>
1894df8c90SGunnar Mills #include <string>
19a8857c50SChris Cain 
206b492fbfSDeepak Kodihalli namespace open_power
216b492fbfSDeepak Kodihalli {
226b492fbfSDeepak Kodihalli namespace occ
236b492fbfSDeepak Kodihalli {
246b492fbfSDeepak Kodihalli 
25*36f9cdedSChris Cain using namespace phosphor::logging;
26*36f9cdedSChris Cain using namespace sdbusplus::org::open_power::OCC::Device::Error;
27*36f9cdedSChris Cain 
28*36f9cdedSChris Cain PassThrough::PassThrough(
29*36f9cdedSChris Cain     const char* path
30*36f9cdedSChris Cain #ifdef POWER10
31*36f9cdedSChris Cain     ,
32*36f9cdedSChris Cain     std::unique_ptr<open_power::occ::powermode::PowerMode>& powerModeRef
33*36f9cdedSChris Cain #endif
34*36f9cdedSChris Cain     ) :
35*36f9cdedSChris Cain     Iface(utils::getBus(), path),
36*36f9cdedSChris Cain     path(path),
37*36f9cdedSChris Cain #ifdef POWER10
38*36f9cdedSChris Cain     pmode(powerModeRef),
39*36f9cdedSChris Cain #endif
403e5422edSVishwanatha Subbanna     devicePath(OCC_DEV_PATH + std::to_string((this->path.back() - '0') + 1)),
41a8857c50SChris Cain     occInstance(this->path.back() - '0'),
423e5422edSVishwanatha Subbanna     activeStatusSignal(
43f3b7514eSGeorge Liu         utils::getBus(),
44f3b7514eSGeorge Liu         sdbusRule::propertiesChanged(path, "org.open_power.OCC.Status"),
4594df8c90SGunnar Mills         std::bind(std::mem_fn(&PassThrough::activeStatusEvent), this,
46a8857c50SChris Cain                   std::placeholders::_1)),
47f3b7514eSGeorge Liu     occCmd(occInstance, path)
486b492fbfSDeepak Kodihalli {
4938b08d79SVishwanatha Subbanna     // Nothing to do.
5038b08d79SVishwanatha Subbanna }
5138b08d79SVishwanatha Subbanna 
526b492fbfSDeepak Kodihalli std::vector<int32_t> PassThrough::send(std::vector<int32_t> command)
536b492fbfSDeepak Kodihalli {
5467d50ad6SVishwanatha Subbanna     std::vector<int32_t> response{};
5567d50ad6SVishwanatha Subbanna 
567d700e26SVishwanatha Subbanna     // OCC only understands [bytes] so need array of bytes. Doing this
577d700e26SVishwanatha Subbanna     // because rest-server currently treats all int* as 32 bit integer.
58a8857c50SChris Cain     std::vector<uint8_t> cmdInBytes, rsp;
597d700e26SVishwanatha Subbanna     cmdInBytes.resize(command.size());
607d700e26SVishwanatha Subbanna 
617d700e26SVishwanatha Subbanna     // Populate uint8_t version of vector.
627d700e26SVishwanatha Subbanna     std::transform(command.begin(), command.end(), cmdInBytes.begin(),
637d700e26SVishwanatha Subbanna                    [](decltype(cmdInBytes)::value_type x) { return x; });
647d700e26SVishwanatha Subbanna 
65a8857c50SChris Cain     rsp = send(cmdInBytes);
66a8857c50SChris Cain 
67a8857c50SChris Cain     response.resize(rsp.size());
68a8857c50SChris Cain     std::transform(rsp.begin(), rsp.end(), response.begin(),
69a8857c50SChris Cain                    [](decltype(response)::value_type x) { return x; });
70a8857c50SChris Cain 
71a8857c50SChris Cain     return response;
726b492fbfSDeepak Kodihalli }
736b492fbfSDeepak Kodihalli 
74a8857c50SChris Cain std::vector<uint8_t> PassThrough::send(std::vector<uint8_t> command)
7567d50ad6SVishwanatha Subbanna {
76a8857c50SChris Cain     std::vector<uint8_t> response{};
77a8857c50SChris Cain 
78a8857c50SChris Cain     log<level::DEBUG>(
79a8857c50SChris Cain         fmt::format("PassThrough::send() Sending 0x{:02X} command to OCC{}",
80a8857c50SChris Cain                     command.front(), occInstance)
81a8857c50SChris Cain             .c_str());
82a8857c50SChris Cain     CmdStatus status = occCmd.send(command, response);
83a8857c50SChris Cain     if (status == CmdStatus::SUCCESS)
8467d50ad6SVishwanatha Subbanna     {
85a8857c50SChris Cain         if (response.size() >= 5)
8667d50ad6SVishwanatha Subbanna         {
87b5ca1015SGeorge Liu             log<level::DEBUG>(
88b5ca1015SGeorge Liu                 fmt::format("PassThrough::send() response had {} bytes",
89a8857c50SChris Cain                             response.size())
90a8857c50SChris Cain                     .c_str());
9167d50ad6SVishwanatha Subbanna         }
9267d50ad6SVishwanatha Subbanna         else
9367d50ad6SVishwanatha Subbanna         {
94a8857c50SChris Cain             log<level::ERR>("PassThrough::send() Invalid OCC response");
95a8857c50SChris Cain             dump_hex(response);
9667d50ad6SVishwanatha Subbanna         }
9767d50ad6SVishwanatha Subbanna     }
98a8857c50SChris Cain     else
99a8857c50SChris Cain     {
100a8857c50SChris Cain         if (status == CmdStatus::OPEN_FAILURE)
101a8857c50SChris Cain         {
102a8857c50SChris Cain             log<level::WARNING>("PassThrough::send() - OCC not active yet");
103a8857c50SChris Cain         }
104a8857c50SChris Cain         else
105a8857c50SChris Cain         {
106a8857c50SChris Cain             log<level::ERR>("PassThrough::send() - OCC command failed!");
107a8857c50SChris Cain         }
108a8857c50SChris Cain     }
1094f4712d8SEddie James 
11067d50ad6SVishwanatha Subbanna     return response;
11167d50ad6SVishwanatha Subbanna }
11267d50ad6SVishwanatha Subbanna 
113*36f9cdedSChris Cain bool PassThrough::setMode(const uint8_t mode, const uint16_t modeData)
114*36f9cdedSChris Cain {
115*36f9cdedSChris Cain #ifdef POWER10
116*36f9cdedSChris Cain     SysPwrMode newMode = SysPwrMode(mode);
117*36f9cdedSChris Cain 
118*36f9cdedSChris Cain     if ((!VALID_POWER_MODE_SETTING(newMode)) &&
119*36f9cdedSChris Cain         (!VALID_OEM_POWER_MODE_SETTING(newMode)))
120*36f9cdedSChris Cain     {
121*36f9cdedSChris Cain         log<level::ERR>(
122*36f9cdedSChris Cain             fmt::format(
123*36f9cdedSChris Cain                 "PassThrough::setMode() Unsupported mode {} requested (0x{:04X})",
124*36f9cdedSChris Cain                 newMode, modeData)
125*36f9cdedSChris Cain                 .c_str());
126*36f9cdedSChris Cain         return false;
127*36f9cdedSChris Cain     }
128*36f9cdedSChris Cain 
129*36f9cdedSChris Cain     if (((newMode == SysPwrMode::FFO) || (newMode == SysPwrMode::SFP)) &&
130*36f9cdedSChris Cain         (modeData == 0))
131*36f9cdedSChris Cain     {
132*36f9cdedSChris Cain         log<level::ERR>(
133*36f9cdedSChris Cain             fmt::format(
134*36f9cdedSChris Cain                 "PassThrough::setMode() Mode {} requires non-zero frequency point.",
135*36f9cdedSChris Cain                 newMode)
136*36f9cdedSChris Cain                 .c_str());
137*36f9cdedSChris Cain         return false;
138*36f9cdedSChris Cain     }
139*36f9cdedSChris Cain 
140*36f9cdedSChris Cain     log<level::INFO>(
141*36f9cdedSChris Cain         fmt::format("PassThrough::setMode() Setting Power Mode {} (data: {})",
142*36f9cdedSChris Cain                     newMode, modeData)
143*36f9cdedSChris Cain             .c_str());
144*36f9cdedSChris Cain     return pmode->setMode(newMode, modeData);
145*36f9cdedSChris Cain #else
146*36f9cdedSChris Cain     log<level::DEBUG>(
147*36f9cdedSChris Cain         fmt::format(
148*36f9cdedSChris Cain             "PassThrough::setMode() No support to setting Power Mode {} (data: {})",
149*36f9cdedSChris Cain             mode, modeData)
150*36f9cdedSChris Cain             .c_str());
151*36f9cdedSChris Cain     return false;
152*36f9cdedSChris Cain #endif
153*36f9cdedSChris Cain }
154*36f9cdedSChris Cain 
1553e5422edSVishwanatha Subbanna // Called at OCC Status change signal
1563e5422edSVishwanatha Subbanna void PassThrough::activeStatusEvent(sdbusplus::message::message& msg)
1573e5422edSVishwanatha Subbanna {
1583e5422edSVishwanatha Subbanna     std::string statusInterface;
159e0962703SPatrick Williams     std::map<std::string, std::variant<bool>> msgData;
1603e5422edSVishwanatha Subbanna     msg.read(statusInterface, msgData);
1613e5422edSVishwanatha Subbanna 
1623e5422edSVishwanatha Subbanna     auto propertyMap = msgData.find("OccActive");
1633e5422edSVishwanatha Subbanna     if (propertyMap != msgData.end())
1643e5422edSVishwanatha Subbanna     {
1653e5422edSVishwanatha Subbanna         // Extract the OccActive property
166305ff8b1SPatrick Williams         if (std::get<bool>(propertyMap->second))
1673e5422edSVishwanatha Subbanna         {
1684f4712d8SEddie James             occActive = true;
1693e5422edSVishwanatha Subbanna         }
1703e5422edSVishwanatha Subbanna         else
1713e5422edSVishwanatha Subbanna         {
1724f4712d8SEddie James             occActive = false;
1733e5422edSVishwanatha Subbanna         }
1743e5422edSVishwanatha Subbanna     }
1753e5422edSVishwanatha Subbanna     return;
1763e5422edSVishwanatha Subbanna }
1773e5422edSVishwanatha Subbanna 
1786b492fbfSDeepak Kodihalli } // namespace occ
1796b492fbfSDeepak Kodihalli } // namespace open_power
180