/*
- * 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
#include <hal.h>
#include <ntdddisk.h>
+#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);
--- /dev/null
+/*
+ * 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 <debug.h>
+
+/* 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 */