1d4ede03eSStanislav Motylkov /*
2d4ede03eSStanislav Motylkov * PROJECT: Xbox HAL
3d4ede03eSStanislav Motylkov * LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
4d4ede03eSStanislav Motylkov * PURPOSE: Xbox reboot functions
5d4ede03eSStanislav Motylkov * COPYRIGHT: Copyright 2004 Lehner Franz (franz@caos.at)
6d4ede03eSStanislav Motylkov * Copyright 2019 Stanislav Motylkov (x86corez@gmail.com)
7d4ede03eSStanislav Motylkov *
8d4ede03eSStanislav Motylkov * REFERENCES: https://xboxdevwiki.net/SMBus
9d4ede03eSStanislav Motylkov * https://github.com/XboxDev/cromwell/blob/master/drivers/pci/i2cio.c
10d4ede03eSStanislav Motylkov * https://github.com/torvalds/linux/blob/master/drivers/i2c/busses/i2c-amd756.c
11d4ede03eSStanislav Motylkov * https://github.com/xqemu/xqemu/blob/master/hw/xbox/smbus_xbox_smc.c
12d4ede03eSStanislav Motylkov */
13d4ede03eSStanislav Motylkov
14d4ede03eSStanislav Motylkov /* INCLUDES ******************************************************************/
15d4ede03eSStanislav Motylkov
16d4ede03eSStanislav Motylkov #include "halxbox.h"
17d4ede03eSStanislav Motylkov
18d4ede03eSStanislav Motylkov /* PRIVATE FUNCTIONS *********************************************************/
19d4ede03eSStanislav Motylkov
20*9ba1849aSHermès Bélusca-Maïto static VOID
SMBusWriteByte(_In_ UCHAR Address,_In_ UCHAR Register,_In_ UCHAR Data)21*9ba1849aSHermès Bélusca-Maïto SMBusWriteByte(
22*9ba1849aSHermès Bélusca-Maïto _In_ UCHAR Address,
23*9ba1849aSHermès Bélusca-Maïto _In_ UCHAR Register,
24*9ba1849aSHermès Bélusca-Maïto _In_ UCHAR Data)
25d4ede03eSStanislav Motylkov {
26d4ede03eSStanislav Motylkov INT Retries = 50;
27d4ede03eSStanislav Motylkov
28d4ede03eSStanislav Motylkov /* Wait while bus is busy with any master traffic */
29d4ede03eSStanislav Motylkov while (READ_PORT_USHORT((PUSHORT)SMB_GLOBAL_STATUS) & 0x800)
30d4ede03eSStanislav Motylkov {
31d4ede03eSStanislav Motylkov NOTHING;
32d4ede03eSStanislav Motylkov }
33d4ede03eSStanislav Motylkov
34d4ede03eSStanislav Motylkov while (Retries--)
35d4ede03eSStanislav Motylkov {
36d4ede03eSStanislav Motylkov UCHAR b;
37d4ede03eSStanislav Motylkov
38d4ede03eSStanislav Motylkov WRITE_PORT_UCHAR((PUCHAR)SMB_HOST_ADDRESS, Address << 1);
39d4ede03eSStanislav Motylkov WRITE_PORT_UCHAR((PUCHAR)SMB_HOST_COMMAND, Register);
40d4ede03eSStanislav Motylkov
41d4ede03eSStanislav Motylkov WRITE_PORT_UCHAR((PUCHAR)SMB_HOST_DATA, Data);
42d4ede03eSStanislav Motylkov
43d4ede03eSStanislav Motylkov /* Clear down all preexisting errors */
44d4ede03eSStanislav Motylkov WRITE_PORT_USHORT((PUSHORT)SMB_GLOBAL_STATUS, READ_PORT_USHORT((PUSHORT)SMB_GLOBAL_STATUS));
45d4ede03eSStanislav Motylkov
46d4ede03eSStanislav Motylkov /* Let I2C SMBus know we're sending a single byte here */
47d4ede03eSStanislav Motylkov WRITE_PORT_UCHAR((PUCHAR)SMB_GLOBAL_ENABLE, 0x1A);
48d4ede03eSStanislav Motylkov
49d4ede03eSStanislav Motylkov b = 0;
50d4ede03eSStanislav Motylkov
51d4ede03eSStanislav Motylkov while (!(b & 0x36))
52d4ede03eSStanislav Motylkov {
53d4ede03eSStanislav Motylkov b = READ_PORT_UCHAR((PUCHAR)SMB_GLOBAL_STATUS);
54d4ede03eSStanislav Motylkov }
55d4ede03eSStanislav Motylkov
56d4ede03eSStanislav Motylkov if (b & 0x10)
57d4ede03eSStanislav Motylkov {
58d4ede03eSStanislav Motylkov return;
59d4ede03eSStanislav Motylkov }
60d4ede03eSStanislav Motylkov
61d4ede03eSStanislav Motylkov KeStallExecutionProcessor(1);
62d4ede03eSStanislav Motylkov }
63d4ede03eSStanislav Motylkov }
64d4ede03eSStanislav Motylkov
65*9ba1849aSHermès Bélusca-Maïto static DECLSPEC_NORETURN
66d4ede03eSStanislav Motylkov VOID
HalpXboxPowerAction(_In_ UCHAR Action)67*9ba1849aSHermès Bélusca-Maïto HalpXboxPowerAction(
68*9ba1849aSHermès Bélusca-Maïto _In_ UCHAR Action)
69d4ede03eSStanislav Motylkov {
70*9ba1849aSHermès Bélusca-Maïto /* Disable interrupts */
71*9ba1849aSHermès Bélusca-Maïto _disable();
72*9ba1849aSHermès Bélusca-Maïto
73*9ba1849aSHermès Bélusca-Maïto /* Send the command */
74d4ede03eSStanislav Motylkov SMBusWriteByte(SMB_DEVICE_SMC_PIC16LC, SMC_REG_POWER, Action);
75d4ede03eSStanislav Motylkov
76d4ede03eSStanislav Motylkov /* Halt the CPU */
77d4ede03eSStanislav Motylkov __halt();
78*9ba1849aSHermès Bélusca-Maïto UNREACHABLE;
79*9ba1849aSHermès Bélusca-Maïto }
80d4ede03eSStanislav Motylkov
81*9ba1849aSHermès Bélusca-Maïto DECLSPEC_NORETURN
82*9ba1849aSHermès Bélusca-Maïto VOID
HalpReboot(VOID)83*9ba1849aSHermès Bélusca-Maïto HalpReboot(VOID)
84*9ba1849aSHermès Bélusca-Maïto {
85*9ba1849aSHermès Bélusca-Maïto HalpXboxPowerAction(SMC_REG_POWER_RESET);
86d4ede03eSStanislav Motylkov }
87d4ede03eSStanislav Motylkov
88d4ede03eSStanislav Motylkov /* PUBLIC FUNCTIONS **********************************************************/
89d4ede03eSStanislav Motylkov
90*9ba1849aSHermès Bélusca-Maïto #ifndef _MINIHAL_
91d4ede03eSStanislav Motylkov /*
92d4ede03eSStanislav Motylkov * @implemented
93d4ede03eSStanislav Motylkov */
94d4ede03eSStanislav Motylkov VOID
95d4ede03eSStanislav Motylkov NTAPI
HalReturnToFirmware(_In_ FIRMWARE_REENTRY Action)96*9ba1849aSHermès Bélusca-Maïto HalReturnToFirmware(
97*9ba1849aSHermès Bélusca-Maïto _In_ FIRMWARE_REENTRY Action)
98d4ede03eSStanislav Motylkov {
99d4ede03eSStanislav Motylkov /* Check what kind of action this is */
100d4ede03eSStanislav Motylkov switch (Action)
101d4ede03eSStanislav Motylkov {
102*9ba1849aSHermès Bélusca-Maïto /* All recognized actions: call the internal power function */
103*9ba1849aSHermès Bélusca-Maïto case HalHaltRoutine:
104d4ede03eSStanislav Motylkov case HalPowerDownRoutine:
105d4ede03eSStanislav Motylkov {
106d4ede03eSStanislav Motylkov HalpXboxPowerAction(SMC_REG_POWER_SHUTDOWN);
107d4ede03eSStanislav Motylkov }
108d4ede03eSStanislav Motylkov case HalRestartRoutine:
109d4ede03eSStanislav Motylkov {
110d4ede03eSStanislav Motylkov HalpXboxPowerAction(SMC_REG_POWER_CYCLE);
111d4ede03eSStanislav Motylkov }
112d4ede03eSStanislav Motylkov case HalRebootRoutine:
113d4ede03eSStanislav Motylkov {
114d4ede03eSStanislav Motylkov HalpXboxPowerAction(SMC_REG_POWER_RESET);
115d4ede03eSStanislav Motylkov }
116*9ba1849aSHermès Bélusca-Maïto
117d4ede03eSStanislav Motylkov /* Anything else */
118d4ede03eSStanislav Motylkov default:
119d4ede03eSStanislav Motylkov {
120d4ede03eSStanislav Motylkov /* Print message and break */
121d4ede03eSStanislav Motylkov DbgPrint("HalReturnToFirmware(%d) called!\n", Action);
122d4ede03eSStanislav Motylkov DbgBreakPoint();
123d4ede03eSStanislav Motylkov }
124d4ede03eSStanislav Motylkov }
125d4ede03eSStanislav Motylkov }
126*9ba1849aSHermès Bélusca-Maïto #endif // _MINIHAL_
127d4ede03eSStanislav Motylkov
128d4ede03eSStanislav Motylkov /* EOF */
129