blob: 4a3ca4b2737c6fd27b5e716d75e10a6c24b9cc33 [file] [log] [blame]
/*
// Copyright (c) 2018 Intel Corporation
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
*/
#include "power_control.hpp"
bool PowerControl::forcePowerOff()
{
return true;
}
int32_t PowerControl::triggerReset()
{
int ret = 0;
int count = 0;
char buf = '0';
phosphor::logging::log<phosphor::logging::level::DEBUG>("triggerReset");
ret = ::lseek(reset_out_fd, 0, SEEK_SET);
if (ret < 0)
{
phosphor::logging::log<phosphor::logging::level::ERR>("lseek error!");
throw sdbusplus::xyz::openbmc_project::Chassis::Common::Error::
IOError();
}
buf = '0';
ret = ::write(reset_out_fd, &buf, sizeof(buf));
if (ret < 0)
{
phosphor::logging::log<phosphor::logging::level::ERR>("write error!");
throw sdbusplus::xyz::openbmc_project::Chassis::Common::Error::
IOError();
}
std::this_thread::sleep_for(std::chrono::milliseconds(RESET_PULSE_TIME_MS));
buf = '1';
ret = ::write(reset_out_fd, &buf, sizeof(buf));
if (ret < 0)
{
phosphor::logging::log<phosphor::logging::level::ERR>("write error!");
throw sdbusplus::xyz::openbmc_project::Chassis::Common::Error::
IOError();
}
return 0;
}
int32_t PowerControl::setPowerState(int newState)
{
int ret = 0;
int count = 0;
char buf = '0';
if (newState < 0 || newState >= powerStateMax)
{
phosphor::logging::log<phosphor::logging::level::ERR>(
"error! invalid parameter!");
return -1;
}
phosphor::logging::log<phosphor::logging::level::DEBUG>(
"setPowerState", phosphor::logging::entry("NEWSTATE=%d", newState));
if (powerStateReset == newState)
{
phosphor::logging::log<phosphor::logging::level::DEBUG>(
"setPowerState system reset");
triggerReset();
return 0;
}
if (state() == newState)
{
phosphor::logging::log<phosphor::logging::level::WARNING>(
"Same powerstate",
phosphor::logging::entry("NEWSTATE=%d", newState));
return 0;
}
state(newState);
ret = ::lseek(power_up_fd, 0, SEEK_SET);
if (ret < 0)
{
phosphor::logging::log<phosphor::logging::level::ERR>("lseek error!");
throw sdbusplus::xyz::openbmc_project::Chassis::Common::Error::
IOError();
}
buf = '0';
ret = ::write(power_up_fd, &buf, sizeof(buf));
if (ret < 0)
{
phosphor::logging::log<phosphor::logging::level::ERR>("write error!");
throw sdbusplus::xyz::openbmc_project::Chassis::Common::Error::
IOError();
}
phosphor::logging::log<phosphor::logging::level::DEBUG>(
"setPowerState power on");
std::this_thread::sleep_for(std::chrono::milliseconds(POWER_PULSE_TIME_MS));
buf = '1';
ret = ::write(power_up_fd, &buf, sizeof(buf));
if (ret < 0)
{
phosphor::logging::log<phosphor::logging::level::ERR>("write error!");
throw sdbusplus::xyz::openbmc_project::Chassis::Common::Error::
IOError();
}
if (0 == newState)
{
/*
* For power off, currently there is a known issue, the "long-press"
* power button cannot power off the host, a workaround is perform force
* power off after waitting for a while
*/
std::this_thread::sleep_for(
std::chrono::milliseconds(POWER_PULSE_TIME_MS));
if (1 == pGood())
{ // still on, force off!
phosphor::logging::log<phosphor::logging::level::DEBUG>(
"Perform force power off");
count = 0;
do
{
if (count++ > 5)
{
phosphor::logging::log<phosphor::logging::level::ERR>(
"forcePowerOff error!");
throw sdbusplus::xyz::openbmc_project::Chassis::Common::
Error::IOError();
}
ret = forcePowerOff();
std::this_thread::sleep_for(
std::chrono::milliseconds(POLLING_INTERVAL_MS));
} while (ret != 0);
}
}
return 0;
}