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

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

[复制链接]
发表于 2010-2-6 04:55:26 | 显示全部楼层 |阅读模式
#include <iostream>
, U" Z7 |# x* }3 H#include <Windows.h>( Z" g4 O9 [& T/ a( W! |
#include "WinIo.h"
) @& P/ B# X/ S8 L( lusing namespace std;2 m/ U8 z5 ?. `0 h% K7 R0 l" f
  r; b, a1 x+ @; M! a
#pragma comment(lib, "winio.lib")
; c4 Q% f9 K" U( b# H  H
9 G0 L( ^/ K* {1 a. _) `' B; x& t) ^) }( m) C1 d' Y+ v
int PMU_SC                =        0x6C;//命令端口
0 V2 ^7 ?/ V- h3 i# W: i  t5 ^- I% ~! ?3 ]int PMU_DATA                =        0x68;//数据端口2 n0 ?) P, e' b: w8 Z" b; c
int RD_EC_SMI                =        0x80;//读寄存器命令
) s& q$ s3 J+ G" e6 U* _int POLLING_DATA                =        0xE7;//CPU温度寄存器号4 u, W+ Q3 _( k; n: v
9 t6 w* t+ ?. R: h' F& ~; B
DWORD dwTemp = 0;
) Z8 }% j) Y7 R9 ~3 @. g/ U# R9 y( ^! r" E1 Y" g7 T
void PMU_Wait4IBE(DWORD *_value);
5 N7 v3 [( r3 `' Z% b5 E/ Mvoid PMU_Wait4OBF(DWORD *_value);! `4 ?0 K$ y  Q; g& w: c6 e+ E
: z, N! V# y4 Q1 H& W7 l

( L  E; u7 @  K  vint main(int argc, char* argv[])
6 G# ^/ M" a: ]* ^, M# @5 L" T6 S{
  S5 X0 o1 d( e        if(InitializeWinIo()==false)cout << "驱动程序加载失败! " << endl;" R  {* y# U& ~. t9 H

- J8 |1 r2 {$ J- I9 p$ `0 J        ! e; \/ }# F$ t% _) f9 g
        //1、mov            dx,PMU_SC                //
7 d. A0 d9 X8 a6 S% z8 l6 A        //2、mov            al,RD_EC_SMI        //+ L# h7 Z  G% @
        //3、call           pmuWait4IBE                //Must  have   输入缓冲为空吗,为空可以放命令了5 }8 V2 r7 k7 o: ?1 |
        //4、out            dx,al                        //将读寄存器命令放到命令端口中。# t& A( U1 f- j
, H3 j; |+ B% e4 Z4 X2 d2 l  i
        PMU_Wait4IBE(&dwTemp);! v5 n5 G& K4 @: C
        9 x+ ~% J; }9 a
        SetPortVal(PMU_SC, RD_EC_SMI, 1);3 k8 q2 ~3 Q3 n7 U( |! k
6 u+ G" `9 _4 p3 \+ V9 C9 u0 _8 P
        PMU_Wait4IBE(&dwTemp);) ~& M  I/ \- N5 M5 Q* G
        * U  f. Y" z, e$ S6 S
        SetPortVal(PMU_DATA, POLLING_DATA, 1);0 K; m7 K4 q) }: ^* `+ w0 V
& V7 p/ M/ u' o. G
        PMU_Wait4IBE(&dwTemp);
! ~2 W% T7 C' ~! X
; A( M2 f5 }; {  D        cout << dwTemp << endl;                ! ^9 r: D8 Q( g" G( {, K

; @! K7 y: f2 X, a8 u) F        ShutdownWinIo();5 c! l; u% F# X/ T* A) O( D

. n) |1 o5 _+ G- J6 G        system("pause");5 K' |! E2 Q. w, t/ `" A
& X4 Z) C' k/ ?- K  g
        return 0;
3 d" y7 Y# h" S9 B' N  k}
0 m4 [8 ]5 J' o% P
8 f5 g! L$ R+ A+ [1 l2 L; c; V" Tvoid PMU_Wait4IBE(DWORD *_value)
  M3 E' t( ?9 o; Q  w5 d- I{
, N6 O/ q' m- k2 o3 n  \4 y: o$ |        //#########################################################   
9 \; ]9 a( ]2 d- f4 S        /** u) \3 l8 [5 k1 a0 K
        pmuWait4IBE proc   
* L, |3 \% h/ x6 j        PUSH        AX   + o9 ?0 G/ @% q
        PW4IBE:               ! c; ~. |) K6 r( f
        IN          AL,  06CH                                //Read  PMU  status   # {; r' f# u  v" E0 s# e
        TEST        AL,  2                                        //Is  Input  Buffer  Empty?   
- q: q8 Z& t8 g& ^        JNZ         PW4IBE                                        //Jmp  if  no   - m' I4 E' j4 q3 _
        POP         AX   7 W  Z7 v' |5 P! y$ p# O
        ret   2 M/ i4 H8 u5 m8 X5 \  d
        pmuWait4IBE        endp                                        //END  OF  PMUWAIT4IBE' z# d- Y9 Q8 S* k
        *///循环读取0x6c端口的数据,看是否为空,不为空则一直等待其为空
4 d4 z1 F" ?1 x        //#########################################################
1 P, Z/ m5 U- Y        /*do
  |8 R! i/ |1 }) Z( g        {( ~" V+ u0 W4 I/ k6 y
                GetPortVal(PMU_SC, _value, 4);
  a1 s, y/ N, z  H5 R7 U        }
4 q, ~' O0 Z5 L; ]' Q        while ( *(_value) & 0x00000001 );*/
" l- E4 @- A" K* e% E. p" N        DWORD   dwRegVal=0;3 m" ^0 |# N) j) f
        do/ B5 ^2 a2 _3 r. E: W( M
        {  " U8 O9 D! [0 |6 F& q
                GetPortVal(PMU_SC,&dwRegVal,1);
8 e" u/ t2 ]6 |7 k        }! k6 R9 }$ Q. X: V& n6 r
        while(dwRegVal!=0x2);
6 }4 ^) Q5 W3 b4 Q# h
. U7 h) @5 V9 e$ k& T}
% Z! V5 P# K' q) C, N- n  @* i; ]/ L: E! Z
以上是我在google了csdn还有有一些其他网站后写成这样了。但是使用getportval得到pmu_sc的值永远都不能等于2。
, H. F* S, q4 h0 Y  ~; `* }所以变成了死循环了。* A" m1 @2 B, k' V# ?6 P6 n  j- {

; O( O* B8 M" [& Q2 o. r我对硬件编程不懂。又不知道从何下手。
+ @" _' F* R0 Z( @: X: }+ F9 E我自己按照amd和intel的cpuid pdf文档写了读取cpu基本信息的小东东。希望可以把cpu的温度也给搞出来,当然更好的是能把bios也解决了。) n4 O1 K" P8 x% M, e: B
但是这个温度已经搞了2天了,无果。很是郁闷。实在没办法了。- P+ H) z1 C/ M5 [

2 s4 G! ~" Q; D& [& x/ K" m我就想知道如果我想写个类似于everest这样的监控软件我需要搞清楚些什么? 或者简单点,我怎么才能把cpu的实时温度,硬盘温度,笔记本电池的信息给搞出来。9 Z1 C8 O7 n! L# E; a* ?
并且我需要最后软件可以运行在x86和x64的系统上,因为我的笔记本是win 7 64bit的。7 S; I- c& s: A4 z

# k% G: ~0 i. ]# M' s1 g0 y3 V6 B: [感觉现在无从下手。我在网上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.但是你这样做法应该是读不到的。: d: V1 V0 w4 L! @' g& k
1.OS会使用 80h RD_EC ACPI CMD 读ACPI EC,可能会冲突,如果一定要这样做,我所知道的办法就是先Disable SCI-读ACPIEC-Enable SCI,不过这种做法也不是适合所有Notebook.
( b! U- z! N* S$ N# W2.0x6C/0x68不适合所有Notebook.EC到底使用哪个Port?.一般是使用0x66/0x62,但是0x66/0x62已经被OS使用了,会冲突
, z# `% |& }1 X% ^- b& r2 N3.不是所有ODM的CPU temp是放在ACPI ECRAM的0x00E7处的.
0 h% @  K- D) |- ~0 Z% M) m
0 u& v1 h9 }& S1 N6 Z( K  c所以.....呵呵
回复

使用道具 举报

 楼主| 发表于 2010-2-6 19:18:05 | 显示全部楼层
按照楼上的说法就是这样做的可行性不好。而且存在端口的变化分歧性。$ |! D. h. D/ Z- p8 h; ?2 {

5 a8 O" _; I& k" l* j2 e% I3 d那么有些什么可行的办法呢?, M7 q3 k7 R! J
为什么类似于everest这样的软件可以识别目前几乎所有的主流机型的温度呢?而且它称这部分为传感器。在里面不止是cpu的温度。还有其他的设备。! x9 N) \4 F5 q5 ^2 H
$ O  r8 ~* Q& L% Y
它的做法是为其建立数据库吗?通过不同的特征采用不同的方式或者端口吗?
4 B: M" O+ m- d& ?) L: J& ^, L; F  L. T. V
那ACPI里面有cpu的温度吗?如果有,我需要怎样才能从这方面下手啊?有些什么值得推荐的书籍吗?
回复

使用道具 举报

 楼主| 发表于 2010-2-6 19:21:42 | 显示全部楼层
http://www.ufoit.com/bbs/viewthread.php?tid=420
8 W+ z* s8 h1 P8 W2 T2 O5 N- {5 e1 r/ x% i) x. q
http://www.ufoit.com/bbs/viewthread.php?tid=452
, a4 \- l" c: V5 k( x% B1 T  T! g1 y/ |/ h9 K# O
http://www.ufoit.com/bbs/viewthread.php?tid=241# z+ \! B$ Y6 c1 @

- ~1 F/ G- ]9 `- T6 w; r$ o, T看来得先从这些地方看看了。谢谢楼上两位的回答。
回复

使用道具 举报

 楼主| 发表于 2010-2-6 19:26:00 | 显示全部楼层
那你的问题,说起来,跟ACPI是没多少关系,但用ACPI的方法,也是会让系统最稳定,也是最适合用acpi windows程序开发,如低难度的就是WMI ACPI,见DDK中带的WMI-ACPI白皮书。API可以获取电池,CPU,等相关信息的。驱动,你可以建立自己的pnp device驱动来获取,如仅仅是EC里的数据,何必呢,用IO读写就可以,只要你知道如何读EC的space。予人鱼,不好呀,渔才好。
) @2 j  _+ J7 U7 V4 b3 ]2 Q5 i- r  j  x" Q+ Q# `8 x) e! P9 k9 G
1、其中WMI-ACPI最简单,但是BIOS得配合,推荐。
, w* `5 a& o+ _8 L0 C2、Driver最复杂,也需要BIOS配合,推荐。
- J% a4 E! O4 g; e. n% D) I  C+ J' }3、Windows API只能获取到特定信息,不需要特定的BIOS配合。
" M0 m3 \- L, c, k- ^* j+ R* C4、IO的方法,能获取到全部的EC状态信息,需要EC的文档,如果是给for end user,要出货的程序,这种方式不推荐。
% ^' o, M, t: f, I4 k你可以混合使用。4 h1 J! L2 k1 N+ \  {7 ~! q! i

1 C8 a( t( K$ ]7 O" m" I===============================================================
( P! h  v9 E: `, V0 E管理员的这句话:
! p" H) r' d# \! y' j9 q1 p" ?如仅仅是EC里的数据,何必呢,用IO读写就可以,只要你知道如何读EC的space。” 如何理解啊?
: [( a3 |% Z; `8 ^3 o7 g % ~' B" c/ Y) X: r
予人鱼,不好呀,渔才好。”这句话又怎么理解啊?呵呵
4 J5 ^9 G% b5 w: s. b9 T. W0 E; g
+ c) `9 h5 }- t2 a另外,居然复制一下有那么多扰乱字符,太万恶了!呵呵!
回复

使用道具 举报

 楼主| 发表于 2010-2-6 19:38:10 | 显示全部楼层
http://www.ufoit.com/bbs/viewthread.php?tid=269: S' k* |2 i* o: A
, f' {" W/ B: M7 {
这个帖子看了后,感到迷茫了。BIOS我知道是就basic input output system。EC是什么东东啊?
: `; r0 A) u, e- V6 ^
1 c2 K, d( `8 u: ~还有就是在里面又找到了个链接是管理员大人,小斌斌发的呵呵。. o2 C2 {# w& S
里面谈到了要用DDK。我对这个完全没有接触过,我猜应该是driver dev kit吧。不过我要去下什么样的版本呢?; w' {2 P3 _1 z

3 g' ]. D2 i! m& D6 O8 q0 _- `我目钱开发的系统是win32 xp sp2,ide 是vc 2005。
回复

使用道具 举报

 楼主| 发表于 2010-2-6 19:40:28 | 显示全部楼层
原帖由 Faintsnow 于 2010-2-6 14:58 发表 . O( ?# c, r' p) d, `
你这种办法应该指的是EC CPU Temp值存放在ACPI ECRAM的offset 00E7h.但是你这样做法应该是读不到的。9 {% k0 l0 g# }9 n
1.OS会使用 80h RD_EC ACPI CMD 读ACPI EC,可能会冲突,如果一定要这样做,我所知道的办法就是先Disable SCI-读ACP ...

: E" j" R5 j& z: x$ O+ l; z' y! q/ e5 `/ v
您能讲讲怎么disable SCI啊?然后又怎样呢?谢谢
回复

使用道具 举报

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

使用道具 举报

发表于 2010-2-9 10:55:59 | 显示全部楼层
不用禁用什么SCI的,有是有冲突,不过马马虎虎还能用。过滤掉异常值就行了。) s6 f: J$ {7 [1 t2 Y7 N( ?

6 b; F& B" A  X& ^* |void write66(unsigned char Data)
. f/ n! q5 c6 U& T/ k{/ \9 @/ Y# n1 {5 U; |( m
        DWORD Status,TimeOut=10000000;
+ h/ s1 W" w3 x) O, Z        do' ]1 b+ F/ Z- W: f/ q' m
        {
1 _/ X' `  N, y9 l! \                GetPortVal(0x66,&Status,1);! q* q  Y( q3 @6 j2 J% E" R
                TimeOut --;
6 T+ U9 Z. R+ s# t//                Sleep(1);
# Q8 T6 v# Q* n/ {        }while((Status & 2) ==2 && TimeOut>0);
2 @8 @( @/ W. |- y
9 W! P) n5 h0 l" T' l" m        SetPortVal(0x66,(DWORD)Data,1);
2 x( a  u2 _" E, l* A+ Q4 F/ A( A# B}
* ]: [% v* _( T# M; s" `void write62(unsigned char Data)5 M9 ^: q2 I& A& A# n
{' n6 F/ f3 Y- w7 {
        DWORD Status,TimeOut=10000000;
5 r; v' c& U4 P1 T1 e; [3 m. y        do6 H* _1 v) u; A) m/ A
        {
$ a) T$ U: P! j, Y                GetPortVal(0x66,&Status,1);( i; b1 U! m+ I9 |- w
                TimeOut --;
) ^- {0 m+ {+ O/ i- u" {+ W2 C  c//                Sleep(1);
7 q1 O6 O: |; a* e# D" {        }while((Status & 2) ==2 && TimeOut>0);
. e1 F! x* \. t2 F# m4 C( k2 R- q% d- w  J  i* |3 g0 u
        SetPortVal(0x62,(DWORD)Data,1);$ P5 ]: d, B+ ?0 a
}
) ^) _- B$ b0 U4 v$ M( ~9 c% Cunsigned char read62()
! o' \# e" E. `% o4 @{
) B4 V) B* k+ y9 d: W6 ~& q3 R        DWORD Status,Data,TimeOut=10000000;9 ~* s2 p5 M' V  H4 Z
        do5 M. F3 K- w# k% J9 h
        {
% O+ q: l: q" v/ H/ V# Q$ R- ?5 t8 E                GetPortVal(0x66,&Status,1);# M/ m2 M' k/ A, K7 N
                TimeOut --;4 Q, E+ U5 Q9 y0 y# s5 A. K1 }" c
//                Sleep(1);
/ b+ _+ g8 d0 _3 R; P: R( s$ G3 J        }while((Status & 1) ==0 && TimeOut>0);% U9 e7 T* K4 Y/ ]/ J2 M

% F( E# I7 C$ I8 Z) a: C3 T$ V0 M" s- V
        GetPortVal(0x62,&Data,1);
& g' L. j, x9 C        return (unsigned char)Data;
$ K- H; K$ L! U, v9 g7 }' p9 G}
: L: Q6 V3 d# v# ]/ W& j+ ?( Kunsigned char read_ec(unsigned char index)
. Y' E, {/ p. o4 Q) X( l{$ h0 v/ r  ?' C6 l
        write66(0x80);
2 w7 A1 Q  P  P& ~& g        write62(index);
0 U/ w& C4 n$ l6 w        return read62();6 W9 A0 i. Z( d5 C  C* x
}
1 s$ I" o; z, n' G' b9 [+ G9 K& _( l+ u
[ 本帖最后由 qdk0901 于 2010-2-9 10:58 编辑 ]
回复

使用道具 举报

发表于 2010-2-9 16:41:22 | 显示全部楼层
HardwareEditor.zip (782.25 KB, 下载次数: 1500) 楼上的有没有发现用你的方式后出现的两种异象,你的while等待EC IBE/OBF的动作是永远退出不了的。都是因为timeout超过了你设定的值才退出来的。那是因为中断优先的缘故,每次你用这种方式读写EC其实首先读写的不是你的AP而是OS的ACPIEC Driver。你读到或者写入的值只不过是OS ACPI读到或者写入后在EC Data port留下来的值。另外你有没有发现OS的错误报告里面一直在报告ACPI错误,因为OS被迫在没有与BIOS同步的情况下对EC做读写。OS读到的数据也当作无用的data忽略掉的。7 p! u2 }9 v6 _8 n$ h4 q
  如果一定要不disable SCI在ACPI OS读写EC那你完全没有必要再去判断EC IBE/OBE了,完全没有意义。  g1 \4 A0 t9 f- Q8 Q& T

, Z" M; \$ c( T: [  j[ 本帖最后由 Faintsnow 于 2010-2-9 16:44 编辑 ]

HE

HE
回复

使用道具 举报

发表于 2010-2-9 16:56:18 | 显示全部楼层
原帖由 海陆空 于 2010-2-6 19:40 发表
/ n( J8 v& E  m: c  U* h' ^5 c6 @7 ?! l: y  f0 M6 O7 I

+ a: i: x5 O% O) ~您能讲讲怎么disable SCI啊?然后又怎样呢?谢谢

) _; w' P! j0 h/ h  c& I6 X& Q) y
1. Find out the APIC address (you may looking it in ACPI APIC table), usually 0xFEC00000,
+ i. B% z0 ?6 Z2 Z# ?  V1 ~# p6 i0 z
2. Find out SCI IRQ number (you may looking it in ACPI FACP table), usually IRQ9.+ c7 A" U5 U6 L4 q# j5 `
5 M* y1 Y* w1 d( Y
3. Then set bit16 of the IRQ to disable it.. M7 F/ }! N* L* T2 z

& V3 u* p" u6 H' m& Y* s' ?; l    a.. Offset = IRQ# * 2 + 0x10;, R: U- P  l! e' a7 V# p6 h  C

% @# @: F1 B! C9 d    b. Write Offset to APIC base,
3 E7 m2 z! Q7 Z0 e. k# h8 |' X
+ X0 ?9 s6 }* N+ Q6 ^" N8 Z    c. Read Data from APIC base + 0x10;& v0 z8 Y( I  C7 I0 [

* q/ p: ~9 r7 o8 O, n    d. Or bit16 to Data;% {0 |2 p9 s, b  O8 D3 ~
& k1 l$ j  l/ t6 t
    e. Write Data back to APIC base + 0x10;
- }! P  d5 }+ ]4 e# m0 R/ M, Y, c! {  n# N+ V" D5 O

2 s! G7 R$ W5 r9 `. x: a* T7 z1 b7 b. R1 W5 d2 H# ~0 R' e
You need to check APIC spec for details.
回复

使用道具 举报

发表于 2010-2-9 17:51:44 | 显示全部楼层
原帖由 Faintsnow 于 2010-2-9 16:41 发表 # E2 N  t; q1 T) ^% ]/ t: f$ @7 h0 ~
545楼上的有没有发现用你的方式后出现的两种异象,你的while等待EC IBE/OBF的动作是永远退出不了的。都是因为timeout超过了你设定的值才退出来的。那是因为中断优先的缘故,每次你用这种方式读写EC其实首先读写的不是你 ...
" O7 t. R4 e8 r
' k& p8 D. O" h( {+ T3 H% e
如果一定要不disable SCI在ACPI OS读写EC那你完全没有必要再去判断EC IBE/OBE了,完全没有意义。
" B( E6 c4 ~2 v# L$ }- W==============================================. ~3 _! F# P; b) n
事实上却是有数据错误,但是说不判断IBE OBF,那就有问题了。# |. S' o* R. t- f* m: y0 ~
0 N9 p+ G0 W3 ^8 v
因为OS去读写62/66 port并不是很频繁(至少我们的平台如此),因此有几个错误的值我们可以容忍的,而且错误的值基本是固定的某个值(就是某个Q Event的id)
0 |2 z! W5 a2 A但是如果不判断IBE或者OBF,连自己的数据都不知道是什么时候ready的了。) @- j0 r4 C' K$ H
* q, s( }7 O$ z% E7 t# u2 ~* ~& b
因为只是用了做些简单的测试工具,所以这样的错误是可以容忍的。
% ]6 U9 m; |7 l" Y# B1 P, e当然正规的做法当然是要禁用SCI
回复

使用道具 举报

发表于 2010-2-9 18:07:46 | 显示全部楼层
我想说两个地方:! O' C7 @: u1 o& P0 o% Z
1、ACPI OS去读写EC Space时,一般情况下EC会用一个SCI去响应OS读或写的每一步细分操作。" x) d+ o0 \. C. a4 i5 _) e: X$ G
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, 2026-2-1 12:04 , Processed in 0.297808 second(s), 20 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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