16b492fbfSDeepak Kodihalli #include <memory> 202ba9eccSDeepak Kodihalli #include <algorithm> 338b08d79SVishwanatha Subbanna #include <fcntl.h> 467d50ad6SVishwanatha Subbanna #include <errno.h> 502ba9eccSDeepak Kodihalli #include <phosphor-logging/log.hpp> 69bb065b8SVishwanatha Subbanna #include <phosphor-logging/elog.hpp> 79bb065b8SVishwanatha Subbanna #include <org/open_power/OCC/PassThrough/error.hpp> 86b492fbfSDeepak Kodihalli #include "occ_pass_through.hpp" 96b492fbfSDeepak Kodihalli #include "occ_finder.hpp" 109bb065b8SVishwanatha Subbanna #include "elog-errors.hpp" 116b492fbfSDeepak Kodihalli namespace open_power 126b492fbfSDeepak Kodihalli { 136b492fbfSDeepak Kodihalli namespace occ 146b492fbfSDeepak Kodihalli { 156b492fbfSDeepak Kodihalli namespace pass_through 166b492fbfSDeepak Kodihalli { 176b492fbfSDeepak Kodihalli 186b492fbfSDeepak Kodihalli void run() 196b492fbfSDeepak Kodihalli { 206b492fbfSDeepak Kodihalli auto bus = sdbusplus::bus::new_default(); 216b492fbfSDeepak Kodihalli sdbusplus::server::manager::manager objManager(bus, 226b492fbfSDeepak Kodihalli OCC_PASS_THROUGH_ROOT); 236b492fbfSDeepak Kodihalli 246b492fbfSDeepak Kodihalli std::vector<std::unique_ptr<PassThrough>> objects; 256b492fbfSDeepak Kodihalli auto occs = open_power::occ::finder::get(); 266b492fbfSDeepak Kodihalli 276b492fbfSDeepak Kodihalli for (const auto& occ : occs) 286b492fbfSDeepak Kodihalli { 296b492fbfSDeepak Kodihalli auto occPassThrough = object(occ); 306b492fbfSDeepak Kodihalli objects.emplace_back( 316b492fbfSDeepak Kodihalli std::make_unique<PassThrough>(bus, occPassThrough.c_str())); 326b492fbfSDeepak Kodihalli } 336b492fbfSDeepak Kodihalli bus.request_name(OCC_PASS_THROUGH_BUSNAME); 346b492fbfSDeepak Kodihalli 356b492fbfSDeepak Kodihalli while (true) 366b492fbfSDeepak Kodihalli { 376b492fbfSDeepak Kodihalli bus.process_discard(); 386b492fbfSDeepak Kodihalli bus.wait(); 396b492fbfSDeepak Kodihalli } 406b492fbfSDeepak Kodihalli } 416b492fbfSDeepak Kodihalli 426b492fbfSDeepak Kodihalli PassThrough::PassThrough( 436b492fbfSDeepak Kodihalli sdbusplus::bus::bus& bus, 446b492fbfSDeepak Kodihalli const char* path) : 456b492fbfSDeepak Kodihalli Iface(bus, path), 4638b08d79SVishwanatha Subbanna path(path), 4738b08d79SVishwanatha Subbanna fd(openDevice()) 486b492fbfSDeepak Kodihalli { 4938b08d79SVishwanatha Subbanna // Nothing to do. 5038b08d79SVishwanatha Subbanna } 5138b08d79SVishwanatha Subbanna 5238b08d79SVishwanatha Subbanna int PassThrough::openDevice() 5338b08d79SVishwanatha Subbanna { 549bb065b8SVishwanatha Subbanna using namespace phosphor::logging; 559bb065b8SVishwanatha Subbanna using namespace sdbusplus::org::open_power::OCC::PassThrough::Error; 569bb065b8SVishwanatha Subbanna 5738b08d79SVishwanatha Subbanna // Device instance number starts from 1. 58afd21a65SVishwanatha Subbanna devicePath.append(std::to_string((this->path.back() - '0') + 1)); 5938b08d79SVishwanatha Subbanna 6038b08d79SVishwanatha Subbanna int fd = open(devicePath.c_str(), O_RDWR | O_NONBLOCK); 6138b08d79SVishwanatha Subbanna if (fd < 0) 6238b08d79SVishwanatha Subbanna { 639bb065b8SVishwanatha Subbanna // This would log and terminate since its not handled. 649bb065b8SVishwanatha Subbanna elog<OpenFailure>( 659bb065b8SVishwanatha Subbanna phosphor::logging::org::open_power::OCC::PassThrough:: 669bb065b8SVishwanatha Subbanna OpenFailure::CALLOUT_ERRNO(errno), 679bb065b8SVishwanatha Subbanna phosphor::logging::org::open_power::OCC::PassThrough:: 689bb065b8SVishwanatha Subbanna OpenFailure::CALLOUT_DEVICE_PATH(devicePath.c_str())); 6938b08d79SVishwanatha Subbanna } 7038b08d79SVishwanatha Subbanna return fd; 716b492fbfSDeepak Kodihalli } 726b492fbfSDeepak Kodihalli 736b492fbfSDeepak Kodihalli std::vector<int32_t> PassThrough::send(std::vector<int32_t> command) 746b492fbfSDeepak Kodihalli { 7567d50ad6SVishwanatha Subbanna using namespace phosphor::logging; 769bb065b8SVishwanatha Subbanna using namespace sdbusplus::org::open_power::OCC::PassThrough::Error; 7767d50ad6SVishwanatha Subbanna 7867d50ad6SVishwanatha Subbanna std::vector<int32_t> response {}; 7967d50ad6SVishwanatha Subbanna 80*7d700e26SVishwanatha Subbanna // OCC only understands [bytes] so need array of bytes. Doing this 81*7d700e26SVishwanatha Subbanna // because rest-server currently treats all int* as 32 bit integer. 82*7d700e26SVishwanatha Subbanna std::vector<uint8_t> cmdInBytes; 83*7d700e26SVishwanatha Subbanna cmdInBytes.resize(command.size()); 84*7d700e26SVishwanatha Subbanna 85*7d700e26SVishwanatha Subbanna // Populate uint8_t version of vector. 86*7d700e26SVishwanatha Subbanna std::transform(command.begin(), command.end(), cmdInBytes.begin(), 87*7d700e26SVishwanatha Subbanna [](decltype(cmdInBytes)::value_type x){return x;}); 88*7d700e26SVishwanatha Subbanna 89*7d700e26SVishwanatha Subbanna ssize_t size = cmdInBytes.size() * sizeof(decltype(cmdInBytes)::value_type); 90*7d700e26SVishwanatha Subbanna auto rc = write((fd)(), cmdInBytes.data(), size); 9167d50ad6SVishwanatha Subbanna if (rc < 0 || (rc != size)) 9267d50ad6SVishwanatha Subbanna { 939bb065b8SVishwanatha Subbanna // This would log and terminate since its not handled. 949bb065b8SVishwanatha Subbanna elog<WriteFailure>( 959bb065b8SVishwanatha Subbanna phosphor::logging::org::open_power::OCC::PassThrough:: 969bb065b8SVishwanatha Subbanna WriteFailure::CALLOUT_ERRNO(errno), 979bb065b8SVishwanatha Subbanna phosphor::logging::org::open_power::OCC::PassThrough:: 989bb065b8SVishwanatha Subbanna WriteFailure::CALLOUT_DEVICE_PATH(devicePath.c_str())); 996b492fbfSDeepak Kodihalli } 1006b492fbfSDeepak Kodihalli 10167d50ad6SVishwanatha Subbanna // Now read the response. This would be the content of occ-sram 10267d50ad6SVishwanatha Subbanna while(1) 10367d50ad6SVishwanatha Subbanna { 104*7d700e26SVishwanatha Subbanna uint8_t data {}; 10567d50ad6SVishwanatha Subbanna auto len = read((fd)(), &data, sizeof(data)); 10667d50ad6SVishwanatha Subbanna if (len > 0) 10767d50ad6SVishwanatha Subbanna { 10867d50ad6SVishwanatha Subbanna response.emplace_back(data); 10967d50ad6SVishwanatha Subbanna } 11067d50ad6SVishwanatha Subbanna else if (len < 0 && errno == EAGAIN) 11167d50ad6SVishwanatha Subbanna { 1129bb065b8SVishwanatha Subbanna // We may have data coming still. 1139bb065b8SVishwanatha Subbanna // This driver does not need a sleep for a retry. 11467d50ad6SVishwanatha Subbanna continue; 11567d50ad6SVishwanatha Subbanna } 11667d50ad6SVishwanatha Subbanna else if (len == 0) 11767d50ad6SVishwanatha Subbanna { 11867d50ad6SVishwanatha Subbanna // We have read all that we can. 11967d50ad6SVishwanatha Subbanna break; 12067d50ad6SVishwanatha Subbanna } 12167d50ad6SVishwanatha Subbanna else 12267d50ad6SVishwanatha Subbanna { 1239bb065b8SVishwanatha Subbanna // This would log and terminate since its not handled. 1249bb065b8SVishwanatha Subbanna elog<ReadFailure>( 1259bb065b8SVishwanatha Subbanna phosphor::logging::org::open_power::OCC::PassThrough:: 1269bb065b8SVishwanatha Subbanna ReadFailure::CALLOUT_ERRNO(errno), 1279bb065b8SVishwanatha Subbanna phosphor::logging::org::open_power::OCC::PassThrough:: 1289bb065b8SVishwanatha Subbanna ReadFailure::CALLOUT_DEVICE_PATH(devicePath.c_str())); 12967d50ad6SVishwanatha Subbanna } 13067d50ad6SVishwanatha Subbanna } 13167d50ad6SVishwanatha Subbanna 13267d50ad6SVishwanatha Subbanna return response; 13367d50ad6SVishwanatha Subbanna } 13467d50ad6SVishwanatha Subbanna 1356b492fbfSDeepak Kodihalli } // namespace pass_through 1366b492fbfSDeepak Kodihalli } // namespace occ 1376b492fbfSDeepak Kodihalli } // namespace open_power 138