Adding SoundGraphDisplay and SensorFrontView classes.
They were respectively based on SystemTray and SensorNotifyIcon.
SoundGraphDisplay is now able to load iMONDisplay.dll providing it lives on your PATH.
Adding option to sensor context menu for adding it into FrontView.
3 This Source Code Form is subject to the terms of the Mozilla Public
4 License, v. 2.0. If a copy of the MPL was not distributed with this
5 file, You can obtain one at http://mozilla.org/MPL/2.0/.
7 Copyright (C) 2009-2013 Michael Möller <mmoeller@openhardwaremonitor.org>
12 using System.Collections.Generic;
13 using System.Globalization;
15 using System.Threading;
17 namespace OpenHardwareMonitor.Hardware.LPC {
18 internal class LPCIO {
20 private readonly List<ISuperIO> superIOs = new List<ISuperIO>();
21 private readonly StringBuilder report = new StringBuilder();
24 private readonly ushort[] REGISTER_PORTS = new ushort[] { 0x2E, 0x4E };
25 private readonly ushort[] VALUE_PORTS = new ushort[] { 0x2F, 0x4F };
27 private ushort registerPort;
28 private ushort valuePort;
31 private const byte CONFIGURATION_CONTROL_REGISTER = 0x02;
32 private const byte DEVCIE_SELECT_REGISTER = 0x07;
33 private const byte CHIP_ID_REGISTER = 0x20;
34 private const byte CHIP_REVISION_REGISTER = 0x21;
35 private const byte BASE_ADDRESS_REGISTER = 0x60;
37 private byte ReadByte(byte register) {
38 Ring0.WriteIoPort(registerPort, register);
39 return Ring0.ReadIoPort(valuePort);
42 private void WriteByte(byte register, byte value) {
43 Ring0.WriteIoPort(registerPort, register);
44 Ring0.WriteIoPort(valuePort, value);
47 private ushort ReadWord(byte register) {
48 return (ushort)((ReadByte(register) << 8) |
49 ReadByte((byte)(register + 1)));
52 private void Select(byte logicalDeviceNumber) {
53 Ring0.WriteIoPort(registerPort, DEVCIE_SELECT_REGISTER);
54 Ring0.WriteIoPort(valuePort, logicalDeviceNumber);
57 private void ReportUnknownChip(string type, int chip) {
58 report.Append("Chip ID: Unknown ");
60 report.Append(" with ID 0x");
61 report.Append(chip.ToString("X", CultureInfo.InvariantCulture));
62 report.Append(" at 0x");
63 report.Append(registerPort.ToString("X", CultureInfo.InvariantCulture));
65 report.AppendLine(valuePort.ToString("X", CultureInfo.InvariantCulture));
69 #region Winbond, Nuvoton, Fintek
71 private const byte FINTEK_VENDOR_ID_REGISTER = 0x23;
72 private const ushort FINTEK_VENDOR_ID = 0x1934;
74 private const byte WINBOND_NUVOTON_HARDWARE_MONITOR_LDN = 0x0B;
76 private const byte F71858_HARDWARE_MONITOR_LDN = 0x02;
77 private const byte FINTEK_HARDWARE_MONITOR_LDN = 0x04;
79 private const byte NUVOTON_HARDWARE_MONITOR_IO_SPACE_LOCK = 0x28;
81 private void WinbondNuvotonFintekEnter() {
82 Ring0.WriteIoPort(registerPort, 0x87);
83 Ring0.WriteIoPort(registerPort, 0x87);
86 private void WinbondNuvotonFintekExit() {
87 Ring0.WriteIoPort(registerPort, 0xAA);
90 private bool DetectWinbondFintek() {
91 WinbondNuvotonFintekEnter();
93 byte logicalDeviceNumber = 0;
94 byte id = ReadByte(CHIP_ID_REGISTER);
95 byte revision = ReadByte(CHIP_REVISION_REGISTER);
96 Chip chip = Chip.Unknown;
102 logicalDeviceNumber = F71858_HARDWARE_MONITOR_LDN;
106 logicalDeviceNumber = FINTEK_HARDWARE_MONITOR_LDN;
113 logicalDeviceNumber = FINTEK_HARDWARE_MONITOR_LDN;
120 logicalDeviceNumber = FINTEK_HARDWARE_MONITOR_LDN;
127 logicalDeviceNumber = FINTEK_HARDWARE_MONITOR_LDN;
134 logicalDeviceNumber = FINTEK_HARDWARE_MONITOR_LDN;
137 chip = Chip.F71889ED;
138 logicalDeviceNumber = FINTEK_HARDWARE_MONITOR_LDN;
144 chip = Chip.F71889AD;
145 logicalDeviceNumber = FINTEK_HARDWARE_MONITOR_LDN;
149 logicalDeviceNumber = FINTEK_HARDWARE_MONITOR_LDN;
157 chip = Chip.W83627HF;
158 logicalDeviceNumber = WINBOND_NUVOTON_HARDWARE_MONITOR_LDN;
162 switch (revision & 0xF0) {
164 chip = Chip.W83627THF;
165 logicalDeviceNumber = WINBOND_NUVOTON_HARDWARE_MONITOR_LDN;
171 chip = Chip.W83687THF;
172 logicalDeviceNumber = WINBOND_NUVOTON_HARDWARE_MONITOR_LDN;
176 switch (revision & 0xF0) {
179 chip = Chip.W83627EHF;
180 logicalDeviceNumber = WINBOND_NUVOTON_HARDWARE_MONITOR_LDN;
184 switch (revision & 0xF0) {
186 chip = Chip.W83627DHG;
187 logicalDeviceNumber = WINBOND_NUVOTON_HARDWARE_MONITOR_LDN;
191 switch (revision & 0xF0) {
193 chip = Chip.W83667HG;
194 logicalDeviceNumber = WINBOND_NUVOTON_HARDWARE_MONITOR_LDN;
198 switch (revision & 0xF0) {
200 chip = Chip.W83627DHGP;
201 logicalDeviceNumber = WINBOND_NUVOTON_HARDWARE_MONITOR_LDN;
205 switch (revision & 0xF0) {
207 chip = Chip.W83667HGB;
208 logicalDeviceNumber = WINBOND_NUVOTON_HARDWARE_MONITOR_LDN;
212 switch (revision & 0xF0) {
214 chip = Chip.NCT6771F;
215 logicalDeviceNumber = WINBOND_NUVOTON_HARDWARE_MONITOR_LDN;
219 switch (revision & 0xF0) {
221 chip = Chip.NCT6776F;
222 logicalDeviceNumber = WINBOND_NUVOTON_HARDWARE_MONITOR_LDN;
226 switch (revision & 0xF0) {
228 chip = Chip.NCT6779D;
229 logicalDeviceNumber = WINBOND_NUVOTON_HARDWARE_MONITOR_LDN;
235 chip = Chip.NCT6791D;
236 logicalDeviceNumber = WINBOND_NUVOTON_HARDWARE_MONITOR_LDN;
240 if (chip == Chip.Unknown) {
241 if (id != 0 && id != 0xff) {
242 WinbondNuvotonFintekExit();
244 ReportUnknownChip("Winbond / Nuvoton / Fintek",
245 ((id << 8) | revision));
249 Select(logicalDeviceNumber);
250 ushort address = ReadWord(BASE_ADDRESS_REGISTER);
252 ushort verify = ReadWord(BASE_ADDRESS_REGISTER);
254 ushort vendorID = ReadWord(FINTEK_VENDOR_ID_REGISTER);
256 // disable the hardware monitor i/o space lock on NCT6791D chips
257 if (address == verify && chip == Chip.NCT6791D) {
258 byte options = ReadByte(NUVOTON_HARDWARE_MONITOR_IO_SPACE_LOCK);
260 // if the i/o space lock is enabled
261 if ((options & 0x10) > 0) {
263 // disable the i/o space lock
264 WriteByte(NUVOTON_HARDWARE_MONITOR_IO_SPACE_LOCK,
265 (byte)(options & ~0x10));
269 WinbondNuvotonFintekExit();
271 if (address != verify) {
272 report.Append("Chip ID: 0x");
273 report.AppendLine(chip.ToString("X"));
274 report.Append("Chip revision: 0x");
275 report.AppendLine(revision.ToString("X",
276 CultureInfo.InvariantCulture));
277 report.AppendLine("Error: Address verification failed");
282 // some Fintek chips have address register offset 0x05 added already
283 if ((address & 0x07) == 0x05)
286 if (address < 0x100 || (address & 0xF007) != 0) {
287 report.Append("Chip ID: 0x");
288 report.AppendLine(chip.ToString("X"));
289 report.Append("Chip revision: 0x");
290 report.AppendLine(revision.ToString("X",
291 CultureInfo.InvariantCulture));
292 report.Append("Error: Invalid address 0x");
293 report.AppendLine(address.ToString("X",
294 CultureInfo.InvariantCulture));
301 case Chip.W83627DHGP:
308 superIOs.Add(new W836XX(chip, revision, address));
314 superIOs.Add(new NCT677X(chip, revision, address));
325 if (vendorID != FINTEK_VENDOR_ID) {
326 report.Append("Chip ID: 0x");
327 report.AppendLine(chip.ToString("X"));
328 report.Append("Chip revision: 0x");
329 report.AppendLine(revision.ToString("X",
330 CultureInfo.InvariantCulture));
331 report.Append("Error: Invalid vendor ID 0x");
332 report.AppendLine(vendorID.ToString("X",
333 CultureInfo.InvariantCulture));
337 superIOs.Add(new F718XX(chip, address));
352 private const byte IT87_ENVIRONMENT_CONTROLLER_LDN = 0x04;
353 private const byte IT8705_GPIO_LDN = 0x05;
354 private const byte IT87XX_GPIO_LDN = 0x07;
355 private const byte IT87_CHIP_VERSION_REGISTER = 0x22;
357 private void IT87Enter() {
358 Ring0.WriteIoPort(registerPort, 0x87);
359 Ring0.WriteIoPort(registerPort, 0x01);
360 Ring0.WriteIoPort(registerPort, 0x55);
361 Ring0.WriteIoPort(registerPort, 0x55);
364 private void IT87Exit() {
365 Ring0.WriteIoPort(registerPort, CONFIGURATION_CONTROL_REGISTER);
366 Ring0.WriteIoPort(valuePort, 0x02);
369 private bool DetectIT87() {
371 // IT87XX can enter only on port 0x2E
372 if (registerPort != 0x2E)
377 ushort chipID = ReadWord(CHIP_ID_REGISTER);
380 case 0x8705: chip = Chip.IT8705F; break;
381 case 0x8712: chip = Chip.IT8712F; break;
382 case 0x8716: chip = Chip.IT8716F; break;
383 case 0x8718: chip = Chip.IT8718F; break;
384 case 0x8720: chip = Chip.IT8720F; break;
385 case 0x8721: chip = Chip.IT8721F; break;
386 case 0x8726: chip = Chip.IT8726F; break;
387 case 0x8728: chip = Chip.IT8728F; break;
388 case 0x8771: chip = Chip.IT8771E; break;
389 case 0x8772: chip = Chip.IT8772E; break;
390 default: chip = Chip.Unknown; break;
392 if (chip == Chip.Unknown) {
393 if (chipID != 0 && chipID != 0xffff) {
396 ReportUnknownChip("ITE", chipID);
399 Select(IT87_ENVIRONMENT_CONTROLLER_LDN);
400 ushort address = ReadWord(BASE_ADDRESS_REGISTER);
402 ushort verify = ReadWord(BASE_ADDRESS_REGISTER);
404 byte version = (byte)(ReadByte(IT87_CHIP_VERSION_REGISTER) & 0x0F);
408 if (chip == Chip.IT8705F) {
409 Select(IT8705_GPIO_LDN);
410 gpioAddress = ReadWord(BASE_ADDRESS_REGISTER);
412 gpioVerify = ReadWord(BASE_ADDRESS_REGISTER);
414 Select(IT87XX_GPIO_LDN);
415 gpioAddress = ReadWord(BASE_ADDRESS_REGISTER + 2);
417 gpioVerify = ReadWord(BASE_ADDRESS_REGISTER + 2);
422 if (address != verify || address < 0x100 || (address & 0xF007) != 0) {
423 report.Append("Chip ID: 0x");
424 report.AppendLine(chip.ToString("X"));
425 report.Append("Error: Invalid address 0x");
426 report.AppendLine(address.ToString("X",
427 CultureInfo.InvariantCulture));
432 if (gpioAddress != gpioVerify || gpioAddress < 0x100 ||
433 (gpioAddress & 0xF007) != 0) {
434 report.Append("Chip ID: 0x");
435 report.AppendLine(chip.ToString("X"));
436 report.Append("Error: Invalid GPIO address 0x");
437 report.AppendLine(gpioAddress.ToString("X",
438 CultureInfo.InvariantCulture));
443 superIOs.Add(new IT87XX(chip, address, gpioAddress, version));
454 private void SMSCEnter() {
455 Ring0.WriteIoPort(registerPort, 0x55);
458 private void SMSCExit() {
459 Ring0.WriteIoPort(registerPort, 0xAA);
462 private bool DetectSMSC() {
465 ushort chipID = ReadWord(CHIP_ID_REGISTER);
468 default: chip = Chip.Unknown; break;
470 if (chip == Chip.Unknown) {
471 if (chipID != 0 && chipID != 0xffff) {
474 ReportUnknownChip("SMSC", chipID);
486 private void Detect() {
488 for (int i = 0; i < REGISTER_PORTS.Length; i++) {
489 registerPort = REGISTER_PORTS[i];
490 valuePort = VALUE_PORTS[i];
492 if (DetectWinbondFintek()) continue;
494 if (DetectIT87()) continue;
496 if (DetectSMSC()) continue;
504 if (!Ring0.WaitIsaBusMutex(100))
509 Ring0.ReleaseIsaBusMutex();
512 public ISuperIO[] SuperIO {
514 return superIOs.ToArray();
518 public string GetReport() {
519 if (report.Length > 0) {
520 return "LPCIO" + Environment.NewLine + Environment.NewLine + report;