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