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

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

[复制链接]
发表于 2008-7-14 00:04:00 | 显示全部楼层 |阅读模式
bini殇,能帮详细解释一下bios post过程中的所有发给ec的60/64命令号码和意义吗?数据量比较大,截不住。
发表于 2008-7-14 12:09:38 | 显示全部楼层
转个别人发的,不知道LZ能不能用上   7 z& w2 \( l% U5 a9 I( o* O$ U; n
5 c! {$ _6 l/ t) L# J3 f
4.2.7 Command2 C( t. l# {* }: L" O2 R( r' P

) h2 R6 k! @* h3 K1 z通过8042芯片,可以:
( J  B( o# P; ?$ W- i' N向8042芯片发布命令(通过64h),并通过60h读取命令的返回结果(如果有的话),或通过60h端口写入命令所需的数据(如果需要的话)。; l  I% N/ j* i8 u! f$ B% p) X5 W
读取Status Register的内容(通过64h);' W7 S% X. v- Y/ t3 L
向8048发布命令(通过60h);
" {8 F7 E5 C5 \1 d2 t# X/ x读取来自于Keyboard的数据(通过60h)。这些数据包括Scan Code(由按键和释放键引起的),对8048发送的命令的确认字节(ACK)及回复数据。
- w" f- o, N; x# J; n6 t
. |9 \# e( ~) @( H0 @4 H再次强调一遍,Command(命令)分为发送给8042芯片的命令和发送给8048的命令。它们是不相同的,并且使用的端口也是不相同的(分别为64h和60h)。: J1 p( M2 K2 ]4 ?+ g- Y

" c9 z# f$ U( J& I1 s$ L
/ Z# `) w. N* Q
* {6 V" S7 E# h    * 64h端口(读操作)5 }# e: z% H* c3 u
* e. R- m9 r0 A5 v! W
+ }+ @9 C  X& d' p* C- n9 f3 i; P+ F
对64h端口进行读操作,会读取Status Register的内容。- O. m9 K& l8 X9 V
/ S* Y* Z" n* M+ M
inb %0x64
1 l6 r. M! y& A. B. Z  Y7 p3 R1 z执行这个指令之后,AL寄存器中存放的就是Status Register的内容。
' C: C; ]$ f+ @3 q/ f
6 E; o) B! [; g5 V    * 64h端口(写操作)
- ?. y7 j1 O% d5 t) }0 F0 O) E! l% l3 R, f
向64h端口写入的字节,被认为是对8042芯片发布的命令(Command):3 ^5 [+ x9 P+ ?- |; H8 ^
Ÿ4 N3 p* `7 Z8 _7 v5 K* j
写入的字节将会被存放在Input Register中;
$ r9 v7 V5 ~- V2 ?) L" EŸ
+ H! G" y; F% t/ F' K同时会引起Status Register的Bit-3自动被设置为1,表示现在放在Input Register中的数据是一个Command,而不是一个Data;; a  ~4 q8 ]3 e& @: X
Ÿ. X  L: z7 S, {6 U2 U1 U4 ?1 N9 k
在向64h端口写某些命令之前必须确保键盘是被禁止的,因为这些被写入的命令的返回结果将会放到Output Register中,而键盘如果不被禁止,则也会将数据放入到Output Register中,会引起相互之间的数据覆盖;: a$ c+ Q! c% t+ ^  e3 h/ B5 g
Ÿ' {- x: N0 M5 M0 w4 k6 x( o; M
在向64h端口写数据之前必须确保Input Register是空的(通过判断Status Register的Bit-1是否为0)。- x0 s0 g& o# C. ]. ?( x
7 I0 L: Y* U! K' w" Q- F2 A
void wait_input_empty(void)" h# E+ O6 W; c
{
! T" d. j' t- P2 b4 c0 O$ f   char __b;
8 c( X2 I, l' K
* g! p1 E, }. N7 ]5 `5 @   do{
' ]- z4 ?( w$ O     __b = inb(0x64);% J4 j$ R+ n7 G" ~0 n: @
   }while(!(__b&0x02));( r. w/ w  o% l2 w$ ?; Q2 z
}! Y8 X0 d( {6 {) E5 F/ _
: g: ?! ]- b# c" C
void disable_keyboard(void)
' C% u  ?! l% n+ H- ?{7 J% n* ?3 B& f. L- q8 Q% C* g
   wait_input_empty();6 p9 ?8 p- Y. m1 @4 f* V5 l
   outb(0x64, 0xAD);
1 X) F7 S4 C1 ~}[size=+0]  s+ J+ y  p% O# Y! |6 Z! B: e* c

7 }2 z' I4 }6 R5 ~5 M" R    * 60h端口(读操作)
. i" Q# E7 R* E$ V, d- C  b( H8 a$ A3 N( W& l5 p
对60h端口进行读操作,将会读取Output Register的内容。Output Register的内容可能是:* e3 y" b+ X# k- V8 h  _, u# T9 Z
Ÿ           来自于8048的数据。这些数据包括Scan Code,对8048发送的命令的确认字节(ACK)及回复数据。
  h$ N" F$ `5 p/ E+ l) F" q5 EŸ           通过64h端口对8042发布的命令的返回结果。0 k7 D# h, g: j; ?5 k

/ A5 L8 I. r0 u0 y$ W在向60h端口读取数据之前必须确保Output Register中有数据(通过判断Status Register的Bit-0是否为1)。
. d( O' L" G5 ~4 g" v% ?void wait_output_full(void)
; [& O' V( j8 d: V8 H{
! S  D: M/ G  O7 I$ j   char __b;# ^' ?5 q5 L, j
# n( v  I6 [4 I3 M. t
   do{
1 O) O& ]5 F+ z9 a     __b = inb(0x64);
6 t/ E% U- O. ~% `' s( d   }while(__b&0x01);2 a$ G+ g. h( u. F% R
}% J+ n. V! F5 `8 p$ P, H
: L: S. a7 h& Z- s, ?, |$ e) u( f* x0 P
unsigned char read_output(void)
! W7 k- }8 ]" e& ^1 k' x- o, m{
( {2 n3 A* J" p! X  e5 u! |  T( O* j   wait_output_full();
3 l# V) S+ }0 Z9 V6 t3 O" Y   return inb(0x60);/ W- y7 p- q$ d$ P9 @$ W
}
5 A( R  k. L1 X; O$ d5 n1 L; D& t+ \) r
    * 60h端口(写操作)
# v2 |2 I1 c& F1 i* m0 S3 P
4 H6 D) ]7 U8 s8 I9 l* G# [向60h端口写入的字节,有两种可能:
! P/ p) O6 N8 ?8 V* o9 B1.如果之前通过64h端口向8042芯片发布的命令需要进一步的数据,则此时写入的字节就被认为是数据;% i& H( j' s( z' V
2.否则,此字节被认为是发送给8048的命令。9 @3 w$ b. O/ w& P
+ k# ]' R5 ^1 e# n0 |: C( J
在向60h端口写数据之前,必须确保Input Register是空的(通过判断Status Register的Bit-1是否为0)。
- ]5 Q& c1 d: T; F9 S2 W3 @% L" R. J. Y  D! a$ d; q

( F; x4 `; e% R2 n% W[size=+0]4.2.7.1 发给8042的命令
# X7 Y+ M0 K$ b$ S8 o0 F2 R
0 A0 Q! Z* G' C( D8 {( q2 o    * 20h
1 X$ h; p# t% y% K8 p/ H- \# a1 g- U( ?3 m! i
准备读取8042芯片的Command Byte;其行为是将当前8042 Command Byte的内容放置于Output Register中,下一个从60H端口的读操作将会将其读取出来。" b* _2 C2 O5 X

) u5 m9 @4 T. }7 w) Y  a6 C" A/ e2 O9 u
unsigned char read_command_byte(void)! i; Y4 y' ?: b$ `) [- N; B- r  V
{- t. t( V. G6 o7 a4 f3 [- D6 V
   wait_input_empty();
0 x! M) n5 u% B/ d   outb(0x64,0x20);
( k) K, @" R! i9 S6 o( d+ X( V; S7 f   wait_output_full();/ x/ _1 H6 z. j: x2 `
   return inb(0x60);   
0 b: A/ v4 p5 X}  B, Q- d% V) X' s/ _/ M. _

% X& G- m5 z/ I, V3 W2 d    * 60h
4 @+ e. N/ m  f* n6 y  O1 b
8 _9 X5 p4 Y: q* Z& \. M准备写入8042芯片的Command Byte;下一个通过60h写入的字节将会被放入Command Byte。% ^" e' o4 i) [& g' ~! u- |
! t! ?% m% Z- @) q

6 M" U' J! y3 |void write_command_byte(unsigned char command_byte). }; R( w! o* i# S- \9 p: B% E
{
* S& B: b8 A0 x1 r% U# F7 Z   wait_input_empty();+ Z, n) X; h- q
   outb(0x64,0x60);6 g  D2 M& @; t& s0 R
   wait_input_empty();
) \& N! f$ l) y7 k5 k5 O   outb(0x60,command_byte);
) |8 v+ Z* R. N: e2 ]2 X}
* Q. l1 k; z. N/ M0 U4 A0 X' O+ J, s
/ M9 ?# o8 K  S$ O! C1 w! z
    * A4h' h+ A: K; h* E
1 K* e) {7 z) `% }7 n8 T* p" p' Q
测试一下键盘密码是否被设置;测试结果放置在Output Register,然后可以通过60h读取出来。测试结果可以有两种值:FAh=密码被设置;F1h=没有密码。
. S+ T/ m  j1 a, F3 D) t5 ]bool is_set_password(void)
' a) [* r" d; ^' ]. f{
4 ]) m8 g5 C7 a1 o   wait_input_empty();2 ]: f4 {9 P+ l! z! E
   outb(0x64,0xA4);! q; a9 }- \: G' \& Q' L# _1 Q
   wait_output_full();
) Y) K, l( U) Y5 D3 I6 U' V4 s   return inb(0x60)==0xFA?true:false;   
0 I! g! u5 [: F! N2 e}- K: R* Q) d( i2 y5 D! t- F
6 U, [0 m* V+ d; U- F: T, P. H
    * A5h
; a. J8 T; H% u
2 T7 q3 i& L& W, d0 ^设置键盘密码。其结果被按照顺序通过60h端口一个一个被放置在Input Register中。密码的最后是一个空字节(内容为0)。
4 V& _( ~6 U7 U  V: f5 T! y1 zvoid set_password(unsigned char* password)
+ a- @* y) i8 J5 M" w! H0 Z7 n- C2 m{( F5 M! w; v  w0 c
   char* p = password;4 t2 \/ N. y3 n2 H3 m7 m
% ]/ K7 I' p+ D1 r: B
   if(p == NULL)) r  ], q- L4 C
      return;; w( R) h; E! l# b' N

+ X2 Y$ p  q3 D" G# W5 L   wait_input_empty();! g3 y. P' r) M8 s
   outb(0x64,0xA5);
: L4 ]! }! Q0 l/ I" Q. Q( b* k8 r% a0 F0 w* Z& q
   do{, y* U4 r) O$ ?6 Y. n* }  h$ b% c
      wait_input_empty();
8 L4 Z) @; |6 [      outb(0x60, *p);: H7 }3 O5 Z1 Z8 e, ^2 O
   }while(*p++ != 0);) Y: K+ w7 R* X! }; L2 ?
}
/ H  w0 s" L+ I, N' ?/ f3 g. t+ D
' Y, d/ f8 W. H2 I. d1 \2 f    * A6h' E" }5 t& v) p. s! v

; l8 r/ k% U7 m+ d/ z让密码生效。在发布这个命令之前,必须首先使用A5h命令设置密码。; B8 o8 a0 H9 B8 X2 A5 k- b
void enable_password(void)* k6 q  n6 ?# K: A* o
{
2 S$ c/ I  f; `+ {  A# `   if(!is_set_password())7 n# |0 S; G$ |4 Y9 D8 u
      return;0 |0 {5 S8 Y  g; [6 B! R2 Q" i4 g

: i7 [6 U5 K; Z5 M* p   wait_input_empty();! _6 J5 r! x- d6 A0 M# E
   outb(0x64,0xA6);   7 s7 l  P. v, @, C0 w8 V# e
}
  Z8 c+ I8 a# w) V% ]9 G! x
& W2 G: V" u# h; C& a# e* H    * AAh
: e; q; A4 m' z2 D7 P5 N; K0 E- f/ g9 g
自检。诊断结果放置在Output Register中,可以通过60h读取。55h=OK。
7 }9 P, o6 \5 S/ ?& v! ?8 r( ]2 F- O# x

; A$ E; q2 t) h- b1 T/ Sbool is_test_ok(void)
4 V+ M( ^1 I  L5 n5 D4 X# v% P{
8 e  P: g& t! \: \   wait_input_empty();/ u( B, ~* [, S6 L# \
   outb(0x64,0xAA);7 a& e0 g) k' u
  Y* m, H8 g  P
! E" |. R- ?% V; r( p# C
   wait_output_full();) C% U/ J4 [1 l: q4 m
   return inb(0x60)==0x55?true:false;   % x/ R0 K6 C0 d; \" j/ I7 e% _$ }
}
+ l/ A& U8 g" @' w9 d+ A/ O6 x' J$ w" T, B# ~+ e0 w) `

( l3 H8 h; e& M    * ADh
* H( H; Q" ~+ c  i0 n7 J; D; u: n2 I
禁止键盘接口。Command Byte的bit-4被设置。当此命令被发布后,Keyboard将被禁止发送数据到Output Register。
. ]: l0 ^: H9 @6 Y# [5 |% kvoid disable_keyboard(void). g- O+ }0 v" ?
{
  G$ r( n8 z0 ?7 ?5 W   wait_input_empty();" {9 H8 c% }8 s% L3 h  u3 S/ X/ y4 C% X
   outb(0x64,0xAD);
+ N* k( ?  P3 P. o7 r
* @4 F& y& q+ W+ D6 H8 p$ ^}
: n6 p9 g/ I3 q3 F- ?: v6 a. R' ^( H
    * AEh
& t" p( g8 @% J( @! g: S
' G+ H) u: m9 }  B: c打开键盘接口。Command Byte的bit-4被清除。当此命令被发布后,Keyboard将被允许发送数据到Output Register。# p3 [4 e7 O  @& v& v6 F" O' e; K
void enable_keyboard(void)
' @& \0 X& l8 p# L1 L{6 a& d8 }' }7 _# L* G$ c: m" ^
   wait_input_empty();
; J& }. a# l% q   outb(0x64,0xAE);
( x" t: f, q7 r- L# }6 P" W! Z9 G+ a( r+ B' |8 a
}5 D- \% n( j# _3 R7 g$ Y2 `

" }  k$ s% H3 S2 f    * C0h
1 U4 g1 B2 `% i" w& G
: {3 U$ D. M/ I准备读取Input Port。Input Port的内容被放置于Output Register中,随后可以通过60h端口读取。+ D! G6 M) Y% m  f, \$ E7 R
unsigned char read_input_port(void): h$ W4 D: ?. r( B8 \2 \
{
8 k& z6 ]$ N1 }1 Z: a3 G+ E   wait_input_empty();
. @$ y( |7 u. d  ~9 h   outb(0x64,0xC0);
' x% ?' S" b# s0 l! X7 e! _
& f2 C1 y3 t0 G; }3 |' a   wait_output_full();
' S. f- N# [; X* C, s9 S1 G7 Y6 D* M6 |5 [# d
   return inb(0x60);
! {, S% }# _  |& _4 S7 o4 i}7 l/ |* O0 K  v# i" M, N1 G2 P# K
) I; P" M" f$ i' L( O* B- F" E
    * D0h
6 E- c8 c2 d8 O1 I4 r9 w4 G7 k, ]& T0 A0 O
准备读取Outport端口。结果被放在Output Register中,随后通过60h端口读取出来。' j3 v4 _1 T+ h: S7 x5 @. S2 c" X
unsigned char read_output_port(void)
, u  r4 d/ d" V2 w2 X- o4 {# g{8 j" _$ v1 P5 D% X
   wait_input_empty();3 R/ f) A3 G5 x% W9 `( s5 l5 E
   outb(0x64,0xD0);4 g' a( @% b" z& \& b, I: g; {

8 b# S% I4 r' P" l   wait_output_full();4 L' s  v  i8 s5 `" p, b

8 t; `) d3 u: I6 Q2 C   return inb(0x60);& M* L2 M$ U, Y" g
}$ ]4 s' l, ?* {9 v/ C. k, ]

1 S0 }3 \; g# E    * D1h
2 b# B/ `) z+ i# {' I% t. [2 k: v0 O, L% E, F! ~
准备写Output端口。随后通过60h端口写入的字节,会被放置在Output Port中。6 w! w# v$ |. w; W+ a
void write_output_port(unsigned char __c)
; B& P- x0 D: P' r; {8 \{
$ e& Q& H- K( t. k9 t: T   wait_input_empty();
) a- f3 o- _5 X9 w& j  M8 y% k   outb(0x64,0xD1);
5 E& W% n- {) `0 _: I! a
' h* e/ O$ g! q1 Q% ^5 ~) ]5 O   wait_input_empty();. j9 P- f: c, ^7 J9 n$ b+ ]. D
   outb(0x60,__c);
/ |& ^# B' h7 P: N3 \9 Z3 \" s
/ O# j* T4 A# M/ s! R9 n3 }& s}
* o- A9 s& D9 d) g% e9 D7 j- y
2 @. s8 E( a" \
7 p# H% Q0 H3 E. y7 ]    * D2h$ g  z4 ~: G& p! w1 J/ I* B3 f

( y. a* J- {' {7 Z* i( u- V* h准备写数据到Output Register中。随后通过60h写入到Input Register的字节会被放入到Output Register中,此功能被用来模拟来自于Keyboard发送的数据。如果中断被允许,则会触发一个中断。
0 ]- I4 B/ Q1 i0 i% tvoid put_data_to_output_register(unsigned char __data)
7 p2 z! t" Q1 q: e# E( i+ I& W) ^9 z0 n{
4 _  m- H; X( Y) w4 ~   wait_input_empty();
: \7 \2 q6 Z7 o+ ]% q   outb(0x64,0xD2);
) [, y+ C4 r, U: b' |) D$ R! y$ ?7 b; j3 ?! Z
   wait_input_empty();
( B+ r# w2 C) s) v2 E   outb(0x60,__c);
% z4 A# ]2 A% H- t+ Q0 F  B}
+ _; u, Q7 C5 f6 R+ r
# M, E0 q# ^1 m4.2.7.2 发给8048的命令
/ Z: R5 ?3 W# O/ v
6 A3 \6 u. N9 c0 [2 t4 R! P( Y& ~4 e+ T" o
    * EDh
% @: s: v# \5 Z, s) G1 r9 P
) v" |, p  C2 r% g" |9 w8 c5 F设置LED。Keyboard收到此命令后,一个LED设置会话开始。Keyboard首先回复一个ACK(FAh),然后等待从60h端口写入的LED设置字节,如果等到一个,则再次回复一个ACK,然后根据此字节设置LED。然后接着等待。。。直到等到一个非LED设置字节(高位被设置),此时LED设置会话结束。8 c& p6 }) c8 c/ T" L; k
: J9 u& g7 ?9 c! x: l' Y
    * EEh
0 a# g% h/ P2 ^" k- ~
, l, w( A2 P* e+ j! M3 N5 d+ c, t诊断Echo。此命令纯粹为了检测Keyboard是否正常,如果正常,当Keyboard收到此命令后,将会回复一个EEh字节。5 s: W1 u9 f7 F
! G4 @- J+ A" k0 b+ M* {* f
    * F0h# h) t. Y, Q3 ~) J1 L1 e4 Q
* e- ]5 d* [& `. y0 d( \6 z
选择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代码所要求的。( Z0 u/ z- x  x1 m

: m$ E/ i  f" z1 V' T    * F20 |7 M8 y, k0 ^

  ?( ]/ |9 E' R8 F读取Keyboard ID。由于8042芯片后不仅仅能够接Keyboard。此命令是为了读取8042后所接的设备ID。设备ID为2个字节,Keyboard ID为83ABh。当键盘收到此命令后,会首先回复一个ACK,然后,将2字节的Keyboard ID一个一个回复回去。  P! E7 A# q% U, ?, A$ w- Z" u
: t! k3 ~7 p* R1 o: |
    * F3h
* t2 e5 ?) n' _% m. ]* v# R& W% E8 y3 d/ M
设置Typematic Rate/Delay。当Keyboard收到此命令后,将回复一个ACK。然后等待来自于60h的设置字节。一旦收到,将回复一个ACK,然后将Keyboard Rate/Delay设置为相应的值。7 U% q( @8 K$ G  _
; }: z" Z' g/ J' B
    * F4h) B& o5 a9 T- l" A- r% L9 B6 M. O

* O3 t* q, A( N# U清理键盘的Output Buffer。一旦Keyboard收到此命令,将会将Output buffer清空,然后回复一个ACK。然后继续接受Keyboard的击键。
8 p; l) }  ]; s2 E* k( I' m8 @% i- _* b' @) b
    * F5h3 O6 p. q% ~) d" M8 s3 ~

0 R6 y1 H) v" R3 Q. J$ C9 I: V# |设置默认状态(w/Disable)。一旦Keyboard收到此命令,将会将Keyboard完全初始化成默认状态。之前所有对它的设置都将失效——Output buffer被清空,Typematic Rate/Delay被设置成默认值。然后回复一个ACK,接着等待下一个命令。需要注意的是,这个命令被执行后,键盘的击键接受是禁止的。如果想让键盘接受击键输入,必须Enable Keyboard。
9 h" ]% D% R% p- V, a) W
% y0 Z/ h" A! P0 Y. m4 r. u    * F6h
2 E9 L  r$ D$ V0 Y/ _  H0 J  R& G7 g: z- S0 F
设置默认状态。和F5命令唯一不同的是,当此命令被执行之后,键盘的击键接收是允许的。
& q5 B/ ~8 w6 l$ E% q2 U2 K( n5 f% Z" ?7 ^9 r% B9 h
    * FEh
! L6 j, b7 v- \5 Z' p% q' k3 s# h! U: h. b; H( H' c
Resend。如果Keyboard收到此命令,则必须将刚才发送到8042 Output Register中的数据重新发送一遍。当系统检测到一个来自于Keyboard的错误之后,可以使用自命令让Keyboard重新发送刚才发送的字节。
+ ]/ U' e/ d4 Z( u' r
9 X& i& r& B9 T! G( M    * FFh: ?4 ?2 O' x! d" m" z

, A, k9 r* Y0 @$ e9 v& MReset Keyboard。如果Keyboard收到此命令,则首先回复一个ACK,然后启动自身的Reset程序,并进行自身基本正确性检测(BAT-Basic Assurance Test)。等这一切结束之后,将返回给系统一个单字节的结束码(AAh=Success, FCh=Failed),并将键盘的Scan code set设置为2。
回复

使用道具 举报

发表于 2009-1-14 13:49:16 | 显示全部楼层
好贴!. h/ h4 ~+ Z& _4 S( q7 I
非常详细!5 M* `. x( p- S; S, k3 T
谢谢!
回复

使用道具 举报

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

使用道具 举报

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

本版积分规则

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

GMT+8, 2026-10-20 09:30 , Processed in 0.083328 second(s), 17 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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