From 69edf0ad610062b9c1609155246f8317d52ce456 Mon Sep 17 00:00:00 2001 From: Ivan Rusanov Date: Tue, 17 Nov 2020 02:24:48 +0200 Subject: [PATCH 1/7] Move the common modules to a separate project --- PowerTableMonitor.cs | 4 +- SMUMonitor.cs | 2 +- SettingsForm.Designer.cs | 2 +- SettingsForm.cs | 147 +++++----- Utils/BiosACPIFunction.cs | 22 -- Utils/BiosMemController.cs | 130 -------- Utils/NativeMethods.cs | 55 ---- Utils/Ols.cs | 435 --------------------------- Utils/Ops.cs | 588 ------------------------------------- Utils/PowerTable.cs | 281 ------------------ Utils/SMU.cs | 355 ---------------------- Utils/SystemInfo.cs | 109 ------- Utils/WMI.cs | 170 ----------- ZenStatesDebugTool.csproj | 12 +- ZenStatesDebugTool.sln | 9 + 15 files changed, 92 insertions(+), 2229 deletions(-) delete mode 100644 Utils/BiosACPIFunction.cs delete mode 100644 Utils/BiosMemController.cs delete mode 100644 Utils/NativeMethods.cs delete mode 100644 Utils/Ols.cs delete mode 100644 Utils/Ops.cs delete mode 100644 Utils/PowerTable.cs delete mode 100644 Utils/SMU.cs delete mode 100644 Utils/SystemInfo.cs delete mode 100644 Utils/WMI.cs diff --git a/PowerTableMonitor.cs b/PowerTableMonitor.cs index 2bf2b6e..e3e3d19 100644 --- a/PowerTableMonitor.cs +++ b/PowerTableMonitor.cs @@ -6,7 +6,7 @@ using System.Linq; using System.Text; using System.Windows.Forms; -using ZenStates; +using ZenStates.Core; namespace ZenStatesDebugTool { @@ -39,7 +39,7 @@ private void ReadPowerConfig() for (int i = 0; i < table.Length; ++i) { - NativeMethods.GetPhysLong(dramPtr + (i * 0x4), out data); + InteropMethods.GetPhysLong(dramPtr + (i * 0x4), out data); table[i] = data; } diff --git a/SMUMonitor.cs b/SMUMonitor.cs index 5721919..f825b20 100644 --- a/SMUMonitor.cs +++ b/SMUMonitor.cs @@ -2,7 +2,7 @@ using System.ComponentModel; using System.Threading; using System.Windows.Forms; -using ZenStates; +using ZenStates.Core; namespace ZenStatesDebugTool { diff --git a/SettingsForm.Designer.cs b/SettingsForm.Designer.cs index 565cb7b..89b9edc 100644 --- a/SettingsForm.Designer.cs +++ b/SettingsForm.Designer.cs @@ -18,7 +18,7 @@ protected override void Dispose(bool disposing) { if (disposing && (components != null)) { - OPS.Dispose(); + m.Dispose(); hMutexPci.Dispose(); components.Dispose(); } diff --git a/SettingsForm.cs b/SettingsForm.cs index 64d8e35..ba44f4f 100644 --- a/SettingsForm.cs +++ b/SettingsForm.cs @@ -1,6 +1,5 @@ using Microsoft.VisualBasic.Devices; using Newtonsoft.Json; -using OpenLibSys; using System; using System.Collections.Generic; using System.ComponentModel; @@ -10,7 +9,7 @@ using System.Reflection; using System.Threading; using System.Windows.Forms; -using ZenStates; +using ZenStates.Core; using ZenStatesDebugTool.Properties; namespace ZenStatesDebugTool @@ -20,7 +19,7 @@ public partial class SettingsForm : Form //private static readonly int Threads = Convert.ToInt32(Environment.GetEnvironmentVariable("NUMBER_OF_PROCESSORS")); private BackgroundWorker backgroundWorker1; private NUMAUtil _numaUtil; - private readonly Ops OPS = new Ops(); + private readonly Zen m; private SystemInfo SI; List matches; private int _coreCount; @@ -65,7 +64,7 @@ public SettingsForm() try { - OPS.CheckOlsStatus(); + m = new Zen(); InitForm(); } catch (ApplicationException ex) @@ -86,33 +85,33 @@ private static void ExitApplication() private void InitSystemInfo() { - var cpufamily = OPS.GetCpuFamily(); - if (cpufamily != SMU.CpuFamily.FAMILY_17H && cpufamily != SMU.CpuFamily.FAMILY_19H) + Ops.CPUInfo cpuinfo = m.Ops.GetCpuInfo(); + + if (cpuinfo.family != SMU.CpuFamily.FAMILY_17H && cpuinfo.family != SMU.CpuFamily.FAMILY_19H) { MessageBox.Show("CPU is not supported.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); ExitApplication(); } - int[] coreCount = OPS.GetCoreCount(); SI = new SystemInfo { - CpuId = OPS.GetCpuId(), - CpuName = OPS.GetCpuName(), - NodesPerProcessor = OPS.GetCpuNodes(), - PackageType = OPS.GetPackageType(), - PatchLevel = OPS.GetPatchLevel(), - SmuVersion = OPS.Smu.Version, - FusedCoreCount = coreCount[0], - Threads = coreCount[1], - CCDCount = OPS.GetCCDCount(), - CodeName = $"{OPS.CpuType}", - SMT = OPS.GetThreadsPerCore() > 1, + CpuId = m.Ops.GetCpuId(), + CpuName = m.Ops.GetCpuName(), + NodesPerProcessor = m.Ops.GetCpuNodes(), + PackageType = m.Ops.GetPackageType(), + PatchLevel = m.Ops.GetPatchLevel(), + SmuVersion = m.Ops.Smu.Version, + FusedCoreCount = (int)cpuinfo.cores, + Threads = (int)cpuinfo.logicalCores, + CCDCount = (int)cpuinfo.ccds, + CCXCount = (int)cpuinfo.ccxs, + NumCoresInCCX = (int)cpuinfo.coresPerCcx, + CodeName = $"{m.Ops.CpuType}", + SMT = (int)cpuinfo.threadsPerCore > 1, + Model = cpuinfo.model, + ExtendedModel = cpuinfo.extModel, }; - SI.Model = (SI.CpuId & 0xff) >> 4; - SI.ExtendedModel = SI.Model + ((SI.CpuId >> 12) & 0xF0); - - ManagementObjectSearcher searcher = new ManagementObjectSearcher("SELECT * FROM Win32_BaseBoard"); foreach (ManagementObject obj in searcher.Get()) { @@ -131,9 +130,9 @@ private void InitSystemInfo() private void ResetSmuAddresses() { - OPS.Smu.SMU_ADDR_MSG = SMU_ADDR_MSG; - OPS.Smu.SMU_ADDR_RSP = SMU_ADDR_RSP; - OPS.Smu.SMU_ADDR_ARG = SMU_ADDR_ARG; + m.Ops.Smu.SMU_ADDR_MSG = SMU_ADDR_MSG; + m.Ops.Smu.SMU_ADDR_RSP = SMU_ADDR_RSP; + m.Ops.Smu.SMU_ADDR_ARG = SMU_ADDR_ARG; textBoxCMDAddress.Text = $"0x{Convert.ToString(SMU_ADDR_MSG, 16).ToUpper()}"; textBoxRSPAddress.Text = $"0x{Convert.ToString(SMU_ADDR_RSP, 16).ToUpper()}"; @@ -153,7 +152,7 @@ private void DisplaySystemInfo() biosInfoLabel.Text = SI.BiosVersion; smuInfoLabel.Text = SI.GetSmuVersionString(); firmwareInfoLabel.Text = $"{SI.PatchLevel:X8}"; - cpuIdLabel.Text = $"{SI.GetCpuIdString()} ({OPS.CpuType})"; + cpuIdLabel.Text = $"{SI.GetCpuIdString()} ({m.Ops.CpuType})"; configInfoLabel.Text = $"{SI.CCDCount} CCD / {SI.CCXCount} CCX / {SI.PhysicalCoreCount} physical cores"; } @@ -161,7 +160,7 @@ private void InitForm() { InitSystemInfo(); - if (OPS.Smu.Version == 0) + if (m.Ops.Smu.Version == 0) { MessageBox.Show("Error getting SMU version!\n" + "Default SMU addresses are not responding to commands.", @@ -170,9 +169,9 @@ private void InitForm() } // Cache default addresses - SMU_ADDR_MSG = OPS.Smu.SMU_ADDR_MSG; - SMU_ADDR_RSP = OPS.Smu.SMU_ADDR_RSP; - SMU_ADDR_ARG = OPS.Smu.SMU_ADDR_ARG; + SMU_ADDR_MSG = m.Ops.Smu.SMU_ADDR_MSG; + SMU_ADDR_RSP = m.Ops.Smu.SMU_ADDR_RSP; + SMU_ADDR_ARG = m.Ops.Smu.SMU_ADDR_ARG; ResetSmuAddresses(); DisplaySystemInfo(); @@ -196,7 +195,7 @@ private void InitForm() comboBoxACF.SelectedIndex = index; comboBoxSCF.SelectedIndex = index; - var prochotEnabled = OPS.IsProchotEnabled(); + var prochotEnabled = m.Ops.IsProchotEnabled(); checkBoxPROCHOT.Checked = prochotEnabled; //checkBoxPROCHOT.Enabled = prochotEnabled; //buttonApplyPROCHOT.Enabled = prochotEnabled; @@ -204,14 +203,14 @@ private void InitForm() ToolTip toolTip = new ToolTip(); toolTip.SetToolTip(checkBoxPROCHOT, "Disables temperature throttling. Can be useful on extreme cooling."); - SetStatusText($"{OPS.CpuType}. Ready."); + SetStatusText($"{m.Ops.CpuType}. Ready."); } // TODO: Detect OC Mode and return PState freq if on auto private double GetCurrentMulti() { uint eax = default, edx = default; - if (OPS.Ols.Rdmsr(0xC0010293, ref eax, ref edx) != 1) + if (m.Ols.Rdmsr(0xC0010293, ref eax, ref edx) != 1) { SetStatusText($@"Error getting current frequency!"); return 0; @@ -236,7 +235,7 @@ private void PopulateCCDList(ComboBox.ObjectCollection l) private void ApplyFrequencyAllCoreSetting(int frequency) { - if (OPS.SendSmuCommand(OPS.Smu.SMU_MSG_SetOverclockFrequencyAllCores, Convert.ToUInt32(frequency))) + if (m.Ops.SendSmuCommand(m.Ops.Smu.SMU_MSG_SetOverclockFrequencyAllCores, Convert.ToUInt32(frequency))) SetStatusText(string.Format("Set frequency to {0} MHz!", (object)frequency)); else HandleError("Error setting frequency!"); @@ -244,7 +243,7 @@ private void ApplyFrequencyAllCoreSetting(int frequency) private void ApplyFrequencySingleCoreSetting(CoreListItem i, int frequency) { - if (OPS.SendSmuCommand(OPS.Smu.SMU_MSG_SetOverclockFrequencyPerCore, Convert.ToUInt32(((i.CCD << 4 | i.CCX % 2 & 15) << 4 | i.CORE % 4 & 15) << 20 | frequency & 0xFFFFF))) + if (m.Ops.SendSmuCommand(m.Ops.Smu.SMU_MSG_SetOverclockFrequencyPerCore, Convert.ToUInt32(((i.CCD << 4 | i.CCX % 2 & 15) << 4 | i.CORE % 4 & 15) << 20 | frequency & 0xFFFFF))) SetStatusText(string.Format("Set core {0} frequency to {1} MHz!", (object)i, (object)frequency)); else HandleError("Error setting frequency!"); @@ -252,7 +251,7 @@ private void ApplyFrequencySingleCoreSetting(CoreListItem i, int frequency) private void EnableOCMode(bool prochotEnabled = true) { - if (OPS.SendSmuCommand(OPS.Smu.SMU_MSG_EnableOcMode, prochotEnabled ? 0U : 0x1000000)) + if (m.Ops.SendSmuCommand(m.Ops.Smu.SMU_MSG_EnableOcMode, prochotEnabled ? 0U : 0x1000000)) SetStatusText(prochotEnabled ? "PROCHOT enabled." : "PROCHOT disabled."); else HandleError("Error setting OC Mode!"); @@ -260,7 +259,7 @@ private void EnableOCMode(bool prochotEnabled = true) private void DisableOCMode() { - if (OPS.SendSmuCommand(OPS.Smu.SMU_MSG_DisableOcMode, 0U)) + if (m.Ops.SendSmuCommand(m.Ops.Smu.SMU_MSG_DisableOcMode, 0U)) SetStatusText(string.Format("Set OK!")); else HandleError("Error disabling OC Mode!"); @@ -388,9 +387,9 @@ private void ApplySettings() TryConvertToUint(textBoxARGAddress.Text, out uint addrArg); TryConvertToUint(textBoxCMD.Text, out uint command); - OPS.Smu.SMU_ADDR_MSG = addrMsg; - OPS.Smu.SMU_ADDR_RSP = addrRsp; - OPS.Smu.SMU_ADDR_ARG = addrArg; + m.Ops.Smu.SMU_ADDR_MSG = addrMsg; + m.Ops.Smu.SMU_ADDR_RSP = addrRsp; + m.Ops.Smu.SMU_ADDR_ARG = addrArg; for (var i = 0; i < userArgs.Length; i++) { @@ -402,12 +401,12 @@ private void ApplySettings() } - Console.WriteLine("MSG Address: 0x" + Convert.ToString(OPS.Smu.SMU_ADDR_MSG, 16).ToUpper()); - Console.WriteLine("RSP Address: 0x" + Convert.ToString(OPS.Smu.SMU_ADDR_RSP, 16).ToUpper()); - Console.WriteLine("ARG0 Address: 0x" + Convert.ToString(OPS.Smu.SMU_ADDR_ARG, 16).ToUpper()); + Console.WriteLine("MSG Address: 0x" + Convert.ToString(m.Ops.Smu.SMU_ADDR_MSG, 16).ToUpper()); + Console.WriteLine("RSP Address: 0x" + Convert.ToString(m.Ops.Smu.SMU_ADDR_RSP, 16).ToUpper()); + Console.WriteLine("ARG0 Address: 0x" + Convert.ToString(m.Ops.Smu.SMU_ADDR_ARG, 16).ToUpper()); Console.WriteLine("ARG0 : 0x" + Convert.ToString(args[0], 16).ToUpper()); - SMU.Status status = OPS.SendSmuCommand(command, ref args); + SMU.Status status = m.Ops.SendSmuCommand(command, ref args); if (status == SMU.Status.OK) { @@ -444,7 +443,7 @@ private void HandlePciReadBtnClick() SetButtonsState(false); TryConvertToUint(textBoxPciAddress.Text, out uint address); - uint data = OPS.ReadDword(address); + uint data = m.Ops.ReadDword(address); textBoxPciValue.Text = $"0x{data:X8}"; @@ -469,7 +468,7 @@ private void HandlePciWriteBtnClick() TryConvertToUint(textBoxPciAddress.Text, out uint address); TryConvertToUint(textBoxPciValue.Text, out uint data); - if (OPS.SmuWriteReg(address, data)) + if (m.Ops.SmuWriteReg(address, data)) SetStatusText("Write OK."); else SetStatusText(Resources.Error); @@ -510,11 +509,11 @@ private SMU.Status TrySettings(uint msgAddr, uint rspAddr, uint argAddress, uint uint[] args = new uint[6]; args[0] = value; - OPS.Smu.SMU_ADDR_MSG = msgAddr; - OPS.Smu.SMU_ADDR_RSP = rspAddr; - OPS.Smu.SMU_ADDR_ARG = argAddress; + m.Ops.Smu.SMU_ADDR_MSG = msgAddr; + m.Ops.Smu.SMU_ADDR_RSP = rspAddr; + m.Ops.Smu.SMU_ADDR_ARG = argAddress; - return OPS.SendSmuCommand(cmd, ref args); + return m.Ops.SendSmuCommand(cmd, ref args); } private void ScanSmuRange(uint start, uint end, int step, byte offset) @@ -526,13 +525,13 @@ private void ScanSmuRange(uint start, uint end, int step, byte offset) uint smuRspAddress = start + offset; uint smuArgAddress = 0xF; - if (OPS.ReadDword(start) != 0xFFFFFFFF) + if (m.Ops.ReadDword(start) != 0xFFFFFFFF) { // Check if CMD-RSP pair returns correct status, while using a placeholder ARG address - if (TrySettings(start, smuRspAddress, smuArgAddress, OPS.Smu.SMU_MSG_TestMessage, 0x0) == SMU.Status.OK) + if (TrySettings(start, smuRspAddress, smuArgAddress, m.Ops.Smu.SMU_MSG_TestMessage, 0x0) == SMU.Status.OK) { // Send smu version command, so the corresponding ARG0 address changes its value - TrySettings(start, smuRspAddress, smuArgAddress, OPS.Smu.SMU_MSG_GetSmuVersion, 0x0); + TrySettings(start, smuRspAddress, smuArgAddress, m.Ops.Smu.SMU_MSG_GetSmuVersion, 0x0); bool match = false; smuArgAddress = smuRspAddress + 4; @@ -541,14 +540,14 @@ private void ScanSmuRange(uint start, uint end, int step, byte offset) while ((smuArgAddress <= end) && !match) { // Check if smu version major is in range - var currentRegValue = (OPS.ReadDword(smuArgAddress) & 0x00FF0000) >> 16; + var currentRegValue = (m.Ops.ReadDword(smuArgAddress) & 0x00FF0000) >> 16; Console.WriteLine($"REG: 0x{smuArgAddress:X8} Value: 0x{currentRegValue:X8}"); if (currentRegValue > 1 && currentRegValue <= 99) { // Send test message with an argument, using the potential ARG0 address var argValue = (uint)matches.Count * 2 + 99; - TrySettings(start, smuRspAddress, smuArgAddress, OPS.Smu.SMU_MSG_TestMessage, argValue); - currentRegValue = OPS.ReadDword(smuArgAddress); + TrySettings(start, smuRspAddress, smuArgAddress, m.Ops.Smu.SMU_MSG_TestMessage, argValue); + currentRegValue = m.Ops.ReadDword(smuArgAddress); Console.WriteLine($"REG: 0x{smuArgAddress:X8} Value: 0x{currentRegValue:X8}"); // Check the address for expected value (argument + 1) @@ -615,7 +614,7 @@ private void BackgroundWorkerTrySettings_DoWork(object sender, DoWorkEventArgs e SetStatusText("Scanning SMU addresses, please wait..."); })); - switch (OPS.CpuType) + switch (m.Ops.CpuType) { case SMU.CPUType.RavenRidge: case SMU.CPUType.Picasso: @@ -802,7 +801,7 @@ private void btnPstateRead_Click(object sender, EventArgs e) { uint eax = default, edx = default; var pstateId = pstateIdBox.SelectedIndex; - if (OPS.Ols.Rdmsr(Convert.ToUInt32(Convert.ToInt64(0xC0010064) + pstateId), ref eax, ref edx) != 1) + if (m.Ols.Rdmsr(Convert.ToUInt32(Convert.ToInt64(0xC0010064) + pstateId), ref eax, ref edx) != 1) { SetStatusText($@"Error reading PState {pstateId}!"); return; @@ -855,7 +854,7 @@ private void btnPstateWrite_Click(object sender, EventArgs e) uint CpuDfsId = 0x0; uint CpuFid = 0x0; - if (OPS.Ols.Rdmsr(Convert.ToUInt32(Convert.ToInt64(0xC0010064) + pstateId), ref eax, ref edx) != 1) + if (m.Ols.Rdmsr(Convert.ToUInt32(Convert.ToInt64(0xC0010064) + pstateId), ref eax, ref edx) != 1) { SetStatusText($@"Error reading PState {pstateId}!"); return; @@ -886,10 +885,10 @@ public bool ApplyTscWorkaround() { uint eax = 0, edx = 0; - if (OPS.Ols.Rdmsr(0xC0010015, ref eax, ref edx) != -1) + if (m.Ols.Rdmsr(0xC0010015, ref eax, ref edx) != -1) { eax |= 0x200000; - return OPS.WriteMsr(0xC0010015, eax, edx); + return m.Ops.WriteMsr(0xC0010015, eax, edx); } SetStatusText($@"Error applying TSC fix!"); @@ -902,7 +901,7 @@ private bool WritePstateClick(int pstateId, uint eax, uint edx, int numanode = 0 if (!ApplyTscWorkaround()) return false; - if (!OPS.WriteMsr(Convert.ToUInt32(Convert.ToInt64(0xC0010064) + pstateId), eax, edx)) + if (!m.Ops.WriteMsr(Convert.ToUInt32(Convert.ToInt64(0xC0010064) + pstateId), eax, edx)) { SetStatusText($@"Error writing PState {pstateId}!"); return false; @@ -933,7 +932,7 @@ private void PciScan_DoWork(object sender, DoWorkEventArgs e) while (startReg <= endReg) { - var data = OPS.ReadDword(startReg); + var data = m.Ops.ReadDword(startReg); result += $"0x{startReg:X8}: 0x{data:X8}" + Environment.NewLine; startReg += 4; } @@ -988,7 +987,7 @@ private void ButtonApplyPROCHOT_Click(object sender, EventArgs e) DisableOCMode(); } EnableOCMode(checkBoxPROCHOT.Checked); - if (!checkBoxPROCHOT.Checked && OPS.IsProchotEnabled()) + if (!checkBoxPROCHOT.Checked && m.Ops.IsProchotEnabled()) { checkBoxPROCHOT.Checked = true; HandleError($@"Error, PROCHOT could not be disabled!"); @@ -1017,7 +1016,7 @@ private void ReadMsr_Task(object sender, DoWorkEventArgs e) while (startReg <= endReg) { uint eax = default, edx = default; - if (OPS.Ols.Rdmsr(startReg, ref eax, ref edx) == 1) + if (m.Ols.Rdmsr(startReg, ref eax, ref edx) == 1) { result += $"0x{startReg:X8}: 0x{edx:X8} 0x{eax:X8}" + Environment.NewLine; } @@ -1041,7 +1040,7 @@ private void ButtonMsrRead_Click(object sender, EventArgs e) { TryConvertToUint(textBoxMsrAddress.Text, out uint msr); uint eax = default, edx = default; - if (OPS.Ols.Rdmsr(msr, ref eax, ref edx) == 1) + if (m.Ols.Rdmsr(msr, ref eax, ref edx) == 1) { textBoxMsrEdx.Text = $"0x{edx:X8}"; textBoxMsrEax.Text = $"0x{eax:X8}"; @@ -1054,7 +1053,7 @@ private void ButtonMsrWrite_Click(object sender, EventArgs e) TryConvertToUint(textBoxMsrEax.Text, out uint eax); TryConvertToUint(textBoxMsrAddress.Text, out uint msr); - if (!OPS.WriteMsr(msr, eax, edx)) + if (!m.Ops.WriteMsr(msr, eax, edx)) { HandleError($@"Error writing MSR {textBoxMsrAddress.Text}!"); return; @@ -1081,23 +1080,23 @@ private void ReadCPUID_Task(object sender, DoWorkEventArgs e) uint LFuncStd = 0, LFuncExt = 0; uint eax = 0, ebx = 0, ecx = 0, edx = 0; - if (OPS.Ols.Cpuid(0x00000000, ref eax, ref ebx, ref ecx, ref edx) == 1) + if (m.Ols.Cpuid(0x00000000, ref eax, ref ebx, ref ecx, ref edx) == 1) LFuncStd = eax; - if (OPS.Ols.Cpuid(0x80000000, ref eax, ref ebx, ref ecx, ref edx) == 1) + if (m.Ols.Cpuid(0x80000000, ref eax, ref ebx, ref ecx, ref edx) == 1) LFuncExt = eax - 0x80000000; for (uint i = 0; i <= LFuncStd; ++i) { var index = 0x00000000 + i; - OPS.Ols.Cpuid(index, ref eax, ref ebx, ref ecx, ref edx); + m.Ols.Cpuid(index, ref eax, ref ebx, ref ecx, ref edx); result += $"0x{index:X8}: 0x{eax:X8} 0x{ebx:X8} 0x{ecx:X8} 0x{edx:X8}" + Environment.NewLine; } for (uint i = 0; i <= LFuncExt; ++i) { var index = 0x80000000 + i; - OPS.Ols.Cpuid(index, ref eax, ref ebx, ref ecx, ref edx); + m.Ols.Cpuid(index, ref eax, ref ebx, ref ecx, ref edx); result += $"0x{index:X8}: 0x{eax:X8} 0x{ebx:X8} 0x{ecx:X8} 0x{edx:X8}" + Environment.NewLine; } @@ -1117,7 +1116,7 @@ private void ButtonCPUIDRead_Click(object sender, EventArgs e) { TryConvertToUint(textBoxCPUIDAddress.Text, out uint index); uint eax = 0, ebx = 0, ecx = 0, edx = 0; - if (OPS.Ols.Cpuid(index, ref eax, ref ebx, ref ecx, ref edx) == 1) + if (m.Ols.Cpuid(index, ref eax, ref ebx, ref ecx, ref edx) == 1) { textBoxCPUIDeax.Text = $"0x{eax:X8}"; textBoxCPUIDebx.Text = $"0x{ebx:X8}"; @@ -1133,7 +1132,7 @@ private void ButtonCPUIDScan_Click(object sender, EventArgs e) private void ButtonPMTable_Click(object sender, EventArgs e) { - new Thread(() => new PowerTableMonitor(OPS).ShowDialog()).Start(); + new Thread(() => new PowerTableMonitor(m.Ops).ShowDialog()).Start(); } private void ButtonSMUMonitor_Click(object sender, EventArgs e) @@ -1142,7 +1141,7 @@ private void ButtonSMUMonitor_Click(object sender, EventArgs e) TryConvertToUint(textBoxRSPAddress.Text, out uint addrRsp); TryConvertToUint(textBoxARGAddress.Text, out uint addrArg); - new Thread(() => new SMUMonitor(OPS, addrMsg, addrArg, addrRsp).ShowDialog()).Start(); + new Thread(() => new SMUMonitor(m.Ops, addrMsg, addrArg, addrRsp).ShowDialog()).Start(); } } } diff --git a/Utils/BiosACPIFunction.cs b/Utils/BiosACPIFunction.cs deleted file mode 100644 index b65ce9f..0000000 --- a/Utils/BiosACPIFunction.cs +++ /dev/null @@ -1,22 +0,0 @@ -using System.Collections; - -namespace ZenStates -{ - public class BiosACPIFunction : IEnumerable - { - public string IDString; - public uint ID; - - public BiosACPIFunction(string idString, uint id) - { - IDString = idString; - ID = id; - } - - public IEnumerator GetEnumerator() - { - return ((IEnumerable)IDString).GetEnumerator(); - } - } - -} diff --git a/Utils/BiosMemController.cs b/Utils/BiosMemController.cs deleted file mode 100644 index 495b2b0..0000000 --- a/Utils/BiosMemController.cs +++ /dev/null @@ -1,130 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Runtime.InteropServices; - -namespace ZenStates -{ - public class BiosMemController - { - private void ParseTable(byte[] table) - { - GCHandle handle = GCHandle.Alloc(table, GCHandleType.Pinned); - try - { - Config = (Resistances)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), - typeof(Resistances)); - } - finally - { - handle.Free(); - } - } - - public BiosMemController() { } - - public BiosMemController(byte[] table) - { - ParseTable(table); - } - - private static readonly Dictionary ProcOdtDict = new Dictionary - { - { 1, "480.0 Ω" }, - { 2, "240.0 Ω" }, - { 3, "160.0 Ω" }, - { 8, "120.0 Ω" }, - { 9, "96.0 Ω" }, - { 10, "80.0 Ω" }, - { 11, "68.6 Ω" }, - { 24, "60.0 Ω" }, - { 25, "53.3 Ω" }, - { 26, "48.0 Ω" }, - { 27, "43.6 Ω" }, - { 56, "40.0 Ω" }, - { 57, "36.9 Ω" }, - { 58, "34.3 Ω" }, - { 59, "32.0 Ω" }, - { 62, "30.0 Ω" }, - { 63, "28.2 Ω" } - }; - - private static readonly Dictionary DriveStrengthDict = new Dictionary - { - { 0, "120.0 Ω" }, - { 1, "60.0 Ω" }, - { 3, "40.0 Ω" }, - { 7, "30.0 Ω" }, - { 15, "24.0 Ω" }, - { 31, "20.0 Ω" } - }; - - private static readonly Dictionary RttDict = new Dictionary - { - { 0, "Disabled" }, - { 1, "RZQ/4" }, - { 2, "RZQ/2" }, - { 3, "RZQ/6" }, - { 4, "RZQ/1" }, - { 5, "RZQ/5" }, - { 6, "RZQ/3" }, - { 7, "RZQ/7" } - }; - - private static readonly Dictionary RttWrDict = new Dictionary - { - { 0, "Off" }, - { 1, "RZQ/2" }, - { 2, "RZQ/1" }, - { 3, "Hi-Z" }, - { 4, "RZQ/3" }, - }; - - private static string GetByKey(Dictionary dict, int key) - { - if (!dict.TryGetValue(key, out string output)) - { - return "N/A"; - } - return output; - } - - [Serializable] - [StructLayout(LayoutKind.Explicit)] - public struct Resistances - { - [FieldOffset(33)] public byte ProcODT; - [FieldOffset(65)] public byte RttNom; - [FieldOffset(66)] public byte RttWr; - [FieldOffset(67)] public byte RttPark; - [FieldOffset(86)] public byte AddrCmdSetup; - [FieldOffset(87)] public byte CsOdtSetup; - [FieldOffset(88)] public byte CkeSetup; - [FieldOffset(89)] public byte ClkDrvStren; - [FieldOffset(90)] public byte AddrCmdDrvStren; - [FieldOffset(91)] public byte CsOdtCmdDrvStren; - [FieldOffset(92)] public byte CkeDrvStren; - }; - - byte[] table; - public byte[] Table - { - get => table; - set - { - if (value != null) - { - table = value; - ParseTable(value); - } - } - } - - public Resistances Config { get; set; } - - public string GetProcODTString(int key) => GetByKey(ProcOdtDict, key); - public string GetDrvStrenString(int key) => GetByKey(DriveStrengthDict, key); - public string GetRttString(int key) => GetByKey(RttDict, key); - public string GetRttWrString(int key) => GetByKey(RttWrDict, key); - public string GetSetupString(byte value) => $"{value / 32}/{value % 32}"; - } -} diff --git a/Utils/NativeMethods.cs b/Utils/NativeMethods.cs deleted file mode 100644 index 8c633a1..0000000 --- a/Utils/NativeMethods.cs +++ /dev/null @@ -1,55 +0,0 @@ -using System; -using System.Runtime.InteropServices; - -namespace ZenStates -{ - // this class just wraps some Win32 stuff that we're going to use - internal static class NativeMethods - { - public const int HWND_BROADCAST = 0xffff; - public static readonly int WM_SHOWME = RegisterWindowMessage("WM_SHOWME"); - - [DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Unicode)] - [return: MarshalAs(UnmanagedType.Bool)] - public static extern bool PostMessage(IntPtr hwnd, int msg, IntPtr wparam, IntPtr lparam); - - [DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Unicode)] - public static extern int RegisterWindowMessage(string lpString); - - [DllImport("psapi.dll")] - public static extern int EmptyWorkingSet(IntPtr hwProc); - - [DllImport("inpout32.dll", EntryPoint = "GetPhysLong", CallingConvention = CallingConvention.StdCall)] - [return: MarshalAs(UnmanagedType.Bool)] - public static extern bool GetPhysLong32(UIntPtr memAddress, out uint data); - - [DllImport("inpoutx64.dll", EntryPoint = "GetPhysLong", CallingConvention = CallingConvention.StdCall)] - [return: MarshalAs(UnmanagedType.Bool)] - public static extern bool GetPhysLong64(UIntPtr memAddress, out uint data); - - public static bool GetPhysLong(UIntPtr memAddress, out uint data) - { - if (Environment.Is64BitProcess) - return GetPhysLong64(memAddress, out data); - - return GetPhysLong32(memAddress, out data); - } - - [DllImport("inpout32.dll", EntryPoint = "IsInpOutDriverOpen", CallingConvention = CallingConvention.StdCall)] - [return: MarshalAs(UnmanagedType.Bool)] - public static extern bool IsInpOutDriverOpen32(); - - [DllImport("inpoutx64.dll", EntryPoint = "IsInpOutDriverOpen", CallingConvention = CallingConvention.StdCall)] - [return: MarshalAs(UnmanagedType.Bool)] - public static extern bool IsInpOutDriverOpen64(); - - public static bool IsInpOutDriverOpen() - { - if (Environment.Is64BitProcess) - return IsInpOutDriverOpen64(); - - return IsInpOutDriverOpen32(); - } - - } -} diff --git a/Utils/Ols.cs b/Utils/Ols.cs deleted file mode 100644 index 94f8921..0000000 --- a/Utils/Ols.cs +++ /dev/null @@ -1,435 +0,0 @@ -//----------------------------------------------------------------------------- -// Author : hiyohiyo -// Mail : hiyohiyo@crystalmark.info -// Web : http://openlibsys.org/ -// License : The modified BSD license -// -// Copyright 2007-2009 OpenLibSys.org. All rights reserved. -//----------------------------------------------------------------------------- -// This is support library for WinRing0 1.3.x. - -using System; -using System.Runtime.InteropServices; - -namespace OpenLibSys -{ - public class Ols : IDisposable - { - const string dllNameX64 = "WinRing0x64.dll"; - const string dllName = "WinRing0.dll"; - - // for this support library - public enum Status - { - NO_ERROR = 0, - DLL_NOT_FOUND = 1, - DLL_INCORRECT_VERSION = 2, - DLL_INITIALIZE_ERROR = 3, - } - - // for WinRing0 - public enum OlsDllStatus - { - OLS_DLL_NO_ERROR = 0, - OLS_DLL_UNSUPPORTED_PLATFORM = 1, - OLS_DLL_DRIVER_NOT_LOADED = 2, - OLS_DLL_DRIVER_NOT_FOUND = 3, - OLS_DLL_DRIVER_UNLOADED = 4, - OLS_DLL_DRIVER_NOT_LOADED_ON_NETWORK = 5, - OLS_DLL_UNKNOWN_ERROR = 9 - } - - // for WinRing0 - public enum OlsDriverType - { - OLS_DRIVER_TYPE_UNKNOWN = 0, - OLS_DRIVER_TYPE_WIN_9X = 1, - OLS_DRIVER_TYPE_WIN_NT = 2, - OLS_DRIVER_TYPE_WIN_NT4 = 3, // Obsolete - OLS_DRIVER_TYPE_WIN_NT_X64 = 4, - OLS_DRIVER_TYPE_WIN_NT_IA64 = 5 - } - - // for WinRing0 - public enum OlsErrorPci : uint - { - OLS_ERROR_PCI_BUS_NOT_EXIST = 0xE0000001, - OLS_ERROR_PCI_NO_DEVICE = 0xE0000002, - OLS_ERROR_PCI_WRITE_CONFIG = 0xE0000003, - OLS_ERROR_PCI_READ_CONFIG = 0xE0000004 - } - - // Bus Number, Device Number and Function Number to PCI Device Address - public uint PciBusDevFunc(uint bus, uint dev, uint func) - { - return ((bus&0xFF)<<8) | ((dev&0x1F)<<3) | (func&7); - } - - // PCI Device Address to Bus Number - public uint PciGetBus(uint address) - { - return ((address>>8) & 0xFF); - } - - // PCI Device Address to Device Number - public uint PciGetDev(uint address) - { - return ((address>>3) & 0x1F); - } - - // PCI Device Address to Function Number - public uint PciGetFunc(uint address) - { - return (address&7); - } - - [DllImport("kernel32")] - public extern static IntPtr LoadLibrary(string lpFileName); - - - [DllImport("kernel32", SetLastError = true)] - private static extern bool FreeLibrary(IntPtr hModule); - - [DllImport("kernel32", CharSet = CharSet.Ansi, SetLastError = true, ExactSpelling = false)] - private static extern IntPtr GetProcAddress(IntPtr hModule, [MarshalAs(UnmanagedType.LPStr)] string lpProcName); - - private IntPtr module = IntPtr.Zero; - private uint status = (uint)Status.NO_ERROR; - - public Ols() - { - string fileName; - - if (System.IntPtr.Size == 8) - { - fileName = dllNameX64; - } - else - { - fileName = dllName; - } - - module = Ols.LoadLibrary(fileName); - if (module == IntPtr.Zero) - { - status = (uint)Status.DLL_NOT_FOUND; - } - else - { - - GetDllStatus = (_GetDllStatus)GetDelegate("GetDllStatus", typeof(_GetDllStatus)); - GetDllVersion = (_GetDllVersion)GetDelegate("GetDllVersion", typeof(_GetDllVersion)); - GetDriverVersion = (_GetDriverVersion)GetDelegate("GetDriverVersion", typeof(_GetDriverVersion)); - GetDriverType = (_GetDriverType)GetDelegate("GetDriverType", typeof(_GetDriverType)); - - InitializeOls = (_InitializeOls)GetDelegate("InitializeOls", typeof(_InitializeOls)); - DeinitializeOls = (_DeinitializeOls)GetDelegate("DeinitializeOls", typeof(_DeinitializeOls)); - - IsCpuid = (_IsCpuid)GetDelegate("IsCpuid", typeof(_IsCpuid)); - IsMsr = (_IsMsr)GetDelegate("IsMsr", typeof(_IsMsr)); - IsTsc = (_IsTsc)GetDelegate("IsTsc", typeof(_IsTsc)); - Hlt = (_Hlt)GetDelegate("Hlt", typeof(_Hlt)); - HltTx = (_HltTx)GetDelegate("HltTx", typeof(_HltTx)); - HltPx = (_HltPx)GetDelegate("HltPx", typeof(_HltPx)); - Rdmsr = (_Rdmsr)GetDelegate("Rdmsr", typeof(_Rdmsr)); - RdmsrTx = (_RdmsrTx)GetDelegate("RdmsrTx", typeof(_RdmsrTx)); - RdmsrPx = (_RdmsrPx)GetDelegate("RdmsrPx", typeof(_RdmsrPx)); - Wrmsr = (_Wrmsr)GetDelegate("Wrmsr", typeof(_Wrmsr)); - WrmsrTx = (_WrmsrTx)GetDelegate("WrmsrTx", typeof(_WrmsrTx)); - WrmsrPx = (_WrmsrPx)GetDelegate("WrmsrPx", typeof(_WrmsrPx)); - Rdpmc = (_Rdpmc)GetDelegate("Rdpmc", typeof(_Rdpmc)); - RdpmcTx = (_RdpmcTx)GetDelegate("RdpmcTx", typeof(_RdpmcTx)); - RdpmcPx = (_RdpmcPx)GetDelegate("RdpmcPx", typeof(_RdpmcPx)); - Cpuid = (_Cpuid)GetDelegate("Cpuid", typeof(_Cpuid)); - CpuidTx = (_CpuidTx)GetDelegate("CpuidTx", typeof(_CpuidTx)); - CpuidPx = (_CpuidPx)GetDelegate("CpuidPx", typeof(_CpuidPx)); - Rdtsc = (_Rdtsc)GetDelegate("Rdtsc", typeof(_Rdtsc)); - RdtscTx = (_RdtscTx)GetDelegate("RdtscTx", typeof(_RdtscTx)); - RdtscPx = (_RdtscPx)GetDelegate("RdtscPx", typeof(_RdtscPx)); - - ReadIoPortByte = (_ReadIoPortByte)GetDelegate("ReadIoPortByte", typeof(_ReadIoPortByte)); - ReadIoPortWord = (_ReadIoPortWord)GetDelegate("ReadIoPortWord", typeof(_ReadIoPortWord)); - ReadIoPortDword = (_ReadIoPortDword)GetDelegate("ReadIoPortDword", typeof(_ReadIoPortDword)); - ReadIoPortByteEx = (_ReadIoPortByteEx)GetDelegate("ReadIoPortByteEx", typeof(_ReadIoPortByteEx)); - ReadIoPortWordEx = (_ReadIoPortWordEx)GetDelegate("ReadIoPortWordEx", typeof(_ReadIoPortWordEx)); - ReadIoPortDwordEx = (_ReadIoPortDwordEx)GetDelegate("ReadIoPortDwordEx", typeof(_ReadIoPortDwordEx)); - - WriteIoPortByte = (_WriteIoPortByte)GetDelegate("WriteIoPortByte", typeof(_WriteIoPortByte)); - WriteIoPortWord = (_WriteIoPortWord)GetDelegate("WriteIoPortWord", typeof(_WriteIoPortWord)); - WriteIoPortDword = (_WriteIoPortDword)GetDelegate("WriteIoPortDword", typeof(_WriteIoPortDword)); - WriteIoPortByteEx = (_WriteIoPortByteEx)GetDelegate("WriteIoPortByteEx", typeof(_WriteIoPortByteEx)); - WriteIoPortWordEx = (_WriteIoPortWordEx)GetDelegate("WriteIoPortWordEx", typeof(_WriteIoPortWordEx)); - WriteIoPortDwordEx = (_WriteIoPortDwordEx)GetDelegate("WriteIoPortDwordEx", typeof(_WriteIoPortDwordEx)); - - SetPciMaxBusIndex = (_SetPciMaxBusIndex)GetDelegate("SetPciMaxBusIndex", typeof(_SetPciMaxBusIndex)); - ReadPciConfigByte = (_ReadPciConfigByte)GetDelegate("ReadPciConfigByte", typeof(_ReadPciConfigByte)); - ReadPciConfigWord = (_ReadPciConfigWord)GetDelegate("ReadPciConfigWord", typeof(_ReadPciConfigWord)); - ReadPciConfigDword = (_ReadPciConfigDword)GetDelegate("ReadPciConfigDword", typeof(_ReadPciConfigDword)); - ReadPciConfigByteEx = (_ReadPciConfigByteEx)GetDelegate("ReadPciConfigByteEx", typeof(_ReadPciConfigByteEx)); - ReadPciConfigWordEx = (_ReadPciConfigWordEx)GetDelegate("ReadPciConfigWordEx", typeof(_ReadPciConfigWordEx)); - ReadPciConfigDwordEx = (_ReadPciConfigDwordEx)GetDelegate("ReadPciConfigDwordEx", typeof(_ReadPciConfigDwordEx)); - WritePciConfigByte = (_WritePciConfigByte)GetDelegate("WritePciConfigByte", typeof(_WritePciConfigByte)); - WritePciConfigWord = (_WritePciConfigWord)GetDelegate("WritePciConfigWord", typeof(_WritePciConfigWord)); - WritePciConfigDword = (_WritePciConfigDword)GetDelegate("WritePciConfigDword", typeof(_WritePciConfigDword)); - WritePciConfigByteEx = (_WritePciConfigByteEx)GetDelegate("WritePciConfigByteEx", typeof(_WritePciConfigByteEx)); - WritePciConfigWordEx = (_WritePciConfigWordEx)GetDelegate("WritePciConfigWordEx", typeof(_WritePciConfigWordEx)); - WritePciConfigDwordEx = (_WritePciConfigDwordEx)GetDelegate("WritePciConfigDwordEx", typeof(_WritePciConfigDwordEx)); - FindPciDeviceById = (_FindPciDeviceById)GetDelegate("FindPciDeviceById", typeof(_FindPciDeviceById)); - FindPciDeviceByClass = (_FindPciDeviceByClass)GetDelegate("FindPciDeviceByClass", typeof(_FindPciDeviceByClass)); - - /* - ReadDmiMemory = (_ReadDmiMemory)GetDelegate("ReadDmiMemory", typeof(_ReadDmiMemory)); - ReadPhysicalMemory = (_ReadPhysicalMemory)GetDelegate("ReadPhysicalMemory", typeof(_ReadPhysicalMemory)); - WritePhysicalMemory = (_WritePhysicalMemory)GetDelegate("WritePhysicalMemory", typeof(_WritePhysicalMemory)); - */ - - if (! ( - GetDllStatus != null - && GetDllVersion != null - && GetDriverVersion != null - && GetDriverType != null - && InitializeOls != null - && DeinitializeOls != null - && IsCpuid != null - && IsMsr != null - && IsTsc != null - && Hlt != null - && HltTx != null - && HltPx != null - && Rdmsr != null - && RdmsrTx != null - && RdmsrPx != null - && Wrmsr != null - && WrmsrTx != null - && WrmsrPx != null - && Rdpmc != null - && RdpmcTx != null - && RdpmcPx != null - && Cpuid != null - && CpuidTx != null - && CpuidPx != null - && Rdtsc != null - && RdtscTx != null - && RdtscPx != null - && ReadIoPortByte != null - && ReadIoPortWord != null - && ReadIoPortDword != null - && ReadIoPortByteEx != null - && ReadIoPortWordEx != null - && ReadIoPortDwordEx != null - && WriteIoPortByte != null - && WriteIoPortWord != null - && WriteIoPortDword != null - && WriteIoPortByteEx != null - && WriteIoPortWordEx != null - && WriteIoPortDwordEx != null - && SetPciMaxBusIndex != null - && ReadPciConfigByte != null - && ReadPciConfigWord != null - && ReadPciConfigDword != null - && ReadPciConfigByteEx != null - && ReadPciConfigWordEx != null - && ReadPciConfigDwordEx != null - && WritePciConfigByte != null - && WritePciConfigWord != null - && WritePciConfigDword != null - && WritePciConfigByteEx != null - && WritePciConfigWordEx != null - && WritePciConfigDwordEx != null - && FindPciDeviceById != null - && FindPciDeviceByClass != null - /*&& ReadDmiMemory != null - && ReadPhysicalMemory != null - && WritePhysicalMemory != null - */ - )) - { - status = (uint)Status.DLL_INCORRECT_VERSION; - } - - if (InitializeOls() == 0) - { - status = (uint)Status.DLL_INITIALIZE_ERROR; - } - } - } - - public uint GetStatus() - { - return status; - } - - public void Dispose() - { - if (module != IntPtr.Zero) - { - DeinitializeOls(); - Ols.FreeLibrary(module); - module = IntPtr.Zero; - } - } - - public Delegate GetDelegate(string procName, Type delegateType) - { - IntPtr ptr = GetProcAddress(module, procName); - if (ptr != IntPtr.Zero) - { - Delegate d = Marshal.GetDelegateForFunctionPointer(ptr, delegateType); - return d; - } - - int result = Marshal.GetHRForLastWin32Error(); - throw Marshal.GetExceptionForHR(result); - } - - //----------------------------------------------------------------------------- - // DLL Information - //----------------------------------------------------------------------------- - public delegate uint _GetDllStatus(); - public delegate uint _GetDllVersion(ref byte major, ref byte minor, ref byte revision, ref byte release); - public delegate uint _GetDriverVersion(ref byte major, ref byte minor, ref byte revision, ref byte release); - public delegate uint _GetDriverType(); - - public delegate int _InitializeOls(); - public delegate void _DeinitializeOls(); - - public _GetDllStatus GetDllStatus = null; - public _GetDriverType GetDriverType = null; - public _GetDllVersion GetDllVersion = null; - public _GetDriverVersion GetDriverVersion = null; - - public _InitializeOls InitializeOls = null; - public _DeinitializeOls DeinitializeOls = null; - - //----------------------------------------------------------------------------- - // CPU - //----------------------------------------------------------------------------- - public delegate int _IsCpuid(); - public delegate int _IsMsr(); - public delegate int _IsTsc(); - public delegate int _Hlt(); - public delegate int _HltTx(UIntPtr threadAffinityMask); - public delegate int _HltPx(UIntPtr processAffinityMask); - public delegate int _Rdmsr(uint index, ref uint eax, ref uint edx); - public delegate int _RdmsrTx(uint index, ref uint eax, ref uint edx, UIntPtr threadAffinityMask); - public delegate int _RdmsrPx(uint index, ref uint eax, ref uint edx, UIntPtr processAffinityMask); - public delegate int _Wrmsr(uint index, uint eax, uint edx); - public delegate int _WrmsrTx(uint index, uint eax, uint edx, UIntPtr threadAffinityMask); - public delegate int _WrmsrPx(uint index, uint eax, uint edx, UIntPtr processAffinityMask); - public delegate int _Rdpmc(uint index, ref uint eax, ref uint edx); - public delegate int _RdpmcTx(uint index, ref uint eax, ref uint edx, UIntPtr threadAffinityMask); - public delegate int _RdpmcPx(uint index, ref uint eax, ref uint edx, UIntPtr processAffinityMask); - public delegate int _Cpuid(uint index, ref uint eax, ref uint ebx, ref uint ecx, ref uint edx); - public delegate int _CpuidTx(uint index, ref uint eax, ref uint ebx, ref uint ecx, ref uint edx, UIntPtr threadAffinityMask); - public delegate int _CpuidPx(uint index, ref uint eax, ref uint ebx, ref uint ecx, ref uint edx, UIntPtr processAffinityMask); - public delegate int _Rdtsc(ref uint eax, ref uint edx); - public delegate int _RdtscTx(ref uint eax, ref uint edx, UIntPtr threadAffinityMask); - public delegate int _RdtscPx(ref uint eax, ref uint edx, UIntPtr processAffinityMask); - - public _IsCpuid IsCpuid = null; - public _IsMsr IsMsr = null; - public _IsTsc IsTsc = null; - public _Hlt Hlt = null; - public _HltTx HltTx = null; - public _HltPx HltPx = null; - public _Rdmsr Rdmsr = null; - public _RdmsrTx RdmsrTx = null; - public _RdmsrPx RdmsrPx = null; - public _Wrmsr Wrmsr = null; - public _WrmsrTx WrmsrTx = null; - public _WrmsrPx WrmsrPx = null; - public _Rdpmc Rdpmc = null; - public _RdpmcTx RdpmcTx = null; - public _RdpmcPx RdpmcPx = null; - public _Cpuid Cpuid = null; - public _CpuidTx CpuidTx = null; - public _CpuidPx CpuidPx = null; - public _Rdtsc Rdtsc = null; - public _RdtscTx RdtscTx = null; - public _RdtscPx RdtscPx = null; - - //----------------------------------------------------------------------------- - // I/O - //----------------------------------------------------------------------------- - public delegate byte _ReadIoPortByte(ushort port); - public delegate ushort _ReadIoPortWord(ushort port); - public delegate uint _ReadIoPortDword(ushort port); - public _ReadIoPortByte ReadIoPortByte; - public _ReadIoPortWord ReadIoPortWord; - public _ReadIoPortDword ReadIoPortDword; - - public delegate int _ReadIoPortByteEx(ushort port, ref byte value); - public delegate int _ReadIoPortWordEx(ushort port, ref ushort value); - public delegate int _ReadIoPortDwordEx(ushort port, ref uint value); - public _ReadIoPortByteEx ReadIoPortByteEx; - public _ReadIoPortWordEx ReadIoPortWordEx; - public _ReadIoPortDwordEx ReadIoPortDwordEx; - - public delegate void _WriteIoPortByte(ushort port, byte value); - public delegate void _WriteIoPortWord(ushort port, ushort value); - public delegate void _WriteIoPortDword(ushort port, uint value); - public _WriteIoPortByte WriteIoPortByte; - public _WriteIoPortWord WriteIoPortWord; - public _WriteIoPortDword WriteIoPortDword; - - public delegate int _WriteIoPortByteEx(ushort port, byte value); - public delegate int _WriteIoPortWordEx(ushort port, ushort value); - public delegate int _WriteIoPortDwordEx(ushort port, uint value); - public _WriteIoPortByteEx WriteIoPortByteEx; - public _WriteIoPortWordEx WriteIoPortWordEx; - public _WriteIoPortDwordEx WriteIoPortDwordEx; - - //----------------------------------------------------------------------------- - // PCI - //----------------------------------------------------------------------------- - public delegate void _SetPciMaxBusIndex(byte max); - public _SetPciMaxBusIndex SetPciMaxBusIndex; - - public delegate byte _ReadPciConfigByte(uint pciAddress, byte regAddress); - public delegate ushort _ReadPciConfigWord(uint pciAddress, byte regAddress); - public delegate uint _ReadPciConfigDword(uint pciAddress, byte regAddress); - public _ReadPciConfigByte ReadPciConfigByte; - public _ReadPciConfigWord ReadPciConfigWord; - public _ReadPciConfigDword ReadPciConfigDword; - - public delegate int _ReadPciConfigByteEx(uint pciAddress, uint regAddress, ref byte value); - public delegate int _ReadPciConfigWordEx(uint pciAddress, uint regAddress, ref ushort value); - public delegate int _ReadPciConfigDwordEx(uint pciAddress, uint regAddress, ref uint value); - public _ReadPciConfigByteEx ReadPciConfigByteEx; - public _ReadPciConfigWordEx ReadPciConfigWordEx; - public _ReadPciConfigDwordEx ReadPciConfigDwordEx; - - public delegate void _WritePciConfigByte(uint pciAddress, byte regAddress, byte value); - public delegate void _WritePciConfigWord(uint pciAddress, byte regAddress, ushort value); - public delegate void _WritePciConfigDword(uint pciAddress, byte regAddress, uint value); - public _WritePciConfigByte WritePciConfigByte; - public _WritePciConfigWord WritePciConfigWord; - public _WritePciConfigDword WritePciConfigDword; - - public delegate int _WritePciConfigByteEx(uint pciAddress, uint regAddress, byte value); - public delegate int _WritePciConfigWordEx(uint pciAddress, uint regAddress, ushort value); - public delegate int _WritePciConfigDwordEx(uint pciAddress, uint regAddress, uint value); - public _WritePciConfigByteEx WritePciConfigByteEx; - public _WritePciConfigWordEx WritePciConfigWordEx; - public _WritePciConfigDwordEx WritePciConfigDwordEx; - - public delegate uint _FindPciDeviceById(ushort vendorId, ushort deviceId, byte index); - public delegate uint _FindPciDeviceByClass(byte baseClass, byte subClass, byte programIf, byte index); - public _FindPciDeviceById FindPciDeviceById; - public _FindPciDeviceByClass FindPciDeviceByClass; - - //----------------------------------------------------------------------------- - // Physical Memory (unsafe) - //----------------------------------------------------------------------------- - - /*public unsafe delegate uint _ReadDmiMemory(byte* buffer, uint count, uint unitSize); - public _ReadDmiMemory ReadDmiMemory; - - public unsafe delegate uint _ReadPhysicalMemory(UIntPtr address, byte* buffer, uint count, uint unitSize); - public unsafe delegate uint _WritePhysicalMemory(UIntPtr address, byte* buffer, uint count, uint unitSize); - - public _ReadPhysicalMemory ReadPhysicalMemory; - public _WritePhysicalMemory WritePhysicalMemory; - */ - } -} diff --git a/Utils/Ops.cs b/Utils/Ops.cs deleted file mode 100644 index 4bbe8fc..0000000 --- a/Utils/Ops.cs +++ /dev/null @@ -1,588 +0,0 @@ -using OpenLibSys; -using System; -using System.Threading; - -namespace ZenStates -{ - public class Ops : IDisposable - { - private static Mutex amdSmuMutex; - private const ushort SMU_TIMEOUT = 8192; - private readonly int Threads; - - public Ops() - { - amdSmuMutex = new Mutex(); - - Ols = new Ols(); - CheckOlsStatus(); - CpuType = GetCPUType(GetPackageType()); - Smu = GetMaintainedSettings.GetByType(CpuType); - Smu.Version = GetSmuVersion(); - Threads = GetCoreCount()[1]; - - //if (!SendTestMessage()) - // throw new ApplicationException("SMU is not responding"); - } - - public SMU Smu { get; } - public Ols Ols { get; } - public SMU.CPUType CpuType { get; } - - public void CheckOlsStatus() - { - // Check support library status - switch (Ols.GetStatus()) - { - case (uint)Ols.Status.NO_ERROR: - break; - case (uint)Ols.Status.DLL_NOT_FOUND: - throw new ApplicationException("WinRing DLL_NOT_FOUND"); - case (uint)Ols.Status.DLL_INCORRECT_VERSION: - throw new ApplicationException("WinRing DLL_INCORRECT_VERSION"); - case (uint)Ols.Status.DLL_INITIALIZE_ERROR: - throw new ApplicationException("WinRing DLL_INITIALIZE_ERROR"); - } - - // Check WinRing0 status - switch (Ols.GetDllStatus()) - { - case (uint)Ols.OlsDllStatus.OLS_DLL_NO_ERROR: - break; - case (uint)Ols.OlsDllStatus.OLS_DLL_DRIVER_NOT_LOADED: - throw new ApplicationException("WinRing OLS_DRIVER_NOT_LOADED"); - case (uint)Ols.OlsDllStatus.OLS_DLL_UNSUPPORTED_PLATFORM: - throw new ApplicationException("WinRing OLS_UNSUPPORTED_PLATFORM"); - case (uint)Ols.OlsDllStatus.OLS_DLL_DRIVER_NOT_FOUND: - throw new ApplicationException("WinRing OLS_DLL_DRIVER_NOT_FOUND"); - case (uint)Ols.OlsDllStatus.OLS_DLL_DRIVER_UNLOADED: - throw new ApplicationException("WinRing OLS_DLL_DRIVER_UNLOADED"); - case (uint)Ols.OlsDllStatus.OLS_DLL_DRIVER_NOT_LOADED_ON_NETWORK: - throw new ApplicationException("WinRing DRIVER_NOT_LOADED_ON_NETWORK"); - case (uint)Ols.OlsDllStatus.OLS_DLL_UNKNOWN_ERROR: - throw new ApplicationException("WinRing OLS_DLL_UNKNOWN_ERROR"); - } - } - - public uint SetBits(uint val, int offset, int n, uint newValue) - { - return val & ~(((1U << n) - 1) << offset) | (newValue << offset); - } - - public uint GetBits(uint val, int offset, int n) - { - return (val >> offset) & ~(~0U << n); - } - - public bool SmuWriteReg(uint addr, uint data) - { - bool res = false; - amdSmuMutex.WaitOne(5000); - if (Ols.WritePciConfigDwordEx(Smu.SMU_PCI_ADDR, Smu.SMU_OFFSET_ADDR, addr) == 1) - res = (Ols.WritePciConfigDwordEx(Smu.SMU_PCI_ADDR, Smu.SMU_OFFSET_DATA, data) == 1); - amdSmuMutex.ReleaseMutex(); - return res; - } - - public bool SmuReadReg(uint addr, ref uint data) - { - bool res = false; - amdSmuMutex.WaitOne(5000); - if (Ols.WritePciConfigDwordEx(Smu.SMU_PCI_ADDR, Smu.SMU_OFFSET_ADDR, addr) == 1) - res = (Ols.ReadPciConfigDwordEx(Smu.SMU_PCI_ADDR, Smu.SMU_OFFSET_DATA, ref data) == 1); - amdSmuMutex.ReleaseMutex(); - return res; - } - - public bool SmuWaitDone() - { - bool res; - ushort timeout = SMU_TIMEOUT; - uint data = 0; - - do - res = SmuReadReg(Smu.SMU_ADDR_RSP, ref data); - while ((!res || data != 1) && --timeout > 0); - - if (timeout == 0 || data != 1) res = false; - - return res; - } - - public SMU.Status SendSmuCommand(uint msg, ref uint[] args) - { - ushort timeout = SMU_TIMEOUT; - uint[] cmdArgs = new uint[6]; - int argsLength = args.Length; - uint status = 0; - - if (argsLength > cmdArgs.Length) - argsLength = cmdArgs.Length; - - for (int i = 0; i < argsLength; ++i) - cmdArgs[i] = args[i]; - - if (amdSmuMutex.WaitOne(5000)) - { - // Clear response register - bool temp; - do - temp = SmuWriteReg(Smu.SMU_ADDR_RSP, 0); - while ((!temp) && --timeout > 0); - - if (timeout == 0) - { - amdSmuMutex.ReleaseMutex(); - SmuReadReg(Smu.SMU_ADDR_RSP, ref status); - return (SMU.Status)status; - } - - // Write data - for (int i = 0; i < cmdArgs.Length; ++i) - SmuWriteReg(Smu.SMU_ADDR_ARG + (uint)(i * 4), cmdArgs[i]); - - // Send message - SmuWriteReg(Smu.SMU_ADDR_MSG, msg); - - // Wait done - if (!SmuWaitDone()) - { - amdSmuMutex.ReleaseMutex(); - SmuReadReg(Smu.SMU_ADDR_RSP, ref status); - return (SMU.Status)status; - } - - // Read back args - for (int i = 0; i < args.Length; ++i) - SmuReadReg(Smu.SMU_ADDR_ARG + (uint)(i * 4), ref args[i]); - } - - amdSmuMutex.ReleaseMutex(); - SmuReadReg(Smu.SMU_ADDR_RSP, ref status); - - return (SMU.Status)status; - } - - // Legacy - public bool SendSmuCommand(uint msg, uint arg) - { - uint[] args = { arg }; - return SendSmuCommand(msg, ref args) == SMU.Status.OK; - } - - public uint ReadDword(uint value) - { - Ols.WritePciConfigDword(Smu.SMU_PCI_ADDR, (byte)Smu.SMU_OFFSET_ADDR, value); - return Ols.ReadPciConfigDword(Smu.SMU_PCI_ADDR, (byte)Smu.SMU_OFFSET_DATA); - } - - private double GetCoreMulti(int index) - { - uint eax = default, edx = default; - if (Ols.RdmsrTx(0xC0010293, ref eax, ref edx, (UIntPtr)(1 << index)) != 1) - { - return 0; - } - - double multi = 25 * (eax & 0xFF) / (12.5 * (eax >> 8 & 0x3F)); - return Math.Round(multi * 4, MidpointRounding.ToEven) / 4; - } - - public bool WriteMsr(uint msr, uint eax, uint edx) - { - bool res = true; - - for (var i = 0; i < Threads; i++) - { - if (Ols.WrmsrTx(msr, eax, edx, (UIntPtr)(1 << i)) != 1) res = false; - } - - return res; - } - - public SMU.CpuFamily GetCpuFamily() - { - uint eax = 0, ebx = 0, ecx = 0, edx = 0; - if (Ols.Cpuid(0x00000001, ref eax, ref ebx, ref ecx, ref edx) == 1) - { - SMU.CpuFamily family = (SMU.CpuFamily)(GetBits(eax, 8, 4) + GetBits(eax, 20, 7)); - return family; - } - return SMU.CpuFamily.UNSUPPORTED; - } - - public SMU.CPUType GetCPUType(uint packageType) - { - SMU.CPUType cpuType; - - // CPU Check. Compare family, model, ext family, ext model - switch (GetCpuId()) - { - case 0x00800F11: // CPU \ Zen \ Summit Ridge \ ZP - B0 \ 14nm - case 0x00800F00: // CPU \ Zen \ Summit Ridge \ ZP - A0 \ 14nm - if (packageType == 4 || packageType == 7) - cpuType = SMU.CPUType.Threadripper; - else - cpuType = SMU.CPUType.SummitRidge; - break; - case 0x00800F12: - cpuType = SMU.CPUType.Naples; - break; - case 0x00800F82: // CPU \ Zen + \ Pinnacle Ridge \ 12nm - if (packageType == 4 || packageType == 7) - cpuType = SMU.CPUType.Colfax; - else - cpuType = SMU.CPUType.PinnacleRidge; - break; - case 0x00810F81: // APU \ Zen + \ Picasso \ 12nm - cpuType = SMU.CPUType.Picasso; - break; - case 0x00810F00: // APU \ Zen \ Raven Ridge \ RV - A0 \ 14nm - case 0x00810F10: // APU \ Zen \ Raven Ridge \ 14nm - case 0x00820F00: // APU \ Zen \ Raven Ridge 2 \ RV2 - A0 \ 14nm - case 0x00820F01: // APU \ Zen \ Dali - cpuType = SMU.CPUType.RavenRidge; - break; - case 0x00870F10: // CPU \ Zen2 \ Matisse \ MTS - B0 \ 7nm + 14nm I/ O Die - case 0x00870F00: // CPU \ Zen2 \ Matisse \ MTS - A0 \ 7nm + 14nm I/ O Die - cpuType = SMU.CPUType.Matisse; - break; - case 0x00830F00: - case 0x00830F10: // CPU \ Epyc 2 \ Rome \ Treadripper 2 \ Castle Peak 7nm - if (packageType == 7) - cpuType = SMU.CPUType.Rome; - else - cpuType = SMU.CPUType.CastlePeak; - break; - case 0x00850F00: // Subor Z+ - cpuType = SMU.CPUType.Fenghuang; - break; - case 0x00860F01: // APU \ Renoir - cpuType = SMU.CPUType.Renoir; - break; - case 0x00A20F00: // CPU \ Vermeer - case 0x00A20F10: - cpuType = SMU.CPUType.Vermeer; - break; - //case 0x00A00F00: // CPU \ Genesis - //case 0x00A00F10: - //cpuType = SMU.CPUType.Genesis; - //break; - default: - cpuType = SMU.CPUType.Unsupported; - break; - } - - return cpuType; - } - - public uint GetCpuId() - { - uint eax = 0, ebx = 0, ecx = 0, edx = 0; - if (Ols.Cpuid(0x00000001, ref eax, ref ebx, ref ecx, ref edx) == 1) - { - return eax; - } - return 0; - } - - public uint GetPackageType() - { - uint eax = 0, ebx = 0, ecx = 0, edx = 0; - if (Ols.Cpuid(0x80000001, ref eax, ref ebx, ref ecx, ref edx) == 1) - { - return ebx >> 28; - } - return 0; - } - - public int GetCpuNodes() - { - uint eax = 0, ebx = 0, ecx = 0, edx = 0; - if (Ols.Cpuid(0x8000001E, ref eax, ref ebx, ref ecx, ref edx) == 1) - { - return Convert.ToInt32(ecx >> 8 & 0x7) + 1; - } - return 1; - } - - // Return [realCores, logicalCores] - public int[] GetCoreCount() - { - uint eax = 0, ebx = 0, ecx = 0, edx = 0; - int logicalCores = 0; - int threadsPerCore = 1; - int[] count = { 0, 1 }; - - if (Ols.Cpuid(0x00000001, ref eax, ref ebx, ref ecx, ref edx) == 1) - { - logicalCores = Convert.ToInt32((ebx >> 16) & 0xFF); - - if (Ols.Cpuid(0x8000001E, ref eax, ref ebx, ref ecx, ref edx) == 1) - threadsPerCore = Convert.ToInt32(ebx >> 8 & 0xF) + 1; - } - if (threadsPerCore == 0) - count[0] = logicalCores; - else - count[0] = logicalCores / threadsPerCore; - - count[1] = logicalCores; - - return count; - } - - public int GetCCDCount() - { - uint value1 = 0, value2 = 0, value3 = 0; - int ccdCount = 0; - uint reg1 = 0x5D22A; - uint reg2 = 0x5D22B; - uint reg3 = 0x5D22C; - - if (CpuType == SMU.CPUType.Matisse) - { - reg1 = 0x5D21A; - reg2 = 0x5D21B; - reg3 = 0x5D21C; - } - - if (!SmuReadReg(reg1, ref value1) || - !SmuReadReg(reg2, ref value2) || - !SmuReadReg(reg3, ref value3)) - return ccdCount; - - value1 = (value1 >> 22) & 0xff; - value2 = (value2 >> 30) & 0xff; - value3 &= 0x3f; - - uint value4 = value2 | 4 * value3; - - if (!((value1 & 1) == 0 || (value4 & 1) == 1)) - ccdCount += 1; - - int i = 0; - do { - uint mask = 1u << i; - if ((value1 & mask) == 1 && (value4 & mask) == 0) - ccdCount += 1; - } while (++i < 8); - - return ccdCount; - } - - private string GetStringPart(uint val) - { - return val != 0 ? Convert.ToChar(val).ToString() : ""; - } - - private string IntToStr(uint val) - { - uint part1 = val & 0xff; - uint part2 = val >> 8 & 0xff; - uint part3 = val >> 16 & 0xff; - uint part4 = val >> 24 & 0xff; - - return string.Format("{0}{1}{2}{3}", GetStringPart(part1), GetStringPart(part2), GetStringPart(part3), GetStringPart(part4)); - } - - public string GetCpuName() - { - string model = ""; - uint eax = 0, ebx = 0, ecx = 0, edx = 0; - - if (Ols.Cpuid(0x80000002, ref eax, ref ebx, ref ecx, ref edx) == 1) - model = model + IntToStr(eax) + IntToStr(ebx) + IntToStr(ecx) + IntToStr(edx); - - if (Ols.Cpuid(0x80000003, ref eax, ref ebx, ref ecx, ref edx) == 1) - model = model + IntToStr(eax) + IntToStr(ebx) + IntToStr(ecx) + IntToStr(edx); - - if (Ols.Cpuid(0x80000004, ref eax, ref ebx, ref ecx, ref edx) == 1) - model = model + IntToStr(eax) + IntToStr(ebx) + IntToStr(ecx) + IntToStr(edx); - - return model.Trim(); - } - - public int GetThreadsPerCore() - { - uint eax = 0, ebx = 0, ecx = 0, edx = 0; - - if (Ols.Cpuid(0x8000001E, ref eax, ref ebx, ref ecx, ref edx) == 1) - { - return Convert.ToInt16(GetBits(ebx, 8, 8)) + 1; - } - return 1; - } - - public uint GetSmuVersion() - { - uint[] args = new uint[6]; - if (SendSmuCommand(Smu.SMU_MSG_GetSmuVersion, ref args) == SMU.Status.OK) - return args[0]; - - return 0; - } - - public uint GetPatchLevel() - { - uint eax = 0, edx = 0; - if (Ols.Rdmsr(0x8b, ref eax, ref edx) != 1) - return 0; - - return eax; - } - - public bool GetOcMode() - { - /* - uint eax = 0; - uint edx = 0; - - if (ols.Rdmsr(MSR_PStateStat, ref eax, ref edx) == 1) - { - // Summit Ridge, Raven Ridge - return Convert.ToBoolean((eax >> 1) & 1); - } - return false; - */ - - return GetPBOScalar() == 0; - } - - public float GetPBOScalar() - { - uint[] args = new uint[6]; - if (SendSmuCommand(Smu.SMU_MSG_GetPBOScalar, ref args) == SMU.Status.OK) - { - byte[] bytes = BitConverter.GetBytes(args[0]); - float scalar = BitConverter.ToSingle(bytes, 0); - - if (scalar > 0) - return scalar; - } - return 0f; - } - - public SMU.Status TransferTableToDram() - { - uint[] args = { 1, 1, 0, 0, 0, 0 }; - - if (Smu.SMU_TYPE == SMU.SmuType.TYPE_APU0) - { - args[0] = 3; - args[1] = 0; - } - - return SendSmuCommand(Smu.SMU_MSG_TransferTableToDram, ref args); - } - - public ulong GetDramBaseAddress() - { - uint[] args = new uint[6]; - ulong address = 0; - - SMU.Status status = SMU.Status.FAILED; - - switch (Smu.SMU_TYPE) - { - // SummitRidge, PinnacleRidge, Colfax - case SMU.SmuType.TYPE_CPU0: - case SMU.SmuType.TYPE_CPU1: - args[0] = 0; - status = SendSmuCommand(Smu.SMU_MSG_GetDramBaseAddress - 1, ref args); - if (status != SMU.Status.OK) - return 0; - - status = SendSmuCommand(Smu.SMU_MSG_GetDramBaseAddress, ref args); - if (status != SMU.Status.OK) - return 0; - - address = args[0]; - - //args[0] = 0; - //status = SendSmuCommand(Smu.SMU_MSG_GetDramBaseAddress + 2, ref args); - //if (status != SMU.Status.OK) - //return 0; - break; - - // Matisse, CastlePeak, Rome, Vermeer - case SMU.SmuType.TYPE_CPU2: - case SMU.SmuType.TYPE_CPU3: - status = SendSmuCommand(Smu.SMU_MSG_GetDramBaseAddress, ref args); - if (status != SMU.Status.OK) - return 0; - address = args[0] | ((ulong)args[1] << 32); - break; - - // Renoir - case SMU.SmuType.TYPE_APU1: - status = SendSmuCommand(Smu.SMU_MSG_GetDramBaseAddress, ref args); - if (status != SMU.Status.OK) - return 0; - address = args[0] | ((ulong)args[1] << 32); - break; - - // RavenRidge, RavenRidge2, Picasso - case SMU.SmuType.TYPE_APU0: - uint[] parts = new uint[2]; - - args[0] = 3; - status = SendSmuCommand(Smu.SMU_MSG_GetDramBaseAddress - 1, ref args); - if (status != SMU.Status.OK) - return 0; - - args[0] = 3; - status = SendSmuCommand(Smu.SMU_MSG_GetDramBaseAddress, ref args); - if (status != SMU.Status.OK) - return 0; - - // First base - parts[0] = args[0]; - - args[0] = 5; - status = SendSmuCommand(Smu.SMU_MSG_GetDramBaseAddress - 1, ref args); - if (status != SMU.Status.OK) - return 0; - - status = SendSmuCommand(Smu.SMU_MSG_GetDramBaseAddress, ref args); - if (status != SMU.Status.OK) - return 0; - - // Second base - parts[1] = args[0]; - address = (ulong)parts[1] << 32 | parts[0]; - break; - - default: - break; - } - - if (status == SMU.Status.OK) - return address; - - return 0; - } - - public bool SendTestMessage() - { - uint[] args = new uint[6]; - return SendSmuCommand(Smu.SMU_MSG_TestMessage, ref args) == SMU.Status.OK; - } - - public bool IsProchotEnabled() - { - uint data = ReadDword(0x59804); - return (data & 1) == 1; - } - - public double VidToVoltage(uint vid) - { - return 1.55 - vid * 0.00625; - } - - public void Dispose() - { - amdSmuMutex.ReleaseMutex(); - Ols.Dispose(); - } - } -} diff --git a/Utils/PowerTable.cs b/Utils/PowerTable.cs deleted file mode 100644 index 3af7eee..0000000 --- a/Utils/PowerTable.cs +++ /dev/null @@ -1,281 +0,0 @@ -using System; -using System.ComponentModel; -using System.Runtime.InteropServices; -using ZenStates; - -namespace ZenStates -{ - public class PowerTable : INotifyPropertyChanged - { - public const uint tableSize = 0x7E4; - private uint[] table = new uint[tableSize]; - - public event PropertyChangedEventHandler PropertyChanged; - - protected bool SetProperty(ref T storage, T value, PropertyChangedEventArgs args) - { - if (Equals(storage, value) || value == null) return false; - storage = value; - OnPropertyChanged(args); - return true; - } - - [Serializable] - [StructLayout(LayoutKind.Explicit)] - private struct PowerTableAPU0 - { - [FieldOffset(0x104)] public uint VddcrSoc; - [FieldOffset(0x298)] public uint Fclk; - [FieldOffset(0x2C8)] public uint Uclk; - [FieldOffset(0x2CC)] public uint Mclk; - }; - - [Serializable] - [StructLayout(LayoutKind.Explicit)] - private struct PowerTableAPU1 - { - [FieldOffset(0x144)] public uint Fclk; - [FieldOffset(0x154)] public uint Uclk; - [FieldOffset(0x164)] public uint Mclk; - [FieldOffset(0x198)] public uint VddcrSoc; - }; - - [Serializable] - [StructLayout(LayoutKind.Explicit)] - private struct PowerTableCPU0 - { - [FieldOffset(0x044)] public uint CldoVddp; - [FieldOffset(0x068)] public uint VddcrSoc; - [FieldOffset(0x084)] public uint Fclk; - [FieldOffset(0x084)] public uint Uclk; - [FieldOffset(0x084)] public uint Mclk; - }; - - [Serializable] - [StructLayout(LayoutKind.Explicit)] - private struct PowerTableCPU1 - { - [FieldOffset(0x03C)] public uint CldoVddp; - [FieldOffset(0x060)] public uint VddcrSoc; - [FieldOffset(0x084)] public uint Fclk; - [FieldOffset(0x084)] public uint Uclk; - [FieldOffset(0x084)] public uint Mclk; - }; - - [Serializable] - [StructLayout(LayoutKind.Explicit)] - private struct PowerTableCPU2 - { - [FieldOffset(0x0B4)] public uint VddcrSoc; - [FieldOffset(0x0C0)] public uint Fclk; - [FieldOffset(0x0C8)] public uint Uclk; - [FieldOffset(0x0CC)] public uint Mclk; - [FieldOffset(0x1F4)] public uint CldoVddp; - [FieldOffset(0x1F8)] public uint CldoVddgIod; - }; - - [Serializable] - [StructLayout(LayoutKind.Explicit)] - private struct PowerTableCPU3 - { - [FieldOffset(0x0B4)] public uint VddcrSoc; - [FieldOffset(0x0C0)] public uint Fclk; - [FieldOffset(0x0C8)] public uint Uclk; - [FieldOffset(0x0CC)] public uint Mclk; - [FieldOffset(0x224)] public uint CldoVddp; - [FieldOffset(0x228)] public uint CldoVddgIod; - [FieldOffset(0x22C)] public uint CldoVddgCcd; - }; - - public PowerTable(SMU.SmuType smutype) => SmuType = smutype; - - private void ParseTable(uint[] pt) - { - if (pt == null) - return; - - GCHandle handle = GCHandle.Alloc(pt, GCHandleType.Pinned); - try - { - dynamic powerTable = null; - byte[] bytes = new byte[4]; - - switch (SmuType) - { - case SMU.SmuType.TYPE_CPU0: - powerTable = (PowerTableCPU0)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(PowerTableCPU0)); - break; - - case SMU.SmuType.TYPE_CPU1: - powerTable = (PowerTableCPU1)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(PowerTableCPU1)); - break; - - case SMU.SmuType.TYPE_CPU2: - powerTable = (PowerTableCPU2)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(PowerTableCPU2)); - break; - - case SMU.SmuType.TYPE_CPU3: - powerTable = (PowerTableCPU3)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(PowerTableCPU3)); - break; - - case SMU.SmuType.TYPE_APU0: - powerTable = (PowerTableAPU0)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(PowerTableAPU0)); - break; - - case SMU.SmuType.TYPE_APU1: - powerTable = (PowerTableAPU1)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(PowerTableAPU1)); - break; - - default: - return; - } - - float bclkCorrection = 1.00f; - - try - { - bytes = BitConverter.GetBytes(powerTable.Mclk); - float mclkFreq = BitConverter.ToSingle(bytes, 0); - - // Compensate for lack of BCLK detection, based on configuredClockSpeed - float dramFreq = ConfiguredClockSpeed / 2; - //if ((dramFreq + 1) / mclkFreq > 1 && dramFreq % mclkFreq > 1) - bclkCorrection = dramFreq / mclkFreq; - - MCLK = mclkFreq * bclkCorrection; - } - catch { } - - try - { - bytes = BitConverter.GetBytes(powerTable.Fclk); - float fclkFreq = BitConverter.ToSingle(bytes, 0); - FCLK = fclkFreq * bclkCorrection; - } - catch { } - - try - { - bytes = BitConverter.GetBytes(powerTable.Uclk); - float uclkFreq = BitConverter.ToSingle(bytes, 0); - UCLK = uclkFreq * bclkCorrection; - } - catch { } - - try - { - bytes = BitConverter.GetBytes(powerTable.VddcrSoc); - VDDCR_SOC = BitConverter.ToSingle(bytes, 0); - } - catch { } - - try - { - bytes = BitConverter.GetBytes(powerTable.CldoVddp); - CLDO_VDDP = BitConverter.ToSingle(bytes, 0); - } - catch { } - - try - { - bytes = BitConverter.GetBytes(powerTable.CldoVddgIod); - CLDO_VDDG_IOD = BitConverter.ToSingle(bytes, 0); - } - catch { } - - try - { - bytes = BitConverter.GetBytes(powerTable.CldoVddgCcd); - CLDO_VDDG_CCD = BitConverter.ToSingle(bytes, 0); - } - catch { } - } - finally - { - handle.Free(); - } - } - - public SMU.SmuType SmuType { get; protected set; } - public uint[] Table - { - get => table; - set - { - if (value != null) - { - table = value; - ParseTable(value); - } - } - } - - float fclk; - public float FCLK - { - get => fclk; - set => SetProperty(ref fclk, value, InternalEventArgsCache.FCLK); - } - - float mclk; - public float MCLK - { - get => mclk; - set => SetProperty(ref mclk, value, InternalEventArgsCache.MCLK); - } - - float uclk; - public float UCLK - { - get => uclk; - set => SetProperty(ref uclk, value, InternalEventArgsCache.UCLK); - } - - float vddcr_soc; - public float VDDCR_SOC - { - get => vddcr_soc; - set => SetProperty(ref vddcr_soc, value, InternalEventArgsCache.VDDCR_SOC); - } - - float cldo_vddp; - public float CLDO_VDDP - { - get => cldo_vddp; - set => SetProperty(ref cldo_vddp, value, InternalEventArgsCache.CLDO_VDDP); - } - - float cldo_vddg_iod; - public float CLDO_VDDG_IOD - { - get => cldo_vddg_iod; - set => SetProperty(ref cldo_vddg_iod, value, InternalEventArgsCache.CLDO_VDDG_IOD); - } - - float cldo_vddg_ccd; - public float CLDO_VDDG_CCD - { - get => cldo_vddg_ccd; - set => SetProperty(ref cldo_vddg_ccd, value, InternalEventArgsCache.CLDO_VDDG_CCD); - } - - protected void OnPropertyChanged(PropertyChangedEventArgs eventArgs) - { - PropertyChanged?.Invoke(this, eventArgs); - } - - public float ConfiguredClockSpeed { get; set; } - } - - internal static class InternalEventArgsCache - { - internal static PropertyChangedEventArgs FCLK = new PropertyChangedEventArgs("FCLK"); - internal static PropertyChangedEventArgs MCLK = new PropertyChangedEventArgs("MCLK"); - internal static PropertyChangedEventArgs UCLK = new PropertyChangedEventArgs("UCLK"); - - internal static PropertyChangedEventArgs VDDCR_SOC = new PropertyChangedEventArgs("VDDCR_SOC"); - internal static PropertyChangedEventArgs CLDO_VDDP = new PropertyChangedEventArgs("CLDO_VDDP"); - internal static PropertyChangedEventArgs CLDO_VDDG_IOD = new PropertyChangedEventArgs("CLDO_VDDG_IOD"); - internal static PropertyChangedEventArgs CLDO_VDDG_CCD = new PropertyChangedEventArgs("CLDO_VDDG_CCD"); - } -} diff --git a/Utils/SMU.cs b/Utils/SMU.cs deleted file mode 100644 index c7a2af2..0000000 --- a/Utils/SMU.cs +++ /dev/null @@ -1,355 +0,0 @@ -using System; -using System.Collections.Generic; - -namespace ZenStates -{ - [System.Diagnostics.CodeAnalysis.SuppressMessage("Naming", "CA1707:Identifiers should not contain underscores", Justification = "")] - public abstract class SMU - { - public enum CpuFamily - { - UNSUPPORTED = 0x0, - FAMILY_17H = 0x17, - FAMILY_18H = 0x18, - FAMILY_19H = 0x19, - }; - - public enum SmuType - { - TYPE_CPU0 = 0x0, - TYPE_CPU1 = 0x1, - TYPE_CPU2 = 0x2, - TYPE_CPU3 = 0x3, - TYPE_APU0 = 0x10, - TYPE_APU1 = 0x11, - TYPE_UNSUPPORTED = 0xFF, - }; - - public enum CPUType : int - { - Unsupported = 0, - DEBUG, - SummitRidge, - Threadripper, - Naples, - RavenRidge, - PinnacleRidge, - Colfax, - Picasso, - Fenghuang, - Matisse, - CastlePeak, - Rome, - Renoir, - Vermeer, - Genesis - }; - - public enum PackageType: int - { - FP6 = 0, - AM4 = 2, - SP3 = 7 - } - - public enum Status : byte - { - OK = 0x01, - FAILED = 0xFF, - UNKNOWN_CMD = 0xFE, - CMD_REJECTED_PREREQ = 0xFD, - CMD_REJECTED_BUSY = 0xFC - } - - public SMU() - { - Version = 0; - // SMU - //ManualOverclockSupported = false; - - SMU_TYPE = SmuType.TYPE_CPU0; - - SMU_PCI_ADDR = 0x00000000; - SMU_OFFSET_ADDR = 0x60; - SMU_OFFSET_DATA = 0x64; - - SMU_ADDR_MSG = 0x03B10528; - SMU_ADDR_RSP = 0x03B10564; - SMU_ADDR_ARG = 0x03B10598; - - // SMU Messages - SMU_MSG_TestMessage = 0x1; - SMU_MSG_GetSmuVersion = 0x2; - SMU_MSG_TransferTableToDram = 0x0; - SMU_MSG_GetDramBaseAddress = 0x0; - SMU_MSG_SetOverclockFrequencyAllCores = 0x0; - SMU_MSG_SetOverclockFrequencyPerCore = 0x0; - SMU_MSG_SetOverclockCpuVid = 0x0; - SMU_MSG_EnableOcMode = 0x0; - SMU_MSG_DisableOcMode = 0x0; - SMU_MSG_GetPBOScalar = 0x0; - SMU_MSG_SetPBOScalar = 0x0; - SMU_MSG_SetPPTLimit = 0x0; - SMU_MSG_SetTDCLimit = 0x0; - SMU_MSG_SetEDCLimit = 0x0; - } - - public uint Version { get; set; } - //public bool ManualOverclockSupported { get; protected set; } - - public SmuType SMU_TYPE { get; protected set; } - - public uint SMU_PCI_ADDR { get; protected set; } - public uint SMU_OFFSET_ADDR { get; protected set; } - public uint SMU_OFFSET_DATA { get; protected set; } - - public uint SMU_ADDR_MSG { get; set; } - public uint SMU_ADDR_RSP { get; set; } - public uint SMU_ADDR_ARG { get; set; } - - public uint SMU_MSG_TestMessage { get; protected set; } - public uint SMU_MSG_GetSmuVersion { get; protected set; } - public uint SMU_MSG_TransferTableToDram { get; protected set; } - public uint SMU_MSG_GetDramBaseAddress { get; protected set; } - public uint SMU_MSG_SetOverclockFrequencyAllCores { get; protected set; } - public uint SMU_MSG_SetOverclockFrequencyPerCore { get; protected set; } - public uint SMU_MSG_SetOverclockCpuVid { get; protected set; } - public uint SMU_MSG_EnableOcMode { get; protected set; } - public uint SMU_MSG_DisableOcMode { get; protected set; } - public uint SMU_MSG_GetPBOScalar { get; protected set; } - public uint SMU_MSG_SetPBOScalar { get; protected set; } - public uint SMU_MSG_SetPPTLimit { get; protected set; } - public uint SMU_MSG_SetTDCLimit { get; protected set; } - public uint SMU_MSG_SetEDCLimit { get; protected set; } - } - - // Zen (Summit Ridge), ThreadRipper - public class SummitRidgeSettings : SMU - { - public SummitRidgeSettings() - { - /* - SMU_ADDR_MSG = 0x03B10528; - SMU_ADDR_RSP = 0x03B10564; - SMU_ADDR_ARG = 0x03B10598; - */ - SMU_TYPE = SmuType.TYPE_CPU0; - - SMU_ADDR_MSG = 0x03B1051C; - SMU_ADDR_RSP = 0x03B10568; - SMU_ADDR_ARG = 0x03B10590; - - SMU_MSG_TransferTableToDram = 0xA; - SMU_MSG_GetDramBaseAddress = 0xC; - /* - SMU_MSG_EnableOcMode = 0x23; - SMU_MSG_DisableOcMode = 0x24; - SMU_MSG_SetOverclockFrequencyAllCores = 0x26; - SMU_MSG_SetOverclockFrequencyPerCore = 0x27; - SMU_MSG_SetOverclockCpuVid = 0x28; - */ - } - } - - // Zen+ (Pinnacle Ridge) - public class ZenPSettings : SMU - { - public ZenPSettings() - { - SMU_TYPE = SmuType.TYPE_CPU1; - - SMU_ADDR_MSG = 0x03B1051C; - SMU_ADDR_RSP = 0x03B10568; - SMU_ADDR_ARG = 0x03B10590; - - SMU_MSG_TransferTableToDram = 0xA; - SMU_MSG_GetDramBaseAddress = 0xC; - SMU_MSG_EnableOcMode = 0x6B; //0x63; - //SMU_MSG_DisableOcMode = 0x64; - SMU_MSG_SetOverclockFrequencyAllCores = 0x6C; - SMU_MSG_SetOverclockFrequencyPerCore = 0x6D; - SMU_MSG_SetOverclockCpuVid = 0x6E; - SMU_MSG_SetPBOScalar = 0x6A; - SMU_MSG_GetPBOScalar = 0x6F; - } - } - - // TR2 (Colfax) - public class ColfaxSettings : SMU - { - public ColfaxSettings() - { - SMU_TYPE = SmuType.TYPE_CPU1; - - SMU_ADDR_MSG = 0x03B1051C; - SMU_ADDR_RSP = 0x03B10568; - SMU_ADDR_ARG = 0x03B10590; - - SMU_MSG_TransferTableToDram = 0xA; - SMU_MSG_GetDramBaseAddress = 0xC; - SMU_MSG_EnableOcMode = 0x63; - SMU_MSG_DisableOcMode = 0x64; - SMU_MSG_SetOverclockFrequencyAllCores = 0x68; - SMU_MSG_SetOverclockFrequencyPerCore = 0x69; - SMU_MSG_SetOverclockCpuVid = 0x6A; - } - } - - // Ryzen 3000 (Matisse), TR 3000 (Castle Peak) - public class Zen2Settings : SMU - { - public Zen2Settings() - { - SMU_TYPE = SmuType.TYPE_CPU2; - - SMU_ADDR_MSG = 0x03B10524; - SMU_ADDR_RSP = 0x03B10570; - SMU_ADDR_ARG = 0x03B10A40; - - SMU_MSG_TransferTableToDram = 0x5; - SMU_MSG_GetDramBaseAddress = 0x6; - SMU_MSG_EnableOcMode = 0x5A; - SMU_MSG_DisableOcMode = 0x5B; - SMU_MSG_SetOverclockFrequencyAllCores = 0x5C; - SMU_MSG_SetOverclockFrequencyPerCore = 0x5D; - SMU_MSG_SetOverclockCpuVid = 0x61; - SMU_MSG_SetPPTLimit = 0x53; - SMU_MSG_SetTDCLimit = 0x54; - SMU_MSG_SetEDCLimit = 0x55; - SMU_MSG_SetPBOScalar = 0x58; - SMU_MSG_GetPBOScalar = 0x6C; - } - } - - // Ryzen 5000 (Vermeer), TR 5000 (Genesis)? - public class Zen3Settings : Zen2Settings - { - public Zen3Settings() - { - SMU_TYPE = SmuType.TYPE_CPU3; - } - } - - // Epyc 2 (Rome) ES - public class RomeSettings : SMU - { - public RomeSettings() - { - SMU_TYPE = SmuType.TYPE_CPU2; - - SMU_ADDR_MSG = 0x03B10524; - SMU_ADDR_RSP = 0x03B10570; - SMU_ADDR_ARG = 0x03B10A40; - - SMU_MSG_TransferTableToDram = 0x5; - SMU_MSG_GetDramBaseAddress = 0x6; - SMU_MSG_SetOverclockFrequencyAllCores = 0x18; - // SMU_MSG_SetOverclockFrequencyPerCore = 0x19; - SMU_MSG_SetOverclockCpuVid = 0x12; - } - } - - // RavenRidge, RavenRidge 2, Fenghuang, Picasso - public class APUSettings0 : SMU - { - public APUSettings0() - { - SMU_TYPE = SmuType.TYPE_APU0; - - SMU_ADDR_MSG = 0x03B10A20; - SMU_ADDR_RSP = 0x03B10A80; - SMU_ADDR_ARG = 0x03B10A88; - - SMU_MSG_GetDramBaseAddress = 0xB; - SMU_MSG_TransferTableToDram = 0x3D; - - SMU_MSG_GetPBOScalar = 0x62; - SMU_MSG_EnableOcMode = 0x69; - SMU_MSG_DisableOcMode = 0x6A; - SMU_MSG_SetOverclockFrequencyAllCores = 0x7D; - SMU_MSG_SetOverclockFrequencyPerCore = 0x7E; - SMU_MSG_SetOverclockCpuVid = 0x7F; - } - } - - // Renoir - public class APUSettings1 : SMU - { - public APUSettings1() - { - SMU_TYPE = SmuType.TYPE_APU1; - - SMU_ADDR_MSG = 0x03B10A20; - SMU_ADDR_RSP = 0x03B10A80; - SMU_ADDR_ARG = 0x03B10A88; - - SMU_MSG_TransferTableToDram = 0x65; - SMU_MSG_GetDramBaseAddress = 0x66; - SMU_MSG_EnableOcMode = 0x17; - SMU_MSG_DisableOcMode = 0x18; - SMU_MSG_SetOverclockFrequencyAllCores = 0x19; - SMU_MSG_SetOverclockFrequencyPerCore = 0x1A; - SMU_MSG_SetOverclockCpuVid = 0x1B; - } - } - - public static class GetMaintainedSettings - { - private static readonly Dictionary settings = new Dictionary() - { - // Zen - { SMU.CPUType.SummitRidge, new SummitRidgeSettings() }, - { SMU.CPUType.Naples, new SummitRidgeSettings() }, - { SMU.CPUType.Threadripper, new SummitRidgeSettings() }, - - // Zen+ - { SMU.CPUType.PinnacleRidge, new ZenPSettings() }, - { SMU.CPUType.Colfax, new ColfaxSettings() }, - - // Zen2 - { SMU.CPUType.Matisse, new Zen2Settings() }, - { SMU.CPUType.CastlePeak, new Zen2Settings() }, - { SMU.CPUType.Rome, new RomeSettings() }, - - // Zen3 - { SMU.CPUType.Vermeer, new Zen3Settings() }, - { SMU.CPUType.Genesis, new Zen3Settings() }, - - // APU - { SMU.CPUType.RavenRidge, new APUSettings0() }, - { SMU.CPUType.Fenghuang, new APUSettings0() }, - { SMU.CPUType.Picasso, new APUSettings0() }, - { SMU.CPUType.Renoir, new APUSettings1() }, - }; - - public static SMU GetByType(SMU.CPUType type) - { - if (!settings.TryGetValue(type, out SMU output)) - { - throw new NotImplementedException(); - } - return output; - } - } - - public static class GetSMUStatus - { - private static readonly Dictionary status = new Dictionary() - { - { SMU.Status.OK, "OK" }, - { SMU.Status.FAILED, "Failed" }, - { SMU.Status.UNKNOWN_CMD, "Unknown Command" }, - { SMU.Status.CMD_REJECTED_PREREQ, "CMD Rejected Prereq" }, - { SMU.Status.CMD_REJECTED_BUSY, "CMD Rejected Busy" } - }; - - public static string GetByType(SMU.Status type) - { - if (!status.TryGetValue(type, out string output)) - { - return "Unknown Status"; - } - return output; - } - } -} diff --git a/Utils/SystemInfo.cs b/Utils/SystemInfo.cs deleted file mode 100644 index d4a17a3..0000000 --- a/Utils/SystemInfo.cs +++ /dev/null @@ -1,109 +0,0 @@ -using System; - -namespace ZenStates -{ - [Serializable] - public class SystemInfo - { - private int ccdCount; - private int threads; - - private static string SmuVersionToString(uint version) - { - string[] versionString = new string[3]; - versionString[0] = ((version & 0x00FF0000) >> 16).ToString("D2"); - versionString[1] = ((version & 0x0000FF00) >> 8).ToString("D2"); - versionString[2] = (version & 0x000000FF).ToString("D2"); - - return string.Join(".", versionString); - } - - public SystemInfo() - { - CpuId = 0; - Model = 0; - ExtendedModel = 0; - NodesPerProcessor = 1; - PackageType = 0; - MbVendor = ""; - MbName = ""; - CpuName = ""; - CodeName = ""; - BiosVersion = ""; - SmuVersion = 0; - FusedCoreCount = 2; // minimum cores - Threads = 2; - PatchLevel = 0; - } - - public SystemInfo(uint cpuId, uint model, uint eModel, int nodes, uint pkgType, - string mbVendor, string mbName, string cpuName, string codeName, string biosVersion, - uint smuVersion, int fusedCoreCount, int threads, uint patchLevel) - { - CpuId = cpuId; - Model = model; - ExtendedModel = eModel; - NodesPerProcessor = nodes; - PackageType = pkgType; - MbVendor = mbVendor ?? throw new ArgumentNullException(nameof(mbVendor)); - MbName = mbName ?? throw new ArgumentNullException(nameof(mbName)); - CpuName = cpuName ?? throw new ArgumentNullException(nameof(cpuName)); - CodeName = codeName ?? throw new ArgumentNullException(nameof(codeName)); - BiosVersion = biosVersion ?? throw new ArgumentNullException(nameof(biosVersion)); - SmuVersion = smuVersion; - FusedCoreCount = fusedCoreCount; - Threads = threads; - PatchLevel = patchLevel; - } - - public string CpuName { get; set; } - public string CodeName { get; set; } - public uint CpuId { get; set; } - public uint Model { get; set; } - public uint ExtendedModel { get; set; } - public uint PackageType { get; set; } - public int FusedCoreCount { get; set; } - public int PhysicalCoreCount { get; private set; } - public int NodesPerProcessor { get; set; } - public int Threads { get; set; } - public bool SMT { get; set; } - - public int CCDCount - { - get => ccdCount; - set - { - if (value > 0) - { - ccdCount = value; - CCXCount = ccdCount * 2; - } - else - { - ccdCount = 1; - CCXCount = ccdCount; - } - - NumCoresInCCX = FusedCoreCount / CCXCount; - PhysicalCoreCount = CCXCount * 4; - } - } - public int CCXCount { get; private set; } - public int NumCoresInCCX { get; private set; } - public string MbVendor { get; set; } - public string MbName { get; set; } - public string BiosVersion { get; set; } - public uint SmuVersion { get; set; } - public uint PatchLevel { get; set; } - - public string GetSmuVersionString() - { - return SmuVersionToString(SmuVersion); - } - - public string GetCpuIdString() - { - return CpuId.ToString("X8").TrimStart('0'); - } - } -} diff --git a/Utils/WMI.cs b/Utils/WMI.cs deleted file mode 100644 index 1d65ddf..0000000 --- a/Utils/WMI.cs +++ /dev/null @@ -1,170 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Management; - -namespace ZenStates -{ - public static class WMI - { - public static object TryGetProperty(ManagementObject wmiObj, string propertyName) - { - object retval; - try - { - retval = wmiObj.GetPropertyValue(propertyName); - } - catch (ManagementException ex) - { - retval = null; - } - return retval; - } - - //root\wmi - public static ManagementScope Connect(string scope) - { - try - { - return new ManagementScope($@"{scope}"); - } - catch (ManagementException e) - { - Console.WriteLine("WMI: Failed to connect", e.Message); - throw; - } - } - - public static ManagementObject Query(string scope, string wmiClass) - { - using (var searcher = new ManagementObjectSearcher($"{scope}", $"SELECT * FROM {wmiClass}")) - { - ManagementObject queryObject = null; - - try - { - queryObject = searcher.Get().Cast().FirstOrDefault(); - } - catch { } - - return queryObject; - } - } - - public static List GetWmiNamespaces(string root) - { - List namespaces = new List(); - try - { - ManagementClass nsClass = new ManagementClass(new ManagementScope(root), new ManagementPath("__namespace"), null); - foreach (ManagementObject ns in nsClass.GetInstances()) - { - string namespaceName = root + "\\" + ns["Name"].ToString(); - namespaces.Add(namespaceName); - namespaces.AddRange(GetWmiNamespaces(namespaceName)); - } - } - catch (ManagementException me) - { - Console.WriteLine(me.Message); - } - - return namespaces.OrderBy(s => s).ToList(); - } - - public static List GetClassNamesWithinWmiNamespace(string wmiNamespaceName) - { - List classes = new List(); - ManagementObjectSearcher searcher = new ManagementObjectSearcher - (new ManagementScope(wmiNamespaceName), - new WqlObjectQuery("SELECT * FROM meta_class")); - List classNames = new List(); - ManagementObjectCollection objectCollection = searcher.Get(); - foreach (ManagementClass wmiClass in objectCollection) - { - string stringified = wmiClass.ToString(); - string[] parts = stringified.Split(new char[] { ':' }); - classes.Add(parts[1]); - } - return classes.OrderBy(s => s).ToList(); - } - - public static string GetInstanceName(string scope, string wmiClass) - { - using (ManagementObject queryObject = Query(scope, wmiClass)) - { - string name = ""; - object obj; - - if (queryObject == null) - return name; - - try - { - obj = TryGetProperty(queryObject, "InstanceName"); - if (obj != null) name = obj.ToString(); - } - catch { } - - return name; - } - } - - public static ManagementBaseObject InvokeMethod(ManagementObject mo, string methodName, string propName, string inParamName, uint arg) - { - try - { - // Obtain in-parameters for the method - ManagementBaseObject inParams = mo.GetMethodParameters($"{methodName}"); - - // Add the input parameters. - if (inParams != null) - inParams[$"{inParamName}"] = arg; - - // Execute the method and obtain the return values. - ManagementBaseObject outParams = mo.InvokeMethod($"{methodName}", inParams, null); - - return (ManagementBaseObject)outParams.Properties[$"{propName}"].Value; - } - catch (ManagementException err) - { - //MessageBox.Show("An error occurred while trying to execute the WMI method: " + err.Message); - return null; - } - } - - public static byte[] RunCommand(ManagementObject mo, uint commandID, uint commandArgs = 0x0) - { - try - { - // Obtain in-parameters for the method - ManagementBaseObject inParams = mo.GetMethodParameters("RunCommand"); - - // Add the input parameters. - byte[] cmd = new byte[4]; - byte[] args = new byte[4]; - byte[] buffer = new byte[8]; - cmd = BitConverter.GetBytes(commandID); - args = BitConverter.GetBytes(commandArgs); - - Buffer.BlockCopy(cmd, 0, buffer, 0, cmd.Length); - Buffer.BlockCopy(args, 0, buffer, cmd.Length, args.Length); - - - inParams["Inbuf"] = buffer; - - // Execute the method and obtain the return values. - ManagementBaseObject outParams = mo.InvokeMethod("RunCommand", inParams, null); - - // return outParam - ManagementBaseObject pack = (ManagementBaseObject)outParams.Properties["Outbuf"].Value; - return (byte[])pack.GetPropertyValue("Result"); - } - catch (ManagementException err) - { - //MessageBox.Show("An error occurred while trying to execute the WMI method: " + err.Message); - return null; - } - } - } -} diff --git a/ZenStatesDebugTool.csproj b/ZenStatesDebugTool.csproj index a526f5e..65a3be2 100644 --- a/ZenStatesDebugTool.csproj +++ b/ZenStatesDebugTool.csproj @@ -81,13 +81,7 @@ ResultForm.cs - - - - - - Form @@ -125,5 +119,11 @@ + + + {39C55831-97A2-498D-A9DD-27BF677E579A} + ZenStates.Core + + \ No newline at end of file diff --git a/ZenStatesDebugTool.sln b/ZenStatesDebugTool.sln index b192106..1bbc94f 100644 --- a/ZenStatesDebugTool.sln +++ b/ZenStatesDebugTool.sln @@ -4,6 +4,11 @@ Microsoft Visual Studio Solution File, Format Version 12.00 VisualStudioVersion = 16.0.29613.14 MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ZenStatesDebugTool", "ZenStatesDebugTool.csproj", "{056A457F-B9D4-4BB9-A9B3-033F2A1E265C}" + ProjectSection(ProjectDependencies) = postProject + {39C55831-97A2-498D-A9DD-27BF677E579A} = {39C55831-97A2-498D-A9DD-27BF677E579A} + EndProjectSection +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ZenStates.Core", "..\ZenStates.Core\ZenStates.Core.csproj", "{39C55831-97A2-498D-A9DD-27BF677E579A}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -15,6 +20,10 @@ Global {056A457F-B9D4-4BB9-A9B3-033F2A1E265C}.Debug|Any CPU.Build.0 = Debug|Any CPU {056A457F-B9D4-4BB9-A9B3-033F2A1E265C}.Release|Any CPU.ActiveCfg = Release|Any CPU {056A457F-B9D4-4BB9-A9B3-033F2A1E265C}.Release|Any CPU.Build.0 = Release|Any CPU + {39C55831-97A2-498D-A9DD-27BF677E579A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {39C55831-97A2-498D-A9DD-27BF677E579A}.Debug|Any CPU.Build.0 = Debug|Any CPU + {39C55831-97A2-498D-A9DD-27BF677E579A}.Release|Any CPU.ActiveCfg = Release|Any CPU + {39C55831-97A2-498D-A9DD-27BF677E579A}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE From 6617fc65e97b5a8edb20733e70761816a399ddf0 Mon Sep 17 00:00:00 2001 From: Ivan Rusanov Date: Fri, 20 Nov 2020 00:46:17 +0200 Subject: [PATCH 2/7] WIP: Initialization rework --- PowerTableMonitor.cs | 3 +- SettingsForm.Designer.cs | 2 +- SettingsForm.cs | 144 +++++++++++++++++++-------------------- 3 files changed, 74 insertions(+), 75 deletions(-) diff --git a/PowerTableMonitor.cs b/PowerTableMonitor.cs index e3e3d19..f522b91 100644 --- a/PowerTableMonitor.cs +++ b/PowerTableMonitor.cs @@ -59,7 +59,6 @@ private void ReadPowerConfig() private void FillInData(uint[] table) { - list.Clear(); for (var i = 0; i < table.Length; i++) @@ -97,7 +96,7 @@ private void PowerCfgTimer_Tick(object sender, EventArgs e) public PowerTableMonitor(Ops ops) { OPS = ops; - PowerTable = new PowerTable(OPS.Smu.SMU_TYPE); + PowerTable = new PowerTable(OPS.cpuinfo.smu.SMU_TYPE); PowerCfgTimer.Interval = 2000; PowerCfgTimer.Tick += new EventHandler(PowerCfgTimer_Tick); diff --git a/SettingsForm.Designer.cs b/SettingsForm.Designer.cs index 89b9edc..6dff430 100644 --- a/SettingsForm.Designer.cs +++ b/SettingsForm.Designer.cs @@ -18,7 +18,7 @@ protected override void Dispose(bool disposing) { if (disposing && (components != null)) { - m.Dispose(); + cpu.Dispose(); hMutexPci.Dispose(); components.Dispose(); } diff --git a/SettingsForm.cs b/SettingsForm.cs index ba44f4f..65b26c4 100644 --- a/SettingsForm.cs +++ b/SettingsForm.cs @@ -19,10 +19,11 @@ public partial class SettingsForm : Form //private static readonly int Threads = Convert.ToInt32(Environment.GetEnvironmentVariable("NUMBER_OF_PROCESSORS")); private BackgroundWorker backgroundWorker1; private NUMAUtil _numaUtil; - private readonly Zen m; + private readonly ZenCpu cpu; private SystemInfo SI; List matches; private int _coreCount; + private Ops.CPUInfo cpuinfo; readonly Mutex hMutexPci; @@ -64,7 +65,8 @@ public SettingsForm() try { - m = new Zen(); + cpu = new ZenCpu(); + cpuinfo = cpu.Ops.cpuinfo; InitForm(); } catch (ApplicationException ex) @@ -85,8 +87,6 @@ private static void ExitApplication() private void InitSystemInfo() { - Ops.CPUInfo cpuinfo = m.Ops.GetCpuInfo(); - if (cpuinfo.family != SMU.CpuFamily.FAMILY_17H && cpuinfo.family != SMU.CpuFamily.FAMILY_19H) { MessageBox.Show("CPU is not supported.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); @@ -95,18 +95,18 @@ private void InitSystemInfo() SI = new SystemInfo { - CpuId = m.Ops.GetCpuId(), - CpuName = m.Ops.GetCpuName(), - NodesPerProcessor = m.Ops.GetCpuNodes(), - PackageType = m.Ops.GetPackageType(), - PatchLevel = m.Ops.GetPatchLevel(), - SmuVersion = m.Ops.Smu.Version, + CpuId = cpuinfo.cpuid, + CpuName = cpuinfo.cpuName, + NodesPerProcessor = cpu.Ops.GetCpuNodes(), + PackageType = cpuinfo.packageType, + PatchLevel = cpuinfo.patchLevel, + SmuVersion = cpuinfo.smuVersion, FusedCoreCount = (int)cpuinfo.cores, Threads = (int)cpuinfo.logicalCores, CCDCount = (int)cpuinfo.ccds, CCXCount = (int)cpuinfo.ccxs, NumCoresInCCX = (int)cpuinfo.coresPerCcx, - CodeName = $"{m.Ops.CpuType}", + CodeName = $"{cpuinfo.codeName}", SMT = (int)cpuinfo.threadsPerCore > 1, Model = cpuinfo.model, ExtendedModel = cpuinfo.extModel, @@ -130,9 +130,9 @@ private void InitSystemInfo() private void ResetSmuAddresses() { - m.Ops.Smu.SMU_ADDR_MSG = SMU_ADDR_MSG; - m.Ops.Smu.SMU_ADDR_RSP = SMU_ADDR_RSP; - m.Ops.Smu.SMU_ADDR_ARG = SMU_ADDR_ARG; + cpuinfo.smu.SMU_ADDR_MSG = SMU_ADDR_MSG; + cpuinfo.smu.SMU_ADDR_RSP = SMU_ADDR_RSP; + cpuinfo.smu.SMU_ADDR_ARG = SMU_ADDR_ARG; textBoxCMDAddress.Text = $"0x{Convert.ToString(SMU_ADDR_MSG, 16).ToUpper()}"; textBoxRSPAddress.Text = $"0x{Convert.ToString(SMU_ADDR_RSP, 16).ToUpper()}"; @@ -152,7 +152,7 @@ private void DisplaySystemInfo() biosInfoLabel.Text = SI.BiosVersion; smuInfoLabel.Text = SI.GetSmuVersionString(); firmwareInfoLabel.Text = $"{SI.PatchLevel:X8}"; - cpuIdLabel.Text = $"{SI.GetCpuIdString()} ({m.Ops.CpuType})"; + cpuIdLabel.Text = $"{SI.GetCpuIdString()} ({cpuinfo.codeName})"; configInfoLabel.Text = $"{SI.CCDCount} CCD / {SI.CCXCount} CCX / {SI.PhysicalCoreCount} physical cores"; } @@ -160,7 +160,7 @@ private void InitForm() { InitSystemInfo(); - if (m.Ops.Smu.Version == 0) + if (cpuinfo.smu.Version == 0) { MessageBox.Show("Error getting SMU version!\n" + "Default SMU addresses are not responding to commands.", @@ -169,9 +169,9 @@ private void InitForm() } // Cache default addresses - SMU_ADDR_MSG = m.Ops.Smu.SMU_ADDR_MSG; - SMU_ADDR_RSP = m.Ops.Smu.SMU_ADDR_RSP; - SMU_ADDR_ARG = m.Ops.Smu.SMU_ADDR_ARG; + SMU_ADDR_MSG = cpuinfo.smu.SMU_ADDR_MSG; + SMU_ADDR_RSP = cpuinfo.smu.SMU_ADDR_RSP; + SMU_ADDR_ARG = cpuinfo.smu.SMU_ADDR_ARG; ResetSmuAddresses(); DisplaySystemInfo(); @@ -195,7 +195,7 @@ private void InitForm() comboBoxACF.SelectedIndex = index; comboBoxSCF.SelectedIndex = index; - var prochotEnabled = m.Ops.IsProchotEnabled(); + var prochotEnabled = cpu.Ops.IsProchotEnabled(); checkBoxPROCHOT.Checked = prochotEnabled; //checkBoxPROCHOT.Enabled = prochotEnabled; //buttonApplyPROCHOT.Enabled = prochotEnabled; @@ -203,14 +203,14 @@ private void InitForm() ToolTip toolTip = new ToolTip(); toolTip.SetToolTip(checkBoxPROCHOT, "Disables temperature throttling. Can be useful on extreme cooling."); - SetStatusText($"{m.Ops.CpuType}. Ready."); + SetStatusText($"{cpuinfo.codeName}. Ready."); } // TODO: Detect OC Mode and return PState freq if on auto private double GetCurrentMulti() { uint eax = default, edx = default; - if (m.Ols.Rdmsr(0xC0010293, ref eax, ref edx) != 1) + if (cpu.Ols.Rdmsr(0xC0010293, ref eax, ref edx) != 1) { SetStatusText($@"Error getting current frequency!"); return 0; @@ -235,7 +235,7 @@ private void PopulateCCDList(ComboBox.ObjectCollection l) private void ApplyFrequencyAllCoreSetting(int frequency) { - if (m.Ops.SendSmuCommand(m.Ops.Smu.SMU_MSG_SetOverclockFrequencyAllCores, Convert.ToUInt32(frequency))) + if (cpu.Ops.SendSmuCommand(cpuinfo.smu.SMU_MSG_SetOverclockFrequencyAllCores, Convert.ToUInt32(frequency))) SetStatusText(string.Format("Set frequency to {0} MHz!", (object)frequency)); else HandleError("Error setting frequency!"); @@ -243,7 +243,7 @@ private void ApplyFrequencyAllCoreSetting(int frequency) private void ApplyFrequencySingleCoreSetting(CoreListItem i, int frequency) { - if (m.Ops.SendSmuCommand(m.Ops.Smu.SMU_MSG_SetOverclockFrequencyPerCore, Convert.ToUInt32(((i.CCD << 4 | i.CCX % 2 & 15) << 4 | i.CORE % 4 & 15) << 20 | frequency & 0xFFFFF))) + if (cpu.Ops.SendSmuCommand(cpuinfo.smu.SMU_MSG_SetOverclockFrequencyPerCore, Convert.ToUInt32(((i.CCD << 4 | i.CCX % 2 & 15) << 4 | i.CORE % 4 & 15) << 20 | frequency & 0xFFFFF))) SetStatusText(string.Format("Set core {0} frequency to {1} MHz!", (object)i, (object)frequency)); else HandleError("Error setting frequency!"); @@ -251,7 +251,7 @@ private void ApplyFrequencySingleCoreSetting(CoreListItem i, int frequency) private void EnableOCMode(bool prochotEnabled = true) { - if (m.Ops.SendSmuCommand(m.Ops.Smu.SMU_MSG_EnableOcMode, prochotEnabled ? 0U : 0x1000000)) + if (cpu.Ops.SendSmuCommand(cpuinfo.smu.SMU_MSG_EnableOcMode, prochotEnabled ? 0U : 0x1000000)) SetStatusText(prochotEnabled ? "PROCHOT enabled." : "PROCHOT disabled."); else HandleError("Error setting OC Mode!"); @@ -259,7 +259,7 @@ private void EnableOCMode(bool prochotEnabled = true) private void DisableOCMode() { - if (m.Ops.SendSmuCommand(m.Ops.Smu.SMU_MSG_DisableOcMode, 0U)) + if (cpu.Ops.SendSmuCommand(cpuinfo.smu.SMU_MSG_DisableOcMode, 0U)) SetStatusText(string.Format("Set OK!")); else HandleError("Error disabling OC Mode!"); @@ -387,9 +387,9 @@ private void ApplySettings() TryConvertToUint(textBoxARGAddress.Text, out uint addrArg); TryConvertToUint(textBoxCMD.Text, out uint command); - m.Ops.Smu.SMU_ADDR_MSG = addrMsg; - m.Ops.Smu.SMU_ADDR_RSP = addrRsp; - m.Ops.Smu.SMU_ADDR_ARG = addrArg; + cpuinfo.smu.SMU_ADDR_MSG = addrMsg; + cpuinfo.smu.SMU_ADDR_RSP = addrRsp; + cpuinfo.smu.SMU_ADDR_ARG = addrArg; for (var i = 0; i < userArgs.Length; i++) { @@ -401,12 +401,12 @@ private void ApplySettings() } - Console.WriteLine("MSG Address: 0x" + Convert.ToString(m.Ops.Smu.SMU_ADDR_MSG, 16).ToUpper()); - Console.WriteLine("RSP Address: 0x" + Convert.ToString(m.Ops.Smu.SMU_ADDR_RSP, 16).ToUpper()); - Console.WriteLine("ARG0 Address: 0x" + Convert.ToString(m.Ops.Smu.SMU_ADDR_ARG, 16).ToUpper()); + Console.WriteLine("MSG Address: 0x" + Convert.ToString(cpuinfo.smu.SMU_ADDR_MSG, 16).ToUpper()); + Console.WriteLine("RSP Address: 0x" + Convert.ToString(cpuinfo.smu.SMU_ADDR_RSP, 16).ToUpper()); + Console.WriteLine("ARG0 Address: 0x" + Convert.ToString(cpuinfo.smu.SMU_ADDR_ARG, 16).ToUpper()); Console.WriteLine("ARG0 : 0x" + Convert.ToString(args[0], 16).ToUpper()); - SMU.Status status = m.Ops.SendSmuCommand(command, ref args); + SMU.Status status = cpu.Ops.SendSmuCommand(command, ref args); if (status == SMU.Status.OK) { @@ -443,7 +443,7 @@ private void HandlePciReadBtnClick() SetButtonsState(false); TryConvertToUint(textBoxPciAddress.Text, out uint address); - uint data = m.Ops.ReadDword(address); + uint data = cpu.Ops.ReadDword(address); textBoxPciValue.Text = $"0x{data:X8}"; @@ -468,7 +468,7 @@ private void HandlePciWriteBtnClick() TryConvertToUint(textBoxPciAddress.Text, out uint address); TryConvertToUint(textBoxPciValue.Text, out uint data); - if (m.Ops.SmuWriteReg(address, data)) + if (cpu.Ops.SmuWriteReg(address, data)) SetStatusText("Write OK."); else SetStatusText(Resources.Error); @@ -509,11 +509,11 @@ private SMU.Status TrySettings(uint msgAddr, uint rspAddr, uint argAddress, uint uint[] args = new uint[6]; args[0] = value; - m.Ops.Smu.SMU_ADDR_MSG = msgAddr; - m.Ops.Smu.SMU_ADDR_RSP = rspAddr; - m.Ops.Smu.SMU_ADDR_ARG = argAddress; + cpuinfo.smu.SMU_ADDR_MSG = msgAddr; + cpuinfo.smu.SMU_ADDR_RSP = rspAddr; + cpuinfo.smu.SMU_ADDR_ARG = argAddress; - return m.Ops.SendSmuCommand(cmd, ref args); + return cpu.Ops.SendSmuCommand(cmd, ref args); } private void ScanSmuRange(uint start, uint end, int step, byte offset) @@ -525,13 +525,13 @@ private void ScanSmuRange(uint start, uint end, int step, byte offset) uint smuRspAddress = start + offset; uint smuArgAddress = 0xF; - if (m.Ops.ReadDword(start) != 0xFFFFFFFF) + if (cpu.Ops.ReadDword(start) != 0xFFFFFFFF) { // Check if CMD-RSP pair returns correct status, while using a placeholder ARG address - if (TrySettings(start, smuRspAddress, smuArgAddress, m.Ops.Smu.SMU_MSG_TestMessage, 0x0) == SMU.Status.OK) + if (TrySettings(start, smuRspAddress, smuArgAddress, cpuinfo.smu.SMU_MSG_TestMessage, 0x0) == SMU.Status.OK) { // Send smu version command, so the corresponding ARG0 address changes its value - TrySettings(start, smuRspAddress, smuArgAddress, m.Ops.Smu.SMU_MSG_GetSmuVersion, 0x0); + TrySettings(start, smuRspAddress, smuArgAddress, cpuinfo.smu.SMU_MSG_GetSmuVersion, 0x0); bool match = false; smuArgAddress = smuRspAddress + 4; @@ -540,14 +540,14 @@ private void ScanSmuRange(uint start, uint end, int step, byte offset) while ((smuArgAddress <= end) && !match) { // Check if smu version major is in range - var currentRegValue = (m.Ops.ReadDword(smuArgAddress) & 0x00FF0000) >> 16; + var currentRegValue = (cpu.Ops.ReadDword(smuArgAddress) & 0x00FF0000) >> 16; Console.WriteLine($"REG: 0x{smuArgAddress:X8} Value: 0x{currentRegValue:X8}"); if (currentRegValue > 1 && currentRegValue <= 99) { // Send test message with an argument, using the potential ARG0 address var argValue = (uint)matches.Count * 2 + 99; - TrySettings(start, smuRspAddress, smuArgAddress, m.Ops.Smu.SMU_MSG_TestMessage, argValue); - currentRegValue = m.Ops.ReadDword(smuArgAddress); + TrySettings(start, smuRspAddress, smuArgAddress, cpuinfo.smu.SMU_MSG_TestMessage, argValue); + currentRegValue = cpu.Ops.ReadDword(smuArgAddress); Console.WriteLine($"REG: 0x{smuArgAddress:X8} Value: 0x{currentRegValue:X8}"); // Check the address for expected value (argument + 1) @@ -614,23 +614,23 @@ private void BackgroundWorkerTrySettings_DoWork(object sender, DoWorkEventArgs e SetStatusText("Scanning SMU addresses, please wait..."); })); - switch (m.Ops.CpuType) + switch (cpuinfo.codeName) { - case SMU.CPUType.RavenRidge: - case SMU.CPUType.Picasso: - case SMU.CPUType.Fenghuang: - case SMU.CPUType.Renoir: + case SMU.CodeName.RavenRidge: + case SMU.CodeName.Picasso: + case SMU.CodeName.Fenghuang: + case SMU.CodeName.Renoir: ScanSmuRange(0x03B10500, 0x03B10998, 8, 0x3C); ScanSmuRange(0x03B10A00, 0x03B10AFF, 4, 0x60); break; - case SMU.CPUType.PinnacleRidge: - case SMU.CPUType.SummitRidge: - case SMU.CPUType.Matisse: - case SMU.CPUType.Threadripper: + case SMU.CodeName.PinnacleRidge: + case SMU.CodeName.SummitRidge: + case SMU.CodeName.Matisse: + case SMU.CodeName.Threadripper: ScanSmuRange(0x03B10500, 0x03B10998, 8, 0x3C); ScanSmuRange(0x03B10500, 0x03B10AFF, 4, 0x4C); break; - case SMU.CPUType.Rome: + case SMU.CodeName.Rome: ScanSmuRange(0x03B10500, 0x03B10AFF, 4, 0x4C); break; default: @@ -801,7 +801,7 @@ private void btnPstateRead_Click(object sender, EventArgs e) { uint eax = default, edx = default; var pstateId = pstateIdBox.SelectedIndex; - if (m.Ols.Rdmsr(Convert.ToUInt32(Convert.ToInt64(0xC0010064) + pstateId), ref eax, ref edx) != 1) + if (cpu.Ols.Rdmsr(Convert.ToUInt32(Convert.ToInt64(0xC0010064) + pstateId), ref eax, ref edx) != 1) { SetStatusText($@"Error reading PState {pstateId}!"); return; @@ -854,7 +854,7 @@ private void btnPstateWrite_Click(object sender, EventArgs e) uint CpuDfsId = 0x0; uint CpuFid = 0x0; - if (m.Ols.Rdmsr(Convert.ToUInt32(Convert.ToInt64(0xC0010064) + pstateId), ref eax, ref edx) != 1) + if (cpu.Ols.Rdmsr(Convert.ToUInt32(Convert.ToInt64(0xC0010064) + pstateId), ref eax, ref edx) != 1) { SetStatusText($@"Error reading PState {pstateId}!"); return; @@ -885,10 +885,10 @@ public bool ApplyTscWorkaround() { uint eax = 0, edx = 0; - if (m.Ols.Rdmsr(0xC0010015, ref eax, ref edx) != -1) + if (cpu.Ols.Rdmsr(0xC0010015, ref eax, ref edx) != -1) { eax |= 0x200000; - return m.Ops.WriteMsr(0xC0010015, eax, edx); + return cpu.Ops.WriteMsr(0xC0010015, eax, edx); } SetStatusText($@"Error applying TSC fix!"); @@ -901,7 +901,7 @@ private bool WritePstateClick(int pstateId, uint eax, uint edx, int numanode = 0 if (!ApplyTscWorkaround()) return false; - if (!m.Ops.WriteMsr(Convert.ToUInt32(Convert.ToInt64(0xC0010064) + pstateId), eax, edx)) + if (!cpu.Ops.WriteMsr(Convert.ToUInt32(Convert.ToInt64(0xC0010064) + pstateId), eax, edx)) { SetStatusText($@"Error writing PState {pstateId}!"); return false; @@ -932,7 +932,7 @@ private void PciScan_DoWork(object sender, DoWorkEventArgs e) while (startReg <= endReg) { - var data = m.Ops.ReadDword(startReg); + var data = cpu.Ops.ReadDword(startReg); result += $"0x{startReg:X8}: 0x{data:X8}" + Environment.NewLine; startReg += 4; } @@ -987,7 +987,7 @@ private void ButtonApplyPROCHOT_Click(object sender, EventArgs e) DisableOCMode(); } EnableOCMode(checkBoxPROCHOT.Checked); - if (!checkBoxPROCHOT.Checked && m.Ops.IsProchotEnabled()) + if (!checkBoxPROCHOT.Checked && cpu.Ops.IsProchotEnabled()) { checkBoxPROCHOT.Checked = true; HandleError($@"Error, PROCHOT could not be disabled!"); @@ -1016,7 +1016,7 @@ private void ReadMsr_Task(object sender, DoWorkEventArgs e) while (startReg <= endReg) { uint eax = default, edx = default; - if (m.Ols.Rdmsr(startReg, ref eax, ref edx) == 1) + if (cpu.Ols.Rdmsr(startReg, ref eax, ref edx) == 1) { result += $"0x{startReg:X8}: 0x{edx:X8} 0x{eax:X8}" + Environment.NewLine; } @@ -1040,7 +1040,7 @@ private void ButtonMsrRead_Click(object sender, EventArgs e) { TryConvertToUint(textBoxMsrAddress.Text, out uint msr); uint eax = default, edx = default; - if (m.Ols.Rdmsr(msr, ref eax, ref edx) == 1) + if (cpu.Ols.Rdmsr(msr, ref eax, ref edx) == 1) { textBoxMsrEdx.Text = $"0x{edx:X8}"; textBoxMsrEax.Text = $"0x{eax:X8}"; @@ -1053,7 +1053,7 @@ private void ButtonMsrWrite_Click(object sender, EventArgs e) TryConvertToUint(textBoxMsrEax.Text, out uint eax); TryConvertToUint(textBoxMsrAddress.Text, out uint msr); - if (!m.Ops.WriteMsr(msr, eax, edx)) + if (!cpu.Ops.WriteMsr(msr, eax, edx)) { HandleError($@"Error writing MSR {textBoxMsrAddress.Text}!"); return; @@ -1080,23 +1080,23 @@ private void ReadCPUID_Task(object sender, DoWorkEventArgs e) uint LFuncStd = 0, LFuncExt = 0; uint eax = 0, ebx = 0, ecx = 0, edx = 0; - if (m.Ols.Cpuid(0x00000000, ref eax, ref ebx, ref ecx, ref edx) == 1) + if (cpu.Ols.Cpuid(0x00000000, ref eax, ref ebx, ref ecx, ref edx) == 1) LFuncStd = eax; - if (m.Ols.Cpuid(0x80000000, ref eax, ref ebx, ref ecx, ref edx) == 1) + if (cpu.Ols.Cpuid(0x80000000, ref eax, ref ebx, ref ecx, ref edx) == 1) LFuncExt = eax - 0x80000000; for (uint i = 0; i <= LFuncStd; ++i) { var index = 0x00000000 + i; - m.Ols.Cpuid(index, ref eax, ref ebx, ref ecx, ref edx); + cpu.Ols.Cpuid(index, ref eax, ref ebx, ref ecx, ref edx); result += $"0x{index:X8}: 0x{eax:X8} 0x{ebx:X8} 0x{ecx:X8} 0x{edx:X8}" + Environment.NewLine; } for (uint i = 0; i <= LFuncExt; ++i) { var index = 0x80000000 + i; - m.Ols.Cpuid(index, ref eax, ref ebx, ref ecx, ref edx); + cpu.Ols.Cpuid(index, ref eax, ref ebx, ref ecx, ref edx); result += $"0x{index:X8}: 0x{eax:X8} 0x{ebx:X8} 0x{ecx:X8} 0x{edx:X8}" + Environment.NewLine; } @@ -1116,7 +1116,7 @@ private void ButtonCPUIDRead_Click(object sender, EventArgs e) { TryConvertToUint(textBoxCPUIDAddress.Text, out uint index); uint eax = 0, ebx = 0, ecx = 0, edx = 0; - if (m.Ols.Cpuid(index, ref eax, ref ebx, ref ecx, ref edx) == 1) + if (cpu.Ols.Cpuid(index, ref eax, ref ebx, ref ecx, ref edx) == 1) { textBoxCPUIDeax.Text = $"0x{eax:X8}"; textBoxCPUIDebx.Text = $"0x{ebx:X8}"; @@ -1132,7 +1132,7 @@ private void ButtonCPUIDScan_Click(object sender, EventArgs e) private void ButtonPMTable_Click(object sender, EventArgs e) { - new Thread(() => new PowerTableMonitor(m.Ops).ShowDialog()).Start(); + new Thread(() => new PowerTableMonitor(cpu.Ops).ShowDialog()).Start(); } private void ButtonSMUMonitor_Click(object sender, EventArgs e) @@ -1141,7 +1141,7 @@ private void ButtonSMUMonitor_Click(object sender, EventArgs e) TryConvertToUint(textBoxRSPAddress.Text, out uint addrRsp); TryConvertToUint(textBoxARGAddress.Text, out uint addrArg); - new Thread(() => new SMUMonitor(m.Ops, addrMsg, addrArg, addrRsp).ShowDialog()).Start(); + new Thread(() => new SMUMonitor(cpu.Ops, addrMsg, addrArg, addrRsp).ShowDialog()).Start(); } } } From 35b2818d12ecbf95310dfddfc3aeabd8e3b3e1b7 Mon Sep 17 00:00:00 2001 From: Ivan Rusanov Date: Fri, 28 May 2021 19:14:22 +0300 Subject: [PATCH 3/7] Use core dll --- PowerTableMonitor.cs | 58 ++-------- Prebuilt/ZenStates-Core.dll | Bin 0 -> 52224 bytes SMUMonitor.cs | 13 ++- SettingsForm.Designer.cs | 35 +++--- SettingsForm.cs | 225 +++++++++++++++--------------------- ZenStatesDebugTool.csproj | 11 +- ZenStatesDebugTool.sln | 9 -- 7 files changed, 127 insertions(+), 224 deletions(-) create mode 100644 Prebuilt/ZenStates-Core.dll diff --git a/PowerTableMonitor.cs b/PowerTableMonitor.cs index f522b91..f5f5aea 100644 --- a/PowerTableMonitor.cs +++ b/PowerTableMonitor.cs @@ -12,11 +12,7 @@ namespace ZenStatesDebugTool { public partial class PowerTableMonitor : Form { - private readonly PowerTable PowerTable; - private uint dramBaseAddress = 0; - private readonly UIntPtr dramPtr; - private readonly Ops OPS; - private readonly uint[] table = new uint[PowerTable.tableSize / 4]; + private readonly Cpu CPU; readonly Timer PowerCfgTimer = new Timer(); private readonly BindingList list = new BindingList(); private class PowerMonitorItem @@ -26,37 +22,6 @@ private class PowerMonitorItem public string Value { get; set; } } - private void ReadPowerConfig() - { - if (dramBaseAddress > 0) - { - try - { - uint data = 0; - - if (OPS.TransferTableToDram() != SMU.Status.OK) - OPS.TransferTableToDram(); // retry - - for (int i = 0; i < table.Length; ++i) - { - InteropMethods.GetPhysLong(dramPtr + (i * 0x4), out data); - table[i] = data; - } - - if (table.Any(v => v != 0)) - PowerTable.Table = table; - } - catch (EntryPointNotFoundException ex) - { - throw new ApplicationException(ex.Message); - } - catch (DllNotFoundException ex) - { - throw new ApplicationException(ex.Message); - } - } - } - private void FillInData(uint[] table) { list.Clear(); @@ -89,30 +54,23 @@ private void RefreshData(uint[] table) private void PowerCfgTimer_Tick(object sender, EventArgs e) { Console.WriteLine("refreshing"); - ReadPowerConfig(); - RefreshData(PowerTable.Table); + if (CPU.RefreshPowerTable() == SMU.Status.OK) + RefreshData(CPU.powerTable.Table); } - public PowerTableMonitor(Ops ops) + public PowerTableMonitor(Cpu cpu) { - OPS = ops; - PowerTable = new PowerTable(OPS.cpuinfo.smu.SMU_TYPE); + CPU = cpu; PowerCfgTimer.Interval = 2000; PowerCfgTimer.Tick += new EventHandler(PowerCfgTimer_Tick); InitializeComponent(); dataGridView1.DataSource = list; - - // Get first base address - dramBaseAddress = (uint)(OPS.GetDramBaseAddress() & 0xFFFFFFFF); - if (dramBaseAddress > 0) - { - dramPtr = new UIntPtr(dramBaseAddress); - ReadPowerConfig(); - } - FillInData(PowerTable.Table); + cpu.RefreshPowerTable(); + + FillInData(cpu.powerTable.Table); } private void PowerTableMonitor_FormClosing(object sender, FormClosingEventArgs e) diff --git a/Prebuilt/ZenStates-Core.dll b/Prebuilt/ZenStates-Core.dll new file mode 100644 index 0000000000000000000000000000000000000000..da8171170af10f31da4a0a6bc915165d1de013b0 GIT binary patch literal 52224 zcmeFa3w&HvwLiYknVB<>q-jpl=G7!KX_GQd($F?7B$h|gBy9(hCM4;TVme8t&9q4- z%uGs4n3`e%ks=_V=;cxHg;#u|AfgmOL;)}I5Fda=3!)BBXx7;_$p=AU2Q_N zD-Ln!8?hgnr5zIs16j&4As&Q8Go-#>;vOJgA(G3yYSfzqRDb?!f*x}EbBLx($dvw1 z-z6jw{=W8t5S`2^;%@4Qseb`QWJ9(Lb`4W?C&B?CJQ;cq@cIl~myGO70_T1Q1Uhc3 ztTzz<1%%j97f-|ofQ-7KZPd_*SZ$Fe3|Cz|G8}^;)m5O*+y_6fOqgjBVvSuQ#Bb0p z`lGt3!X>tB7vd*}WG}PkpCg+b0eF$ro3+=ptves>WBt`tcI9E0|B2Wg$_LU<%2d&~GID0=u4I%5CV+Cw-}1PcVgn zrS#X5zRa#Cn1aue{)?n9x9bU}&|cC%LVCYlPcY>(^uHs0z^*5lLQ5$9-$;)x$!s6N z6r6zcZUy>E&mns4YQNMB>u z6HFBt`YT9ZYu6J@6&m`Fl76XOPcT(v=s!dHI=h}=s@TxqMf#KNdV(o9DYfqb(l4{? z38vtrq<@n1%k6rCDL5(Ve?|Hgc0IuqoRsu`Bz?VIPcQ{1CH>o^UuoA9Ou

KUal* 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 literal 0 HcmV?d00001 diff --git a/SMUMonitor.cs b/SMUMonitor.cs index f825b20..2260599 100644 --- a/SMUMonitor.cs +++ b/SMUMonitor.cs @@ -8,7 +8,7 @@ namespace ZenStatesDebugTool { public partial class SMUMonitor : Form { - private readonly Ops OPS; + private readonly Cpu CPU; readonly System.Windows.Forms.Timer MonitorTimer = new System.Windows.Forms.Timer(); private readonly BindingList list = new BindingList(); private uint prevCmdValue; @@ -23,9 +23,9 @@ private class SmuMonitorItem public string Rsp { get; set; } } - public SMUMonitor(Ops ops, uint addrMsg, uint addrArg, uint addrRsp) + public SMUMonitor(Cpu cpu, uint addrMsg, uint addrArg, uint addrRsp) { - OPS = ops; + CPU = cpu; SMU_ADDR_MSG = addrMsg; SMU_ADDR_ARG = addrArg; SMU_ADDR_RSP = addrRsp; @@ -47,13 +47,14 @@ private void AddLine() uint rsp = 0; uint arg = 0; - OPS.SmuReadReg(SMU_ADDR_MSG, ref msg); + msg = CPU.ReadDword(SMU_ADDR_MSG); if (msg != prevCmdValue) { prevCmdValue = msg; - if (OPS.SmuReadReg(SMU_ADDR_RSP, ref rsp)) - OPS.SmuReadReg(SMU_ADDR_ARG, ref arg); + rsp = CPU.ReadDword(SMU_ADDR_RSP); + if (rsp != 0) + arg = CPU.ReadDword(SMU_ADDR_ARG); new Thread(() => { list.Add(new SmuMonitorItem diff --git a/SettingsForm.Designer.cs b/SettingsForm.Designer.cs index 6dff430..86d6792 100644 --- a/SettingsForm.Designer.cs +++ b/SettingsForm.Designer.cs @@ -19,7 +19,6 @@ protected override void Dispose(bool disposing) if (disposing && (components != null)) { cpu.Dispose(); - hMutexPci.Dispose(); components.Dispose(); } base.Dispose(disposing); @@ -141,7 +140,7 @@ private void InitializeComponent() this.firmwareInfoLabel = new System.Windows.Forms.Label(); this.label24 = new System.Windows.Forms.Label(); this.label28 = new System.Windows.Forms.Label(); - this.extendedModelInfoLabel = new System.Windows.Forms.Label(); + this.modelInfoLabel = new System.Windows.Forms.Label(); this.packageTypeInfoLabel = new System.Windows.Forms.Label(); this.label29 = new System.Windows.Forms.Label(); this.configInfoLabel = new System.Windows.Forms.Label(); @@ -1309,7 +1308,7 @@ private void InitializeComponent() this.btnPstateWrite.TabIndex = 11; this.btnPstateWrite.Text = "Write"; this.btnPstateWrite.UseVisualStyleBackColor = true; - this.btnPstateWrite.Click += new System.EventHandler(this.btnPstateWrite_Click); + this.btnPstateWrite.Click += new System.EventHandler(this.BtnPstateWrite_Click); // // btnPstateRead // @@ -1320,7 +1319,7 @@ private void InitializeComponent() this.btnPstateRead.TabIndex = 12; this.btnPstateRead.Text = "Read"; this.btnPstateRead.UseVisualStyleBackColor = true; - this.btnPstateRead.Click += new System.EventHandler(this.btnPstateRead_Click); + this.btnPstateRead.Click += new System.EventHandler(this.BtnPstateRead_Click); // // tabPageInfo // @@ -1356,7 +1355,7 @@ private void InitializeComponent() this.tableLayoutPanel3.Controls.Add(this.firmwareInfoLabel, 1, 8); this.tableLayoutPanel3.Controls.Add(this.label24, 0, 2); this.tableLayoutPanel3.Controls.Add(this.label28, 0, 3); - this.tableLayoutPanel3.Controls.Add(this.extendedModelInfoLabel, 1, 2); + this.tableLayoutPanel3.Controls.Add(this.modelInfoLabel, 1, 2); this.tableLayoutPanel3.Controls.Add(this.packageTypeInfoLabel, 1, 3); this.tableLayoutPanel3.Controls.Add(this.label29, 0, 4); this.tableLayoutPanel3.Controls.Add(this.configInfoLabel, 1, 4); @@ -1391,7 +1390,7 @@ private void InitializeComponent() this.buttonExport.TabIndex = 1; this.buttonExport.Text = "Debug Report"; this.buttonExport.UseVisualStyleBackColor = true; - this.buttonExport.Click += new System.EventHandler(this.buttonExport_Click); + this.buttonExport.Click += new System.EventHandler(this.ButtonExport_Click); // // smuInfoLabel // @@ -1573,7 +1572,7 @@ private void InitializeComponent() this.label24.Name = "label24"; this.label24.Size = new System.Drawing.Size(65, 23); this.label24.TabIndex = 14; - this.label24.Text = "Ext. Model"; + this.label24.Text = "Model"; this.label24.TextAlign = System.Drawing.ContentAlignment.MiddleLeft; // // label28 @@ -1587,17 +1586,17 @@ private void InitializeComponent() this.label28.Text = "Package"; this.label28.TextAlign = System.Drawing.ContentAlignment.MiddleLeft; // - // extendedModelInfoLabel + // modelInfoLabel // - this.extendedModelInfoLabel.AutoSize = true; - this.extendedModelInfoLabel.Dock = System.Windows.Forms.DockStyle.Fill; - this.extendedModelInfoLabel.Location = new System.Drawing.Point(74, 51); - this.extendedModelInfoLabel.Name = "extendedModelInfoLabel"; - this.extendedModelInfoLabel.Padding = new System.Windows.Forms.Padding(5); - this.extendedModelInfoLabel.Size = new System.Drawing.Size(250, 23); - this.extendedModelInfoLabel.TabIndex = 16; - this.extendedModelInfoLabel.Text = "-"; - this.extendedModelInfoLabel.TextAlign = System.Drawing.ContentAlignment.MiddleLeft; + this.modelInfoLabel.AutoSize = true; + this.modelInfoLabel.Dock = System.Windows.Forms.DockStyle.Fill; + this.modelInfoLabel.Location = new System.Drawing.Point(74, 51); + this.modelInfoLabel.Name = "modelInfoLabel"; + this.modelInfoLabel.Padding = new System.Windows.Forms.Padding(5); + this.modelInfoLabel.Size = new System.Drawing.Size(250, 23); + this.modelInfoLabel.TabIndex = 16; + this.modelInfoLabel.Text = "-"; + this.modelInfoLabel.TextAlign = System.Drawing.ContentAlignment.MiddleLeft; // // packageTypeInfoLabel // @@ -1854,7 +1853,7 @@ private void InitializeComponent() private Label firmwareInfoLabel; private Label label24; private Label label28; - private Label extendedModelInfoLabel; + private Label modelInfoLabel; private Label packageTypeInfoLabel; private Label label29; private Label configInfoLabel; diff --git a/SettingsForm.cs b/SettingsForm.cs index 65b26c4..82dc02b 100644 --- a/SettingsForm.cs +++ b/SettingsForm.cs @@ -19,13 +19,9 @@ public partial class SettingsForm : Form //private static readonly int Threads = Convert.ToInt32(Environment.GetEnvironmentVariable("NUMBER_OF_PROCESSORS")); private BackgroundWorker backgroundWorker1; private NUMAUtil _numaUtil; - private readonly ZenCpu cpu; - private SystemInfo SI; + private Cpu cpu = new Cpu(); List matches; private int _coreCount; - private Ops.CPUInfo cpuinfo; - - readonly Mutex hMutexPci; private uint SMU_ADDR_MSG; private uint SMU_ADDR_RSP; @@ -56,8 +52,6 @@ public SettingsForm() { InitializeComponent(); - hMutexPci = new Mutex(); - _numaUtil = new NUMAUtil(); textBoxResult.Text = $@"Detected NUMA nodes. ({_numaUtil.HighestNumaNode + 1})" + textBoxResult.Text; @@ -65,8 +59,6 @@ public SettingsForm() try { - cpu = new ZenCpu(); - cpuinfo = cpu.Ops.cpuinfo; InitForm(); } catch (ApplicationException ex) @@ -85,54 +77,11 @@ private static void ExitApplication() Environment.Exit(1); } - private void InitSystemInfo() - { - if (cpuinfo.family != SMU.CpuFamily.FAMILY_17H && cpuinfo.family != SMU.CpuFamily.FAMILY_19H) - { - MessageBox.Show("CPU is not supported.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); - ExitApplication(); - } - - SI = new SystemInfo - { - CpuId = cpuinfo.cpuid, - CpuName = cpuinfo.cpuName, - NodesPerProcessor = cpu.Ops.GetCpuNodes(), - PackageType = cpuinfo.packageType, - PatchLevel = cpuinfo.patchLevel, - SmuVersion = cpuinfo.smuVersion, - FusedCoreCount = (int)cpuinfo.cores, - Threads = (int)cpuinfo.logicalCores, - CCDCount = (int)cpuinfo.ccds, - CCXCount = (int)cpuinfo.ccxs, - NumCoresInCCX = (int)cpuinfo.coresPerCcx, - CodeName = $"{cpuinfo.codeName}", - SMT = (int)cpuinfo.threadsPerCore > 1, - Model = cpuinfo.model, - ExtendedModel = cpuinfo.extModel, - }; - - ManagementObjectSearcher searcher = new ManagementObjectSearcher("SELECT * FROM Win32_BaseBoard"); - foreach (ManagementObject obj in searcher.Get()) - { - SI.MbVendor = ((string)obj["Manufacturer"]).Trim(); - SI.MbName = ((string)obj["Product"]).Trim(); - } - if (searcher != null) searcher.Dispose(); - - searcher = new ManagementObjectSearcher("SELECT * FROM Win32_BIOS"); - foreach (ManagementObject obj in searcher.Get()) - { - SI.BiosVersion = ((string)obj["SMBIOSBIOSVersion"]).Trim(); - } - if (searcher != null) searcher.Dispose(); - } - private void ResetSmuAddresses() { - cpuinfo.smu.SMU_ADDR_MSG = SMU_ADDR_MSG; - cpuinfo.smu.SMU_ADDR_RSP = SMU_ADDR_RSP; - cpuinfo.smu.SMU_ADDR_ARG = SMU_ADDR_ARG; + cpu.smu.Rsmu.SMU_ADDR_MSG = SMU_ADDR_MSG; + cpu.smu.Rsmu.SMU_ADDR_RSP = SMU_ADDR_RSP; + cpu.smu.Rsmu.SMU_ADDR_ARG = SMU_ADDR_ARG; textBoxCMDAddress.Text = $"0x{Convert.ToString(SMU_ADDR_MSG, 16).ToUpper()}"; textBoxRSPAddress.Text = $"0x{Convert.ToString(SMU_ADDR_RSP, 16).ToUpper()}"; @@ -144,23 +93,21 @@ private void ResetSmuAddresses() private void DisplaySystemInfo() { - cpuInfoLabel.Text = SI.CpuName; - extendedModelInfoLabel.Text = $"{SI.ExtendedModel:X8}"; - packageTypeInfoLabel.Text = $"{SI.PackageType} ({(SMU.PackageType)SI.PackageType})"; - mbVendorInfoLabel.Text = SI.MbVendor; - mbModelInfoLabel.Text = SI.MbName; - biosInfoLabel.Text = SI.BiosVersion; - smuInfoLabel.Text = SI.GetSmuVersionString(); - firmwareInfoLabel.Text = $"{SI.PatchLevel:X8}"; - cpuIdLabel.Text = $"{SI.GetCpuIdString()} ({cpuinfo.codeName})"; - configInfoLabel.Text = $"{SI.CCDCount} CCD / {SI.CCXCount} CCX / {SI.PhysicalCoreCount} physical cores"; + cpuInfoLabel.Text = cpu.systemInfo.CpuName; + modelInfoLabel.Text = $"{cpu.systemInfo.Model:X2}"; + packageTypeInfoLabel.Text = $"{cpu.systemInfo.PackageType} ({(Cpu.PackageType)cpu.systemInfo.PackageType})"; + mbVendorInfoLabel.Text = cpu.systemInfo.MbVendor; + mbModelInfoLabel.Text = cpu.systemInfo.MbName; + biosInfoLabel.Text = cpu.systemInfo.BiosVersion; + smuInfoLabel.Text = cpu.systemInfo.GetSmuVersionString(); + firmwareInfoLabel.Text = $"{cpu.systemInfo.PatchLevel:X8}"; + cpuIdLabel.Text = $"{cpu.systemInfo.GetCpuIdString()} ({cpu.info.codeName})"; + configInfoLabel.Text = $"{cpu.systemInfo.CCDCount} CCD / {cpu.systemInfo.CCXCount} CCX / {cpu.systemInfo.PhysicalCoreCount} physical cores"; } private void InitForm() { - InitSystemInfo(); - - if (cpuinfo.smu.Version == 0) + if (cpu.smu.Version == 0) { MessageBox.Show("Error getting SMU version!\n" + "Default SMU addresses are not responding to commands.", @@ -169,21 +116,21 @@ private void InitForm() } // Cache default addresses - SMU_ADDR_MSG = cpuinfo.smu.SMU_ADDR_MSG; - SMU_ADDR_RSP = cpuinfo.smu.SMU_ADDR_RSP; - SMU_ADDR_ARG = cpuinfo.smu.SMU_ADDR_ARG; + SMU_ADDR_MSG = cpu.smu.Rsmu.SMU_ADDR_MSG; + SMU_ADDR_RSP = cpu.smu.Rsmu.SMU_ADDR_RSP; + SMU_ADDR_ARG = cpu.smu.Rsmu.SMU_ADDR_ARG; ResetSmuAddresses(); DisplaySystemInfo(); pstateIdBox.SelectedIndex = 0; - pstateDid.KeyDown += pstateFidDid_KeyDown; - pstateDid.KeyPress += pstateFidDid_KeyPress; - pstateDid.KeyUp += pstateFidDid_KeyUp; - pstateFid.KeyDown += pstateFidDid_KeyDown; - pstateFid.KeyPress += pstateFidDid_KeyPress; - pstateFid.KeyUp += pstateFidDid_KeyUp; + pstateDid.KeyDown += PstateFidDid_KeyDown; + pstateDid.KeyPress += PstateFidDid_KeyPress; + pstateDid.KeyUp += PstateFidDid_KeyUp; + pstateFid.KeyDown += PstateFidDid_KeyDown; + pstateFid.KeyPress += PstateFidDid_KeyPress; + pstateFid.KeyUp += PstateFidDid_KeyUp; PopulateFrequencyList(comboBoxACF.Items); PopulateFrequencyList(comboBoxSCF.Items); @@ -195,7 +142,7 @@ private void InitForm() comboBoxACF.SelectedIndex = index; comboBoxSCF.SelectedIndex = index; - var prochotEnabled = cpu.Ops.IsProchotEnabled(); + var prochotEnabled = cpu.IsProchotEnabled(); checkBoxPROCHOT.Checked = prochotEnabled; //checkBoxPROCHOT.Enabled = prochotEnabled; //buttonApplyPROCHOT.Enabled = prochotEnabled; @@ -203,20 +150,17 @@ private void InitForm() ToolTip toolTip = new ToolTip(); toolTip.SetToolTip(checkBoxPROCHOT, "Disables temperature throttling. Can be useful on extreme cooling."); - SetStatusText($"{cpuinfo.codeName}. Ready."); + SetStatusText($"{cpu.info.codeName}. Ready."); } // TODO: Detect OC Mode and return PState freq if on auto private double GetCurrentMulti() { - uint eax = default, edx = default; - if (cpu.Ols.Rdmsr(0xC0010293, ref eax, ref edx) != 1) - { + double multi = cpu.GetCoreMulti(); + if (multi == 0) SetStatusText($@"Error getting current frequency!"); - return 0; - } - return 25 * (eax & 0xFF) / (12.5 * (eax >> 8 & 0x3F)); + return multi; } private void PopulateFrequencyList(ComboBox.ObjectCollection l) @@ -235,7 +179,7 @@ private void PopulateCCDList(ComboBox.ObjectCollection l) private void ApplyFrequencyAllCoreSetting(int frequency) { - if (cpu.Ops.SendSmuCommand(cpuinfo.smu.SMU_MSG_SetOverclockFrequencyAllCores, Convert.ToUInt32(frequency))) + if (cpu.SendSmuCommand(cpu.smu.Rsmu, cpu.smu.Rsmu.SMU_MSG_SetOverclockFrequencyAllCores, Convert.ToUInt32(frequency))) SetStatusText(string.Format("Set frequency to {0} MHz!", (object)frequency)); else HandleError("Error setting frequency!"); @@ -243,7 +187,7 @@ private void ApplyFrequencyAllCoreSetting(int frequency) private void ApplyFrequencySingleCoreSetting(CoreListItem i, int frequency) { - if (cpu.Ops.SendSmuCommand(cpuinfo.smu.SMU_MSG_SetOverclockFrequencyPerCore, Convert.ToUInt32(((i.CCD << 4 | i.CCX % 2 & 15) << 4 | i.CORE % 4 & 15) << 20 | frequency & 0xFFFFF))) + if (cpu.SendSmuCommand(cpu.smu.Rsmu, cpu.smu.Rsmu.SMU_MSG_SetOverclockFrequencyPerCore, Convert.ToUInt32(((i.CCD << 4 | i.CCX % 2 & 15) << 4 | i.CORE % 4 & 15) << 20 | frequency & 0xFFFFF))) SetStatusText(string.Format("Set core {0} frequency to {1} MHz!", (object)i, (object)frequency)); else HandleError("Error setting frequency!"); @@ -251,7 +195,7 @@ private void ApplyFrequencySingleCoreSetting(CoreListItem i, int frequency) private void EnableOCMode(bool prochotEnabled = true) { - if (cpu.Ops.SendSmuCommand(cpuinfo.smu.SMU_MSG_EnableOcMode, prochotEnabled ? 0U : 0x1000000)) + if (cpu.SendSmuCommand(cpu.smu.Rsmu, cpu.smu.Rsmu.SMU_MSG_EnableOcMode, prochotEnabled ? 0U : 0x1000000)) SetStatusText(prochotEnabled ? "PROCHOT enabled." : "PROCHOT disabled."); else HandleError("Error setting OC Mode!"); @@ -259,7 +203,7 @@ private void EnableOCMode(bool prochotEnabled = true) private void DisableOCMode() { - if (cpu.Ops.SendSmuCommand(cpuinfo.smu.SMU_MSG_DisableOcMode, 0U)) + if (cpu.DisableOcMode() == SMU.Status.OK) SetStatusText(string.Format("Set OK!")); else HandleError("Error disabling OC Mode!"); @@ -387,9 +331,9 @@ private void ApplySettings() TryConvertToUint(textBoxARGAddress.Text, out uint addrArg); TryConvertToUint(textBoxCMD.Text, out uint command); - cpuinfo.smu.SMU_ADDR_MSG = addrMsg; - cpuinfo.smu.SMU_ADDR_RSP = addrRsp; - cpuinfo.smu.SMU_ADDR_ARG = addrArg; + cpu.smu.Rsmu.SMU_ADDR_MSG = addrMsg; + cpu.smu.Rsmu.SMU_ADDR_RSP = addrRsp; + cpu.smu.Rsmu.SMU_ADDR_ARG = addrArg; for (var i = 0; i < userArgs.Length; i++) { @@ -401,12 +345,12 @@ private void ApplySettings() } - Console.WriteLine("MSG Address: 0x" + Convert.ToString(cpuinfo.smu.SMU_ADDR_MSG, 16).ToUpper()); - Console.WriteLine("RSP Address: 0x" + Convert.ToString(cpuinfo.smu.SMU_ADDR_RSP, 16).ToUpper()); - Console.WriteLine("ARG0 Address: 0x" + Convert.ToString(cpuinfo.smu.SMU_ADDR_ARG, 16).ToUpper()); + Console.WriteLine("MSG Address: 0x" + Convert.ToString(cpu.smu.Rsmu.SMU_ADDR_MSG, 16).ToUpper()); + Console.WriteLine("RSP Address: 0x" + Convert.ToString(cpu.smu.Rsmu.SMU_ADDR_RSP, 16).ToUpper()); + Console.WriteLine("ARG0 Address: 0x" + Convert.ToString(cpu.smu.Rsmu.SMU_ADDR_ARG, 16).ToUpper()); Console.WriteLine("ARG0 : 0x" + Convert.ToString(args[0], 16).ToUpper()); - SMU.Status status = cpu.Ops.SendSmuCommand(command, ref args); + SMU.Status status = cpu.SendSmuCommand(cpu.smu.Rsmu, command, ref args); if (status == SMU.Status.OK) { @@ -443,7 +387,7 @@ private void HandlePciReadBtnClick() SetButtonsState(false); TryConvertToUint(textBoxPciAddress.Text, out uint address); - uint data = cpu.Ops.ReadDword(address); + uint data = cpu.ReadDword(address); textBoxPciValue.Text = $"0x{data:X8}"; @@ -468,7 +412,11 @@ private void HandlePciWriteBtnClick() TryConvertToUint(textBoxPciAddress.Text, out uint address); TryConvertToUint(textBoxPciValue.Text, out uint data); - if (cpu.Ops.SmuWriteReg(address, data)) + bool res = false; + if (cpu.Ols.WritePciConfigDwordEx(cpu.smu.SMU_PCI_ADDR, cpu.smu.SMU_OFFSET_ADDR, address) == 1) + res = (cpu.Ols.WritePciConfigDwordEx(cpu.smu.SMU_PCI_ADDR, cpu.smu.SMU_OFFSET_DATA, data) == 1); + + if (res) SetStatusText("Write OK."); else SetStatusText(Resources.Error); @@ -509,11 +457,11 @@ private SMU.Status TrySettings(uint msgAddr, uint rspAddr, uint argAddress, uint uint[] args = new uint[6]; args[0] = value; - cpuinfo.smu.SMU_ADDR_MSG = msgAddr; - cpuinfo.smu.SMU_ADDR_RSP = rspAddr; - cpuinfo.smu.SMU_ADDR_ARG = argAddress; + cpu.smu.Rsmu.SMU_ADDR_MSG = msgAddr; + cpu.smu.Rsmu.SMU_ADDR_RSP = rspAddr; + cpu.smu.Rsmu.SMU_ADDR_ARG = argAddress; - return cpu.Ops.SendSmuCommand(cmd, ref args); + return cpu.SendSmuCommand(cpu.smu.Rsmu, cmd, ref args); } private void ScanSmuRange(uint start, uint end, int step, byte offset) @@ -525,13 +473,13 @@ private void ScanSmuRange(uint start, uint end, int step, byte offset) uint smuRspAddress = start + offset; uint smuArgAddress = 0xF; - if (cpu.Ops.ReadDword(start) != 0xFFFFFFFF) + if (cpu.ReadDword(start) != 0xFFFFFFFF) { // Check if CMD-RSP pair returns correct status, while using a placeholder ARG address - if (TrySettings(start, smuRspAddress, smuArgAddress, cpuinfo.smu.SMU_MSG_TestMessage, 0x0) == SMU.Status.OK) + if (TrySettings(start, smuRspAddress, smuArgAddress, cpu.smu.Rsmu.SMU_MSG_TestMessage, 0x0) == SMU.Status.OK) { // Send smu version command, so the corresponding ARG0 address changes its value - TrySettings(start, smuRspAddress, smuArgAddress, cpuinfo.smu.SMU_MSG_GetSmuVersion, 0x0); + TrySettings(start, smuRspAddress, smuArgAddress, cpu.smu.Rsmu.SMU_MSG_GetSmuVersion, 0x0); bool match = false; smuArgAddress = smuRspAddress + 4; @@ -540,14 +488,14 @@ private void ScanSmuRange(uint start, uint end, int step, byte offset) while ((smuArgAddress <= end) && !match) { // Check if smu version major is in range - var currentRegValue = (cpu.Ops.ReadDword(smuArgAddress) & 0x00FF0000) >> 16; + var currentRegValue = (cpu.ReadDword(smuArgAddress) & 0x00FF0000) >> 16; Console.WriteLine($"REG: 0x{smuArgAddress:X8} Value: 0x{currentRegValue:X8}"); if (currentRegValue > 1 && currentRegValue <= 99) { // Send test message with an argument, using the potential ARG0 address var argValue = (uint)matches.Count * 2 + 99; - TrySettings(start, smuRspAddress, smuArgAddress, cpuinfo.smu.SMU_MSG_TestMessage, argValue); - currentRegValue = cpu.Ops.ReadDword(smuArgAddress); + TrySettings(start, smuRspAddress, smuArgAddress, cpu.smu.Rsmu.SMU_MSG_TestMessage, argValue); + currentRegValue = cpu.ReadDword(smuArgAddress); Console.WriteLine($"REG: 0x{smuArgAddress:X8} Value: 0x{currentRegValue:X8}"); // Check the address for expected value (argument + 1) @@ -614,23 +562,27 @@ private void BackgroundWorkerTrySettings_DoWork(object sender, DoWorkEventArgs e SetStatusText("Scanning SMU addresses, please wait..."); })); - switch (cpuinfo.codeName) + switch (cpu.info.codeName) { - case SMU.CodeName.RavenRidge: - case SMU.CodeName.Picasso: - case SMU.CodeName.Fenghuang: - case SMU.CodeName.Renoir: + case Cpu.CodeName.RavenRidge: + case Cpu.CodeName.Picasso: + case Cpu.CodeName.FireFlight: + case Cpu.CodeName.Dali: + case Cpu.CodeName.Renoir: ScanSmuRange(0x03B10500, 0x03B10998, 8, 0x3C); ScanSmuRange(0x03B10A00, 0x03B10AFF, 4, 0x60); break; - case SMU.CodeName.PinnacleRidge: - case SMU.CodeName.SummitRidge: - case SMU.CodeName.Matisse: - case SMU.CodeName.Threadripper: + case Cpu.CodeName.PinnacleRidge: + case Cpu.CodeName.SummitRidge: + case Cpu.CodeName.Matisse: + case Cpu.CodeName.Whitehaven: + case Cpu.CodeName.Naples: + case Cpu.CodeName.Colfax: + case Cpu.CodeName.Vermeer: ScanSmuRange(0x03B10500, 0x03B10998, 8, 0x3C); ScanSmuRange(0x03B10500, 0x03B10AFF, 4, 0x4C); break; - case SMU.CodeName.Rome: + case Cpu.CodeName.Rome: ScanSmuRange(0x03B10500, 0x03B10AFF, 4, 0x4C); break; default: @@ -688,18 +640,18 @@ public string GenerateReportJson() writer.WritePropertyName("OSVersion"); writer.WriteValue(new ComputerInfo().OSFullName); - Type type = SI.GetType(); + Type type = cpu.systemInfo.GetType(); PropertyInfo[] properties = type.GetProperties(); foreach (PropertyInfo property in properties) { writer.WritePropertyName(property.Name); if (property.Name == "CpuId" || property.Name == "PatchLevel") - writer.WriteValue($"{property.GetValue(SI, null):X8}"); + writer.WriteValue($"{property.GetValue(cpu.systemInfo, null):X8}"); else if (property.Name == "SmuVersion") - writer.WriteValue(SI.GetSmuVersionString()); + writer.WriteValue(cpu.systemInfo.GetSmuVersionString()); else - writer.WriteValue(property.GetValue(SI, null)); + writer.WriteValue(property.GetValue(cpu.systemInfo, null)); } // "SmuAddresses:" @@ -754,14 +706,14 @@ public static void CalculatePstateDetails(uint eax, ref uint IddDiv, ref uint Id CpuFid = eax & 0xFF; } - private void buttonExport_Click(object sender, EventArgs e) + private void ButtonExport_Click(object sender, EventArgs e) { RunBackgroundTask(BackgroundWorkerTrySettings_DoWork, BackgroundWorkerReport_RunWorkerCompleted); } private bool nonNumberEntered; - private void pstateFidDid_KeyDown(object sender, KeyEventArgs e) + private void PstateFidDid_KeyDown(object sender, KeyEventArgs e) { nonNumberEntered = false; @@ -782,7 +734,7 @@ private void pstateFidDid_KeyDown(object sender, KeyEventArgs e) } } - private void pstateFidDid_KeyPress(object sender, KeyPressEventArgs e) + private void PstateFidDid_KeyPress(object sender, KeyPressEventArgs e) { if (nonNumberEntered) { @@ -790,14 +742,14 @@ private void pstateFidDid_KeyPress(object sender, KeyPressEventArgs e) } } - private void pstateFidDid_KeyUp(object sender, KeyEventArgs e) + private void PstateFidDid_KeyUp(object sender, KeyEventArgs e) { var fid = string.IsNullOrEmpty(pstateFid.Text) ? 0 : int.Parse(pstateFid.Text); var did = string.IsNullOrEmpty(pstateDid.Text) ? 1 : int.Parse(pstateDid.Text); pstateFrequency.Text = (fid * 25 / (did * 12.5)) * 100 + "MHz"; } - private void btnPstateRead_Click(object sender, EventArgs e) + private void BtnPstateRead_Click(object sender, EventArgs e) { uint eax = default, edx = default; var pstateId = pstateIdBox.SelectedIndex; @@ -826,7 +778,7 @@ private void btnPstateRead_Click(object sender, EventArgs e) btnPstateWrite.Enabled = true; } - private void btnPstateWrite_Click(object sender, EventArgs e) + private void BtnPstateWrite_Click(object sender, EventArgs e) { var confirmResult = MessageBox.Show( @"This will change the selected PState and your CPU frequency." + @@ -888,7 +840,7 @@ public bool ApplyTscWorkaround() if (cpu.Ols.Rdmsr(0xC0010015, ref eax, ref edx) != -1) { eax |= 0x200000; - return cpu.Ops.WriteMsr(0xC0010015, eax, edx); + return cpu.WriteMsr(0xC0010015, eax, edx); } SetStatusText($@"Error applying TSC fix!"); @@ -901,7 +853,7 @@ private bool WritePstateClick(int pstateId, uint eax, uint edx, int numanode = 0 if (!ApplyTscWorkaround()) return false; - if (!cpu.Ops.WriteMsr(Convert.ToUInt32(Convert.ToInt64(0xC0010064) + pstateId), eax, edx)) + if (!cpu.WriteMsr(Convert.ToUInt32(Convert.ToInt64(0xC0010064) + pstateId), eax, edx)) { SetStatusText($@"Error writing PState {pstateId}!"); return false; @@ -932,7 +884,7 @@ private void PciScan_DoWork(object sender, DoWorkEventArgs e) while (startReg <= endReg) { - var data = cpu.Ops.ReadDword(startReg); + var data = cpu.ReadDword(startReg); result += $"0x{startReg:X8}: 0x{data:X8}" + Environment.NewLine; startReg += 4; } @@ -987,7 +939,7 @@ private void ButtonApplyPROCHOT_Click(object sender, EventArgs e) DisableOCMode(); } EnableOCMode(checkBoxPROCHOT.Checked); - if (!checkBoxPROCHOT.Checked && cpu.Ops.IsProchotEnabled()) + if (!checkBoxPROCHOT.Checked && cpu.IsProchotEnabled()) { checkBoxPROCHOT.Checked = true; HandleError($@"Error, PROCHOT could not be disabled!"); @@ -1053,7 +1005,7 @@ private void ButtonMsrWrite_Click(object sender, EventArgs e) TryConvertToUint(textBoxMsrEax.Text, out uint eax); TryConvertToUint(textBoxMsrAddress.Text, out uint msr); - if (!cpu.Ops.WriteMsr(msr, eax, edx)) + if (!cpu.WriteMsr(msr, eax, edx)) { HandleError($@"Error writing MSR {textBoxMsrAddress.Text}!"); return; @@ -1132,7 +1084,10 @@ private void ButtonCPUIDScan_Click(object sender, EventArgs e) private void ButtonPMTable_Click(object sender, EventArgs e) { - new Thread(() => new PowerTableMonitor(cpu.Ops).ShowDialog()).Start(); + if (cpu.Status == Utils.LibStatus.OK) + new Thread(() => new PowerTableMonitor(cpu).ShowDialog()).Start(); + else + HandleError("IO driver is not responding or not loaded."); } private void ButtonSMUMonitor_Click(object sender, EventArgs e) @@ -1141,7 +1096,7 @@ private void ButtonSMUMonitor_Click(object sender, EventArgs e) TryConvertToUint(textBoxRSPAddress.Text, out uint addrRsp); TryConvertToUint(textBoxARGAddress.Text, out uint addrArg); - new Thread(() => new SMUMonitor(cpu.Ops, addrMsg, addrArg, addrRsp).ShowDialog()).Start(); + new Thread(() => new SMUMonitor(cpu, addrMsg, addrArg, addrRsp).ShowDialog()).Start(); } } } diff --git a/ZenStatesDebugTool.csproj b/ZenStatesDebugTool.csproj index 65a3be2..273ca44 100644 --- a/ZenStatesDebugTool.csproj +++ b/ZenStatesDebugTool.csproj @@ -59,6 +59,10 @@ + + False + Prebuilt\ZenStates-Core.dll + @@ -119,11 +123,6 @@ - - - {39C55831-97A2-498D-A9DD-27BF677E579A} - ZenStates.Core - - + \ No newline at end of file diff --git a/ZenStatesDebugTool.sln b/ZenStatesDebugTool.sln index 1bbc94f..b192106 100644 --- a/ZenStatesDebugTool.sln +++ b/ZenStatesDebugTool.sln @@ -4,11 +4,6 @@ Microsoft Visual Studio Solution File, Format Version 12.00 VisualStudioVersion = 16.0.29613.14 MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ZenStatesDebugTool", "ZenStatesDebugTool.csproj", "{056A457F-B9D4-4BB9-A9B3-033F2A1E265C}" - ProjectSection(ProjectDependencies) = postProject - {39C55831-97A2-498D-A9DD-27BF677E579A} = {39C55831-97A2-498D-A9DD-27BF677E579A} - EndProjectSection -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ZenStates.Core", "..\ZenStates.Core\ZenStates.Core.csproj", "{39C55831-97A2-498D-A9DD-27BF677E579A}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -20,10 +15,6 @@ Global {056A457F-B9D4-4BB9-A9B3-033F2A1E265C}.Debug|Any CPU.Build.0 = Debug|Any CPU {056A457F-B9D4-4BB9-A9B3-033F2A1E265C}.Release|Any CPU.ActiveCfg = Release|Any CPU {056A457F-B9D4-4BB9-A9B3-033F2A1E265C}.Release|Any CPU.Build.0 = Release|Any CPU - {39C55831-97A2-498D-A9DD-27BF677E579A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {39C55831-97A2-498D-A9DD-27BF677E579A}.Debug|Any CPU.Build.0 = Debug|Any CPU - {39C55831-97A2-498D-A9DD-27BF677E579A}.Release|Any CPU.ActiveCfg = Release|Any CPU - {39C55831-97A2-498D-A9DD-27BF677E579A}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE From 215149aab10a3381041d895c9497474bb731c39c Mon Sep 17 00:00:00 2001 From: Ivan Rusanov Date: Fri, 28 May 2021 21:44:22 +0300 Subject: [PATCH 4/7] Use test mailbox for scanner and commands in SMU tab --- Prebuilt/ZenStates-Core.dll | Bin 52224 -> 55808 bytes SettingsForm.Designer.cs | 81 +++++++++++++++------ SettingsForm.cs | 141 +++++++++++++++++++++--------------- Utils/CoreListItem.cs | 32 ++++---- Utils/FrequencyListItem.cs | 27 ++++--- Utils/MailboxListItem.cs | 33 +++++++++ Utils/SmuAddressSet.cs | 23 ++++++ ZenStatesDebugTool.csproj | 2 + 8 files changed, 224 insertions(+), 115 deletions(-) create mode 100644 Utils/MailboxListItem.cs create mode 100644 Utils/SmuAddressSet.cs diff --git a/Prebuilt/ZenStates-Core.dll b/Prebuilt/ZenStates-Core.dll index da8171170af10f31da4a0a6bc915165d1de013b0..e55bf0050e4f08f4f4b48914212d98f7714f3d49 100644 GIT binary patch literal 55808 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 H&H{e`6uvH1 literal 52224 zcmeFa3w&HvwLiYknVB<>q-jpl=G7!KX_GQd($F?7B$h|gBy9(hCM4;TVme8t&9q4- z%uGs4n3`e%ks=_V=;cxHg;#u|AfgmOL;)}I5Fda=3!)BBXx7;_$p=AU2Q_N zD-Ln!8?hgnr5zIs16j&4As&Q8Go-#>;vOJgA(G3yYSfzqRDb?!f*x}EbBLx($dvw1 z-z6jw{=W8t5S`2^;%@4Qseb`QWJ9(Lb`4W?C&B?CJQ;cq@cIl~myGO70_T1Q1Uhc3 ztTzz<1%%j97f-|ofQ-7KZPd_*SZ$Fe3|Cz|G8}^;)m5O*+y_6fOqgjBVvSuQ#Bb0p z`lGt3!X>tB7vd*}WG}PkpCg+b0eF$ro3+=ptves>WBt`tcI9E0|B2Wg$_LU<%2d&~GID0=u4I%5CV+Cw-}1PcVgn zrS#X5zRa#Cn1aue{)?n9x9bU}&|cC%LVCYlPcY>(^uHs0z^*5lLQ5$9-$;)x$!s6N z6r6zcZUy>E&mns4YQNMB>u z6HFBt`YT9ZYu6J@6&m`Fl76XOPcT(v=s!dHI=h}=s@TxqMf#KNdV(o9DYfqb(l4{? z38vtrq<@n1%k6rCDL5(Ve?|Hgc0IuqoRsu`Bz?VIPcQ{1CH>o^UuoA9Ou

KUal* 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 diff --git a/SettingsForm.Designer.cs b/SettingsForm.Designer.cs index 86d6792..6fc7aa9 100644 --- a/SettingsForm.Designer.cs +++ b/SettingsForm.Designer.cs @@ -44,6 +44,8 @@ private void InitializeComponent() this.textBoxCMD = new System.Windows.Forms.TextBox(); this.labelARGAddress = new System.Windows.Forms.Label(); this.textBoxARGAddress = new System.Windows.Forms.TextBox(); + this.label30 = new System.Windows.Forms.Label(); + this.comboBoxMailboxSelect = new System.Windows.Forms.ComboBox(); this.statusStrip1 = new System.Windows.Forms.StatusStrip(); this.labelStatus = new System.Windows.Forms.ToolStripStatusLabel(); this.tableLayoutPanel2 = new System.Windows.Forms.TableLayoutPanel(); @@ -178,33 +180,36 @@ private void InitializeComponent() this.tableLayoutPanel1.ColumnCount = 2; this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 100F)); this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 100F)); - this.tableLayoutPanel1.Controls.Add(this.labelCMDAddress, 0, 0); - this.tableLayoutPanel1.Controls.Add(this.labelRSP, 0, 1); - this.tableLayoutPanel1.Controls.Add(this.textBoxCMDAddress, 1, 0); - this.tableLayoutPanel1.Controls.Add(this.textBoxRSPAddress, 1, 1); - this.tableLayoutPanel1.Controls.Add(this.labelARG0, 0, 4); - this.tableLayoutPanel1.Controls.Add(this.textBoxARG0, 1, 4); - this.tableLayoutPanel1.Controls.Add(this.labelCMD, 0, 3); - this.tableLayoutPanel1.Controls.Add(this.textBoxCMD, 1, 3); - this.tableLayoutPanel1.Controls.Add(this.labelARGAddress, 0, 2); - this.tableLayoutPanel1.Controls.Add(this.textBoxARGAddress, 1, 2); + this.tableLayoutPanel1.Controls.Add(this.labelCMDAddress, 0, 1); + this.tableLayoutPanel1.Controls.Add(this.labelRSP, 0, 2); + this.tableLayoutPanel1.Controls.Add(this.textBoxCMDAddress, 1, 1); + this.tableLayoutPanel1.Controls.Add(this.textBoxRSPAddress, 1, 2); + this.tableLayoutPanel1.Controls.Add(this.labelARG0, 0, 5); + this.tableLayoutPanel1.Controls.Add(this.textBoxARG0, 1, 5); + this.tableLayoutPanel1.Controls.Add(this.labelCMD, 0, 4); + this.tableLayoutPanel1.Controls.Add(this.textBoxCMD, 1, 4); + this.tableLayoutPanel1.Controls.Add(this.labelARGAddress, 0, 3); + this.tableLayoutPanel1.Controls.Add(this.textBoxARGAddress, 1, 3); + this.tableLayoutPanel1.Controls.Add(this.label30, 0, 0); + this.tableLayoutPanel1.Controls.Add(this.comboBoxMailboxSelect, 1, 0); this.tableLayoutPanel1.Location = new System.Drawing.Point(3, 3); this.tableLayoutPanel1.Name = "tableLayoutPanel1"; this.tableLayoutPanel1.Padding = new System.Windows.Forms.Padding(0, 5, 0, 5); - this.tableLayoutPanel1.RowCount = 5; + this.tableLayoutPanel1.RowCount = 6; this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle()); this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle()); this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle()); this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle()); this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle()); - this.tableLayoutPanel1.Size = new System.Drawing.Size(200, 150); + this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle()); + this.tableLayoutPanel1.Size = new System.Drawing.Size(200, 179); this.tableLayoutPanel1.TabIndex = 0; // // labelCMDAddress // this.labelCMDAddress.AutoSize = true; this.labelCMDAddress.Dock = System.Windows.Forms.DockStyle.Fill; - this.labelCMDAddress.Location = new System.Drawing.Point(3, 5); + this.labelCMDAddress.Location = new System.Drawing.Point(3, 34); this.labelCMDAddress.MinimumSize = new System.Drawing.Size(77, 27); this.labelCMDAddress.Name = "labelCMDAddress"; this.labelCMDAddress.Padding = new System.Windows.Forms.Padding(0, 5, 5, 5); @@ -217,7 +222,7 @@ private void InitializeComponent() // this.labelRSP.AutoSize = true; this.labelRSP.Dock = System.Windows.Forms.DockStyle.Fill; - this.labelRSP.Location = new System.Drawing.Point(3, 33); + this.labelRSP.Location = new System.Drawing.Point(3, 62); this.labelRSP.MinimumSize = new System.Drawing.Size(77, 27); this.labelRSP.Name = "labelRSP"; this.labelRSP.Padding = new System.Windows.Forms.Padding(0, 5, 5, 5); @@ -231,7 +236,7 @@ private void InitializeComponent() this.textBoxCMDAddress.Dock = System.Windows.Forms.DockStyle.Fill; this.textBoxCMDAddress.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); this.textBoxCMDAddress.HideSelection = false; - this.textBoxCMDAddress.Location = new System.Drawing.Point(104, 9); + this.textBoxCMDAddress.Location = new System.Drawing.Point(104, 38); this.textBoxCMDAddress.Margin = new System.Windows.Forms.Padding(4); this.textBoxCMDAddress.Name = "textBoxCMDAddress"; this.textBoxCMDAddress.Size = new System.Drawing.Size(92, 20); @@ -242,7 +247,7 @@ private void InitializeComponent() this.textBoxRSPAddress.Dock = System.Windows.Forms.DockStyle.Fill; this.textBoxRSPAddress.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); this.textBoxRSPAddress.HideSelection = false; - this.textBoxRSPAddress.Location = new System.Drawing.Point(104, 37); + this.textBoxRSPAddress.Location = new System.Drawing.Point(104, 66); this.textBoxRSPAddress.Margin = new System.Windows.Forms.Padding(4); this.textBoxRSPAddress.Name = "textBoxRSPAddress"; this.textBoxRSPAddress.Size = new System.Drawing.Size(92, 20); @@ -252,7 +257,7 @@ private void InitializeComponent() // this.labelARG0.AutoSize = true; this.labelARG0.Dock = System.Windows.Forms.DockStyle.Fill; - this.labelARG0.Location = new System.Drawing.Point(3, 117); + this.labelARG0.Location = new System.Drawing.Point(3, 146); this.labelARG0.MinimumSize = new System.Drawing.Size(77, 27); this.labelARG0.Name = "labelARG0"; this.labelARG0.Padding = new System.Windows.Forms.Padding(0, 5, 5, 5); @@ -266,7 +271,7 @@ private void InitializeComponent() this.textBoxARG0.Dock = System.Windows.Forms.DockStyle.Fill; this.textBoxARG0.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); this.textBoxARG0.HideSelection = false; - this.textBoxARG0.Location = new System.Drawing.Point(104, 121); + this.textBoxARG0.Location = new System.Drawing.Point(104, 150); this.textBoxARG0.Margin = new System.Windows.Forms.Padding(4); this.textBoxARG0.Name = "textBoxARG0"; this.textBoxARG0.Size = new System.Drawing.Size(92, 20); @@ -276,7 +281,7 @@ private void InitializeComponent() // this.labelCMD.AutoSize = true; this.labelCMD.Dock = System.Windows.Forms.DockStyle.Fill; - this.labelCMD.Location = new System.Drawing.Point(3, 89); + this.labelCMD.Location = new System.Drawing.Point(3, 118); this.labelCMD.MinimumSize = new System.Drawing.Size(77, 27); this.labelCMD.Name = "labelCMD"; this.labelCMD.Padding = new System.Windows.Forms.Padding(0, 5, 5, 5); @@ -290,7 +295,7 @@ private void InitializeComponent() this.textBoxCMD.Dock = System.Windows.Forms.DockStyle.Fill; this.textBoxCMD.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); this.textBoxCMD.HideSelection = false; - this.textBoxCMD.Location = new System.Drawing.Point(104, 93); + this.textBoxCMD.Location = new System.Drawing.Point(104, 122); this.textBoxCMD.Margin = new System.Windows.Forms.Padding(4); this.textBoxCMD.Name = "textBoxCMD"; this.textBoxCMD.Size = new System.Drawing.Size(92, 20); @@ -300,7 +305,7 @@ private void InitializeComponent() // this.labelARGAddress.AutoSize = true; this.labelARGAddress.Dock = System.Windows.Forms.DockStyle.Fill; - this.labelARGAddress.Location = new System.Drawing.Point(3, 61); + this.labelARGAddress.Location = new System.Drawing.Point(3, 90); this.labelARGAddress.MinimumSize = new System.Drawing.Size(77, 27); this.labelARGAddress.Name = "labelARGAddress"; this.labelARGAddress.Padding = new System.Windows.Forms.Padding(0, 5, 5, 5); @@ -313,12 +318,38 @@ private void InitializeComponent() // this.textBoxARGAddress.Dock = System.Windows.Forms.DockStyle.Fill; this.textBoxARGAddress.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); - this.textBoxARGAddress.Location = new System.Drawing.Point(104, 65); + this.textBoxARGAddress.Location = new System.Drawing.Point(104, 94); this.textBoxARGAddress.Margin = new System.Windows.Forms.Padding(4); this.textBoxARGAddress.Name = "textBoxARGAddress"; this.textBoxARGAddress.Size = new System.Drawing.Size(92, 20); this.textBoxARGAddress.TabIndex = 11; // + // label30 + // + this.label30.AutoSize = true; + this.label30.Dock = System.Windows.Forms.DockStyle.Fill; + this.label30.Location = new System.Drawing.Point(3, 5); + this.label30.Name = "label30"; + this.label30.Size = new System.Drawing.Size(94, 29); + this.label30.TabIndex = 12; + this.label30.Text = "Mailbox"; + this.label30.TextAlign = System.Drawing.ContentAlignment.MiddleLeft; + // + // comboBoxMailboxSelect + // + this.comboBoxMailboxSelect.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; + this.comboBoxMailboxSelect.FormattingEnabled = true; + this.comboBoxMailboxSelect.Items.AddRange(new object[] { + "RSMU", + "MP1", + "HSMP"}); + this.comboBoxMailboxSelect.Location = new System.Drawing.Point(104, 9); + this.comboBoxMailboxSelect.Margin = new System.Windows.Forms.Padding(4); + this.comboBoxMailboxSelect.Name = "comboBoxMailboxSelect"; + this.comboBoxMailboxSelect.Size = new System.Drawing.Size(92, 21); + this.comboBoxMailboxSelect.TabIndex = 13; + this.comboBoxMailboxSelect.SelectedIndexChanged += new System.EventHandler(this.ComboBoxMailboxSelect_SelectedIndexChanged); + // // statusStrip1 // this.statusStrip1.ImageScalingSize = new System.Drawing.Size(20, 20); @@ -593,7 +624,7 @@ private void InitializeComponent() this.tableLayoutPanel7.ColumnCount = 1; this.tableLayoutPanel7.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle()); this.tableLayoutPanel7.Dock = System.Windows.Forms.DockStyle.Top; - this.tableLayoutPanel7.Location = new System.Drawing.Point(0, 161); + this.tableLayoutPanel7.Location = new System.Drawing.Point(0, 185); this.tableLayoutPanel7.Name = "tableLayoutPanel7"; this.tableLayoutPanel7.RowCount = 1; this.tableLayoutPanel7.RowStyles.Add(new System.Windows.Forms.RowStyle()); @@ -614,7 +645,7 @@ private void InitializeComponent() this.tableLayoutPanel6.Name = "tableLayoutPanel6"; this.tableLayoutPanel6.RowCount = 1; this.tableLayoutPanel6.RowStyles.Add(new System.Windows.Forms.RowStyle()); - this.tableLayoutPanel6.Size = new System.Drawing.Size(338, 161); + this.tableLayoutPanel6.Size = new System.Drawing.Size(338, 185); this.tableLayoutPanel6.TabIndex = 3; // // tabPagePci @@ -1859,6 +1890,8 @@ private void InitializeComponent() private Label configInfoLabel; private Button buttonPMTable; private Button buttonSmuLog; + private Label label30; + private ComboBox comboBoxMailboxSelect; } } diff --git a/SettingsForm.cs b/SettingsForm.cs index 82dc02b..1c89b2e 100644 --- a/SettingsForm.cs +++ b/SettingsForm.cs @@ -18,35 +18,11 @@ public partial class SettingsForm : Form { //private static readonly int Threads = Convert.ToInt32(Environment.GetEnvironmentVariable("NUMBER_OF_PROCESSORS")); private BackgroundWorker backgroundWorker1; - private NUMAUtil _numaUtil; - private Cpu cpu = new Cpu(); + private readonly NUMAUtil _numaUtil; + private readonly Cpu cpu = new Cpu(); List matches; - private int _coreCount; - - private uint SMU_ADDR_MSG; - private uint SMU_ADDR_RSP; - private uint SMU_ADDR_ARG; - - private class SmuAddressSet - { - public uint MsgAddress; - public uint RspAddress; - public uint ArgAddress; - - public SmuAddressSet() - { - MsgAddress = 0; - RspAddress = 0; - ArgAddress = 0; - } - - public SmuAddressSet(uint msgAddress, uint rspAddress, uint argAddress) - { - MsgAddress = msgAddress; - RspAddress = rspAddress; - ArgAddress = argAddress; - } - } + private readonly int _coreCount; + private readonly Mailbox testMailbox = new Mailbox(); public SettingsForm() { @@ -77,15 +53,27 @@ private static void ExitApplication() Environment.Exit(1); } - private void ResetSmuAddresses() + private void InitTestMailbox(uint msgAddr, uint rspAddr, uint argAddr) { - cpu.smu.Rsmu.SMU_ADDR_MSG = SMU_ADDR_MSG; - cpu.smu.Rsmu.SMU_ADDR_RSP = SMU_ADDR_RSP; - cpu.smu.Rsmu.SMU_ADDR_ARG = SMU_ADDR_ARG; + testMailbox.SMU_ADDR_MSG = msgAddr; + testMailbox.SMU_ADDR_RSP = rspAddr; + testMailbox.SMU_ADDR_ARG = argAddr; + ResetSmuAddresses(); + } + + private void InitTestMailbox(Mailbox mailbox) + { + testMailbox.SMU_ADDR_MSG = mailbox.SMU_ADDR_MSG; + testMailbox.SMU_ADDR_RSP = mailbox.SMU_ADDR_RSP; + testMailbox.SMU_ADDR_ARG = mailbox.SMU_ADDR_ARG; + ResetSmuAddresses(); + } - textBoxCMDAddress.Text = $"0x{Convert.ToString(SMU_ADDR_MSG, 16).ToUpper()}"; - textBoxRSPAddress.Text = $"0x{Convert.ToString(SMU_ADDR_RSP, 16).ToUpper()}"; - textBoxARGAddress.Text = $"0x{Convert.ToString(SMU_ADDR_ARG, 16).ToUpper()}"; + private void ResetSmuAddresses() + { + textBoxCMDAddress.Text = $"0x{Convert.ToString(testMailbox.SMU_ADDR_MSG, 16).ToUpper()}"; + textBoxRSPAddress.Text = $"0x{Convert.ToString(testMailbox.SMU_ADDR_RSP, 16).ToUpper()}"; + textBoxARGAddress.Text = $"0x{Convert.ToString(testMailbox.SMU_ADDR_ARG, 16).ToUpper()}"; textBoxCMD.Text = "0x1"; textBoxARG0.Text = "0x0"; @@ -115,12 +103,7 @@ private void InitForm() MessageBoxButtons.OK, MessageBoxIcon.Error); } - // Cache default addresses - SMU_ADDR_MSG = cpu.smu.Rsmu.SMU_ADDR_MSG; - SMU_ADDR_RSP = cpu.smu.Rsmu.SMU_ADDR_RSP; - SMU_ADDR_ARG = cpu.smu.Rsmu.SMU_ADDR_ARG; - - ResetSmuAddresses(); + InitTestMailbox(cpu.smu.Rsmu); DisplaySystemInfo(); pstateIdBox.SelectedIndex = 0; @@ -135,6 +118,7 @@ private void InitForm() PopulateFrequencyList(comboBoxACF.Items); PopulateFrequencyList(comboBoxSCF.Items); PopulateCCDList(comboBoxCore.Items); + PopulateMailboxesList(comboBoxMailboxSelect.Items); comboBoxCore.SelectedIndex = 0; @@ -147,6 +131,8 @@ private void InitForm() //checkBoxPROCHOT.Enabled = prochotEnabled; //buttonApplyPROCHOT.Enabled = prochotEnabled; + comboBoxMailboxSelect.SelectedIndex = 0; + ToolTip toolTip = new ToolTip(); toolTip.SetToolTip(checkBoxPROCHOT, "Disables temperature throttling. Can be useful on extreme cooling."); @@ -177,6 +163,19 @@ private void PopulateCCDList(ComboBox.ObjectCollection l) l.Add((object)new CoreListItem(core / 8, core / 4, core)); } + private void PopulateMailboxesList(ComboBox.ObjectCollection l) + { + l.Clear(); + l.Add(new MailboxListItem("RSMU", cpu.smu.Rsmu)); + l.Add(new MailboxListItem("MP1", cpu.smu.Mp1smu)); + l.Add(new MailboxListItem("HSMP", cpu.smu.Hsmp)); + } + + private void AddMailboxToList(string label, SmuAddressSet addressSet) + { + comboBoxMailboxSelect.Items.Add(new MailboxListItem(label, addressSet)); + } + private void ApplyFrequencyAllCoreSetting(int frequency) { if (cpu.SendSmuCommand(cpu.smu.Rsmu, cpu.smu.Rsmu.SMU_MSG_SetOverclockFrequencyAllCores, Convert.ToUInt32(frequency))) @@ -227,6 +226,7 @@ private void SetButtonsState(bool enabled = true) buttonMsrScan.Enabled = enabled; buttonMsrWrite.Enabled = enabled; buttonPMTable.Enabled = enabled; + buttonSmuLog.Enabled = enabled; textBoxCMDAddress.Enabled = enabled; textBoxRSPAddress.Enabled = enabled; @@ -242,6 +242,7 @@ private void SetButtonsState(bool enabled = true) textBoxMsrEax.Enabled = enabled; textBoxMsrStart.Enabled = enabled; textBoxMsrEnd.Enabled = enabled; + comboBoxMailboxSelect.Enabled = enabled; // textBoxResult.Enabled = enabled; } @@ -331,9 +332,9 @@ private void ApplySettings() TryConvertToUint(textBoxARGAddress.Text, out uint addrArg); TryConvertToUint(textBoxCMD.Text, out uint command); - cpu.smu.Rsmu.SMU_ADDR_MSG = addrMsg; - cpu.smu.Rsmu.SMU_ADDR_RSP = addrRsp; - cpu.smu.Rsmu.SMU_ADDR_ARG = addrArg; + testMailbox.SMU_ADDR_MSG = addrMsg; + testMailbox.SMU_ADDR_RSP = addrRsp; + testMailbox.SMU_ADDR_ARG = addrArg; for (var i = 0; i < userArgs.Length; i++) { @@ -345,12 +346,12 @@ private void ApplySettings() } - Console.WriteLine("MSG Address: 0x" + Convert.ToString(cpu.smu.Rsmu.SMU_ADDR_MSG, 16).ToUpper()); - Console.WriteLine("RSP Address: 0x" + Convert.ToString(cpu.smu.Rsmu.SMU_ADDR_RSP, 16).ToUpper()); - Console.WriteLine("ARG0 Address: 0x" + Convert.ToString(cpu.smu.Rsmu.SMU_ADDR_ARG, 16).ToUpper()); + Console.WriteLine("MSG Address: 0x" + Convert.ToString(testMailbox.SMU_ADDR_MSG, 16).ToUpper()); + Console.WriteLine("RSP Address: 0x" + Convert.ToString(testMailbox.SMU_ADDR_RSP, 16).ToUpper()); + Console.WriteLine("ARG0 Address: 0x" + Convert.ToString(testMailbox.SMU_ADDR_ARG, 16).ToUpper()); Console.WriteLine("ARG0 : 0x" + Convert.ToString(args[0], 16).ToUpper()); - SMU.Status status = cpu.SendSmuCommand(cpu.smu.Rsmu, command, ref args); + SMU.Status status = cpu.SendSmuCommand(testMailbox, command, ref args); if (status == SMU.Status.OK) { @@ -365,7 +366,11 @@ private void ApplySettings() } } - private void ButtonDefaults_Click(object sender, EventArgs e) => ResetSmuAddresses(); + private void ButtonDefaults_Click(object sender, EventArgs e) + { + InitTestMailbox(cpu.smu.Rsmu); + comboBoxMailboxSelect.SelectedIndex = 0; + } private void ButtonApply_Click(object sender, EventArgs e) { @@ -457,11 +462,11 @@ private SMU.Status TrySettings(uint msgAddr, uint rspAddr, uint argAddress, uint uint[] args = new uint[6]; args[0] = value; - cpu.smu.Rsmu.SMU_ADDR_MSG = msgAddr; - cpu.smu.Rsmu.SMU_ADDR_RSP = rspAddr; - cpu.smu.Rsmu.SMU_ADDR_ARG = argAddress; + testMailbox.SMU_ADDR_MSG = msgAddr; + testMailbox.SMU_ADDR_RSP = rspAddr; + testMailbox.SMU_ADDR_ARG = argAddress; - return cpu.SendSmuCommand(cpu.smu.Rsmu, cmd, ref args); + return cpu.SendSmuCommand(testMailbox, cmd, ref args); } private void ScanSmuRange(uint start, uint end, int step, byte offset) @@ -476,10 +481,10 @@ private void ScanSmuRange(uint start, uint end, int step, byte offset) if (cpu.ReadDword(start) != 0xFFFFFFFF) { // Check if CMD-RSP pair returns correct status, while using a placeholder ARG address - if (TrySettings(start, smuRspAddress, smuArgAddress, cpu.smu.Rsmu.SMU_MSG_TestMessage, 0x0) == SMU.Status.OK) + if (TrySettings(start, smuRspAddress, smuArgAddress, testMailbox.SMU_MSG_TestMessage, 0x0) == SMU.Status.OK) { // Send smu version command, so the corresponding ARG0 address changes its value - TrySettings(start, smuRspAddress, smuArgAddress, cpu.smu.Rsmu.SMU_MSG_GetSmuVersion, 0x0); + TrySettings(start, smuRspAddress, smuArgAddress, testMailbox.SMU_MSG_GetSmuVersion, 0x0); bool match = false; smuArgAddress = smuRspAddress + 4; @@ -494,7 +499,7 @@ private void ScanSmuRange(uint start, uint end, int step, byte offset) { // Send test message with an argument, using the potential ARG0 address var argValue = (uint)matches.Count * 2 + 99; - TrySettings(start, smuRspAddress, smuArgAddress, cpu.smu.Rsmu.SMU_MSG_TestMessage, argValue); + TrySettings(start, smuRspAddress, smuArgAddress, testMailbox.SMU_MSG_TestMessage, argValue); currentRegValue = cpu.ReadDword(smuArgAddress); Console.WriteLine($"REG: 0x{smuArgAddress:X8} Value: 0x{currentRegValue:X8}"); @@ -553,8 +558,6 @@ private void RunBackgroundTask(DoWorkEventHandler task, RunWorkerCompletedEventH private void BackgroundWorkerTrySettings_DoWork(object sender, DoWorkEventArgs e) { - ResetSmuAddresses(); - try { Invoke(new MethodInvoker(delegate @@ -691,7 +694,7 @@ private void BackgroundWorkerReport_RunWorkerCompleted(object sender, RunWorkerC sw.WriteLine(GenerateReportJson()); } - ResetSmuAddresses(); + //ResetSmuAddresses(); SetButtonsState(); SetStatusText("Report Complete."); MessageBox.Show($"Report saved as {fileName}"); @@ -909,8 +912,20 @@ private void Scan_WorkerCompleted(object sender, RunWorkerCompletedEventArgs e) private void SmuScan_WorkerCompleted(object sender, RunWorkerCompletedEventArgs e) { + int index = comboBoxMailboxSelect.SelectedIndex; + PopulateMailboxesList(comboBoxMailboxSelect.Items); + + for (var i = 0; i < matches.Count; i++) + { + AddMailboxToList($"Mailbox {i + 1}", matches[i]); + } + + if (index > comboBoxMailboxSelect.Items.Count) + index = 0; + + comboBoxMailboxSelect.SelectedIndex = index; SetButtonsState(); - ResetSmuAddresses(); + //ResetSmuAddresses(); SetStatusText("Scan Complete."); } @@ -1098,5 +1113,11 @@ private void ButtonSMUMonitor_Click(object sender, EventArgs e) new Thread(() => new SMUMonitor(cpu, addrMsg, addrArg, addrRsp).ShowDialog()).Start(); } + + private void ComboBoxMailboxSelect_SelectedIndexChanged(object sender, EventArgs e) + { + MailboxListItem item = comboBoxMailboxSelect.SelectedItem as MailboxListItem; + InitTestMailbox(item.msgAddr, item.rspAddr, item.argAddr); + } } } diff --git a/Utils/CoreListItem.cs b/Utils/CoreListItem.cs index 8090da7..a07a553 100644 --- a/Utils/CoreListItem.cs +++ b/Utils/CoreListItem.cs @@ -1,23 +1,21 @@ namespace ZenStatesDebugTool { - public class CoreListItem - { - public int CCD { get; } - - public int CCX { get; } - - public int CORE { get; } - - public CoreListItem(int ccd, int ccx, int core) + public class CoreListItem { - this.CCD = ccd; - this.CCX = ccx; - this.CORE = core; - } + public int CCD { get; } + public int CCX { get; } + public int CORE { get; } - public override string ToString() - { - return string.Format("Core {0}", (object) (this.CORE)); + public CoreListItem(int ccd, int ccx, int core) + { + this.CCD = ccd; + this.CCX = ccx; + this.CORE = core; + } + + public override string ToString() + { + return string.Format("Core {0}", (object)(this.CORE)); + } } - } } \ No newline at end of file diff --git a/Utils/FrequencyListItem.cs b/Utils/FrequencyListItem.cs index b1ac0a8..23de3dd 100644 --- a/Utils/FrequencyListItem.cs +++ b/Utils/FrequencyListItem.cs @@ -1,20 +1,19 @@ namespace ZenStatesDebugTool { - public class FrequencyListItem - { - public double multi { get; } - - public string display { get; } - - public FrequencyListItem(double multi, string display) + public class FrequencyListItem { - this.multi = multi; - this.display = display; - } + public double multi { get; } + public string display { get; } - public override string ToString() - { - return this.display; + public FrequencyListItem(double multi, string display) + { + this.multi = multi; + this.display = display; + } + + public override string ToString() + { + return this.display; + } } - } } \ No newline at end of file diff --git a/Utils/MailboxListItem.cs b/Utils/MailboxListItem.cs new file mode 100644 index 0000000..550b565 --- /dev/null +++ b/Utils/MailboxListItem.cs @@ -0,0 +1,33 @@ +using ZenStates.Core; + +namespace ZenStatesDebugTool +{ + public class MailboxListItem + { + public uint msgAddr { get; } + public uint rspAddr { get; } + public uint argAddr { get; } + public string label { get; } + + public MailboxListItem(string label, SmuAddressSet addressSet) + { + this.label = label; + msgAddr = addressSet.MsgAddress; + rspAddr = addressSet.RspAddress; + argAddr = addressSet.ArgAddress; + } + + public MailboxListItem(string label, Mailbox mailbox) + { + this.label = label; + msgAddr = mailbox.SMU_ADDR_MSG; + rspAddr = mailbox.SMU_ADDR_RSP; + argAddr = mailbox.SMU_ADDR_ARG; + } + + public override string ToString() + { + return this.label; + } + } +} \ No newline at end of file diff --git a/Utils/SmuAddressSet.cs b/Utils/SmuAddressSet.cs new file mode 100644 index 0000000..43a2433 --- /dev/null +++ b/Utils/SmuAddressSet.cs @@ -0,0 +1,23 @@ +namespace ZenStatesDebugTool +{ + public class SmuAddressSet + { + public uint MsgAddress; + public uint RspAddress; + public uint ArgAddress; + + public SmuAddressSet() + { + MsgAddress = 0; + RspAddress = 0; + ArgAddress = 0; + } + + public SmuAddressSet(uint msgAddress, uint rspAddress, uint argAddress) + { + MsgAddress = msgAddress; + RspAddress = rspAddress; + ArgAddress = argAddress; + } + } +} diff --git a/ZenStatesDebugTool.csproj b/ZenStatesDebugTool.csproj index 273ca44..4cd74ee 100644 --- a/ZenStatesDebugTool.csproj +++ b/ZenStatesDebugTool.csproj @@ -77,6 +77,7 @@ PowerTableMonitor.cs + Form @@ -84,6 +85,7 @@ ResultForm.cs + From 3d0cd4bcf8a4bcd967332a222a6b588bba2454ad Mon Sep 17 00:00:00 2001 From: Ivan Rusanov Date: Thu, 24 Jun 2021 00:55:24 +0300 Subject: [PATCH 5/7] WIP --- Prebuilt/ZenStates-Core.dll | Bin 55808 -> 60928 bytes SettingsForm.Designer.cs | 40 ++++++---- SettingsForm.cs | 145 +++++++++++++++++++++++++++++++----- 3 files changed, 153 insertions(+), 32 deletions(-) diff --git a/Prebuilt/ZenStates-Core.dll b/Prebuilt/ZenStates-Core.dll index e55bf0050e4f08f4f4b48914212d98f7714f3d49..cb5d8eb794d2137f9e711843eb688c75e1c75122 100644 GIT binary patch literal 60928 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%0D)4Ph%5}Cp^jGmGy+`uSDrm%xigN)@?M(4>C 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

noy(dk0Ark;OHZsBMS6DprHq#8w_XV%cOlwmgYr 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 literal 55808 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 H&H{e`6uvH1 diff --git a/SettingsForm.Designer.cs b/SettingsForm.Designer.cs index 6fc7aa9..2644757 100644 --- a/SettingsForm.Designer.cs +++ b/SettingsForm.Designer.cs @@ -41,11 +41,11 @@ private void InitializeComponent() this.labelARG0 = new System.Windows.Forms.Label(); this.textBoxARG0 = new System.Windows.Forms.TextBox(); this.labelCMD = new System.Windows.Forms.Label(); - this.textBoxCMD = new System.Windows.Forms.TextBox(); this.labelARGAddress = new System.Windows.Forms.Label(); this.textBoxARGAddress = new System.Windows.Forms.TextBox(); this.label30 = new System.Windows.Forms.Label(); this.comboBoxMailboxSelect = new System.Windows.Forms.ComboBox(); + this.textBoxCMD = new System.Windows.Forms.NumericUpDown(); this.statusStrip1 = new System.Windows.Forms.StatusStrip(); this.labelStatus = new System.Windows.Forms.ToolStripStatusLabel(); this.tableLayoutPanel2 = new System.Windows.Forms.TableLayoutPanel(); @@ -150,6 +150,7 @@ private void InitializeComponent() this.splitContainer1 = new System.Windows.Forms.SplitContainer(); this.tableLayoutPanel11 = new System.Windows.Forms.TableLayoutPanel(); this.tableLayoutPanel1.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.textBoxCMD)).BeginInit(); this.statusStrip1.SuspendLayout(); this.tableLayoutPanel2.SuspendLayout(); this.tabControl1.SuspendLayout(); @@ -187,11 +188,11 @@ private void InitializeComponent() this.tableLayoutPanel1.Controls.Add(this.labelARG0, 0, 5); this.tableLayoutPanel1.Controls.Add(this.textBoxARG0, 1, 5); this.tableLayoutPanel1.Controls.Add(this.labelCMD, 0, 4); - this.tableLayoutPanel1.Controls.Add(this.textBoxCMD, 1, 4); this.tableLayoutPanel1.Controls.Add(this.labelARGAddress, 0, 3); this.tableLayoutPanel1.Controls.Add(this.textBoxARGAddress, 1, 3); this.tableLayoutPanel1.Controls.Add(this.label30, 0, 0); this.tableLayoutPanel1.Controls.Add(this.comboBoxMailboxSelect, 1, 0); + this.tableLayoutPanel1.Controls.Add(this.textBoxCMD, 1, 4); this.tableLayoutPanel1.Location = new System.Drawing.Point(3, 3); this.tableLayoutPanel1.Name = "tableLayoutPanel1"; this.tableLayoutPanel1.Padding = new System.Windows.Forms.Padding(0, 5, 0, 5); @@ -276,6 +277,7 @@ private void InitializeComponent() this.textBoxARG0.Name = "textBoxARG0"; this.textBoxARG0.Size = new System.Drawing.Size(92, 20); this.textBoxARG0.TabIndex = 6; + this.textBoxARG0.Text = "0"; // // labelCMD // @@ -290,17 +292,6 @@ private void InitializeComponent() this.labelCMD.Text = "Command ID"; this.labelCMD.TextAlign = System.Drawing.ContentAlignment.MiddleLeft; // - // textBoxCMD - // - this.textBoxCMD.Dock = System.Windows.Forms.DockStyle.Fill; - this.textBoxCMD.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); - this.textBoxCMD.HideSelection = false; - this.textBoxCMD.Location = new System.Drawing.Point(104, 122); - this.textBoxCMD.Margin = new System.Windows.Forms.Padding(4); - this.textBoxCMD.Name = "textBoxCMD"; - this.textBoxCMD.Size = new System.Drawing.Size(92, 20); - this.textBoxCMD.TabIndex = 9; - // // labelARGAddress // this.labelARGAddress.AutoSize = true; @@ -350,6 +341,26 @@ private void InitializeComponent() this.comboBoxMailboxSelect.TabIndex = 13; this.comboBoxMailboxSelect.SelectedIndexChanged += new System.EventHandler(this.ComboBoxMailboxSelect_SelectedIndexChanged); // + // textBoxCMD + // + this.textBoxCMD.Dock = System.Windows.Forms.DockStyle.Fill; + this.textBoxCMD.Hexadecimal = true; + this.textBoxCMD.Location = new System.Drawing.Point(104, 122); + this.textBoxCMD.Margin = new System.Windows.Forms.Padding(4); + this.textBoxCMD.Maximum = new decimal(new int[] { + 255, + 0, + 0, + 0}); + this.textBoxCMD.Name = "textBoxCMD"; + this.textBoxCMD.Size = new System.Drawing.Size(92, 20); + this.textBoxCMD.TabIndex = 14; + this.textBoxCMD.Value = new decimal(new int[] { + 1, + 0, + 0, + 0}); + // // statusStrip1 // this.statusStrip1.ImageScalingSize = new System.Drawing.Size(20, 20); @@ -1731,6 +1742,7 @@ private void InitializeComponent() this.Text = "SMU Debug Tool"; this.tableLayoutPanel1.ResumeLayout(false); this.tableLayoutPanel1.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.textBoxCMD)).EndInit(); this.statusStrip1.ResumeLayout(false); this.statusStrip1.PerformLayout(); this.tableLayoutPanel2.ResumeLayout(false); @@ -1787,7 +1799,6 @@ private void InitializeComponent() private System.Windows.Forms.Label labelARG0; private System.Windows.Forms.TextBox textBoxARG0; private System.Windows.Forms.Label labelCMD; - private System.Windows.Forms.TextBox textBoxCMD; private System.Windows.Forms.Label labelARGAddress; private System.Windows.Forms.TextBox textBoxARGAddress; private System.Windows.Forms.Button buttonApply; @@ -1892,6 +1903,7 @@ private void InitializeComponent() private Button buttonSmuLog; private Label label30; private ComboBox comboBoxMailboxSelect; + private NumericUpDown textBoxCMD; } } diff --git a/SettingsForm.cs b/SettingsForm.cs index 1c89b2e..e716d13 100644 --- a/SettingsForm.cs +++ b/SettingsForm.cs @@ -5,7 +5,6 @@ using System.ComponentModel; using System.IO; using System.Linq; -using System.Management; using System.Reflection; using System.Threading; using System.Windows.Forms; @@ -19,25 +18,22 @@ public partial class SettingsForm : Form //private static readonly int Threads = Convert.ToInt32(Environment.GetEnvironmentVariable("NUMBER_OF_PROCESSORS")); private BackgroundWorker backgroundWorker1; private readonly NUMAUtil _numaUtil; - private readonly Cpu cpu = new Cpu(); + private readonly Cpu cpu; List matches; - private readonly int _coreCount; private readonly Mailbox testMailbox = new Mailbox(); public SettingsForm() { InitializeComponent(); - _numaUtil = new NUMAUtil(); textBoxResult.Text = $@"Detected NUMA nodes. ({_numaUtil.HighestNumaNode + 1})" + textBoxResult.Text; - _coreCount = new ManagementObjectSearcher("Select * from Win32_Processor").Get().Cast().Sum(item => int.Parse(item["NumberOfCores"].ToString())); - try { + cpu = new Cpu(); InitForm(); } - catch (ApplicationException ex) + catch (Exception ex) { MessageBox.Show(ex.Message, Resources.Error); Dispose(); @@ -74,9 +70,6 @@ private void ResetSmuAddresses() textBoxCMDAddress.Text = $"0x{Convert.ToString(testMailbox.SMU_ADDR_MSG, 16).ToUpper()}"; textBoxRSPAddress.Text = $"0x{Convert.ToString(testMailbox.SMU_ADDR_RSP, 16).ToUpper()}"; textBoxARGAddress.Text = $"0x{Convert.ToString(testMailbox.SMU_ADDR_ARG, 16).ToUpper()}"; - - textBoxCMD.Text = "0x1"; - textBoxARG0.Text = "0x0"; } private void DisplaySystemInfo() @@ -95,6 +88,12 @@ private void DisplaySystemInfo() private void InitForm() { + /*if (cpu.Status == Utils.LibStatus.PARTIALLY_OK) + { + if (cpu.LastError != null) + MessageBox.Show(cpu.LastError.Message, Resources.Error); + }*/ + if (cpu.smu.Version == 0) { MessageBox.Show("Error getting SMU version!\n" + @@ -159,15 +158,15 @@ private void PopulateFrequencyList(ComboBox.ObjectCollection l) private void PopulateCCDList(ComboBox.ObjectCollection l) { - for (int core = 0; core < this._coreCount; ++core) - l.Add((object)new CoreListItem(core / 8, core / 4, core)); + for (int core = 0; core < cpu.info.cores; ++core) + l.Add(new CoreListItem(core / 8, core / 4, core)); } private void PopulateMailboxesList(ComboBox.ObjectCollection l) { l.Clear(); l.Add(new MailboxListItem("RSMU", cpu.smu.Rsmu)); - l.Add(new MailboxListItem("MP1", cpu.smu.Mp1smu)); + l.Add(new MailboxListItem("MP1", cpu.smu.Mp1Smu)); l.Add(new MailboxListItem("HSMP", cpu.smu.Hsmp)); } @@ -370,6 +369,8 @@ private void ButtonDefaults_Click(object sender, EventArgs e) { InitTestMailbox(cpu.smu.Rsmu); comboBoxMailboxSelect.SelectedIndex = 0; + textBoxCMD.Value = 1; + textBoxARG0.Text = "0"; } private void ButtonApply_Click(object sender, EventArgs e) @@ -457,26 +458,134 @@ private void TextBoxPciValue_KeyDown(object sender, KeyEventArgs e) HandlePciWriteBtnClick(); } - private SMU.Status TrySettings(uint msgAddr, uint rspAddr, uint argAddress, uint cmd, uint value) + private SMU.Status TrySettings(uint msgAddr, uint rspAddr, uint argAddr, uint cmd, uint value) { uint[] args = new uint[6]; args[0] = value; testMailbox.SMU_ADDR_MSG = msgAddr; testMailbox.SMU_ADDR_RSP = rspAddr; - testMailbox.SMU_ADDR_ARG = argAddress; + testMailbox.SMU_ADDR_ARG = argAddr; return cpu.SendSmuCommand(testMailbox, cmd, ref args); } - private void ScanSmuRange(uint start, uint end, int step, byte offset) + private void ScanSmuRange(uint start, uint end, uint step, uint offset) + { + matches = new List(); + + List> temp = new List>(); + + while (start <= end) + { + uint smuRspAddress = start + offset; + + if (cpu.ReadDword(start) != 0xFFFFFFFF) + { + // Send unknown command 0xFF to each pair of this start and possible response addresses + if (cpu.WriteDwordEx(start, 0xFF)) + { + Thread.Sleep(10); + + while (smuRspAddress <= end) + { + // Expect UNKNOWN_CMD status to be returned if the mailbox works + if (cpu.ReadDword(smuRspAddress) == 0xFE) + { + // Send Get_SMU_Version command + if (cpu.WriteDwordEx(start, 0x2)) + { + Thread.Sleep(10); + if (cpu.ReadDword(smuRspAddress) == 0x1) + temp.Add(new KeyValuePair(start, smuRspAddress)); + } + } + smuRspAddress += step; + } + } + } + + start += step; + } + + if (temp.Count > 0) + { + for (var i = 0; i < temp.Count; i++) + { + Console.WriteLine($"{temp[i].Key:X8}: {temp[i].Value:X8}"); + } + + Console.WriteLine(); + } + + List possibleArgAddresses = new List(); + + foreach (var pair in temp) + { + Console.WriteLine($"Testing {pair.Key:X8}: {pair.Value:X8}"); + + if (TrySettings(pair.Key, pair.Value, 0xFFFFFFFF, 0x2, 0xFF) == SMU.Status.OK) + { + var smuArgAddress = pair.Value + 4; + while (smuArgAddress <= end) + { + if (cpu.ReadDword(smuArgAddress) == cpu.smu.Version) + { + possibleArgAddresses.Add(smuArgAddress); + } + smuArgAddress += step; + } + } + + // Verify the arg address returns correct value (should be test argument + 1) + foreach (var address in possibleArgAddresses) + { + uint testArg = 0xFAFAFAFA; + var retries = 3; + + while (retries > 0) + { + testArg++; + retries--; + + // Send test command + if (TrySettings(pair.Key, pair.Value, address, 0x1, testArg) == SMU.Status.OK) + if (cpu.ReadDword(address) != testArg + 1) + retries = -1; + } + + if (retries == 0) + { + matches.Add(new SmuAddressSet(pair.Key, pair.Value, address)); + + string responseString = + $"CMD: 0x{pair.Key:X8}" + + Environment.NewLine + + $"RSP: 0x{pair.Value:X8}" + + Environment.NewLine + + $"ARG: 0x{address:X8}" + + Environment.NewLine + + Environment.NewLine; + + Invoke(new MethodInvoker(delegate + { + textBoxResult.Text += responseString; + })); + + break; + } + } + } + } + + /*private void ScanSmuRange_old(uint start, uint end, int step, byte offset) { matches = new List(); while (start <= end) { uint smuRspAddress = start + offset; - uint smuArgAddress = 0xF; + uint smuArgAddress = 0xFFFFFFFF; if (cpu.ReadDword(start) != 0xFFFFFFFF) { @@ -534,7 +643,7 @@ private void ScanSmuRange(uint start, uint end, int step, byte offset) start += (uint)step; } - } + }*/ private void RunBackgroundTask(DoWorkEventHandler task, RunWorkerCompletedEventHandler completedHandler) { From f65ae7dc43c62832e1e3abe12dae573bc7958945 Mon Sep 17 00:00:00 2001 From: Ivan Rusanov Date: Mon, 22 Nov 2021 05:04:00 +0200 Subject: [PATCH 6/7] Update core dll --- PowerTableMonitor.cs | 10 ++++------ Prebuilt/ZenStates-Core.dll | Bin 60928 -> 107520 bytes SettingsForm.cs | 31 +++++++++++++++++-------------- 3 files changed, 21 insertions(+), 20 deletions(-) diff --git a/PowerTableMonitor.cs b/PowerTableMonitor.cs index f5f5aea..dfa80ac 100644 --- a/PowerTableMonitor.cs +++ b/PowerTableMonitor.cs @@ -22,29 +22,27 @@ private class PowerMonitorItem public string Value { get; set; } } - private void FillInData(uint[] table) + private void FillInData(float[] table) { list.Clear(); for (var i = 0; i < table.Length; i++) { - var bytes = BitConverter.GetBytes(table[i]); list.Add(new PowerMonitorItem { Index = $"{i:D4}", Offset = $"0x{(i*4):X4}", - Value = $"{BitConverter.ToSingle(bytes, 0):F6}" + Value = $"{table[i]:F6}" });; } } - private void RefreshData(uint[] table) + private void RefreshData(float[] table) { int index = 0; foreach (var item in list) { - var bytes = BitConverter.GetBytes(table[index]); - item.Value = $"{BitConverter.ToSingle(bytes, 0):F6}"; + item.Value = $"{table[index]:F6}"; index++; } diff --git a/Prebuilt/ZenStates-Core.dll b/Prebuilt/ZenStates-Core.dll index cb5d8eb794d2137f9e711843eb688c75e1c75122..4dd9d5612b83fa67f07dc1ca418893f33d4d379e 100644 GIT binary patch literal 107520 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

V=5V#0VYJQxswP_jb>=+GF?Gid-(Q zuhiaX_rW^hc3Jm`Aq@;ndja|U_sKAPBn3qluMKtuEWaM=LR<7rJ<$2~>cs-7OZ^tX z#iE2%U8_-J|BW~Gl1()Ihw(~G|3PLb6#IAoQKA1)JiXp@k<7aA*F|FSF%MzGi$tT$ zAaeg%#2^cG@7FFo);$81q=w=S@Y6+Vgbh%&tI6r>oÅ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 U$4(xLcc1kAy%chK{zx_!76zCk7+`P)q7f%0 zwpw?M8h2yjUZd5z?x&HdJHr0xV4uIc&tKcv;_r=gh09Y@-BV@MO?5&nR&3(YtKZmT zq_$g3@h2-Yg?JYdO_$!3qzK^$@5fz;bmmn(-z1>?^Itpkkkg+{RGmVm^nc_oA&Ky} z9Pu_1gLvkGc_!?T(`*?P_KmUSU@!#*_3L zT#1lFzoB&qAws$#INg%<8&W5fs^2E)H)NNDh@WmA{g$EMy!vgTe)H+KO#POn-?H`F zB>jduqF8eE+hqNgr{D7RTLIkyNC$ZfARTx9UM1O4>K0K{Out(Mog!MuoT>#-L`^UC z5S5*4A%I-DQ=Fv}gqp=wA?9XK{i$kn9>P73Jg5O=*&RT!wE=>9RjJXXq(|lw^#t|G zQ=`X`9=T4`6O41Ms?iHbkK!ci3C6h%)ab3GM>!Mq1oh@nqfe6_6_BVWsJD|E{ebj- ztDd0VfNJzB(xY+`!xM~i%c@a_0{s-Lo}k|3YSc^mBCDQYoP9x!=8_&`SYrGHkB&KfyS=t{NR8ebA~W7-yeWqi2%7)T$>KXJ=QV7n8osswWudUZ6&AAbq)2 zPcY8iLyg`;`u(hWf^qIQYVK#gr{*Lssta^fR?rCcDZPM>=)f0?!7gVEv zC;e=zo?x8&rW*Z*^c7Y;!8mtXHJYYEKgX&k7>ASE(f`Uwe}Gj_Fb*dr{Sl-;(5fdG zhm(?i9qBP2CAJ^IIGmL9XOq6tswWtSlal^c(jR2i6O6-2N&h?2V~|LUpI{tLO8S42 z{$Q(~U>r_Ldan)oL#%p&aX2aI=aBwTtDaySPD=Wfq(986Cm4s5k{&}{|MOK=J;6Af zl=Rn-zS^oM7>ARR{z=kfGE6KV!8n|h^dFGE#;PY6hm(>%%?^F7RZlPuCnfzH($`t_ z1mkd0(jP#cf%aX2aIzastN zRz1NuoRsuMNzfl*)f0@vNlD*8`o&f~!8n|h^v9FF!Kx=1hm(^28qzPZ>Iuf-q@;h6 z^o>?M!8n}Mt_~%ER_3S>3^|BJcLVDr*3PU(?3W5jUBrIGteaSLeMpmueU;f1VxMI; zmDop_oj@#xA=su7do!~%`B!dd){V5-El23s0~ zD!&%Q(r{Dx3A2U7zRTAGfP85<*%5XM(q8}7883bv(&dMuVt3Hapk4V zQje`Xhgs^Jl|NyY`eEsiIz;`gG^P$wzbaj)4wcirQytom?nkLZ)E`P))FJZw(j(L% z^6%0bb%^}9be=jy{#rU)9U{Lh4XQ)rf2Bq05cyeYt~x~iRO(fS$ZtxM)gkhaiF=ix zl9lQzbqO_FU-;;55Sge5EpxBpwR`NOoTMuS^6j0euk%rX9@Lv1(U@ya41BalA~|ky zZG|RvyS3735RzL(vJtg32*CTa;)Inb5}>s!#e;~Acx(aquIASCwHn38Ycq#t<+AL9HQR1_F#`dYsHau)q*70|CY>-GUhiFhJ=7W+1?b zqzjmV;BZ603OW;P1fEzVGZq(?wQB&ha4U8K#D{j=7xKR`0Mh%A>H5YEwNVrkc;6@FC8#M!N zRQb43mE%SgjT==jZd9qbQB~qb6^I*E8*WrtxKS11Miqk_RR?ZV338W3ov8z`1oc3B z%BdI(RPMcnh-zbL|9X;w0`6UA9iq%c-a#1MnA##AwhF~<%Sys|Ku6X}I#cLa-8R9_ z%*eTdT}(7>N!8`!0INsN5CYI^6j!D@=tG2US-i2fYgsGYwydsnMc6X;+ESclZ)>SR z;X>IIP9MWH(l2vFpF{-(C)fhHXft<)2u#M^ELW01OVQbndH&(H8Rr|xwt{qd)RAH< z$d+s>`~+^OsSf?-)Nd}n1@aI%rUHS{AMw)p3M6z6;t@s9K0|+B9A;bJQ*_y-^ta)# zRV(EY3-@dEO*%iooYUmaN)}p5W@>PT({&B}I@fDQq-PNqK=ry&W^a-wsWeGsCI^#+ zD{Don%Xv=s{x3MZ8j{yarlcvf0tqsMU^-(n7&|fK2k7jEAGD(-M|>V0p$2DhZ_42+ z$H~MHIaTDZXzXGDvJap~o6{!=^m41>0K|(#P!?MN-Tenno#@IxzJ)evN611E7X93DP&|zZ&R)9=CIGOOEbA434wr!MOv4unwRPxr;N=N||1JrZ*|m zt7Uo}nO>(q`^6;Tb@?aL&F!Cy>h~sRdsEaQ%I6S94|`UInqkYZXCy^dpf=&t-c(O& z<%Os;p`LUC44m<=Kqc>|2M7kAmb;M$bD%Dkxo*%);tHrTK#gLRDqF#sSj}@W3Cngla4+k3_Rgeju z38h`K6t05FUGZo8qGXJ%~&uA@lW(j#NnU+68N|`Im??Og7q>IHp!Y@Bq6m{ z!Exmi6XC4A3i23KGQB>JuQXkFTm@Atye^NMZf>D^Tp3y*in=LHQ$6ks2lE^v%bV%R zEKQCsPiSEB0gqOYsXKue6N8lGXLAKf?8uzVFuSAOo8cGP&Y7O%6<)6;*C<$)C#%%w z@p?R2ZKbx%U=n;-sO?^FFbl#AkEab|dU>Kk^>{O!Mh?B%o@`|A^pWi8Ev;wC6ZsJ} zxD8dJCo2;tfhT2E91jAl3KHb6@}wLccbX~;GF(2Vey+_?t|Sv2x69BTXFM4|yy^2! zLTyfpZzLDXj?*ATLxtf-fs-gZZZn+4zv22?JcV?+J4fz?K(hA}8`uQu>uc+cT|%aa z3#PGGh=*TeBs&!>`C^VIr!-xSK4esio}Db29iKNBdCc7>j~JM%yO2}-VG+mkZU}d{ z8x1b#$%6Mh>9}Lb$8%_&ls}FE>|R)$gaO?LU9Oa$4}1==ACVYxntxw}EQQB@9`GWV z|FmR>TdRXTEz(eDoG3qh2o?nkqsdNVc!?f3!eVT<4mwE39zhdosjd`f9i~c-4cX@y zF|LYfxMt#7kZ{cdAFK_|kKSU&7ya7^8*~||M0-crTSnN=O%`=X>zfWlm`df#bj#6j zE;SF2QIQ8xSjj#N))skQAK{aQ+vixBr;A)6+w{()5#% zo=w!Ed=sdAe*6>3nJKC*l7ZZ1sDVD*urjbav&xelSu0eVd&9z0a{?kgmdieOUgbGXM z04Z}rh@ik7I1RR`uF54q$QZKbwNF0#FgT+(38A{Znn&{_ozuNn^*TMyQs!w&b_LTt zNgh{HlgG7Xs|QOZ42&+1w%6`;d)#I3$iig?dJ(<=EE z1yVdIrTJLX==CAEK8gdUBc#w?Oqq)wEi%2S!8}+{$vmk!t5zWK)GZu)u_qO&W2Wb9 z+P#=6%U*^lRfb)+z;Y=9M7^A5DD>oU(h4?adeei2MndUG2qjEEm+C{$mM0yFVcMd) zL18@}PuUA&#zt8uZ!^~J$c{&3am`N4Oxo&JZFVf2`;jeLd>eZLyBI`iJ@h}*En5d| z7Q$rxEnaTv6F5UL`o#C~QN5nw1GLab+LT{3nt*Rw^RUv$!<;capYrgcE%G>A-!R;7 zOv9aI7{O_x<~Gun-ICMBtTDR$oko;n_i~xG928IirQcdzoP&{3!N`SP1KybqfhDf+ z>gCVGks8-L>cj58Kvi~ThzupmMtiSg15?rSB6IcL4)4O2G!^SP{SSThu!2dNKL4%4 z{zMngsM7Mg3Jz;q-?Qqd6sHuXSFOqnV3>8A_$Xt?Tq3q1TJK`Z#Jg^L4z{hj zC=Vjqve_rOgKD-rxH{Jz>?lZe2al0K%9Bk)9Es9sR%*|K?PPcGpnP}mfC860ILkDl zk*YMQAlV(X6{NU>*##5aL2rT29h^|$b_ZPrY3`sMdu9~4PgWSMGHGD^k*qHo{%9yH zD4a9F<0{R;cn!Wh7@SMX$MOKrwgJK-{9 zbf5bfNQUsIY)caHFVPI((}_nQ``mx%N)|{Z8?y3cT{&^gkTk5zIsI-734XwD+OP#j zCz?ENdLo!Zx-pXz!L{S5f=i&8`>|#g;9%k@kHLy@!{k6SW}(pmjowM)r6$&+J+i1h z_+SKmRPJA8H_bshek{?3GZcMeXYNnQbsKWe#=c&emZ@DmElXcDJ0k6(D9T zBptdW%#llMyN(0J7(a})6DMgKD@p1B|9wef5jwh*)T#b!lhh*9QCP1NeL`Q)Y5e|9 zwmz2W^`BVz`IIe;+f@B#<V0Ii+ z*^Norn3J(bz}XM))rM$ypG|Ab(n=gxVL7Q!QygWdz%+%z8d0K4rC~bg%4!SDpn9_h zi*ULU%vS>&k@K@^;C?h(2<8G9WGv@xcF_ghQ8c^w%t5biG+GziuABgGU|O=X4ckeSy@;!>AQjZkxW54pP#vrz@)8OR_0bZ z;idD8$i9t(N;fiQ;(V`ywxQNV>!5}BY!sVS6-()axH6BG zi|m99(=c}rjNcO{>_V&6zG{mDq4 zpfX^o_k;3)8B_-U8A772`?RbreFgrG_T;(kKQJzuTJ`eG8xq1SpV<$ph#3yq}4n(b63XlHG!Y*hT;U{0Wm1QLKxCmw+EtsAt!QvR(TFmI! zz!aHVAN$sn#LUwEmo`DEL8pH&qUJtTtY&2fPKLCkSk07N?o7O!i54rQwAG=L(A9@d z1ws67t#W^8;AMdyBM^5}>IO8zI33=kH}rP}ILOZsBoD@AB0FYmfijFy z8MdsP02ZKHF;1U@1<~1V(T~0D=CjCLKcy~*8J-AW%0ORp@m7#Fxi9eoAb^bz4#hD& ztwK(*p|KBjf+Qr<=W*t&I(7x`A2M8#*D>-Jdz_SKa{jDn4N~;D&cZTHrpGa&b9!7` zG36my@OU(V9VqRiFE!Q)VPx7%uBjipB?nXWM4b`%nI=#dZ%!=MPYl4icyA)d-Rj9y zgS?Ir#i-3ga3uq$ArCbF%m$yHFvcY|Vq&XfU22S%w3*)nIfDZPP`#83 zT2I>e+z&fJ)Kx)xM^eFrj&>W)gYCv6KG-<;T#@T4dL*1>QYJrSn&clw6#DZfY_+su z^auM!B9RItfYR`@E#o01?JeI#0Q6MUxoO5bDi<7Bo4X5IdlOoMcSgGG7RWM`y}qNU z!_7gov@fHHqX^=Y(y?jGjHiK0U<+V*>yA%=MBr(oMcNlnC2@u_!5;T;kfeA9?i1`u ztMCXY!@k#tyeXVDb?7I^i{mUxwjkZ!PPiF_lTqk_EqS*8kGUl zss6sTO3cCqnvq^9lF@S2wvn}>KJ2ZP9CCHRXfb|4&zN$XGE)bqJ9 zIy84oKklek-p8kxA5GhNPx-1~zn}V&JGj=5XIi+o+w$6y9p=#Lr;}oLu*i{B?sjCC zYYsR9ZL(=shYhkV2EyVHi@4?qNF&@NrvB` z4^w-2klk6y82`z9uN_CZXl17jA-CX#0JJuSFhS!Vt&|WJb1Qlr#+jtKS3-h93?JrJ z16Ls@T%ZHe)WCKF$dlsIiMoNQSyZ#?C^x!_O=dd_l@_=Zp?EotR^;Wl*RFc(+N!{f zP~hRLd`LSI3X9OOLM5r5B!s$toKTr#htgD!hEO++6Dr#pN|jj*+&qr`q;c$jF^+xC zIQF-VW1l;Y{q2eNCCUo&vBSm86Galum1rz6^EQLOTg-gd;6D^4nToWTtduM;_{B=e zdV@bnDY;(fb2gqqo|LZ+^F3!H_K6JTeTcl8-+E&P&)dkiS-=bg+>PG>4{$0ug#nH>RBp3IE5|nC(BnxFG#|N2_2;VB>;7L21Fvf^-zdER7HcB3lk* z=1wZZy+j@)avo){6p936g^bT~LUAos){R7NCc?&(p-3=R$@oGtW|P~Asljn)NWE$66jg!duc{2VhnS4m(W7D|DVqD<)zLtJPRLN+kQiG9u`%8&j zK^eZn5-q%-N*W(bCRIdgO=BuaLRHwvxYh-eb~5QAveq=Fk|Y@0$#@YNkJ$B?#xGfo zlYW44LB{uvR#1uGA+Pu;Ty%sKtSzWb$SO_zW16)W9GqZAD*@dMqbYoh$b&?#CGrkM zf;XH{2WA&D1F+fSWcCyh4*xL)_|y`BmJxaiJ5AeXh`W;r+4{er0RF`=G*Yp-%4DFi zQb7yDOF>4mMZ@IysgSKdK%|sH>8T9U(u;Re`bdrJ(DV9Zai_oNeYCnb1Z$sR8d0N< znUKcN=(8rIQ8W6A32B^+eqcfx8Kd8rkjBDjZn62nP;5L{^pn1KK*DBXe? z2(Wz71k%l@J{ZE=h=v z1O-KrX(JI7Or?`-ikx-Dk%9y?JyMu}0+Av@Xl8C_Y?t`YEN9k#Q#q;H3f38!X4GS3 zlTojcO-6lsHf3#fMauLdur3_gF9EHlt+!dP$3}t)C=$WC*{GHuRLlP}_0wsopDv?O zxzuYdwbgB@tz#{KIE^g)CLoVsWfiOT{gQH{E&-)R7ABwxk@^Ib7C9mTrAHbPkSEfZfHERS zCZLIt7D6Qp)WFlk;1fl<7wP9|_vWLXNGZ7K95OQCZth0gtDP%}j2P^|B8oP;AOmxw)&u7Ib%`hgUkN6nCPbqqb%JuN$i zg{~H<0xzcJB!WqaU~=r&BW8KA-;96)cZ_L77Cg{>*SRWMnu#zw_^0D1i@YyN4paQ|0cod34*Ul@JmxLOqt;46j!T4 zlu^D^oBlBVD`*05pe9TSVz&pd79~mKMBD>^OH_YD>bDam^nP;yVhW%?$iACGA?6VY zwpCgH*&InmqfmcIl+cS_fe#WT^xk&h?}-weOxOdTBueP5?7%-0CG;wH0G%FbMPEi8 z$dV#;`&r9q*-(gj4g4`N2)&q}wO0-7NfgpcWPv{=O0cE02i_uyh`xcCW3`CMt8ZmdB~*!-ZGF^nAGS`GIKT7)gDpC*{rA=12GV z88yAQW`3?uO0resGk;PrNk4&T(;?>xhKzsFyddzYn20kaEbx9IXO4j%(xNv%W;tnUCFpeNBm-3MmQlJLh0#G6OT>$Db7}B z<`DfXyLf7vxE9MLP0XFN(yxi@nf{DvRt`ztX8voYjZCLb3M1@$*+h?J$$Nped`;Z# zBYJ%{(KoV)uFEHSB}@KYLj3&6M4!o~)Ne)Vns7}bI#mASTumHONZQ}|o`&QbKk@q& zlKd~sr%yi;pI?4Ii|7|#qPI;W`a37toQ)LS;%Cl^Jh!-d3eh#i6?vNIQ5qbYcouYm zcz8GV{}!=Jfa?@p%j{vnqn z*KvLvrNn>9dH&7x_mNf<<;@hE${#Jx#G}+li#72)Ti&XWrH^Bq$Te^t$CH~$@{gtv z-JC;o9!n-z>VmVF4`M@SJ0&{^e#4uKU}-d#+nT`XlZSW0LO`Yq{J`w0D1Y!<@^=Vi1- z+$lCe_moDuE5u!FS&mqyitEHvj6R>HqhB*>l)B$AdPC}-X7oN#1;RbUXuh<3meIpP zkL5W=F-1qeWt1Z=pU0cl>B0_l2x57G(U;Q+T`zto6o0x{S4ijv@v^{>E3OF8=fEBi zHib|wqn#36oJG2)B$_mt&~GK8*H4cWFG;kqKt~Rar0{>5TT4=_ttPHxli~$RT5y&FDj^JCM=663t^Y zL0TTh=rgISVYEx4g^bq9yd1&k1*vOfbfrWsj8@7LEobz$)E&j>R*Bje-6`YjWb~TU ztzmS%MC%w0=IEu3F#3Cjj$({zygE9b(Fro#5Tgf5b={8{6-(Vu7@Z>H{28NfWSnO* zYL#)G%jgUl?gB>7$~Z4(R4H|rGb%0D)4Ph%5}Cp^jGmGy+`uSDrm%xigN)@?M(4>C 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

noy(dk0Ark;OHZsBMS6DprHq#8w_XV%cOlwmgYr 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 diff --git a/SettingsForm.cs b/SettingsForm.cs index e716d13..b923443 100644 --- a/SettingsForm.cs +++ b/SettingsForm.cs @@ -122,8 +122,11 @@ private void InitForm() comboBoxCore.SelectedIndex = 0; int index = (int)((GetCurrentMulti() - 5.50) / 0.25); - comboBoxACF.SelectedIndex = index; - comboBoxSCF.SelectedIndex = index; + if (index > -1) + { + comboBoxACF.SelectedIndex = index; + comboBoxSCF.SelectedIndex = index; + } var prochotEnabled = cpu.IsProchotEnabled(); checkBoxPROCHOT.Checked = prochotEnabled; @@ -419,8 +422,8 @@ private void HandlePciWriteBtnClick() TryConvertToUint(textBoxPciValue.Text, out uint data); bool res = false; - if (cpu.Ols.WritePciConfigDwordEx(cpu.smu.SMU_PCI_ADDR, cpu.smu.SMU_OFFSET_ADDR, address) == 1) - res = (cpu.Ols.WritePciConfigDwordEx(cpu.smu.SMU_PCI_ADDR, cpu.smu.SMU_OFFSET_DATA, data) == 1); + if (cpu.WriteDwordEx(cpu.smu.SMU_OFFSET_ADDR, address)) + res = cpu.WriteDwordEx(cpu.smu.SMU_OFFSET_DATA, data); if (res) SetStatusText("Write OK."); @@ -865,7 +868,7 @@ private void BtnPstateRead_Click(object sender, EventArgs e) { uint eax = default, edx = default; var pstateId = pstateIdBox.SelectedIndex; - if (cpu.Ols.Rdmsr(Convert.ToUInt32(Convert.ToInt64(0xC0010064) + pstateId), ref eax, ref edx) != 1) + if (!cpu.ReadMsr(Convert.ToUInt32(Convert.ToInt64(0xC0010064) + pstateId), ref eax, ref edx)) { SetStatusText($@"Error reading PState {pstateId}!"); return; @@ -918,7 +921,7 @@ private void BtnPstateWrite_Click(object sender, EventArgs e) uint CpuDfsId = 0x0; uint CpuFid = 0x0; - if (cpu.Ols.Rdmsr(Convert.ToUInt32(Convert.ToInt64(0xC0010064) + pstateId), ref eax, ref edx) != 1) + if (!cpu.ReadMsr(Convert.ToUInt32(Convert.ToInt64(0xC0010064) + pstateId), ref eax, ref edx)) { SetStatusText($@"Error reading PState {pstateId}!"); return; @@ -949,7 +952,7 @@ public bool ApplyTscWorkaround() { uint eax = 0, edx = 0; - if (cpu.Ols.Rdmsr(0xC0010015, ref eax, ref edx) != -1) + if (cpu.ReadMsr(0xC0010015, ref eax, ref edx)) { eax |= 0x200000; return cpu.WriteMsr(0xC0010015, eax, edx); @@ -1092,7 +1095,7 @@ private void ReadMsr_Task(object sender, DoWorkEventArgs e) while (startReg <= endReg) { uint eax = default, edx = default; - if (cpu.Ols.Rdmsr(startReg, ref eax, ref edx) == 1) + if (cpu.ReadMsr(startReg, ref eax, ref edx)) { result += $"0x{startReg:X8}: 0x{edx:X8} 0x{eax:X8}" + Environment.NewLine; } @@ -1116,7 +1119,7 @@ private void ButtonMsrRead_Click(object sender, EventArgs e) { TryConvertToUint(textBoxMsrAddress.Text, out uint msr); uint eax = default, edx = default; - if (cpu.Ols.Rdmsr(msr, ref eax, ref edx) == 1) + if (cpu.ReadMsr(msr, ref eax, ref edx)) { textBoxMsrEdx.Text = $"0x{edx:X8}"; textBoxMsrEax.Text = $"0x{eax:X8}"; @@ -1156,23 +1159,23 @@ private void ReadCPUID_Task(object sender, DoWorkEventArgs e) uint LFuncStd = 0, LFuncExt = 0; uint eax = 0, ebx = 0, ecx = 0, edx = 0; - if (cpu.Ols.Cpuid(0x00000000, ref eax, ref ebx, ref ecx, ref edx) == 1) + if (cpu.Cpuid(0x00000000, ref eax, ref ebx, ref ecx, ref edx)) LFuncStd = eax; - if (cpu.Ols.Cpuid(0x80000000, ref eax, ref ebx, ref ecx, ref edx) == 1) + if (cpu.Cpuid(0x80000000, ref eax, ref ebx, ref ecx, ref edx)) LFuncExt = eax - 0x80000000; for (uint i = 0; i <= LFuncStd; ++i) { var index = 0x00000000 + i; - cpu.Ols.Cpuid(index, ref eax, ref ebx, ref ecx, ref edx); + cpu.Cpuid(index, ref eax, ref ebx, ref ecx, ref edx); result += $"0x{index:X8}: 0x{eax:X8} 0x{ebx:X8} 0x{ecx:X8} 0x{edx:X8}" + Environment.NewLine; } for (uint i = 0; i <= LFuncExt; ++i) { var index = 0x80000000 + i; - cpu.Ols.Cpuid(index, ref eax, ref ebx, ref ecx, ref edx); + cpu.Cpuid(index, ref eax, ref ebx, ref ecx, ref edx); result += $"0x{index:X8}: 0x{eax:X8} 0x{ebx:X8} 0x{ecx:X8} 0x{edx:X8}" + Environment.NewLine; } @@ -1192,7 +1195,7 @@ private void ButtonCPUIDRead_Click(object sender, EventArgs e) { TryConvertToUint(textBoxCPUIDAddress.Text, out uint index); uint eax = 0, ebx = 0, ecx = 0, edx = 0; - if (cpu.Ols.Cpuid(index, ref eax, ref ebx, ref ecx, ref edx) == 1) + if (cpu.Cpuid(index, ref eax, ref ebx, ref ecx, ref edx)) { textBoxCPUIDeax.Text = $"0x{eax:X8}"; textBoxCPUIDebx.Text = $"0x{ebx:X8}"; From 06e1bfc3dad5c917251cce6979157811ec9adb02 Mon Sep 17 00:00:00 2001 From: Ivan Rusanov Date: Mon, 10 Jan 2022 18:23:14 +0200 Subject: [PATCH 7/7] Update core dll --- Prebuilt/ZenStates-Core.dll | Bin 107520 -> 93184 bytes SettingsForm.Designer.cs | 1 + SettingsForm.cs | 36 +++++++++++++++++++++++++----------- 3 files changed, 26 insertions(+), 11 deletions(-) diff --git a/Prebuilt/ZenStates-Core.dll b/Prebuilt/ZenStates-Core.dll index 4dd9d5612b83fa67f07dc1ca418893f33d4d379e..f88298e0055f9ab6e490c904260cc955213b74f6 100644 GIT binary patch delta 40603 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 F|1UU&hcW;F literal 107520 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

V=5V#0VYJQxswP_jb>=+GF?Gid-(Q zuhiaX_rW^hc3Jm`Aq@;ndja|U_sKAPBn3qluMKtuEWaM=LR<7rJ<$2~>cs-7OZ^tX z#iE2%U8_-J|BW~Gl1()Ihw(~G|3PLb6#IAoQKA1)JiXp@k<7aA*F|FSF%MzGi$tT$ zAaeg%#2^cG@7FFo);$81q=w=S@Y6+Vgbh%&tI6r>oÅ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 U$4(xLcc1kAy%chK{zx