From d4ede03e192ae492b796ee7c8d6c9c71409ec56a Mon Sep 17 00:00:00 2001 From: Stanislav Motylkov Date: Fri, 4 Oct 2019 22:04:51 +0300 Subject: [PATCH] [HALXBOX] Implement shutdown, reboot, and power cycle routines CORE-16216 --- hal/halx86/xbox.cmake | 2 +- hal/halx86/xbox/halxbox.h | 28 ++++++++-- hal/halx86/xbox/reboot.c | 115 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 139 insertions(+), 6 deletions(-) create mode 100644 hal/halx86/xbox/reboot.c diff --git a/hal/halx86/xbox.cmake b/hal/halx86/xbox.cmake index a259df7a57c..c3604e70dfe 100644 --- a/hal/halx86/xbox.cmake +++ b/hal/halx86/xbox.cmake @@ -15,7 +15,6 @@ list(APPEND HAL_XBOX_SOURCE generic/memory.c generic/misc.c generic/pic.c - generic/reboot.c generic/sysinfo.c generic/usage.c generic/bios.c @@ -34,6 +33,7 @@ list(APPEND HAL_XBOX_SOURCE generic/timer.c xbox/part_xbox.c xbox/halinit_xbox.c + xbox/reboot.c up/pic.c) add_asm_files(lib_hal_xbox_asm ${HAL_XBOX_ASM_SOURCE}) diff --git a/hal/halx86/xbox/halxbox.h b/hal/halx86/xbox/halxbox.h index b27c6e31c23..5e4a5228800 100644 --- a/hal/halx86/xbox/halxbox.h +++ b/hal/halx86/xbox/halxbox.h @@ -1,11 +1,14 @@ /* - * COPYRIGHT: See COPYING in the top level directory * PROJECT: Xbox HAL - * FILE: hal/halx86/xbox/halxbox.h + * LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later) * PURPOSE: Xbox specific routines - * PROGRAMMER: Ge van Geldorp (gvg@reactos.com) - * UPDATE HISTORY: - * Created 2004/12/02 + * COPYRIGHT: Copyright 2004 Gé van Geldorp (gvg@reactos.com) + * Copyright 2019 Stanislav Motylkov (x86corez@gmail.com) + * + * REFERENCES: https://xboxdevwiki.net/SMBus + * https://github.com/XboxDev/cromwell/blob/master/drivers/pci/i2cio.c + * https://github.com/torvalds/linux/blob/master/drivers/i2c/busses/i2c-amd756.c + * https://github.com/xqemu/xqemu/blob/master/hw/xbox/smbus_xbox_smc.c */ #ifndef HALXBOX_H_INCLUDED @@ -14,6 +17,21 @@ #include #include +#define SMB_IO_BASE 0xC000 + +#define SMB_GLOBAL_STATUS (0 + SMB_IO_BASE) +#define SMB_GLOBAL_ENABLE (2 + SMB_IO_BASE) +#define SMB_HOST_ADDRESS (4 + SMB_IO_BASE) +#define SMB_HOST_DATA (6 + SMB_IO_BASE) +#define SMB_HOST_COMMAND (8 + SMB_IO_BASE) + +#define SMB_DEVICE_SMC_PIC16LC 0x10 + +#define SMC_REG_POWER 0x02 +#define SMC_REG_POWER_RESET 0x01 +#define SMC_REG_POWER_CYCLE 0x40 +#define SMC_REG_POWER_SHUTDOWN 0x80 + VOID HalpXboxInitPciBus(PBUS_HANDLER BusHandler); VOID HalpXboxInitPartIo(VOID); diff --git a/hal/halx86/xbox/reboot.c b/hal/halx86/xbox/reboot.c new file mode 100644 index 00000000000..1f2dec387c1 --- /dev/null +++ b/hal/halx86/xbox/reboot.c @@ -0,0 +1,115 @@ +/* + * PROJECT: Xbox HAL + * LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later) + * PURPOSE: Xbox reboot functions + * COPYRIGHT: Copyright 2004 Lehner Franz (franz@caos.at) + * Copyright 2019 Stanislav Motylkov (x86corez@gmail.com) + * + * REFERENCES: https://xboxdevwiki.net/SMBus + * https://github.com/XboxDev/cromwell/blob/master/drivers/pci/i2cio.c + * https://github.com/torvalds/linux/blob/master/drivers/i2c/busses/i2c-amd756.c + * https://github.com/xqemu/xqemu/blob/master/hw/xbox/smbus_xbox_smc.c + */ + +/* INCLUDES ******************************************************************/ + +#include "halxbox.h" + +#define NDEBUG +#include + +/* PRIVATE FUNCTIONS *********************************************************/ + +VOID +NTAPI +SMBusWriteByte(UCHAR Address, UCHAR Register, UCHAR Data) +{ + INT Retries = 50; + + /* Wait while bus is busy with any master traffic */ + while (READ_PORT_USHORT((PUSHORT)SMB_GLOBAL_STATUS) & 0x800) + { + NOTHING; + } + + while (Retries--) + { + UCHAR b; + + WRITE_PORT_UCHAR((PUCHAR)SMB_HOST_ADDRESS, Address << 1); + WRITE_PORT_UCHAR((PUCHAR)SMB_HOST_COMMAND, Register); + + WRITE_PORT_UCHAR((PUCHAR)SMB_HOST_DATA, Data); + + /* Clear down all preexisting errors */ + WRITE_PORT_USHORT((PUSHORT)SMB_GLOBAL_STATUS, READ_PORT_USHORT((PUSHORT)SMB_GLOBAL_STATUS)); + + /* Let I2C SMBus know we're sending a single byte here */ + WRITE_PORT_UCHAR((PUCHAR)SMB_GLOBAL_ENABLE, 0x1A); + + b = 0; + + while (!(b & 0x36)) + { + b = READ_PORT_UCHAR((PUCHAR)SMB_GLOBAL_STATUS); + } + + if (b & 0x10) + { + return; + } + + KeStallExecutionProcessor(1); + } +} + +VOID +DECLSPEC_NORETURN +NTAPI +HalpXboxPowerAction(IN UCHAR Action) +{ + SMBusWriteByte(SMB_DEVICE_SMC_PIC16LC, SMC_REG_POWER, Action); + + /* Halt the CPU */ + __halt(); + + while (TRUE); /* 'noreturn' function */ +} + +/* PUBLIC FUNCTIONS **********************************************************/ + +/* + * @implemented + */ +VOID +NTAPI +HalReturnToFirmware(IN FIRMWARE_REENTRY Action) +{ + /* Check what kind of action this is */ + switch (Action) + { + /* All recognized actions */ + case HalPowerDownRoutine: + { + /* Call the internal power function */ + HalpXboxPowerAction(SMC_REG_POWER_SHUTDOWN); + } + case HalRestartRoutine: + { + HalpXboxPowerAction(SMC_REG_POWER_CYCLE); + } + case HalRebootRoutine: + { + HalpXboxPowerAction(SMC_REG_POWER_RESET); + } + /* Anything else */ + default: + { + /* Print message and break */ + DbgPrint("HalReturnToFirmware(%d) called!\n", Action); + DbgBreakPoint(); + } + } +} + +/* EOF */