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

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

[复制链接]
发表于 2008-7-14 00:04:00 | 显示全部楼层 |阅读模式
bini殇,能帮详细解释一下bios post过程中的所有发给ec的60/64命令号码和意义吗?数据量比较大,截不住。
发表于 2008-7-14 12:09:38 | 显示全部楼层
转个别人发的,不知道LZ能不能用上  
4 T: A9 Z8 N, n9 r" I& @
9 c5 @$ c" s5 \4.2.7 Command+ e$ \2 V$ R9 A9 W, q) W6 E
* ]0 t) r5 W) @
通过8042芯片,可以:
" m% f: Q/ L7 V' d& `1 S向8042芯片发布命令(通过64h),并通过60h读取命令的返回结果(如果有的话),或通过60h端口写入命令所需的数据(如果需要的话)。. D" R; x/ ^# R
读取Status Register的内容(通过64h);
; Q# s( x, G! L+ R% z4 U, K  m向8048发布命令(通过60h);
9 v0 W4 \( R! s. e& |读取来自于Keyboard的数据(通过60h)。这些数据包括Scan Code(由按键和释放键引起的),对8048发送的命令的确认字节(ACK)及回复数据。
! ^, ~1 b  Z( [+ j
# d  M, ~8 p1 _5 i2 q0 o* _再次强调一遍,Command(命令)分为发送给8042芯片的命令和发送给8048的命令。它们是不相同的,并且使用的端口也是不相同的(分别为64h和60h)。
/ R) d. ~/ m' Z9 p6 b4 q+ l8 [: `5 q+ g" f5 s& P

3 _6 F+ F+ m$ _! h4 K* O- S& J7 {  N" b
* b. d5 d) [% a, X! {    * 64h端口(读操作)
7 M/ z. ~, l- O, h9 Y2 Z# i: c2 F5 D9 o+ G' g

# z( }2 b& M+ ~" j. v对64h端口进行读操作,会读取Status Register的内容。
' W2 x7 b+ ^8 W) E+ t$ R- X& [
5 t) L4 o$ |" V, @. i4 v: Yinb %0x646 Z/ W  W: v  z4 G. u; V! Q
执行这个指令之后,AL寄存器中存放的就是Status Register的内容。9 W: c6 p5 q" H0 M
' o% C+ r1 X3 x1 p, ]5 s
    * 64h端口(写操作)& w' R5 K, f( s+ Q. y

' C0 m1 B2 M, e7 e; P向64h端口写入的字节,被认为是对8042芯片发布的命令(Command):
+ \) F- l+ B9 i) e) V. @2 HŸ& R" z. {& l& j# Z* t
写入的字节将会被存放在Input Register中;' f0 }8 s6 r4 {. l, |
Ÿ
, n  L& F- v. a7 ~0 ]# I/ A同时会引起Status Register的Bit-3自动被设置为1,表示现在放在Input Register中的数据是一个Command,而不是一个Data;! ?  ^9 ?; m: n$ ]) u+ A
Ÿ+ Q; \% f2 W- [7 \! z
在向64h端口写某些命令之前必须确保键盘是被禁止的,因为这些被写入的命令的返回结果将会放到Output Register中,而键盘如果不被禁止,则也会将数据放入到Output Register中,会引起相互之间的数据覆盖;7 s0 q7 U0 Y2 v' q! U
Ÿ
3 k2 a& ?+ R# J& V6 V1 v在向64h端口写数据之前必须确保Input Register是空的(通过判断Status Register的Bit-1是否为0)。" R8 y9 w: D5 x

# V5 {, x; Q6 J9 I' k) z6 R# x, gvoid wait_input_empty(void)
, v. n! e) f) K6 a2 x* d{1 _+ r! f' j! u( O5 ^% d( Y* l
   char __b;% I8 U% T; O0 K/ A, Q* |- T
5 Z5 s; C% Y; P7 ^0 x
   do{
+ t  E! |5 d) x  n% M# B     __b = inb(0x64);  i8 q0 X" l1 K
   }while(!(__b&0x02));! W& p! O7 W; ^
}
  N+ `2 o3 S: b' t  `/ k& p* G! Y( V% n( j8 q* p5 ~
void disable_keyboard(void)! y, v6 e. y- U8 n5 f
{$ T7 }) e. s. e' h/ |
   wait_input_empty();
# K+ `2 ^, i# Y/ s' G: I   outb(0x64, 0xAD);9 m. N1 Q! _4 q& C* s
}[size=+0]
/ o8 Q& I# M2 T: y3 i4 M( ]; W7 z* [& S4 T3 ]$ C- {4 h
    * 60h端口(读操作)9 n2 {3 ?) _! R; A! @

. T3 z- u  N- M对60h端口进行读操作,将会读取Output Register的内容。Output Register的内容可能是:
2 N0 Z$ y8 D# @8 f7 ]% tŸ           来自于8048的数据。这些数据包括Scan Code,对8048发送的命令的确认字节(ACK)及回复数据。
4 ]) }! S1 }6 C6 R& W6 TŸ           通过64h端口对8042发布的命令的返回结果。8 N1 b, M1 L2 X; U( m" v

$ [3 D# z' R& D$ j7 y& W在向60h端口读取数据之前必须确保Output Register中有数据(通过判断Status Register的Bit-0是否为1)。  V. j. L) C+ w( e
void wait_output_full(void)
& I: s9 K  A) x0 e8 x{
9 `$ [' W; T* s0 h% `   char __b;
4 A2 N. J4 s4 S0 \& ?/ F3 P& }. u( E; ~* ^% C; R
   do{8 g6 B+ r/ h9 i
     __b = inb(0x64);* B% P7 q5 {3 @" C  O
   }while(__b&0x01);1 v% v# ^( `5 \# o! j# p
}* h. j1 N4 p' i% [- p9 J1 @+ p2 m

1 A) U/ q5 A2 Y" f! gunsigned char read_output(void)3 J( ~3 L+ t& b9 o# D# \: T; `% C
{
8 X0 m1 s# l8 w6 V% o* {' j$ E   wait_output_full();
! ^! o( i( U8 W( O   return inb(0x60);
7 s' p# _6 {+ R, [. w9 {}$ ]5 b3 p/ R$ J2 Z+ e$ P
) M3 n. o& j* y- j8 ~' @$ s* O5 P
    * 60h端口(写操作)
( ?- @! U6 }3 l5 h  ]
4 Y, j. J4 E9 c/ s: O向60h端口写入的字节,有两种可能:
) _; `5 f. [9 T' g" ]1.如果之前通过64h端口向8042芯片发布的命令需要进一步的数据,则此时写入的字节就被认为是数据;! ]0 m  a2 E/ J! Q& y) _$ q9 m7 `
2.否则,此字节被认为是发送给8048的命令。$ G- }2 u. t" b5 t% s' N
" f6 V. x) A- P
在向60h端口写数据之前,必须确保Input Register是空的(通过判断Status Register的Bit-1是否为0)。
5 i3 T: d6 @7 d" d
6 m: Q( v8 Q0 ^$ y: ^6 `5 \8 k; {% F# T9 J6 K( g$ I
[size=+0]4.2.7.1 发给8042的命令3 u( [8 _! @% M3 D4 `4 m, A$ V5 x
+ x& O( H/ N: g
    * 20h
( W$ {. O. }* P  p4 Z: ]( `5 h9 u9 p$ H
准备读取8042芯片的Command Byte;其行为是将当前8042 Command Byte的内容放置于Output Register中,下一个从60H端口的读操作将会将其读取出来。, Y' D2 @- b+ N- b
8 c! B: G- d5 F6 d' H+ d4 {" C
! U- y' }8 ~! z! P- L* x( W
unsigned char read_command_byte(void)
$ ^7 s- P, }% b# c* N: H! c{1 t+ N: |0 f% {* r1 Y5 w2 @; I
   wait_input_empty();) S" W. j) S& B2 B4 ]0 V0 [& W
   outb(0x64,0x20);8 y2 a; d& ]3 O" z: g
   wait_output_full();
' _& w0 H8 q( h, R   return inb(0x60);   
' k! u' L. R5 r}0 {) X, H0 C/ v8 E: m6 M# q1 l

  s. M6 m8 _& O1 v9 n9 W+ G& C    * 60h
  U; d  X& H. w: s9 E
/ I3 |0 z1 `2 L2 x5 [/ T  a  E准备写入8042芯片的Command Byte;下一个通过60h写入的字节将会被放入Command Byte。$ a' `1 M4 K' T, G

5 O4 u( z; z1 q; [2 i9 L
" R1 N; n. v. h' R# \void write_command_byte(unsigned char command_byte)4 q6 i9 s( v: D6 Q9 x9 r
{* N4 i: t# h# ~8 B
   wait_input_empty();8 ^$ R" X; g4 b% Q& Y3 k
   outb(0x64,0x60);' o2 H( j$ ^' ^1 f! a. Q
   wait_input_empty();0 L4 |$ o1 h4 j: j* T1 K
   outb(0x60,command_byte);
3 a* z4 M5 y$ O% F0 U& U# S}+ m4 x- x6 F! K  B) j
/ M. ]$ p8 N1 {; u
4 ]6 L8 E" f4 {; M: H  X3 r3 ]" m
    * A4h* Y( p/ N' N( j' F  Q! o
  c  R  K/ _. G4 ?  n3 B) E, o
测试一下键盘密码是否被设置;测试结果放置在Output Register,然后可以通过60h读取出来。测试结果可以有两种值:FAh=密码被设置;F1h=没有密码。
5 ?3 Q8 M; {: O" C1 lbool is_set_password(void)
0 q. R, L+ F8 ^. G9 D{+ j1 W$ H7 }$ J
   wait_input_empty();
* }6 u7 ]) k$ y   outb(0x64,0xA4);
/ Q- l9 ]: s/ z# b5 R   wait_output_full();& d0 m1 P) t! ^$ V) ]2 Y
   return inb(0x60)==0xFA?true:false;   & F+ _) n6 k6 [1 p  E0 M
}3 [7 c0 g) `+ ]

6 r5 h/ b) V* F& a% I/ \    * A5h5 Q  |2 J8 h# n8 p

  ]5 o7 g+ B; T6 @2 B设置键盘密码。其结果被按照顺序通过60h端口一个一个被放置在Input Register中。密码的最后是一个空字节(内容为0)。' N5 f, T* D- n( S1 X* t# }
void set_password(unsigned char* password)! {  @( q7 f' h
{
+ r: D. x5 @1 W( B" z   char* p = password;
+ V& n8 W0 q1 g1 e6 @% ~5 {( K8 ~+ Z8 _. R/ K( _3 h5 Y
   if(p == NULL)
" I" Q" |1 W4 D) v      return;
4 E( y3 v8 O' {9 `) D$ q9 S
  d+ l6 w1 }4 x+ D   wait_input_empty();7 O$ ~6 [  e  {! W9 x, u
   outb(0x64,0xA5);
/ Y7 K1 @) J/ H1 _) S2 N8 w) Q" e
& `0 x/ _( k, U# N2 {   do{* w/ [% d. D" b# i9 N+ a
      wait_input_empty();/ n+ o0 w0 q' _% v! \/ ^8 n' V
      outb(0x60, *p);" n9 e8 |2 F( b$ Q# N
   }while(*p++ != 0);
* Q# H6 g4 b3 C, U) k3 w}" `; w* L- @7 c- z3 w- d

  T  F) t- O% O  S4 O3 b0 F    * A6h5 u& s& f- ]8 N  e. P
' V7 ^+ L* y! [' `' `0 ?
让密码生效。在发布这个命令之前,必须首先使用A5h命令设置密码。
+ w, a/ @1 M( J' ~0 q; ~void enable_password(void)% C8 M* J5 I8 ]5 P4 j# E7 s. X  h
{9 i5 p& g8 q- X& h1 |9 E7 K
   if(!is_set_password())
7 `% z5 ^/ V: ^* b% N6 B      return;
' K; \# N& H0 W) a( M+ @' x) }' E2 p- U, c- S- o  z$ w
   wait_input_empty();
0 {! p  l$ J0 `   outb(0x64,0xA6);   
+ x; X* T1 E! E5 {5 R2 v/ q}- e/ h* Q& P: K4 ^  Z  U" w( X8 |: w
1 T% ^4 x5 J" ^$ d5 e0 X6 p
    * AAh
- A; e' K; e/ @% H3 g; U0 d
9 I! L2 F. o' I! a* |  M5 c自检。诊断结果放置在Output Register中,可以通过60h读取。55h=OK。5 X$ p7 T' ]$ ~9 I4 ]

2 d$ a; v3 V$ C7 I0 [0 H- ?- e$ a( l: ]% D* G1 I
bool is_test_ok(void). k0 F( w$ w  V% E* [, X  `
{
1 H- v) ]8 h2 l  S5 h6 s) l0 f   wait_input_empty();
( }: G3 X; k; ~3 R* p& t) p( d: L   outb(0x64,0xAA);- i+ C# A" m3 v1 {9 f" V8 j: T
) v7 P* C8 u: q* T; |- F* X) F

$ J: S- |' C% e# x   wait_output_full();/ {3 L, t7 I/ O. T% {; ]' e4 o
   return inb(0x60)==0x55?true:false;   
' F+ M" Z4 D0 B; a4 j+ n0 W}
" c! G+ Z% b$ V* R5 r, T. h* ~- N" f- }' h" i0 z- W+ L
1 h1 M  C1 X7 x- C% G& X" v# r; e1 o
    * ADh
" \6 r% o& @- m4 G2 ]
, N9 f* C) |" l禁止键盘接口。Command Byte的bit-4被设置。当此命令被发布后,Keyboard将被禁止发送数据到Output Register。
! X) u( T1 h1 ^void disable_keyboard(void)
3 b( ~( C. r2 C/ T9 b* T{
$ P+ ?$ j" a% f* F, `   wait_input_empty();
* j0 [5 C  S% m( E   outb(0x64,0xAD);) c, D# `5 M* r, B2 P' `
# G/ j1 @1 w, _- b% m
}
" j7 F( U4 N0 b! k% ^' s2 T7 w% I* Z  B1 X# W
    * AEh
1 p$ c" `3 i" t4 a  S& i
; N, c* |; y# d0 r  ^$ v3 G: }打开键盘接口。Command Byte的bit-4被清除。当此命令被发布后,Keyboard将被允许发送数据到Output Register。( _2 s' g/ u* ]7 H5 o3 E
void enable_keyboard(void)! D! c5 x; f& Y8 a0 C" @$ \" `3 l. \
{
. i, h, C6 n6 p; L7 }* `% Q: {( D) {   wait_input_empty();
# c) P- N5 \: r4 f   outb(0x64,0xAE);7 o' b3 K0 B5 h! C6 _9 k

4 F& n5 k9 k4 ^) H. U/ j}# ?8 v6 |8 q) F; N$ T& K* J4 T

1 u/ N& y* p# v4 a    * C0h
/ _/ j8 g. U% z, ?7 j3 ?) I1 K& @. Y7 U+ J8 _$ i# M
准备读取Input Port。Input Port的内容被放置于Output Register中,随后可以通过60h端口读取。
0 R' b$ G  x/ ~( _; G+ F& dunsigned char read_input_port(void)  f9 K' x& p$ ~% `
{# C/ H6 z3 w( u4 P
   wait_input_empty();
/ B8 c! b& M, b7 T, n3 Z   outb(0x64,0xC0);
& Q/ U1 J2 `/ f. [% r. n
. X) B7 a) w1 ^# }   wait_output_full();
! Z4 j  J7 U2 n8 C8 I' v, R( x% O# o2 A' x8 v: c+ k2 S
   return inb(0x60);( t& k* z5 [9 U+ {3 F
}
/ W/ b0 a: o1 y1 p
! @8 W7 O1 ]3 c& j+ P    * D0h
1 C; m; Y' {  D; G$ p  F8 U
' [3 p+ t6 J5 p7 B0 ?9 l: w$ @准备读取Outport端口。结果被放在Output Register中,随后通过60h端口读取出来。* U. k) d# D9 i8 P$ q6 [; \' J
unsigned char read_output_port(void)9 t8 a. s8 F5 _: u
{! r* |  Y0 D/ |6 p8 e4 m8 h9 ~
   wait_input_empty();
$ Q; O5 D; H' a" \   outb(0x64,0xD0);
- d& _* A4 I- b6 K) q, [
* H; |- k5 q. S% c3 f0 @; `+ k   wait_output_full();
& `' E- c5 c# j# |% R( H% k3 Q9 x0 ^; }
   return inb(0x60);
3 y: H1 o3 S- A! a2 X+ {8 M}: v, w3 ?% U2 g
) S( Q, P) {) ]! t& i
    * D1h" k0 K8 w- d% Z, j: g+ ^0 o

# i& l* T6 ]: E. B8 @准备写Output端口。随后通过60h端口写入的字节,会被放置在Output Port中。
3 F$ ~( w: h4 H; G$ Hvoid write_output_port(unsigned char __c)
) r/ x# A# W& `{
+ G6 r4 o7 Z2 [' I   wait_input_empty();
' i' q  ?- S1 Z9 v4 v; ~   outb(0x64,0xD1);
. P$ Y7 x% H& b/ C# Y6 t
- Z+ D# y3 Z. v   wait_input_empty();1 o  z: s' f+ b  h8 w* B
   outb(0x60,__c);2 b% x# y, x1 |

; }! P5 |! J2 a! j5 y}
* S5 M9 d, k; C! g; g! Z, n' m6 ]) h' d

. n+ j, r- R% z    * D2h) J3 @3 k7 k( X, @# N7 @" z, e

( _6 ?2 O$ O7 _, \* E+ ~准备写数据到Output Register中。随后通过60h写入到Input Register的字节会被放入到Output Register中,此功能被用来模拟来自于Keyboard发送的数据。如果中断被允许,则会触发一个中断。  `0 l; u2 b6 A+ j1 o, L2 s
void put_data_to_output_register(unsigned char __data)
4 g# E) ?% E% q% ~" ^& `, J) m{
; }2 b" x7 @' y   wait_input_empty();
2 ^( m( l* w9 S: r& Q6 A   outb(0x64,0xD2);
6 x' i- X2 I1 r$ l1 \7 @5 k+ g! a4 p9 o; Y( {2 S' [
   wait_input_empty();0 q: d7 g0 V! {0 Q% X9 g8 H, z7 o
   outb(0x60,__c);5 w' k* M9 F! s) P6 `. |; B
}( b8 B* r) J5 W. _

: S2 t7 ]" H( Z! d2 E% Q+ @/ e4.2.7.2 发给8048的命令1 U) [/ j2 N6 w( G

' O: B* n' W3 W# s& q
: i4 d. d) A2 _$ [* x) y    * EDh* w7 j3 ]7 N2 [/ W! @' M) @- P: b
0 A& {8 S, b% f9 `" M
设置LED。Keyboard收到此命令后,一个LED设置会话开始。Keyboard首先回复一个ACK(FAh),然后等待从60h端口写入的LED设置字节,如果等到一个,则再次回复一个ACK,然后根据此字节设置LED。然后接着等待。。。直到等到一个非LED设置字节(高位被设置),此时LED设置会话结束。) c& l, h1 a0 P4 E8 S

3 a8 `) ^! t5 k/ ^( d( G5 H    * EEh7 G5 e! S" F4 {( |7 e3 U
* n& b7 v$ j% `" b8 g8 R  D. Z  a
诊断Echo。此命令纯粹为了检测Keyboard是否正常,如果正常,当Keyboard收到此命令后,将会回复一个EEh字节。- K( c. U0 P% e# p" ^
& e* ?& T+ s+ ^* ~+ `8 @' j$ J
    * F0h1 p% q* i' r* p( e* y# X% z% F# }" ~
, B- e: P/ B8 ?# @% v/ |
选择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代码所要求的。
5 j+ Y+ D( E4 j( o4 k- Z8 T- r/ X* c8 ]" u/ v) b- x
    * F2# K! M2 ~7 c7 r0 N- M2 O

5 V% `0 }, B5 m+ L0 K+ w! @4 Q/ |读取Keyboard ID。由于8042芯片后不仅仅能够接Keyboard。此命令是为了读取8042后所接的设备ID。设备ID为2个字节,Keyboard ID为83ABh。当键盘收到此命令后,会首先回复一个ACK,然后,将2字节的Keyboard ID一个一个回复回去。0 ?# n4 O5 j/ E, d& u. {% Q

$ x, x. \  `- ?; v5 f2 z    * F3h
; w/ H# Z4 z  M
- `; T  H  B4 e: y0 P6 U1 [设置Typematic Rate/Delay。当Keyboard收到此命令后,将回复一个ACK。然后等待来自于60h的设置字节。一旦收到,将回复一个ACK,然后将Keyboard Rate/Delay设置为相应的值。
8 f, E5 Q) A5 Z/ S3 K0 L+ m  z/ m! f. o  @; ~5 G
    * F4h
8 S/ B& V1 I8 I! A
- W% Z+ ^7 F5 J, e5 p- y4 K清理键盘的Output Buffer。一旦Keyboard收到此命令,将会将Output buffer清空,然后回复一个ACK。然后继续接受Keyboard的击键。
. \- D( G" ?# \9 o* S1 O
0 O6 t0 g: c, q    * F5h
! c. u7 g$ ?* ^) O& U" t' [8 p& Q. n0 f/ J) r4 _2 ]5 [
设置默认状态(w/Disable)。一旦Keyboard收到此命令,将会将Keyboard完全初始化成默认状态。之前所有对它的设置都将失效——Output buffer被清空,Typematic Rate/Delay被设置成默认值。然后回复一个ACK,接着等待下一个命令。需要注意的是,这个命令被执行后,键盘的击键接受是禁止的。如果想让键盘接受击键输入,必须Enable Keyboard。' R( q5 Z  I# h5 g

% U+ j: X1 u' M5 A+ o% _( Z9 ?    * F6h$ m8 G2 \2 B" T' T7 d$ H, Q

6 ~- h" M* \1 P/ w% f) L设置默认状态。和F5命令唯一不同的是,当此命令被执行之后,键盘的击键接收是允许的。# m* U1 ~5 \( X2 Q! }& l

( S7 ]" n0 ]0 h. W0 c    * FEh
) K) R* p; H" f; N+ X4 E
/ I7 M4 [1 n8 `; u& G2 jResend。如果Keyboard收到此命令,则必须将刚才发送到8042 Output Register中的数据重新发送一遍。当系统检测到一个来自于Keyboard的错误之后,可以使用自命令让Keyboard重新发送刚才发送的字节。+ S, y6 w% P3 x% k; d( V9 E" _; I

: _# D+ {  C" t7 P5 K    * FFh- O* o5 \" Y# H3 R9 C
+ Y4 j9 k  p3 z8 E, Q5 u
Reset Keyboard。如果Keyboard收到此命令,则首先回复一个ACK,然后启动自身的Reset程序,并进行自身基本正确性检测(BAT-Basic Assurance Test)。等这一切结束之后,将返回给系统一个单字节的结束码(AAh=Success, FCh=Failed),并将键盘的Scan code set设置为2。
回复

使用道具 举报

发表于 2009-1-14 13:49:16 | 显示全部楼层
好贴!
: P9 b, b9 G; }( w非常详细!
" D% Z9 d1 k4 K. a谢谢!
回复

使用道具 举报

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

使用道具 举报

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

本版积分规则

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

GMT+8, 2026-9-1 17:44 , Processed in 0.292223 second(s), 16 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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