Fleshed out SMC (PIC16LC) device

This commit is contained in:
PatrickvL 2017-12-14 03:24:16 +01:00 committed by Luke Usher
parent b44b433259
commit f15a572bef
3 changed files with 129 additions and 12 deletions

View File

@ -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);
}

View File

@ -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)

View File

@ -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;