Hardware/LPC/LPCIO.cs
author StephaneLenclud
Sun, 03 Feb 2013 18:01:50 +0100
branchMiniDisplay
changeset 433 090259cfd699
parent 413 362c5e77197d
child 454 f84878f52cd9
permissions -rw-r--r--
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.
moel@110
     1
/*
moel@110
     2
 
moel@344
     3
  This Source Code Form is subject to the terms of the Mozilla Public
moel@344
     4
  License, v. 2.0. If a copy of the MPL was not distributed with this
moel@344
     5
  file, You can obtain one at http://mozilla.org/MPL/2.0/.
moel@110
     6
 
moel@408
     7
  Copyright (C) 2009-2013 Michael Möller <mmoeller@openhardwaremonitor.org>
moel@344
     8
	
moel@110
     9
*/
moel@110
    10
moel@110
    11
using System;
moel@110
    12
using System.Collections.Generic;
moel@166
    13
using System.Globalization;
moel@110
    14
using System.Text;
moel@110
    15
using System.Threading;
moel@110
    16
moel@110
    17
namespace OpenHardwareMonitor.Hardware.LPC {
moel@165
    18
  internal class LPCIO {
moel@110
    19
moel@195
    20
    private readonly List<ISuperIO> superIOs = new List<ISuperIO>();
moel@195
    21
    private readonly StringBuilder report = new StringBuilder();
moel@110
    22
moel@110
    23
    // I/O Ports
moel@195
    24
    private readonly ushort[] REGISTER_PORTS = new ushort[] { 0x2E, 0x4E };
moel@195
    25
    private readonly ushort[] VALUE_PORTS = new ushort[] { 0x2F, 0x4F };
moel@110
    26
moel@110
    27
    private ushort registerPort;
moel@110
    28
    private ushort valuePort;
moel@110
    29
moel@110
    30
    // Registers
moel@110
    31
    private const byte CONFIGURATION_CONTROL_REGISTER = 0x02;
moel@110
    32
    private const byte DEVCIE_SELECT_REGISTER = 0x07;
moel@110
    33
    private const byte CHIP_ID_REGISTER = 0x20;
moel@110
    34
    private const byte CHIP_REVISION_REGISTER = 0x21;
moel@110
    35
    private const byte BASE_ADDRESS_REGISTER = 0x60;
moel@110
    36
moel@110
    37
    private byte ReadByte(byte register) {
moel@236
    38
      Ring0.WriteIoPort(registerPort, register);
moel@236
    39
      return Ring0.ReadIoPort(valuePort);
moel@228
    40
    }
moel@110
    41
moel@423
    42
    private void WriteByte(byte register, byte value) {
moel@423
    43
      Ring0.WriteIoPort(registerPort, register);
moel@423
    44
      Ring0.WriteIoPort(valuePort, value);
moel@423
    45
    }
moel@423
    46
moel@110
    47
    private ushort ReadWord(byte register) {
moel@228
    48
      return (ushort)((ReadByte(register) << 8) |
moel@110
    49
        ReadByte((byte)(register + 1)));
moel@110
    50
    }
moel@110
    51
moel@110
    52
    private void Select(byte logicalDeviceNumber) {
moel@236
    53
      Ring0.WriteIoPort(registerPort, DEVCIE_SELECT_REGISTER);
moel@236
    54
      Ring0.WriteIoPort(valuePort, logicalDeviceNumber);
moel@110
    55
    }
moel@110
    56
moel@169
    57
    private void ReportUnknownChip(string type, int chip) {
moel@169
    58
      report.Append("Chip ID: Unknown ");
moel@169
    59
      report.Append(type);
moel@169
    60
      report.Append(" with ID 0x");
moel@169
    61
      report.Append(chip.ToString("X", CultureInfo.InvariantCulture));
moel@169
    62
      report.Append(" at 0x");
moel@169
    63
      report.Append(registerPort.ToString("X", CultureInfo.InvariantCulture));
moel@169
    64
      report.Append("/0x");
moel@169
    65
      report.AppendLine(valuePort.ToString("X", CultureInfo.InvariantCulture));
moel@169
    66
      report.AppendLine();
moel@110
    67
    }
moel@110
    68
moel@245
    69
    #region Winbond, Nuvoton, Fintek
moel@110
    70
moel@110
    71
    private const byte FINTEK_VENDOR_ID_REGISTER = 0x23;
moel@110
    72
    private const ushort FINTEK_VENDOR_ID = 0x1934;
moel@110
    73
moel@245
    74
    private const byte WINBOND_NUVOTON_HARDWARE_MONITOR_LDN = 0x0B;
moel@110
    75
moel@110
    76
    private const byte F71858_HARDWARE_MONITOR_LDN = 0x02;
moel@110
    77
    private const byte FINTEK_HARDWARE_MONITOR_LDN = 0x04;
moel@110
    78
moel@423
    79
    private const byte NUVOTON_HARDWARE_MONITOR_IO_SPACE_LOCK = 0x28;
moel@423
    80
moel@245
    81
    private void WinbondNuvotonFintekEnter() {
moel@236
    82
      Ring0.WriteIoPort(registerPort, 0x87);
moel@236
    83
      Ring0.WriteIoPort(registerPort, 0x87);
moel@110
    84
    }
moel@110
    85
moel@245
    86
    private void WinbondNuvotonFintekExit() {
moel@236
    87
      Ring0.WriteIoPort(registerPort, 0xAA);
moel@110
    88
    }
moel@110
    89
moel@167
    90
    private bool DetectWinbondFintek() {
moel@245
    91
      WinbondNuvotonFintekEnter();
moel@167
    92
moel@195
    93
      byte logicalDeviceNumber = 0;
moel@167
    94
      byte id = ReadByte(CHIP_ID_REGISTER);
moel@167
    95
      byte revision = ReadByte(CHIP_REVISION_REGISTER);
moel@167
    96
      Chip chip = Chip.Unknown;
moel@167
    97
      switch (id) {
moel@167
    98
        case 0x05:
moel@167
    99
          switch (revision) {
moel@167
   100
            case 0x07:
moel@167
   101
              chip = Chip.F71858;
moel@167
   102
              logicalDeviceNumber = F71858_HARDWARE_MONITOR_LDN;
moel@167
   103
              break;
moel@167
   104
            case 0x41:
moel@167
   105
              chip = Chip.F71882;
moel@167
   106
              logicalDeviceNumber = FINTEK_HARDWARE_MONITOR_LDN;
moel@167
   107
              break;
moel@167
   108
          } break;
moel@167
   109
        case 0x06:
moel@167
   110
          switch (revision) {
moel@167
   111
            case 0x01:
moel@167
   112
              chip = Chip.F71862;
moel@167
   113
              logicalDeviceNumber = FINTEK_HARDWARE_MONITOR_LDN;
moel@167
   114
              break;
moel@167
   115
          } break;
moel@167
   116
        case 0x07:
moel@167
   117
          switch (revision) {
moel@167
   118
            case 0x23:
moel@167
   119
              chip = Chip.F71889F;
moel@167
   120
              logicalDeviceNumber = FINTEK_HARDWARE_MONITOR_LDN;
moel@167
   121
              break;
moel@167
   122
          } break;
moel@167
   123
        case 0x08:
moel@167
   124
          switch (revision) {
moel@167
   125
            case 0x14:
moel@167
   126
              chip = Chip.F71869;
moel@167
   127
              logicalDeviceNumber = FINTEK_HARDWARE_MONITOR_LDN;
moel@167
   128
              break;
moel@167
   129
          } break;
moel@167
   130
        case 0x09:
moel@167
   131
          switch (revision) {
moel@352
   132
            case 0x01:
moel@352
   133
              chip = Chip.F71808E;
moel@352
   134
              logicalDeviceNumber = FINTEK_HARDWARE_MONITOR_LDN;
moel@352
   135
              break;
moel@167
   136
            case 0x09:
moel@167
   137
              chip = Chip.F71889ED;
moel@167
   138
              logicalDeviceNumber = FINTEK_HARDWARE_MONITOR_LDN;
moel@167
   139
              break;
moel@167
   140
          } break;
moel@296
   141
        case 0x10:
moel@296
   142
          switch (revision) {
moel@296
   143
            case 0x05:
moel@296
   144
              chip = Chip.F71889AD;
moel@296
   145
              logicalDeviceNumber = FINTEK_HARDWARE_MONITOR_LDN;
moel@296
   146
              break;
moel@408
   147
            case 0x07:
moel@408
   148
              chip = Chip.F71869A;
moel@408
   149
              logicalDeviceNumber = FINTEK_HARDWARE_MONITOR_LDN;
moel@408
   150
              break;
moel@296
   151
          } break;
moel@167
   152
        case 0x52:
moel@167
   153
          switch (revision) {
moel@167
   154
            case 0x17:
moel@167
   155
            case 0x3A:
moel@167
   156
            case 0x41:
moel@167
   157
              chip = Chip.W83627HF;
moel@245
   158
              logicalDeviceNumber = WINBOND_NUVOTON_HARDWARE_MONITOR_LDN;
moel@167
   159
              break;
moel@167
   160
          } break;
moel@167
   161
        case 0x82:
moel@167
   162
          switch (revision & 0xF0) {
moel@167
   163
            case 0x80:
moel@167
   164
              chip = Chip.W83627THF;
moel@245
   165
              logicalDeviceNumber = WINBOND_NUVOTON_HARDWARE_MONITOR_LDN;
moel@167
   166
              break;
moel@167
   167
          } break;
moel@167
   168
        case 0x85:
moel@167
   169
          switch (revision) {
moel@167
   170
            case 0x41:
moel@167
   171
              chip = Chip.W83687THF;
moel@245
   172
              logicalDeviceNumber = WINBOND_NUVOTON_HARDWARE_MONITOR_LDN;
moel@167
   173
              break;
moel@167
   174
          } break;
moel@167
   175
        case 0x88:
moel@167
   176
          switch (revision & 0xF0) {
moel@167
   177
            case 0x50:
moel@167
   178
            case 0x60:
moel@167
   179
              chip = Chip.W83627EHF;
moel@245
   180
              logicalDeviceNumber = WINBOND_NUVOTON_HARDWARE_MONITOR_LDN;
moel@167
   181
              break;
moel@167
   182
          } break;
moel@167
   183
        case 0xA0:
moel@167
   184
          switch (revision & 0xF0) {
moel@167
   185
            case 0x20:
moel@167
   186
              chip = Chip.W83627DHG;
moel@245
   187
              logicalDeviceNumber = WINBOND_NUVOTON_HARDWARE_MONITOR_LDN;
moel@167
   188
              break;
moel@167
   189
          } break;
moel@167
   190
        case 0xA5:
moel@167
   191
          switch (revision & 0xF0) {
moel@167
   192
            case 0x10:
moel@167
   193
              chip = Chip.W83667HG;
moel@245
   194
              logicalDeviceNumber = WINBOND_NUVOTON_HARDWARE_MONITOR_LDN;
moel@167
   195
              break;
moel@167
   196
          } break;
moel@167
   197
        case 0xB0:
moel@167
   198
          switch (revision & 0xF0) {
moel@167
   199
            case 0x70:
moel@167
   200
              chip = Chip.W83627DHGP;
moel@245
   201
              logicalDeviceNumber = WINBOND_NUVOTON_HARDWARE_MONITOR_LDN;
moel@167
   202
              break;
moel@167
   203
          } break;
moel@167
   204
        case 0xB3:
moel@167
   205
          switch (revision & 0xF0) {
moel@167
   206
            case 0x50:
moel@167
   207
              chip = Chip.W83667HGB;
moel@245
   208
              logicalDeviceNumber = WINBOND_NUVOTON_HARDWARE_MONITOR_LDN;
moel@245
   209
              break;
moel@245
   210
          } break;
moel@245
   211
        case 0xB4:
moel@245
   212
          switch (revision & 0xF0) {
moel@245
   213
            case 0x70:
moel@245
   214
              chip = Chip.NCT6771F;
moel@245
   215
              logicalDeviceNumber = WINBOND_NUVOTON_HARDWARE_MONITOR_LDN;
moel@167
   216
              break;
moel@167
   217
          } break;
moel@265
   218
        case 0xC3:
moel@265
   219
          switch (revision & 0xF0) {
moel@265
   220
            case 0x30:
moel@265
   221
              chip = Chip.NCT6776F;
moel@265
   222
              logicalDeviceNumber = WINBOND_NUVOTON_HARDWARE_MONITOR_LDN;
moel@265
   223
              break;
moel@265
   224
          } break;
moel@355
   225
        case 0xC5:
moel@355
   226
          switch (revision & 0xF0) {
moel@355
   227
            case 0x60:
moel@355
   228
              chip = Chip.NCT6779D;
moel@355
   229
              logicalDeviceNumber = WINBOND_NUVOTON_HARDWARE_MONITOR_LDN;
moel@355
   230
              break;
moel@355
   231
          } break;
moel@413
   232
        case 0xC8:
moel@413
   233
          switch (revision) {
moel@413
   234
            case 0x03:
moel@413
   235
              chip = Chip.NCT6791D;
moel@413
   236
              logicalDeviceNumber = WINBOND_NUVOTON_HARDWARE_MONITOR_LDN;
moel@413
   237
              break;
moel@413
   238
          } break;
moel@167
   239
      }
moel@167
   240
      if (chip == Chip.Unknown) {
moel@167
   241
        if (id != 0 && id != 0xff) {
moel@245
   242
          WinbondNuvotonFintekExit();
moel@167
   243
moel@245
   244
          ReportUnknownChip("Winbond / Nuvoton / Fintek", 
moel@245
   245
            ((id << 8) | revision));
moel@167
   246
        }
moel@167
   247
      } else {
moel@167
   248
moel@167
   249
        Select(logicalDeviceNumber);
moel@167
   250
        ushort address = ReadWord(BASE_ADDRESS_REGISTER);
moel@167
   251
        Thread.Sleep(1);
moel@167
   252
        ushort verify = ReadWord(BASE_ADDRESS_REGISTER);
moel@167
   253
moel@167
   254
        ushort vendorID = ReadWord(FINTEK_VENDOR_ID_REGISTER);
moel@167
   255
moel@423
   256
        // disable the hardware monitor i/o space lock on NCT6791D chips
moel@423
   257
        if (address == verify && chip == Chip.NCT6791D) {
moel@423
   258
          byte options = ReadByte(NUVOTON_HARDWARE_MONITOR_IO_SPACE_LOCK);
moel@423
   259
moel@423
   260
          // if the i/o space lock is enabled
moel@423
   261
          if ((options & 0x10) > 0) {
moel@423
   262
moel@423
   263
            // disable the i/o space lock
moel@423
   264
            WriteByte(NUVOTON_HARDWARE_MONITOR_IO_SPACE_LOCK,
moel@423
   265
              (byte)(options & ~0x10));
moel@423
   266
          }
moel@423
   267
        }
moel@423
   268
moel@245
   269
        WinbondNuvotonFintekExit();
moel@167
   270
moel@167
   271
        if (address != verify) {
moel@167
   272
          report.Append("Chip ID: 0x");
moel@167
   273
          report.AppendLine(chip.ToString("X"));
moel@167
   274
          report.Append("Chip revision: 0x");
moel@228
   275
          report.AppendLine(revision.ToString("X",
moel@167
   276
            CultureInfo.InvariantCulture));
moel@167
   277
          report.AppendLine("Error: Address verification failed");
moel@167
   278
          report.AppendLine();
moel@167
   279
          return false;
moel@167
   280
        }
moel@167
   281
moel@167
   282
        // some Fintek chips have address register offset 0x05 added already
moel@167
   283
        if ((address & 0x07) == 0x05)
moel@167
   284
          address &= 0xFFF8;
moel@167
   285
moel@167
   286
        if (address < 0x100 || (address & 0xF007) != 0) {
moel@167
   287
          report.Append("Chip ID: 0x");
moel@167
   288
          report.AppendLine(chip.ToString("X"));
moel@167
   289
          report.Append("Chip revision: 0x");
moel@228
   290
          report.AppendLine(revision.ToString("X",
moel@167
   291
            CultureInfo.InvariantCulture));
moel@167
   292
          report.Append("Error: Invalid address 0x");
moel@228
   293
          report.AppendLine(address.ToString("X",
moel@167
   294
            CultureInfo.InvariantCulture));
moel@167
   295
          report.AppendLine();
moel@167
   296
          return false;
moel@167
   297
        }
moel@167
   298
moel@167
   299
        switch (chip) {
moel@167
   300
          case Chip.W83627DHG:
moel@167
   301
          case Chip.W83627DHGP:
moel@167
   302
          case Chip.W83627EHF:
moel@167
   303
          case Chip.W83627HF:
moel@167
   304
          case Chip.W83627THF:
moel@167
   305
          case Chip.W83667HG:
moel@167
   306
          case Chip.W83667HGB:
moel@167
   307
          case Chip.W83687THF:
moel@167
   308
            superIOs.Add(new W836XX(chip, revision, address));
moel@167
   309
            break;
moel@245
   310
          case Chip.NCT6771F:
moel@265
   311
          case Chip.NCT6776F:
moel@355
   312
          case Chip.NCT6779D:
moel@413
   313
          case Chip.NCT6791D:
moel@245
   314
            superIOs.Add(new NCT677X(chip, revision, address));
moel@245
   315
            break;
moel@167
   316
          case Chip.F71858:
moel@167
   317
          case Chip.F71862:
moel@167
   318
          case Chip.F71869:
moel@408
   319
          case Chip.F71869A:
moel@167
   320
          case Chip.F71882:
moel@296
   321
          case Chip.F71889AD:
moel@167
   322
          case Chip.F71889ED:
moel@167
   323
          case Chip.F71889F:
moel@352
   324
          case Chip.F71808E:
moel@167
   325
            if (vendorID != FINTEK_VENDOR_ID) {
moel@167
   326
              report.Append("Chip ID: 0x");
moel@167
   327
              report.AppendLine(chip.ToString("X"));
moel@167
   328
              report.Append("Chip revision: 0x");
moel@228
   329
              report.AppendLine(revision.ToString("X",
moel@167
   330
                CultureInfo.InvariantCulture));
moel@167
   331
              report.Append("Error: Invalid vendor ID 0x");
moel@228
   332
              report.AppendLine(vendorID.ToString("X",
moel@167
   333
                CultureInfo.InvariantCulture));
moel@167
   334
              report.AppendLine();
moel@167
   335
              return false;
moel@167
   336
            }
moel@167
   337
            superIOs.Add(new F718XX(chip, address));
moel@167
   338
            break;
moel@167
   339
          default: break;
moel@167
   340
        }
moel@167
   341
moel@167
   342
        return true;
moel@167
   343
      }
moel@167
   344
moel@167
   345
      return false;
moel@167
   346
    }
moel@167
   347
moel@169
   348
    #endregion
moel@169
   349
moel@169
   350
    #region ITE
moel@169
   351
moel@169
   352
    private const byte IT87_ENVIRONMENT_CONTROLLER_LDN = 0x04;
moel@353
   353
    private const byte IT8705_GPIO_LDN = 0x05;
moel@353
   354
    private const byte IT87XX_GPIO_LDN = 0x07;
moel@169
   355
    private const byte IT87_CHIP_VERSION_REGISTER = 0x22;
moel@169
   356
moel@169
   357
    private void IT87Enter() {
moel@236
   358
      Ring0.WriteIoPort(registerPort, 0x87);
moel@236
   359
      Ring0.WriteIoPort(registerPort, 0x01);
moel@236
   360
      Ring0.WriteIoPort(registerPort, 0x55);
moel@236
   361
      Ring0.WriteIoPort(registerPort, 0x55);
moel@169
   362
    }
moel@169
   363
moel@169
   364
    private void IT87Exit() {
moel@236
   365
      Ring0.WriteIoPort(registerPort, CONFIGURATION_CONTROL_REGISTER);
moel@236
   366
      Ring0.WriteIoPort(valuePort, 0x02);
moel@169
   367
    }
moel@169
   368
moel@167
   369
    private bool DetectIT87() {
moel@169
   370
moel@169
   371
      // IT87XX can enter only on port 0x2E
moel@169
   372
      if (registerPort != 0x2E)
moel@169
   373
        return false;
moel@169
   374
moel@167
   375
      IT87Enter();
moel@167
   376
moel@167
   377
      ushort chipID = ReadWord(CHIP_ID_REGISTER);
moel@167
   378
      Chip chip;
moel@167
   379
      switch (chipID) {
moel@353
   380
        case 0x8705: chip = Chip.IT8705F; break;
moel@167
   381
        case 0x8712: chip = Chip.IT8712F; break;
moel@167
   382
        case 0x8716: chip = Chip.IT8716F; break;
moel@167
   383
        case 0x8718: chip = Chip.IT8718F; break;
moel@167
   384
        case 0x8720: chip = Chip.IT8720F; break;
moel@170
   385
        case 0x8721: chip = Chip.IT8721F; break;
moel@167
   386
        case 0x8726: chip = Chip.IT8726F; break;
moel@277
   387
        case 0x8728: chip = Chip.IT8728F; break;
moel@341
   388
        case 0x8771: chip = Chip.IT8771E; break;
moel@319
   389
        case 0x8772: chip = Chip.IT8772E; break;
moel@167
   390
        default: chip = Chip.Unknown; break;
moel@167
   391
      }
moel@167
   392
      if (chip == Chip.Unknown) {
moel@167
   393
        if (chipID != 0 && chipID != 0xffff) {
moel@167
   394
          IT87Exit();
moel@167
   395
moel@167
   396
          ReportUnknownChip("ITE", chipID);
moel@167
   397
        }
moel@167
   398
      } else {
moel@167
   399
        Select(IT87_ENVIRONMENT_CONTROLLER_LDN);
moel@167
   400
        ushort address = ReadWord(BASE_ADDRESS_REGISTER);
moel@167
   401
        Thread.Sleep(1);
moel@167
   402
        ushort verify = ReadWord(BASE_ADDRESS_REGISTER);
moel@167
   403
moel@167
   404
        byte version = (byte)(ReadByte(IT87_CHIP_VERSION_REGISTER) & 0x0F);
moel@167
   405
moel@353
   406
        ushort gpioAddress;
moel@353
   407
        ushort gpioVerify;
moel@353
   408
        if (chip == Chip.IT8705F) {
moel@353
   409
          Select(IT8705_GPIO_LDN);
moel@353
   410
          gpioAddress = ReadWord(BASE_ADDRESS_REGISTER);
moel@353
   411
          Thread.Sleep(1);
moel@353
   412
          gpioVerify = ReadWord(BASE_ADDRESS_REGISTER);
moel@353
   413
        } else {
moel@353
   414
          Select(IT87XX_GPIO_LDN);
moel@353
   415
          gpioAddress = ReadWord(BASE_ADDRESS_REGISTER + 2);
moel@353
   416
          Thread.Sleep(1);
moel@353
   417
          gpioVerify = ReadWord(BASE_ADDRESS_REGISTER + 2);
moel@353
   418
        }
moel@353
   419
        
moel@167
   420
        IT87Exit();
moel@167
   421
moel@167
   422
        if (address != verify || address < 0x100 || (address & 0xF007) != 0) {
moel@167
   423
          report.Append("Chip ID: 0x");
moel@167
   424
          report.AppendLine(chip.ToString("X"));
moel@167
   425
          report.Append("Error: Invalid address 0x");
moel@167
   426
          report.AppendLine(address.ToString("X",
moel@167
   427
            CultureInfo.InvariantCulture));
moel@167
   428
          report.AppendLine();
moel@167
   429
          return false;
moel@167
   430
        }
moel@167
   431
moel@228
   432
        if (gpioAddress != gpioVerify || gpioAddress < 0x100 ||
moel@228
   433
          (gpioAddress & 0xF007) != 0) {
moel@228
   434
          report.Append("Chip ID: 0x");
moel@228
   435
          report.AppendLine(chip.ToString("X"));
moel@228
   436
          report.Append("Error: Invalid GPIO address 0x");
moel@228
   437
          report.AppendLine(gpioAddress.ToString("X",
moel@228
   438
            CultureInfo.InvariantCulture));
moel@228
   439
          report.AppendLine();
moel@228
   440
          return false;
moel@228
   441
        }
moel@228
   442
moel@228
   443
        superIOs.Add(new IT87XX(chip, address, gpioAddress, version));
moel@167
   444
        return true;
moel@167
   445
      }
moel@167
   446
moel@167
   447
      return false;
moel@167
   448
    }
moel@167
   449
moel@169
   450
    #endregion
moel@169
   451
moel@169
   452
    #region SMSC
moel@169
   453
moel@169
   454
    private void SMSCEnter() {
moel@236
   455
      Ring0.WriteIoPort(registerPort, 0x55);
moel@169
   456
    }
moel@169
   457
moel@169
   458
    private void SMSCExit() {
moel@236
   459
      Ring0.WriteIoPort(registerPort, 0xAA);
moel@169
   460
    }
moel@169
   461
moel@167
   462
    private bool DetectSMSC() {
moel@167
   463
      SMSCEnter();
moel@167
   464
moel@167
   465
      ushort chipID = ReadWord(CHIP_ID_REGISTER);
moel@167
   466
      Chip chip;
moel@167
   467
      switch (chipID) {
moel@167
   468
        default: chip = Chip.Unknown; break;
moel@167
   469
      }
moel@167
   470
      if (chip == Chip.Unknown) {
moel@167
   471
        if (chipID != 0 && chipID != 0xffff) {
moel@167
   472
          SMSCExit();
moel@167
   473
moel@167
   474
          ReportUnknownChip("SMSC", chipID);
moel@167
   475
        }
moel@167
   476
      } else {
moel@167
   477
        SMSCExit();
moel@167
   478
        return true;
moel@167
   479
      }
moel@167
   480
moel@167
   481
      return false;
moel@167
   482
    }
moel@167
   483
moel@169
   484
    #endregion
moel@169
   485
moel@163
   486
    private void Detect() {
moel@110
   487
moel@110
   488
      for (int i = 0; i < REGISTER_PORTS.Length; i++) {
moel@110
   489
        registerPort = REGISTER_PORTS[i];
moel@110
   490
        valuePort = VALUE_PORTS[i];
moel@110
   491
moel@167
   492
        if (DetectWinbondFintek()) continue;
moel@110
   493
moel@167
   494
        if (DetectIT87()) continue;
moel@110
   495
moel@167
   496
        if (DetectSMSC()) continue;
moel@228
   497
      }
moel@163
   498
    }
moel@163
   499
moel@163
   500
    public LPCIO() {
moel@236
   501
      if (!Ring0.IsOpen)
moel@163
   502
        return;
moel@163
   503
moel@236
   504
      if (!Ring0.WaitIsaBusMutex(100))
moel@163
   505
        return;
moel@163
   506
moel@163
   507
      Detect();
moel@163
   508
moel@236
   509
      Ring0.ReleaseIsaBusMutex();
moel@110
   510
    }
moel@110
   511
moel@130
   512
    public ISuperIO[] SuperIO {
moel@110
   513
      get {
moel@130
   514
        return superIOs.ToArray();
moel@110
   515
      }
moel@110
   516
    }
moel@110
   517
moel@110
   518
    public string GetReport() {
moel@110
   519
      if (report.Length > 0) {
moel@195
   520
        return "LPCIO" + Environment.NewLine + Environment.NewLine + report;
moel@110
   521
      } else
moel@110
   522
        return null;
moel@110
   523
    }
moel@110
   524
  }
moel@110
   525
}