1 #pragma once 2 3 #include "i2c_occ.hpp" 4 #include "occ_device.hpp" 5 #include "occ_events.hpp" 6 7 #include <functional> 8 #include <org/open_power/Control/Host/server.hpp> 9 #include <org/open_power/OCC/Status/server.hpp> 10 #include <sdbusplus/bus.hpp> 11 #include <sdbusplus/server/object.hpp> 12 13 namespace open_power 14 { 15 namespace occ 16 { 17 18 class Manager; 19 namespace Base = sdbusplus::org::open_power::OCC::server; 20 using Interface = sdbusplus::server::object::object<Base::Status>; 21 22 // IPMID's host control application 23 namespace Control = sdbusplus::org::open_power::Control::server; 24 25 // For waiting on signals 26 namespace sdbusRule = sdbusplus::bus::match::rules; 27 28 // OCC status instance. Ex. for "occ0", the instance is 0 29 using instanceID = int; 30 31 // IPMI sensor ID for a given OCC instance 32 using sensorID = uint8_t; 33 34 // OCC sysfs name prefix 35 const std::string sysfsName = "occ-hwmon"; 36 37 /** @class Status 38 * @brief Implementation of OCC Active Status 39 */ 40 class Status : public Interface 41 { 42 public: 43 Status() = delete; 44 ~Status() = default; 45 Status(const Status&) = delete; 46 Status& operator=(const Status&) = delete; 47 Status(Status&&) = default; 48 Status& operator=(Status&&) = default; 49 50 /** @brief Constructs the Status object and 51 * the underlying device object 52 * 53 * @param[in] bus - DBus bus to attach to 54 * @param[in] event - sd_event unique pointer reference 55 * @param[in] path - DBus object path 56 * @param[in] manager - OCC manager instance 57 * @param[in] callBack - Callback handler to invoke during 58 * property change 59 */ 60 Status(sdbusplus::bus::bus& bus, EventPtr& event, const char* path, 61 const Manager& manager, 62 std::function<void(bool)> callBack = nullptr) : 63 Interface(bus, path, true), 64 bus(bus), path(path), callBack(callBack), 65 instance(((this->path.back() - '0'))), 66 device(event, 67 #ifdef I2C_OCC 68 i2c_occ::getI2cDeviceName(path), 69 #else 70 sysfsName + "." + std::to_string(instance + 1), 71 #endif 72 manager, *this, 73 std::bind(std::mem_fn(&Status::deviceErrorHandler), this, 74 std::placeholders::_1)), 75 hostControlSignal( 76 bus, 77 sdbusRule::type::signal() + sdbusRule::member("CommandComplete") + 78 sdbusRule::path("/org/open_power/control/host0") + 79 sdbusRule::interface("org.open_power.Control.Host") + 80 sdbusRule::argN(0, Control::convertForMessage( 81 Control::Host::Command::OCCReset)), 82 std::bind(std::mem_fn(&Status::hostControlEvent), this, 83 std::placeholders::_1)) 84 { 85 // Check to see if we have OCC already bound. If so, just set it 86 if (device.bound()) 87 { 88 this->occActive(true); 89 } 90 91 // Announce that we are ready 92 this->emit_object_added(); 93 } 94 95 /** @brief Since we are overriding the setter-occActive but not the 96 * getter-occActive, we need to have this using in order to 97 * allow passthrough usage of the getter-occActive 98 */ 99 using Base::Status::occActive; 100 101 /** @brief SET OccActive to True or False 102 * 103 * @param[in] value - Intended value 104 * 105 * @return - Updated value of the property 106 */ 107 bool occActive(bool value) override; 108 109 /** @brief Starts OCC error detection */ 110 inline void addErrorWatch() 111 { 112 return device.addErrorWatch(); 113 } 114 115 /** @brief Stops OCC error detection */ 116 inline void removeErrorWatch() 117 { 118 return device.removeErrorWatch(); 119 } 120 121 /** @brief Starts to watch how many OCCs are present on the master */ 122 inline void addPresenceWatchMaster() 123 { 124 return device.addPresenceWatchMaster(); 125 } 126 127 private: 128 /** @brief sdbus handle */ 129 sdbusplus::bus::bus& bus; 130 131 /** @brief OCC dbus object path */ 132 std::string path; 133 134 /** @brief Callback handler to be invoked during property change. 135 * This is a handler in Manager class 136 */ 137 std::function<void(bool)> callBack; 138 139 /** @brief OCC instance number. Ex, 0,1, etc */ 140 int instance; 141 142 /** @brief OCC instance to Sensor ID mapping */ 143 static const std::map<instanceID, sensorID> sensorMap; 144 145 /** @brief OCC device object to do bind and unbind */ 146 Device device; 147 148 /** @brief Subscribe to host control signal 149 * 150 * Once the OCC reset is requested, BMC sends that message to host. 151 * If the host does not ack the message, then there would be a timeout 152 * and we need to catch that to log an error 153 **/ 154 sdbusplus::bus::match_t hostControlSignal; 155 156 /** @brief Callback handler when device errors are detected 157 * 158 * @param[in] error - True if an error is reported, false otherwise 159 */ 160 void deviceErrorHandler(bool error); 161 162 /** @brief Callback function on host control signals 163 * 164 * @param[in] msg - Data associated with subscribed signal 165 */ 166 void hostControlEvent(sdbusplus::message::message& msg); 167 168 /** @brief Sends a message to host control command handler to reset OCC 169 */ 170 void resetOCC(); 171 }; 172 173 } // namespace occ 174 } // namespace open_power 175