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

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

[复制链接]
发表于 2010-2-6 04:55:26 | 显示全部楼层 |阅读模式
#include <iostream>
4 E+ c/ g1 e$ O* l+ T. m( w#include <Windows.h>; \# w3 F3 q, q# z
#include "WinIo.h"% ^% ~: X/ C7 }4 A# q( t6 T3 v2 o
using namespace std;
5 m8 m5 U* k, l7 T8 N, _1 {  F5 J( c& B6 `; ~7 H: x0 P# ~2 p
#pragma comment(lib, "winio.lib"), g, U% Q$ E7 B2 p8 l

4 i. Y+ I4 k  c$ p0 w2 E# v
. O. y" G. i/ z9 y( y7 pint PMU_SC                =        0x6C;//命令端口" c) P' m7 }4 m; c" ?0 W* z
int PMU_DATA                =        0x68;//数据端口
( w, T' E, l3 I: J; Jint RD_EC_SMI                =        0x80;//读寄存器命令  s1 J: g4 ~/ s' y% L, D5 i1 c0 B: W
int POLLING_DATA                =        0xE7;//CPU温度寄存器号
  |" \/ d( {  `: \3 w- L: L7 \+ E* D  k8 p$ b
DWORD dwTemp = 0;9 s$ t; e$ F& O  u5 S5 b  ~

. ^, q: l$ L( S' e$ yvoid PMU_Wait4IBE(DWORD *_value);- g& O: Q8 p9 n
void PMU_Wait4OBF(DWORD *_value);
5 v- O7 f6 D7 _" B" m. }4 L4 k5 g/ Y* X

$ r4 U; l' Y# Y- ~: f+ v, H$ P1 _$ Dint main(int argc, char* argv[]), p6 o$ C- u! V9 C5 ^
{
# A5 V* A4 |* o' ]% X        if(InitializeWinIo()==false)cout << "驱动程序加载失败! " << endl;% z8 c$ q0 Y, i

6 a; I- D" a7 g/ T5 X& V4 p8 y8 |        , P2 p8 V' k% K! e0 Y
        //1、mov            dx,PMU_SC                //; s- z% K; D' k/ z
        //2、mov            al,RD_EC_SMI        //
, L" ~' K. u1 h        //3、call           pmuWait4IBE                //Must  have   输入缓冲为空吗,为空可以放命令了
$ m, {/ O- w0 ^2 `; p        //4、out            dx,al                        //将读寄存器命令放到命令端口中。
0 W$ h) t% F" L+ ^
# {. r) w! U# u1 w: U        PMU_Wait4IBE(&dwTemp);2 r7 Y; I0 K+ @0 S  R, p% e  u' X
        8 K3 x1 R, U9 u/ u* q
        SetPortVal(PMU_SC, RD_EC_SMI, 1);9 z6 p$ z  M- e. R' t

( M" M; @; e7 f, k7 ^        PMU_Wait4IBE(&dwTemp);
1 n. X! L+ i: U# d7 X- A9 P       
  u; [7 K9 P) q& I8 h        SetPortVal(PMU_DATA, POLLING_DATA, 1);
0 `* O/ V' k8 J; [  R9 W+ w/ J6 `# O+ @2 i$ ^! q4 m
        PMU_Wait4IBE(&dwTemp);) r% v9 s: |( u6 |+ p% \! Y
+ n' o, L: B, H1 F  |+ ~
        cout << dwTemp << endl;                . l+ f1 C% |1 N5 T
; q0 Q1 [5 [* Q/ D  B$ G' x
        ShutdownWinIo();; f4 N1 w: X, }7 M: w6 J: Z

# [4 c4 B- T! ^$ x        system("pause");
' H& f+ a5 [; x, a' W$ a$ t8 n0 C! N  T4 T# G
        return 0;
' c% r' a( D* D9 b* ^1 V1 _}3 R) B' q* M* t. `( ~7 F

7 [, S1 F% N) _. ovoid PMU_Wait4IBE(DWORD *_value)9 L  C& ^! q- b4 m8 U
{* C3 R$ D$ _2 y8 a' h
        //#########################################################   
, @# G" U7 Q. B# r7 d        /*& i/ t+ a2 _$ w' {& I
        pmuWait4IBE proc   
( n( l# J( C0 H9 h        PUSH        AX   3 i1 K  a3 J8 L0 t# U
        PW4IBE:               ; s; G" j+ u- I3 q2 q2 i, y
        IN          AL,  06CH                                //Read  PMU  status   
. N8 D- c; H) Z" u0 V        TEST        AL,  2                                        //Is  Input  Buffer  Empty?   1 O6 z4 W- P- m( v+ r' K0 `# \
        JNZ         PW4IBE                                        //Jmp  if  no   
- m. x3 G  k" D7 Y# `9 ^6 y        POP         AX   + m) A: c; p. V! K. T5 J8 t' ^) z4 F
        ret   
( s7 e( }" t6 k( k9 ?: Z0 o        pmuWait4IBE        endp                                        //END  OF  PMUWAIT4IBE; F. M0 B8 N0 `  r
        *///循环读取0x6c端口的数据,看是否为空,不为空则一直等待其为空7 f: r/ V8 n( d  n
        //#########################################################
! z9 _/ Z; F8 x$ h) b        /*do
2 N7 e& L$ b5 e2 ~        {) x! E0 R. s9 s( C( U
                GetPortVal(PMU_SC, _value, 4);6 ]( \" W5 G& K) K7 c
        }4 C$ F9 `: ~% V2 z$ V* u8 Y; o
        while ( *(_value) & 0x00000001 );*/
' _. @* {6 C- [) b+ s        DWORD   dwRegVal=0;
2 `8 _' i4 q/ @! \! y/ ]        do5 V1 D' V3 d1 V) A. P
        {  
5 s$ E: k/ ~- S1 A9 J                GetPortVal(PMU_SC,&dwRegVal,1);( _; \9 C( R, P/ J
        }
1 J+ t# q7 U5 ], R/ W2 U        while(dwRegVal!=0x2);
% E' p. N1 k: k' o0 l
. b2 U$ h, [$ a$ o* w}  @" S$ U1 K1 z$ X, p

, G4 N( v$ F+ `9 _* z) e以上是我在google了csdn还有有一些其他网站后写成这样了。但是使用getportval得到pmu_sc的值永远都不能等于2。
1 N5 G7 E/ ?  s4 S% S9 g. ^所以变成了死循环了。0 F# P9 q4 E; g0 G: A
$ S2 N4 \0 ?" L8 P0 }, V
我对硬件编程不懂。又不知道从何下手。
6 m/ X% t/ C+ a) K' K$ M我自己按照amd和intel的cpuid pdf文档写了读取cpu基本信息的小东东。希望可以把cpu的温度也给搞出来,当然更好的是能把bios也解决了。% \. u5 j1 b7 [! O; P
但是这个温度已经搞了2天了,无果。很是郁闷。实在没办法了。
2 a/ j) V& v2 U' s0 A3 V, ~1 p/ y; H+ C
我就想知道如果我想写个类似于everest这样的监控软件我需要搞清楚些什么? 或者简单点,我怎么才能把cpu的实时温度,硬盘温度,笔记本电池的信息给搞出来。
1 i' @' H0 L/ M$ H  b" S! t并且我需要最后软件可以运行在x86和x64的系统上,因为我的笔记本是win 7 64bit的。9 \7 @. C+ T" G$ J$ s" X3 O8 r$ _
7 y4 P! a- A( a+ j: Y8 {6 o- G
感觉现在无从下手。我在网上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.但是你这样做法应该是读不到的。
& p% l# r; z9 L9 Y3 A1 o$ @1.OS会使用 80h RD_EC ACPI CMD 读ACPI EC,可能会冲突,如果一定要这样做,我所知道的办法就是先Disable SCI-读ACPIEC-Enable SCI,不过这种做法也不是适合所有Notebook.9 [4 L) f4 ]& l5 t
2.0x6C/0x68不适合所有Notebook.EC到底使用哪个Port?.一般是使用0x66/0x62,但是0x66/0x62已经被OS使用了,会冲突6 C5 j( c8 L% p2 y$ {! }/ P+ P
3.不是所有ODM的CPU temp是放在ACPI ECRAM的0x00E7处的.% m. i$ s: P/ t3 k
3 W$ n  W: `0 ?3 \7 v* Z# }+ c
所以.....呵呵
回复

使用道具 举报

 楼主| 发表于 2010-2-6 19:18:05 | 显示全部楼层
按照楼上的说法就是这样做的可行性不好。而且存在端口的变化分歧性。" ^/ R3 L/ f7 [! {+ j

7 V" P( b( R! z9 ?+ d那么有些什么可行的办法呢?$ _8 N' J  v; ~) V* P
为什么类似于everest这样的软件可以识别目前几乎所有的主流机型的温度呢?而且它称这部分为传感器。在里面不止是cpu的温度。还有其他的设备。, I+ G: j$ I# ]4 n5 E* v7 X. J
/ h8 Y" i% H6 J# R) |7 ~; O: s
它的做法是为其建立数据库吗?通过不同的特征采用不同的方式或者端口吗?& J, {- S+ C$ I. t3 K' `
8 j6 ^( s& ~/ G4 b3 i
那ACPI里面有cpu的温度吗?如果有,我需要怎样才能从这方面下手啊?有些什么值得推荐的书籍吗?
回复

使用道具 举报

 楼主| 发表于 2010-2-6 19:21:42 | 显示全部楼层
http://www.ufoit.com/bbs/viewthread.php?tid=420
6 V+ ^1 }1 m3 ~8 x0 E8 F5 x% t- p1 _1 K& a- E3 c' M/ b2 F# s
http://www.ufoit.com/bbs/viewthread.php?tid=452
- e! ^0 V1 D$ n1 z/ g+ S! `  @
4 j/ Y/ q$ O0 M+ @+ o8 khttp://www.ufoit.com/bbs/viewthread.php?tid=241
9 ^6 |+ b5 F+ |8 n+ r0 g0 l# M- @6 B4 j) ]" S" a' M9 u) q
看来得先从这些地方看看了。谢谢楼上两位的回答。
回复

使用道具 举报

 楼主| 发表于 2010-2-6 19:26:00 | 显示全部楼层
那你的问题,说起来,跟ACPI是没多少关系,但用ACPI的方法,也是会让系统最稳定,也是最适合用acpi windows程序开发,如低难度的就是WMI ACPI,见DDK中带的WMI-ACPI白皮书。API可以获取电池,CPU,等相关信息的。驱动,你可以建立自己的pnp device驱动来获取,如仅仅是EC里的数据,何必呢,用IO读写就可以,只要你知道如何读EC的space。予人鱼,不好呀,渔才好。3 n, b+ a' K6 }, s2 O/ f
6 x7 W2 }6 V! l6 ]8 Z9 j4 h
1、其中WMI-ACPI最简单,但是BIOS得配合,推荐。7 i& D0 U$ g8 b
2、Driver最复杂,也需要BIOS配合,推荐。
% b9 j) c5 y/ y+ b5 G3、Windows API只能获取到特定信息,不需要特定的BIOS配合。8 Q' S  r. k$ z3 @% J- W
4、IO的方法,能获取到全部的EC状态信息,需要EC的文档,如果是给for end user,要出货的程序,这种方式不推荐。5 ]7 |% _: l! v' T: {; I
你可以混合使用。
! Y0 q( @/ Q$ F, Y( x; c5 i0 B; v4 j  C8 h% N1 s/ ]
===============================================================0 O6 G$ x* |' l
管理员的这句话:
3 U5 |* p9 d+ G& E: ?如仅仅是EC里的数据,何必呢,用IO读写就可以,只要你知道如何读EC的space。” 如何理解啊?
: u: T/ a: N$ b
6 I, {2 c$ Q! a予人鱼,不好呀,渔才好。”这句话又怎么理解啊?呵呵- p6 _- L, R, h

) w" X8 @% D6 _6 X8 D另外,居然复制一下有那么多扰乱字符,太万恶了!呵呵!
回复

使用道具 举报

 楼主| 发表于 2010-2-6 19:38:10 | 显示全部楼层
http://www.ufoit.com/bbs/viewthread.php?tid=269
5 r# G  T! t( H, h5 V. v/ E; H& F# |! g+ O- w" B9 @4 v9 Z) A+ m
这个帖子看了后,感到迷茫了。BIOS我知道是就basic input output system。EC是什么东东啊?
; r& h# ^) z* H' @
5 S% T0 ~7 I% d还有就是在里面又找到了个链接是管理员大人,小斌斌发的呵呵。( y# }& l. D# }# d% S7 B$ V; z
里面谈到了要用DDK。我对这个完全没有接触过,我猜应该是driver dev kit吧。不过我要去下什么样的版本呢?0 n- q! F& b7 m& @/ \
7 L1 _0 D9 i5 A2 P/ o# o
我目钱开发的系统是win32 xp sp2,ide 是vc 2005。
回复

使用道具 举报

 楼主| 发表于 2010-2-6 19:40:28 | 显示全部楼层
原帖由 Faintsnow 于 2010-2-6 14:58 发表
( G: ^+ m6 F0 X; j6 f9 W你这种办法应该指的是EC CPU Temp值存放在ACPI ECRAM的offset 00E7h.但是你这样做法应该是读不到的。" }8 |4 Z) i2 T3 J% G
1.OS会使用 80h RD_EC ACPI CMD 读ACPI EC,可能会冲突,如果一定要这样做,我所知道的办法就是先Disable SCI-读ACP ...

+ J9 z2 G1 A3 b8 m4 w* P1 ~  A( e/ _6 \* Y0 @! [+ |
您能讲讲怎么disable SCI啊?然后又怎样呢?谢谢
回复

使用道具 举报

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

使用道具 举报

发表于 2010-2-9 10:55:59 | 显示全部楼层
不用禁用什么SCI的,有是有冲突,不过马马虎虎还能用。过滤掉异常值就行了。9 a, J% {' ?# m) Z7 K

2 g# `8 G/ w/ `. G( x: _void write66(unsigned char Data)
& q" v2 c8 ?. M  c{
2 Q- _+ h1 p3 r        DWORD Status,TimeOut=10000000;) Y7 L% Y& y* J5 N+ h8 s- g4 e
        do
' M1 T5 G; M& f3 B/ x$ t! e        {5 W( {7 \6 J1 t5 f# g% O
                GetPortVal(0x66,&Status,1);
) [2 E6 ^5 `3 e                TimeOut --;9 T* l; v+ w" c5 I; t- p
//                Sleep(1);8 K+ _$ }* R. r* Y* i% R
        }while((Status & 2) ==2 && TimeOut>0);- r3 [( y, y7 W- Q0 S
/ B$ {" `( H# k& B
        SetPortVal(0x66,(DWORD)Data,1);
3 X2 T! R* Z, m- M}" @/ H% `5 m" f1 ~  V& C
void write62(unsigned char Data)
+ n) C! r3 g! o6 e1 T: z) [{
2 A) h9 d' d5 m& B        DWORD Status,TimeOut=10000000;+ ^* S: C* Y. T0 U! J3 z1 _
        do$ G' q8 R- D, g& `+ D
        {
; Z' K  L, k4 y8 u0 v                GetPortVal(0x66,&Status,1);
; W* ?! b$ {" C  R, P  c                TimeOut --;4 L% d/ q3 X/ O- y, k
//                Sleep(1);1 x8 {/ x% j8 Y' n, U
        }while((Status & 2) ==2 && TimeOut>0);
% c  y/ G8 ?) _3 A0 ?9 e- t
( Y6 t7 R+ R! W8 h# d9 W: z        SetPortVal(0x62,(DWORD)Data,1);- {9 F$ d5 O) ~! i, I
}
0 d" C! j" d1 Q. |1 C- R/ I1 p+ qunsigned char read62()% G& S& a& ?: |9 D: `$ |
{
1 z9 A* c* C+ P7 L& n& [: q        DWORD Status,Data,TimeOut=10000000;
$ \- k! q+ {1 i& Q        do9 {0 q; U4 Y4 z4 w- f
        {
' L' h. R8 M8 a, L                GetPortVal(0x66,&Status,1);
8 ?" ^: c1 g* Q9 ?: Y                TimeOut --;: X: l* K5 a7 j& G, {4 F; E+ P
//                Sleep(1);1 [/ Q7 a& l( {+ ?3 A, c
        }while((Status & 1) ==0 && TimeOut>0);
" F& A5 T1 ^7 c0 I6 Q, B& Z  N2 B2 m1 V; l0 o

  a; M" r+ C8 [' h9 j' Z6 W        GetPortVal(0x62,&Data,1);# @8 b+ O- I# E# [' U: ]+ Y0 ]3 R0 \3 }
        return (unsigned char)Data;
  H; v+ ?! W, `}
9 h7 Q! H) @0 X0 T) v( Uunsigned char read_ec(unsigned char index)" w' R2 E0 d4 E' y
{0 E+ X, @9 N( {" f% R/ k9 f* P
        write66(0x80);8 `4 V2 U- c( n- ]$ `
        write62(index);
0 R( ~4 a0 _# E% z! {        return read62();
4 }- _! G0 Q/ b) R- O9 w: T( ~}! P9 a5 ?* f$ v$ H' e( A
; G! a' {0 O# M1 L5 {# z* X
[ 本帖最后由 qdk0901 于 2010-2-9 10:58 编辑 ]
回复

使用道具 举报

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

HE

HE
回复

使用道具 举报

发表于 2010-2-9 16:56:18 | 显示全部楼层
原帖由 海陆空 于 2010-2-6 19:40 发表
& Z- i1 ^# r% r% d, E) y, F5 K$ S2 v3 l, K! I7 X& v
0 g" ~; O( [, V/ M
您能讲讲怎么disable SCI啊?然后又怎样呢?谢谢
0 O5 B8 e! i) H4 }! t% k: h
( L3 h/ k2 T) g+ t) @4 B# R
1. Find out the APIC address (you may looking it in ACPI APIC table), usually 0xFEC00000,) _) A3 ~! U6 ~0 S
# H2 y; _5 F$ L( f5 N% c, ]5 p
2. Find out SCI IRQ number (you may looking it in ACPI FACP table), usually IRQ9.
# r/ h0 F$ {% S; s
  |! ^4 W  y8 a/ V. @3. Then set bit16 of the IRQ to disable it.
# H3 |& S/ z; m8 X( \( s+ k
: V/ G+ U. s3 H    a.. Offset = IRQ# * 2 + 0x10;
7 e1 j& W# W( u1 Y% A8 o$ T$ V0 y( p. r7 \4 _8 w( Q- u
    b. Write Offset to APIC base,$ E$ `- @* _9 d+ _5 A) A

( k* |( {7 j& N* `2 Q    c. Read Data from APIC base + 0x10;
- ^" H" x! e2 B1 {& f: x
6 b- \, V+ C/ ~; {; q# Q3 w    d. Or bit16 to Data;
: i1 i: p; a6 G; |+ a: B9 \9 s# x
7 K2 Z6 X% k. f$ Y* v) K  j- r    e. Write Data back to APIC base + 0x10;8 h9 e" ~% B6 n7 B! v1 r
1 U. F! R6 y, ]9 y2 B! ]

. \  J; s, ~! R. |  Q5 ~) H
9 T4 x* P, U+ ^1 PYou need to check APIC spec for details.
回复

使用道具 举报

发表于 2010-2-9 17:51:44 | 显示全部楼层
原帖由 Faintsnow 于 2010-2-9 16:41 发表 & T& b* {1 i) [3 D8 k4 b5 B
545楼上的有没有发现用你的方式后出现的两种异象,你的while等待EC IBE/OBF的动作是永远退出不了的。都是因为timeout超过了你设定的值才退出来的。那是因为中断优先的缘故,每次你用这种方式读写EC其实首先读写的不是你 ...

0 x! d; o1 ~5 S5 |) _3 G; s9 E
. g' o2 @, [0 |8 X( M; A 如果一定要不disable SCI在ACPI OS读写EC那你完全没有必要再去判断EC IBE/OBE了,完全没有意义。- D6 I. j- }  t) J* n. [
==============================================
9 A# ]1 M" i! ?, k 事实上却是有数据错误,但是说不判断IBE OBF,那就有问题了。- Z# F* z: X6 x# I+ U
% N! D( T, |" Y' m  @+ Z* z2 A
因为OS去读写62/66 port并不是很频繁(至少我们的平台如此),因此有几个错误的值我们可以容忍的,而且错误的值基本是固定的某个值(就是某个Q Event的id)1 X' \# [/ }. i% j3 D6 S8 c
但是如果不判断IBE或者OBF,连自己的数据都不知道是什么时候ready的了。
. N9 L/ E" m( u/ Y" ~) @
1 _9 U* a/ R0 U因为只是用了做些简单的测试工具,所以这样的错误是可以容忍的。0 x4 P! ]* I6 r6 q2 N& e
当然正规的做法当然是要禁用SCI
回复

使用道具 举报

发表于 2010-2-9 18:07:46 | 显示全部楼层
我想说两个地方:  `) b/ n( b8 A1 q3 Z. O
1、ACPI OS去读写EC Space时,一般情况下EC会用一个SCI去响应OS读或写的每一步细分操作。, d# c9 l" E2 m" q
2、新手不要把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, 2025-6-16 12:45 , Processed in 0.038189 second(s), 20 queries .

Powered by Discuz! X3.5

© 2001-2023 Discuz! Team.

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