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

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

[复制链接]
发表于 2010-2-6 04:55:26 | 显示全部楼层 |阅读模式
#include <iostream>
- K! b" s2 D/ m) D4 E& r% ?#include <Windows.h>$ r) C* b! k8 |' p$ Q+ w: x
#include "WinIo.h"$ Z4 v  B6 ~3 x: ]
using namespace std;) P) s0 W9 i% ], k# s

0 @" {3 c) x0 C1 D& {( i#pragma comment(lib, "winio.lib"), m: `- l$ G! W
/ \0 M: B9 ]  F7 r9 J; ?) g

, m4 Q5 ?7 s0 sint PMU_SC                =        0x6C;//命令端口+ \6 X0 j4 i, d( B' x
int PMU_DATA                =        0x68;//数据端口
$ {! O9 e# f7 v$ O9 S. m3 l% X; qint RD_EC_SMI                =        0x80;//读寄存器命令; y% w1 u7 o: d3 s
int POLLING_DATA                =        0xE7;//CPU温度寄存器号
. n6 {7 r5 r" p9 N8 u& `( x
8 O% P' s7 b( qDWORD dwTemp = 0;
3 G3 {- Q8 I' |5 I! j8 u# |2 @) v' o4 Y7 Z
void PMU_Wait4IBE(DWORD *_value);
" m  W0 d3 x) ivoid PMU_Wait4OBF(DWORD *_value);3 p+ k- s5 B/ n4 {9 t

! t+ s0 _5 I4 r' p& U+ Q2 p: v. ]* y/ w- |$ j* H
int main(int argc, char* argv[])2 M; L8 s6 p) v
{/ X' d/ f* L, Z) {5 i
        if(InitializeWinIo()==false)cout << "驱动程序加载失败! " << endl;
- Z# P# k) j# z( G. L" [' ^- ~& W) q
       
. f* u0 k4 l0 A- t9 {        //1、mov            dx,PMU_SC                //
$ c% I0 D: P3 w& z        //2、mov            al,RD_EC_SMI        //
, m6 `# k, E2 i! `7 ~        //3、call           pmuWait4IBE                //Must  have   输入缓冲为空吗,为空可以放命令了
% P, E/ f7 K1 D, M: G2 H" e        //4、out            dx,al                        //将读寄存器命令放到命令端口中。
. X: z* ^) R$ e( z1 a- W6 g& s& M/ e- _* f) F" K2 O$ g# h
        PMU_Wait4IBE(&dwTemp);& o7 }2 e  @6 }/ p% _
       
+ H) L( p: D( j3 {  d( _- y* p" K        SetPortVal(PMU_SC, RD_EC_SMI, 1);  Z* U& j7 I% X3 A3 S2 V. H2 M3 S

- c8 @2 @1 P- C3 u        PMU_Wait4IBE(&dwTemp);
/ A  V$ C$ z5 e. o9 n        * H- e3 g& ]8 i5 O
        SetPortVal(PMU_DATA, POLLING_DATA, 1);
9 E" M' U& u) q; U$ m7 ~* Z0 b# A8 F$ |2 \8 U7 t- l2 Q
        PMU_Wait4IBE(&dwTemp);
, f% C! N! Y9 Z+ T* b. K4 H* u- V: V1 a) l5 b( \8 o4 s9 [
        cout << dwTemp << endl;               
3 W3 T2 m3 B; T
$ z& ^* l8 x( z/ K. X9 |& [        ShutdownWinIo();
) e- w% P4 M/ s: d; W1 e- n# X- \0 z+ u8 V. {
        system("pause");
2 y7 l; X7 C$ Q( n, c
4 j* l& u6 y: d  O2 m        return 0;6 O$ h' T6 \9 ~/ @
}! U( q. M4 ?- t
& A; P3 M9 y7 j  K
void PMU_Wait4IBE(DWORD *_value)
5 W3 E; z0 M! M5 V7 ~{
8 P9 |( L/ f# s4 E& k- j1 j        //#########################################################   4 v0 J2 q  |& [) h5 c& H4 q
        /*2 @5 f5 Z, s. ^0 c0 n) M
        pmuWait4IBE proc   3 j, r  K4 g. ^1 _
        PUSH        AX   * ?0 e* |6 E  j$ _2 C- h
        PW4IBE:               
0 U0 }0 d& [, i  Z        IN          AL,  06CH                                //Read  PMU  status   / v; c% }( R& k  @0 a
        TEST        AL,  2                                        //Is  Input  Buffer  Empty?   
2 s( Z8 L5 a8 ^5 ?) `1 I        JNZ         PW4IBE                                        //Jmp  if  no   
% T# ]# n( N2 N$ K/ c. S1 Y% s        POP         AX   - |, v8 D. P. E: w2 f  k: _6 ]
        ret   # a# c- @# f  m( Q
        pmuWait4IBE        endp                                        //END  OF  PMUWAIT4IBE
2 l5 r, Q1 G) U3 @, v) k) v        *///循环读取0x6c端口的数据,看是否为空,不为空则一直等待其为空
8 \- I% F7 x% T        //######################################################### 3 _! w$ @  t. e% @% I9 S+ ]8 S
        /*do & h: {9 I5 }3 s/ m, s
        {
$ v. c$ P( c7 |; z6 J! U                GetPortVal(PMU_SC, _value, 4);% `: y5 g( J+ s; d# b) E
        }
* k) @; T' p/ k' }. a9 X5 A5 S        while ( *(_value) & 0x00000001 );*/0 w0 e! J1 G3 y, n+ [) U" @
        DWORD   dwRegVal=0;
* }! @' D1 r# ?8 ?) ^# ?        do. k2 L7 }% J: a
        {  + K) A( p3 s" _  \9 }- y8 V) A
                GetPortVal(PMU_SC,&dwRegVal,1);1 n2 G, V6 l' L* l5 R3 S# ~- F
        }+ P* `" Q* j4 M% U; I) G5 C1 I
        while(dwRegVal!=0x2);, a, e8 U/ `0 L: P5 q3 ]4 q

* Y, }# E- O; ^7 p}6 F  M+ ^/ H$ I2 M4 f

& y) S. e- n4 y) R以上是我在google了csdn还有有一些其他网站后写成这样了。但是使用getportval得到pmu_sc的值永远都不能等于2。& L, f) n% l4 S- `
所以变成了死循环了。
) T  \5 G% m' V  i
: B& n4 r7 V9 v我对硬件编程不懂。又不知道从何下手。
% q- U# g- a: ]( P我自己按照amd和intel的cpuid pdf文档写了读取cpu基本信息的小东东。希望可以把cpu的温度也给搞出来,当然更好的是能把bios也解决了。
/ B" X) g5 V* M但是这个温度已经搞了2天了,无果。很是郁闷。实在没办法了。2 ]  G' A2 r  t
9 L% o8 ~" x7 Z5 r# x# H: m
我就想知道如果我想写个类似于everest这样的监控软件我需要搞清楚些什么? 或者简单点,我怎么才能把cpu的实时温度,硬盘温度,笔记本电池的信息给搞出来。
& `9 t: p' k$ M6 ^/ Z并且我需要最后软件可以运行在x86和x64的系统上,因为我的笔记本是win 7 64bit的。% j1 z9 k  b2 U+ ~+ ?/ q
$ E9 _! o% w+ _' m
感觉现在无从下手。我在网上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.但是你这样做法应该是读不到的。
0 J0 z1 U& H2 H7 n' z8 S* s7 p; b1.OS会使用 80h RD_EC ACPI CMD 读ACPI EC,可能会冲突,如果一定要这样做,我所知道的办法就是先Disable SCI-读ACPIEC-Enable SCI,不过这种做法也不是适合所有Notebook.% o; {& C4 F( @3 n( S, U* Q) N0 t
2.0x6C/0x68不适合所有Notebook.EC到底使用哪个Port?.一般是使用0x66/0x62,但是0x66/0x62已经被OS使用了,会冲突8 c7 \7 o. P/ S6 A, a+ F1 H8 U. R
3.不是所有ODM的CPU temp是放在ACPI ECRAM的0x00E7处的.
3 `" A: U, @8 ~/ ]0 z4 c* U3 B  y7 e- |; O3 G
所以.....呵呵
回复

使用道具 举报

 楼主| 发表于 2010-2-6 19:18:05 | 显示全部楼层
按照楼上的说法就是这样做的可行性不好。而且存在端口的变化分歧性。: H, ?( v7 x: @' L2 X) J7 ?
# C. V0 i: c! L- F4 T, a
那么有些什么可行的办法呢?  L7 Q1 s) e- e6 ^
为什么类似于everest这样的软件可以识别目前几乎所有的主流机型的温度呢?而且它称这部分为传感器。在里面不止是cpu的温度。还有其他的设备。1 b. r' C5 k3 l- p% H7 A2 V
! y* h/ Q2 k* {6 S3 B+ v
它的做法是为其建立数据库吗?通过不同的特征采用不同的方式或者端口吗?
5 g( F3 N; F$ K# B* }+ b
* \) R7 Q( f9 P% @8 B那ACPI里面有cpu的温度吗?如果有,我需要怎样才能从这方面下手啊?有些什么值得推荐的书籍吗?
回复

使用道具 举报

 楼主| 发表于 2010-2-6 19:21:42 | 显示全部楼层
http://www.ufoit.com/bbs/viewthread.php?tid=4209 J/ J% N( q. z5 K/ @. `

6 z3 ]- H# @: b" \7 ]" y+ |http://www.ufoit.com/bbs/viewthread.php?tid=4527 `0 z; e5 i# O: w
2 q7 ]% V) Y/ c9 l
http://www.ufoit.com/bbs/viewthread.php?tid=241
: E. b" E9 R- J% z- F+ F" N* F
8 G. W4 H5 H  j, M1 d" C: G看来得先从这些地方看看了。谢谢楼上两位的回答。
回复

使用道具 举报

 楼主| 发表于 2010-2-6 19:26:00 | 显示全部楼层
那你的问题,说起来,跟ACPI是没多少关系,但用ACPI的方法,也是会让系统最稳定,也是最适合用acpi windows程序开发,如低难度的就是WMI ACPI,见DDK中带的WMI-ACPI白皮书。API可以获取电池,CPU,等相关信息的。驱动,你可以建立自己的pnp device驱动来获取,如仅仅是EC里的数据,何必呢,用IO读写就可以,只要你知道如何读EC的space。予人鱼,不好呀,渔才好。
$ Q4 t, `' ?3 L/ f4 W8 F, c" Q0 R
% o9 G0 ~7 m+ S! [- r1、其中WMI-ACPI最简单,但是BIOS得配合,推荐。
; Y2 `9 W/ w2 }% ^, Q$ {2 E- L5 i2、Driver最复杂,也需要BIOS配合,推荐。# m& W' r+ k: ]- ?1 y& C3 `* S1 F
3、Windows API只能获取到特定信息,不需要特定的BIOS配合。; h% g' u9 y& r8 p! B3 F
4、IO的方法,能获取到全部的EC状态信息,需要EC的文档,如果是给for end user,要出货的程序,这种方式不推荐。
. q) l& I& P9 K' k你可以混合使用。. H+ }2 Z, \! Z+ S9 s

2 z- ?( {) }) L4 q* f===============================================================( z+ i8 W/ D9 m8 l' o8 J  C
管理员的这句话:
5 u, y0 q: K& K8 ?! W如仅仅是EC里的数据,何必呢,用IO读写就可以,只要你知道如何读EC的space。” 如何理解啊?0 u0 \" F; x) q- w' R2 M
; S' [0 ~7 A- M
予人鱼,不好呀,渔才好。”这句话又怎么理解啊?呵呵
; s( d) K4 k( a+ t3 v3 i) n6 q
) k* `' y: Q$ M+ s3 h3 a' S另外,居然复制一下有那么多扰乱字符,太万恶了!呵呵!
回复

使用道具 举报

 楼主| 发表于 2010-2-6 19:38:10 | 显示全部楼层
http://www.ufoit.com/bbs/viewthread.php?tid=269
2 C6 K. M- h4 U  Y2 p4 a1 D* {4 ^
! {2 X2 s. C3 ~这个帖子看了后,感到迷茫了。BIOS我知道是就basic input output system。EC是什么东东啊?, e2 e* o1 O& y* f
* y: y  {7 K7 `0 S2 }
还有就是在里面又找到了个链接是管理员大人,小斌斌发的呵呵。
6 A8 |! F, s6 Y  ]% D* K! V) s里面谈到了要用DDK。我对这个完全没有接触过,我猜应该是driver dev kit吧。不过我要去下什么样的版本呢?
& X8 N# k8 _' l, B, |
" K5 x+ V! g# T$ G; o我目钱开发的系统是win32 xp sp2,ide 是vc 2005。
回复

使用道具 举报

 楼主| 发表于 2010-2-6 19:40:28 | 显示全部楼层
原帖由 Faintsnow 于 2010-2-6 14:58 发表
& S  y9 Q2 R- l: k, Q! m. g% A% S你这种办法应该指的是EC CPU Temp值存放在ACPI ECRAM的offset 00E7h.但是你这样做法应该是读不到的。
+ h4 p3 I6 ^9 S  K+ X1.OS会使用 80h RD_EC ACPI CMD 读ACPI EC,可能会冲突,如果一定要这样做,我所知道的办法就是先Disable SCI-读ACP ...

+ x, e/ ?( k7 j/ I9 I. P
2 u; z  L, w6 g# t' @& J# i. J4 A您能讲讲怎么disable SCI啊?然后又怎样呢?谢谢
回复

使用道具 举报

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

使用道具 举报

发表于 2010-2-9 10:55:59 | 显示全部楼层
不用禁用什么SCI的,有是有冲突,不过马马虎虎还能用。过滤掉异常值就行了。
. ]& O" J; x7 r- n
: m9 L6 o' Z  A% g: h" {* q# U$ Gvoid write66(unsigned char Data)
! u0 e- V; u* G{, \+ ?8 d2 G4 T4 m& _' S5 [9 q0 s
        DWORD Status,TimeOut=10000000;# R' ~  S6 N0 R# I
        do) e  Y4 i, f+ _
        {' ^; G# n2 E. [2 X" n
                GetPortVal(0x66,&Status,1);
+ X# i6 [7 `; @5 g2 o8 u, D( n0 h" H                TimeOut --;
* U2 u3 y8 P: z: I- g* {8 y//                Sleep(1);
$ ~) A/ c: @9 F- S' l5 d7 t8 ^8 s        }while((Status & 2) ==2 && TimeOut>0);
4 ?2 Y! _- a* [/ I, X
- N6 a: }* }0 w$ W) [) K# j, z        SetPortVal(0x66,(DWORD)Data,1);  _  P8 l- I" ^3 U' E( K
}1 P& @- i  d; ^3 {& J- G8 g
void write62(unsigned char Data)/ [3 \$ X0 R- |! `' i
{
0 s) z3 A+ g8 J  S        DWORD Status,TimeOut=10000000;
' Z: m: ?5 P/ g9 m) o1 Z        do8 h/ Y+ E) ]( Z( x, y: A8 m
        {
4 w* M# x5 s. C9 c                GetPortVal(0x66,&Status,1);
2 S* t# h8 T/ M" X, K                TimeOut --;; ~" y" `* i: L3 C9 `; X
//                Sleep(1);
. j6 c. D) x3 A7 l        }while((Status & 2) ==2 && TimeOut>0);
4 ^- S' i$ O) o
- l7 j% |: d& w8 O        SetPortVal(0x62,(DWORD)Data,1);1 ]4 S# O; Z* d/ P
}
8 I$ [4 i+ l9 y* ^9 ?9 Iunsigned char read62()# G+ K1 g# r/ M# G) W) C+ F
{
" ^$ f  j+ a# K) Y/ r4 F8 j5 x0 Y        DWORD Status,Data,TimeOut=10000000;
* F6 J7 r% u" @, ?' l2 J, M        do6 e  G- f: k9 L( T
        {3 J7 I( j: f1 |' z; p
                GetPortVal(0x66,&Status,1);, r: H+ w3 H' m0 X
                TimeOut --;" K4 K' |4 q6 U! h0 c
//                Sleep(1);* x9 i% y3 Z3 Y1 ~' g9 q0 w3 I
        }while((Status & 1) ==0 && TimeOut>0);* v' f* w! E; {" H0 `9 t* k$ g* M8 @

& Y/ q. x3 n% J; P. j  r; L
; F6 c; [* p) C1 `' }        GetPortVal(0x62,&Data,1);, k2 S6 D- K) i+ z( j
        return (unsigned char)Data;) c- r7 n# G4 o7 s, j0 |7 q; ]: Y( M$ C
}
. n8 j# @( q6 O) i8 u0 d7 h1 g. sunsigned char read_ec(unsigned char index)
1 ?* C3 t+ D6 O4 ~. W. Q{9 M) J  D8 i% Y4 b6 c, o% ?" p
        write66(0x80);
" a. |' `+ V# T; A& {; ~8 O        write62(index);) c( @( Z0 u4 j( U; x1 Y1 Q' z
        return read62();- }% E9 u7 m+ X. ]8 D' F
}
" u9 I# V) |. D$ q$ o6 [5 D+ i3 I3 K5 s' u
[ 本帖最后由 qdk0901 于 2010-2-9 10:58 编辑 ]
回复

使用道具 举报

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

HE

HE
回复

使用道具 举报

发表于 2010-2-9 16:56:18 | 显示全部楼层
原帖由 海陆空 于 2010-2-6 19:40 发表
6 N* U( y4 J: _* X4 x, G- n7 H: X2 J/ z
( m/ y6 \! S# Q! I8 W' h
您能讲讲怎么disable SCI啊?然后又怎样呢?谢谢

& A+ n7 [" ~9 Y; [1 }  w! D" I( w2 L
1. Find out the APIC address (you may looking it in ACPI APIC table), usually 0xFEC00000,# _; w3 v$ V7 \3 f, Q# m1 I$ b# a
- O& D6 }0 z: b* e  q* _
2. Find out SCI IRQ number (you may looking it in ACPI FACP table), usually IRQ9.  L& n4 m% I0 @0 R  M

9 ?( Y- D; r; T, P. H2 M+ F& @3. Then set bit16 of the IRQ to disable it.
3 K% P- l: s7 S7 F- H
( g1 I) G! F" [" J) q" ~    a.. Offset = IRQ# * 2 + 0x10;
* l! ]2 b* ^- _
' J# _  F% J1 k" I5 G' Q    b. Write Offset to APIC base,7 |9 [) `9 n# n8 Z( j. C

( h: T+ R1 H6 y) l, f, Q% [    c. Read Data from APIC base + 0x10;! Z- O( @) x6 h. u. [3 N: H, F6 V( N
3 B+ n, \" ^- Q- Q# f' i
    d. Or bit16 to Data;
9 C+ ]+ I7 `! T9 i
3 X. f/ F2 t( l( ?& A6 [    e. Write Data back to APIC base + 0x10;9 N( y$ u4 t" g) D

7 S% S5 I" s' u
0 d3 P. ^% M$ v3 P2 ]2 Q' H: I# D% a( @  e0 W
You need to check APIC spec for details.
回复

使用道具 举报

发表于 2010-2-9 17:51:44 | 显示全部楼层
原帖由 Faintsnow 于 2010-2-9 16:41 发表 & U# x* L0 H1 g4 P- z, h
545楼上的有没有发现用你的方式后出现的两种异象,你的while等待EC IBE/OBF的动作是永远退出不了的。都是因为timeout超过了你设定的值才退出来的。那是因为中断优先的缘故,每次你用这种方式读写EC其实首先读写的不是你 ...
: e. ?6 T3 @' t1 {
* n4 z% x& R: N# h. h
如果一定要不disable SCI在ACPI OS读写EC那你完全没有必要再去判断EC IBE/OBE了,完全没有意义。
# }4 Z- M  \. T# \) X' `==============================================
% P( r% M/ i8 k( j, y+ a7 r 事实上却是有数据错误,但是说不判断IBE OBF,那就有问题了。! w+ [+ m, G. {' y
$ ~* ~3 H: t/ z7 q  D8 A
因为OS去读写62/66 port并不是很频繁(至少我们的平台如此),因此有几个错误的值我们可以容忍的,而且错误的值基本是固定的某个值(就是某个Q Event的id)
9 h# k- a. X+ k- n& k" Y  [但是如果不判断IBE或者OBF,连自己的数据都不知道是什么时候ready的了。
* v8 m( o8 W, q. m, @7 |* X' m4 Y$ ^6 ]: J# m
因为只是用了做些简单的测试工具,所以这样的错误是可以容忍的。# b; k% c6 i. v, v
当然正规的做法当然是要禁用SCI
回复

使用道具 举报

发表于 2010-2-9 18:07:46 | 显示全部楼层
我想说两个地方:/ A. {8 W* e5 e: U& G4 ]1 l3 S$ E
1、ACPI OS去读写EC Space时,一般情况下EC会用一个SCI去响应OS读或写的每一步细分操作。
7 F# K% o$ V/ t5 b: q6 o$ d+ n2、新手不要把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-4-4 16:20 , Processed in 0.080419 second(s), 20 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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