blob: 7027d6539d83579c08fe1c83fd8577db675e1800 [file] [log] [blame]
Deepak Kodihalli6b492fb2017-03-18 01:09:28 -05001#include <memory>
Deepak Kodihalli02ba9ec2017-03-18 02:57:43 -05002#include <algorithm>
Vishwanatha Subbanna38b08d72017-04-14 18:12:14 +05303#include <fcntl.h>
Vishwanatha Subbanna67d50ad2017-04-17 23:21:52 +05304#include <errno.h>
Deepak Kodihalli02ba9ec2017-03-18 02:57:43 -05005#include <phosphor-logging/log.hpp>
Vishwanatha Subbanna9bb065b2017-04-18 14:25:26 +05306#include <phosphor-logging/elog.hpp>
7#include <org/open_power/OCC/PassThrough/error.hpp>
Deepak Kodihalli6b492fb2017-03-18 01:09:28 -05008#include "occ_pass_through.hpp"
9#include "occ_finder.hpp"
Vishwanatha Subbanna9bb065b2017-04-18 14:25:26 +053010#include "elog-errors.hpp"
Deepak Kodihalli6b492fb2017-03-18 01:09:28 -050011namespace open_power
12{
13namespace occ
14{
15namespace pass_through
16{
17
18void run()
19{
20 auto bus = sdbusplus::bus::new_default();
21 sdbusplus::server::manager::manager objManager(bus,
22 OCC_PASS_THROUGH_ROOT);
23
24 std::vector<std::unique_ptr<PassThrough>> objects;
25 auto occs = open_power::occ::finder::get();
26
27 for (const auto& occ : occs)
28 {
29 auto occPassThrough = object(occ);
30 objects.emplace_back(
31 std::make_unique<PassThrough>(bus, occPassThrough.c_str()));
32 }
33 bus.request_name(OCC_PASS_THROUGH_BUSNAME);
34
35 while (true)
36 {
37 bus.process_discard();
38 bus.wait();
39 }
40}
41
42PassThrough::PassThrough(
43 sdbusplus::bus::bus& bus,
44 const char* path) :
45 Iface(bus, path),
Vishwanatha Subbanna38b08d72017-04-14 18:12:14 +053046 path(path),
47 fd(openDevice())
Deepak Kodihalli6b492fb2017-03-18 01:09:28 -050048{
Vishwanatha Subbanna38b08d72017-04-14 18:12:14 +053049 // Nothing to do.
50}
51
52int PassThrough::openDevice()
53{
Vishwanatha Subbanna9bb065b2017-04-18 14:25:26 +053054 using namespace phosphor::logging;
55 using namespace sdbusplus::org::open_power::OCC::PassThrough::Error;
56
Vishwanatha Subbanna38b08d72017-04-14 18:12:14 +053057 // Device instance number starts from 1.
Vishwanatha Subbannaafd21a62017-04-13 20:17:13 +053058 devicePath.append(std::to_string((this->path.back() - '0') + 1));
Vishwanatha Subbanna38b08d72017-04-14 18:12:14 +053059
60 int fd = open(devicePath.c_str(), O_RDWR | O_NONBLOCK);
61 if (fd < 0)
62 {
Vishwanatha Subbanna9bb065b2017-04-18 14:25:26 +053063 // This would log and terminate since its not handled.
64 elog<OpenFailure>(
65 phosphor::logging::org::open_power::OCC::PassThrough::
66 OpenFailure::CALLOUT_ERRNO(errno),
67 phosphor::logging::org::open_power::OCC::PassThrough::
68 OpenFailure::CALLOUT_DEVICE_PATH(devicePath.c_str()));
Vishwanatha Subbanna38b08d72017-04-14 18:12:14 +053069 }
70 return fd;
Deepak Kodihalli6b492fb2017-03-18 01:09:28 -050071}
72
73std::vector<int32_t> PassThrough::send(std::vector<int32_t> command)
74{
Vishwanatha Subbanna67d50ad2017-04-17 23:21:52 +053075 using namespace phosphor::logging;
Vishwanatha Subbanna9bb065b2017-04-18 14:25:26 +053076 using namespace sdbusplus::org::open_power::OCC::PassThrough::Error;
Vishwanatha Subbanna67d50ad2017-04-17 23:21:52 +053077
78 std::vector<int32_t> response {};
79
Vishwanatha Subbanna7d700e22017-05-19 19:58:01 +053080 // OCC only understands [bytes] so need array of bytes. Doing this
81 // because rest-server currently treats all int* as 32 bit integer.
82 std::vector<uint8_t> cmdInBytes;
83 cmdInBytes.resize(command.size());
84
85 // Populate uint8_t version of vector.
86 std::transform(command.begin(), command.end(), cmdInBytes.begin(),
87 [](decltype(cmdInBytes)::value_type x){return x;});
88
89 ssize_t size = cmdInBytes.size() * sizeof(decltype(cmdInBytes)::value_type);
90 auto rc = write((fd)(), cmdInBytes.data(), size);
Vishwanatha Subbanna67d50ad2017-04-17 23:21:52 +053091 if (rc < 0 || (rc != size))
92 {
Vishwanatha Subbanna9bb065b2017-04-18 14:25:26 +053093 // This would log and terminate since its not handled.
94 elog<WriteFailure>(
95 phosphor::logging::org::open_power::OCC::PassThrough::
96 WriteFailure::CALLOUT_ERRNO(errno),
97 phosphor::logging::org::open_power::OCC::PassThrough::
98 WriteFailure::CALLOUT_DEVICE_PATH(devicePath.c_str()));
Vishwanatha Subbanna67d50ad2017-04-17 23:21:52 +053099 }
100
101 // Now read the response. This would be the content of occ-sram
102 while(1)
103 {
Vishwanatha Subbanna7d700e22017-05-19 19:58:01 +0530104 uint8_t data {};
Vishwanatha Subbanna67d50ad2017-04-17 23:21:52 +0530105 auto len = read((fd)(), &data, sizeof(data));
106 if (len > 0)
107 {
108 response.emplace_back(data);
109 }
110 else if (len < 0 && errno == EAGAIN)
111 {
Vishwanatha Subbanna9bb065b2017-04-18 14:25:26 +0530112 // We may have data coming still.
113 // This driver does not need a sleep for a retry.
Vishwanatha Subbanna67d50ad2017-04-17 23:21:52 +0530114 continue;
115 }
116 else if (len == 0)
117 {
118 // We have read all that we can.
119 break;
120 }
121 else
122 {
Vishwanatha Subbanna9bb065b2017-04-18 14:25:26 +0530123 // This would log and terminate since its not handled.
124 elog<ReadFailure>(
125 phosphor::logging::org::open_power::OCC::PassThrough::
126 ReadFailure::CALLOUT_ERRNO(errno),
127 phosphor::logging::org::open_power::OCC::PassThrough::
128 ReadFailure::CALLOUT_DEVICE_PATH(devicePath.c_str()));
Vishwanatha Subbanna67d50ad2017-04-17 23:21:52 +0530129 }
130 }
131
132 return response;
Deepak Kodihalli6b492fb2017-03-18 01:09:28 -0500133}
134
Deepak Kodihalli6b492fb2017-03-18 01:09:28 -0500135} // namespace pass_through
136} // namespace occ
137} // namespace open_power