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

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

[复制链接]
发表于 2010-2-6 04:55:26 | 显示全部楼层 |阅读模式
#include <iostream>
& K, ]; `6 x/ m/ K8 B#include <Windows.h>2 h. U( c; y( A
#include "WinIo.h"8 r( S4 p4 k7 I! `
using namespace std;
8 A$ Y" r5 ?9 r: ~" q. N, E- e
# C5 j: Y9 d( B% Q; _#pragma comment(lib, "winio.lib")/ f5 `+ N$ ]. H1 L8 L9 a4 D9 x
6 c% V8 m$ h; }1 x0 t1 r2 O" Y
2 o; j9 |3 I( r. X& q  p
int PMU_SC                =        0x6C;//命令端口* U7 x' z  c4 [. L& T$ T
int PMU_DATA                =        0x68;//数据端口5 N# Z* ^! h5 O7 X) z( F
int RD_EC_SMI                =        0x80;//读寄存器命令0 ~- i8 K1 T7 H+ f8 ?- j' A2 w5 i
int POLLING_DATA                =        0xE7;//CPU温度寄存器号+ i/ B! Z1 n& K7 }
' ]+ }3 o8 e# B4 L, Y( p1 m) L
DWORD dwTemp = 0;
8 E" s8 k* F4 W% `' I! i- x& C& S2 B% Y* a! ~1 I
void PMU_Wait4IBE(DWORD *_value);
8 S7 m! u: `& @7 X6 D9 uvoid PMU_Wait4OBF(DWORD *_value);) u, l7 y# C6 @/ C; a2 I' e
$ ?/ E! U# u$ b

) n+ p! y; ^2 k3 e. x  iint main(int argc, char* argv[])
) [2 H; D% n5 U{+ J9 A+ j; z2 v2 y7 k
        if(InitializeWinIo()==false)cout << "驱动程序加载失败! " << endl;
" f; {- Y0 i6 W) p$ g/ l; |0 n% a# U* {6 S$ W
        # T1 |( T/ {0 b9 M
        //1、mov            dx,PMU_SC                //" }4 K/ l& m6 p
        //2、mov            al,RD_EC_SMI        //+ Q+ {' g5 ^8 W7 }0 O5 b( Y! h
        //3、call           pmuWait4IBE                //Must  have   输入缓冲为空吗,为空可以放命令了, f) N0 j- u# J8 r8 d' h' X, ~2 B7 n" J
        //4、out            dx,al                        //将读寄存器命令放到命令端口中。2 h: Q" R* X/ }( V9 D; {
& i9 D. a: _0 h% }" A
        PMU_Wait4IBE(&dwTemp);, C% C# e- D+ N0 S
        / z& A$ C) c/ Y
        SetPortVal(PMU_SC, RD_EC_SMI, 1);" J. y3 D# O* S
2 x: d+ v: l$ f/ R6 Z5 W
        PMU_Wait4IBE(&dwTemp);
! q' C! h. t+ ?2 y' ?        " D5 A3 o9 V2 f( u
        SetPortVal(PMU_DATA, POLLING_DATA, 1);! x- {7 J0 e! i1 z$ t

* h+ m9 G6 r3 l% {" C5 `        PMU_Wait4IBE(&dwTemp);
( G, _6 g7 k( N/ J/ X) Z  h, D6 q3 i# i5 X6 A
        cout << dwTemp << endl;               
& M1 h2 p# X' S3 Z% I- Y! y$ b$ Y+ t9 e) ^( W5 |$ Z# t
        ShutdownWinIo();
; _& v: t6 R9 z3 c& i
1 ]- n. f, z# b# M7 g        system("pause");9 I; c3 K/ x+ T
3 O* V- Q# l# J  F, m3 B- |
        return 0;- I( x; q$ E  `" f3 ?$ X6 P- i, d
}7 h2 j1 |/ Z' w3 m' a: W
3 K1 l5 p; P5 q, A" a
void PMU_Wait4IBE(DWORD *_value)
! U6 _7 J: L: Q# i6 l/ R+ w: t7 P{
0 d' b$ ]/ z" q$ A        //#########################################################   
% ~, A" H: |/ T' G        /*
7 E' K2 h3 Z$ ?: q/ V. Z; t        pmuWait4IBE proc   , P9 c  y+ O; Y) o$ M2 U2 r
        PUSH        AX   
# [: R0 ?! ^# q% I  r/ G  c        PW4IBE:               
; z6 ?9 B0 C6 Y" L        IN          AL,  06CH                                //Read  PMU  status   & w+ R0 h7 ~5 o4 _! J6 k" ]
        TEST        AL,  2                                        //Is  Input  Buffer  Empty?   ' L! M/ b6 t- R+ @& b/ z
        JNZ         PW4IBE                                        //Jmp  if  no   
, G2 ^, O$ I* d8 s        POP         AX   - ~" ^0 u2 E, }6 c% Y3 ]( r
        ret   ) M8 d( R1 {) n1 C
        pmuWait4IBE        endp                                        //END  OF  PMUWAIT4IBE
- @7 U/ x* m9 o1 V" ^5 f/ |8 v        *///循环读取0x6c端口的数据,看是否为空,不为空则一直等待其为空
6 T% b5 p/ V8 A* ?* K        //######################################################### . [+ o) F/ Q' G# k0 e$ J2 F
        /*do + ~: L0 b* c! M1 `2 r
        {8 ]$ Y9 i: R3 s, O
                GetPortVal(PMU_SC, _value, 4);
0 P* x* ]  Y7 I        }8 r+ G  z! t; R2 d
        while ( *(_value) & 0x00000001 );*/
1 ^- F5 e/ e7 j  x& G6 v, u        DWORD   dwRegVal=0;  E) W$ `, \8 a' V
        do
" J+ I9 I7 d* }& e; v# V        {  ' c. R) C* |4 q( ?8 |# l
                GetPortVal(PMU_SC,&dwRegVal,1);% S4 q% q& n6 m" M- L6 i* d# D
        }# r, @7 ~8 F) }6 m
        while(dwRegVal!=0x2);
. V4 q& P& \, E2 z0 A8 ^8 P2 m6 R4 L* c+ `% M* A+ n8 p2 ^& x) J
}
0 h/ e7 H/ u8 l/ [( I! K1 v$ T4 f
以上是我在google了csdn还有有一些其他网站后写成这样了。但是使用getportval得到pmu_sc的值永远都不能等于2。
. d5 k' _* j0 l) v) e3 A; J% D所以变成了死循环了。" d6 R! F2 G' ]  O) \# r/ n7 ^

5 w5 k3 Z* d- B+ ]我对硬件编程不懂。又不知道从何下手。
3 S; [5 Y0 f( \我自己按照amd和intel的cpuid pdf文档写了读取cpu基本信息的小东东。希望可以把cpu的温度也给搞出来,当然更好的是能把bios也解决了。
$ e/ K% ]% U1 I0 E4 z- y但是这个温度已经搞了2天了,无果。很是郁闷。实在没办法了。
. Z, J" L  X- c" s9 N( z
+ L0 w- y+ Y3 {" H4 ~! q: j+ x我就想知道如果我想写个类似于everest这样的监控软件我需要搞清楚些什么? 或者简单点,我怎么才能把cpu的实时温度,硬盘温度,笔记本电池的信息给搞出来。
# H7 |% P4 S/ t并且我需要最后软件可以运行在x86和x64的系统上,因为我的笔记本是win 7 64bit的。, a4 D# M( p! O4 h: [  g

& E8 L/ c, B' r* W1 r感觉现在无从下手。我在网上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.但是你这样做法应该是读不到的。
' r0 k1 `& V+ ?4 J( [1.OS会使用 80h RD_EC ACPI CMD 读ACPI EC,可能会冲突,如果一定要这样做,我所知道的办法就是先Disable SCI-读ACPIEC-Enable SCI,不过这种做法也不是适合所有Notebook.
1 x; Z7 H2 b  k5 v' b2.0x6C/0x68不适合所有Notebook.EC到底使用哪个Port?.一般是使用0x66/0x62,但是0x66/0x62已经被OS使用了,会冲突2 g* X7 o% Y  h' h. G! \& l- M; C
3.不是所有ODM的CPU temp是放在ACPI ECRAM的0x00E7处的.+ H0 N2 t8 |. C2 s& M# R+ \, G6 {% S( A
! o1 N3 [( H1 {  A/ D0 C% S6 M
所以.....呵呵
回复

使用道具 举报

 楼主| 发表于 2010-2-6 19:18:05 | 显示全部楼层
按照楼上的说法就是这样做的可行性不好。而且存在端口的变化分歧性。4 P1 U) G( T# l# u5 \, M
% i- v2 Q- y1 z. n% u
那么有些什么可行的办法呢?  Y! X* |& e6 N. s3 z$ [# ^
为什么类似于everest这样的软件可以识别目前几乎所有的主流机型的温度呢?而且它称这部分为传感器。在里面不止是cpu的温度。还有其他的设备。" Z( w( n5 o) e2 S7 G( G

% z3 a. Z& Q9 t# j它的做法是为其建立数据库吗?通过不同的特征采用不同的方式或者端口吗?
: b7 F* ^6 V6 ^* W& `- [" I7 f8 }9 V- B# U+ F7 N. w2 Y: X# ~
那ACPI里面有cpu的温度吗?如果有,我需要怎样才能从这方面下手啊?有些什么值得推荐的书籍吗?
回复

使用道具 举报

 楼主| 发表于 2010-2-6 19:21:42 | 显示全部楼层
http://www.ufoit.com/bbs/viewthread.php?tid=420
: H) \& v) v6 x* u4 {# E) X2 |3 n5 Q1 x9 h' h1 j3 x
http://www.ufoit.com/bbs/viewthread.php?tid=452
, V8 u0 \1 N: b9 ^" @% k
6 T, t. s* V# N7 Z- V% Hhttp://www.ufoit.com/bbs/viewthread.php?tid=2413 S5 Z7 p# m) b% x! N

) _; w1 S& ?' a( c0 ^' b看来得先从这些地方看看了。谢谢楼上两位的回答。
回复

使用道具 举报

 楼主| 发表于 2010-2-6 19:26:00 | 显示全部楼层
那你的问题,说起来,跟ACPI是没多少关系,但用ACPI的方法,也是会让系统最稳定,也是最适合用acpi windows程序开发,如低难度的就是WMI ACPI,见DDK中带的WMI-ACPI白皮书。API可以获取电池,CPU,等相关信息的。驱动,你可以建立自己的pnp device驱动来获取,如仅仅是EC里的数据,何必呢,用IO读写就可以,只要你知道如何读EC的space。予人鱼,不好呀,渔才好。. x# P' g  l$ l* ^) |) i
; H9 J, L1 v* t5 M. q, k
1、其中WMI-ACPI最简单,但是BIOS得配合,推荐。
! E; s; F9 q) N% z3 |# o2、Driver最复杂,也需要BIOS配合,推荐。
; X7 U  _* @7 v3 v3、Windows API只能获取到特定信息,不需要特定的BIOS配合。, G8 S, @7 Z1 p5 }9 p9 Y
4、IO的方法,能获取到全部的EC状态信息,需要EC的文档,如果是给for end user,要出货的程序,这种方式不推荐。$ K* H2 J5 |- }2 i, U- P" x
你可以混合使用。: A$ K) H1 n2 B2 C. B+ o

2 D9 D7 D2 X# S' j===============================================================, v( [/ H) M# i/ i( k
管理员的这句话:! k4 I( N8 J' f4 U! M
“如仅仅是EC里的数据,何必呢,用IO读写就可以,只要你知道如何读EC的space。” 如何理解啊?
: a# {! {7 }; `0 y0 z 5 R* g9 B5 }6 k- v# ?+ z* N" e3 D7 n
“予人鱼,不好呀,渔才好。”这句话又怎么理解啊?呵呵
/ U$ l4 _: U1 `6 D9 n# R. d( G8 y8 |  `8 f
另外,居然复制一下有那么多扰乱字符,太万恶了!呵呵!
回复

使用道具 举报

 楼主| 发表于 2010-2-6 19:38:10 | 显示全部楼层
http://www.ufoit.com/bbs/viewthread.php?tid=269
* j; U- T3 i9 M9 G$ |2 N8 f0 ]% V# i4 x$ O3 U( p
这个帖子看了后,感到迷茫了。BIOS我知道是就basic input output system。EC是什么东东啊?+ b2 b( |$ _& [
/ r2 d0 K2 ^' G5 o; U
还有就是在里面又找到了个链接是管理员大人,小斌斌发的呵呵。
/ _+ ^' ~3 q8 i7 N7 `& P0 U8 \里面谈到了要用DDK。我对这个完全没有接触过,我猜应该是driver dev kit吧。不过我要去下什么样的版本呢?
# r' S2 @3 ~: j8 B$ h
  N1 C- Z8 T$ q4 Y我目钱开发的系统是win32 xp sp2,ide 是vc 2005。
回复

使用道具 举报

 楼主| 发表于 2010-2-6 19:40:28 | 显示全部楼层
原帖由 Faintsnow 于 2010-2-6 14:58 发表 * v5 @0 W& e; E
你这种办法应该指的是EC CPU Temp值存放在ACPI ECRAM的offset 00E7h.但是你这样做法应该是读不到的。
5 ~; c9 z, E$ \0 n1 J$ x/ b1.OS会使用 80h RD_EC ACPI CMD 读ACPI EC,可能会冲突,如果一定要这样做,我所知道的办法就是先Disable SCI-读ACP ...
9 R* e; E5 G1 Y6 T. d7 ^
/ n0 B! c4 s2 \1 G
您能讲讲怎么disable SCI啊?然后又怎样呢?谢谢
回复

使用道具 举报

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

使用道具 举报

发表于 2010-2-9 10:55:59 | 显示全部楼层
不用禁用什么SCI的,有是有冲突,不过马马虎虎还能用。过滤掉异常值就行了。" |. S% h$ N$ H$ z' h; |6 M

+ {9 T% ^" T% }% H1 ?void write66(unsigned char Data)% Z0 I5 i* B+ O; g3 b7 d( a
{
9 X+ H7 B$ U8 y  v        DWORD Status,TimeOut=10000000;" T. x2 Z( ^0 S# Z; N
        do! |) r1 v4 P+ G0 A* K
        {2 c1 Q0 C0 `7 v- D8 }" h! P# p
                GetPortVal(0x66,&Status,1);" _/ m2 Y5 \& S& ]8 g: ]' \: Z) a) v* g  u
                TimeOut --;, B$ m* f5 L  D5 {$ ^
//                Sleep(1);& X3 _: B; l$ T9 z" r& a
        }while((Status & 2) ==2 && TimeOut>0);) q, f, x2 `& S7 f5 i9 Q% ?

7 U4 n# |) f& C/ p# h# b        SetPortVal(0x66,(DWORD)Data,1);3 T7 v( d: d+ G
}
, u$ R% ~' k7 Cvoid write62(unsigned char Data)% a  ]5 [9 |2 \% d* P1 t; n
{
% F+ K/ k7 w0 U5 f        DWORD Status,TimeOut=10000000;1 z* E; v( _7 Y/ F
        do& R( b" B5 K- r6 N9 m1 ~6 ?
        {" \4 t5 U' h' l' U: K; D
                GetPortVal(0x66,&Status,1);: }0 D- s& T/ J, C
                TimeOut --;
8 v; U, b9 l. g. u6 L; y, x//                Sleep(1);
9 i. n) k4 ]6 Q  u9 \        }while((Status & 2) ==2 && TimeOut>0);
% b, H+ h8 U' N6 m
# R! e; D7 r0 {) G; z) S1 U        SetPortVal(0x62,(DWORD)Data,1);
' x: g3 x& P4 ~. M0 @) |}
/ e) b( X( [, E% J; |' _unsigned char read62()( H. f( p7 O# `$ U. d+ ~, e
{
) ]  E! u8 m" j; X! d6 j: b        DWORD Status,Data,TimeOut=10000000;: h1 Z7 u6 y- U# e) }. I% l7 Q
        do' C+ J& B) H  \; @* q; d# G7 V
        {
0 p" L5 B! N7 j6 M3 F                GetPortVal(0x66,&Status,1);0 m$ A) r) W% I2 h6 r0 p& _/ [
                TimeOut --;3 `" X# o; |8 h5 `/ A
//                Sleep(1);' Q  m* V8 @. ^$ M: \$ S
        }while((Status & 1) ==0 && TimeOut>0);# T$ n5 l; X- a! t
# g% \3 O5 H) B( N. n* ?' u

; _9 }1 N7 Z! P$ P$ z7 t! B        GetPortVal(0x62,&Data,1);/ M/ L- }3 z2 P" @' m
        return (unsigned char)Data;
, c! Z! k# h/ m, |4 Z}3 K" D4 }$ Y& `8 S
unsigned char read_ec(unsigned char index)
4 G$ G% U9 Y; ]: N8 X{5 w; v0 U! Q' E4 N5 }* I& ~" \, J
        write66(0x80);
  M+ V1 t! g" N/ i: C6 }$ R7 G& F        write62(index);/ {: J9 E- J* h" T8 O( ^& V
        return read62();
) a  D1 j8 ^) f/ }# U}
# k  _' b3 j% I3 o* a+ A' U# v: ~/ m9 }% c: e- C
[ 本帖最后由 qdk0901 于 2010-2-9 10:58 编辑 ]
回复

使用道具 举报

发表于 2010-2-9 16:41:22 | 显示全部楼层
HardwareEditor.zip (782.25 KB, 下载次数: 1904) 楼上的有没有发现用你的方式后出现的两种异象,你的while等待EC IBE/OBF的动作是永远退出不了的。都是因为timeout超过了你设定的值才退出来的。那是因为中断优先的缘故,每次你用这种方式读写EC其实首先读写的不是你的AP而是OS的ACPIEC Driver。你读到或者写入的值只不过是OS ACPI读到或者写入后在EC Data port留下来的值。另外你有没有发现OS的错误报告里面一直在报告ACPI错误,因为OS被迫在没有与BIOS同步的情况下对EC做读写。OS读到的数据也当作无用的data忽略掉的。
1 {1 D% R7 I* [* m, f  如果一定要不disable SCI在ACPI OS读写EC那你完全没有必要再去判断EC IBE/OBE了,完全没有意义。
, ^7 ]! N4 D8 h+ _$ x) G; a, `! N+ I5 f
[ 本帖最后由 Faintsnow 于 2010-2-9 16:44 编辑 ]

HE

HE
回复

使用道具 举报

发表于 2010-2-9 16:56:18 | 显示全部楼层
原帖由 海陆空 于 2010-2-6 19:40 发表 + @, |& Q6 C  v! M$ P3 o& t0 N5 ^

# g8 B2 Z" M) V( Y- o) K( C6 _  Z& I; V# k
您能讲讲怎么disable SCI啊?然后又怎样呢?谢谢
, j* q2 l9 V$ s
/ h# J  b$ _* e, A' h$ z5 G4 E
1. Find out the APIC address (you may looking it in ACPI APIC table), usually 0xFEC00000,
& s$ {' Y0 Y8 l: }
2 @' ]& h& S4 _3 _0 F1 C2. Find out SCI IRQ number (you may looking it in ACPI FACP table), usually IRQ9.
5 ]& N" Q. \# C' c2 m  H6 A' Q& h" s- n! q+ v  Q
3. Then set bit16 of the IRQ to disable it.
6 |, ~. s$ Y$ Y( `( k: [, j# p8 c: t# P3 v: `7 {2 i
    a.. Offset = IRQ# * 2 + 0x10;/ T: y8 O% w* |- c1 ]9 A; f+ D' Q5 D
) a+ r- L8 S0 Y% u! d  U0 [% T
    b. Write Offset to APIC base,
. V* B0 B$ S$ g+ }1 R# L* @( B1 t6 u/ j# U0 e, N* Q
    c. Read Data from APIC base + 0x10;# L1 x1 P9 w9 s" w+ \

# E" l, ]  K  a+ o6 H    d. Or bit16 to Data;
2 \( h3 p5 t9 p" ^2 L7 o
, x( b# Z8 y) u5 @+ Y5 j9 K    e. Write Data back to APIC base + 0x10;
  E  B* ^9 R$ N3 L& j2 D4 r" j2 |9 C0 ]2 f8 G5 y. a1 Z$ k
2 C, c% f* P5 t: O- s: g9 o4 j- h

4 T  h: ^9 w8 f$ @9 }! _' |) [) PYou need to check APIC spec for details.
回复

使用道具 举报

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

8 \, g. Q( k2 H" F; Q( S: s8 G* h, V% \! N( b' t. \
如果一定要不disable SCI在ACPI OS读写EC那你完全没有必要再去判断EC IBE/OBE了,完全没有意义。7 \! I4 H; v( z; v5 W+ D" ]5 u
==============================================
$ \1 e& J2 a: d; P& S$ ~4 ~5 F 事实上却是有数据错误,但是说不判断IBE OBF,那就有问题了。
/ q7 {. `: e$ p. Z5 C* h# I. I$ c6 Q& D) V
因为OS去读写62/66 port并不是很频繁(至少我们的平台如此),因此有几个错误的值我们可以容忍的,而且错误的值基本是固定的某个值(就是某个Q Event的id)
% }$ K. V' x2 e+ P0 F但是如果不判断IBE或者OBF,连自己的数据都不知道是什么时候ready的了。9 e( r) I0 y. \& K- {; F7 w
3 t3 w6 k7 t! s1 I
因为只是用了做些简单的测试工具,所以这样的错误是可以容忍的。: C' U! J' l3 q1 L
当然正规的做法当然是要禁用SCI
回复

使用道具 举报

发表于 2010-2-9 18:07:46 | 显示全部楼层
我想说两个地方:" I3 D6 }8 `% L/ Z4 d
1、ACPI OS去读写EC Space时,一般情况下EC会用一个SCI去响应OS读或写的每一步细分操作。
  r/ i) }% p2 u* n/ G9 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-10-12 08:48 , Processed in 0.078318 second(s), 19 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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