13e5422edSVishwanatha Subbanna #include "config.h"
294df8c90SGunnar Mills
394df8c90SGunnar Mills #include "occ_pass_through.hpp"
494df8c90SGunnar Mills
594df8c90SGunnar Mills #include <errno.h>
694df8c90SGunnar Mills #include <fcntl.h>
794df8c90SGunnar Mills #include <unistd.h>
894df8c90SGunnar Mills
994df8c90SGunnar Mills #include <org/open_power/OCC/Device/error.hpp>
10d8aab2a9SPatrick Williams #include <phosphor-logging/elog-errors.hpp>
1194df8c90SGunnar Mills #include <phosphor-logging/elog.hpp>
1294df8c90SGunnar Mills #include <phosphor-logging/log.hpp>
13b5ca1015SGeorge Liu
14b5ca1015SGeorge Liu #include <algorithm>
15*48002498SPatrick Williams #include <format>
16b5ca1015SGeorge Liu #include <memory>
1794df8c90SGunnar Mills #include <string>
18a8857c50SChris Cain
196b492fbfSDeepak Kodihalli namespace open_power
206b492fbfSDeepak Kodihalli {
216b492fbfSDeepak Kodihalli namespace occ
226b492fbfSDeepak Kodihalli {
236b492fbfSDeepak Kodihalli
2436f9cdedSChris Cain using namespace phosphor::logging;
2536f9cdedSChris Cain using namespace sdbusplus::org::open_power::OCC::Device::Error;
2636f9cdedSChris Cain
PassThrough(const char * path,std::unique_ptr<open_power::occ::powermode::PowerMode> & powerModeRef)2736f9cdedSChris Cain PassThrough::PassThrough(
2836f9cdedSChris Cain const char* path
2936f9cdedSChris Cain #ifdef POWER10
3036f9cdedSChris Cain ,
3136f9cdedSChris Cain std::unique_ptr<open_power::occ::powermode::PowerMode>& powerModeRef
3236f9cdedSChris Cain #endif
3336f9cdedSChris Cain ) :
3436f9cdedSChris Cain Iface(utils::getBus(), path),
3536f9cdedSChris Cain path(path),
3636f9cdedSChris Cain #ifdef POWER10
3736f9cdedSChris Cain pmode(powerModeRef),
3836f9cdedSChris Cain #endif
393e5422edSVishwanatha Subbanna devicePath(OCC_DEV_PATH + std::to_string((this->path.back() - '0') + 1)),
40a8857c50SChris Cain occInstance(this->path.back() - '0'),
413e5422edSVishwanatha Subbanna activeStatusSignal(
42f3b7514eSGeorge Liu utils::getBus(),
43f3b7514eSGeorge Liu sdbusRule::propertiesChanged(path, "org.open_power.OCC.Status"),
4494df8c90SGunnar Mills std::bind(std::mem_fn(&PassThrough::activeStatusEvent), this,
45a8857c50SChris Cain std::placeholders::_1)),
46f3b7514eSGeorge Liu occCmd(occInstance, path)
476b492fbfSDeepak Kodihalli {
4838b08d79SVishwanatha Subbanna // Nothing to do.
4938b08d79SVishwanatha Subbanna }
5038b08d79SVishwanatha Subbanna
send(std::vector<int32_t> command)516b492fbfSDeepak Kodihalli std::vector<int32_t> PassThrough::send(std::vector<int32_t> command)
526b492fbfSDeepak Kodihalli {
5367d50ad6SVishwanatha Subbanna std::vector<int32_t> response{};
5467d50ad6SVishwanatha Subbanna
557d700e26SVishwanatha Subbanna // OCC only understands [bytes] so need array of bytes. Doing this
567d700e26SVishwanatha Subbanna // because rest-server currently treats all int* as 32 bit integer.
57a8857c50SChris Cain std::vector<uint8_t> cmdInBytes, rsp;
587d700e26SVishwanatha Subbanna cmdInBytes.resize(command.size());
597d700e26SVishwanatha Subbanna
607d700e26SVishwanatha Subbanna // Populate uint8_t version of vector.
617d700e26SVishwanatha Subbanna std::transform(command.begin(), command.end(), cmdInBytes.begin(),
627d700e26SVishwanatha Subbanna [](decltype(cmdInBytes)::value_type x) { return x; });
637d700e26SVishwanatha Subbanna
64a8857c50SChris Cain rsp = send(cmdInBytes);
65a8857c50SChris Cain
66a8857c50SChris Cain response.resize(rsp.size());
67a8857c50SChris Cain std::transform(rsp.begin(), rsp.end(), response.begin(),
68a8857c50SChris Cain [](decltype(response)::value_type x) { return x; });
69a8857c50SChris Cain
70a8857c50SChris Cain return response;
716b492fbfSDeepak Kodihalli }
726b492fbfSDeepak Kodihalli
send(std::vector<uint8_t> command)73a8857c50SChris Cain std::vector<uint8_t> PassThrough::send(std::vector<uint8_t> command)
7467d50ad6SVishwanatha Subbanna {
75a8857c50SChris Cain std::vector<uint8_t> response{};
76a8857c50SChris Cain
77d4c19a07SChris Cain if (!occActive)
78d4c19a07SChris Cain {
79d4c19a07SChris Cain log<level::ERR>(
80*48002498SPatrick Williams std::format(
81d4c19a07SChris Cain "PassThrough::send() - OCC{} not active, command not sent",
82d4c19a07SChris Cain occInstance)
83d4c19a07SChris Cain .c_str());
84d4c19a07SChris Cain return response;
85d4c19a07SChris Cain }
86d4c19a07SChris Cain
8740501a23SChris Cain log<level::INFO>(
88*48002498SPatrick Williams std::format("PassThrough::send() Sending 0x{:02X} command to OCC{}",
89a8857c50SChris Cain command.front(), occInstance)
90a8857c50SChris Cain .c_str());
91a8857c50SChris Cain CmdStatus status = occCmd.send(command, response);
92a8857c50SChris Cain if (status == CmdStatus::SUCCESS)
9367d50ad6SVishwanatha Subbanna {
94a8857c50SChris Cain if (response.size() >= 5)
9567d50ad6SVishwanatha Subbanna {
96b5ca1015SGeorge Liu log<level::DEBUG>(
97*48002498SPatrick Williams std::format("PassThrough::send() response had {} bytes",
98a8857c50SChris Cain response.size())
99a8857c50SChris Cain .c_str());
10067d50ad6SVishwanatha Subbanna }
10167d50ad6SVishwanatha Subbanna else
10267d50ad6SVishwanatha Subbanna {
103a8857c50SChris Cain log<level::ERR>("PassThrough::send() Invalid OCC response");
104a8857c50SChris Cain dump_hex(response);
10567d50ad6SVishwanatha Subbanna }
10667d50ad6SVishwanatha Subbanna }
107a8857c50SChris Cain else
108a8857c50SChris Cain {
109c567dc8dSChris Cain log<level::ERR>(
110*48002498SPatrick Williams std::format(
111c567dc8dSChris Cain "PassThrough::send(): OCC command failed with status {}",
112c567dc8dSChris Cain uint32_t(status))
113c567dc8dSChris Cain .c_str());
114a8857c50SChris Cain }
1154f4712d8SEddie James
11667d50ad6SVishwanatha Subbanna return response;
11767d50ad6SVishwanatha Subbanna }
11867d50ad6SVishwanatha Subbanna
setMode(const uint8_t mode,const uint16_t modeData)11936f9cdedSChris Cain bool PassThrough::setMode(const uint8_t mode, const uint16_t modeData)
12036f9cdedSChris Cain {
12136f9cdedSChris Cain #ifdef POWER10
12236f9cdedSChris Cain SysPwrMode newMode = SysPwrMode(mode);
12336f9cdedSChris Cain
12436f9cdedSChris Cain if ((!VALID_POWER_MODE_SETTING(newMode)) &&
12536f9cdedSChris Cain (!VALID_OEM_POWER_MODE_SETTING(newMode)))
12636f9cdedSChris Cain {
12736f9cdedSChris Cain log<level::ERR>(
128*48002498SPatrick Williams std::format(
12936f9cdedSChris Cain "PassThrough::setMode() Unsupported mode {} requested (0x{:04X})",
13036f9cdedSChris Cain newMode, modeData)
13136f9cdedSChris Cain .c_str());
13236f9cdedSChris Cain return false;
13336f9cdedSChris Cain }
13436f9cdedSChris Cain
13536f9cdedSChris Cain if (((newMode == SysPwrMode::FFO) || (newMode == SysPwrMode::SFP)) &&
13636f9cdedSChris Cain (modeData == 0))
13736f9cdedSChris Cain {
13836f9cdedSChris Cain log<level::ERR>(
139*48002498SPatrick Williams std::format(
14036f9cdedSChris Cain "PassThrough::setMode() Mode {} requires non-zero frequency point.",
14136f9cdedSChris Cain newMode)
14236f9cdedSChris Cain .c_str());
14336f9cdedSChris Cain return false;
14436f9cdedSChris Cain }
14536f9cdedSChris Cain
1466fa848a9SChris Cain if (!pmode)
1476fa848a9SChris Cain {
1486fa848a9SChris Cain log<level::ERR>("PassThrough::setMode: PowerMode is not defined!");
1496fa848a9SChris Cain return false;
1506fa848a9SChris Cain }
1516fa848a9SChris Cain
15236f9cdedSChris Cain log<level::INFO>(
153*48002498SPatrick Williams std::format("PassThrough::setMode() Setting Power Mode {} (data: {})",
15436f9cdedSChris Cain newMode, modeData)
15536f9cdedSChris Cain .c_str());
15636f9cdedSChris Cain return pmode->setMode(newMode, modeData);
15736f9cdedSChris Cain #else
15836f9cdedSChris Cain log<level::DEBUG>(
159*48002498SPatrick Williams std::format(
16036f9cdedSChris Cain "PassThrough::setMode() No support to setting Power Mode {} (data: {})",
16136f9cdedSChris Cain mode, modeData)
16236f9cdedSChris Cain .c_str());
16336f9cdedSChris Cain return false;
16436f9cdedSChris Cain #endif
16536f9cdedSChris Cain }
16636f9cdedSChris Cain
1673e5422edSVishwanatha Subbanna // Called at OCC Status change signal
activeStatusEvent(sdbusplus::message_t & msg)168af40808fSPatrick Williams void PassThrough::activeStatusEvent(sdbusplus::message_t& msg)
1693e5422edSVishwanatha Subbanna {
1703e5422edSVishwanatha Subbanna std::string statusInterface;
171e0962703SPatrick Williams std::map<std::string, std::variant<bool>> msgData;
1723e5422edSVishwanatha Subbanna msg.read(statusInterface, msgData);
1733e5422edSVishwanatha Subbanna
1743e5422edSVishwanatha Subbanna auto propertyMap = msgData.find("OccActive");
1753e5422edSVishwanatha Subbanna if (propertyMap != msgData.end())
1763e5422edSVishwanatha Subbanna {
1773e5422edSVishwanatha Subbanna // Extract the OccActive property
178305ff8b1SPatrick Williams if (std::get<bool>(propertyMap->second))
1793e5422edSVishwanatha Subbanna {
1804f4712d8SEddie James occActive = true;
1813e5422edSVishwanatha Subbanna }
1823e5422edSVishwanatha Subbanna else
1833e5422edSVishwanatha Subbanna {
1844f4712d8SEddie James occActive = false;
1853e5422edSVishwanatha Subbanna }
1863e5422edSVishwanatha Subbanna }
1873e5422edSVishwanatha Subbanna return;
1883e5422edSVishwanatha Subbanna }
1893e5422edSVishwanatha Subbanna
1906b492fbfSDeepak Kodihalli } // namespace occ
1916b492fbfSDeepak Kodihalli } // namespace open_power
192