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

谁帮详细解释所有发给ec的60/64命令号码和意义

[复制链接]
发表于 2008-7-14 00:04:00 | 显示全部楼层 |阅读模式
bini殇,能帮详细解释一下bios post过程中的所有发给ec的60/64命令号码和意义吗?数据量比较大,截不住。
发表于 2008-7-14 12:09:38 | 显示全部楼层
转个别人发的,不知道LZ能不能用上  
1 F/ G6 g0 H/ y9 a5 V2 \  ^2 Z" Q7 @7 a" k: l
4.2.7 Command
3 N5 j8 Q0 b' d* a4 Z! _1 I2 j0 g
7 j" T% c7 g+ S- j- H通过8042芯片,可以:
( L+ r- p8 T* S/ R0 s3 k) f5 |向8042芯片发布命令(通过64h),并通过60h读取命令的返回结果(如果有的话),或通过60h端口写入命令所需的数据(如果需要的话)。, P& O* f6 {9 @0 s! {; `7 m+ _8 z5 L
读取Status Register的内容(通过64h);0 O2 c/ E8 l% U& l0 `
向8048发布命令(通过60h);
% @$ V: c8 U5 j7 j9 W# Y9 e读取来自于Keyboard的数据(通过60h)。这些数据包括Scan Code(由按键和释放键引起的),对8048发送的命令的确认字节(ACK)及回复数据。! A5 ?4 J/ J" L7 q
) a* c1 E5 b* O( g7 K
再次强调一遍,Command(命令)分为发送给8042芯片的命令和发送给8048的命令。它们是不相同的,并且使用的端口也是不相同的(分别为64h和60h)。
* b3 Z5 p6 Y! H
/ R% [  S- ^( j( r6 b6 I7 B# l" g) @2 B5 R' p7 J  n
1 Y. B. P% k  S
    * 64h端口(读操作)
6 J- f1 P/ Q# G, U/ N8 H/ O9 I: i) Z6 P! Y3 z
5 e# h% {' K* k% ^  ^$ p/ v% r
对64h端口进行读操作,会读取Status Register的内容。8 A4 W2 T$ ~6 a  S
0 Y% L+ T6 l2 L+ Z+ S2 X
inb %0x64
( i* A/ |; N0 E* n1 \执行这个指令之后,AL寄存器中存放的就是Status Register的内容。$ m0 q! o7 b6 g* D

9 u1 Q; z5 b5 R" p8 O, t4 b" |5 x1 A  u    * 64h端口(写操作)
* k/ S" \7 l8 n# j7 \5 U
# s) b/ t5 G) W3 P9 b向64h端口写入的字节,被认为是对8042芯片发布的命令(Command):8 O) t. C& ]) [5 _! V' T1 p) m
Ÿ
+ j3 [! [( q" ?2 A写入的字节将会被存放在Input Register中;
9 u, Z7 ]8 V! Z$ sŸ! [# a1 I2 S" z7 O! N" p1 U, B
同时会引起Status Register的Bit-3自动被设置为1,表示现在放在Input Register中的数据是一个Command,而不是一个Data;1 E6 x& k1 c2 f" z9 j, N
Ÿ
7 m- l9 S' G. }6 l0 E# Z5 x在向64h端口写某些命令之前必须确保键盘是被禁止的,因为这些被写入的命令的返回结果将会放到Output Register中,而键盘如果不被禁止,则也会将数据放入到Output Register中,会引起相互之间的数据覆盖;
' n. L# E( M' u, V( }! w& J8 z/ kŸ+ q( |% {* [9 w: ?' G! M
在向64h端口写数据之前必须确保Input Register是空的(通过判断Status Register的Bit-1是否为0)。: o+ K3 w8 u- n0 m

$ [# H8 R* O- A% t4 B. `+ u7 S1 O  @4 nvoid wait_input_empty(void)5 y% E$ q, `* M: f3 e( W
{0 R- y6 P' R' s8 K( T. n- ~1 O
   char __b;
5 f0 s3 m6 e& J0 I: J  Q4 w
- m+ f! `2 X' s1 Q+ o7 U" D% o   do{8 K. l# _- ^0 S0 R% i: p. b2 I0 e' b
     __b = inb(0x64);
+ T& I2 K1 q' V4 P, Y# t- f   }while(!(__b&0x02));
6 w: Y( g, M# P! i7 f3 {}) c6 ^% ^% L% y( E  Y- |% z
0 V7 f$ h. J- N* E! R
void disable_keyboard(void)" n7 A7 ~3 r, t. {/ F6 G
{% d4 g; {. e: o1 o( _4 K
   wait_input_empty();
8 {% I* T3 c4 k+ N+ S   outb(0x64, 0xAD);- X* y! l, }" Y, V0 T, B' X
}[size=+0]
: Y) f5 K$ p* H
4 i' c* g! `7 z4 Y    * 60h端口(读操作)% y8 k; V  ~% }* y
1 X- u+ p) B: u* t: y8 I2 ]6 }
对60h端口进行读操作,将会读取Output Register的内容。Output Register的内容可能是:
# \1 O1 P/ p' X% k! {& `( ~Ÿ           来自于8048的数据。这些数据包括Scan Code,对8048发送的命令的确认字节(ACK)及回复数据。. W. g; _3 z" i: p6 X( A
Ÿ           通过64h端口对8042发布的命令的返回结果。
+ }' T) d5 j0 A: z" ?5 q4 C  \- K+ g/ d( r
在向60h端口读取数据之前必须确保Output Register中有数据(通过判断Status Register的Bit-0是否为1)。
  l; m0 i0 c/ r* q; O  mvoid wait_output_full(void)* E1 e7 Y. E7 L) _0 o! B3 m
{% o% B( g2 a, q0 }: I% a
   char __b;
! E7 ^: e2 E4 j: I0 }- m# s( W5 _' t4 e
   do{/ {# S+ V6 R6 F. Q3 i5 f
     __b = inb(0x64);
( g1 x. `& K3 `% x   }while(__b&0x01);
) i" v  ?+ W8 q  X/ N}
% |( V; C. S! N/ u2 |  D, v
5 v* s6 ]7 E+ S! B" Funsigned char read_output(void)
/ I8 A/ D& |8 e{
# R+ c% e  }) k' T' }   wait_output_full();) j9 [; U8 R3 H2 O
   return inb(0x60);
- F$ v6 Z3 Z; \( R}
0 L+ J  e9 a0 u+ s: p8 m* D6 U: `. j. P. I( ?
    * 60h端口(写操作)1 f- k1 c1 G2 G; w6 r) y) S

" L  }  K  I1 t6 P# V" n向60h端口写入的字节,有两种可能:, I( S1 M# t! _4 b/ \. ?- }
1.如果之前通过64h端口向8042芯片发布的命令需要进一步的数据,则此时写入的字节就被认为是数据;6 m: }0 s+ g3 i6 W+ W3 U( c
2.否则,此字节被认为是发送给8048的命令。
6 f. I5 E% ~$ x& \1 D& f3 k2 p) T6 [; p
在向60h端口写数据之前,必须确保Input Register是空的(通过判断Status Register的Bit-1是否为0)。
0 \. j/ Q  L- Z# s$ j) u0 z8 H' U- ?9 J0 n

4 q% e3 \" Y" A+ H! F, k- O" \[size=+0]4.2.7.1 发给8042的命令; a5 P. K- E& d3 H6 k
- W" E: r, w" D6 ?  U
    * 20h 5 w4 {% }5 L7 u3 U( K

0 H$ K" |+ g% G% N7 w8 I% O准备读取8042芯片的Command Byte;其行为是将当前8042 Command Byte的内容放置于Output Register中,下一个从60H端口的读操作将会将其读取出来。
3 q0 ~8 p. B7 C# L& c" v* b) T% r

0 b1 A3 J" b/ t  H; y8 @- Zunsigned char read_command_byte(void)
7 ^, u1 {# G' P7 Q9 ^" }{
1 Y2 M7 \4 c# ^   wait_input_empty();7 M( Y5 H" l9 N# L% ?: N8 Z0 Q2 ?
   outb(0x64,0x20);( n- w2 P, z3 I- [
   wait_output_full();
' j9 R) L: c0 {   return inb(0x60);   1 F( c+ b; _( U1 t
}; |6 V: q( u. J1 }9 _0 G

3 P6 h: S- M' }/ C% x+ q    * 60h! k9 b4 a5 u  _  n5 a4 {: _8 W- z
' ~$ `# V2 Q% [! q
准备写入8042芯片的Command Byte;下一个通过60h写入的字节将会被放入Command Byte。( v9 M* u8 F: z8 [) _

; F7 H6 D- M3 s1 ~- J( [+ D$ R* W+ j6 k$ b! f0 y
void write_command_byte(unsigned char command_byte)+ G5 [. g( Z# @9 [; Q8 I$ O* s
{& _: o  C9 S1 ~' b( f8 c( L
   wait_input_empty();
/ y$ ^: m& s" W" ~   outb(0x64,0x60);2 r7 o- h/ X8 K( I( H
   wait_input_empty();
8 M, q6 T* @* l! {5 A6 T   outb(0x60,command_byte);
6 P  @1 r5 u* E5 S2 A- c}+ K  x, B& c. R& N% _$ n

, k; R  C( J7 I. S+ p# @" y
: U6 w' r7 L8 R! H: Z  E5 C2 D    * A4h
8 X+ ?# X; z3 d2 P6 a2 X: i2 u' s! F: ^1 K7 a2 L  W. F, r
测试一下键盘密码是否被设置;测试结果放置在Output Register,然后可以通过60h读取出来。测试结果可以有两种值:FAh=密码被设置;F1h=没有密码。# e5 M6 D  T1 l* r6 s/ o3 I- ]
bool is_set_password(void)
2 u( L8 P1 _) }{
; X8 ^' v; n0 Z! d8 l% e& ~   wait_input_empty();
% |' o% v$ V' O2 z0 r6 Y   outb(0x64,0xA4);
! P0 ~2 b- C3 n! |0 i+ z   wait_output_full();
5 T# B1 ]( C' f6 e   return inb(0x60)==0xFA?true:false;   
2 v9 w+ }6 P, V: b7 F$ g4 y5 w  a}1 Y4 K, q4 }9 I9 U9 i
4 s4 B) i4 Y) F0 h; n6 @1 e8 [5 a  O
    * A5h
; Y6 e' N- R$ [4 m( U0 I: z: b7 R
  ?; F7 y( }4 Z设置键盘密码。其结果被按照顺序通过60h端口一个一个被放置在Input Register中。密码的最后是一个空字节(内容为0)。* Y0 Z7 y/ w, |! S) D
void set_password(unsigned char* password)' f$ P1 c9 |. S7 }9 v$ _: d; H6 A
{
' {: n; q3 }! x' a+ K+ T3 u   char* p = password;1 W1 a; d* s% e" ^6 V7 G
* p5 [$ G1 P( y. g) n
   if(p == NULL)
9 A4 A' U, D0 O; }      return;
, o4 l* G+ [# A/ L
- f: [& x8 m' r1 I8 Z   wait_input_empty();. i7 Q% x" Z( r" y
   outb(0x64,0xA5);
; \( z  P7 ?% |/ S1 f* ?; v
6 H, u0 K9 e* F- e; V5 {   do{) _3 P/ j  w# W5 c1 f
      wait_input_empty();
8 |  ^! R( N3 i4 O4 E: a/ S      outb(0x60, *p);; X8 j' a: e' _$ T
   }while(*p++ != 0);
. @9 n: Y7 W( Y/ U- K}) w! Q9 r- a  }1 D; X& Z

5 V' o) @0 d8 o0 E* G* h    * A6h
$ Q' F7 N" i' Y7 G, S! w% R. K7 y. P. a. U
让密码生效。在发布这个命令之前,必须首先使用A5h命令设置密码。% a9 b* H& j2 j, w  y4 B
void enable_password(void)
5 @- Y5 e$ i- f7 H4 U{
: Y7 ^* i* y  ?2 q   if(!is_set_password())
( @) `4 j" n2 C9 ~! x+ G' E1 z& `      return;7 N' o& C. K! Y7 M
2 a$ X9 J9 ^) n
   wait_input_empty();
. r) d# Q6 w5 h9 b" G9 ]   outb(0x64,0xA6);   
4 e" l$ W# H0 }9 l}
$ ~/ L, e! R# K7 d7 M
5 m  ?. h3 y/ s/ l% K    * AAh  @, D! K) m$ O6 P2 j3 P$ u  U5 y4 r

" P3 k$ `( z6 ~% }! p  y% U自检。诊断结果放置在Output Register中,可以通过60h读取。55h=OK。
: u1 b) h/ z9 {/ q9 m/ z, m3 G
' n) O1 f6 r- q" \
2 I1 m# W  C: g: Bbool is_test_ok(void)
+ f! d1 D7 K# G8 \- x* E- M{
/ S, V% O- K( N0 |5 {' H   wait_input_empty();
# Z, k4 X, }# h0 Z   outb(0x64,0xAA);  k) |4 t- f9 j: J

: ^& \! D9 h, S5 K7 O/ S8 v1 g5 _9 }4 D- S1 U  ^1 T8 V
   wait_output_full();2 J3 T) G' Y' s& ?/ V
   return inb(0x60)==0x55?true:false;   - }1 ~6 c6 f4 |. O# d
}
3 }7 Z- M, }0 n, f: Z) J% D7 T1 E( Q$ I8 i3 P

1 Z4 E# u' o# b    * ADh
2 w/ k5 F1 @9 ~5 Y% y" \
2 u: G( L8 L+ j, d禁止键盘接口。Command Byte的bit-4被设置。当此命令被发布后,Keyboard将被禁止发送数据到Output Register。
( l4 k( z7 |9 g: i4 ~4 Nvoid disable_keyboard(void)6 s: A  Q1 _% `0 A# r1 c+ K
{% n5 h# R" f+ G1 V% E
   wait_input_empty();
6 F: v3 R! k1 C   outb(0x64,0xAD);- [. i/ }  }' V, q
, g1 G: x; r. c$ B2 F- c
}
" O3 ?" n1 f: O
5 t6 s, Q1 t2 c# }    * AEh; Q9 _7 I' L: a
6 c8 j& j# y+ u: m3 N
打开键盘接口。Command Byte的bit-4被清除。当此命令被发布后,Keyboard将被允许发送数据到Output Register。4 ~& U1 |1 R% u6 R7 f& h+ }3 Q: m
void enable_keyboard(void)
7 D: n. u' G2 D; ?# @! Z4 Q% u{
  s# G$ h6 Q9 C  N+ o+ n   wait_input_empty();
- ]! V! n, i; S& t7 r8 c   outb(0x64,0xAE);7 ~5 @* w) _1 W+ c! L! T+ d

7 T  M: _! d2 Y. }; g}4 N% l; }" Z0 N- |) ]

5 N, Q& I# m1 I    * C0h
3 I' U0 x$ O$ M- U6 A! N5 p- T/ S, t) b
准备读取Input Port。Input Port的内容被放置于Output Register中,随后可以通过60h端口读取。  y4 k, |" A7 a8 }
unsigned char read_input_port(void). H4 w- ~+ N5 G: U7 K: G1 F. E
{9 v3 n5 f% o) C# ?
   wait_input_empty();+ S3 G' z% R8 X  n+ ~  Y
   outb(0x64,0xC0);9 a& c& {" e5 ~! m) Y4 ?! `

+ J( W# q) [4 N; Y2 S   wait_output_full();: ?, r' `2 i- W! d' B& d+ @

* t- p9 \* l6 M, _6 u. |8 R* d   return inb(0x60);
4 D3 a7 b; ^  s}+ s6 [2 p) L7 n" m2 J' V
9 e- [  @0 |& Y9 B7 x: y- d
    * D0h6 Z1 @/ _' {- |  j

% f0 D$ a8 F+ h, ?/ [4 ~  B准备读取Outport端口。结果被放在Output Register中,随后通过60h端口读取出来。8 n9 Z$ T2 G0 c
unsigned char read_output_port(void)
. g3 C" E: U# m0 M6 k# ]7 x{
: _: ]; s4 B- B" K. d# G   wait_input_empty();
8 B( O( r# W& q" w5 ~( G1 q   outb(0x64,0xD0);
. H  b3 M3 J4 e4 {/ `+ Z) _
2 I" B9 r6 L5 G& K4 t   wait_output_full();
, t; \1 G' e, S3 A) v9 E, b2 Z% X! ?) L6 O/ d  Q4 O- h
   return inb(0x60);
" O7 E2 N* c. S9 F* y3 A( g}
& f+ G1 g3 k9 E- J$ p1 u5 [( e+ g& E9 w+ w5 b4 P
    * D1h
! h8 ^4 ]+ H- N  S: b& h$ Y8 x+ O' P4 F
准备写Output端口。随后通过60h端口写入的字节,会被放置在Output Port中。+ e; f/ T3 f# R' u; B
void write_output_port(unsigned char __c)1 ]1 d  z) H6 }# ]
{2 s% ?4 I5 H0 ?' \+ l1 k3 t
   wait_input_empty();
1 I: Q0 B3 A1 W) P( p; a1 Y   outb(0x64,0xD1);( w4 \/ A; ]& M7 S" ~

% E+ \6 H7 m, g1 Y9 m$ s7 G   wait_input_empty();( D& X2 U0 X$ r+ T$ u
   outb(0x60,__c);
  ~3 m$ w0 j( J' f1 X9 \1 n9 x  o/ n' N1 G% {+ i3 S) }8 g
}
" ]7 A' Y. n# i4 D  I* j; I# n' `) y( V( p# G
. {, T' _* N: F, p5 N9 ^# [
    * D2h
! k! g7 A0 u9 ~- w) z4 R. X8 v6 ^0 @
4 W  v. l- V. f$ W7 Q准备写数据到Output Register中。随后通过60h写入到Input Register的字节会被放入到Output Register中,此功能被用来模拟来自于Keyboard发送的数据。如果中断被允许,则会触发一个中断。
# G7 G7 u9 `8 m- K$ e" M+ c8 ^void put_data_to_output_register(unsigned char __data)
2 m7 m, n1 \% r{% Z( s. @, }- V) d# v6 u! r  q
   wait_input_empty();$ V( ~  |0 u5 G7 V8 _
   outb(0x64,0xD2);
7 l5 c' a8 r& C  @( \; u% j3 H9 t  e6 S
   wait_input_empty();
  m$ g! s8 I2 N, f- g% `$ X   outb(0x60,__c);% O9 M  p" {* E* R
}
: [4 n/ A1 v' P, Y, z4 u7 e! k0 R. R6 v
4.2.7.2 发给8048的命令
9 |$ E( l- G( F4 z& o# V8 V( J5 i( _/ V, \( n

& I& K& _8 d3 c3 Z    * EDh
% ]; a# ?) I% Z
- o% B' o( p  l& @2 O" q设置LED。Keyboard收到此命令后,一个LED设置会话开始。Keyboard首先回复一个ACK(FAh),然后等待从60h端口写入的LED设置字节,如果等到一个,则再次回复一个ACK,然后根据此字节设置LED。然后接着等待。。。直到等到一个非LED设置字节(高位被设置),此时LED设置会话结束。  U; l8 S% N( _

4 r$ p# j; q+ ?: Y' ?    * EEh) H) B5 U7 s* U0 Y
( t- F0 B4 r; U( l, m/ E# k# _" N( K
诊断Echo。此命令纯粹为了检测Keyboard是否正常,如果正常,当Keyboard收到此命令后,将会回复一个EEh字节。% t8 K$ s# N7 L4 T: i" ~1 S

% b. ]! @7 B, L! h' S    * F0h1 r, r7 P% J7 P' M$ A

: d4 [' r5 I& X2 [选择Scan code set。Keyboard系统共可能有3个Scan code set。当Keyboard收到此命令后,将回复一个ACK,然后等待一个来自于60h端口的Scan code set代码。系统必须在此命令之后发送给Keyboard一个Scan code set代码。当Keyboard收到此代码后,将再次回复一个ACK,然后将Scan code set设置为收到的Scan code set代码所要求的。' C( G9 i: Q/ Z3 p
9 ?# i/ k6 v* \$ F; X5 D
    * F2
/ o7 T1 H$ Q/ h( S: f) c4 h4 i# Y# Z; b+ S
读取Keyboard ID。由于8042芯片后不仅仅能够接Keyboard。此命令是为了读取8042后所接的设备ID。设备ID为2个字节,Keyboard ID为83ABh。当键盘收到此命令后,会首先回复一个ACK,然后,将2字节的Keyboard ID一个一个回复回去。
" M, T4 G/ J5 I( {5 y  ]0 K
& I5 B! T" B' \# a% t8 n* X    * F3h  c- [2 |& f9 i! Y6 @: f( u% {
8 r  f# r! @5 ~/ {
设置Typematic Rate/Delay。当Keyboard收到此命令后,将回复一个ACK。然后等待来自于60h的设置字节。一旦收到,将回复一个ACK,然后将Keyboard Rate/Delay设置为相应的值。5 D. g# d2 B5 M: f5 r* H% r

% I' x7 u6 O: r0 a7 H; O1 P    * F4h5 ]* d( m1 g5 I$ w  ^

8 p% v4 `  Z; z( w! O9 h0 j7 ]# @清理键盘的Output Buffer。一旦Keyboard收到此命令,将会将Output buffer清空,然后回复一个ACK。然后继续接受Keyboard的击键。( ?2 E$ u- o# y- q
4 N9 K0 _8 z# \& f
    * F5h6 H: e7 V6 ?! F2 |' b$ h
+ u  ]# J1 y8 C
设置默认状态(w/Disable)。一旦Keyboard收到此命令,将会将Keyboard完全初始化成默认状态。之前所有对它的设置都将失效——Output buffer被清空,Typematic Rate/Delay被设置成默认值。然后回复一个ACK,接着等待下一个命令。需要注意的是,这个命令被执行后,键盘的击键接受是禁止的。如果想让键盘接受击键输入,必须Enable Keyboard。
8 f" B' G  r  N- ^9 k/ r/ a- X- _9 X) g4 c, N$ c
    * F6h" l% T( K9 e* u$ B4 O

2 D- t* V' w( {8 P" b设置默认状态。和F5命令唯一不同的是,当此命令被执行之后,键盘的击键接收是允许的。
2 r4 \  M; v0 m! ^2 O
6 ~2 J; R- V. |) y1 a+ R! p    * FEh
  i) K5 Z4 V! B8 r7 s, \$ Q1 T* F6 M3 R# [+ ]
Resend。如果Keyboard收到此命令,则必须将刚才发送到8042 Output Register中的数据重新发送一遍。当系统检测到一个来自于Keyboard的错误之后,可以使用自命令让Keyboard重新发送刚才发送的字节。
0 R! Q5 k! Y6 M4 g: j/ p0 W  m! Q/ _3 Y. M5 H5 K9 P9 _' D
    * FFh  N! ?" ~% D4 A) O* d# l( T

4 Z( G& _7 S! F/ Z4 J/ CReset Keyboard。如果Keyboard收到此命令,则首先回复一个ACK,然后启动自身的Reset程序,并进行自身基本正确性检测(BAT-Basic Assurance Test)。等这一切结束之后,将返回给系统一个单字节的结束码(AAh=Success, FCh=Failed),并将键盘的Scan code set设置为2。
回复

使用道具 举报

发表于 2009-1-14 13:49:16 | 显示全部楼层
好贴!
7 C" s" t1 }% ]& m5 C' q! _4 O非常详细!
. j$ Z) P- w: C4 y9 b谢谢!
回复

使用道具 举报

发表于 2009-2-25 17:37:28 | 显示全部楼层
2楼好帖!在helppc的Hardware Data and Specifications栏里有相应的寄存器和命令详细描述。
- D+ [6 m0 r; R5 t7 N5 W
( h4 _, K( `4 V: I9 B/ q9 Z  s我的问题是,上述描述应该是针对老的8042的,在目前的使用EC的系统中,这些status register和command描述在哪个文档中可以找到?比如intel的santarosa,使用renessas的H8s 2104 EC,按道理上述状态寄存器,命令等的描述应该在2104 datasheet里,但是我怎么找都没有。还是有某个spec定义了这些命令格式?新手问题,高手莫笑
回复

使用道具 举报

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

本版积分规则

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

GMT+8, 2026-7-19 20:45 , Processed in 0.156627 second(s), 17 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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