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