From 6edb1bc08dbbaaf5a8c3799345438c8eb12622a0 Mon Sep 17 00:00:00 2001 From: sebastian-dev Date: Sat, 20 Jul 2024 16:46:23 +0200 Subject: [PATCH] Nct677x esio mutex (#1254) * Nct677X fix mutex acess with other devices an multiple instances Fix the access with multiple devices. Issue: #1243 Improper accessing the Nuvoton eSIO causes problems with other monitoring software * Fix timeout behavior, ensure the wait loop abort after a defined time * Update timeout behavior and Code Formatting * Update timeout behavior --- .../Hardware/Motherboard/Lpc/Nct677X.cs | 58 +++++++++++++++++-- 1 file changed, 53 insertions(+), 5 deletions(-) diff --git a/LibreHardwareMonitorLib/Hardware/Motherboard/Lpc/Nct677X.cs b/LibreHardwareMonitorLib/Hardware/Motherboard/Lpc/Nct677X.cs index 48390ed..ee0204d 100644 --- a/LibreHardwareMonitorLib/Hardware/Motherboard/Lpc/Nct677X.cs +++ b/LibreHardwareMonitorLib/Hardware/Motherboard/Lpc/Nct677X.cs @@ -817,11 +817,36 @@ internal class Nct677X : ISuperIO } byte page = (byte)(address >> 8); - byte index = (byte)(address & 0xFF); - Ring0.WriteIoPort(_port + EC_SPACE_PAGE_REGISTER_OFFSET, EC_SPACE_PAGE_SELECT); + byte index = (byte)(address & 0xFF); + + //wait for access, access == EC_SPACE_PAGE_SELECT + //timeout: after 500ms, abort and force access + byte access; + + DateTime timeout = DateTime.UtcNow.AddMilliseconds(500); + while (true) + { + access = Ring0.ReadIoPort(_port + EC_SPACE_PAGE_REGISTER_OFFSET); + if (access == EC_SPACE_PAGE_SELECT || DateTime.UtcNow > timeout) + break; + + System.Threading.Thread.Sleep(1); + } + + if (access != EC_SPACE_PAGE_SELECT) + { + // Failed to gain access: force register access + Ring0.WriteIoPort(_port + EC_SPACE_PAGE_REGISTER_OFFSET, EC_SPACE_PAGE_SELECT); + } + Ring0.WriteIoPort(_port + EC_SPACE_PAGE_REGISTER_OFFSET, page); Ring0.WriteIoPort(_port + EC_SPACE_INDEX_REGISTER_OFFSET, index); - return Ring0.ReadIoPort(_port + EC_SPACE_DATA_REGISTER_OFFSET); + byte result = Ring0.ReadIoPort(_port + EC_SPACE_DATA_REGISTER_OFFSET); + + //free access for other instances + Ring0.WriteIoPort(_port + EC_SPACE_PAGE_REGISTER_OFFSET, EC_SPACE_PAGE_SELECT); + + return result; } private void WriteByte(ushort address, byte value) @@ -838,11 +863,34 @@ internal class Nct677X : ISuperIO else { byte page = (byte)(address >> 8); - byte index = (byte)(address & 0xFF); - Ring0.WriteIoPort(_port + EC_SPACE_PAGE_REGISTER_OFFSET, EC_SPACE_PAGE_SELECT); + byte index = (byte)(address & 0xFF); + + //wait for access, access == EC_SPACE_PAGE_SELECT + //timeout: after 500ms, abort and force access + byte access; + + DateTime timeout = DateTime.UtcNow.AddMilliseconds(500); + while (true) + { + access = Ring0.ReadIoPort(_port + EC_SPACE_PAGE_REGISTER_OFFSET); + if (access == EC_SPACE_PAGE_SELECT || DateTime.UtcNow > timeout) + break; + + System.Threading.Thread.Sleep(1); + } + + if (access != EC_SPACE_PAGE_SELECT) + { + // Failed to gain access: force register access + Ring0.WriteIoPort(_port + EC_SPACE_PAGE_REGISTER_OFFSET, EC_SPACE_PAGE_SELECT); + } + Ring0.WriteIoPort(_port + EC_SPACE_PAGE_REGISTER_OFFSET, page); Ring0.WriteIoPort(_port + EC_SPACE_INDEX_REGISTER_OFFSET, index); Ring0.WriteIoPort(_port + EC_SPACE_DATA_REGISTER_OFFSET, value); + + //free access for other instances + Ring0.WriteIoPort(_port + EC_SPACE_PAGE_REGISTER_OFFSET, EC_SPACE_PAGE_SELECT); } }