From f15a572bef3ab8545b7ef3ca62592bb4308e4ec6 Mon Sep 17 00:00:00 2001 From: PatrickvL Date: Thu, 14 Dec 2017 03:24:16 +0100 Subject: [PATCH] Fleshed out SMC (PIC16LC) device --- src/CxbxKrnl/EmuKrnlHal.cpp | 12 ++--- src/CxbxKrnl/PIC16LCDevice.cpp | 83 ++++++++++++++++++++++++++++++++-- src/CxbxKrnl/PIC16LCDevice.h | 46 +++++++++++++++++++ 3 files changed, 129 insertions(+), 12 deletions(-) diff --git a/src/CxbxKrnl/EmuKrnlHal.cpp b/src/CxbxKrnl/EmuKrnlHal.cpp index cfc238204..3daea8fff 100644 --- a/src/CxbxKrnl/EmuKrnlHal.cpp +++ b/src/CxbxKrnl/EmuKrnlHal.cpp @@ -53,6 +53,7 @@ namespace xboxkrnl #include "EmuX86.h" // HalReadWritePciSpace needs this #include "SMBus.h" // For g_SMBus #include "EmuEEPROM.h" // For EEPROM +#include "PIC16LCDevice.h" // For SMC_COMMAND_SCRATCH #include "EmuShared.h" #include "EmuFile.h" // For FindNtSymbolicLinkObjectByDriveLetter @@ -729,14 +730,9 @@ XBSYSAPI EXPORTNUM(366) xboxkrnl::NTSTATUS NTAPI xboxkrnl::HalWriteSMCScratchReg { LOG_FUNC_ONE_ARG(ScratchRegister); - LOG_UNIMPLEMENTED(); +// HalpSMCScratchRegister = ScratchRegister; -/* TODO - HalpSMCScratchRegister = ScratchRegister; + NTSTATUS Res = HalWriteSMBusValue(SMBUS_SMC_SLAVE_ADDRESS, SMC_COMMAND_SCRATCH, /*WordFlag:*/false, ScratchRegister); - // TODO : Is this the way we need to set the value? - return HalWriteSMBusValue(SMBUS_SMC_ADDRESS, SMC_COMMAND_SCRATCH, WordFlag: False, ScratchRegister); -*/ - - RETURN(S_OK); + RETURN(Res); } diff --git a/src/CxbxKrnl/PIC16LCDevice.cpp b/src/CxbxKrnl/PIC16LCDevice.cpp index 55bc9a258..aeb2bbc88 100644 --- a/src/CxbxKrnl/PIC16LCDevice.cpp +++ b/src/CxbxKrnl/PIC16LCDevice.cpp @@ -38,9 +38,25 @@ #include "PIC16LCDevice.h" // For PIC16LCDevice +void SetLEDSequence(uint8_t LEDSequence) +{ + // TODO : Move to best suited location & implement + // See http://xboxdevwiki.net/PIC#The_LED +} + +// See http://xboxdevwiki.net/PIC#PIC_version_string +const char *PICVersion_Retail_1_0 = "P01"; +const char *PICVersion_Retail_1_1 = "P05"; +const char *PICVersion_Debug_Kit = "DXB"; + void PIC16LCDevice::Init() { - // TODO + m_PICVersion = (char*)PICVersion_Retail_1_1; // TODO : Configurable selection + + buffer[SMC_COMMAND_VERSION] = m_PICVersion[2]; + buffer[SMC_COMMAND_AV_PACK] = 2; // VGA, see http://xboxdevwiki.net/PIC#The_AV_Pack + buffer[SMC_COMMAND_LED_SEQUENCE] = 0x0F; // solid green + buffer[SMC_COMMAND_SCRATCH] = 0; // http://xboxdevwiki.net/PIC#Scratch_register_values } void PIC16LCDevice::Reset() @@ -60,7 +76,40 @@ uint8_t PIC16LCDevice::ReceiveByte() uint8_t PIC16LCDevice::ReadByte(uint8_t command) { - return 0; // TODO + switch (command) { + case SMC_COMMAND_VERSION: // 0x01 PIC version string + // See https://github.com/bji/libmame/blob/master/src/mame/drivers/chihiro.c#L977 + if (buffer[0] == m_PICVersion[0]) + buffer[0] = m_PICVersion[1]; + else + if (buffer[0] == m_PICVersion[1]) + buffer[0] = m_PICVersion[2]; + else + buffer[0] = m_PICVersion[0]; + break; + //0x03 tray state + //#define SMC_COMMAND_AV_PACK 0x04 // A / V Pack state + //0x09 CPU temperature(°C) + //0x0A board temperature(°C) + case 0x0F: // reads scratch register written with 0x0E + return buffer[0x0E]; + //0x10 current fan speed(0~50) + //0x11 interrupt reason + //0x18 reading this reg locks up xbox in "overheated" state + //#define SMC_COMMAND_SCRATCH 0x1B // scratch register for the original kernel + case SMC_COMMAND_CHALLENGE_1C: // random number for boot challenge + case SMC_COMMAND_CHALLENGE_1D: // random number for boot challenge + case SMC_COMMAND_CHALLENGE_1E: // random number for boot challenge + case SMC_COMMAND_CHALLENGE_1F: // random number for boot challenge + if (m_PICVersion == PICVersion_Debug_Kit) + // See http://xboxdevwiki.net/PIC#PIC_Challenge_.28regs_0x1C.7E0x21.29 + return 0; + + break; + // case SMC_COMMAND_...: TODO + } + + return buffer[command]; } uint16_t PIC16LCDevice::ReadWord(uint8_t command) @@ -80,12 +129,38 @@ void PIC16LCDevice::SendByte(uint8_t data) void PIC16LCDevice::WriteByte(uint8_t command, uint8_t value) { - // TODO + switch (command) { + case SMC_COMMAND_VERSION: // 0x01 PIC version string counter reset + if (value == 0) // Note : MAME Xbox/Chihiro driver doesn't check for zero + buffer[0] = m_PICVersion[2]; + return; + //0x02 reset and power off control + //0x05 power fan mode(0 = automatic; 1 = custom speed from reg 0x06) + //0x06 power fan speed(0..~50) + case SMC_COMMAND_LED_MODE: // 0x07 LED mode(0 = automatic; 1 = custom sequence from reg 0x08) + switch (value) { + case 0: SetLEDSequence(0x0F); return; // Automatic; Solid green? + case 1: SetLEDSequence(buffer[SMC_COMMAND_LED_SEQUENCE]); // Custom sequence + } + return; + // #define SMC_COMMAND_LED_SEQUENCE 0x08 // LED flashing sequence + //0x0C tray eject(0 = eject; 1 = load) + //0x0E another scratch register ? seems like an error code. + //0x19 reset on eject(0 = enable; 1 = disable) + //0x1A interrupt enable(write 0x01 to enable; can't disable once enabled) + //0x1B scratch register for the original kernel + //0x20 response to PIC challenge(written first) + //0x21 response to PIC challenge(written second) + } + + buffer[command] = value; } void PIC16LCDevice::WriteWord(uint8_t command, uint16_t value) { - // TODO + // TODO : Is this needed and/or acceptable? + WriteByte(command, value >> 8); + WriteByte(command + 1, value & 0xFF); } void PIC16LCDevice::WriteBlock(uint8_t command, uint8_t* data, int length) diff --git a/src/CxbxKrnl/PIC16LCDevice.h b/src/CxbxKrnl/PIC16LCDevice.h index e1c57843d..9ed8ee424 100644 --- a/src/CxbxKrnl/PIC16LCDevice.h +++ b/src/CxbxKrnl/PIC16LCDevice.h @@ -37,8 +37,51 @@ #include "SMDevice.h" +// This https://upload.wikimedia.org/wikipedia/commons/9/94/Xbox-Motherboard-FR.jpg shows : +// PIC16LC63A-04/SO +// (M) 0123857 +// +// Producer : http://www.microchip.com/wwwproducts/en/en010145 +// Datasheet : http://ww1.microchip.com/downloads/en/DeviceDoc/30605D.pdf + #define SMBUS_SMC_SLAVE_ADDRESS 0x20 // = Write; Read = 0x21 +// Reading: + +// From https://web.archive.org/web/20100617022549/http://www.xbox-linux.org/wiki/PIC : +// Command Description +#define SMC_COMMAND_VERSION 0x01 // PIC version string +//0x03 tray state +#define SMC_COMMAND_AV_PACK 0x04 // A / V Pack state +//0x09 CPU temperature(°C) +//0x0A board temperature(°C) +//0x0F reads scratch register written with 0x0E +//0x10 current fan speed(0~50) +//0x11 interrupt reason +//0x18 reading this reg locks up xbox in "overheated" state +#define SMC_COMMAND_SCRATCH 0x1B // scratch register for the original kernel +#define SMC_COMMAND_CHALLENGE_1C 0x1C // random number for boot challenge +#define SMC_COMMAND_CHALLENGE_1D 0x1D // random number for boot challenge +#define SMC_COMMAND_CHALLENGE_1E 0x1E // random number for boot challenge +#define SMC_COMMAND_CHALLENGE_1F 0x1F // random number for boot challenge +// +// Writing: +// +//Command Description +//0x01 PIC version string counter reset +//0x02 reset and power off control +//0x05 power fan mode(0 = automatic; 1 = custom speed from reg 0x06) +//0x06 power fan speed(0..~50) +#define SMC_COMMAND_LED_MODE 0x07 // LED mode(0 = automatic; 1 = custom sequence from reg 0x08) +#define SMC_COMMAND_LED_SEQUENCE 0x08 // LED flashing sequence +//0x0C tray eject(0 = eject; 1 = load) +//0x0E another scratch register ? seems like an error code. +//0x19 reset on eject(0 = enable; 1 = disable) +//0x1A interrupt enable(write 0x01 to enable; can't disable once enabled) +//0x1B scratch register for the original kernel +//0x20 response to PIC challenge(written first) +//0x21 response to PIC challenge(written second) + class PIC16LCDevice : public SMDevice { public: // SMDevice functions @@ -55,6 +98,9 @@ public: void WriteByte(uint8_t command, uint8_t value); void WriteWord(uint8_t command, uint16_t value); void WriteBlock(uint8_t command, uint8_t* data, int length); +private: + char* m_PICVersion; + uint8_t buffer[256] = {}; }; extern PIC16LCDevice* gPIC16LC;