16b492fbfSDeepak Kodihalli #include <memory>
202ba9eccSDeepak Kodihalli #include <algorithm>
338b08d79SVishwanatha Subbanna #include <fcntl.h>
467d50ad6SVishwanatha Subbanna #include <errno.h>
5*3e5422edSVishwanatha Subbanna #include <string>
6*3e5422edSVishwanatha Subbanna #include <unistd.h>
702ba9eccSDeepak Kodihalli #include <phosphor-logging/log.hpp>
89bb065b8SVishwanatha Subbanna #include <phosphor-logging/elog.hpp>
9ee4d83dfSVishwanatha Subbanna #include <org/open_power/OCC/Device/error.hpp>
106b492fbfSDeepak Kodihalli #include "occ_pass_through.hpp"
119bb065b8SVishwanatha Subbanna #include "elog-errors.hpp"
12*3e5422edSVishwanatha Subbanna #include "config.h"
136b492fbfSDeepak Kodihalli namespace open_power
146b492fbfSDeepak Kodihalli {
156b492fbfSDeepak Kodihalli namespace occ
166b492fbfSDeepak Kodihalli {
176b492fbfSDeepak Kodihalli 
186b492fbfSDeepak Kodihalli PassThrough::PassThrough(
196b492fbfSDeepak Kodihalli     sdbusplus::bus::bus& bus,
206b492fbfSDeepak Kodihalli     const char* path) :
216b492fbfSDeepak Kodihalli     Iface(bus, path),
2238b08d79SVishwanatha Subbanna     path(path),
23*3e5422edSVishwanatha Subbanna     devicePath(OCC_DEV_PATH + std::to_string((this->path.back() - '0') + 1)),
24*3e5422edSVishwanatha Subbanna     activeStatusSignal(
25*3e5422edSVishwanatha Subbanna             bus,
26*3e5422edSVishwanatha Subbanna             sdbusRule::propertiesChanged(path, "org.open_power.OCC.Status"),
27*3e5422edSVishwanatha Subbanna             std::bind(std::mem_fn(&PassThrough::activeStatusEvent),
28*3e5422edSVishwanatha Subbanna                 this, std::placeholders::_1))
296b492fbfSDeepak Kodihalli {
3038b08d79SVishwanatha Subbanna     // Nothing to do.
3138b08d79SVishwanatha Subbanna }
3238b08d79SVishwanatha Subbanna 
33*3e5422edSVishwanatha Subbanna void PassThrough::openDevice()
3438b08d79SVishwanatha Subbanna {
359bb065b8SVishwanatha Subbanna     using namespace phosphor::logging;
36ee4d83dfSVishwanatha Subbanna     using namespace sdbusplus::org::open_power::OCC::Device::Error;
379bb065b8SVishwanatha Subbanna 
38*3e5422edSVishwanatha Subbanna     fd = open(devicePath.c_str(), O_RDWR | O_NONBLOCK);
3938b08d79SVishwanatha Subbanna     if (fd < 0)
4038b08d79SVishwanatha Subbanna     {
419bb065b8SVishwanatha Subbanna         // This would log and terminate since its not handled.
429bb065b8SVishwanatha Subbanna         elog<OpenFailure>(
43ee4d83dfSVishwanatha Subbanna             phosphor::logging::org::open_power::OCC::Device::
449bb065b8SVishwanatha Subbanna                 OpenFailure::CALLOUT_ERRNO(errno),
45ee4d83dfSVishwanatha Subbanna             phosphor::logging::org::open_power::OCC::Device::
469bb065b8SVishwanatha Subbanna                 OpenFailure::CALLOUT_DEVICE_PATH(devicePath.c_str()));
4738b08d79SVishwanatha Subbanna     }
48*3e5422edSVishwanatha Subbanna     return;
49*3e5422edSVishwanatha Subbanna }
50*3e5422edSVishwanatha Subbanna 
51*3e5422edSVishwanatha Subbanna void PassThrough::closeDevice()
52*3e5422edSVishwanatha Subbanna {
53*3e5422edSVishwanatha Subbanna     if (fd >= 0)
54*3e5422edSVishwanatha Subbanna     {
55*3e5422edSVishwanatha Subbanna         close(fd);
56*3e5422edSVishwanatha Subbanna     }
576b492fbfSDeepak Kodihalli }
586b492fbfSDeepak Kodihalli 
596b492fbfSDeepak Kodihalli std::vector<int32_t> PassThrough::send(std::vector<int32_t> command)
606b492fbfSDeepak Kodihalli {
6167d50ad6SVishwanatha Subbanna     using namespace phosphor::logging;
62ee4d83dfSVishwanatha Subbanna     using namespace sdbusplus::org::open_power::OCC::Device::Error;
6367d50ad6SVishwanatha Subbanna 
6467d50ad6SVishwanatha Subbanna     std::vector<int32_t> response {};
6567d50ad6SVishwanatha Subbanna 
667d700e26SVishwanatha Subbanna     // OCC only understands [bytes] so need array of bytes. Doing this
677d700e26SVishwanatha Subbanna     // because rest-server currently treats all int* as 32 bit integer.
687d700e26SVishwanatha Subbanna     std::vector<uint8_t> cmdInBytes;
697d700e26SVishwanatha Subbanna     cmdInBytes.resize(command.size());
707d700e26SVishwanatha Subbanna 
717d700e26SVishwanatha Subbanna     // Populate uint8_t version of vector.
727d700e26SVishwanatha Subbanna     std::transform(command.begin(), command.end(), cmdInBytes.begin(),
737d700e26SVishwanatha Subbanna             [](decltype(cmdInBytes)::value_type x){return x;});
747d700e26SVishwanatha Subbanna 
757d700e26SVishwanatha Subbanna     ssize_t size = cmdInBytes.size() * sizeof(decltype(cmdInBytes)::value_type);
76*3e5422edSVishwanatha Subbanna     auto rc = write(fd, cmdInBytes.data(), size);
7767d50ad6SVishwanatha Subbanna     if (rc < 0 || (rc != size))
7867d50ad6SVishwanatha Subbanna     {
799bb065b8SVishwanatha Subbanna         // This would log and terminate since its not handled.
809bb065b8SVishwanatha Subbanna         elog<WriteFailure>(
81ee4d83dfSVishwanatha Subbanna             phosphor::logging::org::open_power::OCC::Device::
829bb065b8SVishwanatha Subbanna                 WriteFailure::CALLOUT_ERRNO(errno),
83ee4d83dfSVishwanatha Subbanna             phosphor::logging::org::open_power::OCC::Device::
849bb065b8SVishwanatha Subbanna                 WriteFailure::CALLOUT_DEVICE_PATH(devicePath.c_str()));
856b492fbfSDeepak Kodihalli     }
866b492fbfSDeepak Kodihalli 
8767d50ad6SVishwanatha Subbanna     // Now read the response. This would be the content of occ-sram
8867d50ad6SVishwanatha Subbanna     while(1)
8967d50ad6SVishwanatha Subbanna     {
907d700e26SVishwanatha Subbanna         uint8_t data {};
91*3e5422edSVishwanatha Subbanna         auto len = read(fd, &data, sizeof(data));
9267d50ad6SVishwanatha Subbanna         if (len > 0)
9367d50ad6SVishwanatha Subbanna         {
9467d50ad6SVishwanatha Subbanna             response.emplace_back(data);
9567d50ad6SVishwanatha Subbanna         }
9667d50ad6SVishwanatha Subbanna         else if (len < 0 && errno == EAGAIN)
9767d50ad6SVishwanatha Subbanna         {
989bb065b8SVishwanatha Subbanna             // We may have data coming still.
999bb065b8SVishwanatha Subbanna             // This driver does not need a sleep for a retry.
10067d50ad6SVishwanatha Subbanna             continue;
10167d50ad6SVishwanatha Subbanna         }
10267d50ad6SVishwanatha Subbanna         else if (len == 0)
10367d50ad6SVishwanatha Subbanna         {
10467d50ad6SVishwanatha Subbanna             // We have read all that we can.
10567d50ad6SVishwanatha Subbanna             break;
10667d50ad6SVishwanatha Subbanna         }
10767d50ad6SVishwanatha Subbanna         else
10867d50ad6SVishwanatha Subbanna         {
1099bb065b8SVishwanatha Subbanna             // This would log and terminate since its not handled.
1109bb065b8SVishwanatha Subbanna             elog<ReadFailure>(
111ee4d83dfSVishwanatha Subbanna                 phosphor::logging::org::open_power::OCC::Device::
1129bb065b8SVishwanatha Subbanna                     ReadFailure::CALLOUT_ERRNO(errno),
113ee4d83dfSVishwanatha Subbanna                 phosphor::logging::org::open_power::OCC::Device::
1149bb065b8SVishwanatha Subbanna                     ReadFailure::CALLOUT_DEVICE_PATH(devicePath.c_str()));
11567d50ad6SVishwanatha Subbanna         }
11667d50ad6SVishwanatha Subbanna     }
11767d50ad6SVishwanatha Subbanna 
11867d50ad6SVishwanatha Subbanna     return response;
11967d50ad6SVishwanatha Subbanna }
12067d50ad6SVishwanatha Subbanna 
121*3e5422edSVishwanatha Subbanna // Called at OCC Status change signal
122*3e5422edSVishwanatha Subbanna void PassThrough::activeStatusEvent(sdbusplus::message::message& msg)
123*3e5422edSVishwanatha Subbanna {
124*3e5422edSVishwanatha Subbanna     std::string statusInterface;
125*3e5422edSVishwanatha Subbanna     std::map<std::string, sdbusplus::message::variant<bool>> msgData;
126*3e5422edSVishwanatha Subbanna     msg.read(statusInterface, msgData);
127*3e5422edSVishwanatha Subbanna 
128*3e5422edSVishwanatha Subbanna     auto propertyMap = msgData.find("OccActive");
129*3e5422edSVishwanatha Subbanna     if (propertyMap != msgData.end())
130*3e5422edSVishwanatha Subbanna     {
131*3e5422edSVishwanatha Subbanna         // Extract the OccActive property
132*3e5422edSVishwanatha Subbanna         if (sdbusplus::message::variant_ns::get<bool>(propertyMap->second))
133*3e5422edSVishwanatha Subbanna         {
134*3e5422edSVishwanatha Subbanna             this->openDevice();
135*3e5422edSVishwanatha Subbanna         }
136*3e5422edSVishwanatha Subbanna         else
137*3e5422edSVishwanatha Subbanna         {
138*3e5422edSVishwanatha Subbanna             this->closeDevice();
139*3e5422edSVishwanatha Subbanna         }
140*3e5422edSVishwanatha Subbanna     }
141*3e5422edSVishwanatha Subbanna     return;
142*3e5422edSVishwanatha Subbanna }
143*3e5422edSVishwanatha Subbanna 
1446b492fbfSDeepak Kodihalli } // namespace occ
1456b492fbfSDeepak Kodihalli } // namespace open_power
146