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

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

[复制链接]
发表于 2008-7-14 00:04:00 | 显示全部楼层 |阅读模式
bini殇,能帮详细解释一下bios post过程中的所有发给ec的60/64命令号码和意义吗?数据量比较大,截不住。
发表于 2008-7-14 12:09:38 | 显示全部楼层
转个别人发的,不知道LZ能不能用上   5 c; k3 B- |* Q+ y6 q
% T& r3 y4 c. D/ I" c: @
4.2.7 Command
/ F$ f: x7 Q& h% ~4 \9 w/ \/ T  Z, R
通过8042芯片,可以:4 l0 m0 {* H: `
向8042芯片发布命令(通过64h),并通过60h读取命令的返回结果(如果有的话),或通过60h端口写入命令所需的数据(如果需要的话)。
5 b; K$ z& L" Q$ W, v# b读取Status Register的内容(通过64h);
1 j8 p# C$ x  P& R9 x+ D向8048发布命令(通过60h);
, u% s2 G6 W4 s2 C4 [读取来自于Keyboard的数据(通过60h)。这些数据包括Scan Code(由按键和释放键引起的),对8048发送的命令的确认字节(ACK)及回复数据。
0 `( k3 s/ V* `1 _7 G, j8 M# a  E. z5 X
再次强调一遍,Command(命令)分为发送给8042芯片的命令和发送给8048的命令。它们是不相同的,并且使用的端口也是不相同的(分别为64h和60h)。9 U# j( `8 X  e4 ]

! ?6 @* x3 O4 t4 ]; n& J. d0 e4 v6 {

6 ^) e4 S6 q6 T( u  D1 {6 t$ f- ^    * 64h端口(读操作)0 }4 g  @2 u3 y7 H2 M4 s. U

1 n' l. `, H9 Y
+ @& `& i0 e7 J6 s对64h端口进行读操作,会读取Status Register的内容。+ U: q; v: ]! Q* Z$ D7 b3 ^; x
4 `1 W" E/ i: z+ f' o) ]% c
inb %0x64
1 ~% ~# i$ ~* ~3 p" m执行这个指令之后,AL寄存器中存放的就是Status Register的内容。- e6 r$ a" J' x$ h
0 I- m4 H" U0 L& v/ m: r7 `- L
    * 64h端口(写操作)
3 ~2 b1 s3 f  O' I3 m7 U7 d5 \% k; q5 S6 a  X
向64h端口写入的字节,被认为是对8042芯片发布的命令(Command):% T9 u$ u6 B  J* V
Ÿ
* m" m3 {, K# L2 k; N* P写入的字节将会被存放在Input Register中;& F* W  m0 x3 |$ J- I( h
Ÿ
. C, A& s- m5 D+ O4 r5 k同时会引起Status Register的Bit-3自动被设置为1,表示现在放在Input Register中的数据是一个Command,而不是一个Data;
$ f8 J$ z6 a. b2 CŸ! [) w9 P) J, Y- ?+ ^0 [
在向64h端口写某些命令之前必须确保键盘是被禁止的,因为这些被写入的命令的返回结果将会放到Output Register中,而键盘如果不被禁止,则也会将数据放入到Output Register中,会引起相互之间的数据覆盖;# s3 Q/ v3 m5 s  s$ A9 J7 H
Ÿ
  [: P( _9 }9 I+ t在向64h端口写数据之前必须确保Input Register是空的(通过判断Status Register的Bit-1是否为0)。
" s- [) L6 I- ]. @
! @" V; U" {# T0 z8 V! l) z" svoid wait_input_empty(void): B8 q. a3 J' @- e7 f! E7 i
{
1 O" E6 P9 ~, c" {# z; k5 Z   char __b;# @! E1 Z, s, B
6 n. m. Y) k* l' W+ j. M4 p! c9 e
   do{
6 M5 V# w7 U+ ?' `7 _     __b = inb(0x64);5 ^; w+ y' q& o# W% h$ G  E
   }while(!(__b&0x02));
# Z  G$ j0 @( a- Q7 Q}4 Q; F9 P2 v9 }
6 v- b3 O! ~/ m2 ?4 o7 C
void disable_keyboard(void)( q* d% l( B1 E8 Z
{
: F$ V2 M: e4 Z' P- y. }5 W1 A   wait_input_empty();
& m. y; ?) _. @6 i3 `   outb(0x64, 0xAD);
+ ]) `" y: S/ O3 q1 e. C% m9 j}[size=+0]. o7 E9 v5 k9 V9 N: {9 }

9 P! z# d' n0 v; s# W    * 60h端口(读操作)
2 k0 z6 n; ?' X4 q% R: z4 ^3 t  Z9 M  S* \: p! T$ |
对60h端口进行读操作,将会读取Output Register的内容。Output Register的内容可能是:
; {( l$ V, `8 r9 b: s/ C2 F- ^Ÿ           来自于8048的数据。这些数据包括Scan Code,对8048发送的命令的确认字节(ACK)及回复数据。: s" a' s1 j2 V5 L# n+ v& j
Ÿ           通过64h端口对8042发布的命令的返回结果。! O7 k8 z" T( c! \

: T+ @. G5 A1 ~9 {5 S+ _在向60h端口读取数据之前必须确保Output Register中有数据(通过判断Status Register的Bit-0是否为1)。$ _- O. m* N9 ?& q& J  R
void wait_output_full(void)1 Z% Y6 n. V# V# y. u
{7 d2 h7 \( e- {9 S
   char __b;! U0 @- Z0 j; r7 h+ j( N

. g  l# H' w* o5 _   do{: h. D. b' h/ I, k! [- t
     __b = inb(0x64);
3 r7 ~& A- o3 |2 m; K2 Y   }while(__b&0x01);) M+ f, |* ?- O0 i
}
+ k1 |1 o, s+ |5 s, M5 ?  ^. A  v
unsigned char read_output(void)5 \  I8 |/ i+ z1 B! P
{
8 e1 ?/ J. e5 o6 c   wait_output_full();
1 W1 r: B: H( P2 U$ Z; t" t   return inb(0x60);( V- o3 v' ~9 _: z4 h9 Z
}) k; X) ]3 a( \) _# _
" d; _; s$ h* t1 \+ |4 M' _8 i
    * 60h端口(写操作); t; J1 @9 Y+ n3 ]4 i

, `" ]' ~% C4 @2 Q4 Y) y向60h端口写入的字节,有两种可能:8 h& x) N! Y  F1 `, @) Y2 y
1.如果之前通过64h端口向8042芯片发布的命令需要进一步的数据,则此时写入的字节就被认为是数据;& o6 ^$ N' y5 T, L1 \  w2 i
2.否则,此字节被认为是发送给8048的命令。
8 r) D! v8 C! D% \) `$ l8 G* {  a" J  |7 l
在向60h端口写数据之前,必须确保Input Register是空的(通过判断Status Register的Bit-1是否为0)。* D) L* c; q% x3 p, E% U

) i0 U- }! K4 A$ B3 i6 a+ p5 h2 ?# U0 H7 e, C
[size=+0]4.2.7.1 发给8042的命令: n% }1 B' U3 W9 A' F, p  H/ {2 A

/ X: M3 I: `: ^% k6 Q" N    * 20h
) g; C& }' x' k% F# P8 l) Z; q1 F- a7 L9 S3 \* i$ g
准备读取8042芯片的Command Byte;其行为是将当前8042 Command Byte的内容放置于Output Register中,下一个从60H端口的读操作将会将其读取出来。- S+ F4 g( S7 v8 m# D  S
) J, k. l4 @; y$ t4 L# C* g5 @% L

9 H, U7 `& x2 a. O1 Z+ P( I& a; zunsigned char read_command_byte(void)
" R  J3 x; S' m# T" [{
6 m/ c9 v0 V% {7 ~5 k% j   wait_input_empty();
" X: ^/ x; k# C, d5 \( W   outb(0x64,0x20);
2 ~9 q  V* `0 K. x5 ^   wait_output_full();
: \* K' k' A% |; R; j   return inb(0x60);   
6 J: w! \2 J; ?}- T5 h/ k6 u6 v4 j" e+ r2 s+ T
' J7 q& r  r6 h
    * 60h
' o3 H8 W/ v9 }  P9 ]  P+ \5 w% @. v5 K7 J
准备写入8042芯片的Command Byte;下一个通过60h写入的字节将会被放入Command Byte。9 y% j5 o8 r7 K, R5 a; b& ?4 F

7 M6 ?; n! K, o8 P* v3 z5 F1 Q: t6 @' G
void write_command_byte(unsigned char command_byte)+ {, b0 p* B; v" b3 D7 W, n6 K
{7 o) H4 e8 S* [, C$ d5 F
   wait_input_empty();. R- h$ [' s# Y# n+ H; u6 p3 }
   outb(0x64,0x60);
3 k3 ~- |9 o8 |   wait_input_empty();1 |' q. E$ l6 G/ t
   outb(0x60,command_byte);
1 F. p8 g( y  `. j3 ^}
8 H7 N1 p6 ~: ]+ P2 b; W
% }. M# a0 y2 R# D& ^# H- j$ @, y: l( f9 }& G: u8 r, X  q8 b
    * A4h  i1 ]- u& q# C. ~0 l
1 l" `: c: Q2 o1 p
测试一下键盘密码是否被设置;测试结果放置在Output Register,然后可以通过60h读取出来。测试结果可以有两种值:FAh=密码被设置;F1h=没有密码。! g* |8 @' g% k; a
bool is_set_password(void)
2 X+ @/ p: c4 v3 Z{
- B% z; V: ]. Y/ v/ |! h   wait_input_empty();9 {' P( Z$ e, C8 @
   outb(0x64,0xA4);
! r: p5 l, J3 B  Z   wait_output_full();- V3 t# b; A% M& n( y7 M
   return inb(0x60)==0xFA?true:false;   
7 C$ q8 V8 ]" T! }6 }) J+ {}# ]6 ~% A+ y3 y; Z; p  q  u, s! @) ^
# q  z' ~3 i8 D
    * A5h
) t1 n0 C! }0 a5 S- c- t1 Y
- i" ?+ Y5 B( [设置键盘密码。其结果被按照顺序通过60h端口一个一个被放置在Input Register中。密码的最后是一个空字节(内容为0)。4 t5 `- d7 c" N5 z  m% a
void set_password(unsigned char* password)9 g, S! _/ ~. B
{
6 u( s" E6 H" e8 `   char* p = password;
- X& q' u% }( p1 _% q' J9 X& J; S3 ?* [. h) E( R5 q- ]4 I+ ~' b5 L
   if(p == NULL)
$ u! `* t4 \8 a# Z: U2 g6 s5 ?8 Z: L7 K      return;
, a: n  S/ X# I# P4 P
7 f2 ^  A' r, n5 O, J2 ^2 X. s3 V   wait_input_empty();5 {6 b: |2 Z. P; u" p
   outb(0x64,0xA5);
6 e; ]" w; U, [, F; M1 t# q* ^# q  v
   do{/ _( L! P$ d! {- P6 V2 G
      wait_input_empty();
! m0 K! Y; c; w$ w1 G+ z      outb(0x60, *p);1 r( j- y# L7 z/ D# m
   }while(*p++ != 0);
- t+ x" G7 {7 ^! C+ q+ l0 X}
. B1 g. a% D# P9 o
# A( C4 V) H  R    * A6h
% X) M, c% S, T; z  i8 P% w. m- A: z! U- x& o9 _
让密码生效。在发布这个命令之前,必须首先使用A5h命令设置密码。; n+ _' t' e* C$ H- A
void enable_password(void)* Q# }4 N  B0 b* h) j( t2 [' B' r
{. ?& Y+ x) b/ t8 G8 n) N
   if(!is_set_password())6 }4 v! N9 m: ~  Q- I
      return;+ c! j8 ~7 y- b# @, y

9 t3 u7 C* m) h1 R  f   wait_input_empty();1 i/ j0 r, Z6 U8 ]6 j! L
   outb(0x64,0xA6);   ( ]/ J2 A" W9 U2 M% t- P
}6 _: [2 h8 p" c

: M2 h# l7 I+ A' l: T    * AAh) H# P* K/ Q0 n/ E$ W  w

4 {" D9 i# F4 C/ s/ v) Z  v8 H自检。诊断结果放置在Output Register中,可以通过60h读取。55h=OK。
  z+ C( k. r  C& D- _4 h
: d# Q# q" u6 j6 o6 ?5 I5 Q' S4 r  E5 P
bool is_test_ok(void)% v  J0 ^7 }. t$ S" U" N
{
+ f4 |: r$ W, c   wait_input_empty();
9 Y" F) z  n5 Q+ P) B4 R, V   outb(0x64,0xAA);
; l9 D4 V# u- m8 g$ I" m' j
$ ~' y$ o0 g8 {. }, ^
, j" }! j5 h5 R5 X6 ^/ T+ V, q   wait_output_full();3 Y3 x- }+ w6 ~3 l
   return inb(0x60)==0x55?true:false;   ! ~1 s- f: Y/ Y0 s  k, m
}
( y5 \& q1 m) q) v
5 q0 t0 v3 g& A" m: `# `7 l. \/ {" f8 f- Y8 B
    * ADh
  N( L  t9 e* Q6 E' _
5 [* R8 J) g1 ^$ H4 s2 W4 z) |1 ^1 s0 \( y禁止键盘接口。Command Byte的bit-4被设置。当此命令被发布后,Keyboard将被禁止发送数据到Output Register。
. [7 l! S1 w2 p: O0 l1 X! _  u% p2 A# Fvoid disable_keyboard(void)
: P% i- d- X& j2 I3 h% r{2 n" t1 z( @$ G, F
   wait_input_empty();
" V# Z! ^4 Z- d& Z   outb(0x64,0xAD);
( ?2 E! C1 x. S+ X+ v" V+ i6 x8 l3 t: J. m9 H
}
2 O8 I, x! y: c9 D) l" W5 L' l2 J9 G1 I6 w! y/ H
    * AEh
$ J- @4 ?9 P, v
9 X2 ?$ H: C$ y( d- Y1 t打开键盘接口。Command Byte的bit-4被清除。当此命令被发布后,Keyboard将被允许发送数据到Output Register。, j7 l( @, H5 e
void enable_keyboard(void)
) n* o. x. F! [0 X, a{
  s/ Q2 O$ y$ O. a   wait_input_empty();5 ]: w- j! d8 g6 {$ n5 e
   outb(0x64,0xAE);
6 `' p$ v9 L  G2 Y6 y2 M( j2 d0 a" r  u: ^+ J
}
& u; J+ U: l4 Q2 R$ r9 Y; c( b: Y5 {2 E' \( p) T: D1 P) K: t5 l
    * C0h
3 J; y# A( r8 C5 V# z  ~8 ?& {3 `6 u. A* w) Y; J$ b
准备读取Input Port。Input Port的内容被放置于Output Register中,随后可以通过60h端口读取。9 w9 E( y) B' g( {+ F( {# [7 L
unsigned char read_input_port(void)
* D8 g" k! Z6 M0 q" o2 H- R4 u  Q; d{; F7 N- h4 S# h" g
   wait_input_empty();
; [# t, V! ?+ ?. X   outb(0x64,0xC0);
  l4 p6 U+ j+ m9 Q' H$ S, R
- W0 ~+ b. {1 b- b9 s   wait_output_full();
. d9 B- I" c1 t8 A7 d( K# l: v. r* r$ v
   return inb(0x60);1 M( m. J6 y% ^0 y# g# Q
}
9 X; |' v. A! S8 W7 g) M, `# @4 Q# Y0 `  y. @% L7 \
    * D0h
! o& ?/ u) U! L. R( B$ B9 h. v5 ~# Q9 r/ d, u- p
准备读取Outport端口。结果被放在Output Register中,随后通过60h端口读取出来。
; F6 M  U: ^- m* f9 m7 i2 {unsigned char read_output_port(void)
$ k3 X  `6 |1 S+ @; {9 Y{
" u7 `3 [+ k2 g' `' u. Y   wait_input_empty();
' R) p5 `% _$ [6 g& ^   outb(0x64,0xD0);
. _) @1 d) M5 [: ~# h9 ?- k' ?
. y8 ]( I- D& F+ `6 F, @   wait_output_full();# S/ X. p% i+ X; s

) L0 P% h; f0 u% z   return inb(0x60);' f/ z. h: ]3 A# q4 J  v
}5 o& c6 v, T4 N

+ N* F; K  p# f: _, M2 h/ W    * D1h" F. {9 q' Q0 `/ n% A
, L5 ^, [! _& ^8 _8 R0 F9 p
准备写Output端口。随后通过60h端口写入的字节,会被放置在Output Port中。3 i, \5 @9 v( _+ i
void write_output_port(unsigned char __c)  s8 a# |# {5 N& V2 |
{% F" R- [3 q/ f' {+ N- E
   wait_input_empty();* r+ z. m6 k7 j
   outb(0x64,0xD1);
% V4 _# E7 A% ~( @/ X9 m, B/ S& ~7 k0 v" u1 ?
   wait_input_empty();# L- t: d4 L2 U4 {  J. H
   outb(0x60,__c);5 g# H: U1 Z) A+ _+ z8 S/ ~  W
2 z+ j# u* V  w
}# I+ U$ H2 l9 `9 F

. c$ Z2 G. J9 ]
  y5 P. d  T$ `1 c    * D2h* P5 h4 p; q/ l4 q! Q/ f

2 N* h9 w; U; v0 P7 L1 Q准备写数据到Output Register中。随后通过60h写入到Input Register的字节会被放入到Output Register中,此功能被用来模拟来自于Keyboard发送的数据。如果中断被允许,则会触发一个中断。
- W( p/ N( l- _) o( c7 Nvoid put_data_to_output_register(unsigned char __data)
0 {$ }+ T5 ?& T4 Y2 M1 b{$ _; @+ `6 T3 p# O1 @
   wait_input_empty();
- d1 x0 T# ?: m. }( p1 J, t   outb(0x64,0xD2);  E( x8 ?- Y3 E! s  ^. F7 a

) u( @7 m2 c7 r   wait_input_empty();; f! b; T# K1 T/ L4 g* |6 i- R: N0 t
   outb(0x60,__c);" @4 T& L4 _7 k& [" J# d
}
0 c, {! n; A$ b3 @/ \' ]! L' B  A$ e% X' h1 I2 ]( e
4.2.7.2 发给8048的命令
* w+ K# N1 n  h) V+ u
& ]9 ^4 N8 B" H3 d# u; ~
  z+ x& E& t& o% k/ W    * EDh$ w5 L3 b# r, Z; ~* L% a
% G; C; Q9 r5 W1 l0 O3 }
设置LED。Keyboard收到此命令后,一个LED设置会话开始。Keyboard首先回复一个ACK(FAh),然后等待从60h端口写入的LED设置字节,如果等到一个,则再次回复一个ACK,然后根据此字节设置LED。然后接着等待。。。直到等到一个非LED设置字节(高位被设置),此时LED设置会话结束。( }6 p% S1 g, K& J1 l

* Q5 @4 D( u. o2 Y: Z    * EEh% N/ L% o! }- z# L
# S4 k( N5 E& j
诊断Echo。此命令纯粹为了检测Keyboard是否正常,如果正常,当Keyboard收到此命令后,将会回复一个EEh字节。) ?. G* f# L' m' {
( u$ ~+ h7 L+ p. L
    * F0h6 s) X/ t8 ~& L9 I
3 \& r% ~2 {. g  Y% V( p
选择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代码所要求的。# ^* C4 P, z) ?; b  i, }3 e

7 o( }: D" M8 r, {9 L    * F28 [8 Y9 P. l: d. J
8 v7 |0 K1 Q1 U7 [7 t
读取Keyboard ID。由于8042芯片后不仅仅能够接Keyboard。此命令是为了读取8042后所接的设备ID。设备ID为2个字节,Keyboard ID为83ABh。当键盘收到此命令后,会首先回复一个ACK,然后,将2字节的Keyboard ID一个一个回复回去。0 f$ l/ ]; C# r! F
3 m* M  q  g% J& f# v: ^
    * F3h
' e( ~" Q+ `: G9 {# q, m1 |8 Q+ t* U* ~* K
设置Typematic Rate/Delay。当Keyboard收到此命令后,将回复一个ACK。然后等待来自于60h的设置字节。一旦收到,将回复一个ACK,然后将Keyboard Rate/Delay设置为相应的值。* Q# R: W5 c& x  a

7 M7 j1 P7 D! O1 D: v    * F4h% s9 z- @% v! @6 R6 [4 \

  g- l* p) m7 {2 b5 w1 h' `清理键盘的Output Buffer。一旦Keyboard收到此命令,将会将Output buffer清空,然后回复一个ACK。然后继续接受Keyboard的击键。( f& J* g( y# q
; t2 J  U: O5 A5 ~, J4 k# l
    * F5h4 L; t) g9 p2 y% ?* ]
7 M" f6 @% |7 o! V* @" f# |" I5 q
设置默认状态(w/Disable)。一旦Keyboard收到此命令,将会将Keyboard完全初始化成默认状态。之前所有对它的设置都将失效——Output buffer被清空,Typematic Rate/Delay被设置成默认值。然后回复一个ACK,接着等待下一个命令。需要注意的是,这个命令被执行后,键盘的击键接受是禁止的。如果想让键盘接受击键输入,必须Enable Keyboard。' B3 J& N! m: ]9 j( b# `
, e. ?- M% p9 Z, {/ K
    * F6h, o4 F$ V5 K& u. @
( ]2 `6 V6 [) z# Y6 h
设置默认状态。和F5命令唯一不同的是,当此命令被执行之后,键盘的击键接收是允许的。
1 z+ l/ j0 ?8 b  t6 R) i$ I
3 N+ F* L: e! R8 |! W    * FEh
) s0 S5 z7 M, Z8 h+ P, V& \) L  [; a# j9 h7 J
Resend。如果Keyboard收到此命令,则必须将刚才发送到8042 Output Register中的数据重新发送一遍。当系统检测到一个来自于Keyboard的错误之后,可以使用自命令让Keyboard重新发送刚才发送的字节。8 Q# @4 @! o, y5 t3 S5 B

- Y; i# L( L. Z7 a; j) n6 l    * FFh
+ w2 {% V, m: ?9 `+ ], d0 C& I9 t7 F- Q5 h
Reset Keyboard。如果Keyboard收到此命令,则首先回复一个ACK,然后启动自身的Reset程序,并进行自身基本正确性检测(BAT-Basic Assurance Test)。等这一切结束之后,将返回给系统一个单字节的结束码(AAh=Success, FCh=Failed),并将键盘的Scan code set设置为2。
回复

使用道具 举报

发表于 2009-1-14 13:49:16 | 显示全部楼层
好贴!$ l; B* {. u, u1 v& l7 b1 O
非常详细!) E; k5 v8 w' m! f
谢谢!
回复

使用道具 举报

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

使用道具 举报

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

本版积分规则

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

GMT+8, 2026-6-29 04:09 , Processed in 1.459113 second(s), 17 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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