[HALXBOX] Implement shutdown, reboot, and power cycle routines
authorStanislav Motylkov <x86corez@gmail.com>
Fri, 4 Oct 2019 19:04:51 +0000 (22:04 +0300)
committerHermès BÉLUSCA - MAÏTO <hermes.belusca-maito@reactos.org>
Sat, 5 Oct 2019 15:42:28 +0000 (17:42 +0200)
CORE-16216

hal/halx86/xbox.cmake
hal/halx86/xbox/halxbox.h
hal/halx86/xbox/reboot.c [new file with mode: 0644]

index a259df7..c3604e7 100644 (file)
@@ -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})
index b27c6e3..5e4a522 100644 (file)
@@ -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
 #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);
 
diff --git a/hal/halx86/xbox/reboot.c b/hal/halx86/xbox/reboot.c
new file mode 100644 (file)
index 0000000..1f2dec3
--- /dev/null
@@ -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 <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 */