//#define ISA_BRIDGE_EC_DEBUG using System.Diagnostics; namespace LibreHardwareMonitor.PawnIo { public enum MMIOState { Unknown = -999, MMIO_Original = -1, MMIO_Disabled = 0, MMIO_Enabled2E = 1, MMIO_Enabled4E = 2, MMIO_EnabledBoth = 3 }; public struct MMIOMapping { public int Index; public long BaseAddress; public long SuperIoSize; public long ChipId; } public class IsaBridgeEc { private readonly PawnIo _pawnIO = PawnIo.LoadModuleFromResource(typeof(IsaBridgeEc).Assembly, $"{nameof(LibreHardwareMonitor)}.Resources.PawnIo.IsaBridgeEC.bin"); // ioctl_find_superio_mmio public bool FindSuperIoMMIO(out MMIOMapping firstMmio, out MMIOMapping secondMmio) { long[] outArray = new long[6]; int ntStatusCode = _pawnIO.ExecuteHr("ioctl_find_superio_mmio", [], 0, outArray, 6, out uint returnSize); Log($"FindSuperIoMMIO statusCode: {ntStatusCode}"); if (ntStatusCode != 0) { firstMmio = default; secondMmio = default; return false; } firstMmio = new MMIOMapping { Index = 0, BaseAddress = outArray[0], SuperIoSize = outArray[1], ChipId = outArray[2] }; secondMmio = new MMIOMapping { Index = 1, BaseAddress = outArray[3], SuperIoSize = outArray[4], ChipId = outArray[5] }; Log($"First MMIO - BaseAddress: 0x{firstMmio.BaseAddress:X}, SuperIoSize: 0x{firstMmio.SuperIoSize:X}, ChipId: 0x{firstMmio.ChipId:X}"); Log($"Second MMIO - BaseAddress: 0x{secondMmio.BaseAddress:X}, SuperIoSize: 0x{secondMmio.SuperIoSize:X}, ChipId: 0x{secondMmio.ChipId:X}"); return firstMmio.BaseAddress != 0 || secondMmio.BaseAddress != 0; } //ioctl_access_superio_mmio public bool ReadMmio(long superIoIndex, long offset, long size, out byte value) { long[] inArray = new long[5] { superIoIndex, // superio index offset, // offset size, // size 0, // is write? 0 // value (ignored for read) }; long[] outarray = new long[1]; int ntStatusCode = _pawnIO.ExecuteHr("ioctl_access_superio_mmio", inArray, 5, outarray, 1, out uint returnSize); Log($"ReadMmio statusCode: {ntStatusCode}, Read Value: 0x{outarray[0]:X} at SuperIoIndex {superIoIndex}, offset {offset}, size {size}"); value = (byte)outarray[0]; return ntStatusCode == 0; } //ioctl_access_superio_mmio public bool WriteMmio(long superIoIndex, long offset, long size, byte value) { long[] inArray = new long[5] { superIoIndex, // superio index offset, // offset size, // size 1, // is write? value // value }; long[] outarray = new long[1]; int ntStatusCode = _pawnIO.ExecuteHr("ioctl_access_superio_mmio", inArray, 5, outarray, 1, out uint returnSize); Log($"WriteMmio statusCode: {ntStatusCode}, Written Value: 0x{value:X} at SuperIoIndex {superIoIndex}, offset {offset}, size {size}"); return ntStatusCode == 0; } // ioctl_map_superio_mmio public bool Map() { int ntStatusCode = _pawnIO.ExecuteHr("ioctl_map_superio_mmio", [], 0, [], 0, out uint returnSize); Log($"Map statusCode: {ntStatusCode}"); return ntStatusCode == 0; } // ioctl_unmap_superio_mmio public bool Unmap() { int ntStatusCode = _pawnIO.ExecuteHr("ioctl_unmap_superio_mmio", [], 0, [], 0, out uint returnSize); Log($"Unmap statusCode: {ntStatusCode}"); return ntStatusCode == 0; } // ioctl_access_superio_mmio public bool GetOriginalState(out MMIOState state) { state = MMIOState.Unknown; long[] outArray = new long[1]; int ntStatusCode = _pawnIO.ExecuteHr("ioctl_iomem_mmio_get_org_state", [], 0, outArray, 1, out uint returnSize); Log($"GetOriginalState statusCode: {ntStatusCode}"); if (ntStatusCode != 0) return false; Log($"Original MMIO State: {(MMIOState)outArray[0]}"); state = (MMIOState)outArray[0]; return true; } public bool TryGetCurrentState(out MMIOState state) { state = MMIOState.Unknown; long[] outArray = new long[1]; int ntStatusCode = _pawnIO.ExecuteHr("ioctl_iomem_mmio_get_cur_state", [], 0, outArray, 1, out uint returnSize); if (ntStatusCode != 0) return false; state = (MMIOState)outArray[0]; return true; } public bool TrySetState(MMIOState state) { long[] inArray = new long[1]; inArray[0] = (long)state; int ntStatusCode = _pawnIO.ExecuteHr("ioctl_iomem_mmio_set_state", inArray, 1, [], 0, out uint returnSize); Log($"TrySetState to {state} statusCode: {ntStatusCode}"); if (ntStatusCode != 0) return false; return true; } public void Close() => _pawnIO.Close(); /// /// Writes a debug message to both the output window and a log file when ISA_BRIDGE_EC_DEBUG is defined. /// /// The log entry is timestamped and appended to the file /// 'PawnIo_IsaBridgeEc_DebugLog.txt' in the application's working directory. This method only produces output /// when compiled with the ISA_BRIDGE_EC_DEBUG symbol defined. /// The message to log. This should provide relevant information for debugging purposes. [Conditional("DEBUG_LOG"), Conditional("ISA_BRIDGE_EC_DEBUG")] private static void Log(string message) { Debug.WriteLine(message); } } }