using System; using System.Collections.Generic; using IL2CPU.API.Attribs; namespace Cosmos.Core { // Non hardware class, only used by core and hardware drivers for ports etc. /// /// CPU class. Non hardware class, only used by core and hardware drivers for ports etc. /// public class CPU { // Amount of RAM in MB's. // needs to be static, as Heap needs it before we can instantiate objects /// /// Get amount of RAM in MB's. Plugged. /// [PlugMethod(PlugRequired = true)] public static uint GetAmountOfRAM() => throw null; // needs to be static, as Heap needs it before we can instantiate objects /// /// Get end of the kernel. Plugged. /// [PlugMethod(PlugRequired = true)] public static uint GetEndOfKernel() => throw null; /// /// Update IDT. Plugged. /// [PlugMethod(PlugRequired = true)] public void UpdateIDT(bool aEnableInterruptsImmediately) => throw null; /// /// Init float. Plugged. /// [PlugMethod(PlugRequired = true)] public void InitFloat() => throw null; /// /// Init SSE. Plugged. /// [PlugMethod(PlugRequired = true)] public void InitSSE() => throw null; /// /// Zero fill. Plugged. /// [PlugMethod(PlugRequired = true)] public static void ZeroFill(uint aStartAddress, uint aLength) => throw null; /// /// Hult the CPU. Plugged. /// [PlugMethod(PlugRequired = true)] public void Halt() => throw null; /// /// Reboot the CPU. /// public void Reboot() { // Disable all interrupts DisableInterrupts(); var myPort = new IOPort(0x64); while ((myPort.Byte & 0x02) != 0) { } myPort.Byte = 0xFE; Halt(); // If it didn't work, Halt the CPU } /// /// Enable interrupts. Plugged. /// [PlugMethod(PlugRequired = true)] private static void DoEnableInterrupts() => throw null; /// /// Disable interrupts. Plugged. /// [PlugMethod(PlugRequired = true)] private static void DoDisableInterrupts() => throw null; /// /// Check if interrupts enabled. /// [AsmMarker(AsmMarker.Type.Processor_IntsEnabled)] public static bool mInterruptsEnabled; /// /// Enable interrupts. /// public static void EnableInterrupts() { mInterruptsEnabled = true; DoEnableInterrupts(); } /// /// Returns if the interrupts were actually enabled. /// /// bool value. public static bool DisableInterrupts() { DoDisableInterrupts(); var xResult = mInterruptsEnabled; mInterruptsEnabled = false; return xResult; } /// /// Get CPU vendor name. /// /// string value. /// Thrown on fatal error, contact support. /// Thrown if can not read CPU vendor name. public static string GetCPUVendorName() { if (CanReadCPUID() != 0) { int eax = 0; int ebx = 0; int ecx = 0; int edx = 0; ReadCPUID(0, ref eax, ref ebx, ref ecx, ref edx); // 0 is vendor name string s = ""; s += (char)(ebx & 0xff); s += (char)((ebx >> 8) & 0xff); s += (char)((ebx >> 16) & 0xff); s += (char)(ebx >> 24); s += (char)((edx) & 0xff); s += (char)((edx >> 8) & 0xff); s += (char)((edx >> 16) & 0xff); s += (char)(edx >> 24); s += (char)((ecx) & 0xff); s += (char)((ecx >> 8) & 0xff); s += (char)((ecx >> 16) & 0xff); s += (char)(ecx >> 24); return s; } throw new NotSupportedException(); } /// /// Get CPU up time. /// /// ulong value. /// Thrown on fatal error, contact support. public static ulong GetCPUUptime() { // TODO Divide by cpu clock speed return ReadTimestampCounter(); } /// /// Get CPU cycle speed. /// /// long value. /// Thrown on fatal error, contact support. /// Thrown if can not read CPU ID. public static long GetCPUCycleSpeed() { if (CanReadCPUID() != 0) { // See https://c9x.me/x86/html/file_module_x86_id_45.html int eax = 0; int ebx = 0; int ecx = 0; int edx = 0; string s = ""; for (uint i = 0; i < 3; i++) { ReadCPUID(0x80000002 + i, ref eax, ref ebx, ref ecx, ref edx); s += (char)(ebx % 256); s += (char)((ebx >> 8) % 256); s += (char)((ebx>> 16) % 256); s += (char)((ebx >> 24) % 256); s += (char)(edx % 256); s += (char)((edx >> 8) % 256); s += (char)((edx >> 16) % 256); s += (char)((edx >> 24) % 256); s += (char)(ecx % 256); s += (char)((ecx >> 8) % 256); s += (char)((ecx >> 16) % 256); s += (char)((ecx >> 24) % 256); } var _words = new List(); string curr = ""; for (int i = 0; i < s.Length; i++) { if (s[i] == ' ' || (byte)s[i] == 0) { if (curr != "") { _words.Add(curr); } curr = ""; } else { curr += s[i]; } } _words.Add(curr); string[] words = _words.ToArray(); string[] w = new string[words.Length]; for (int i = 0; i < words.Length; i++) { w[i] = words[words.Length - i - 1]; } words = w; double multiplier = 0; double value = 0; for (int i = 0; i < words.Length; i++) { if (words[i] == "MHz") { multiplier = 10e6; break; } else if (words[i] == "GHz") { multiplier = 10e9; break; } else if (words[i] == "THz") { multiplier = 10e12; break; } else if (value == 0) { Double.TryParse(words[i], out value); } } value *= multiplier; return (long)value; } throw new NotSupportedException(); } /// /// Check if can read CPU ID. Plugged. /// /// non-zero if can read. /// Thrown on fatal error, contact support. internal static int CanReadCPUID() => throw new NotImplementedException(); /// /// Read CPU ID. Plugged. /// /// type. /// eax. /// ebx. /// ecx. /// edx. /// Thrown on fatal error, contact support. internal static void ReadCPUID(uint type, ref int eax, ref int ebx, ref int ecx, ref int edx) => throw new NotImplementedException(); /// /// Read timestamp counter. Plugged. /// /// ulong value. /// Thrown on fatal error, contact support. internal static ulong ReadTimestampCounter() => throw new NotImplementedException(); /// /// Read from mode specific register. Plugged. /// /// ulong value. /// Thrown on fatal error, contact support. internal static ulong ReadFromModelSpecificRegister() => throw new NotImplementedException(); } }