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

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

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

6 C. _, S2 @2 {+ E- E! p4.2.7 Command8 P5 r) s4 y6 h' f4 ?6 I. N3 {- r0 p9 {

! B4 H) o: v( S3 B3 T( j通过8042芯片,可以:% g' z0 G9 t3 T. P# u3 v9 M8 L/ b
向8042芯片发布命令(通过64h),并通过60h读取命令的返回结果(如果有的话),或通过60h端口写入命令所需的数据(如果需要的话)。
/ x6 S: i8 \7 z读取Status Register的内容(通过64h);
. ^: U7 T1 h2 V5 R3 V向8048发布命令(通过60h);' P' C4 i! L3 @. i7 q/ \
读取来自于Keyboard的数据(通过60h)。这些数据包括Scan Code(由按键和释放键引起的),对8048发送的命令的确认字节(ACK)及回复数据。
- _2 [; g3 @2 T: O; {' O
3 o* X4 B$ T  M2 k; H再次强调一遍,Command(命令)分为发送给8042芯片的命令和发送给8048的命令。它们是不相同的,并且使用的端口也是不相同的(分别为64h和60h)。  {% a8 [( n- N1 m# K& ^0 H4 v0 z+ [  z

& Y0 z. j/ }- i7 Q& ]4 q, f
7 d, A# [& ~. [4 m# F/ B- ^6 P( h* M& C
    * 64h端口(读操作). L9 Y% I5 ~& ]  v& e

* I7 Q+ q0 l% P7 @' K+ ~; ~# D) z
2 i5 M! _0 X3 z+ x' w对64h端口进行读操作,会读取Status Register的内容。
+ \  l4 R: ~5 V  S- z0 y$ @2 R
6 y8 _  W  K3 y+ Hinb %0x64
, B  Y( h! }* A- K4 X9 x执行这个指令之后,AL寄存器中存放的就是Status Register的内容。- S7 j, `7 a! K( O2 f& ?1 [
% n/ W0 o5 r8 A2 E/ Z7 a/ ~
    * 64h端口(写操作)5 z$ a0 d& ?0 L' X0 K

, q8 r- C- n+ S向64h端口写入的字节,被认为是对8042芯片发布的命令(Command):
1 |8 @' `& I/ i/ l: k( WŸ
" L- c: u1 O, R5 \1 ^4 A# X3 V写入的字节将会被存放在Input Register中;: m3 j8 P, I: J3 j% c2 _8 j
Ÿ
( Y4 U- W6 ^' f( s% }) A同时会引起Status Register的Bit-3自动被设置为1,表示现在放在Input Register中的数据是一个Command,而不是一个Data;
# R' n* r/ b  x9 Z3 a+ h- ZŸ1 }/ B' Z' s" r7 L/ q
在向64h端口写某些命令之前必须确保键盘是被禁止的,因为这些被写入的命令的返回结果将会放到Output Register中,而键盘如果不被禁止,则也会将数据放入到Output Register中,会引起相互之间的数据覆盖;4 B/ L2 F$ G$ h- T
Ÿ
- W+ [. B0 e0 Z! A" I0 a- L3 y在向64h端口写数据之前必须确保Input Register是空的(通过判断Status Register的Bit-1是否为0)。
9 B; ]4 n4 h- K& S7 ]2 U9 W4 q3 n6 Z$ {( H
void wait_input_empty(void): Q. M4 v. C( d! l7 L: j% a
{
; I+ T4 K- g. ?; V   char __b;; g0 \$ B7 n2 ]7 e, l, ~$ R

3 w4 A8 L# S! s  I4 i7 x) v   do{
# V& P. p" X) ~% p! v     __b = inb(0x64);
7 B2 x" c0 E* \   }while(!(__b&0x02));5 |- ~  ^/ p( z
}
) Y( _# _& v+ F; @5 Z; x) R5 c' U  _" f8 z; p9 ]; I, a! A
void disable_keyboard(void)
6 [" g9 G; C" `7 ~{/ y: r& {2 A. K6 X4 f) B& ]) ?- ?
   wait_input_empty();( r9 z: X4 z! z3 D' L/ p0 E  w: v
   outb(0x64, 0xAD);
4 h8 c7 j2 j5 W: I7 p0 I}[size=+0]+ O" w. ^4 u1 o! w
& {* D: d9 W$ `+ Z3 m
    * 60h端口(读操作)" I% y! Q5 M- P& C

! n3 S: Z. C8 b0 C" O* g对60h端口进行读操作,将会读取Output Register的内容。Output Register的内容可能是:& E! F, Q  Z$ V
Ÿ           来自于8048的数据。这些数据包括Scan Code,对8048发送的命令的确认字节(ACK)及回复数据。$ K+ L5 ~  J  T; v6 `2 s
Ÿ           通过64h端口对8042发布的命令的返回结果。9 P7 j1 L2 e; x0 g  G

, n. c; y9 ~2 Q2 V8 e在向60h端口读取数据之前必须确保Output Register中有数据(通过判断Status Register的Bit-0是否为1)。
% N( p4 c1 t( `! o1 Q9 _void wait_output_full(void)1 k3 V6 D9 q* z9 R
{9 c; X8 ?8 {8 v. n3 ^
   char __b;
* n  z' r: t4 j' I% G" ^& ~' S
   do{
: s% D5 e( _& ?0 T  \& c( o     __b = inb(0x64);
6 d; V- y7 c; N6 O7 o" b  O   }while(__b&0x01);5 t* r. I# n. O
}
& Y$ `2 d, T% L/ h  G/ H9 `# R# }' R5 ^# }! S5 ~) j
unsigned char read_output(void)% t9 w* u6 ?# ~4 X8 \) A' i, z  g
{
+ G1 M5 g3 M/ r$ f   wait_output_full();
+ k( H  k8 L1 ~# W, m: t6 Q   return inb(0x60);
/ n, H! U; \1 E2 \/ [}
( k$ a; L6 x) v9 s+ i# s" g# @" s: B
    * 60h端口(写操作)5 u: J1 c) ]# i1 M% G" A
% J7 o9 X0 F7 @$ q9 o
向60h端口写入的字节,有两种可能:6 A$ S& V/ F4 S# u7 R
1.如果之前通过64h端口向8042芯片发布的命令需要进一步的数据,则此时写入的字节就被认为是数据;) s. y  D  u* J0 m! m4 P) W
2.否则,此字节被认为是发送给8048的命令。/ T+ X8 n" ^4 M$ p# M
* ^) c9 C+ ?' q, D' Y" `# K! K
在向60h端口写数据之前,必须确保Input Register是空的(通过判断Status Register的Bit-1是否为0)。6 o& n+ T) w1 P* c

( i: H# |- V1 `$ l
% @( Z6 ?  B! ~# J9 m4 W! k. ~[size=+0]4.2.7.1 发给8042的命令% \' Z3 P( L: B4 R& B( z! \% B: o

9 Y) M7 p% D, |( B+ A; L    * 20h
9 Z! L2 H' O) l6 G9 Z+ ?9 ^; c4 H, h/ b' z% @
准备读取8042芯片的Command Byte;其行为是将当前8042 Command Byte的内容放置于Output Register中,下一个从60H端口的读操作将会将其读取出来。
; d  u: V( T  s& v" e, p. k' }! ?

, O- _3 [% E$ m  [8 Q  l) u  q: xunsigned char read_command_byte(void)2 ^$ |  v. Z4 ~  A  Y! |3 F
{, i' C+ |6 ]- d" r$ m
   wait_input_empty();
5 X2 A/ I  F3 q- j7 v8 V; c   outb(0x64,0x20);
0 d( k0 u" g& u* A   wait_output_full();7 N# [* U- n: d( Y
   return inb(0x60);   / C- ~% N, f; L0 X8 X; I4 h- ^8 W
}0 V& t$ D; b+ w( Q7 I
3 H; ^0 R' ]3 a" W- V1 a5 C
    * 60h
, I* u* l( R& P5 |" L. T0 ?
( M8 H2 \8 R" J+ Q0 H. G2 ]6 Q# k准备写入8042芯片的Command Byte;下一个通过60h写入的字节将会被放入Command Byte。" o7 M' ?+ e$ U- q- s) M& j" ~# L' ?% d
$ Q, x. b- }( a4 N- r. w

' b  p0 s) X4 \2 ~1 n; B+ n- w) jvoid write_command_byte(unsigned char command_byte): o! ~& _% l  }- k2 ~! r
{9 s5 x2 k3 ~3 A7 O' h
   wait_input_empty();
3 F9 T3 i, M2 `5 U" x: X  ~   outb(0x64,0x60);
  |0 u( ]5 y, P8 U: d+ S   wait_input_empty();
# _" H5 ^. d) }   outb(0x60,command_byte);! k/ R! s' G/ V+ @
}7 M. O+ F% W: s, [4 P* |# x
& ?' u2 K9 O* @) k" R# E: U

8 ~5 |) b" Q" m8 Z/ r. @    * A4h6 [; x7 O" ~, S3 ?/ ?

1 m3 }: J/ L2 V; B6 p! F测试一下键盘密码是否被设置;测试结果放置在Output Register,然后可以通过60h读取出来。测试结果可以有两种值:FAh=密码被设置;F1h=没有密码。
: F9 u. D/ o4 s  Z# ~6 K& Mbool is_set_password(void)
' t+ {) q. {2 y2 P1 J{
" T* e0 _* F8 V+ z) @- Q( Y   wait_input_empty();
) m. e& O) f+ {# k0 D& Z, M   outb(0x64,0xA4);
1 }0 u" @7 m7 z0 J  g   wait_output_full();  P9 r5 e) J* z6 y! d5 l; E7 D
   return inb(0x60)==0xFA?true:false;   
& i& N) W& ~7 T+ l/ A. Z}
* h8 h6 Q% B4 A$ t+ r# D' g' [
; ?. S6 _6 A# d6 c    * A5h7 {+ X% t' i& A3 L/ w
9 y" Z+ t2 ?# N" w& ~
设置键盘密码。其结果被按照顺序通过60h端口一个一个被放置在Input Register中。密码的最后是一个空字节(内容为0)。
2 _/ m2 [) @/ B# l( h/ ]void set_password(unsigned char* password); m! `+ _, ?8 L9 J1 |
{
7 f2 {. j, Y) b# Q   char* p = password;
1 c8 z1 {; M) C# Y, t- O! M; W$ x- B
   if(p == NULL)$ P3 C8 t7 b; r6 ^# d
      return;
! w8 I8 Y% }% W$ \* W, M  m" h
" e- M5 m8 c9 q1 w$ a5 g8 ^0 p9 _   wait_input_empty();
- d1 D  Y4 ?- w, ^   outb(0x64,0xA5);- q" v2 I3 h+ x3 Q  S
- B1 W# l: k* v8 M
   do{
+ b6 H* k" c; |% [3 W8 M6 [      wait_input_empty();/ g2 {/ B/ ?; M& `" J* W  `/ L
      outb(0x60, *p);
* U& `, _) h: @+ H   }while(*p++ != 0);
* L# [8 [4 ^! z}
5 ]8 s4 T* I7 n( x) f0 g# {% w7 w
, L4 e; w7 l% g2 u6 b    * A6h
: D/ ^5 {! ~/ v8 {* T
* U$ Z2 t3 |$ V" V9 L5 ~让密码生效。在发布这个命令之前,必须首先使用A5h命令设置密码。
+ I, @9 h5 t  f2 w8 vvoid enable_password(void)
2 y( v% l* {3 Z5 q9 ?{" h7 K- L5 N8 A/ n, ?+ A" L
   if(!is_set_password()): d- M: i- J3 T7 G% G7 m
      return;
/ c6 Y8 W7 U. @4 h% R3 |  C/ h
6 X" r6 ]" V: [% z* q7 J   wait_input_empty();
+ H: j$ @- \3 s8 w2 H* s8 j0 J   outb(0x64,0xA6);   
8 k$ P& E1 j9 @$ |! @% u}
& ?! d  g' p$ S( e/ _" k
3 t- e( k5 i" R/ W( v    * AAh
( b7 h: L7 Y2 W5 k. i0 ^& B& L; l/ w# m3 O2 K7 T. H6 e! G$ N
自检。诊断结果放置在Output Register中,可以通过60h读取。55h=OK。
6 ]: z0 _- k# x% \9 j& v* l
& B+ G- f& g" J  T; n4 K& [8 v, _3 M! k& e! [/ j* u
bool is_test_ok(void)- E: R8 \6 V$ C+ a8 b6 N
{# _# m7 Q: o6 H1 b
   wait_input_empty();
# Y( G# G- b3 A   outb(0x64,0xAA);0 H. Q, U0 Y9 s' Y
: T7 E8 [( {% b1 |3 [
, I( c4 `. i" ~
   wait_output_full();
- B4 N& U- M- M" W4 V2 q& a   return inb(0x60)==0x55?true:false;   
" {' n$ F) r- @}- p" ^8 \5 }; q1 i. F% `, g
, f3 v2 C! ^/ u7 k! s
! u- `8 d9 u- C9 `$ A
    * ADh
5 |$ k5 b3 R  G8 [2 G  U! v! b* `+ `
. H; K" B, d' B; f! u2 `  t禁止键盘接口。Command Byte的bit-4被设置。当此命令被发布后,Keyboard将被禁止发送数据到Output Register。6 U0 t( a) p% w$ C' V& @1 k) W
void disable_keyboard(void)
: P3 e! H/ E; W, ^( b) Q1 K9 g: _0 o{* G: T) D; X+ [2 t" m
   wait_input_empty();" @& _! s# [8 m! D# r: u) g& u
   outb(0x64,0xAD);6 t- l! S% @1 S3 O

# t9 r% Y& K, q( h& |) L& a}/ L) F; W$ C8 z; }+ k: P% {

, s4 b  O- X5 o' z. ^; ]; @    * AEh
* a9 \& j; Z& H$ g: H% t8 U' d6 z& h3 G. S; E
打开键盘接口。Command Byte的bit-4被清除。当此命令被发布后,Keyboard将被允许发送数据到Output Register。
; j1 ]" `, j6 |. y- ^# \1 zvoid enable_keyboard(void)
/ t2 @3 `  t6 [; z/ K' o( X1 R{! _2 r3 Y  |! `( d! n- k, A
   wait_input_empty();% z, g7 R, A8 x6 K
   outb(0x64,0xAE);! V5 C' h0 }2 _! u& T  i( C3 ~  Q
9 ~- H1 y8 l5 `& [/ ^# g1 e0 Q
}9 t8 r& }- v+ }6 \5 b
# K# O, O! H% C0 \" |
    * C0h
1 |: q* s0 z9 M$ T; x! ^% c$ r  i3 O: k) X- L$ c6 l
准备读取Input Port。Input Port的内容被放置于Output Register中,随后可以通过60h端口读取。
' Y  d! a5 [1 C" N/ n5 {unsigned char read_input_port(void)5 H8 c! Q7 K/ F2 o4 y0 e: E9 f& s' G
{2 s$ s5 S$ T2 q4 v4 N6 }+ u- x
   wait_input_empty();+ I2 l+ D( w  [6 K
   outb(0x64,0xC0);
% J" K" m- l0 h! c
( B+ D3 L+ n: i; R$ v9 t8 Z  o   wait_output_full();, W6 K6 G$ j4 i  O. n2 _

, |8 |/ R" y; D( x  G   return inb(0x60);
' z- J/ G+ a/ Q+ Z}) D" Z3 T1 o7 ^" L! d

, i2 Z) S$ M$ O0 E1 N$ H    * D0h
# T) b* }1 _! D6 ?" q1 e/ P' {  D1 }! R
准备读取Outport端口。结果被放在Output Register中,随后通过60h端口读取出来。! v- T' G4 R2 G0 A3 }
unsigned char read_output_port(void)
$ Q# |% I5 d* r; b4 j. \7 b' k5 q{
5 x  ?3 V$ O) E( W$ J' e   wait_input_empty();& Z8 W$ ?6 z( Z( w
   outb(0x64,0xD0);  i8 H5 q  a* r2 T* P( z/ H

  P5 d' h* B3 e" M" y, Z8 F: m   wait_output_full();; {# P" z3 g: O* H& b7 k

8 J9 u1 d" v2 y8 R4 A8 }  K9 T   return inb(0x60);
* G; X; K: e" g/ ]4 Y}! q# s/ T" j. z- W: w$ p

7 W7 `2 I+ Q5 Z! j! E3 Z    * D1h' A$ b" H+ |9 }2 O

4 u$ w) I4 }5 s准备写Output端口。随后通过60h端口写入的字节,会被放置在Output Port中。" d8 M6 F% K5 Z) _3 r, l) c5 G
void write_output_port(unsigned char __c)
6 g1 b2 z" }; i. f/ m: y; k{
3 o  M5 c3 L5 T8 b   wait_input_empty();3 ?+ z9 Q9 c7 A0 |7 j2 N
   outb(0x64,0xD1);4 R$ u+ C+ \& x! R9 D
& V$ b, G. F! w4 \7 h6 B
   wait_input_empty();
$ G" b5 u* W7 f" C, C' x8 Z   outb(0x60,__c);
8 q8 d. a2 k0 ]2 S3 u0 Q4 b2 ~+ y" g9 R+ X0 P
}
0 D& _& i$ W5 u- [1 G+ O  R( Q% \2 X( N
- g1 \1 q0 }2 c7 p/ P% `- \& ^
    * D2h! A  j: t+ g$ }5 ]" P2 D

2 s5 G# G% d, E准备写数据到Output Register中。随后通过60h写入到Input Register的字节会被放入到Output Register中,此功能被用来模拟来自于Keyboard发送的数据。如果中断被允许,则会触发一个中断。
; f$ w! K2 i1 q. Jvoid put_data_to_output_register(unsigned char __data)* A8 ~% d- j) U* R
{$ k+ W% O: E' ]1 O
   wait_input_empty();6 X$ G2 p+ ^0 u7 I. n
   outb(0x64,0xD2);$ I( _. T  x9 y4 F, `
; R( t$ ~+ G# m  v
   wait_input_empty();/ }  }, k; R: N5 f# m5 b2 p
   outb(0x60,__c);6 d1 i# _5 d/ A' C" q! y
}$ }; O3 I) }$ v, n

3 L; p& i8 T3 H5 R% z4.2.7.2 发给8048的命令; n+ l. s  ^$ n

+ W- w. u; p3 h# `
5 ^6 u/ ]! L. L. ~' V- J9 ]    * EDh7 N) Y- i/ k8 A  @; l2 f! \1 q5 ?

; G7 F& z$ R: |' m设置LED。Keyboard收到此命令后,一个LED设置会话开始。Keyboard首先回复一个ACK(FAh),然后等待从60h端口写入的LED设置字节,如果等到一个,则再次回复一个ACK,然后根据此字节设置LED。然后接着等待。。。直到等到一个非LED设置字节(高位被设置),此时LED设置会话结束。
4 e8 G8 I, K+ z) ?1 ?7 l; H! N
! D" C' \; h$ X5 K' O    * EEh- K" d. `/ W9 {8 t9 Y

; F1 N3 u8 ^: U" o, `* K, }( V( n3 B诊断Echo。此命令纯粹为了检测Keyboard是否正常,如果正常,当Keyboard收到此命令后,将会回复一个EEh字节。2 W9 k$ Y. @. E! G) v
$ r, k8 j% B% i# g
    * F0h* S5 D1 A* }. T# K8 I( S7 z1 i: y

9 O& r' U3 t# E% _# B+ 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代码所要求的。
9 @- x' q# T' W2 Q' @$ C4 ]
; }8 s% k# `0 j, [" e+ D" b    * F2
+ I3 m8 d8 }  C0 P6 o) Z; Q
8 C9 o' q+ m! q) F$ ^$ o2 O读取Keyboard ID。由于8042芯片后不仅仅能够接Keyboard。此命令是为了读取8042后所接的设备ID。设备ID为2个字节,Keyboard ID为83ABh。当键盘收到此命令后,会首先回复一个ACK,然后,将2字节的Keyboard ID一个一个回复回去。* i$ I6 H9 ]6 r4 B4 |. ~

0 j: M1 ~# v. i    * F3h8 ^/ h' g/ W* [0 R, C6 F

  A7 Q* o3 |5 K; J, f设置Typematic Rate/Delay。当Keyboard收到此命令后,将回复一个ACK。然后等待来自于60h的设置字节。一旦收到,将回复一个ACK,然后将Keyboard Rate/Delay设置为相应的值。8 \( L, B5 _1 c& d

1 @0 J+ u# l  b  a" N+ n    * F4h, k6 s; }* w9 g

& ^- F- r: U( T$ x5 f清理键盘的Output Buffer。一旦Keyboard收到此命令,将会将Output buffer清空,然后回复一个ACK。然后继续接受Keyboard的击键。$ T$ \% N& ^" d/ b% I0 G- _
9 x3 _" _' s1 F2 ^- y7 w
    * F5h5 }: L  _4 ]% u; x& }7 U

( I) ^$ L' a' [6 D' b3 w7 A& T设置默认状态(w/Disable)。一旦Keyboard收到此命令,将会将Keyboard完全初始化成默认状态。之前所有对它的设置都将失效——Output buffer被清空,Typematic Rate/Delay被设置成默认值。然后回复一个ACK,接着等待下一个命令。需要注意的是,这个命令被执行后,键盘的击键接受是禁止的。如果想让键盘接受击键输入,必须Enable Keyboard。- X" z9 A% p: y" H8 Q

4 ^4 o3 \5 r" l4 S+ F9 N) T    * F6h
/ X+ q' W- ^) |1 ?6 d+ L* `. \$ J, Y
设置默认状态。和F5命令唯一不同的是,当此命令被执行之后,键盘的击键接收是允许的。
- `3 x8 L) p8 S
8 v% C5 W0 l4 Y5 ?* J8 J    * FEh
( w4 I( n3 ~4 A4 ?
  ^: m. X4 S+ l% q- IResend。如果Keyboard收到此命令,则必须将刚才发送到8042 Output Register中的数据重新发送一遍。当系统检测到一个来自于Keyboard的错误之后,可以使用自命令让Keyboard重新发送刚才发送的字节。+ r" \% }9 h: H  \# I8 s. r4 l. T
5 o, K6 O, g, Z6 \: f( z: o5 o/ S
    * FFh
  S: L6 u4 ~. P- n& ^  _4 r: M% r+ u6 ?6 Y4 J: Y3 O
Reset Keyboard。如果Keyboard收到此命令,则首先回复一个ACK,然后启动自身的Reset程序,并进行自身基本正确性检测(BAT-Basic Assurance Test)。等这一切结束之后,将返回给系统一个单字节的结束码(AAh=Success, FCh=Failed),并将键盘的Scan code set设置为2。
回复

使用道具 举报

发表于 2009-1-14 13:49:16 | 显示全部楼层
好贴!0 ^1 S9 N! ?- ~' n+ A; g
非常详细!
. Q6 _, l) A3 h0 T谢谢!
回复

使用道具 举报

发表于 2009-2-25 17:37:28 | 显示全部楼层
2楼好帖!在helppc的Hardware Data and Specifications栏里有相应的寄存器和命令详细描述。6 g$ h1 e; F1 T, m

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

使用道具 举报

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

本版积分规则

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

GMT+8, 2025-5-2 05:54 , Processed in 0.033017 second(s), 16 queries .

Powered by Discuz! X3.5

© 2001-2023 Discuz! Team.

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