ACPI Reset if possible

This commit is contained in:
Baptiste Wicht 2016-07-24 16:06:03 +02:00
parent 389e0846fb
commit 57f755bdae
5 changed files with 69 additions and 8 deletions

View File

@ -11,10 +11,11 @@
namespace acpi {
void init();
void shutdown();
bool initialized();
void shutdown();
bool reboot();
} //end of acpi namespace
#endif

View File

@ -18,10 +18,13 @@ extern "C" {
#pragma GCC diagnostic ignored "-Wunused-parameter"
#pragma GCC diagnostic ignored "-Wunused-function" //TODO Does not work
#include "acpi.h"
#include "accommon.h"
#pragma GCC diagnostic pop
} //end of extern "C"
#include <types.hpp>
constexpr const size_t FADT2_REVISION_ID = 3;
#endif

View File

@ -14,6 +14,7 @@
#include "logging.hpp"
#include "scheduler.hpp"
#include "arch.hpp"
#include "assert.hpp"
namespace {
@ -105,6 +106,43 @@ void initialize_acpica(){
logging::logf(logging::log_level::DEBUG, "acpi:: Finished initialization of ACPICA\n");
}
uint64_t acpi_read(const ACPI_GENERIC_ADDRESS& address){
if(address.SpaceId == ACPI_ADR_SPACE_SYSTEM_MEMORY){
UINT64 value = 0;
auto status = AcpiOsReadMemory(address.Address, &value, address.BitWidth);
if(ACPI_FAILURE(status)){
logging::logf(logging::log_level::ERROR, "acpica: Unable to read from memory: error: %s\n", AcpiGbl_ExceptionNames_Env[status].Name);
}
return value;
} else if(address.SpaceId == ACPI_ADR_SPACE_SYSTEM_IO){
UINT32 value = 0;
auto status = AcpiHwReadPort(address.Address, &value, address.BitWidth);
if(ACPI_FAILURE(status)){
logging::logf(logging::log_level::ERROR, "acpica: Unable to read from hardware port: error: %s\n", AcpiGbl_ExceptionNames_Env[status].Name);
}
return value;
} else {
logging::logf(logging::log_level::ERROR, "acpica: Unimplemented read generic address space id\n");
return 0;
}
}
void acpi_write(const ACPI_GENERIC_ADDRESS& address, uint64_t value){
if(address.SpaceId == ACPI_ADR_SPACE_SYSTEM_MEMORY){
auto status = AcpiOsWriteMemory(address.Address, value, address.BitWidth);
if(ACPI_FAILURE(status)){
logging::logf(logging::log_level::ERROR, "acpica: Unable to write to memory: error: %s\n", AcpiGbl_ExceptionNames_Env[status].Name);
}
} else if(address.SpaceId == ACPI_ADR_SPACE_SYSTEM_IO){
auto status = AcpiHwWritePort(address.Address, value, address.BitWidth);
if(ACPI_FAILURE(status)){
logging::logf(logging::log_level::ERROR, "acpica: Unable to write to hardware port: error: %s\n", AcpiGbl_ExceptionNames_Env[status].Name);
}
} else {
logging::logf(logging::log_level::ERROR, "acpica: Unimplemented write generic address space id\n");
}
}
} //end of anonymous namespace
void acpi::init(){
@ -112,7 +150,13 @@ void acpi::init(){
scheduler::queue_async_init_task(initialize_acpica);
}
bool acpi::initialized(){
return acpi_initialized;
}
void acpi::shutdown(){
thor_assert(acpi::initialized(), "ACPI must be initialized for acpi::shutdown()");
auto status = AcpiEnterSleepStatePrep(5);
if(ACPI_FAILURE(status)){
@ -133,6 +177,19 @@ void acpi::shutdown(){
arch::enable_hwint(rflags);
}
bool acpi::initialized(){
return acpi_initialized;
bool acpi::reboot(){
thor_assert(acpi::initialized(), "ACPI must be initialized for acpi::reboot()");
if (AcpiGbl_FADT.Header.Revision < FADT2_REVISION_ID){
return false;
}
if(!(AcpiGbl_FADT.Flags & ACPI_FADT_RESET_REGISTER)){
return false;
}
auto reset_register = AcpiGbl_FADT.ResetRegister;
auto reset_value = AcpiGbl_FADT.ResetValue;
acpi_write(reset_register, reset_value);
}

View File

@ -13,8 +13,6 @@
namespace {
constexpr const size_t FADT2_REVISION_ID = 3;
#define CURRENT_YEAR 2013
#define cmos_address 0x70
#define cmos_data 0x71

View File

@ -91,8 +91,10 @@ void sc_clear(interrupt::syscall_regs*){
}
void sc_reboot(interrupt::syscall_regs*){
//TODO Reboot should be done more properly
asm volatile("mov al, 0x64; or al, 0xFE; out 0x64, al; mov al, 0xFE; out 0x64, al; " : : );
if(!acpi::initialized() || !acpi::reboot()){
logging::logf(logging::log_level::ERROR, "ACPI reset not possible, fallback to 8042 reboot\n");
asm volatile("mov al, 0x64; or al, 0xFE; out 0x64, al; mov al, 0xFE; out 0x64, al; " : : );
}
__builtin_unreachable();
}