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

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

[复制链接]
发表于 2008-7-14 00:04:00 | 显示全部楼层 |阅读模式
bini殇,能帮详细解释一下bios post过程中的所有发给ec的60/64命令号码和意义吗?数据量比较大,截不住。
发表于 2008-7-14 12:09:38 | 显示全部楼层
转个别人发的,不知道LZ能不能用上  
7 Z5 j" @5 j" t8 \( b) L8 s+ y, i8 t, R7 M
4.2.7 Command
  K3 b6 s1 F( c) V
% E2 S( ]6 l# j# S& H. [- r  D通过8042芯片,可以:0 p' m: [  X1 T: u! ?2 E
向8042芯片发布命令(通过64h),并通过60h读取命令的返回结果(如果有的话),或通过60h端口写入命令所需的数据(如果需要的话)。; O: w2 F$ K6 x
读取Status Register的内容(通过64h);
- [9 j. i- e" l& B. O向8048发布命令(通过60h);
7 k4 x" O4 X+ N. |' G4 q, e读取来自于Keyboard的数据(通过60h)。这些数据包括Scan Code(由按键和释放键引起的),对8048发送的命令的确认字节(ACK)及回复数据。
4 |" u5 Y: W; H- F# ]9 A# W
2 I" f9 h& w$ Q( w5 A8 K* N再次强调一遍,Command(命令)分为发送给8042芯片的命令和发送给8048的命令。它们是不相同的,并且使用的端口也是不相同的(分别为64h和60h)。
8 B- T7 _) ~, R& V, j
$ X* e- z/ K& L' N4 y3 Z9 k
' H8 V( O; O3 T6 y' f3 r
6 A( o" R5 W& C7 B2 t. m9 Q    * 64h端口(读操作)- R! ]% ]4 O  G

& y2 r' z) X) o$ \" _7 w
; w+ N, l3 I7 F& U5 }. Q对64h端口进行读操作,会读取Status Register的内容。
% s; s2 Z/ f3 L, ~$ B! W
$ S) T. Y6 X7 H5 p% _$ g" a5 J: \' Kinb %0x647 x1 c" s  Q7 |) u  Z0 Z+ T; c
执行这个指令之后,AL寄存器中存放的就是Status Register的内容。8 z) {- G" P; {' Z; M; l' V  q

( D/ r  H8 l3 V& P6 K% a& ?9 _    * 64h端口(写操作)
" N4 r# R- _' k2 e8 \$ G. }( L  U* @1 _, ?" N' f2 s+ v
向64h端口写入的字节,被认为是对8042芯片发布的命令(Command):
6 l8 S$ ~2 q3 E, T( F) HŸ, M. n0 A" Y. Y; {3 }5 v8 @
写入的字节将会被存放在Input Register中;* H& J* M& B" q) s+ Z) r; B$ Z
Ÿ
# w# ]6 G; R: Q$ l- B/ \同时会引起Status Register的Bit-3自动被设置为1,表示现在放在Input Register中的数据是一个Command,而不是一个Data;' p& X9 ], R2 ~' [) {
Ÿ0 T4 Q- w! X. r& w4 p: b6 m/ `
在向64h端口写某些命令之前必须确保键盘是被禁止的,因为这些被写入的命令的返回结果将会放到Output Register中,而键盘如果不被禁止,则也会将数据放入到Output Register中,会引起相互之间的数据覆盖;8 E2 s5 [3 N3 \  j- d" ?
Ÿ
3 T2 V" c/ u' [. Z' Y  \  J- s在向64h端口写数据之前必须确保Input Register是空的(通过判断Status Register的Bit-1是否为0)。) j! k, F7 j- ^& b0 r

9 A" Q5 P) A1 ~  z* Xvoid wait_input_empty(void); U% |/ r: n- y- P# F
{
: h4 @5 p2 I- t' d. s+ V   char __b;
! V7 x7 V6 r2 C% o. }, _
3 |/ m: E' a* B' T; C   do{
3 x) I4 E/ H9 a: q     __b = inb(0x64);' x6 N2 ?( o: O1 Z, g+ A5 x5 \9 N3 D8 a
   }while(!(__b&0x02));* v% C% n* M- G: [- G: W5 X; ~/ ~
}
5 `9 n$ \$ w! X( m! M; \
& W" T) F* H3 k' V$ d  N+ Q8 Lvoid disable_keyboard(void); p+ j+ G! K" w+ h2 ~$ Y
{' b/ S& H0 ~4 l$ y
   wait_input_empty();
3 Y; o% Q: I' J, K. |   outb(0x64, 0xAD);* q9 V+ m. D* Z+ w: W
}[size=+0]! D6 G! s" Q) E# j6 m

( l. {/ J1 P3 t  \* K+ w    * 60h端口(读操作)5 m% q! q  r3 i5 ]% J3 W

2 I& e# b& r  [2 g8 l0 m对60h端口进行读操作,将会读取Output Register的内容。Output Register的内容可能是:
( h& Z' E# u# M/ ^  h* C, C, OŸ           来自于8048的数据。这些数据包括Scan Code,对8048发送的命令的确认字节(ACK)及回复数据。- a" R  K7 P  i8 y8 F
Ÿ           通过64h端口对8042发布的命令的返回结果。
7 r! x0 `$ x, H- A9 `
% W' I  L/ s. E/ o" A' X( l在向60h端口读取数据之前必须确保Output Register中有数据(通过判断Status Register的Bit-0是否为1)。4 R: m; W- C( B0 q# `' }
void wait_output_full(void); G  J+ ]* l4 k1 X4 d; z! L
{' H- o7 c; R! l6 N) c% x% ?
   char __b;( D' K! K3 I- Y5 G
% q7 j4 Z- t( e0 Z- F( f6 e
   do{7 |( ?3 j0 J' c3 F# ^
     __b = inb(0x64);1 ?9 n+ \" r& n$ _+ p1 S" L
   }while(__b&0x01);
) @( S) |3 d0 i# }4 M: z( z}
6 k% `/ |5 }0 k* I( p
% I$ f- K& v  N7 r4 G$ F# ^: Bunsigned char read_output(void)0 k( {( K6 r& A+ P* [$ b' u
{
" U4 D8 @! t( M( q! X$ @   wait_output_full();6 ?  t0 |/ m: a; G+ ?  H( i4 R
   return inb(0x60);+ O2 ]( D4 T% c8 R3 Y
}. c% Y3 }$ }. C; O; j1 U

3 d4 x0 a' X0 }+ C: M    * 60h端口(写操作)
  t' C, l8 T! s4 d; i+ m: t; ?1 Y
  u* ~2 m! x4 y' S2 R/ F向60h端口写入的字节,有两种可能:" K. f1 g7 ~' V3 x/ H2 Y& f9 _
1.如果之前通过64h端口向8042芯片发布的命令需要进一步的数据,则此时写入的字节就被认为是数据;
+ V( u% @( X2 C6 K  w: A& n7 n2.否则,此字节被认为是发送给8048的命令。) v. k" k0 h/ z' n8 H# \' j

6 P8 M* C! b3 M, ~0 z在向60h端口写数据之前,必须确保Input Register是空的(通过判断Status Register的Bit-1是否为0)。
- O+ `8 P; t2 h) t! I' \$ Q! I  J7 }2 z1 v; }

; |9 l5 ?6 Z% G1 H3 X[size=+0]4.2.7.1 发给8042的命令! f* d) z- U7 a; Q6 y0 f9 d$ j
' x2 D1 j) t4 D& R+ Z9 G4 u# F5 b" d
    * 20h
6 d. A/ [4 z2 ]8 q& L( {
' d6 Y0 ~! z' Q准备读取8042芯片的Command Byte;其行为是将当前8042 Command Byte的内容放置于Output Register中,下一个从60H端口的读操作将会将其读取出来。
4 K9 t' V+ \' B+ u; [2 P/ U3 n1 b; U+ S

9 e" w( ?& l1 Wunsigned char read_command_byte(void)
) |+ X: X, \: B6 Y{
% f# O2 X4 Q8 [4 x) n   wait_input_empty();! G9 C& Q$ p$ B5 I4 ~5 R  V0 K$ [
   outb(0x64,0x20);
' h, d* L. c- t% u. l   wait_output_full();
" `* i# e2 j# s3 P3 B   return inb(0x60);   
+ N6 O) B$ R& e% F* H}
" q' V( t" w8 O. X" X" |, l2 z' ]/ Y* T4 N+ {4 [% }% x
    * 60h. b; i$ L# L) i5 o

' `. W2 m' v% I2 z* O* k; P3 V准备写入8042芯片的Command Byte;下一个通过60h写入的字节将会被放入Command Byte。/ |2 j$ G; E0 ^% S" Q3 T1 b# B& B
. e7 }% P8 Q, ], d5 Z

/ T: U* O) h& Y' {' l6 k0 A' g( `void write_command_byte(unsigned char command_byte)
% w) |" W8 }! X, a, O5 U* h{
+ ]' d9 `& x! O& l9 t0 d   wait_input_empty();4 [1 Z, R" O( L% x+ V2 A% U
   outb(0x64,0x60);! `; [4 n- O+ ~4 S2 m& V
   wait_input_empty();
7 ^; d* u: P, n- l   outb(0x60,command_byte);
* j. F+ ]  ?6 ?0 s) m% b}
# D  |* N0 R# C4 j. R$ v# A: H! K) [+ g) ~2 _
' R0 r# S2 G( i* O2 T3 r. j
    * A4h7 M: F- |3 D( ]% ~! Y; ]4 x

' r& R2 q( p, w" A测试一下键盘密码是否被设置;测试结果放置在Output Register,然后可以通过60h读取出来。测试结果可以有两种值:FAh=密码被设置;F1h=没有密码。
7 }; {) Q7 @) h( Fbool is_set_password(void)
1 D( i- H- |9 K6 p{
+ l; [3 D+ ]. H6 h   wait_input_empty();
/ @1 g6 A* Z1 E! y4 W4 J   outb(0x64,0xA4);( m% T! U' [' t. G$ E: ~
   wait_output_full();
: H! F$ f) g5 X! ~0 z- E- c) X   return inb(0x60)==0xFA?true:false;   
8 N3 D! o4 W5 K; u5 A* I}, s" Q2 B" y, u" o2 T

* r! Y, D4 B8 `1 W- K    * A5h: q. a/ ~$ ?' J6 M9 p3 {* T0 W

: ~5 l% a, I- e, R7 l; y# i设置键盘密码。其结果被按照顺序通过60h端口一个一个被放置在Input Register中。密码的最后是一个空字节(内容为0)。# U8 w4 G6 ~  G! L
void set_password(unsigned char* password): F3 I. T2 x- t% p
{
% |$ p/ b* E; U- ?) }   char* p = password;7 Q2 P- b& q# }& k

2 j9 X/ O( |; v6 y5 L   if(p == NULL)+ x9 B6 ~+ y: z
      return;5 ^0 L2 |2 l4 s  P3 g# z
$ I7 ?& B! Q7 U6 I8 C
   wait_input_empty();
$ }6 B9 Z) R* X6 x   outb(0x64,0xA5);0 x9 c/ l& i, M/ c

, l" }# b3 T  F9 |9 T7 P   do{; d5 _4 i4 W5 N. p
      wait_input_empty();
% \$ q: b3 U2 k4 m  r      outb(0x60, *p);
7 I7 [- Z: }' p8 E$ ~) r   }while(*p++ != 0);  p! Z+ n/ u! ^$ I  r
}( V5 ?7 L) H+ W/ L# E: t

1 A$ o0 B; H+ A3 c/ h+ ^    * A6h
) k) s! T# K" c+ j" b. l8 }- t! ^6 J: K+ v* n1 J: I0 U. d
让密码生效。在发布这个命令之前,必须首先使用A5h命令设置密码。
+ o" R& N4 T; J# S1 E5 ^$ Fvoid enable_password(void)
* K: C4 c% h! U' S$ m$ H{
- _1 ^& K* ]) s- R   if(!is_set_password())! O7 v$ ^* _/ K3 P" Q+ m2 P9 \$ t1 t5 m
      return;! ~0 ~% l) a5 }

/ {% R, Z6 O' Q   wait_input_empty();6 i; ]) r0 ?. G# J* B! O. z
   outb(0x64,0xA6);   . W9 U) C( c5 l
}
$ t( R8 C% f* q$ n; Y( \# A" a* {4 k$ N# W
    * AAh
  L1 n1 M  [2 J
5 ^' [2 t% U$ I2 q" f+ a4 r; ?自检。诊断结果放置在Output Register中,可以通过60h读取。55h=OK。
+ o. v! h7 \! E0 B  I7 t% A1 h" C& v
  ~$ v) K; b* g" {4 }% B; ?$ P
bool is_test_ok(void)
: J! R, R- r$ ]. F3 K2 x{
- k% b2 n. W( H. x3 T3 {% P   wait_input_empty();7 l, M! e. u) ~7 j7 T
   outb(0x64,0xAA);: I% }# m9 u: @4 L( P+ g' W

" c3 g3 G! c2 g; O5 L& V* C
% J& r2 ]) B1 E3 I  e   wait_output_full();
; C, Y5 m, A8 X* g' t1 h6 o( v3 o  c   return inb(0x60)==0x55?true:false;   
+ O! a& R  G3 t1 [}
6 n" @9 C$ l4 C8 p4 R( V% Y0 d5 y( t5 \- S% {

5 l% \) x. k( ^4 w, R% s7 Y    * ADh" r) A- M! x9 E% m0 ~( e

9 N. }2 H6 P; i; P. d禁止键盘接口。Command Byte的bit-4被设置。当此命令被发布后,Keyboard将被禁止发送数据到Output Register。
9 H$ K  C* p0 @6 p6 _void disable_keyboard(void)+ @" s0 |& O! f/ P8 @1 F
{8 I- V  l% B, }" b6 I% z
   wait_input_empty();& z. U* u) L  _7 c
   outb(0x64,0xAD);4 O: O; \; D1 A* `
. n5 |0 M& p& a3 o- Y, ~# z7 Q
}
: X! l' Y3 T8 E# ?. s: }
$ Z6 T. n& h+ _0 q0 _    * AEh/ u' K8 E+ D0 k9 L$ L% B& d8 l
+ D4 }) [( F  k9 M3 I
打开键盘接口。Command Byte的bit-4被清除。当此命令被发布后,Keyboard将被允许发送数据到Output Register。
' _9 P+ v; P! ^0 y+ y  |void enable_keyboard(void), T* N# d, x' S6 q8 a, W- D
{
1 D* t  V* `1 W: T   wait_input_empty();
* |/ {: D$ f( s& P   outb(0x64,0xAE);! b$ C# }1 q. Z% R) F4 ~, P
% {3 k) q/ u* l. o0 {3 h
}$ }2 t  e$ N, W9 T; ]
% |& L3 |1 I: A9 X
    * C0h
/ K4 |- Q+ j: L+ J
# {# r2 U7 t# R# {! p; U" W2 q准备读取Input Port。Input Port的内容被放置于Output Register中,随后可以通过60h端口读取。; m# u2 M7 b. l
unsigned char read_input_port(void)
& o7 e7 e+ A1 k$ E* C6 i) T% C2 b  A{# U& o6 P% `$ s
   wait_input_empty();5 I2 k' _) C- D6 M1 J- b
   outb(0x64,0xC0);
8 z! a- E' d6 S, M, O5 e+ Q( C8 E
   wait_output_full();) h4 h4 T0 f' K# B5 V

& R- r* [+ ?) K2 U/ r   return inb(0x60);4 l" K$ y+ V  n( j" k4 P
}
! Y" @, c6 C. [+ o6 m% Q' m/ e8 b- Q1 W9 o6 w% I
    * D0h
, n5 s# L1 N7 x* M
+ D/ s9 G) S) Y2 i7 ]2 ^4 Z准备读取Outport端口。结果被放在Output Register中,随后通过60h端口读取出来。8 v: L" k2 T- D% n$ a7 U1 I# a
unsigned char read_output_port(void)
; Q1 K/ y1 O0 Y  l: J2 d4 `{/ M4 [  O2 z# T) W1 ~. Q
   wait_input_empty();! \( ^9 B7 c% N' o3 ~- I1 `& K* u
   outb(0x64,0xD0);
) N" S/ g6 E" C2 a# ^) t& X6 g: N1 X/ w( P* R+ {
   wait_output_full();
3 m; w5 }) r: v0 w+ ]( [! T" V% n% G" n% R1 z0 F; ?6 Y
   return inb(0x60);, ]& t2 ?) r9 Z% S) F# l
}
( L' _( }1 s% l$ U' D4 K, T0 W5 |. E- a8 L) ~
    * D1h" B5 {" n2 t5 C$ }1 k9 _0 a
& J2 n) L% b/ ^1 e" a1 G' ]0 \
准备写Output端口。随后通过60h端口写入的字节,会被放置在Output Port中。# a# r1 a8 d# |3 S1 y  V" o% g
void write_output_port(unsigned char __c)
: |1 j, `: T+ _* m/ }{3 a5 h5 y; m+ b+ C4 B
   wait_input_empty();4 O6 q( M5 l# g9 g
   outb(0x64,0xD1);( Y4 ^0 }$ H3 v  K0 n
. k' q, _2 I4 `  ?9 ?
   wait_input_empty();! ^: H2 `2 z; l8 g. ?
   outb(0x60,__c);
/ @. v" Q. Y7 g0 ]3 w, A' d% _& |  x. T" K) o" o
}
/ e8 |% S' P8 B; |
/ Q8 W. q3 b6 Z% l- f% F& n/ c+ U5 s  @4 M
    * D2h
9 u& r$ M" X0 G9 U8 k! _# U9 |/ e0 q, E; y2 E2 E
准备写数据到Output Register中。随后通过60h写入到Input Register的字节会被放入到Output Register中,此功能被用来模拟来自于Keyboard发送的数据。如果中断被允许,则会触发一个中断。. P, X+ P# S) u: d( J" r* U$ V/ t
void put_data_to_output_register(unsigned char __data)
  \! `9 c, i6 f% M{3 w9 G. q$ F+ f' b/ X3 e
   wait_input_empty();
/ v1 {* {+ {$ _7 t1 q7 G   outb(0x64,0xD2);5 Y5 m; E7 U! R* A2 D6 T
: v0 R2 H9 M4 \9 L; f' S" a
   wait_input_empty();  m+ A$ O# ?# Y
   outb(0x60,__c);' C8 i1 x' k, G
}2 \# S9 A+ Y1 s* V7 R

! W+ j& a  n  Y) ^6 H1 }4.2.7.2 发给8048的命令
7 U- z' Y( t- {% v. v1 b" ^; N
# ?( m. W4 U* s- q  @* Y% p
; {  I5 l1 J- {3 q% w" G, Z! g$ ]    * EDh0 u( [8 I& ~9 z, I+ H
" r4 |$ D% f( h* }0 p& [# J
设置LED。Keyboard收到此命令后,一个LED设置会话开始。Keyboard首先回复一个ACK(FAh),然后等待从60h端口写入的LED设置字节,如果等到一个,则再次回复一个ACK,然后根据此字节设置LED。然后接着等待。。。直到等到一个非LED设置字节(高位被设置),此时LED设置会话结束。
8 m! F  w5 W; V6 E7 `% a6 o5 M# o0 s0 Z+ A# c
    * EEh( U8 E9 C9 s# w, R$ O4 {" Q6 w

: ^0 k2 G+ u$ ^! T3 [2 f& I$ \诊断Echo。此命令纯粹为了检测Keyboard是否正常,如果正常,当Keyboard收到此命令后,将会回复一个EEh字节。. q5 a5 U$ G7 x
" _- U0 H7 F, p& c
    * F0h
* B' Q; e& l$ O3 s* k7 u# c1 T' m- s
选择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代码所要求的。- m* U- j/ q( E' _' O8 ^% D

+ `' {! E; e0 t+ X. V- M, c- D    * F27 |; O7 y7 ~) ?: x( E
" w2 ^2 i( M- }4 b  W8 X$ T% k8 d
读取Keyboard ID。由于8042芯片后不仅仅能够接Keyboard。此命令是为了读取8042后所接的设备ID。设备ID为2个字节,Keyboard ID为83ABh。当键盘收到此命令后,会首先回复一个ACK,然后,将2字节的Keyboard ID一个一个回复回去。
& ?8 ]' D! B3 ^" ^8 V
8 m4 A9 C& T2 h4 P- D    * F3h4 ]( p+ z! d8 A
& W8 p7 i3 g7 j9 ^: X" v
设置Typematic Rate/Delay。当Keyboard收到此命令后,将回复一个ACK。然后等待来自于60h的设置字节。一旦收到,将回复一个ACK,然后将Keyboard Rate/Delay设置为相应的值。
5 l% l1 n) r3 ^) g/ [& U3 B
* {: U& v. b+ i! y9 Q    * F4h+ P5 h* E& Z  B: I4 u
& l! ^6 K4 V. a1 M* ~# D  p. G- y
清理键盘的Output Buffer。一旦Keyboard收到此命令,将会将Output buffer清空,然后回复一个ACK。然后继续接受Keyboard的击键。
1 ^% D* L4 |6 F
8 \5 Y$ k5 _$ M# w/ h. @' z    * F5h
. @- D7 ?& r$ z$ |1 g: x5 }# M
设置默认状态(w/Disable)。一旦Keyboard收到此命令,将会将Keyboard完全初始化成默认状态。之前所有对它的设置都将失效——Output buffer被清空,Typematic Rate/Delay被设置成默认值。然后回复一个ACK,接着等待下一个命令。需要注意的是,这个命令被执行后,键盘的击键接受是禁止的。如果想让键盘接受击键输入,必须Enable Keyboard。
$ N/ s  {3 Y8 y4 L8 k0 I
$ ^8 j9 r. \: k4 X% K) g7 n& w    * F6h
; }! w7 G- |- w, x+ n3 N9 k. p8 |, f& O9 b2 D' J! N5 g4 d* l
设置默认状态。和F5命令唯一不同的是,当此命令被执行之后,键盘的击键接收是允许的。
( _. \$ }/ f" z; {0 p1 \4 |9 c
4 J5 A: [" j. ]" c8 f. S    * FEh3 d) X' \& ?, _3 e% I

8 r7 S; k( n* ~Resend。如果Keyboard收到此命令,则必须将刚才发送到8042 Output Register中的数据重新发送一遍。当系统检测到一个来自于Keyboard的错误之后,可以使用自命令让Keyboard重新发送刚才发送的字节。, d) U( Q, E9 K, m) s3 v. }
: P1 d. L6 y- h3 a/ l
    * FFh
5 }# t7 c: P  }7 ^( }$ g' [; }, M; i2 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 a( a- E( _' _2 Q& ]非常详细!
: O, n1 e9 y6 ~0 h2 Z- k& E8 O谢谢!
回复

使用道具 举报

发表于 2009-2-25 17:37:28 | 显示全部楼层
2楼好帖!在helppc的Hardware Data and Specifications栏里有相应的寄存器和命令详细描述。$ B2 x: X. g9 x- m

9 k+ T  G/ G6 [) x: ]我的问题是,上述描述应该是针对老的8042的,在目前的使用EC的系统中,这些status register和command描述在哪个文档中可以找到?比如intel的santarosa,使用renessas的H8s 2104 EC,按道理上述状态寄存器,命令等的描述应该在2104 datasheet里,但是我怎么找都没有。还是有某个spec定义了这些命令格式?新手问题,高手莫笑
回复

使用道具 举报

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

本版积分规则

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

GMT+8, 2026-1-12 05:29 , Processed in 0.309469 second(s), 16 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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