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

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

[复制链接]
发表于 2008-7-14 00:04:00 | 显示全部楼层 |阅读模式
bini殇,能帮详细解释一下bios post过程中的所有发给ec的60/64命令号码和意义吗?数据量比较大,截不住。
发表于 2008-7-14 12:09:38 | 显示全部楼层
转个别人发的,不知道LZ能不能用上  
* J& C0 Z) O- E! b$ o7 S7 K
0 p" n, H& d( W) P: z' }8 a5 A4.2.7 Command3 m! V* t0 w6 I" J
6 ?1 i) ]9 H, ~- p# u- B
通过8042芯片,可以:
6 {9 i3 L$ h; `  q/ u向8042芯片发布命令(通过64h),并通过60h读取命令的返回结果(如果有的话),或通过60h端口写入命令所需的数据(如果需要的话)。& q  [1 @7 p, D9 q/ F. e0 \+ {
读取Status Register的内容(通过64h);. y& U3 {1 |+ a: p+ q- U
向8048发布命令(通过60h);7 t4 v; D! n4 B: M7 X
读取来自于Keyboard的数据(通过60h)。这些数据包括Scan Code(由按键和释放键引起的),对8048发送的命令的确认字节(ACK)及回复数据。/ ^% t* l0 b& _) F- k

, @6 P  V$ F: g& p6 I/ t# |$ b* a' t0 N再次强调一遍,Command(命令)分为发送给8042芯片的命令和发送给8048的命令。它们是不相同的,并且使用的端口也是不相同的(分别为64h和60h)。  z3 @- c1 c& A) m( L* J: d" N
  U; [; t, M* Y

3 q/ [+ D3 g  e! W1 `' i$ @* n; k) c$ P: ^% {! E* P8 O
    * 64h端口(读操作)$ \" W( j/ ~( M  y  [3 |; M! a
( B# ]8 H2 O8 Z. ~5 {! ^: T

" A! f3 f, F+ D对64h端口进行读操作,会读取Status Register的内容。: G' L, i) f' x; O" @  p! z: v

3 P  n! p5 ~) Ainb %0x64' I- l. }2 }2 l, v+ h
执行这个指令之后,AL寄存器中存放的就是Status Register的内容。. W5 D& X1 p* \9 D# ~* i
$ K- c$ c0 M5 s( [4 {, b/ g; E; \) B
    * 64h端口(写操作), R, }5 e" w( k. M- @

" m- h+ S' p8 X6 B) Q5 F' T向64h端口写入的字节,被认为是对8042芯片发布的命令(Command):1 ]7 D2 q$ }1 h! w5 r# n
Ÿ, q/ y9 d/ q; r6 ~. h1 e
写入的字节将会被存放在Input Register中;  z% x. d5 s4 B2 W0 }
Ÿ' ~! Z+ H4 n) d" e* a; U. b
同时会引起Status Register的Bit-3自动被设置为1,表示现在放在Input Register中的数据是一个Command,而不是一个Data;
8 D1 o3 G# H; @$ Q+ @Ÿ) W3 p" L  F+ a/ u& ~8 Y) _
在向64h端口写某些命令之前必须确保键盘是被禁止的,因为这些被写入的命令的返回结果将会放到Output Register中,而键盘如果不被禁止,则也会将数据放入到Output Register中,会引起相互之间的数据覆盖;# q$ _3 ^1 w0 A2 C
Ÿ
3 D# M4 ]0 {" R$ M+ |在向64h端口写数据之前必须确保Input Register是空的(通过判断Status Register的Bit-1是否为0)。. |$ Z; _) m* O0 w3 W

- q& Q# @/ `" R/ i5 rvoid wait_input_empty(void)+ R& K# h- ?' E. W
{
: v  r+ ~, t) q! @; V   char __b;
4 [, t# e! R9 J6 D, H" d0 @8 z& k4 K% M1 N# I& ?
   do{
& C* V( x2 b: a     __b = inb(0x64);
9 l( ]7 e. Y- V* y. \   }while(!(__b&0x02));, Y: k+ {1 j( W1 }5 e9 c# Z
}
5 `2 {$ A9 {) l$ k  I; f9 E' C
& i5 d; d7 f1 P8 G2 j5 B! Qvoid disable_keyboard(void)7 h' p, q5 u- g6 e0 n4 h, U
{
0 R& L9 u: q6 Z7 w2 l   wait_input_empty();  l/ q! u1 J- [! Z+ m
   outb(0x64, 0xAD);
! X% n- M; l8 o, z5 [  W  A}[size=+0]
6 B: R3 J! }- W8 d; C& N
. x' T4 u0 D( S  e( G    * 60h端口(读操作). o# E9 q% V) v
+ ~4 V- \8 P( ]8 P* [" d
对60h端口进行读操作,将会读取Output Register的内容。Output Register的内容可能是:
2 A6 O5 c6 d, A# XŸ           来自于8048的数据。这些数据包括Scan Code,对8048发送的命令的确认字节(ACK)及回复数据。
$ X, M! f, [; [4 AŸ           通过64h端口对8042发布的命令的返回结果。
+ z9 @+ j* }% D  C) \- c3 S7 @0 d8 d; d! B" q9 [& w
在向60h端口读取数据之前必须确保Output Register中有数据(通过判断Status Register的Bit-0是否为1)。) _- V8 X! P' `. \# k  c5 r( v0 _
void wait_output_full(void)1 |  W4 c* T! q
{& {1 C7 s5 z# l0 T; J  N
   char __b;7 ?0 j# W/ k- b: N4 t, r' `

" a1 Z$ n. S/ {7 D% v- e   do{
% R" _- W" \3 j& N% G7 N4 l     __b = inb(0x64);; w: w* o; g. D) B
   }while(__b&0x01);
+ H+ r1 b" E3 b( f3 D: }}( [4 b, h  E2 Q8 @

5 F5 t' t# d) kunsigned char read_output(void)) e. M- h9 i& C( N9 {+ J) J! X* I
{2 `# v% f$ |+ k3 R2 ]5 C, A+ c
   wait_output_full();
$ Q5 F7 H* w1 B" l! g   return inb(0x60);
, J+ Q6 m+ u6 N  z" C}
1 W. b- R* G* [* i2 u9 h4 _, H
( n  M5 d' T* D6 _; s) c. J5 T    * 60h端口(写操作)
1 Y" _- G! i; F8 y
) L) g+ m4 p+ F. I向60h端口写入的字节,有两种可能:3 u  @. I: R! p, h% B6 a9 z
1.如果之前通过64h端口向8042芯片发布的命令需要进一步的数据,则此时写入的字节就被认为是数据;
. u2 i- O3 {7 h/ M+ A* U2 K2.否则,此字节被认为是发送给8048的命令。
2 k' x' o  G" \7 y
# n9 E6 ]7 {. C5 d% m在向60h端口写数据之前,必须确保Input Register是空的(通过判断Status Register的Bit-1是否为0)。( M% G' p( D! u9 U& l6 M$ J

& u3 {. ^3 T% a
$ f* G  y8 I  n, o0 u[size=+0]4.2.7.1 发给8042的命令
  X4 O) U$ L7 c& o5 k4 {& K! R" {( x1 L0 m
    * 20h
* a8 ~4 Q) J( L+ Y% Z4 C% l3 h; }. e) x% [
准备读取8042芯片的Command Byte;其行为是将当前8042 Command Byte的内容放置于Output Register中,下一个从60H端口的读操作将会将其读取出来。6 `7 n" Z! ^& }3 y; Y% B

7 D8 o8 t3 `3 j( D! P0 b; V$ g. K8 B
unsigned char read_command_byte(void)
$ P3 ^8 n7 f- i: W( l- _: v{' V1 s2 W! c( V
   wait_input_empty();
" `8 Q: b4 r/ @- D$ I4 o7 a   outb(0x64,0x20);! F; t+ h% V9 d
   wait_output_full();
# t9 V" Y2 j# }! ~5 q% f. E3 \   return inb(0x60);   
& b1 L: m9 }7 U# |# I7 o" |}
- }$ I- x8 [. W+ g0 W
+ l" Q" h+ f# `: t" V    * 60h9 \! f% \7 l, m5 M& S; G& p

" ]" K0 a% }9 _8 l" N* v. [4 |, f4 h准备写入8042芯片的Command Byte;下一个通过60h写入的字节将会被放入Command Byte。
" e6 j+ u; S. j( v3 ~7 a
2 f# k4 e$ f! m6 _: @
2 v4 _: h3 h$ Z' X4 e( Svoid write_command_byte(unsigned char command_byte)$ j# \: h9 Y8 Y6 }5 e
{
; R  l" j' n! ?+ s6 \$ z   wait_input_empty();
: Z: e7 y# |6 ^- t3 N8 q4 f/ v   outb(0x64,0x60);' S9 x: s* A( i) k0 R4 {
   wait_input_empty();
% a0 C4 Q* N1 Z+ x4 ~/ d! o   outb(0x60,command_byte);! D. O. |7 l8 Z
}
& [$ w* r( V* ]- q! |3 L
9 M. D2 G+ r: e, q
+ A1 @. w, ]: o* i0 S) Z% Q$ e* F) @    * A4h* H' l& `3 w, P. i* r: O
' N+ j* D7 T7 S3 k
测试一下键盘密码是否被设置;测试结果放置在Output Register,然后可以通过60h读取出来。测试结果可以有两种值:FAh=密码被设置;F1h=没有密码。
8 n' v5 J' e! c& i% V/ l  }bool is_set_password(void)" a. o) `+ D5 ?
{
' `% m# j/ O8 q& F, R7 s   wait_input_empty();7 D# q- ?- `# y  X- L: s0 c
   outb(0x64,0xA4);
, U# b1 ^& _' `  o   wait_output_full();. [! ]7 B8 Y2 m. b
   return inb(0x60)==0xFA?true:false;   9 z' h: P( w, V3 L% t# X
}# l- a1 V# G9 W: m" `' v7 J9 H
/ Y4 V* v; h1 h- B+ K
    * A5h
& a; U. z4 U5 G
2 Y" e3 S$ u; U( e6 Q5 a设置键盘密码。其结果被按照顺序通过60h端口一个一个被放置在Input Register中。密码的最后是一个空字节(内容为0)。
9 [2 V- S) F, m' R& R; R9 X0 S1 k7 cvoid set_password(unsigned char* password)% @7 [! q: F$ q. a
{
) P( D1 \3 [1 S, P4 ]   char* p = password;0 z( X7 p. p) P- k- Y3 O* k2 z

: t3 R  ?9 B: u   if(p == NULL)- v, s0 X; l* O
      return;. M: Q' ^; u8 f! R. z  {

& _! }: j9 Z9 f   wait_input_empty();
1 L7 Z& V6 @4 ]- ?  h& R   outb(0x64,0xA5);
9 _, [% H$ O! G9 c* G) `& ]
9 M1 u. ^* a6 `# w( i0 K$ h   do{9 k: I' n' Q% @0 k: W5 k- V$ ^
      wait_input_empty();
$ a8 K+ ^, q* {& W: @7 Z      outb(0x60, *p);
/ H$ {" A) U+ O   }while(*p++ != 0);  B$ J; b* ?8 I' k
}6 n" K4 c" I+ U9 Y
6 ?# {& n) i3 ^# |# D5 N
    * A6h; K  E5 s0 h/ h8 ~  f1 X# c  o& F

" u6 `; Y" _3 \- X让密码生效。在发布这个命令之前,必须首先使用A5h命令设置密码。) m& V9 R: `8 _
void enable_password(void)) I6 u, z# z7 R& U  }
{
2 ^" h- r" U8 D0 h* {9 @2 N   if(!is_set_password())
& G% s7 {$ ]! g  X" m! O" t      return;8 ], P' w! N4 g' C, z' w9 c9 K& j. Q2 {6 B

- M  E6 }4 @; I8 @' o0 o( p   wait_input_empty();5 K. B# R) O- [( l
   outb(0x64,0xA6);   
9 t7 G( V! ~$ N}; x# Q0 R7 O5 S

5 x2 P( _  o* o3 E7 S% f/ {    * AAh
0 m4 m* @6 i  F; ~& k. w5 _, n
- @+ D, Z+ Q: l2 Q$ b* \自检。诊断结果放置在Output Register中,可以通过60h读取。55h=OK。, ?5 B9 g3 v6 w$ m9 l# e. Z

# x8 W+ v- K1 v- F) w/ h
( B. j) i2 J1 tbool is_test_ok(void)
1 w  ~7 t2 K& v. L{; O' @: W( ?, H( N
   wait_input_empty();
" ?8 c& K1 p/ E4 h   outb(0x64,0xAA);) d0 X6 j) r! }9 d( b
: e! {5 i/ I: A7 L$ [0 C

8 w  s( R8 m9 g/ o) Y; H   wait_output_full();: P4 s* v# g( }1 U; N
   return inb(0x60)==0x55?true:false;   , ?! M) J* C8 N5 s3 B7 A4 g; \
}
5 @4 i" E1 _/ z& \
  _/ c/ i0 A3 N" g$ E& y& g5 c* G5 A- W# q- m1 X! k
    * ADh% a+ T7 A2 V' V4 L" o& B7 k9 A
2 Y8 `+ z/ X8 ^
禁止键盘接口。Command Byte的bit-4被设置。当此命令被发布后,Keyboard将被禁止发送数据到Output Register。/ O6 c% G5 z/ v5 S- A
void disable_keyboard(void)
* g$ e- J; W% A6 W4 i0 E( n{
' K+ P- W3 }6 u& v% B) l   wait_input_empty();
, L) }. J1 n% f0 Q5 y3 k   outb(0x64,0xAD);" G* S( T; T- v* h2 r* m" T0 s
5 M* X9 }+ M- |8 X
}7 {( H9 L  M% `! P- Q

) X  `: r% o3 X& H+ }    * AEh; [) d, @* \+ l. ~* E# P

9 z6 p$ r* V' S( y打开键盘接口。Command Byte的bit-4被清除。当此命令被发布后,Keyboard将被允许发送数据到Output Register。, X) q9 k1 F( _% w
void enable_keyboard(void)
  n! X: d1 ?, C: h9 Y- Z{
0 [* y8 B% L8 y* x1 ~   wait_input_empty();
* x' N, Y7 W2 [6 G   outb(0x64,0xAE);
7 ^% F; g% x- x# ]. x* H1 [9 g% w7 ~& R- c  e2 K  |
}9 R  O  t2 p- }9 y6 C3 K# f1 V
/ u, h. ~* P. p& B9 p
    * C0h2 s  |0 M1 o& `
% M( v; h8 r+ ^$ ~& u
准备读取Input Port。Input Port的内容被放置于Output Register中,随后可以通过60h端口读取。
. q* H+ H; |4 X! [3 z( R7 j- r3 Munsigned char read_input_port(void)
0 \. d6 y2 C) d( \+ z{
- Q* H0 w3 ^$ O6 _   wait_input_empty();/ o0 n* ?7 l5 E5 H$ J# _2 t& k
   outb(0x64,0xC0);" D( F2 k$ H. E4 c5 ?; T7 Q% T
) e0 H+ L& m" _
   wait_output_full();
) R  Z/ ~$ \4 s# `* \6 f: m" T4 C$ N( x2 D2 M  n7 h$ ~' M( k
   return inb(0x60);4 U5 }# s  s  n! f. Z  Y
}
+ ^& g: l9 y' U" W5 w; E2 I% W- `7 ?8 k, \! l( o2 V3 v* i
    * D0h
3 P. t/ M) o8 d' B0 }% T- c+ y3 @# X# o6 N" z. O
准备读取Outport端口。结果被放在Output Register中,随后通过60h端口读取出来。3 L" u; x. W! x& c/ \  H
unsigned char read_output_port(void)* I% R' ], U' h9 l2 C
{
! c3 [) N. v; ]' B- N   wait_input_empty();
. ?; C9 a, Z, m  }   outb(0x64,0xD0);$ D/ A& b) B* H* x( r

& Z1 y7 z$ e3 F4 W* S   wait_output_full();
; y$ E) D% g' G3 {
; h8 C9 i/ r$ v9 N- ~7 J   return inb(0x60);/ c* X, T' Z& W$ @  x. ^8 z. N4 l
}
/ g# V4 ^7 r( y, a* i7 d
: M3 V  y5 b  ]( H9 P+ y    * D1h
0 [% \) _* o1 E( C$ ^: d" A, `1 M* c. C, f
准备写Output端口。随后通过60h端口写入的字节,会被放置在Output Port中。: ]* q% H3 H( Y# d
void write_output_port(unsigned char __c)( S, J0 M# D, s& b- B
{
" H+ ~3 A5 b; h# X1 x   wait_input_empty();
# ]: v! _" u5 R7 [  [   outb(0x64,0xD1);8 ?# D( H1 G! R

3 [4 \) e& Z) b' H& g7 Z   wait_input_empty();( z0 m$ f- D7 i+ o
   outb(0x60,__c);
' G0 l! o5 C3 d& @- \1 `  H2 A* j
, [6 h" m$ f( _* u9 g}
: ^) r6 I. U( S% {3 ~' x" A+ n! [
- A. ^5 z; V6 g9 t9 d0 F- F0 q% l* [0 |6 g. x
    * D2h
' G: A  z0 P: Q: n9 e7 c: p+ w9 t* e, |0 O% D
准备写数据到Output Register中。随后通过60h写入到Input Register的字节会被放入到Output Register中,此功能被用来模拟来自于Keyboard发送的数据。如果中断被允许,则会触发一个中断。' Q8 P) @. y; I
void put_data_to_output_register(unsigned char __data)) k' y0 O7 f8 S4 T
{0 O6 V$ ]" B  q4 ?; N; ^, ^* K
   wait_input_empty();; k+ H5 P( s6 U: e4 O
   outb(0x64,0xD2);
' ~  t& l1 M) u8 j0 @1 K" _, g3 x! I% L1 g% ~# F' O0 r
   wait_input_empty();5 L. C% r6 x: X; g, H' B8 F+ L  ?. N
   outb(0x60,__c);
8 ~6 N5 u4 m* N  w  o* D9 v2 J}0 h9 M) J  O- c0 ^4 [

0 I0 Q. a) B' i7 Q4.2.7.2 发给8048的命令6 S1 _, q' d8 ^  W* M7 T" z
- ?& Y; h2 [: P
9 F* h" m* ~+ ^, x" T: }
    * EDh
& A2 X+ C( s6 G, X
* r+ s- |5 e) y$ [8 x+ x设置LED。Keyboard收到此命令后,一个LED设置会话开始。Keyboard首先回复一个ACK(FAh),然后等待从60h端口写入的LED设置字节,如果等到一个,则再次回复一个ACK,然后根据此字节设置LED。然后接着等待。。。直到等到一个非LED设置字节(高位被设置),此时LED设置会话结束。8 l6 ]* @& r7 |8 v7 k

% Z3 G8 l+ U; H0 X    * EEh
( e8 `; [3 Z% v1 K: e
" c" r; a) w3 I- }4 ]诊断Echo。此命令纯粹为了检测Keyboard是否正常,如果正常,当Keyboard收到此命令后,将会回复一个EEh字节。: k0 I6 b( |" U2 V7 V- O7 k+ W
# ?* k& z, y5 k/ Z! c& Z
    * F0h0 D$ f8 q; J1 n7 W6 ~) ^

" E' k( a  n1 u$ h选择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代码所要求的。' R, Y" `5 K4 x3 ~
# K# Y: k, f7 ^& S
    * F2" T0 S2 u0 g/ Y# H

1 n: s- d' G8 E8 P- \$ B读取Keyboard ID。由于8042芯片后不仅仅能够接Keyboard。此命令是为了读取8042后所接的设备ID。设备ID为2个字节,Keyboard ID为83ABh。当键盘收到此命令后,会首先回复一个ACK,然后,将2字节的Keyboard ID一个一个回复回去。$ H' v: j3 B/ W5 m: {

; u, c; Y, u* \/ l    * F3h& B2 Z! ]8 n: U7 J4 Z6 b* I9 v" l

, ~: b8 t8 S$ ]( V设置Typematic Rate/Delay。当Keyboard收到此命令后,将回复一个ACK。然后等待来自于60h的设置字节。一旦收到,将回复一个ACK,然后将Keyboard Rate/Delay设置为相应的值。
" z# x/ P$ X( r( t& _$ u% Y1 [8 l! E  n6 Z' Y, S
    * F4h: P7 z5 d$ M! y8 ]
0 s3 h* w% c9 ]! }/ d+ @- Q
清理键盘的Output Buffer。一旦Keyboard收到此命令,将会将Output buffer清空,然后回复一个ACK。然后继续接受Keyboard的击键。
9 _9 H' S4 j3 B- R) M+ R  n$ H# u  b& B" T4 T5 Z, f5 }- b1 o
    * F5h
# S% ~2 D2 R1 ~! o3 r" w5 h- }0 h: C- I6 \1 F2 o' p6 q
设置默认状态(w/Disable)。一旦Keyboard收到此命令,将会将Keyboard完全初始化成默认状态。之前所有对它的设置都将失效——Output buffer被清空,Typematic Rate/Delay被设置成默认值。然后回复一个ACK,接着等待下一个命令。需要注意的是,这个命令被执行后,键盘的击键接受是禁止的。如果想让键盘接受击键输入,必须Enable Keyboard。
- G+ v& s- x2 q, r9 B+ A0 J
: r5 I9 [1 |$ {, A! X4 o    * F6h
" K& S! H0 y6 i1 \& ]8 B
* ^1 d/ x1 y- ]* Q) q5 x设置默认状态。和F5命令唯一不同的是,当此命令被执行之后,键盘的击键接收是允许的。7 N, k$ j/ ?7 c$ s7 B7 s: c
2 r0 `( ]5 \" X
    * FEh2 m! K; n, L, {4 }. O2 \
6 J% y3 i. l# I7 A' d
Resend。如果Keyboard收到此命令,则必须将刚才发送到8042 Output Register中的数据重新发送一遍。当系统检测到一个来自于Keyboard的错误之后,可以使用自命令让Keyboard重新发送刚才发送的字节。) {  J: @( v% u+ }

0 c! D9 x& d7 ~    * FFh, T7 {& E4 |- T2 w( {0 ]
, k# K+ b1 [% j; I6 y
Reset Keyboard。如果Keyboard收到此命令,则首先回复一个ACK,然后启动自身的Reset程序,并进行自身基本正确性检测(BAT-Basic Assurance Test)。等这一切结束之后,将返回给系统一个单字节的结束码(AAh=Success, FCh=Failed),并将键盘的Scan code set设置为2。
回复

使用道具 举报

发表于 2009-1-14 13:49:16 | 显示全部楼层
好贴!4 ]% f+ {- n- l' ^& `  H
非常详细!
8 H9 w# ^# y) T3 B4 ]: J谢谢!
回复

使用道具 举报

发表于 2009-2-25 17:37:28 | 显示全部楼层
2楼好帖!在helppc的Hardware Data and Specifications栏里有相应的寄存器和命令详细描述。$ g  F% p1 ~5 \8 ]

  @. @! v' M8 C+ N9 F' r我的问题是,上述描述应该是针对老的8042的,在目前的使用EC的系统中,这些status register和command描述在哪个文档中可以找到?比如intel的santarosa,使用renessas的H8s 2104 EC,按道理上述状态寄存器,命令等的描述应该在2104 datasheet里,但是我怎么找都没有。还是有某个spec定义了这些命令格式?新手问题,高手莫笑
回复

使用道具 举报

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

本版积分规则

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

GMT+8, 2025-4-16 14:40 , Processed in 0.050198 second(s), 16 queries .

Powered by Discuz! X3.5

© 2001-2023 Discuz! Team.

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