iT邦幫忙

2023 iThome 鐵人賽

DAY 18
0

經過昨天的介紹,目前應該都對Hardware Monitor有初步的瞭解,今天要來介紹與讀取CPU風扇轉速相關的實作。

主要函式宣告如下:

  • SioSdk.h
    SIO_API unsigned int GetCpuFanSpeed();
    
  • SioSdk.c
    unsigned int GetHwmBase();
    unsigned char ReadHwm(unsigned int Base, unsigned int Bank, unsigned int Register);
    bool WriteHwm(unsigned int Base, unsigned int Bank, unsigned int Register, unsigned int Data);
    
    • GetCpuFanSpeed為讀取CPU風扇轉速的主體函式。
    • GetHwmBase用來讀取Hardware Monitor的I/O位址。
    • ReadHwmWriteHwm就類似於Day13ReadSioWriteSio,但這裡只針對Hardware Monitor的暫存器作讀寫。

主要函式實作如下:

  • SioSdk.c
    • GetHwmBase

      unsigned int GetHwmBase()
      {
          unsigned int BaseLow, BaseHigh;
      
          printf("GetHwmBase\n");
          WriteSio(LDN_SEL, LDN_HWM);
          BaseLow = (unsigned int)ReadSio(BASE1_LO) & 0xFF;
          BaseHigh = (unsigned int)ReadSio(BASE1_HI) & 0xFF;
      
          return (BaseHigh << 8) + BaseLow;
      }
      
      • Hardware Monitor I/O位址會介於0x100至0xFFE,所以我們將函式宣告為unsigned int
      • 須先切換到logical device B。
      • 然後分別讀取Hardware Monitor的I/O位址的高位元組低位元組
      • 最後將高位元組左移8個bit再加上低位元組就是完整的Hardware Monitor I/O位址。
    • ReadHwm

      unsigned char ReadHwm(unsigned int Base, unsigned int Bank, unsigned int Register)
      {
          unsigned char Temp;
          unsigned char Output;
      
          printf("ReadHwm\n");
          WriteIoPort(Base + 0x05, HWM_BANK_NO);
          Temp = ReadIoPort(Base + 0x06);
          Temp &= 0xF0;
          WriteIoPort(Base + 0x06, Temp | Bank);
      
          WriteIoPort(Base + 0x05, Register);
          Output = ReadIoPort(Base + 0x06);
      
          return Output;
      }
      
      • Base為Hardware Monitor I/O位址,Base + 0x05為Index埠,Base + 0x06為Data埠。
      • 需要先對Bank Select Register寫入Bank number切換到對應的Bank。
      • Register為想要讀取的暫存器位址。
      • 對Index埠寫入暫存器位址,然後就可以從Data埠讀出該暫存器位址的值。
    • ReadHwm

      bool WriteHwm(unsigned int Base, unsigned int Bank, unsigned int Register, unsigned int Data)
      {
          unsigned char Temp;
          bool Result = FALSE;
      
          printf("WriteHwm\n");
          WriteIoPort(Base + 0x05, HWM_BANK_NO);
          Temp = ReadIoPort(Base + 0x06);
          Temp &= 0xF0;
          WriteIoPort(Base + 0x06, Temp | Bank);
      
          Result = WriteIoPort(Base + 0x05, Register);
          Result = WriteIoPort(Base + 0x06, Data);
      
          return Result;
      }
      
      • 一樣先對Bank Select Register寫入Bank number切換到對應的Bank。
      • Register為想要寫入的暫存器位址。
      • Data為想要寫入的暫存器的值。
      • 對Index埠寫入暫存器位址,然後再對Data埠寫入想要寫入該暫存器位址的值。
    • GetCpuFanSpeed

      unsigned int GetCpuFanSpeed()
      {
          unsigned int Base;
          unsigned int RpmLow, RpmHigh;
      
          printf("GetCpuFanSpeed\n");
          OpenSioConfig();
          Base = GetHwmBase();
          CloseSioConfig();
          RpmHigh = ReadHwm(Base, 0x04, 0xC2);
          RpmLow = ReadHwm(Base, 0x04, 0xC3);
      
          return (RpmHigh << 8) + RpmLow;
      }
      
      • 因為GetHwmBase會使用到環控晶片的一般暫存器,要先使用Day12中提到的存取環控晶片暫存器的方式,先進入Extended Function Mode,讀出Hardware Monitor I/O位址,再離開Extended Function Mode。
      • 我們的目標是讀取CPU風扇轉速,如Day17所提,與環境相關的數值都位於bank 4,風扇轉速也包含其中,而CPU風扇通常與環控晶片的CPUFANIN相連,如下圖所示:
      • 可以看到Bank4 0xC2為CPU風扇轉速的高位元組,0xC3為低位元組,要得到風扇轉速則是將高位元組左移8個bit再加上低位元組,所得出的結果就是完整的風扇轉速。

以上就是讀取CPU風扇轉速相關的實作,完整的專案可以到參考內容中的SioSdk閱讀。

參考內容

SioSdk - Repo
環控晶片 - NCT6796


上一篇
Day17 使用I/O存取環控晶片-7
下一篇
Day19 使用I/O存取環控晶片-9
系列文
Windows Driver + Electron 學習筆記30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言