1 #pragma once
2 
3 #include "occ_errors.hpp"
4 #include "utils.hpp"
5 
6 #include <org/open_power/OCC/PassThrough/server.hpp>
7 #include <sdbusplus/bus.hpp>
8 #include <sdbusplus/server/object.hpp>
9 
10 #include <format>
11 #include <string>
12 #include <utility>
13 
14 namespace open_power
15 {
16 namespace occ
17 {
18 
19 // For waiting on signals
20 namespace sdbusRule = sdbusplus::bus::match::rules;
21 
22 enum class CmdType
23 {
24     POLL = 0x00,
25     CLEAR_ERROR_LOG = 0x12,
26     SET_MODE_AND_STATE = 0x20,
27     SET_CONFIG_DATA = 0x21,
28     SET_USER_PCAP = 0x22,
29     RESET_PREP = 0x25,
30     SEND_AMBIENT = 0x30,
31     DEBUG_PASS_THROUGH = 0x40,
32     AME_PASS_THROUGH = 0x41,
33     GET_FIELD_DEBUG_DATA = 0x42,
34     MFG_TEST = 0x53
35 };
36 
37 enum class OccState
38 {
39     NO_CHANGE = 0x00,
40     STANDBY = 0x01,
41     OBSERVATION = 0x02,
42     ACTIVE = 0x03,
43     SAFE = 0x04,
44     CHARACTERIZATION = 0x05
45 };
46 
47 enum class SysPwrMode
48 {
49     NO_CHANGE = 0,
50     STATIC = 0x01,            // Static Base Frequencey
51     NON_DETERMINISTIC = 0x02, // Non-Deterministic
52     SFP = 0x03,               // Static Frequency Point (requires freqPt)
53     SAFE = 0x04,         // reported when system is in SAFE mode (not settable)
54     POWER_SAVING = 0x05, // Static Power Saving
55     EFF_FAVOR_POWER = 0x06, // Efficiency - Favor Power
56     EFF_FAVOR_PERF = 0x07,  // Efficiency - Favor Performance
57     MAX_FREQ = 0x09,        // Maximum Frequency (per chip)
58     BALANCED_PERF = 0x0A,   // Balanced Performance
59     FFO = 0x0B,             // Fixed Frequency Override (requires freqPt)
60     MAX_PERF = 0x0C         // Maximum Performance
61 };
62 
63 enum class RspStatus
64 {
65     SUCCESS = 0x00,
66     CONDITIONAL_SUCCESS = 0x01,
67     INVALID_COMMAND = 0x11,
68     INVALID_COMMAND_LENGTH = 0x12,
69     INVALID_DATA_FIELD = 0x13,
70     CHECKSUM_FAILURE = 0x14,
71     INTERNAL_ERROR = 0x15,
72     PRESENT_STATE_PROHIBITS = 0x16,
73     COMMAND_IN_PROGRESS = 0xFF
74 };
75 
76 enum class CmdStatus
77 {
78     SUCCESS = 0x00,
79     FAILURE = 0x02,
80     COMM_FAILURE = 0x03
81 };
82 
83 /** @brief Trace block of data in hex with log<level:INFO>
84  *
85  *  @param[in] data - vector containing data to trace
86  *  @param[in] data_len - optional number of bytes to trace
87  *  If 0, entire vector will be traced.
88  */
89 void dump_hex(const std::vector<std::uint8_t>& data,
90               const unsigned int data_len = 0);
91 
92 /** @class OccCommand
93  *  @brief Send commands and process respsonses from the OCC
94  */
95 class OccCommand
96 {
97   public:
98     OccCommand() = delete;
99     OccCommand(const OccCommand&) = delete;
100     OccCommand& operator=(const OccCommand&) = delete;
101     OccCommand(OccCommand&&) = default;
102     OccCommand& operator=(OccCommand&&) = default;
103 
104     /** @brief Ctor to set up which OCC the command will go to
105      *
106      *  @param[in] instance - OCC instance
107      *  @param[in] path - Path to attach at
108      */
109     OccCommand(uint8_t instance, const char* path);
110 
111     /** @brief Dtor to clean up and close device */
112     ~OccCommand()
113     {
114         closeDevice();
115     }
116 
117     /** @brief Send the command to the OCC and collect the response.
118      * The checksum will be validated and removed from the response.
119      *
120      *  @param[in] command - command to pass-through
121      *  @param[out] response - response
122      *  returns SUCCESS if response was received
123      */
124     CmdStatus send(const std::vector<std::uint8_t>& command,
125                    std::vector<std::uint8_t>& response);
126 
127   private:
128     /** @brief Instance number of the target OCC */
129     uint8_t occInstance;
130 
131     /** @brief OCC path on the bus */
132     std::string path;
133 
134     /** @brief OCC device path
135      *  For now, here is the hard-coded mapping until
136      *  the udev rule is in.
137      *  occ0 --> /dev/occ1
138      *  occ1 --> /dev/occ2
139      *  ...
140      */
141     std::string devicePath;
142 
143     /** @brief Indicates whether or not the OCC is currently active */
144     bool occActive = false;
145 
146     /** brief file descriptor associated with occ device */
147     int fd = -1;
148 
149     /** @brief Subscribe to OCC Status signal
150      *
151      *  Once the OCC status gets to active, only then we will get /dev/occ2
152      *  populated and hence need to wait on that before opening that
153      */
154     sdbusplus::bus::match_t activeStatusSignal;
155 
156     /** Opens devicePath and populates file descriptor */
157     void openDevice();
158 
159     /** Closed the fd associated with opened device */
160     void closeDevice();
161 
162     /** @brief Callback function on OCC Status change signals
163      *
164      *  @param[in]  msg - Data associated with subscribed signal
165      */
166     void activeStatusEvent(sdbusplus::message_t& msg);
167 };
168 
169 } // namespace occ
170 } // namespace open_power
171 
172 template <>
173 struct std::formatter<open_power::occ::SysPwrMode> : formatter<int>
174 {
175     auto format(open_power::occ::SysPwrMode f, format_context& ctx) const
176     {
177         return formatter<int>::format(std::to_underlying(f), ctx);
178     }
179 };
180 
181 template <>
182 struct std::formatter<open_power::occ::CmdStatus> : formatter<int>
183 {
184     auto format(open_power::occ::CmdStatus f, format_context& ctx) const
185     {
186         return formatter<int>::format(std::to_underlying(f), ctx);
187     }
188 };
189