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

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

[复制链接]
发表于 2008-7-14 00:04:00 | 显示全部楼层 |阅读模式
bini殇,能帮详细解释一下bios post过程中的所有发给ec的60/64命令号码和意义吗?数据量比较大,截不住。
发表于 2008-7-14 12:09:38 | 显示全部楼层
转个别人发的,不知道LZ能不能用上   " \/ ^5 g4 y8 _6 R! n0 `) }3 R
' S" A- X' v9 S- z1 W+ U! @3 D
4.2.7 Command" J- _% Z: x; A1 |
0 h( I5 L! Q) D5 v+ N
通过8042芯片,可以:
& \: F) O4 t9 f' j向8042芯片发布命令(通过64h),并通过60h读取命令的返回结果(如果有的话),或通过60h端口写入命令所需的数据(如果需要的话)。. T% x# P% x+ @. F" r2 n+ i
读取Status Register的内容(通过64h);
& I# [4 E  t+ n/ `2 _9 b2 n向8048发布命令(通过60h);, j9 j$ C2 O: f0 T2 T
读取来自于Keyboard的数据(通过60h)。这些数据包括Scan Code(由按键和释放键引起的),对8048发送的命令的确认字节(ACK)及回复数据。! d" [# [& T" L. Y! Z0 M) }9 G+ c
! F. f. E4 ~% M8 S
再次强调一遍,Command(命令)分为发送给8042芯片的命令和发送给8048的命令。它们是不相同的,并且使用的端口也是不相同的(分别为64h和60h)。( s  I/ Z2 ?; U1 }$ v9 Q7 Z

3 X) e/ Y4 ?$ m* W8 [* j  O4 l2 ~, H" m4 n; r
6 {) I) F5 v* d& g' ~) ]
    * 64h端口(读操作)& d8 J5 q2 k% v. f

/ l6 Q3 w! a, Q; u; Q. A( |0 k9 _3 v9 f# X! m
对64h端口进行读操作,会读取Status Register的内容。
3 [2 T) C- _9 l& h( a/ \! }3 S* e
+ J0 ?5 `) H9 Winb %0x64: z. O$ [% e! S4 K  O- n
执行这个指令之后,AL寄存器中存放的就是Status Register的内容。0 X) ^( R0 b1 @
* Z7 n+ B- u1 K
    * 64h端口(写操作)
6 i) S4 O3 C' V6 `0 w7 s( F! s/ z& P1 O" ]% l# y/ ^
向64h端口写入的字节,被认为是对8042芯片发布的命令(Command):. A0 ]+ h0 E* @3 v4 {( e9 N" O
Ÿ
4 Q* ~7 X5 L( U% j. y9 G' Z写入的字节将会被存放在Input Register中;  _0 r6 q  ?/ n+ j; X% Q
Ÿ1 D7 g( Q5 \( ]7 k
同时会引起Status Register的Bit-3自动被设置为1,表示现在放在Input Register中的数据是一个Command,而不是一个Data;4 B3 b& y4 Z3 W) @
Ÿ
  n% K3 K( q. A( ^在向64h端口写某些命令之前必须确保键盘是被禁止的,因为这些被写入的命令的返回结果将会放到Output Register中,而键盘如果不被禁止,则也会将数据放入到Output Register中,会引起相互之间的数据覆盖;7 V; ]) x( F. J& V0 p
Ÿ% P6 `4 j5 o/ s; n% V4 @2 _& J
在向64h端口写数据之前必须确保Input Register是空的(通过判断Status Register的Bit-1是否为0)。9 ]/ x6 `& `( }' {( }, y: M8 s
# g/ O: _! `6 y$ `
void wait_input_empty(void): @0 {: N" T2 N, o% s
{$ @/ z+ J3 ?7 G5 M: {/ O4 t$ D7 y
   char __b;
  `8 X  g, l! N6 g
5 H+ M: w9 n8 g% p6 a& v   do{
  [1 Q6 A* `: D' }' v9 r( u2 b     __b = inb(0x64);2 Y) Z2 g) [6 _2 E$ I3 f# Y. y
   }while(!(__b&0x02));, L. Z" d& ?2 Q/ S( x. m
}
# ?1 F. a# ^6 q# e. m. D! a
: `6 p& B" @! E$ f( Z6 nvoid disable_keyboard(void)
% U8 O1 b( _& K3 V, n% W$ C" B) E{) ^- C0 x' {& n1 R9 I; ?
   wait_input_empty();
0 I0 ~' w8 u7 T" v8 p: w9 G# H   outb(0x64, 0xAD);
$ [; I2 c, b, T; L}[size=+0]
; u" D2 D+ \0 K+ e! e/ X
: v) L2 @* y5 c. A9 e' ]    * 60h端口(读操作)) s, U" \4 h0 F4 }$ P- I
: C# n) l5 R, V6 i) c1 o* F5 {6 I  V
对60h端口进行读操作,将会读取Output Register的内容。Output Register的内容可能是:
+ ^6 u. ?: i5 e4 b/ OŸ           来自于8048的数据。这些数据包括Scan Code,对8048发送的命令的确认字节(ACK)及回复数据。
, {, ^) y6 q& }' a/ r) }0 E% BŸ           通过64h端口对8042发布的命令的返回结果。
0 U6 o1 N- f" }3 u$ G5 O0 i, e- q* K. p2 O# Z0 T
在向60h端口读取数据之前必须确保Output Register中有数据(通过判断Status Register的Bit-0是否为1)。
  j4 F1 l+ u" G+ R% Q0 I( {void wait_output_full(void)
3 J3 a' Y9 ~3 Z% t4 u( o& {  a{' R4 D. v, ^& Y( G. s" c! @: T
   char __b;
4 B7 y; o8 ~' W+ ^' G' H: k7 G; m+ R! T4 _1 A
   do{
5 d1 B5 u3 T6 p     __b = inb(0x64);
+ F4 ?) \# K9 x2 l- ^   }while(__b&0x01);
: P2 y% j) t9 @1 t  k, s6 w; v}
( O) f/ j, B) J  c7 R, @0 y) t+ w( R
unsigned char read_output(void)7 T4 b- P. ~" T5 Y
{
' W& ]  }8 `/ b+ b( ]   wait_output_full();
, v; t2 Q. X( [& m7 p& S7 B( _  S" G   return inb(0x60);$ f3 _9 @) D  ~# J9 v9 S7 b& B  o# _
}
3 q+ M; n* n- c
( S6 q9 s! u+ x, ]# y& L  h* R    * 60h端口(写操作)
6 H( ^7 \" K2 _0 l) V. r& x) S; ^- }
5 v7 O9 ]1 x, M% ~向60h端口写入的字节,有两种可能:3 U6 N: O: s3 O
1.如果之前通过64h端口向8042芯片发布的命令需要进一步的数据,则此时写入的字节就被认为是数据;8 t7 c/ Y; g' u1 e
2.否则,此字节被认为是发送给8048的命令。
. t/ b3 b3 L4 N+ T
8 W2 M; S' b& R! W) P' b在向60h端口写数据之前,必须确保Input Register是空的(通过判断Status Register的Bit-1是否为0)。
1 \1 w" q4 u& O. X: |
9 }3 w8 M2 [( }+ |( s" X) Q9 @: t. a( x' q5 o* P
[size=+0]4.2.7.1 发给8042的命令
6 z& V& {7 C# s! {0 q8 o0 N5 O. P& t) A6 |9 e/ J
    * 20h - H# i3 U- ^5 |; W! b
3 N/ N1 o: k4 d9 ~0 @: J. l; ^
准备读取8042芯片的Command Byte;其行为是将当前8042 Command Byte的内容放置于Output Register中,下一个从60H端口的读操作将会将其读取出来。
9 F- x" }/ K, ^
, K  a- \2 L3 m" t* T
) y3 e: |6 J1 n  Z6 bunsigned char read_command_byte(void)5 l: {8 }9 D) H$ k5 ~/ h/ I
{
. ]9 G, X# S; R1 b* ]5 e   wait_input_empty();
  z  Z  R( p( _. |6 y- D' A7 g- y2 f$ y   outb(0x64,0x20);( U: [" ~, n- k) @3 R; k
   wait_output_full();1 h4 u# [& L) y+ @" |  U. D8 a* E- T' {
   return inb(0x60);   + Y. m& [% }. I# h- }
}
. v8 U3 g0 q  k5 @( J4 l% P
6 }: `- L% E$ y% b+ I; b    * 60h& _0 X" J5 }8 p: c  S7 I$ n

- |* R. m* j3 L% j6 |2 `  n准备写入8042芯片的Command Byte;下一个通过60h写入的字节将会被放入Command Byte。  T( ]9 _& Y7 a; d1 H
- t& J9 X" B% i0 y  F  z  f

& A) k6 C9 l, a3 {$ I* t0 Gvoid write_command_byte(unsigned char command_byte)/ `8 I1 y2 m6 a+ @9 Z/ I
{
! [4 ^8 X% z% Y   wait_input_empty();# W6 t% d1 i/ Z, z+ W$ {
   outb(0x64,0x60);- M2 N4 p# z- I6 A
   wait_input_empty();
- z4 s, h: |# t5 ]0 S   outb(0x60,command_byte);
! L: p- o) v! n6 R7 w}( }( N& \- Y' u4 s3 v

) o4 X: q  h+ U, @
5 m# J0 b( U4 r/ V- i' a6 L    * A4h
6 ^0 v3 D; Q+ ~1 E+ ~( T1 b, E6 |  H( U; x
测试一下键盘密码是否被设置;测试结果放置在Output Register,然后可以通过60h读取出来。测试结果可以有两种值:FAh=密码被设置;F1h=没有密码。
3 w) L7 [  B3 p3 i7 M$ p6 Ebool is_set_password(void)# S/ n) v* R1 h; b3 ~! t) A' \
{: \6 x+ U. z  p9 H* h
   wait_input_empty();$ F. R8 U+ h1 e' a
   outb(0x64,0xA4);
+ _3 n1 b" G* {# M2 X/ O6 T: u   wait_output_full();
! X/ P8 X: p1 ?   return inb(0x60)==0xFA?true:false;   
( w# \* i% F  d9 u" O% w}* ]' W6 X7 M0 p  Q! i" `" A) _0 [
, l9 q* `# \( p4 Y- g
    * A5h
4 l, B0 |7 g& @! X
- t6 S2 X( C6 e设置键盘密码。其结果被按照顺序通过60h端口一个一个被放置在Input Register中。密码的最后是一个空字节(内容为0)。/ C! k$ Z! |) l8 Y6 T
void set_password(unsigned char* password)
) K0 G& ]/ x) ]$ }{
7 N5 U/ w0 E( s' q+ x   char* p = password;1 q1 W, x" W( H( N0 E( u" C0 J
# t2 a- s% k! V9 P' t$ t* \+ O- P; h
   if(p == NULL)
# G. B: b) n2 f* |+ D      return;; g9 }  j, t3 }& t+ a) B* x5 T
, o( B7 M) o' F" y6 R' b1 f- g1 G
   wait_input_empty();
# v5 o) P+ L& v   outb(0x64,0xA5);
; @( V2 W6 R3 [# l$ h4 V  r) `4 F8 [; X' F
   do{
9 a, d, I  k# e, d2 v1 Y      wait_input_empty();
# u) ^5 L7 s3 H# _      outb(0x60, *p);; X! N+ |' j, \$ I. [/ U& h% c
   }while(*p++ != 0);, z5 Y& F9 H+ m* ?
}
5 Z; c) j( G; j: m; I' X6 G# h& Z1 `% D0 j+ D. U
    * A6h
: }% `; j" d, n! p& r9 A9 |! k' l. \! c5 ~4 b( k  B
让密码生效。在发布这个命令之前,必须首先使用A5h命令设置密码。! L4 _2 k  ^1 t" E- E
void enable_password(void)7 C7 T, g: M$ s9 a: i" A% ~
{2 T8 @7 [& U/ r+ [* A' ~
   if(!is_set_password())) u  O4 o$ ~1 p' o4 d. W6 n0 a
      return;+ B9 g1 g' a( ~) ?: h
+ O2 o2 ]! h; ?6 W
   wait_input_empty();
4 N! L0 [. ?) [   outb(0x64,0xA6);   1 O7 l" f7 ~' v, ?3 y# o
}
7 E" _) w5 M' h+ `* |2 p- y' ^' W+ b( A3 e: O5 e
    * AAh% t: l9 e5 u* s. q8 E' X, ^1 u
4 J: }8 ^6 p+ [- _  `6 X( j
自检。诊断结果放置在Output Register中,可以通过60h读取。55h=OK。
; N! m0 [3 }1 M: A4 D9 ]3 Z* }
  \; J. e. n( Q3 M5 y4 z. l* L  M) P" o2 C/ {! O7 a' n
bool is_test_ok(void)
6 h- t3 z/ y( q9 A{& s; d' x1 C8 Q2 R' t
   wait_input_empty();. H  o3 l, ~0 L1 |9 p1 G" i0 M8 l
   outb(0x64,0xAA);$ d: m4 i! x9 H/ c0 `
8 N) G/ [" h9 c7 d! ]$ R. ^

/ y- w- B9 e- C  ]0 e* a: d6 c   wait_output_full();0 l7 V; F5 E/ V$ B' _" D
   return inb(0x60)==0x55?true:false;   . }+ u' ?; m! C- j; O' o
}
' S% {1 d; H5 b& b% P4 k# H" E! t. }; H

& w* @  h# p2 \0 l    * ADh
0 X1 D& w) M4 u; B9 n7 N3 G3 p( N8 M" ]& i
禁止键盘接口。Command Byte的bit-4被设置。当此命令被发布后,Keyboard将被禁止发送数据到Output Register。
; v" d! h# A# n. `$ Yvoid disable_keyboard(void)% K( T- z& U$ J6 _: F( D: w8 s; ~
{( |7 a0 m& Y$ e
   wait_input_empty();
+ j; w) B- i# ]4 H4 N1 X+ |) _   outb(0x64,0xAD);- m- F, E4 K7 e$ M7 {4 k! b

$ y: k% \% v; C}
8 S) ^" v4 D% |+ f7 }6 r; E% j1 o) D$ j6 y* Z1 @
    * AEh; ]9 C) g3 m& h& j6 s  H

# H) s( v4 F* s! z打开键盘接口。Command Byte的bit-4被清除。当此命令被发布后,Keyboard将被允许发送数据到Output Register。
2 ~- `" ]% J" Z+ P/ H! W& b: F/ Lvoid enable_keyboard(void)
0 m* o% o7 D, [8 Z+ ^5 g{
  m7 [: `# R+ i% o& N, P) T   wait_input_empty();, W( t) A( v% u3 H* Y* O0 B
   outb(0x64,0xAE);
) L, e  V- Y3 ~- j, Q5 q+ }+ f" ]% M( J9 Q) e/ e
}- z; L- ?4 A& Z/ W# e0 `: ^( I' r
: w( o$ A5 L8 e1 {- ^
    * C0h
. b6 \- T- f% U  `, Q
# y4 {: x8 A, \准备读取Input Port。Input Port的内容被放置于Output Register中,随后可以通过60h端口读取。
4 r% M5 Z' f4 l% J8 t  kunsigned char read_input_port(void)
/ a3 e* Q- W5 F5 G' h2 c{
' T2 C; x4 @1 V/ b. ?   wait_input_empty();4 G# t& _- _4 R! W
   outb(0x64,0xC0);; Y6 v6 L) `( E8 b; u+ n

+ ~; j- R& i, i4 X* c% g+ t8 n   wait_output_full();& k+ B  n: Z4 ?! a( i
: o" P/ ?, a5 E3 A* R4 H% T, x' N
   return inb(0x60);
: l3 q0 L5 H0 p" f) }}
. J( q. {1 f; B9 y9 K, B! \
0 f0 q& [* P: B2 n: T5 L/ N( c/ O    * D0h
9 m8 h4 \: @% e: k1 N( j4 o8 u. x! O0 `
准备读取Outport端口。结果被放在Output Register中,随后通过60h端口读取出来。
- n. t7 B: y; C* p$ ?9 hunsigned char read_output_port(void)
. \" F3 n1 z% n; L{
$ Q8 a& N2 Q+ b# X$ ?. w: N* C$ i2 k   wait_input_empty();2 ?% J! @. [& {8 C' `
   outb(0x64,0xD0);
. |- w) b4 I4 ]" S- D' Y- ?4 M: e% f9 t0 t. f( {3 q
   wait_output_full();$ |+ ?- T4 c6 B! V$ v  H) G

& v7 ~- s0 u: Z0 g   return inb(0x60);
. z5 c9 i- N+ v, r7 p5 Y: z. v" E}
' X5 V$ {* V  @  \
( {( @8 `9 S" e" u1 l    * D1h0 y- D8 w8 @3 f

% R' e0 v3 T( `6 U) H' U( B+ i; J, J准备写Output端口。随后通过60h端口写入的字节,会被放置在Output Port中。( X  K' V+ _, W# v( {6 X& D
void write_output_port(unsigned char __c)
1 m6 [4 R. a2 l$ ]5 L" D{" f3 r. x0 H$ S8 w
   wait_input_empty();
$ r6 l0 ?& i! k1 C   outb(0x64,0xD1);& D$ |9 x2 [! P( `" a1 [
& ]0 y/ d% e9 f8 Y1 H
   wait_input_empty();
( P! k# C0 m' s( T! T1 V   outb(0x60,__c);) W9 H$ D, B* T+ z$ A
: _4 m$ C% h) L- g  E
}! z( z' ^5 [2 t" r

, t( s2 X6 W! [& _6 i* o
, W, `5 u( I  a! h9 ?% k0 w' n    * D2h
! ?( G5 d; e4 Q: J% P6 q5 D( m
$ m, f% r: i$ @7 C准备写数据到Output Register中。随后通过60h写入到Input Register的字节会被放入到Output Register中,此功能被用来模拟来自于Keyboard发送的数据。如果中断被允许,则会触发一个中断。
5 e% [9 X  s8 F" pvoid put_data_to_output_register(unsigned char __data)
6 @4 m& v4 p6 C6 P$ K9 r& l{
) ^. K& l) n+ O/ `, D7 d9 C   wait_input_empty();
: u: U0 G, h6 w  Q: {' Z   outb(0x64,0xD2);5 O7 }, A  a  k$ [5 s( H

4 z! o* H) h' Z& Y   wait_input_empty();9 M4 s2 b" O8 o6 A+ O8 E- u6 Y
   outb(0x60,__c);6 m0 d- m  O4 i5 A9 C& y3 y6 k
}
) I+ q; l# g! r+ Y0 {6 B# s
0 D7 Z  h  Q* |0 E4.2.7.2 发给8048的命令/ k  T( v" e9 p- C
5 B" s. s4 b7 Z" S2 Y7 H' u

/ s( I2 r0 e. W    * EDh4 f: R5 j; l; M5 P2 A

: l. E% G% T" w  j设置LED。Keyboard收到此命令后,一个LED设置会话开始。Keyboard首先回复一个ACK(FAh),然后等待从60h端口写入的LED设置字节,如果等到一个,则再次回复一个ACK,然后根据此字节设置LED。然后接着等待。。。直到等到一个非LED设置字节(高位被设置),此时LED设置会话结束。- W, l% r1 z% o- g+ K# p
* y% C7 n3 L- F; [9 U* e
    * EEh6 i& J" F* Y" L
. d- {, k& m/ f# {
诊断Echo。此命令纯粹为了检测Keyboard是否正常,如果正常,当Keyboard收到此命令后,将会回复一个EEh字节。9 F1 Q4 A2 @8 m  @  `1 O
5 r$ A* D' a* H9 w& @
    * F0h
5 A5 E, q: `* |8 g( ]
4 G7 z/ J) d$ r. Q" r选择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代码所要求的。
6 y. h9 s( D6 t, ^
8 W5 F7 j( ?' D6 F. r' U5 A( l    * F2
: m- c( q4 d' T2 p: u& p2 ^% Q# @% `4 H. [# I! b$ X1 t6 l' l
读取Keyboard ID。由于8042芯片后不仅仅能够接Keyboard。此命令是为了读取8042后所接的设备ID。设备ID为2个字节,Keyboard ID为83ABh。当键盘收到此命令后,会首先回复一个ACK,然后,将2字节的Keyboard ID一个一个回复回去。/ D7 n1 L1 I8 e4 H5 Q% x

% C( ]! t7 q/ }0 F    * F3h
/ a/ ?! p% g1 W+ J! J; ?
! ~4 E( [1 N9 ?0 H设置Typematic Rate/Delay。当Keyboard收到此命令后,将回复一个ACK。然后等待来自于60h的设置字节。一旦收到,将回复一个ACK,然后将Keyboard Rate/Delay设置为相应的值。
: [( b$ D" Z, f3 \* M2 B! h9 _2 J5 o1 X5 G8 J# I/ X
    * F4h
4 C; J- t* b" P2 O: M! w& J* i  M  C" P0 i
清理键盘的Output Buffer。一旦Keyboard收到此命令,将会将Output buffer清空,然后回复一个ACK。然后继续接受Keyboard的击键。" G1 u8 a* m2 n0 [5 m: K

! v3 T! s# l$ `# e* _! z/ `& ~- `    * F5h
" j% o7 j. _8 e) p  k
5 t1 n3 M6 N& Q, g$ @. x* I& ]0 i2 O设置默认状态(w/Disable)。一旦Keyboard收到此命令,将会将Keyboard完全初始化成默认状态。之前所有对它的设置都将失效——Output buffer被清空,Typematic Rate/Delay被设置成默认值。然后回复一个ACK,接着等待下一个命令。需要注意的是,这个命令被执行后,键盘的击键接受是禁止的。如果想让键盘接受击键输入,必须Enable Keyboard。1 u$ [: Y: D! y# ]; D

$ T3 r0 n' o* C; [8 K    * F6h8 {6 }4 Z8 g3 b" }' V2 ^

# y" I2 ^7 w; W设置默认状态。和F5命令唯一不同的是,当此命令被执行之后,键盘的击键接收是允许的。
. [# y  \6 h: ?  ^) Z$ \& M9 j$ I1 X% k6 ]1 Q
    * FEh9 `1 G% ~" X2 Z$ r* `7 c: F

1 m" S& d- K! |2 K3 ^Resend。如果Keyboard收到此命令,则必须将刚才发送到8042 Output Register中的数据重新发送一遍。当系统检测到一个来自于Keyboard的错误之后,可以使用自命令让Keyboard重新发送刚才发送的字节。
* Z) V5 H. m& A' U' z1 G
/ z' I" C& @/ B: R8 {* w% m    * FFh! S$ P' q$ G0 U  W' N3 K; |, c3 W

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

使用道具 举报

发表于 2009-1-14 13:49:16 | 显示全部楼层
好贴!
3 H. k% a5 N. I$ E. e: d非常详细!
$ F, A6 W1 V, n: W$ q( c谢谢!
回复

使用道具 举报

发表于 2009-2-25 17:37:28 | 显示全部楼层
2楼好帖!在helppc的Hardware Data and Specifications栏里有相应的寄存器和命令详细描述。
# M" m; d8 ]8 y  @& L5 n( Z& M5 J$ T+ h  V' o
我的问题是,上述描述应该是针对老的8042的,在目前的使用EC的系统中,这些status register和command描述在哪个文档中可以找到?比如intel的santarosa,使用renessas的H8s 2104 EC,按道理上述状态寄存器,命令等的描述应该在2104 datasheet里,但是我怎么找都没有。还是有某个spec定义了这些命令格式?新手问题,高手莫笑
回复

使用道具 举报

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

本版积分规则

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

GMT+8, 2026-4-4 18:24 , Processed in 0.068222 second(s), 17 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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