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

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

[复制链接]
发表于 2008-7-14 00:04:00 | 显示全部楼层 |阅读模式
bini殇,能帮详细解释一下bios post过程中的所有发给ec的60/64命令号码和意义吗?数据量比较大,截不住。
发表于 2008-7-14 12:09:38 | 显示全部楼层
转个别人发的,不知道LZ能不能用上  
! X9 x6 S' }' {% q
; h8 q* h6 M3 H+ q4.2.7 Command
) m7 Y, m/ t* W# p7 x" E, e  ?
! Q( s$ d& N  d. ~9 A2 E: D1 l通过8042芯片,可以:8 Z" t4 |/ I$ a
向8042芯片发布命令(通过64h),并通过60h读取命令的返回结果(如果有的话),或通过60h端口写入命令所需的数据(如果需要的话)。/ l" Y  T: D& f# F* S
读取Status Register的内容(通过64h);
* ?+ T& _$ S: }. @9 r6 Q向8048发布命令(通过60h);
1 n9 D6 k8 g+ k! y- g& V# g读取来自于Keyboard的数据(通过60h)。这些数据包括Scan Code(由按键和释放键引起的),对8048发送的命令的确认字节(ACK)及回复数据。, U* s' A8 h% f1 ]
5 r. V$ u6 b8 e
再次强调一遍,Command(命令)分为发送给8042芯片的命令和发送给8048的命令。它们是不相同的,并且使用的端口也是不相同的(分别为64h和60h)。0 M- R8 X3 b4 y6 u9 |' \" j' N
0 X3 t  s2 @% [6 V2 y+ ]
' ]/ U0 s# D* v. v( q+ O

# L2 Z8 ]" ?& f    * 64h端口(读操作)3 I1 x" C! c9 T% F3 Q3 @& W$ F
7 S2 f0 H, z' N9 ?
2 t  @: L+ V/ L- `
对64h端口进行读操作,会读取Status Register的内容。
& u% _: t* e# r; ~# F- Y! T4 E( [6 N9 }5 u# ]
inb %0x64
# t% @0 @. l6 A# G" N$ n5 r执行这个指令之后,AL寄存器中存放的就是Status Register的内容。7 [# M# I8 A0 N5 a/ l- s' F$ T' U
$ L" w2 @: s  N0 [
    * 64h端口(写操作)
% f: F, A' A+ Y7 _1 d) O- s: a
/ M. C" [9 z' h向64h端口写入的字节,被认为是对8042芯片发布的命令(Command):. R! B6 G( W+ v8 Z# G
Ÿ
3 X1 ?- v$ p- O写入的字节将会被存放在Input Register中;1 c, |% _! y/ S4 X0 T& i
Ÿ0 q; Y7 h# O1 E7 P
同时会引起Status Register的Bit-3自动被设置为1,表示现在放在Input Register中的数据是一个Command,而不是一个Data;$ i. K9 y8 T( ], s
Ÿ7 K  R, p+ }9 N
在向64h端口写某些命令之前必须确保键盘是被禁止的,因为这些被写入的命令的返回结果将会放到Output Register中,而键盘如果不被禁止,则也会将数据放入到Output Register中,会引起相互之间的数据覆盖;
3 q9 a0 l& I; U$ I0 M( wŸ1 K1 h& c' q5 d4 t
在向64h端口写数据之前必须确保Input Register是空的(通过判断Status Register的Bit-1是否为0)。
* M: a5 l, p4 v) u" }" t1 G: |+ E
void wait_input_empty(void)
7 G% e: M+ d8 W9 o. X6 c0 B3 u{4 L8 p; [) M6 S2 w- {, t
   char __b;* u( s; f+ \% c2 E

( H& i# f1 R3 M2 G. s7 T+ p! I   do{
% Y4 F- _7 l! t! R9 `" D1 v9 F     __b = inb(0x64);0 R+ r  k, G. N$ x! X
   }while(!(__b&0x02));
: h: f+ U1 G" D& M! J}4 R( T6 A8 g; p+ ]5 H
# @4 f% V2 V9 W; i! h6 j) s8 I
void disable_keyboard(void)
% G* |( w% g$ h8 `4 ^. w{5 N7 U: h5 e  F# Q. n% e6 C0 j7 @! l
   wait_input_empty();
* ~2 s7 L3 w6 O, M7 U   outb(0x64, 0xAD);
  f% s+ t: Y7 Z}[size=+0]" ~9 @/ J& D6 Q$ Y" p

7 d: R( [; o5 D9 |    * 60h端口(读操作)- L8 j1 x! M9 o$ c
+ }8 H4 @; h8 ?$ O' k8 b
对60h端口进行读操作,将会读取Output Register的内容。Output Register的内容可能是:0 o. ~( o- I3 y/ o. X' ?
Ÿ           来自于8048的数据。这些数据包括Scan Code,对8048发送的命令的确认字节(ACK)及回复数据。
1 f& ^$ L' Z- M6 x0 E0 ^  E# RŸ           通过64h端口对8042发布的命令的返回结果。
5 c8 M: C0 ]" u$ d! P9 ]6 e& \
; c3 M# e3 C2 K0 G% R3 B! t在向60h端口读取数据之前必须确保Output Register中有数据(通过判断Status Register的Bit-0是否为1)。1 P; L8 U) K/ t2 G/ T& \
void wait_output_full(void)# D7 y% d( E1 N+ j" L% ^+ h4 I* M
{
, I5 k4 o7 _1 e: d; D& i   char __b;
& O, z! f  X! V9 q  I, H: m* ~- o6 e8 y- c
   do{
, F- [# k% y! |" H     __b = inb(0x64);  {( w/ V% \8 e4 R! o7 g
   }while(__b&0x01);5 R5 x5 t6 p# _# X7 D# N
}
+ m2 [  Y, D1 R6 D4 W, n( E  W: B' E" }7 @2 q% X, c. f6 T0 m' a
unsigned char read_output(void)+ e% j( s. D  G" W
{
" U" p6 Q, Z5 K+ j7 b& Z   wait_output_full();
5 p: a! ]0 p% |# e   return inb(0x60);4 \# k3 @  R+ F+ y% N
}/ ], S6 Q5 x% W

3 Y* ?$ b- u" \" w3 X. D0 W* k    * 60h端口(写操作)
2 ]3 i3 s% F- q% ?8 O2 j& W  |+ H9 R- Q
向60h端口写入的字节,有两种可能:) G- a4 v+ D# D% T0 S1 s
1.如果之前通过64h端口向8042芯片发布的命令需要进一步的数据,则此时写入的字节就被认为是数据;
; f6 l/ ^, `1 i. C' t2.否则,此字节被认为是发送给8048的命令。( Z' E8 X: x, V8 G; u$ O3 ?

- S$ K. a, X; D9 S在向60h端口写数据之前,必须确保Input Register是空的(通过判断Status Register的Bit-1是否为0)。
0 p* H8 i8 T4 }5 t- f
4 f8 F7 r$ T' \/ M; c1 L. B3 h4 {! d- E0 ~9 }6 a- G. p, }
[size=+0]4.2.7.1 发给8042的命令& }' E6 s. F; t5 W8 |8 x1 |9 D

' C3 L+ T) l8 O  x1 B* \3 A    * 20h
) i1 o! p+ K5 ?0 \) }/ k9 l* T* Z, U& ~/ R3 k
准备读取8042芯片的Command Byte;其行为是将当前8042 Command Byte的内容放置于Output Register中,下一个从60H端口的读操作将会将其读取出来。/ i5 r* C2 e# U8 e' m5 C# I$ g& t  I

! s1 R- e' _- J, G2 ?3 x  m/ ?
# H% |% f3 S6 _& c9 ?7 \- ?; qunsigned char read_command_byte(void)4 Q7 z: K4 O% I6 Y5 ^* U
{
. Z% Y3 Z2 O) L# V2 t2 I   wait_input_empty();7 L8 b0 N+ s, i/ b; }/ W
   outb(0x64,0x20);
) B5 @2 j: V% l# C6 I   wait_output_full();9 F" U0 U, b; c: q) H
   return inb(0x60);   
- \/ e4 E7 h9 X/ d3 |2 B}
, B  {; z" i; @# B  d: `, P3 f9 l1 |+ f
    * 60h4 R4 r$ x7 R9 f

9 A, T6 E* X# @/ G+ [. H( C! B7 t准备写入8042芯片的Command Byte;下一个通过60h写入的字节将会被放入Command Byte。
# `, f' a& P! v. F# x& e# O5 |& {. a& s, S; E1 u

$ @7 m- C; `, pvoid write_command_byte(unsigned char command_byte)
; h- o3 L, E% _5 \+ `{
4 o! h1 [. U* w" K$ t$ z   wait_input_empty();: [6 }  [& a/ Q; i. `
   outb(0x64,0x60);
. B5 P/ w# ~0 ~. g8 y( ]1 i. Z   wait_input_empty();
. |7 w8 @5 T& S' @+ \" m8 C, _   outb(0x60,command_byte);# a( @! h/ [. Y
}* Q( ~2 B1 U; D2 r" B8 I( v) N* G
. X* v8 I' t# e& P# d* [8 p

. j4 [# c7 }% V    * A4h
3 J: i7 c& e4 q! h
( r. r! t2 X4 O3 j* B, P! Z% F测试一下键盘密码是否被设置;测试结果放置在Output Register,然后可以通过60h读取出来。测试结果可以有两种值:FAh=密码被设置;F1h=没有密码。* e5 T5 }/ A0 @! @' p5 c
bool is_set_password(void)
# Q$ U3 L2 N+ z( j1 ^. l5 p{
: x* y& R: S' `5 q# X   wait_input_empty();" g% m0 z- {1 T  A
   outb(0x64,0xA4);
( W/ e& r" F# }) R  m   wait_output_full();
- R$ Q3 n4 u# K) N# D8 z% {   return inb(0x60)==0xFA?true:false;   $ u+ T7 P% B1 c. |4 Q- \
}. [! Z2 k: t2 H- X4 i& f5 e
. J& L% a) [6 g& u2 I1 L( O
    * A5h
- c9 ~9 d1 Y! S+ V, B
) F  O( p" I. ~( v, V  W设置键盘密码。其结果被按照顺序通过60h端口一个一个被放置在Input Register中。密码的最后是一个空字节(内容为0)。: _0 X7 a, [% u
void set_password(unsigned char* password)( A- [- m$ n& [$ @6 _. v
{
1 k/ g5 S6 H& f, M/ Q6 M   char* p = password;( V# L3 }! c: Q  C* U: A

- B  P% F. x3 j$ {   if(p == NULL)
6 R9 w9 N' p: z/ q8 g% e      return;+ e* i7 S3 j) Y! Y
0 a; S0 m- l9 g0 H2 {: i& J: `
   wait_input_empty();" j' I7 s7 o# o$ X# O& G# i
   outb(0x64,0xA5);
4 D/ [; P% `0 i. S
7 _7 L  ]% Z9 v6 \   do{4 _; u; o' l5 {2 t$ n. L
      wait_input_empty();% c' z4 O) w* a) s' M( M% E
      outb(0x60, *p);
, o/ u- y! j0 X5 p2 i   }while(*p++ != 0);
6 Y8 v6 _% u. Z* Y6 H% o}
9 e3 c$ d0 D( o
1 @4 C- ]( s( L: c. R    * A6h( `5 X0 L3 x$ w4 r% l9 p" b- I$ m: K
# E( f* p. K' J  P
让密码生效。在发布这个命令之前,必须首先使用A5h命令设置密码。- C1 f7 N' G# s" k' B, d. m$ v  x
void enable_password(void)- y0 U. x3 R6 ^: h8 b
{
1 @+ ]& ~; y$ @+ [6 ^. ^' S4 ?   if(!is_set_password())9 z/ e  H, c) Z5 q  H
      return;
: X2 s% _$ c0 J  Z" j; {
# d4 J( X4 i5 j- z+ n- t   wait_input_empty();: {) D; X* D! S+ z0 {/ P3 [& l! j: z
   outb(0x64,0xA6);   * L8 W* h$ W7 s  Z4 s- z
}* }7 g9 z. e0 q( V: T

" T4 ?2 N2 c2 ~* b& y8 U; j9 M1 J. Q    * AAh
& E) [- j5 i1 n2 a" [9 c. U% J; o+ b% a
自检。诊断结果放置在Output Register中,可以通过60h读取。55h=OK。* a5 W3 R4 g% o# I, U
/ ~# t, x- i, M3 G

2 e  S( m. c" m' h; Q$ U+ i& obool is_test_ok(void)
8 ]! S& u( H  L+ Y; s0 N{+ A% I5 u, }& @
   wait_input_empty();
) G. w# O3 Z) u# p   outb(0x64,0xAA);
' [% P4 O5 h: i$ [6 K8 ]* @) H1 t( k* i) k

& L7 P, i  B% l5 \" h* |   wait_output_full();2 u7 X/ g# O0 Z/ a; q. {3 {7 v
   return inb(0x60)==0x55?true:false;   
7 K( e+ M0 h- e% ^* ^' S0 B}0 e; f/ v5 I- Y. n. x( k

5 L" x& o; V( Y6 K" Y% v5 K  L& l) Q$ B9 J
    * ADh( x( }1 I) y0 v4 F- a& b7 A

+ Y3 i2 r$ h3 Q& D! y/ @禁止键盘接口。Command Byte的bit-4被设置。当此命令被发布后,Keyboard将被禁止发送数据到Output Register。  L; x+ a5 X. K. D
void disable_keyboard(void). J8 h+ [7 N  ~% T% |5 C
{8 I- p1 s) J1 h  l# u
   wait_input_empty();+ I) u; Q$ n* p# d$ |$ e7 m6 r. h
   outb(0x64,0xAD);' H2 T& f4 y* w# r
5 S! R5 h: k  Q2 D0 ^; u8 F; d
}: S) T" B# K. d: E+ N% b. c( m
: _" a6 d' i, W7 s0 W; w& K9 W
    * AEh
/ @6 n! J3 D1 P5 U1 o, }% D7 e1 Q; m* F% u' W; [
打开键盘接口。Command Byte的bit-4被清除。当此命令被发布后,Keyboard将被允许发送数据到Output Register。
) }+ J4 }' Z8 Qvoid enable_keyboard(void): p: y( t8 ~: m1 k* ^) C: i
{8 C; D) q& @0 `# \" b
   wait_input_empty();
  v3 v" D& C+ i* @/ i! p   outb(0x64,0xAE);
9 x% Y4 Z2 R# h) j( v
, @; E6 g5 d: P}, o! _) m; p. E) ~9 O6 V; o8 n
$ h- G& h" O+ l$ ^" ~( I% p6 k8 r% N
    * C0h1 P; J+ N8 C( P5 I9 V: T

. T) T5 B6 @  E7 }  a; ]7 a4 ]准备读取Input Port。Input Port的内容被放置于Output Register中,随后可以通过60h端口读取。
, B% t5 S  U# a, q8 ~2 E/ R8 dunsigned char read_input_port(void)
, b3 b$ P+ O& ^0 @: y' E0 {{
1 f5 ?7 [* Q; \0 ]" d/ E: [1 F2 ^6 n   wait_input_empty();7 u( b2 v9 f  s0 c
   outb(0x64,0xC0);
1 r" W: G! j% R# l
: `5 c& {* Q' a" m   wait_output_full();: {6 s2 s( }# I' P
- Y7 j5 I, A5 R4 ^
   return inb(0x60);4 D" [3 b6 k+ U+ F
}: A! C) s5 m2 G
& g3 o0 Z; @3 p/ a9 f
    * D0h7 i0 p4 s  D& c* X$ F

* O' s0 s5 P6 B准备读取Outport端口。结果被放在Output Register中,随后通过60h端口读取出来。
/ H3 |* J& ?4 W1 Q$ Dunsigned char read_output_port(void)4 ?( {( t: K/ j0 a& n: h
{, a3 e5 J8 T; O& |4 O5 t
   wait_input_empty();
6 i' p/ g: j3 u& j1 d5 f   outb(0x64,0xD0);2 H: T2 t- @- G5 [2 Z) J- o# ?

$ _* M! T, k3 e   wait_output_full();
3 g6 Y8 Z( E7 c) C, M+ o5 Z1 P6 a& L
   return inb(0x60);* W8 x; V+ x2 }6 D9 D) d& M+ ^
}
8 \% {$ N; ^# k  v6 M' w. K1 s% y6 {) r
    * D1h
4 g. j, K# D8 |2 p' ~' j. X) k3 r9 {/ q
准备写Output端口。随后通过60h端口写入的字节,会被放置在Output Port中。/ d# O; U) i- ^% C
void write_output_port(unsigned char __c)
! Q8 E9 m7 l: ~5 r( m% H5 I6 y{  W4 a+ d( D# P. q# C
   wait_input_empty();  s: z. ~9 b1 G9 k
   outb(0x64,0xD1);
6 M1 \- M0 \& Z' M- B- p
! T% H6 A9 _8 r& i   wait_input_empty();
6 A9 d/ p8 ?$ j7 d   outb(0x60,__c);
8 L2 R. y8 P: C* z8 F0 k) Z. _' ^( Q, E6 \
}
% O2 J/ [; Q! s, s: m1 ]& ^: M; J% b2 e0 g( _
9 K$ _; K$ y5 S
    * D2h3 n2 @; a$ }" c! z' \; c) l* M9 U

  O9 _# A  D) v: b准备写数据到Output Register中。随后通过60h写入到Input Register的字节会被放入到Output Register中,此功能被用来模拟来自于Keyboard发送的数据。如果中断被允许,则会触发一个中断。! c. F6 s& k, @% Q9 N
void put_data_to_output_register(unsigned char __data)& M; o, F- v$ J* i
{
* Z+ u, r1 v% \( ]; n2 f9 Y! {9 S   wait_input_empty();
2 d8 v) c, p/ j, q2 Z9 |- R4 ^   outb(0x64,0xD2);. G- s" [4 B0 L: u. F

( C. V" h3 {0 i+ T   wait_input_empty();
0 f! |. S4 C+ P' b0 J4 j# p   outb(0x60,__c);
/ A; Q7 L0 ~. ]3 N}
6 q8 v6 r- Q# Z1 C/ i( N( z' g' D4 D  g) n* L2 e2 J
4.2.7.2 发给8048的命令" }) b$ U7 N" m* t' Y

; b# o8 P7 I! T) ~, r( h0 D1 }+ N& q2 U/ k) R) e; q
    * EDh
& D0 ]. j0 s4 |3 J
5 ~; E# ~# `  }/ q! O8 g, g$ w设置LED。Keyboard收到此命令后,一个LED设置会话开始。Keyboard首先回复一个ACK(FAh),然后等待从60h端口写入的LED设置字节,如果等到一个,则再次回复一个ACK,然后根据此字节设置LED。然后接着等待。。。直到等到一个非LED设置字节(高位被设置),此时LED设置会话结束。3 v$ a/ L$ f( a, M3 J# I2 F

1 ]: i, ?: R4 G1 @    * EEh
0 b* X+ X% X& L  w) ^2 Q& F0 ]/ p/ J- J" s9 i9 H0 y7 I
诊断Echo。此命令纯粹为了检测Keyboard是否正常,如果正常,当Keyboard收到此命令后,将会回复一个EEh字节。
* c, k* n4 j3 q% r9 R
5 t1 c% B) h6 G! v( N    * F0h
( F8 s8 n! Z- k* A) e* v6 A- a( k9 k, l) J. M" T
选择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代码所要求的。
; q4 ~* a8 p% q
7 d' G  G% \" q; @+ ]    * F2
1 O+ @1 @% ^+ g, X5 H  Z, Y& H
: X2 e$ y) w& \# D7 Q读取Keyboard ID。由于8042芯片后不仅仅能够接Keyboard。此命令是为了读取8042后所接的设备ID。设备ID为2个字节,Keyboard ID为83ABh。当键盘收到此命令后,会首先回复一个ACK,然后,将2字节的Keyboard ID一个一个回复回去。; _/ o  ^3 L) P8 T3 d' J  N0 f
  S4 G! `9 W+ K# P9 a7 ^
    * F3h* ]' Y  a! G! j0 o
- U- D+ ^& K4 s
设置Typematic Rate/Delay。当Keyboard收到此命令后,将回复一个ACK。然后等待来自于60h的设置字节。一旦收到,将回复一个ACK,然后将Keyboard Rate/Delay设置为相应的值。; j" d1 ]3 \, h2 @+ x6 a, ~  ~
) K: f8 n( H) _( z
    * F4h
" r: M! ?4 K# R4 p( R: x8 \# n% x0 ]- y: y, K* `
清理键盘的Output Buffer。一旦Keyboard收到此命令,将会将Output buffer清空,然后回复一个ACK。然后继续接受Keyboard的击键。
4 Y+ m/ e( i: t) J2 s- b" `% l! ?/ y( l7 d9 M) V3 T
    * F5h
$ m( [$ ^8 F6 V6 a$ \0 t4 X* G: `2 j5 H% f
设置默认状态(w/Disable)。一旦Keyboard收到此命令,将会将Keyboard完全初始化成默认状态。之前所有对它的设置都将失效——Output buffer被清空,Typematic Rate/Delay被设置成默认值。然后回复一个ACK,接着等待下一个命令。需要注意的是,这个命令被执行后,键盘的击键接受是禁止的。如果想让键盘接受击键输入,必须Enable Keyboard。
  r7 J; G- T: M3 a+ V6 P. `
( _2 p6 A) H- j  I. J2 M    * F6h
! A2 a+ w/ e) T& _! b# ^1 u1 g1 ]
设置默认状态。和F5命令唯一不同的是,当此命令被执行之后,键盘的击键接收是允许的。
* P$ U: ~5 ?, M# ?- t" u, Y& t* e- U1 Z6 e. l: {; k, r- l
    * FEh: C/ `+ h1 `3 z6 G5 ?

8 Y1 s; @7 G9 g) h: q4 pResend。如果Keyboard收到此命令,则必须将刚才发送到8042 Output Register中的数据重新发送一遍。当系统检测到一个来自于Keyboard的错误之后,可以使用自命令让Keyboard重新发送刚才发送的字节。% _! p& u2 g) a  U  |

$ m7 ?" Q4 U- H. c& d: E2 Z    * FFh
; Q+ |3 L. g8 o! x( x) b+ N
$ C0 H3 c. a3 t# m& |! D0 pReset Keyboard。如果Keyboard收到此命令,则首先回复一个ACK,然后启动自身的Reset程序,并进行自身基本正确性检测(BAT-Basic Assurance Test)。等这一切结束之后,将返回给系统一个单字节的结束码(AAh=Success, FCh=Failed),并将键盘的Scan code set设置为2。
回复

使用道具 举报

发表于 2009-1-14 13:49:16 | 显示全部楼层
好贴!
5 B) p4 E" w& I' q非常详细!6 b7 _3 O9 \+ u
谢谢!
回复

使用道具 举报

发表于 2009-2-25 17:37:28 | 显示全部楼层
2楼好帖!在helppc的Hardware Data and Specifications栏里有相应的寄存器和命令详细描述。1 A/ M6 x+ A4 G& [9 s1 X
+ {, D/ _8 n9 p/ _  d; V# Q0 e
我的问题是,上述描述应该是针对老的8042的,在目前的使用EC的系统中,这些status register和command描述在哪个文档中可以找到?比如intel的santarosa,使用renessas的H8s 2104 EC,按道理上述状态寄存器,命令等的描述应该在2104 datasheet里,但是我怎么找都没有。还是有某个spec定义了这些命令格式?新手问题,高手莫笑
回复

使用道具 举报

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

本版积分规则

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

GMT+8, 2026-3-15 06:51 , Processed in 1.535935 second(s), 17 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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