找回密码
 加入计匠网
搜索
热搜: BIOS ACPI CPU Windows
查看: 34809|回复: 14

菜鸟的求助啊!关于winio 得到cpu温度

[复制链接]
发表于 2010-2-6 04:55:26 | 显示全部楼层 |阅读模式
#include <iostream>) A, x% y% L1 B/ D
#include <Windows.h>) {, E% r6 f" R
#include "WinIo.h"1 }( H% c& J. i: C9 `
using namespace std;
* _! d" G! J& i4 t7 n9 P* J$ P& q* U' U
& q* ~6 W! E$ z4 B#pragma comment(lib, "winio.lib")* M9 `, P2 J6 z8 Q  v
  O  b! s- b% O3 Y2 f
& W0 D) C$ a  m, S% {
int PMU_SC                =        0x6C;//命令端口, P" k9 k1 j8 c- \7 O
int PMU_DATA                =        0x68;//数据端口1 s( n, x/ I/ y0 j" L
int RD_EC_SMI                =        0x80;//读寄存器命令
7 w; E0 g+ j) C( y) rint POLLING_DATA                =        0xE7;//CPU温度寄存器号% K, f* q- B8 x2 f: ~+ L

" m* m  Q0 T8 B* G3 X3 i) ~DWORD dwTemp = 0;( F; B& M  `$ S& g6 F

( `6 R& X2 P# j  }$ Z2 Svoid PMU_Wait4IBE(DWORD *_value);
7 k- S8 t" ~- ]+ mvoid PMU_Wait4OBF(DWORD *_value);
# N; g& [1 M- Z7 U3 i6 {. d4 R% [% n5 t4 \
, j8 [+ T0 b; F! ?5 h
int main(int argc, char* argv[])9 R4 r& G4 U: Q* h- T
{3 @) c- D* i# V7 T5 G) @
        if(InitializeWinIo()==false)cout << "驱动程序加载失败! " << endl;
* o. x; c( ?6 N
- V! @! A- L9 b) l5 Z0 \7 k       
1 c( T/ D, @! ]& O' i0 f7 ]& X        //1、mov            dx,PMU_SC                /// k4 m* t) m0 Z3 p2 v
        //2、mov            al,RD_EC_SMI        //
) j" e3 R" @$ y; e. d        //3、call           pmuWait4IBE                //Must  have   输入缓冲为空吗,为空可以放命令了
* d! p9 p- l0 @- ~" o        //4、out            dx,al                        //将读寄存器命令放到命令端口中。* f$ y4 t7 i: F7 e2 Q/ t2 V

$ F% U3 x' ?7 Q9 H        PMU_Wait4IBE(&dwTemp);
% G+ \  ?6 N% Y        + r# b$ f3 z; x6 o. A& {
        SetPortVal(PMU_SC, RD_EC_SMI, 1);% _) z9 K% k9 Y& [
; W; n. h5 u# V! q
        PMU_Wait4IBE(&dwTemp);' R" _# P1 P: o% f2 ]0 w0 a6 V
        3 a2 p- Z" Y1 R. z% X
        SetPortVal(PMU_DATA, POLLING_DATA, 1);1 B$ E  n. ^/ B" n$ \* c& C

( W- c, D8 C; S) o  S* X. }3 E1 l% k        PMU_Wait4IBE(&dwTemp);5 @; W- |1 s4 w% _* J- u; Q/ U

2 t8 b( o) G( }, ?# }/ F. _        cout << dwTemp << endl;               
! Q- p8 u. o- I* I# ]
) S+ b" i5 b3 I0 Q: M4 @# L. R+ a        ShutdownWinIo();
; ?1 F) ]3 B) |9 c- p0 W5 c3 Y4 ^8 ^& ?: U9 H; h
        system("pause");" Y% S) R' ~3 y9 b
' d5 m2 c( r# ?( }5 M
        return 0;
( b& C' u  Y* u. F}: ]0 w. F7 Z3 P5 o

0 Z8 N" ^# f, j4 {void PMU_Wait4IBE(DWORD *_value)
; t* Q* }1 V& \{
" x/ O; U* B4 X3 G* b        //#########################################################   + m: Z0 Y% M, T
        /*
% J$ x2 }5 i) n5 G  r$ k% z        pmuWait4IBE proc   
" T: y  x( @- l2 v/ V        PUSH        AX   
* M7 z* i8 I# k# s$ I        PW4IBE:               
; h, f# q& h( s" w* r8 a- C* N        IN          AL,  06CH                                //Read  PMU  status   ) i, ]+ `. o; J* ]& J! p( {. \. S
        TEST        AL,  2                                        //Is  Input  Buffer  Empty?   
. U3 U5 d# v' R8 i% L4 @. N        JNZ         PW4IBE                                        //Jmp  if  no   
! r8 O% Z) i+ s' @2 J# \- p; p  s        POP         AX   7 u' H2 S# l' @  v
        ret   
/ E5 ]+ c7 F5 j+ d        pmuWait4IBE        endp                                        //END  OF  PMUWAIT4IBE
7 T1 \8 b8 ?& Q# w        *///循环读取0x6c端口的数据,看是否为空,不为空则一直等待其为空/ F# w. d- [' k0 w4 L# E7 \  o
        //#########################################################
! K; Y3 ]8 E9 p2 ~0 m6 P        /*do - E0 T6 r' n. k0 u" b# p/ o7 y4 }
        {
4 m3 v9 x! C& f4 x7 L                GetPortVal(PMU_SC, _value, 4);
% C' u( u3 f0 w0 a! l- c8 ^        }
+ l1 N4 K! k* [* p) B3 q+ F2 [* ~& Q        while ( *(_value) & 0x00000001 );*/  l: t' L, V6 _- T& e" z
        DWORD   dwRegVal=0;& B' b& g+ N8 F4 j2 ^* z8 P3 }; H6 I
        do* I0 p- F$ t9 @5 {$ Q( J' Y
        {  9 \7 W4 l! l. \6 N1 J5 }7 a+ U
                GetPortVal(PMU_SC,&dwRegVal,1);
* @4 {7 g/ m. F( w9 o# Z) b        }
& J7 U2 C" M" t+ d9 @        while(dwRegVal!=0x2);9 }3 F% y; [+ c
' r, a) g  D1 }' J
}
0 c- u; W+ w( N! Q) m" Z1 w3 Y, J. q+ ^* b$ n! ^8 i
以上是我在google了csdn还有有一些其他网站后写成这样了。但是使用getportval得到pmu_sc的值永远都不能等于2。: A" R) \7 T5 L$ b) H% x0 A5 M
所以变成了死循环了。
# H# B5 m; N' y. A1 q. ^1 M) f- p4 h! {! e6 `
我对硬件编程不懂。又不知道从何下手。
6 N) \( K  W4 f4 Q6 l3 z: P/ Y  i我自己按照amd和intel的cpuid pdf文档写了读取cpu基本信息的小东东。希望可以把cpu的温度也给搞出来,当然更好的是能把bios也解决了。6 f; j% F$ }1 ^3 A; Z/ K, W
但是这个温度已经搞了2天了,无果。很是郁闷。实在没办法了。! x8 D0 e2 s/ B" D$ k
: }/ i5 ]8 V! k, Q- ^8 n
我就想知道如果我想写个类似于everest这样的监控软件我需要搞清楚些什么? 或者简单点,我怎么才能把cpu的实时温度,硬盘温度,笔记本电池的信息给搞出来。
! i) p2 s4 I. j6 n并且我需要最后软件可以运行在x86和x64的系统上,因为我的笔记本是win 7 64bit的。( z8 k# Y' ]+ c7 ^3 z

! K5 {/ R# {' \: C感觉现在无从下手。我在网上google不到pmu的信息。比如说我想搞清楚0x6c到底是pmu的什么东西。我想这该有张表什么的吧?硬是没得。郎个办嘛?有哪位大侠给我指条明路吧!:
发表于 2010-2-6 12:02:36 | 显示全部楼层
这东西,底层实现是千差万别的。你如果没有主板的电路图的话,怎么知道温度这些东西是那种方式设计的? 一般的程序都是通过Windows的API读的
回复

使用道具 举报

发表于 2010-2-6 14:58:08 | 显示全部楼层
你这种办法应该指的是EC CPU Temp值存放在ACPI ECRAM的offset 00E7h.但是你这样做法应该是读不到的。6 s4 K: s* I9 i
1.OS会使用 80h RD_EC ACPI CMD 读ACPI EC,可能会冲突,如果一定要这样做,我所知道的办法就是先Disable SCI-读ACPIEC-Enable SCI,不过这种做法也不是适合所有Notebook.
; A9 I, X! l6 `6 X( @3 q, J* c2.0x6C/0x68不适合所有Notebook.EC到底使用哪个Port?.一般是使用0x66/0x62,但是0x66/0x62已经被OS使用了,会冲突4 B+ x) Y; s6 u: s0 w$ S3 M! Y9 B
3.不是所有ODM的CPU temp是放在ACPI ECRAM的0x00E7处的.2 |' ]$ G( {! ]# I6 X  _4 B& B3 J
& L& E& g8 ]7 D
所以.....呵呵
回复

使用道具 举报

 楼主| 发表于 2010-2-6 19:18:05 | 显示全部楼层
按照楼上的说法就是这样做的可行性不好。而且存在端口的变化分歧性。+ S. i% `' G' q  q

/ s( w" v& D0 c那么有些什么可行的办法呢?
0 W3 x7 j9 l) p4 W1 B; w为什么类似于everest这样的软件可以识别目前几乎所有的主流机型的温度呢?而且它称这部分为传感器。在里面不止是cpu的温度。还有其他的设备。
3 v1 c' h6 T. ]+ R" R1 U/ e! R1 o  p; z$ A0 }8 l; r
它的做法是为其建立数据库吗?通过不同的特征采用不同的方式或者端口吗?
, i: @. k' S  r+ \* W1 X
0 O7 M$ e4 B/ F" t" \- O那ACPI里面有cpu的温度吗?如果有,我需要怎样才能从这方面下手啊?有些什么值得推荐的书籍吗?
回复

使用道具 举报

 楼主| 发表于 2010-2-6 19:21:42 | 显示全部楼层
http://www.ufoit.com/bbs/viewthread.php?tid=420
# |2 o) j1 s0 c5 N1 l1 y# i7 ^* k3 L  r, n3 |$ x
http://www.ufoit.com/bbs/viewthread.php?tid=452' W% s+ ?& t- M

7 U0 h3 e& U; Z. [! h% m/ ghttp://www.ufoit.com/bbs/viewthread.php?tid=241
$ b+ Z. e! _/ A8 S: M( t
( z  L5 L& I! ~, E2 X& ^* z看来得先从这些地方看看了。谢谢楼上两位的回答。
回复

使用道具 举报

 楼主| 发表于 2010-2-6 19:26:00 | 显示全部楼层
那你的问题,说起来,跟ACPI是没多少关系,但用ACPI的方法,也是会让系统最稳定,也是最适合用acpi windows程序开发,如低难度的就是WMI ACPI,见DDK中带的WMI-ACPI白皮书。API可以获取电池,CPU,等相关信息的。驱动,你可以建立自己的pnp device驱动来获取,如仅仅是EC里的数据,何必呢,用IO读写就可以,只要你知道如何读EC的space。予人鱼,不好呀,渔才好。
7 ]; ?5 t  `) Z0 f& Z4 I
: q6 i3 w0 J5 T4 S1、其中WMI-ACPI最简单,但是BIOS得配合,推荐。
7 h7 n. _9 K9 x, h, c  R. n. s2、Driver最复杂,也需要BIOS配合,推荐。, V  |. B" i9 H# b0 Z6 E; @5 D6 H# Y
3、Windows API只能获取到特定信息,不需要特定的BIOS配合。
  U6 I/ V6 f6 S% e1 |$ l4、IO的方法,能获取到全部的EC状态信息,需要EC的文档,如果是给for end user,要出货的程序,这种方式不推荐。
% G6 H' i: z) O你可以混合使用。
9 t; V) C* ^/ `  ~# {
* `' D- s6 x* g===============================================================
+ I: K5 `4 d8 d4 p' B( a" V管理员的这句话:
$ T  V" t3 O' j- @: i7 [% I( M如仅仅是EC里的数据,何必呢,用IO读写就可以,只要你知道如何读EC的space。” 如何理解啊?
+ @. i, {( K" v% j  E" k, M
; P! Z: D) R0 m- P2 t- X$ ^予人鱼,不好呀,渔才好。”这句话又怎么理解啊?呵呵
# `+ a8 _/ b( H' ?9 K+ B+ F  s
: |% a. |# z# @7 [5 ?另外,居然复制一下有那么多扰乱字符,太万恶了!呵呵!
回复

使用道具 举报

 楼主| 发表于 2010-2-6 19:38:10 | 显示全部楼层
http://www.ufoit.com/bbs/viewthread.php?tid=269
$ P+ X. s: `+ {8 C2 b+ y& W+ C
$ ]( `0 J! @/ G, l: _% J1 u% T2 z9 J9 t这个帖子看了后,感到迷茫了。BIOS我知道是就basic input output system。EC是什么东东啊?) P: i# Q9 h- R5 X4 I* U9 Q
& E4 ]" M- G; V8 F  ~* n& {
还有就是在里面又找到了个链接是管理员大人,小斌斌发的呵呵。. n* r$ y" J) h! |* g
里面谈到了要用DDK。我对这个完全没有接触过,我猜应该是driver dev kit吧。不过我要去下什么样的版本呢?
. d: S2 @, @/ G5 h, N# W6 [7 F0 M9 O# l+ ]- r
我目钱开发的系统是win32 xp sp2,ide 是vc 2005。
回复

使用道具 举报

 楼主| 发表于 2010-2-6 19:40:28 | 显示全部楼层
原帖由 Faintsnow 于 2010-2-6 14:58 发表
: K$ B- w3 C$ N/ A) E, n0 g你这种办法应该指的是EC CPU Temp值存放在ACPI ECRAM的offset 00E7h.但是你这样做法应该是读不到的。8 \' J9 m8 D4 q
1.OS会使用 80h RD_EC ACPI CMD 读ACPI EC,可能会冲突,如果一定要这样做,我所知道的办法就是先Disable SCI-读ACP ...
3 M5 S( G9 k( T* E

) c& ?" p$ E9 y: F' S您能讲讲怎么disable SCI啊?然后又怎样呢?谢谢
回复

使用道具 举报

发表于 2010-2-8 09:25:24 | 显示全部楼层
找个APIC spec看看就知道了
回复

使用道具 举报

发表于 2010-2-9 10:55:59 | 显示全部楼层
不用禁用什么SCI的,有是有冲突,不过马马虎虎还能用。过滤掉异常值就行了。( J8 d6 J4 J0 x# k& u1 X: @+ z
: ]7 N" u" o/ \' K2 I5 r8 F% f
void write66(unsigned char Data)& o& M' h1 Y1 \
{
/ P0 {- \, j) l# W0 q% S& U: z        DWORD Status,TimeOut=10000000;9 j) @% l( Z+ e% x& k8 w/ X
        do
4 Y2 w3 {6 {; @: A, Z$ S6 M- u        {8 m$ m9 P4 b7 E
                GetPortVal(0x66,&Status,1);
  e& [& F& K0 c0 ~                TimeOut --;
" X3 j" s5 N$ P3 C' [//                Sleep(1);
/ |2 b; r/ z. T% |# W8 r        }while((Status & 2) ==2 && TimeOut>0);! E" R5 Z! b$ j" F
4 x; b4 G3 ], f! ?7 O
        SetPortVal(0x66,(DWORD)Data,1);& h! n* s0 [0 L4 c0 p+ p
}
! @- ^8 A6 |2 B  nvoid write62(unsigned char Data)6 I9 l% H% N+ e. V3 J
{
  d- V- A$ G) X* Y! t9 ~        DWORD Status,TimeOut=10000000;; K+ t# {5 G6 c2 z
        do* d( e# m/ _! Y: i; I
        {
. `* R% R% j4 c$ ^                GetPortVal(0x66,&Status,1);. `9 t( u) o1 h+ ^/ b
                TimeOut --;9 z/ v6 r2 \6 r# y, |, |
//                Sleep(1);" x& u. b, i* L7 W
        }while((Status & 2) ==2 && TimeOut>0);
" _# m3 C7 c) ?7 [' T; p! C
+ I" n% e3 a, P0 w+ o+ N0 N        SetPortVal(0x62,(DWORD)Data,1);
. n- Q/ @/ \. {7 l4 h) \}
* p  s6 S1 F+ s* sunsigned char read62()& {: \4 @+ a' U. g) ?5 u
{  L$ D5 |: F* U
        DWORD Status,Data,TimeOut=10000000;
4 K  Q: ^- n1 x' m2 _& b* t        do
2 d+ _% i3 _# w+ X" w        {9 |/ P$ U: `; \- j
                GetPortVal(0x66,&Status,1);8 L" J- g7 ?! C- n. q
                TimeOut --;* r  b5 X  c+ {3 q2 B
//                Sleep(1);
$ b8 }3 n4 J& W8 P9 z7 X" K5 V6 Y        }while((Status & 1) ==0 && TimeOut>0);
4 j" z. P+ i' _8 |! N) f+ @3 \6 H& n% }
% X8 T- \# X/ ^! ?
        GetPortVal(0x62,&Data,1);
4 s0 M; g' v7 S+ Z! m1 i: @9 o; R        return (unsigned char)Data;
; A( N/ w6 r3 h}1 g5 {/ H) j/ y( A; k
unsigned char read_ec(unsigned char index)
2 ], q  _$ o2 T: v# C# m/ c{
, N9 f; ~2 y8 y5 h8 z        write66(0x80);$ q  E8 Y( p0 M" @
        write62(index);
% |4 ?  H; r8 h* y, S. U* i  O        return read62();1 S/ F3 p' p' B3 B. Y
}
( t1 X3 b& C7 Q; K$ V4 B' y3 w. N) O$ b3 H& q+ x* [
[ 本帖最后由 qdk0901 于 2010-2-9 10:58 编辑 ]
回复

使用道具 举报

发表于 2010-2-9 16:41:22 | 显示全部楼层
HardwareEditor.zip (782.25 KB, 下载次数: 1471) 楼上的有没有发现用你的方式后出现的两种异象,你的while等待EC IBE/OBF的动作是永远退出不了的。都是因为timeout超过了你设定的值才退出来的。那是因为中断优先的缘故,每次你用这种方式读写EC其实首先读写的不是你的AP而是OS的ACPIEC Driver。你读到或者写入的值只不过是OS ACPI读到或者写入后在EC Data port留下来的值。另外你有没有发现OS的错误报告里面一直在报告ACPI错误,因为OS被迫在没有与BIOS同步的情况下对EC做读写。OS读到的数据也当作无用的data忽略掉的。
6 a2 V& k$ ]) |, M5 G  如果一定要不disable SCI在ACPI OS读写EC那你完全没有必要再去判断EC IBE/OBE了,完全没有意义。
% m* v3 T# e- p, x8 }, U. {4 V4 U" ]1 ?3 n
[ 本帖最后由 Faintsnow 于 2010-2-9 16:44 编辑 ]

HE

HE
回复

使用道具 举报

发表于 2010-2-9 16:56:18 | 显示全部楼层
原帖由 海陆空 于 2010-2-6 19:40 发表 + x5 W3 I  l4 {" k3 b. V

3 u; x6 G6 W  I/ h6 `0 S0 n
1 b) v- u& y  u$ e& m+ ~9 j& q您能讲讲怎么disable SCI啊?然后又怎样呢?谢谢
/ r& U  [* U$ T4 ]- o7 ~
+ L; D- |6 R* D! ^, M
1. Find out the APIC address (you may looking it in ACPI APIC table), usually 0xFEC00000,0 o9 H% @6 o6 J/ A5 }% I) U
1 J! O/ A2 N/ _3 z
2. Find out SCI IRQ number (you may looking it in ACPI FACP table), usually IRQ9.- M6 e4 U, \- f# S# T6 z
* M  e/ @% }9 J, K) c
3. Then set bit16 of the IRQ to disable it.
7 s1 t4 g. F2 G- s" x% G1 G- p9 j
    a.. Offset = IRQ# * 2 + 0x10;
9 B9 \6 h2 e4 U
) l( x: g: f1 g9 z3 M& _. Y. U& x    b. Write Offset to APIC base,
3 M: x# g& T2 T( n& z- M: S
3 ?. ~' W2 g  W; u+ c    c. Read Data from APIC base + 0x10;
3 {5 m( T% A8 Q9 ^% m1 K* h2 u) l0 X, ^* Q' X5 k) _9 a
    d. Or bit16 to Data;, F; @2 w+ m# J5 t; ^+ B

+ H: P6 [3 v5 ~( g/ P    e. Write Data back to APIC base + 0x10;
/ K# [$ B% S4 l* e1 L: p6 D8 p0 j/ O5 f( ?- _; C
7 a# b+ ^7 ]1 Z# B5 K

6 P  S9 f* A; m* `3 Y/ ~( qYou need to check APIC spec for details.
回复

使用道具 举报

发表于 2010-2-9 17:51:44 | 显示全部楼层
原帖由 Faintsnow 于 2010-2-9 16:41 发表
/ @2 f$ W. y5 K' P3 _545楼上的有没有发现用你的方式后出现的两种异象,你的while等待EC IBE/OBF的动作是永远退出不了的。都是因为timeout超过了你设定的值才退出来的。那是因为中断优先的缘故,每次你用这种方式读写EC其实首先读写的不是你 ...

; I% \9 v, s/ f& X, E7 {: d) u: Y. M5 `9 h; l$ X9 ]
如果一定要不disable SCI在ACPI OS读写EC那你完全没有必要再去判断EC IBE/OBE了,完全没有意义。
/ J5 L- \: N! k==============================================5 g) o: s9 m1 e
事实上却是有数据错误,但是说不判断IBE OBF,那就有问题了。; `' M# B. d& s5 o, F( f; M5 O6 i0 N
" s! z1 }3 Y+ A) o$ H" E
因为OS去读写62/66 port并不是很频繁(至少我们的平台如此),因此有几个错误的值我们可以容忍的,而且错误的值基本是固定的某个值(就是某个Q Event的id)5 w5 G3 M# K; U4 x; h9 F, r
但是如果不判断IBE或者OBF,连自己的数据都不知道是什么时候ready的了。# h7 [( @0 d8 g8 w2 l

2 o% J+ n; {7 X  H# J( n& h因为只是用了做些简单的测试工具,所以这样的错误是可以容忍的。; ?* |+ u3 f: d2 b& q6 v/ @
当然正规的做法当然是要禁用SCI
回复

使用道具 举报

发表于 2010-2-9 18:07:46 | 显示全部楼层
我想说两个地方:! X. J* C9 O0 `7 A
1、ACPI OS去读写EC Space时,一般情况下EC会用一个SCI去响应OS读或写的每一步细分操作。
$ u% {: h+ Q% P3 z2、新手不要把EC Space和EC Ram space搞混了。在DOS下,ACPI中定义的EC Space是由OS发8x command给EC去访问的,这个访问到的地方,或许是EC Ram space一样,也许是另一块地方,也许是EC ram space中的某一块地方,这个要看EC自己的做法,平常我们所说的EC Space基本上就是ACPI中定议的EC Space.
回复

使用道具 举报

发表于 2010-5-14 20:38:27 | 显示全部楼层
讲得很好,哈哈,学习了
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 加入计匠网

本版积分规则

Archiver|手机版|小黑屋|计匠网

GMT+8, 2026-1-19 00:34 , Processed in 0.303184 second(s), 19 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

快速回复 返回顶部 返回列表