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

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

[复制链接]
发表于 2008-7-14 00:04:00 | 显示全部楼层 |阅读模式
bini殇,能帮详细解释一下bios post过程中的所有发给ec的60/64命令号码和意义吗?数据量比较大,截不住。
发表于 2008-7-14 12:09:38 | 显示全部楼层
转个别人发的,不知道LZ能不能用上   7 W# _! Y; M! I: T

1 t$ T3 o* y, b) {( ]9 E6 E# Q4.2.7 Command
. k! @. \; `. u
$ f4 j- H! E  I  O3 V; l通过8042芯片,可以:" y/ s  E& H7 |7 T
向8042芯片发布命令(通过64h),并通过60h读取命令的返回结果(如果有的话),或通过60h端口写入命令所需的数据(如果需要的话)。
1 h& W7 K. C# e读取Status Register的内容(通过64h);2 O$ z5 x# I) F
向8048发布命令(通过60h);
! m; T: A* i5 I3 a8 X# W读取来自于Keyboard的数据(通过60h)。这些数据包括Scan Code(由按键和释放键引起的),对8048发送的命令的确认字节(ACK)及回复数据。6 l7 t, C) L. k' B  R6 b. t  {) I
& R* T1 g- ^6 J( _5 K% i
再次强调一遍,Command(命令)分为发送给8042芯片的命令和发送给8048的命令。它们是不相同的,并且使用的端口也是不相同的(分别为64h和60h)。2 s- j6 U; l1 C" z- @
9 h+ G5 v# J$ s- v$ Q2 }1 n
# U  T4 [1 W  ~* X: x0 O

% J7 L$ m6 p2 {# m4 O  k    * 64h端口(读操作)/ {+ Q6 D% }) H- _9 Y
/ ^3 G4 H( c$ @: v( R
- r6 h; R1 o  {0 m3 ?4 O
对64h端口进行读操作,会读取Status Register的内容。# u) Q$ I' p$ G8 b& G
* M5 N& }* Z/ E2 K$ o# b
inb %0x64
* _$ c$ |5 Y' q: w执行这个指令之后,AL寄存器中存放的就是Status Register的内容。
, M* m7 l6 t6 R( b; `. X  e; v; E* B) f% ?# a7 C
    * 64h端口(写操作)
9 E6 `7 q: _6 M, U- B
9 P9 N# s% C9 L, D向64h端口写入的字节,被认为是对8042芯片发布的命令(Command):
8 x6 k9 f, w2 I" I/ R' F0 yŸ
0 Y, b9 t/ A" V写入的字节将会被存放在Input Register中;+ T3 v0 e& K4 D( R, h& Q
Ÿ
; l5 r: v  d' n, l4 ]同时会引起Status Register的Bit-3自动被设置为1,表示现在放在Input Register中的数据是一个Command,而不是一个Data;* w6 Z# D9 O: T4 ?( H
Ÿ% h: E" A, Q. q' I" |$ S
在向64h端口写某些命令之前必须确保键盘是被禁止的,因为这些被写入的命令的返回结果将会放到Output Register中,而键盘如果不被禁止,则也会将数据放入到Output Register中,会引起相互之间的数据覆盖;) e3 h' c# w9 }) W, Q- K* m) w
Ÿ5 s0 {1 V& Y7 o% n: l% ?
在向64h端口写数据之前必须确保Input Register是空的(通过判断Status Register的Bit-1是否为0)。
4 Y: o# M6 U( O7 I1 f; j) j
4 `' X5 f' D9 K# k$ G- I0 \( hvoid wait_input_empty(void)8 O0 \. |& J7 q; W
{* X* e, G8 A8 a2 G
   char __b;
& F! H% @2 y& f0 G5 E, e6 {2 {  y, ?1 h& F- v( d' |
   do{2 M% H, y9 m7 ?
     __b = inb(0x64);' E7 t- ^" e/ T& m1 b
   }while(!(__b&0x02));' L5 d& ^5 B7 I4 r
}  }/ z; S6 {" P& C9 V8 Z

; g; S$ v3 X+ pvoid disable_keyboard(void)3 O0 W4 W$ S6 v8 y
{
1 c4 M1 m1 h% a% N) w( `   wait_input_empty();
1 X# p  g3 w3 G$ K   outb(0x64, 0xAD);
8 V' z# |! j9 n( @9 G- m; q}[size=+0]$ Q* X) J6 i1 a1 B3 n

' T3 w1 H% m1 g- [, m4 _, e8 j0 n; K    * 60h端口(读操作)8 o" D, J) O# g( t: h8 i9 ?8 s
8 z* q* m/ B% X
对60h端口进行读操作,将会读取Output Register的内容。Output Register的内容可能是:
- _5 J& |$ {8 O7 JŸ           来自于8048的数据。这些数据包括Scan Code,对8048发送的命令的确认字节(ACK)及回复数据。" C2 {  O0 D: `0 v1 o6 E% L6 J
Ÿ           通过64h端口对8042发布的命令的返回结果。
! \& z( n9 p* a) T1 Y: a
- j# n! m9 e) M% v, {1 ?在向60h端口读取数据之前必须确保Output Register中有数据(通过判断Status Register的Bit-0是否为1)。
8 l) p2 s! l8 X7 Vvoid wait_output_full(void)- t- X, }- c3 j! \# N7 j2 s# A  A
{
# z' Y8 k9 f& H   char __b;
/ ^7 {% C/ `" E& |7 C& x5 g
' Y9 ?# f/ M& ^( H2 M2 q7 i6 V   do{% R' u$ E- V* T+ K
     __b = inb(0x64);% l( y2 R7 J1 R9 _7 X' s+ c
   }while(__b&0x01);, S, G. @7 s, y6 r
}9 g. h/ h7 ^" H7 j. T! F

( R5 j; I) V* gunsigned char read_output(void)
6 n# s0 E' Y7 C7 F5 x1 D2 ~{
$ u, H# Y" ]# ~   wait_output_full();
! g; G2 W- z$ H/ c4 G, g   return inb(0x60);
( m4 _; `! A% {  W! A  T}8 {$ s, O% o5 Y7 ~' G
0 q, d9 |# Z' A6 K0 u
    * 60h端口(写操作)
  v! @: e4 g* E  `( y& m$ N( S1 u" C0 g  c! V) F, N. c9 a. u7 \6 T
向60h端口写入的字节,有两种可能:$ T0 Z! C: F6 |0 U0 n# O
1.如果之前通过64h端口向8042芯片发布的命令需要进一步的数据,则此时写入的字节就被认为是数据;1 C* V3 ]3 w  r! w7 r/ x
2.否则,此字节被认为是发送给8048的命令。6 F. U$ u) [1 T8 e% n
' I7 i+ ?7 z; d$ @
在向60h端口写数据之前,必须确保Input Register是空的(通过判断Status Register的Bit-1是否为0)。
8 g7 e* @3 z/ |( B
$ N7 S, f; s" q
! ^! i" }6 Q" Q$ j8 G: E[size=+0]4.2.7.1 发给8042的命令
  d( }, J% i( T
# S" B: G9 I- Y. H. r$ k    * 20h
. n3 \  X- W& N
# }$ Z9 t% g! E% T. C准备读取8042芯片的Command Byte;其行为是将当前8042 Command Byte的内容放置于Output Register中,下一个从60H端口的读操作将会将其读取出来。/ z, P5 P/ L* M/ D0 X2 R+ ^
) M# x( e: \1 J5 n+ W. A
' p  J; B: h& c* S  A* y
unsigned char read_command_byte(void)
# W  M; R- G8 ?& N9 c3 h{, e; ~/ R1 z% O/ O2 X* E5 E% \) Z- b" L% d
   wait_input_empty();
; S  q  [8 M% r2 c   outb(0x64,0x20);+ Q" l& F9 b3 [$ R4 F
   wait_output_full();
' {" J6 h! h2 j, c   return inb(0x60);   
/ T  j6 X- n! N( }( f2 n" h}1 }4 v0 q; b) q. b1 p
7 e# q  @6 v6 b" B
    * 60h, P2 c( y; P* t% c2 G+ _
9 L" l! M6 F2 E! y% R5 H- h
准备写入8042芯片的Command Byte;下一个通过60h写入的字节将会被放入Command Byte。( ~2 n; o' c3 G* l8 q' h

% {, ~) X; N3 i3 B
. F8 }4 _! c5 x/ Q- x; s6 avoid write_command_byte(unsigned char command_byte)
+ q/ O; k2 ^1 f" u; u! l{& |& [2 X  `7 X! c( z. F
   wait_input_empty();
6 }! F* |4 ]1 T* [5 w* S! U   outb(0x64,0x60);6 |7 ~0 D0 ~. h  r2 m9 |' y
   wait_input_empty();/ O! h( z9 U" T% J; `1 i# l
   outb(0x60,command_byte);
& v: E; A" j# {9 P}
/ F! T# y, b8 Q
- V$ B( N. \2 k0 I8 M. z
3 Z6 J# m/ r/ F( O! J& y. i    * A4h
+ `6 b5 c  E/ F9 Q: ]% H1 P! ^4 H) f2 {0 Z. p* W
测试一下键盘密码是否被设置;测试结果放置在Output Register,然后可以通过60h读取出来。测试结果可以有两种值:FAh=密码被设置;F1h=没有密码。2 e1 u# A# b, F- U6 f
bool is_set_password(void)
. ]- Y& \2 y1 j{
" Q6 l! t; p* T  \   wait_input_empty();
  _  C8 v2 `: S' k   outb(0x64,0xA4);
9 g1 v/ {4 S: k3 M' Y. s7 `   wait_output_full();1 A3 i: W. x1 a. S0 U  e6 w
   return inb(0x60)==0xFA?true:false;   ( M( G' o% h/ c: d( ~3 c! b
}% U2 ~- ^+ ~$ K$ l  }

/ c$ u2 Z) A; H    * A5h
. u3 ]4 k! O) n0 O. f' _6 `3 y- q7 H: r
设置键盘密码。其结果被按照顺序通过60h端口一个一个被放置在Input Register中。密码的最后是一个空字节(内容为0)。* D4 h6 S1 l+ z' k8 @( p
void set_password(unsigned char* password)+ }  F5 D2 n& ~+ O: x3 d
{
2 r+ E. n& T. h   char* p = password;
$ U3 e' A& |" t, W
6 e: Y3 e" ]3 ?9 K4 _/ t# N4 L5 ?   if(p == NULL)
- z0 C: c$ d6 k8 s2 k      return;
! K, ]5 n) e! P8 Z0 g  u* j% E7 G$ P# |' ^( N
   wait_input_empty();) ~( ~3 F9 X/ Y! G1 D
   outb(0x64,0xA5);
; d! `7 E( Q: @7 G
( t/ ^, G7 E# `   do{
4 k) I1 l2 F9 Z/ Z3 Q0 m      wait_input_empty();- k: R: e$ Q! {
      outb(0x60, *p);# r) X$ ]( m8 n
   }while(*p++ != 0);
& m* u6 S+ c% T/ j8 P% C, G}0 z& N) h' [3 z0 n9 c

# _2 c+ K' B: f/ B& t6 W    * A6h
. T8 `( {; t2 m, N% @8 ~3 \  u% I2 u3 w1 v
让密码生效。在发布这个命令之前,必须首先使用A5h命令设置密码。" B. r* l5 D, h) g
void enable_password(void)
* Y/ [, E1 V4 W{# V5 i# i, E- x2 \
   if(!is_set_password())* d* h0 y2 k6 Q5 }3 U# t2 d# N+ G
      return;! E# r: z4 J1 ~2 c0 E

* d- A6 P6 ~, G- L2 f   wait_input_empty();+ L2 m& C" _7 d0 p% v7 F
   outb(0x64,0xA6);   
4 \1 d( D+ B) e- ?# F9 x9 z}
  B7 ~6 k8 [# V9 U$ x7 r) v) E; q2 |  U! A( ]' x2 O
    * AAh
6 l+ j( b4 U* @& D  z2 B
5 P/ Q4 q3 ^8 `9 i5 F* i9 s) C自检。诊断结果放置在Output Register中,可以通过60h读取。55h=OK。% C. ?3 f* B% z+ Y
9 h8 T8 V8 ^2 h: b: C  [

' r3 P  k8 E( Obool is_test_ok(void)3 K; J. k' R7 B: u. A' |5 v2 Z8 N
{
  ?$ ~  E* f8 U2 |9 ]- N4 ~: s   wait_input_empty();* }# R7 p: r6 A3 E- l7 L
   outb(0x64,0xAA);0 f3 y2 e  ~* O5 T$ `

8 j) E' R5 F1 v: {$ t- ]- h3 h: g; U
   wait_output_full();4 x# p; Q; o" h9 r2 B4 z$ k" k+ n
   return inb(0x60)==0x55?true:false;   
6 J" _3 {$ p8 p0 p3 n}
. Y% J7 c8 s. I" X8 y$ X! L0 W7 Z6 ~& `: P! C4 H

7 Z6 [* G4 A) u! I8 f    * ADh/ I1 _) A1 h0 @4 s3 f& u
0 Z' O: M! x' D% L  K% f1 y4 h
禁止键盘接口。Command Byte的bit-4被设置。当此命令被发布后,Keyboard将被禁止发送数据到Output Register。
9 X( x* v8 K4 qvoid disable_keyboard(void)
: I8 B: g; t4 {, [{/ u8 }; Y0 s6 H9 Y& `1 S& M
   wait_input_empty();
7 B/ i& }) G1 s$ J   outb(0x64,0xAD);
5 W' {4 f, ]1 e3 h2 `
8 E# j, Q/ D4 W7 n. b- K0 _: e}; ^4 }) w4 |/ K( w5 {4 A& n

& f" Q2 t2 E0 @    * AEh1 O% P3 q9 h( @% X/ _

+ \/ R7 ^6 o2 }" H# k* @% @打开键盘接口。Command Byte的bit-4被清除。当此命令被发布后,Keyboard将被允许发送数据到Output Register。
. _4 i) D7 P$ J1 L! X6 Tvoid enable_keyboard(void), u9 |, l% ]: {+ l6 ?, w
{
4 h3 J# w; w% {3 w; V; H( n   wait_input_empty();+ B9 p8 t, [! v; Z
   outb(0x64,0xAE);
/ Z% u& l) H4 r: S, E! K7 N
" c6 J& T* }, M& G3 F' }}4 _7 s, A4 [; A
4 z+ P3 l2 g$ q# \: }
    * C0h
4 _+ Q" Z# H3 V& I6 @/ w/ i9 M$ C; \: V0 r) b
准备读取Input Port。Input Port的内容被放置于Output Register中,随后可以通过60h端口读取。
3 X% F4 Y5 p6 {( e: r% tunsigned char read_input_port(void)
8 [2 v  w; M: q4 W! B' @, k  f, N{$ P' w" y8 U7 H' q7 y$ f3 ~' `( v
   wait_input_empty();; e7 e# ?7 H# L& ]; o
   outb(0x64,0xC0);) i1 L# i; x5 F4 S1 p" u

6 b; y3 ^8 W* D   wait_output_full();( Z8 q: Q" Q( G( Z9 E! [8 O3 ~3 x, J

' D/ F+ h  u# p' l   return inb(0x60);
' \- Q' T, d5 ]- k  J$ ]4 G}6 n, ]7 ^1 {; q" c1 C! x
) o+ @0 N, _5 `  u) Y( H) z6 u
    * D0h. p, G  u, I. B" d# t* S7 @9 g6 F

9 D% d+ d" n% n3 b' H准备读取Outport端口。结果被放在Output Register中,随后通过60h端口读取出来。
3 ]9 u+ [" v! A3 qunsigned char read_output_port(void)
8 T/ \& G" g2 J% A/ D{8 I( W; k/ H* `$ b# b1 M, H
   wait_input_empty();5 D: y- g7 l9 D5 U) s
   outb(0x64,0xD0);- W" D2 [( a$ y! H9 g1 L

& G. c) x; E. R, w   wait_output_full();
: E& K( L  U+ ^4 h- I% h" P  _# {4 K) L- J) P; P0 M% y6 t
   return inb(0x60);
: F$ s1 M* Z" h: K8 h2 {4 T}
. M' m$ _* j: \- u7 o7 Z! z; V$ J/ X! [( |( B. J
    * D1h3 }7 a' U. x7 F% X7 O6 k
' o1 o% Q6 ]" Z
准备写Output端口。随后通过60h端口写入的字节,会被放置在Output Port中。  g5 ?* Z1 o5 C0 @3 K
void write_output_port(unsigned char __c)/ i8 @/ M  P. T* G6 u6 X
{
9 ^# V, \( ?8 g   wait_input_empty();1 y( ^4 v2 Q* l) L4 [# w
   outb(0x64,0xD1);
7 \, h* B7 w- s
! b0 A2 m8 x6 W- w, Y" u   wait_input_empty();# p4 q* K0 F5 j: f- O
   outb(0x60,__c);4 G' x4 S5 @+ H( L4 ^" k

) v; g# c. j, x" w& s& F% q# f( t}
! {4 ]( P  e# F% a, q# H/ |, O3 I) F. o8 n* [1 n! c' E4 l& H" R

# ~6 h9 s5 e% j" ]9 C, D    * D2h* e% X0 m1 f; ?6 Q! f
; V* Z! ~9 I- ?! U
准备写数据到Output Register中。随后通过60h写入到Input Register的字节会被放入到Output Register中,此功能被用来模拟来自于Keyboard发送的数据。如果中断被允许,则会触发一个中断。+ M8 s/ Y5 G4 d/ e& }
void put_data_to_output_register(unsigned char __data)6 K5 }! x/ y; g& i" e( {2 [
{
; `7 e3 Y8 M0 I8 F) r   wait_input_empty();# [' G) [, g6 U4 G/ O! s6 [: [
   outb(0x64,0xD2);6 u$ E8 Y* o7 j
" p5 ^2 X) Q5 ~: y" i5 G
   wait_input_empty();
+ L* [$ t6 u0 s+ ?* |   outb(0x60,__c);3 F9 S' _$ d/ k! W* ?2 ]* N
}
7 S8 }1 g/ V% K6 Q
) H, Z, z) c1 j" H8 s$ Q" w4.2.7.2 发给8048的命令
* T$ }9 v1 Q, h1 O; m6 l) c* V+ k9 x
; D2 W6 _6 q2 N/ P1 p! h" o
    * EDh
. k5 J5 D. y. `; @) A: P- N
8 `/ N; _9 y2 @+ k6 t! \+ O6 F8 A$ _设置LED。Keyboard收到此命令后,一个LED设置会话开始。Keyboard首先回复一个ACK(FAh),然后等待从60h端口写入的LED设置字节,如果等到一个,则再次回复一个ACK,然后根据此字节设置LED。然后接着等待。。。直到等到一个非LED设置字节(高位被设置),此时LED设置会话结束。! C0 [" V" s  n0 R3 q

2 ]5 v6 |# P) I0 Q    * EEh- M( R+ R- {6 k7 u

* q6 j: i) n1 A5 }% u" \/ w诊断Echo。此命令纯粹为了检测Keyboard是否正常,如果正常,当Keyboard收到此命令后,将会回复一个EEh字节。: z2 m9 M  o5 Y1 N" ~, X

* y' d' E7 a6 ]& b/ d    * F0h) N4 y9 \3 Q+ H4 c5 k: f# r

  X. X  q! z8 e' y5 H, x选择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代码所要求的。' G/ L* b/ ?2 s
* I2 ]3 ]" P) @) p
    * F2. i% s3 o+ j4 m* e3 u9 b

  o4 m! e5 d5 R0 F读取Keyboard ID。由于8042芯片后不仅仅能够接Keyboard。此命令是为了读取8042后所接的设备ID。设备ID为2个字节,Keyboard ID为83ABh。当键盘收到此命令后,会首先回复一个ACK,然后,将2字节的Keyboard ID一个一个回复回去。
# d  c0 R7 E' F6 K" ~6 g
, F: h& p; D9 H9 l% Z    * F3h7 h6 o0 l! y" E

- Y% s. T4 V6 d) m+ A设置Typematic Rate/Delay。当Keyboard收到此命令后,将回复一个ACK。然后等待来自于60h的设置字节。一旦收到,将回复一个ACK,然后将Keyboard Rate/Delay设置为相应的值。* A2 i5 s3 A9 c- {. O

0 v% _! Z, f1 i7 U    * F4h
5 C6 S  H5 }' B4 Z3 I
! A+ j9 V0 p* Y2 ^7 h' ]清理键盘的Output Buffer。一旦Keyboard收到此命令,将会将Output buffer清空,然后回复一个ACK。然后继续接受Keyboard的击键。& s% S8 B9 A- M( H7 Q

; J* O7 t, X& H/ P. q5 K) y    * F5h2 K* D* J# P& H& Y9 ~+ z

1 U0 {( \2 P9 R- w: v设置默认状态(w/Disable)。一旦Keyboard收到此命令,将会将Keyboard完全初始化成默认状态。之前所有对它的设置都将失效——Output buffer被清空,Typematic Rate/Delay被设置成默认值。然后回复一个ACK,接着等待下一个命令。需要注意的是,这个命令被执行后,键盘的击键接受是禁止的。如果想让键盘接受击键输入,必须Enable Keyboard。" t6 z: v7 W  @; \% w9 v

. X9 ?9 t1 t0 j# R& d8 `- a5 e    * F6h
9 M) E% y& x5 z* ]
% s3 J* n, {$ h' |: m) V! W5 ^设置默认状态。和F5命令唯一不同的是,当此命令被执行之后,键盘的击键接收是允许的。
. a6 z1 w8 S7 y7 {* m
7 G0 m. R, P/ s! N    * FEh
$ i  A" V& p; I# m2 ]& d. Y, `6 r6 [9 J* `8 g- {
Resend。如果Keyboard收到此命令,则必须将刚才发送到8042 Output Register中的数据重新发送一遍。当系统检测到一个来自于Keyboard的错误之后,可以使用自命令让Keyboard重新发送刚才发送的字节。
1 r. _) w" _$ E7 B6 M) F. J$ V
, k  f. c8 ^* {+ ]    * FFh
" ?+ P% M5 I2 a$ N2 p. ?0 F( |, b( C6 Z/ V" x; U% R
Reset Keyboard。如果Keyboard收到此命令,则首先回复一个ACK,然后启动自身的Reset程序,并进行自身基本正确性检测(BAT-Basic Assurance Test)。等这一切结束之后,将返回给系统一个单字节的结束码(AAh=Success, FCh=Failed),并将键盘的Scan code set设置为2。
回复

使用道具 举报

发表于 2009-1-14 13:49:16 | 显示全部楼层
好贴!
  }( \0 R, p( N) X非常详细!" I  u- L0 }) |: ?3 F/ [8 |; P
谢谢!
回复

使用道具 举报

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

使用道具 举报

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

本版积分规则

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

GMT+8, 2026-3-5 16:01 , Processed in 0.632980 second(s), 17 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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