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

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

[复制链接]
发表于 2008-7-14 00:04:00 | 显示全部楼层 |阅读模式
bini殇,能帮详细解释一下bios post过程中的所有发给ec的60/64命令号码和意义吗?数据量比较大,截不住。
发表于 2008-7-14 12:09:38 | 显示全部楼层
转个别人发的,不知道LZ能不能用上   0 m, o7 a( b, x& B* n" L9 k, v
3 R' A! {* N$ w& J
4.2.7 Command
! L# a0 Y" _. J" G0 R. b: K' S3 s
, t) w! h6 F7 |: J' V5 G( k& ?通过8042芯片,可以:' _1 h/ S; B* Z2 S' s
向8042芯片发布命令(通过64h),并通过60h读取命令的返回结果(如果有的话),或通过60h端口写入命令所需的数据(如果需要的话)。" {7 y, f% _! A( k  r% E. T
读取Status Register的内容(通过64h);
( s- |0 b6 A9 a: D4 G8 z9 \向8048发布命令(通过60h);
' b& b& l+ b- {6 y读取来自于Keyboard的数据(通过60h)。这些数据包括Scan Code(由按键和释放键引起的),对8048发送的命令的确认字节(ACK)及回复数据。
8 U8 ]5 `1 W; ]
, c+ h& G5 M+ g8 b" P再次强调一遍,Command(命令)分为发送给8042芯片的命令和发送给8048的命令。它们是不相同的,并且使用的端口也是不相同的(分别为64h和60h)。
3 ~8 u/ `* I  n9 e; t1 y! J6 V! R3 @$ a/ b5 d) T' k  H3 m+ I5 g

& u" R# b/ k7 b/ \+ u  P) j! r5 b3 P. y
    * 64h端口(读操作)/ \% m8 F- l2 a8 Z  r5 D
8 i& A% p# n' r6 F+ m

, H& u* V* @/ ~; S! H对64h端口进行读操作,会读取Status Register的内容。/ k/ f3 J) C5 T7 O: b
  r: i+ V. P5 \1 E" b
inb %0x64: D/ k0 r3 P* m  f
执行这个指令之后,AL寄存器中存放的就是Status Register的内容。
9 R3 j& U* p0 J0 r0 C- i7 _/ G7 c" W$ f
    * 64h端口(写操作)
8 @6 H. t8 ?7 T' M* ?) ~- m/ e1 C. W) t
向64h端口写入的字节,被认为是对8042芯片发布的命令(Command):
9 a) j, w% g8 A- m" XŸ' \, J& Z5 E( f3 @
写入的字节将会被存放在Input Register中;- \6 j. P: U  a* e! R6 e1 D
Ÿ1 g& ~2 x/ J, L; U9 b% m2 b
同时会引起Status Register的Bit-3自动被设置为1,表示现在放在Input Register中的数据是一个Command,而不是一个Data;0 f9 t. s, L& l6 ~: x! i$ ]
Ÿ
: i0 X$ ^. [! K, s- ]$ L2 @8 \在向64h端口写某些命令之前必须确保键盘是被禁止的,因为这些被写入的命令的返回结果将会放到Output Register中,而键盘如果不被禁止,则也会将数据放入到Output Register中,会引起相互之间的数据覆盖;
5 g+ t" l  O1 J2 sŸ: U8 g7 R; k( g: \+ N
在向64h端口写数据之前必须确保Input Register是空的(通过判断Status Register的Bit-1是否为0)。: m2 }/ F) L4 ?+ d. U7 q
3 f) a, q; \  }3 j" V6 {$ P& s
void wait_input_empty(void)) T  A; r+ ~& i
{. i2 {) H5 V! j6 t: r% ^! F: z
   char __b;; H3 X$ R$ z3 D

/ G% G% _" W5 q   do{; c0 j) c" O& E7 I
     __b = inb(0x64);
& t0 d7 z! n6 ~# U1 G   }while(!(__b&0x02));* a  S5 a! D1 K% G7 U
}
6 z2 C( Y; [- O2 V
# f  O& P9 l6 H1 k6 rvoid disable_keyboard(void)
' @* J7 x6 {# t. n4 W( ~{
7 q! I/ Q- @5 j% H! Z3 M; S   wait_input_empty();
0 r/ x2 W6 H" y" a: o! {   outb(0x64, 0xAD);+ Q  e& m7 V+ k: L( B8 U
}[size=+0]" a1 V' ]& ~  ~; O( E4 W

" @5 F) Z: @8 M% i/ [$ L9 B    * 60h端口(读操作)" _$ c9 ^- j5 q( `# l
7 c% D6 y/ o' k* _7 o
对60h端口进行读操作,将会读取Output Register的内容。Output Register的内容可能是:
( a- F  N/ n' FŸ           来自于8048的数据。这些数据包括Scan Code,对8048发送的命令的确认字节(ACK)及回复数据。
8 P4 ?  _( ?  \, Y; CŸ           通过64h端口对8042发布的命令的返回结果。! I; t+ B) C  z7 C* b7 a' n5 P

) Y% }1 {3 {  W) m% |7 a# @* Y在向60h端口读取数据之前必须确保Output Register中有数据(通过判断Status Register的Bit-0是否为1)。) K, D2 @4 H- Q. V. I" u4 K
void wait_output_full(void)
) y3 B: s# i  C5 I! I1 I9 Q. b{3 w. o* S" b! }% b
   char __b;
* Z% h1 ^; s9 `  f
# Z* e8 ^' l+ q. ]   do{! h" i% V- M2 o- i& m% ^* T- Y
     __b = inb(0x64);
; n9 \7 K# i2 L1 }( _) r   }while(__b&0x01);5 G+ m+ t1 ~9 N# s  |' y
}
9 [4 N5 P! E1 }% \+ R, e1 F
( G3 [" F& h% q# e( @& Junsigned char read_output(void)* G' R: n2 H9 W+ V8 s4 a
{
9 v" w4 J/ {6 k. P   wait_output_full();4 M6 k3 i8 N- d1 v' z" c
   return inb(0x60);
% ]# P5 @! X) v# f# R}$ l) T' V  _5 R  x! H
5 H! k0 d4 t) ?' D; F, P, s
    * 60h端口(写操作)( s- p& b6 R: |9 h6 @6 v' ?9 s, i
/ p  t9 ~& c5 O8 Y  J, W% n
向60h端口写入的字节,有两种可能:
4 P% y4 i6 l2 W9 p; h7 x% L1.如果之前通过64h端口向8042芯片发布的命令需要进一步的数据,则此时写入的字节就被认为是数据;* o3 c8 M0 u. D
2.否则,此字节被认为是发送给8048的命令。
; n8 s9 J* P, j/ m0 Z- e8 w( G9 W* t" s/ @; H$ |1 P- `  Q
在向60h端口写数据之前,必须确保Input Register是空的(通过判断Status Register的Bit-1是否为0)。
$ v8 Z. G* h' o
& G# b- K3 W/ ?: r1 S7 W
, q. O- ~2 n7 L# e[size=+0]4.2.7.1 发给8042的命令
2 L7 Z$ K8 \: {. E( z* R+ L: B
7 d8 T  I& j! A; j5 W    * 20h
$ y1 M+ S, u6 r% t1 F  A) J# `: u8 D  G/ ]) s6 r: o4 S& \+ z. {7 r- X
准备读取8042芯片的Command Byte;其行为是将当前8042 Command Byte的内容放置于Output Register中,下一个从60H端口的读操作将会将其读取出来。
% i( A' O- w  y; d6 X
, X4 Y% r0 D" t
5 A8 V9 Z8 A" ]% q' H9 Uunsigned char read_command_byte(void)1 o7 |& q* @2 C3 ^% \
{
) {7 i$ h5 b* R   wait_input_empty();
5 L2 U3 I5 O- T( E4 v1 z   outb(0x64,0x20);! r! h- z3 m6 {; p1 j
   wait_output_full();
5 H1 f1 R: i/ e   return inb(0x60);   
) f  S- N. Q7 ^. M: K; U}
4 J3 A) Z' ^  A4 s- J9 A- X" }- V
    * 60h
7 P, a2 M8 K) P5 H* b* j" h* B: K2 R2 T2 D
准备写入8042芯片的Command Byte;下一个通过60h写入的字节将会被放入Command Byte。+ U) q2 L0 ]" \) l& _
) s1 y8 J4 ?6 b4 o

' H8 n  N6 o" ]) bvoid write_command_byte(unsigned char command_byte)2 U; e* d7 n; R) y0 ?9 d" c+ ^5 v
{; p  w( X0 x1 ?: J- v  z
   wait_input_empty();( |: y! a& D9 v
   outb(0x64,0x60);
9 x% X3 K& u+ t/ c$ d   wait_input_empty();% `& _; ]* B+ O
   outb(0x60,command_byte);, w* c2 j& k. l7 }4 v& m  G
}
$ @; w7 X1 _/ g; j- |" a; M$ }  ?/ `' I
* t6 n* F) d1 d  w! T
    * A4h
7 x' W" t$ N' e9 G; _3 V8 `
6 P# d" @6 Z+ E$ ^4 h6 ^测试一下键盘密码是否被设置;测试结果放置在Output Register,然后可以通过60h读取出来。测试结果可以有两种值:FAh=密码被设置;F1h=没有密码。+ E! u" H, k8 |1 C9 w
bool is_set_password(void)
6 Y( j- b3 Z) G9 n& f{7 t5 B) j6 ?' s% w
   wait_input_empty();
% M  @, L: ^1 X  a. W4 e   outb(0x64,0xA4);
$ R9 O9 K" d7 l3 |  a: a   wait_output_full();
. @. d! Y8 N8 i) E3 M; ?   return inb(0x60)==0xFA?true:false;   , k4 v4 G3 u. k5 B
}# u6 _4 i8 B; G9 g+ I3 |5 c& |

( C% @8 `; M# ~8 Q9 s    * A5h$ c2 C) l0 E' N# N: n
& m! _5 O! m, Y' n
设置键盘密码。其结果被按照顺序通过60h端口一个一个被放置在Input Register中。密码的最后是一个空字节(内容为0)。
4 n8 M+ z, Q+ Svoid set_password(unsigned char* password)8 T* ?/ g8 K6 C2 |& r. A. u
{
  a5 z/ P* ?: g9 w   char* p = password;
5 W- j- z& D) J  Q( E- y! J
" k/ s+ D4 N5 i- z   if(p == NULL)
, a& R3 b/ B, S4 b2 I4 s. F      return;
( U7 Z/ u+ J) r5 O: R( Y8 P2 ^( J' U& {* m9 `3 c& |
   wait_input_empty();
) T3 r, D1 u* y) `; Y6 \1 r$ x   outb(0x64,0xA5);' u# g( ~! r* i# g8 @4 }

! p" o3 c7 o: y4 o8 S2 j& @   do{
4 A# V, G6 A) D0 r# G: k      wait_input_empty();' M1 F" |( ~4 q0 N, ^
      outb(0x60, *p);
9 b6 A7 Q- k4 a$ c) c3 [: H   }while(*p++ != 0);
  ?3 y6 N$ ?+ E! x) Z: n}
' O, V# K7 Q% \5 V7 w. N: ~9 y- \6 K+ J
    * A6h) ]; x! u  s) ~( f  V7 r- S' N$ ]/ D
" J0 ?" U" x4 v* m6 }) y
让密码生效。在发布这个命令之前,必须首先使用A5h命令设置密码。" ^5 R' I9 |! a2 P
void enable_password(void)% V3 |; T2 n4 q
{
! m. W( K# R$ y$ r   if(!is_set_password())2 M% D+ T. @  e' o
      return;
' f; U3 r) }! ~+ l6 c$ |
7 i4 m- o1 P5 p1 b( z; N   wait_input_empty();$ y' d+ X. E. e; G7 N
   outb(0x64,0xA6);   
- T/ |* Q7 K0 L+ |2 v}
( A/ ^! ]( Q7 B& s( r! Y2 t% U1 {- {/ I4 W
    * AAh3 ?, |! g5 w4 M

; }: x  \- ]4 n: U+ S& e0 _& f自检。诊断结果放置在Output Register中,可以通过60h读取。55h=OK。
- S3 Z! M$ d2 E/ Y* b5 x$ {
1 H7 f; \4 M: `- x) O% N/ T4 M9 g2 K, v4 c
bool is_test_ok(void)
; W, z6 s: U. C! V. {6 E* h{. y/ i1 Z5 g9 W
   wait_input_empty();
4 ~: n8 w+ i5 b% D0 p   outb(0x64,0xAA);
& k8 ?4 Z' T$ @" W1 }6 e8 {4 M- R& i- W; }) B7 @8 f6 u

8 R+ w5 F/ \# J+ @# t   wait_output_full();* K" V* S$ S' S- d/ [! }5 [& h7 E
   return inb(0x60)==0x55?true:false;   0 D! ^% L* e0 h5 p3 X5 ^
}- n7 U/ U2 V: L5 A* @
/ {3 ]# p8 E% t+ l8 J
. W2 w5 x. r8 w7 q$ g4 T: t5 `8 U
    * ADh0 F- I, t3 j. A: V0 ?

% S* ~* b* s& \  _3 @" J禁止键盘接口。Command Byte的bit-4被设置。当此命令被发布后,Keyboard将被禁止发送数据到Output Register。
$ c' A9 }" O5 {void disable_keyboard(void)* x* b1 v1 {6 U6 v2 g& C( {
{  P$ b4 s1 N* B. |) j" H" f( t
   wait_input_empty();
! V$ |. Y) A, \# j" K   outb(0x64,0xAD);
# K% a) U8 z* s/ B, y* x! E6 Y& Y" u2 R6 q# d
}
* @- ~; B/ \- G. L( y. d+ b! y2 Q5 e" y, h
    * AEh3 I' S% g0 Z$ e$ V6 ]# [& m
) y7 k! \$ y- w7 f3 M' |9 i. t
打开键盘接口。Command Byte的bit-4被清除。当此命令被发布后,Keyboard将被允许发送数据到Output Register。. c' i8 Z  I" V4 M+ l/ y
void enable_keyboard(void)2 B3 e$ Q4 h% v0 z: \; Z
{1 `  T4 q/ a3 U) o
   wait_input_empty();4 K" x- z( d7 Y" Q
   outb(0x64,0xAE);
: E7 N0 y$ B- Z" H2 ]; ]) x
7 h$ ]! C# }/ ^2 _* @1 Z- K}* G# q" P- z& [& L" v

6 j% O. r% v  o% z, F2 U% F    * C0h: k  T1 O) l3 q7 s! k/ c4 v# v
- Q9 m3 l! `1 X& {. b; y% ^
准备读取Input Port。Input Port的内容被放置于Output Register中,随后可以通过60h端口读取。4 a, ?5 `& G( L% H; T
unsigned char read_input_port(void)
/ w# E' p* U' U: g8 n{
1 _' a6 N7 U  [! B& {( d   wait_input_empty();
* h+ k; \7 Q* P+ a   outb(0x64,0xC0);) g4 {4 u7 k6 X2 Y2 a  u
' u7 k! \% K) |& W$ e# D( G+ T3 J
   wait_output_full();5 H1 E( J- `" C9 H

  I' I. I4 Y% ~; O1 T   return inb(0x60);$ ^" V4 `  D: c1 R% u; C. I
}$ @0 g* e7 {  |; l! E

5 z( u1 y& H" e/ ^) L8 b    * D0h
. x' {' [9 ~' L; P1 b& G7 l" d( r: G" R8 h
准备读取Outport端口。结果被放在Output Register中,随后通过60h端口读取出来。
2 O* S: E% a2 A9 zunsigned char read_output_port(void)7 g' k- P; X& B, m) m% ]( a" F
{
" x) |, K" X# ~  x- W   wait_input_empty();
( c0 J# ?+ r7 t- a1 i7 y7 f& D: O2 g7 z# m   outb(0x64,0xD0);
( H3 }& ]: I  o  d
4 C# C) i; T- I& u+ w   wait_output_full();
9 {7 N" O8 [" P+ O* E1 Z5 q0 e- o; d* ^) ]: ^+ Z& l, v
   return inb(0x60);
( S* _5 z( w0 w}' P9 n! |$ C0 P

% d5 w7 W2 s3 n* G4 A    * D1h
; o5 |9 F4 U$ Y' i# X
) }/ D( N' Z+ @( l, w% k准备写Output端口。随后通过60h端口写入的字节,会被放置在Output Port中。
% R, [4 W) w3 V+ ~1 P1 i* Ivoid write_output_port(unsigned char __c)* ]' b: x. v* t) D% A" [7 U
{6 q3 \; Y& f+ [' l/ y8 R0 l" }
   wait_input_empty();$ e7 T3 [) C, O7 B
   outb(0x64,0xD1);
! @. Q/ O1 F4 q& e) Q/ R2 Z
" O& A8 |3 o# ^2 @1 _/ {8 c   wait_input_empty();
' y6 t, Z' o+ [# X# c# x   outb(0x60,__c);; \% x/ q7 M1 p7 B3 m
6 H' B2 M& p7 g' y1 n2 _9 Y9 W8 [& T
}0 o5 V" N0 K5 @' Z
) p) ^" s2 N  _+ S; H9 |- h

7 f- _. R3 a/ t0 P; \3 Q2 d    * D2h
2 N- M# T! N* I: v; F8 M. F" x
5 Z. I& M) z' v2 T准备写数据到Output Register中。随后通过60h写入到Input Register的字节会被放入到Output Register中,此功能被用来模拟来自于Keyboard发送的数据。如果中断被允许,则会触发一个中断。
. N: x) g" m  a8 Wvoid put_data_to_output_register(unsigned char __data), d' @5 Q& A7 |
{
5 l1 \! v8 b2 }1 G/ T   wait_input_empty();
( w' _4 k! ?5 P3 q! k+ |   outb(0x64,0xD2);& T; `+ a( h: U9 b, b5 y

5 E3 X! L1 C! e# Z   wait_input_empty();) W) G; ?. A. e# v$ T0 j# {$ G8 I
   outb(0x60,__c);6 h2 l& }- A8 f
}, X; e* G5 z$ Z# v7 a

7 U' S: P+ [. T* B/ a4.2.7.2 发给8048的命令5 \/ E( ?- D' `# |% a

5 R% Y* P$ y* U1 k! w, J  Z" j- `4 S& e+ A6 M5 t: F
    * EDh/ J6 y/ M4 W9 X4 v2 g7 y

4 _* X2 X. U, Q  k- z4 @! V9 E设置LED。Keyboard收到此命令后,一个LED设置会话开始。Keyboard首先回复一个ACK(FAh),然后等待从60h端口写入的LED设置字节,如果等到一个,则再次回复一个ACK,然后根据此字节设置LED。然后接着等待。。。直到等到一个非LED设置字节(高位被设置),此时LED设置会话结束。7 v) N& q/ ], ^, W" u  K, S
* g! {  e1 M' O- H/ C$ `2 T
    * EEh; Q/ s" t) Z  W# g6 D
6 w4 y- M6 b, E0 K2 X# z
诊断Echo。此命令纯粹为了检测Keyboard是否正常,如果正常,当Keyboard收到此命令后,将会回复一个EEh字节。
' v/ X* D6 k1 F( `4 M" G. \8 o! J
    * F0h2 S$ Y: X: s* Z9 J
7 p8 R5 _6 ?6 b, w2 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代码所要求的。
# O3 }4 Y5 `, N, D! c- M9 u
& N- z" F& G# g' Q6 A    * F2. O/ O- i9 \' Z; i! U
6 j  \% d3 j) T& V/ y5 `! {7 ~
读取Keyboard ID。由于8042芯片后不仅仅能够接Keyboard。此命令是为了读取8042后所接的设备ID。设备ID为2个字节,Keyboard ID为83ABh。当键盘收到此命令后,会首先回复一个ACK,然后,将2字节的Keyboard ID一个一个回复回去。
, c( \5 i' S( x5 T6 @/ i1 ^% O+ ~8 I7 D' g. k/ f' k
    * F3h
4 f" m$ d" l/ Z5 Y5 G
8 j. i: |- o' e) r设置Typematic Rate/Delay。当Keyboard收到此命令后,将回复一个ACK。然后等待来自于60h的设置字节。一旦收到,将回复一个ACK,然后将Keyboard Rate/Delay设置为相应的值。
* T3 N9 }" b+ k+ Z( U. F) X# k
" j- f/ W8 [2 {    * F4h# e0 E3 v: |) H$ B# h

3 U' q* R: I% ^# I: Q+ W清理键盘的Output Buffer。一旦Keyboard收到此命令,将会将Output buffer清空,然后回复一个ACK。然后继续接受Keyboard的击键。$ ^) D$ S8 g- T( @7 F! w8 N# w
8 e/ L  b1 r+ O2 q5 X+ m3 [' m
    * F5h2 H" E6 d; x1 H* K* G" [) j

" G" B* N1 r/ ~9 Y/ j# k0 H( ?设置默认状态(w/Disable)。一旦Keyboard收到此命令,将会将Keyboard完全初始化成默认状态。之前所有对它的设置都将失效——Output buffer被清空,Typematic Rate/Delay被设置成默认值。然后回复一个ACK,接着等待下一个命令。需要注意的是,这个命令被执行后,键盘的击键接受是禁止的。如果想让键盘接受击键输入,必须Enable Keyboard。
0 u8 j1 |( e" B5 ?' y* R( g# x$ S  H! |8 J  x* }6 H* `
    * F6h% J) C, i2 ?: q+ F+ L) K

9 p- u7 y  B! w" U设置默认状态。和F5命令唯一不同的是,当此命令被执行之后,键盘的击键接收是允许的。. o1 ~, k. u  ~

7 i; P4 }/ o6 c4 Q; W    * FEh" E* ?- T3 l) _3 D2 g  o
5 O( k& W8 F$ J5 w$ [( g$ V. q) c
Resend。如果Keyboard收到此命令,则必须将刚才发送到8042 Output Register中的数据重新发送一遍。当系统检测到一个来自于Keyboard的错误之后,可以使用自命令让Keyboard重新发送刚才发送的字节。) b! m, E, U% D  D/ j" W
* e5 K+ z. n+ }6 L
    * FFh( e- |* ^* {. I4 l4 v

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

使用道具 举报

发表于 2009-1-14 13:49:16 | 显示全部楼层
好贴!
; }. T* |% h* S: T非常详细!$ l  f! Y# y7 F/ k8 T% S
谢谢!
回复

使用道具 举报

发表于 2009-2-25 17:37:28 | 显示全部楼层
2楼好帖!在helppc的Hardware Data and Specifications栏里有相应的寄存器和命令详细描述。. `. s% n# n. g

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

使用道具 举报

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

本版积分规则

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

GMT+8, 2026-9-22 01:11 , Processed in 0.067315 second(s), 17 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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