mirror of
https://github.com/openhardwaremonitor/openhardwaremonitor
synced 2025-08-31 06:15:08 +00:00
Extracted the register and value port state and some methods from the LPCIO class into a new class LPCPort. Fixed issue #733 (unlocking the i/o space after sleep).
This commit is contained in:
@@ -24,45 +24,22 @@ namespace OpenHardwareMonitor.Hardware.LPC {
|
||||
private readonly ushort[] REGISTER_PORTS = new ushort[] { 0x2E, 0x4E };
|
||||
private readonly ushort[] VALUE_PORTS = new ushort[] { 0x2F, 0x4F };
|
||||
|
||||
private ushort registerPort;
|
||||
private ushort valuePort;
|
||||
|
||||
// Registers
|
||||
private const byte CONFIGURATION_CONTROL_REGISTER = 0x02;
|
||||
private const byte DEVCIE_SELECT_REGISTER = 0x07;
|
||||
private const byte CHIP_ID_REGISTER = 0x20;
|
||||
private const byte CHIP_REVISION_REGISTER = 0x21;
|
||||
private const byte BASE_ADDRESS_REGISTER = 0x60;
|
||||
|
||||
private byte ReadByte(byte register) {
|
||||
Ring0.WriteIoPort(registerPort, register);
|
||||
return Ring0.ReadIoPort(valuePort);
|
||||
}
|
||||
|
||||
private void WriteByte(byte register, byte value) {
|
||||
Ring0.WriteIoPort(registerPort, register);
|
||||
Ring0.WriteIoPort(valuePort, value);
|
||||
}
|
||||
|
||||
private ushort ReadWord(byte register) {
|
||||
return (ushort)((ReadByte(register) << 8) |
|
||||
ReadByte((byte)(register + 1)));
|
||||
}
|
||||
|
||||
private void Select(byte logicalDeviceNumber) {
|
||||
Ring0.WriteIoPort(registerPort, DEVCIE_SELECT_REGISTER);
|
||||
Ring0.WriteIoPort(valuePort, logicalDeviceNumber);
|
||||
}
|
||||
|
||||
private void ReportUnknownChip(string type, int chip) {
|
||||
private void ReportUnknownChip(LPCPort port, string type, int chip) {
|
||||
report.Append("Chip ID: Unknown ");
|
||||
report.Append(type);
|
||||
report.Append(" with ID 0x");
|
||||
report.Append(chip.ToString("X", CultureInfo.InvariantCulture));
|
||||
report.Append(" at 0x");
|
||||
report.Append(registerPort.ToString("X", CultureInfo.InvariantCulture));
|
||||
report.Append(port.RegisterPort.ToString("X",
|
||||
CultureInfo.InvariantCulture));
|
||||
report.Append("/0x");
|
||||
report.AppendLine(valuePort.ToString("X", CultureInfo.InvariantCulture));
|
||||
report.AppendLine(port.ValuePort.ToString("X",
|
||||
CultureInfo.InvariantCulture));
|
||||
report.AppendLine();
|
||||
}
|
||||
|
||||
@@ -76,23 +53,12 @@ namespace OpenHardwareMonitor.Hardware.LPC {
|
||||
private const byte F71858_HARDWARE_MONITOR_LDN = 0x02;
|
||||
private const byte FINTEK_HARDWARE_MONITOR_LDN = 0x04;
|
||||
|
||||
private const byte NUVOTON_HARDWARE_MONITOR_IO_SPACE_LOCK = 0x28;
|
||||
|
||||
private void WinbondNuvotonFintekEnter() {
|
||||
Ring0.WriteIoPort(registerPort, 0x87);
|
||||
Ring0.WriteIoPort(registerPort, 0x87);
|
||||
}
|
||||
|
||||
private void WinbondNuvotonFintekExit() {
|
||||
Ring0.WriteIoPort(registerPort, 0xAA);
|
||||
}
|
||||
|
||||
private bool DetectWinbondFintek() {
|
||||
WinbondNuvotonFintekEnter();
|
||||
private bool DetectWinbondFintek(LPCPort port) {
|
||||
port.WinbondNuvotonFintekEnter();
|
||||
|
||||
byte logicalDeviceNumber = 0;
|
||||
byte id = ReadByte(CHIP_ID_REGISTER);
|
||||
byte revision = ReadByte(CHIP_REVISION_REGISTER);
|
||||
byte id = port.ReadByte(CHIP_ID_REGISTER);
|
||||
byte revision = port.ReadByte(CHIP_REVISION_REGISTER);
|
||||
Chip chip = Chip.Unknown;
|
||||
switch (id) {
|
||||
case 0x05:
|
||||
@@ -223,13 +189,12 @@ namespace OpenHardwareMonitor.Hardware.LPC {
|
||||
break;
|
||||
} break;
|
||||
case 0xC4:
|
||||
switch (revision & 0xF0)
|
||||
{
|
||||
case 0x50:
|
||||
chip = Chip.NCT610X;
|
||||
logicalDeviceNumber = WINBOND_NUVOTON_HARDWARE_MONITOR_LDN;
|
||||
break;
|
||||
} break;
|
||||
switch (revision & 0xF0) {
|
||||
case 0x50:
|
||||
chip = Chip.NCT610X;
|
||||
logicalDeviceNumber = WINBOND_NUVOTON_HARDWARE_MONITOR_LDN;
|
||||
break;
|
||||
} break;
|
||||
case 0xC5:
|
||||
switch (revision & 0xF0) {
|
||||
case 0x60:
|
||||
@@ -247,34 +212,26 @@ namespace OpenHardwareMonitor.Hardware.LPC {
|
||||
}
|
||||
if (chip == Chip.Unknown) {
|
||||
if (id != 0 && id != 0xff) {
|
||||
WinbondNuvotonFintekExit();
|
||||
port.WinbondNuvotonFintekExit();
|
||||
|
||||
ReportUnknownChip("Winbond / Nuvoton / Fintek",
|
||||
ReportUnknownChip(port, "Winbond / Nuvoton / Fintek",
|
||||
((id << 8) | revision));
|
||||
}
|
||||
} else {
|
||||
|
||||
Select(logicalDeviceNumber);
|
||||
ushort address = ReadWord(BASE_ADDRESS_REGISTER);
|
||||
port.Select(logicalDeviceNumber);
|
||||
ushort address = port.ReadWord(BASE_ADDRESS_REGISTER);
|
||||
Thread.Sleep(1);
|
||||
ushort verify = ReadWord(BASE_ADDRESS_REGISTER);
|
||||
ushort verify = port.ReadWord(BASE_ADDRESS_REGISTER);
|
||||
|
||||
ushort vendorID = ReadWord(FINTEK_VENDOR_ID_REGISTER);
|
||||
ushort vendorID = port.ReadWord(FINTEK_VENDOR_ID_REGISTER);
|
||||
|
||||
// disable the hardware monitor i/o space lock on NCT6791D chips
|
||||
if (address == verify && chip == Chip.NCT6791D) {
|
||||
byte options = ReadByte(NUVOTON_HARDWARE_MONITOR_IO_SPACE_LOCK);
|
||||
|
||||
// if the i/o space lock is enabled
|
||||
if ((options & 0x10) > 0) {
|
||||
|
||||
// disable the i/o space lock
|
||||
WriteByte(NUVOTON_HARDWARE_MONITOR_IO_SPACE_LOCK,
|
||||
(byte)(options & ~0x10));
|
||||
}
|
||||
port.NuvotonDisableIOSpaceLock();
|
||||
}
|
||||
|
||||
WinbondNuvotonFintekExit();
|
||||
port.WinbondNuvotonFintekExit();
|
||||
|
||||
if (address != verify) {
|
||||
report.Append("Chip ID: 0x");
|
||||
@@ -320,7 +277,7 @@ namespace OpenHardwareMonitor.Hardware.LPC {
|
||||
case Chip.NCT6776F:
|
||||
case Chip.NCT6779D:
|
||||
case Chip.NCT6791D:
|
||||
superIOs.Add(new NCT677X(chip, revision, address));
|
||||
superIOs.Add(new NCT677X(chip, revision, address, port));
|
||||
break;
|
||||
case Chip.F71858:
|
||||
case Chip.F71862:
|
||||
@@ -363,27 +320,15 @@ namespace OpenHardwareMonitor.Hardware.LPC {
|
||||
private const byte IT87XX_GPIO_LDN = 0x07;
|
||||
private const byte IT87_CHIP_VERSION_REGISTER = 0x22;
|
||||
|
||||
private void IT87Enter() {
|
||||
Ring0.WriteIoPort(registerPort, 0x87);
|
||||
Ring0.WriteIoPort(registerPort, 0x01);
|
||||
Ring0.WriteIoPort(registerPort, 0x55);
|
||||
Ring0.WriteIoPort(registerPort, 0x55);
|
||||
}
|
||||
|
||||
private void IT87Exit() {
|
||||
Ring0.WriteIoPort(registerPort, CONFIGURATION_CONTROL_REGISTER);
|
||||
Ring0.WriteIoPort(valuePort, 0x02);
|
||||
}
|
||||
|
||||
private bool DetectIT87() {
|
||||
private bool DetectIT87(LPCPort port) {
|
||||
|
||||
// IT87XX can enter only on port 0x2E
|
||||
if (registerPort != 0x2E)
|
||||
if (port.RegisterPort != 0x2E)
|
||||
return false;
|
||||
|
||||
IT87Enter();
|
||||
port.IT87Enter();
|
||||
|
||||
ushort chipID = ReadWord(CHIP_ID_REGISTER);
|
||||
ushort chipID = port.ReadWord(CHIP_ID_REGISTER);
|
||||
Chip chip;
|
||||
switch (chipID) {
|
||||
case 0x8705: chip = Chip.IT8705F; break;
|
||||
@@ -400,33 +345,33 @@ namespace OpenHardwareMonitor.Hardware.LPC {
|
||||
}
|
||||
if (chip == Chip.Unknown) {
|
||||
if (chipID != 0 && chipID != 0xffff) {
|
||||
IT87Exit();
|
||||
port.IT87Exit();
|
||||
|
||||
ReportUnknownChip("ITE", chipID);
|
||||
ReportUnknownChip(port, "ITE", chipID);
|
||||
}
|
||||
} else {
|
||||
Select(IT87_ENVIRONMENT_CONTROLLER_LDN);
|
||||
ushort address = ReadWord(BASE_ADDRESS_REGISTER);
|
||||
port.Select(IT87_ENVIRONMENT_CONTROLLER_LDN);
|
||||
ushort address = port.ReadWord(BASE_ADDRESS_REGISTER);
|
||||
Thread.Sleep(1);
|
||||
ushort verify = ReadWord(BASE_ADDRESS_REGISTER);
|
||||
ushort verify = port.ReadWord(BASE_ADDRESS_REGISTER);
|
||||
|
||||
byte version = (byte)(ReadByte(IT87_CHIP_VERSION_REGISTER) & 0x0F);
|
||||
byte version = (byte)(port.ReadByte(IT87_CHIP_VERSION_REGISTER) & 0x0F);
|
||||
|
||||
ushort gpioAddress;
|
||||
ushort gpioVerify;
|
||||
if (chip == Chip.IT8705F) {
|
||||
Select(IT8705_GPIO_LDN);
|
||||
gpioAddress = ReadWord(BASE_ADDRESS_REGISTER);
|
||||
port.Select(IT8705_GPIO_LDN);
|
||||
gpioAddress = port.ReadWord(BASE_ADDRESS_REGISTER);
|
||||
Thread.Sleep(1);
|
||||
gpioVerify = ReadWord(BASE_ADDRESS_REGISTER);
|
||||
gpioVerify = port.ReadWord(BASE_ADDRESS_REGISTER);
|
||||
} else {
|
||||
Select(IT87XX_GPIO_LDN);
|
||||
gpioAddress = ReadWord(BASE_ADDRESS_REGISTER + 2);
|
||||
port.Select(IT87XX_GPIO_LDN);
|
||||
gpioAddress = port.ReadWord(BASE_ADDRESS_REGISTER + 2);
|
||||
Thread.Sleep(1);
|
||||
gpioVerify = ReadWord(BASE_ADDRESS_REGISTER + 2);
|
||||
gpioVerify = port.ReadWord(BASE_ADDRESS_REGISTER + 2);
|
||||
}
|
||||
|
||||
IT87Exit();
|
||||
|
||||
port.IT87Exit();
|
||||
|
||||
if (address != verify || address < 0x100 || (address & 0xF007) != 0) {
|
||||
report.Append("Chip ID: 0x");
|
||||
@@ -460,30 +405,22 @@ namespace OpenHardwareMonitor.Hardware.LPC {
|
||||
|
||||
#region SMSC
|
||||
|
||||
private void SMSCEnter() {
|
||||
Ring0.WriteIoPort(registerPort, 0x55);
|
||||
}
|
||||
private bool DetectSMSC(LPCPort port) {
|
||||
port.SMSCEnter();
|
||||
|
||||
private void SMSCExit() {
|
||||
Ring0.WriteIoPort(registerPort, 0xAA);
|
||||
}
|
||||
|
||||
private bool DetectSMSC() {
|
||||
SMSCEnter();
|
||||
|
||||
ushort chipID = ReadWord(CHIP_ID_REGISTER);
|
||||
ushort chipID = port.ReadWord(CHIP_ID_REGISTER);
|
||||
Chip chip;
|
||||
switch (chipID) {
|
||||
default: chip = Chip.Unknown; break;
|
||||
}
|
||||
if (chip == Chip.Unknown) {
|
||||
if (chipID != 0 && chipID != 0xffff) {
|
||||
SMSCExit();
|
||||
port.SMSCExit();
|
||||
|
||||
ReportUnknownChip("SMSC", chipID);
|
||||
ReportUnknownChip(port, "SMSC", chipID);
|
||||
}
|
||||
} else {
|
||||
SMSCExit();
|
||||
port.SMSCExit();
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -495,14 +432,13 @@ namespace OpenHardwareMonitor.Hardware.LPC {
|
||||
private void Detect() {
|
||||
|
||||
for (int i = 0; i < REGISTER_PORTS.Length; i++) {
|
||||
registerPort = REGISTER_PORTS[i];
|
||||
valuePort = VALUE_PORTS[i];
|
||||
var port = new LPCPort(REGISTER_PORTS[i], VALUE_PORTS[i]);
|
||||
|
||||
if (DetectWinbondFintek()) continue;
|
||||
if (DetectWinbondFintek(port)) continue;
|
||||
|
||||
if (DetectIT87()) continue;
|
||||
if (DetectIT87(port)) continue;
|
||||
|
||||
if (DetectSMSC()) continue;
|
||||
if (DetectSMSC(port)) continue;
|
||||
}
|
||||
}
|
||||
|
||||
|
101
Hardware/LPC/LPCPort.cs
Normal file
101
Hardware/LPC/LPCPort.cs
Normal file
@@ -0,0 +1,101 @@
|
||||
/*
|
||||
|
||||
This Source Code Form is subject to the terms of the Mozilla Public
|
||||
License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
Copyright (C) 2009-2015 Michael Möller <mmoeller@openhardwaremonitor.org>
|
||||
|
||||
*/
|
||||
|
||||
namespace OpenHardwareMonitor.Hardware.LPC {
|
||||
|
||||
internal class LPCPort {
|
||||
private readonly ushort registerPort;
|
||||
private readonly ushort valuePort;
|
||||
|
||||
public LPCPort(ushort registerPort, ushort valuePort) {
|
||||
this.registerPort = registerPort;
|
||||
this.valuePort = valuePort;
|
||||
}
|
||||
|
||||
public ushort RegisterPort {
|
||||
get {
|
||||
return registerPort;
|
||||
}
|
||||
}
|
||||
|
||||
public ushort ValuePort {
|
||||
get {
|
||||
return valuePort;
|
||||
}
|
||||
}
|
||||
|
||||
private const byte DEVCIE_SELECT_REGISTER = 0x07;
|
||||
private const byte CONFIGURATION_CONTROL_REGISTER = 0x02;
|
||||
|
||||
public byte ReadByte(byte register) {
|
||||
Ring0.WriteIoPort(registerPort, register);
|
||||
return Ring0.ReadIoPort(valuePort);
|
||||
}
|
||||
|
||||
public void WriteByte(byte register, byte value) {
|
||||
Ring0.WriteIoPort(registerPort, register);
|
||||
Ring0.WriteIoPort(valuePort, value);
|
||||
}
|
||||
|
||||
public ushort ReadWord(byte register) {
|
||||
return (ushort)((ReadByte(register) << 8) |
|
||||
ReadByte((byte)(register + 1)));
|
||||
}
|
||||
|
||||
public void Select(byte logicalDeviceNumber) {
|
||||
Ring0.WriteIoPort(registerPort, DEVCIE_SELECT_REGISTER);
|
||||
Ring0.WriteIoPort(valuePort, logicalDeviceNumber);
|
||||
}
|
||||
|
||||
public void WinbondNuvotonFintekEnter() {
|
||||
Ring0.WriteIoPort(registerPort, 0x87);
|
||||
Ring0.WriteIoPort(registerPort, 0x87);
|
||||
}
|
||||
|
||||
public void WinbondNuvotonFintekExit() {
|
||||
Ring0.WriteIoPort(registerPort, 0xAA);
|
||||
}
|
||||
|
||||
private const byte NUVOTON_HARDWARE_MONITOR_IO_SPACE_LOCK = 0x28;
|
||||
|
||||
public void NuvotonDisableIOSpaceLock() {
|
||||
byte options = ReadByte(NUVOTON_HARDWARE_MONITOR_IO_SPACE_LOCK);
|
||||
|
||||
// if the i/o space lock is enabled
|
||||
if ((options & 0x10) > 0) {
|
||||
|
||||
// disable the i/o space lock
|
||||
WriteByte(NUVOTON_HARDWARE_MONITOR_IO_SPACE_LOCK,
|
||||
(byte)(options & ~0x10));
|
||||
}
|
||||
}
|
||||
|
||||
public void IT87Enter() {
|
||||
Ring0.WriteIoPort(registerPort, 0x87);
|
||||
Ring0.WriteIoPort(registerPort, 0x01);
|
||||
Ring0.WriteIoPort(registerPort, 0x55);
|
||||
Ring0.WriteIoPort(registerPort, 0x55);
|
||||
}
|
||||
|
||||
public void IT87Exit() {
|
||||
Ring0.WriteIoPort(registerPort, CONFIGURATION_CONTROL_REGISTER);
|
||||
Ring0.WriteIoPort(valuePort, 0x02);
|
||||
}
|
||||
|
||||
public void SMSCEnter() {
|
||||
Ring0.WriteIoPort(registerPort, 0x55);
|
||||
}
|
||||
|
||||
public void SMSCExit() {
|
||||
Ring0.WriteIoPort(registerPort, 0xAA);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@@ -20,6 +20,7 @@ namespace OpenHardwareMonitor.Hardware.LPC {
|
||||
private readonly byte revision;
|
||||
|
||||
private readonly Chip chip;
|
||||
private readonly LPCPort lpcPort;
|
||||
|
||||
private readonly bool isNuvotonVendor;
|
||||
|
||||
@@ -183,10 +184,12 @@ namespace OpenHardwareMonitor.Hardware.LPC {
|
||||
BYTE_TEMP = 22
|
||||
}
|
||||
|
||||
public NCT677X(Chip chip, byte revision, ushort port) {
|
||||
public NCT677X(Chip chip, byte revision, ushort port, LPCPort lpcPort)
|
||||
{
|
||||
this.chip = chip;
|
||||
this.revision = revision;
|
||||
this.port = port;
|
||||
this.lpcPort = lpcPort;
|
||||
|
||||
if (chip == LPC.Chip.NCT610X) {
|
||||
VENDOR_ID_HIGH_REGISTER = 0x80FE;
|
||||
@@ -410,6 +413,19 @@ namespace OpenHardwareMonitor.Hardware.LPC {
|
||||
public float?[] Fans { get { return fans; } }
|
||||
public float?[] Controls { get { return controls; } }
|
||||
|
||||
private void DisableIOSpaceLock() {
|
||||
if (chip != Chip.NCT6791D)
|
||||
return;
|
||||
|
||||
// the lock is disabled already if the vendor ID can be read
|
||||
if (IsNuvotonVendor())
|
||||
return;
|
||||
|
||||
lpcPort.WinbondNuvotonFintekEnter();
|
||||
lpcPort.NuvotonDisableIOSpaceLock();
|
||||
lpcPort.WinbondNuvotonFintekExit();
|
||||
}
|
||||
|
||||
public void Update() {
|
||||
if (!isNuvotonVendor)
|
||||
return;
|
||||
@@ -417,6 +433,8 @@ namespace OpenHardwareMonitor.Hardware.LPC {
|
||||
if (!Ring0.WaitIsaBusMutex(10))
|
||||
return;
|
||||
|
||||
DisableIOSpaceLock();
|
||||
|
||||
for (int i = 0; i < voltages.Length; i++) {
|
||||
float value = 0.008f * ReadByte(voltageRegisters[i]);
|
||||
bool valid = value > 0;
|
||||
|
@@ -89,6 +89,7 @@
|
||||
<Compile Include="Hardware\CPU\CPUID.cs" />
|
||||
<Compile Include="Hardware\CPU\CPULoad.cs" />
|
||||
<Compile Include="Hardware\CPU\IntelCPU.cs" />
|
||||
<Compile Include="Hardware\LPC\LPCPort.cs" />
|
||||
<Compile Include="Hardware\LPC\NCT677X.cs" />
|
||||
<Compile Include="Hardware\Mainboard\GigabyteTAMG.cs" />
|
||||
<Compile Include="Hardware\Mainboard\Identification.cs" />
|
||||
|
Reference in New Issue
Block a user