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

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

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

9 i# \7 b" }/ ?# _, S! ^) \; E4.2.7 Command
0 {$ i' D* E  E: R% R' f) q% H* Y: B# n# u9 G5 @
通过8042芯片,可以:
8 H. r! f3 w/ C! r0 d向8042芯片发布命令(通过64h),并通过60h读取命令的返回结果(如果有的话),或通过60h端口写入命令所需的数据(如果需要的话)。( @- K# `$ {8 c% |% C, s
读取Status Register的内容(通过64h);
1 |" S5 |% z* ?8 t/ E向8048发布命令(通过60h);- P2 \/ O2 ~. `- c5 ?4 ^9 W, N0 K
读取来自于Keyboard的数据(通过60h)。这些数据包括Scan Code(由按键和释放键引起的),对8048发送的命令的确认字节(ACK)及回复数据。$ t. P3 z( K' Z. O, P1 Q
+ Z8 ]. R2 L9 w4 x
再次强调一遍,Command(命令)分为发送给8042芯片的命令和发送给8048的命令。它们是不相同的,并且使用的端口也是不相同的(分别为64h和60h)。
5 p  W* H: A0 w# A" w
. N# {# Q+ K8 D
& T* ]6 W9 r, j
' J( |2 U; [) z  W! v3 c    * 64h端口(读操作)
7 l/ k/ [! t7 D+ L, _) `: X5 C( ^8 a9 u8 ]6 P' p* h

0 l# q5 Z. j% y! y. s对64h端口进行读操作,会读取Status Register的内容。
' O- M7 J( \# z8 R! f1 v" L0 s& m$ t1 A8 ^4 }% M/ ?- r0 {. L* @4 H( j3 A. T
inb %0x643 b( y& Z$ f3 s$ v
执行这个指令之后,AL寄存器中存放的就是Status Register的内容。! ?# [9 F1 l# Z8 V% L' {! Q- F& C
0 g- q2 z6 A' f6 ~
    * 64h端口(写操作)
0 ^0 g  i- W5 a7 v+ y% s- C& X/ i/ t! h
向64h端口写入的字节,被认为是对8042芯片发布的命令(Command):
! C1 l3 W$ m9 a7 a" AŸ
7 Z* t3 b6 _/ {( t写入的字节将会被存放在Input Register中;
1 n. `9 h9 Z2 t8 J. I1 YŸ3 ~, W4 b! g8 @6 A  d  i! n  }, T8 d
同时会引起Status Register的Bit-3自动被设置为1,表示现在放在Input Register中的数据是一个Command,而不是一个Data;
( N8 B6 \, n, zŸ
: v' f0 f( A3 q0 ?* h3 h+ G在向64h端口写某些命令之前必须确保键盘是被禁止的,因为这些被写入的命令的返回结果将会放到Output Register中,而键盘如果不被禁止,则也会将数据放入到Output Register中,会引起相互之间的数据覆盖;, N7 w2 v& f4 @4 z
Ÿ
6 [( t2 H+ u8 V$ o9 b7 O在向64h端口写数据之前必须确保Input Register是空的(通过判断Status Register的Bit-1是否为0)。
6 V* ?5 [4 W8 i" _6 ^5 G' V9 B' y6 E# q# E
void wait_input_empty(void)
, v7 C  a# b& y' x% `{
% {* h$ i( U; [0 G& l2 C   char __b;
6 A6 `5 P7 N  o6 q/ B1 [) p/ H  F; o5 g: Z5 n
   do{
0 O$ p9 J7 l, C: T     __b = inb(0x64);' i% U$ e3 l7 }0 h& W# Q
   }while(!(__b&0x02));6 h2 @: J+ @, v2 y/ \
}
! k' K! {7 [6 D3 d0 r' K- C$ z/ H
( K% M$ V/ Y* e* Pvoid disable_keyboard(void)
/ q+ e( w1 F- B% |* ^( U, g1 B$ g: s{2 W; {, N0 t# q4 N1 o' i+ e
   wait_input_empty();# _5 `* U3 [4 o) k
   outb(0x64, 0xAD);4 U6 w7 I3 j, S! {7 p9 s$ C( n6 a
}[size=+0]
/ v* Z, H% P5 ~+ e
% p8 y5 G# R- w    * 60h端口(读操作)! w( c& _9 E& _  b7 A* M9 Z5 b# D
/ C, H% i1 ~0 t6 B' Y: T
对60h端口进行读操作,将会读取Output Register的内容。Output Register的内容可能是:: J/ j+ P. p, X& h6 e& G- p- X
Ÿ           来自于8048的数据。这些数据包括Scan Code,对8048发送的命令的确认字节(ACK)及回复数据。
$ a  U; Q" O; I7 G, z6 L! Q! pŸ           通过64h端口对8042发布的命令的返回结果。, [1 H9 H  G0 o  k% o) D
) t& \  c$ G& U# \3 @6 I
在向60h端口读取数据之前必须确保Output Register中有数据(通过判断Status Register的Bit-0是否为1)。: U* D7 E: D1 r. g" p
void wait_output_full(void)
+ k" }6 }5 L+ ~; {4 `{
5 e8 u; a; B9 m! R   char __b;
# H- \; l3 k. n2 `( {* `) W5 @) M2 h6 {- o; ?/ @
   do{1 @: I# k+ Z6 Y( ~  h$ V. L
     __b = inb(0x64);
* ]* S' P9 |4 D  p   }while(__b&0x01);8 H. N0 E8 r6 i
}
2 [. f) U6 l+ p4 P8 c' }' C) V, |  x1 v
unsigned char read_output(void)
/ r- ~- v/ G6 P0 G5 v6 d# f{
5 V+ Q8 b# u* c6 y0 J# X   wait_output_full();
7 d% w# S7 L2 K0 ^   return inb(0x60);2 T' M8 S4 J/ }! V! X1 [
}! K2 G0 n3 F7 E: y. }! v" A

; ~/ g) c+ t2 o4 c# a    * 60h端口(写操作)
  g) J" \! r3 k7 u- W" W4 H$ Z, U! ?, Z; k2 q( s
向60h端口写入的字节,有两种可能:
6 n$ k6 ]; e. e- C0 g! p  |5 R1.如果之前通过64h端口向8042芯片发布的命令需要进一步的数据,则此时写入的字节就被认为是数据;0 N9 w  r) r/ p; w* G! \! A: H' K
2.否则,此字节被认为是发送给8048的命令。
" W1 }3 `2 V0 ?9 {: e" s& b7 v6 t( L& f( g" b+ _6 n' e6 Z7 o
在向60h端口写数据之前,必须确保Input Register是空的(通过判断Status Register的Bit-1是否为0)。) ]4 h# w2 U. W
- H  A( q3 s6 ]/ i  V
6 `& M) f: ]8 O- w/ v- I
[size=+0]4.2.7.1 发给8042的命令
" f5 d! u4 K3 }2 f2 @9 M" W% Z6 a1 x2 g- M: _+ m9 R( w* f8 M  H5 _& E
    * 20h & f/ i7 X1 [* N! L' r# H

/ L5 h) H( c6 t8 i6 p9 u4 @: e4 G. I准备读取8042芯片的Command Byte;其行为是将当前8042 Command Byte的内容放置于Output Register中,下一个从60H端口的读操作将会将其读取出来。
- k6 x6 ?0 P/ i( x3 _/ m  r, i, a2 M6 h8 o

" |) P7 O6 e1 ]0 T; ~$ u% W6 G, runsigned char read_command_byte(void)
3 a) J, A+ @8 Q+ A3 L/ a/ n{* T; }6 F& v; ~, d
   wait_input_empty();" V$ E! X% y5 t3 ]* B
   outb(0x64,0x20);5 ], g2 C8 U' H6 T5 C' P$ Z
   wait_output_full();4 R7 F3 s+ x% A" P# ~- l5 i
   return inb(0x60);   * ?( ?- T  X7 L2 `5 d1 Q7 U
}3 _+ ]/ Y. u  I* \

2 Y2 S/ B, W$ }, N1 J  x2 {, X' w5 W    * 60h
) d2 h- E, v$ C, s4 B+ r& A
0 _( Z% D  `3 x( F2 C准备写入8042芯片的Command Byte;下一个通过60h写入的字节将会被放入Command Byte。1 X7 b$ P% [0 O) U# o

, o( I3 g: r4 R! A+ f" b2 B' _+ |5 L- N1 {
void write_command_byte(unsigned char command_byte)
; `  R9 ]. u1 @) y+ S; K& w; r{
5 A6 o( k. m) x4 o" p$ m5 d   wait_input_empty();" i8 y0 f* F4 `6 t& E( j+ r
   outb(0x64,0x60);- c2 s3 J1 J! @
   wait_input_empty();
! O8 v5 c- A, o   outb(0x60,command_byte);- a2 S# l( h9 M( ]! {" |4 x: y+ l
}
7 {3 K  ^! }( H: _/ S7 L0 p0 K# t1 L% n) q
! Y8 H/ ], `7 M3 B" f, e) \
    * A4h
6 E# ^4 B+ b# o
3 F2 z0 u& L) Z' L测试一下键盘密码是否被设置;测试结果放置在Output Register,然后可以通过60h读取出来。测试结果可以有两种值:FAh=密码被设置;F1h=没有密码。8 f2 m/ B+ a/ |2 I$ R* |
bool is_set_password(void)
5 q, B! h1 f4 J4 c4 S" y# p  v3 `{' W$ p* P6 c  ?: {: V! G& |, z) {
   wait_input_empty();
/ ^/ U. W' i9 _) {8 m   outb(0x64,0xA4);6 q; b/ c9 @( {+ C
   wait_output_full();+ n6 e7 j# m# v  p5 Z
   return inb(0x60)==0xFA?true:false;   5 e* x+ C0 E7 R  C" v
}
# u, E7 [$ T' {7 H' ~/ C) p: X( h) ?0 o$ ]4 E
    * A5h# B( _' {2 F+ Y* ]

  e0 q' [7 |& s/ t设置键盘密码。其结果被按照顺序通过60h端口一个一个被放置在Input Register中。密码的最后是一个空字节(内容为0)。- U) X4 G1 @; F$ `' I  }
void set_password(unsigned char* password)* o& q9 }* {9 [9 g
{
1 }, s0 }6 ~0 N2 P$ B4 ]   char* p = password;6 |9 b5 C8 o0 ?1 b2 Q' w& }5 G
* y6 [9 J: \1 k# u% E, p
   if(p == NULL); G" W6 E7 Y% _* l
      return;
0 q; F" n0 y) N* I6 B1 a4 P) H5 _
   wait_input_empty();& S/ P7 g5 T5 l; Z2 D
   outb(0x64,0xA5);& o# N- x4 z6 _5 o4 h* {3 @8 B
" D) P% z( H7 d! b5 l' I
   do{( h+ |. e9 ]2 B- C! q
      wait_input_empty();3 c; P0 u1 g& v/ ~; \* Q( M
      outb(0x60, *p);
+ m( W2 \& Z2 A4 o3 ~% e% H; }. J# b   }while(*p++ != 0);
- O" d( d( T" B; T% x( s! q2 J" w1 r}' S; M* |$ f0 K4 j9 C8 V
0 J! u, l% {9 i' F0 {7 t
    * A6h1 Q" S' L7 t7 R, w

* O' H# `# j; A% h+ H让密码生效。在发布这个命令之前,必须首先使用A5h命令设置密码。
; o& Q; s& r- u/ \9 Pvoid enable_password(void)
& n- f) `, f+ _% P" k{
7 h4 p- @) Q# i9 m   if(!is_set_password())
4 _9 `  f6 _8 }      return;
& q9 B2 J/ |- w- D1 M' }# W
' n: y4 ~3 x& Z* F7 T  `+ l6 q   wait_input_empty();
, G! H5 \9 e4 l   outb(0x64,0xA6);   
3 A* q! ^$ ^9 }2 t' G; h9 F4 l# K}, N4 f9 P2 Q( C

& f( F3 s& a' B6 D/ W, C    * AAh$ y7 P0 I* E' K" T  h

3 a/ @" O( D! i& n自检。诊断结果放置在Output Register中,可以通过60h读取。55h=OK。
% W9 i# G* b' S7 }& W, Q8 L4 l! ~) u7 [+ g* P. \; y& w
3 g/ e) ?5 ^- B% `, E2 G; m; j
bool is_test_ok(void)1 m, o% \/ H5 b1 H/ i: F
{
' ?1 ]/ S4 U( k/ E   wait_input_empty();
6 x8 z/ o( i( N0 U: X3 j% \) Z   outb(0x64,0xAA);/ V# b& I; }9 s9 p( _

  B2 B+ i' e: J( ^6 n1 ]! |# S# {. |1 H9 Y. U# U" u' Y' X) K$ k
   wait_output_full();% f4 E& C7 G1 ~+ V) _- ~: r" }7 x
   return inb(0x60)==0x55?true:false;   # _" D, y) m/ ]" n+ Y
}  t, e  c; ]# ^+ b" i' ?
# f9 O/ a+ p! S+ W
: O; w- N& r, x. m( U$ n6 a
    * ADh4 X$ r2 G! i* S/ o
: V2 ]# m7 q+ C, W7 w
禁止键盘接口。Command Byte的bit-4被设置。当此命令被发布后,Keyboard将被禁止发送数据到Output Register。
: N5 Z( I5 R2 Avoid disable_keyboard(void)  O0 A' P% o: e' ^
{
$ h5 k/ Z1 N8 L0 \* ^) W# h   wait_input_empty();: l+ I1 s7 i& ]! y& L
   outb(0x64,0xAD);
, k" ]  p* ^& _/ c6 ]9 N; u0 d$ C3 S8 {1 q* |0 H& @5 g/ z9 x
}
9 s- c5 Q2 d  ]/ K! t. }! H% r# H# d$ U; F$ G  e2 G2 Z3 ?
    * AEh4 p; H- T/ m, K- P; T* H
; ~) [' y+ b$ ]* E' ^& M
打开键盘接口。Command Byte的bit-4被清除。当此命令被发布后,Keyboard将被允许发送数据到Output Register。
: [/ g$ @- ?# P$ @& ~void enable_keyboard(void)
! ?) [/ H  |6 i# P! b* H4 u: G{) n' G4 g  ~3 }* N& ^* {+ x
   wait_input_empty();+ D: l+ F4 G; X2 s+ I4 r' a( b
   outb(0x64,0xAE);
& _4 c& ~# ~; L7 g6 @$ v' l$ ~: w: C1 u1 Q/ K0 a
}
& g- Z. p; x  ]  R! l' \( m0 v+ m7 V, o4 ]; q
    * C0h
# G: b( Y+ E) r, }6 p* |, F2 w* l& |/ X1 G! U. y( s: w& _, @6 p" q* a
准备读取Input Port。Input Port的内容被放置于Output Register中,随后可以通过60h端口读取。
9 [: t' ~+ x- h! E  ^5 W' Wunsigned char read_input_port(void)8 {0 Y1 Q4 b; s% ~
{
8 Q8 E' F2 ?5 {% }# l0 W" D! }   wait_input_empty();/ }2 S# Q2 _9 G4 R# J) _
   outb(0x64,0xC0);; ?4 P" n% r6 c9 P

: v% ]$ ]8 Q+ j$ D   wait_output_full();/ W* L9 ~! m8 z4 G
4 h' ]' O5 Z$ g6 w9 u/ f0 S
   return inb(0x60);
( h5 l; [0 |7 h/ s}
! O% A5 b+ _& P9 j$ n; d' d) g$ d& g6 P$ D
    * D0h
% l6 }* M& O2 w  Q
0 r& e3 M( _, o( p; {$ j- I1 v- R准备读取Outport端口。结果被放在Output Register中,随后通过60h端口读取出来。
5 J8 m: v; c. l+ R" ?1 x1 I  S1 a8 Punsigned char read_output_port(void)
, G8 v2 q* u0 L6 {) B# u% x# A{* s) s# |+ R  e" A
   wait_input_empty();3 b1 [. V: ]8 _( ]
   outb(0x64,0xD0);% g! i7 ~* F" H- o/ j/ G3 u
  B+ o$ E/ {- W0 _2 P+ f& r
   wait_output_full();
* h/ p  h2 }1 g; t! O
( H  ^2 Y0 o* n* U1 c: p   return inb(0x60);
3 m: a4 z/ T% I) L. {}2 Z* T0 J0 n* d0 H- W
* u3 v( q2 z# X7 t- N5 @
    * D1h( w9 t) j0 Q3 t5 ~- \5 T2 L

$ ]; V( k" N$ T0 [( e8 G  k% Q0 F/ g准备写Output端口。随后通过60h端口写入的字节,会被放置在Output Port中。
, W+ D9 L9 ]2 f; h" H4 _3 Uvoid write_output_port(unsigned char __c)
& D% I# `/ E( m9 K- X! e# V{6 ?0 p0 S5 S( n
   wait_input_empty();: u+ x& @- {& l+ v
   outb(0x64,0xD1);
0 `+ {2 o( T; R5 X* N+ [$ {: W* g, [3 i; m9 e; ~
   wait_input_empty();" G/ x% V  U% E* z: J
   outb(0x60,__c);
3 r" a5 N7 |4 Y- c
/ s$ p2 S& _$ X" J}* E3 @* C  l5 z, `* w( A

: T  Z7 x7 F6 p+ D7 L& b; Q$ n) f+ d: W% P& _/ {
    * D2h
8 V# @6 Z- g% S/ z$ K4 y* [7 U6 h. d' ~0 P! |/ E4 @7 T
准备写数据到Output Register中。随后通过60h写入到Input Register的字节会被放入到Output Register中,此功能被用来模拟来自于Keyboard发送的数据。如果中断被允许,则会触发一个中断。" s/ M+ z4 W' _3 ~
void put_data_to_output_register(unsigned char __data)
0 Y$ u' z! ~: X* H{& h* {$ q& W( N3 p1 |' j3 d+ b
   wait_input_empty();
2 ?9 M1 K0 u/ y6 ~4 _/ D& \   outb(0x64,0xD2);
0 f& }* N+ W( |2 C% t( W3 D, z& {! w& I
   wait_input_empty();
! x" ~' {4 Y" G0 @   outb(0x60,__c);
8 n$ c  ]! A% ]% F* @5 a}$ }% t/ M! v% H& r8 a
# ?1 n: w* D" n4 e7 h* ], s7 N1 ~
4.2.7.2 发给8048的命令  \. u' B% f; k3 T  W+ T" z! E" i

7 T2 A9 u' @2 p8 g8 y+ p) B# {; M  k" ]6 h7 ~( m
    * EDh! b' j% x0 c/ [
  E+ E: Z. N4 y8 X% R
设置LED。Keyboard收到此命令后,一个LED设置会话开始。Keyboard首先回复一个ACK(FAh),然后等待从60h端口写入的LED设置字节,如果等到一个,则再次回复一个ACK,然后根据此字节设置LED。然后接着等待。。。直到等到一个非LED设置字节(高位被设置),此时LED设置会话结束。
( F1 ]/ f! p# j. l
1 S7 ^7 n# V. o! C- E    * EEh4 o" V  f/ k7 E  h: ~2 F7 H# P
- u% a0 z/ z0 a  i  K5 [! h6 {* o! ~9 ~
诊断Echo。此命令纯粹为了检测Keyboard是否正常,如果正常,当Keyboard收到此命令后,将会回复一个EEh字节。: c) R. O# d8 [4 V8 L; Z$ b) N  @1 O
- ?8 A3 K$ R, X0 p- Q: I
    * F0h
, z! o) l- [5 _9 B" J* S
7 Z7 }! p% Q1 {$ |+ ~选择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代码所要求的。
. k5 [( [& P% w: F! T9 d: X- p- w/ L& E
    * F2$ L& F' o2 v* M/ W

4 X( V2 D' y1 ~9 I0 s7 A读取Keyboard ID。由于8042芯片后不仅仅能够接Keyboard。此命令是为了读取8042后所接的设备ID。设备ID为2个字节,Keyboard ID为83ABh。当键盘收到此命令后,会首先回复一个ACK,然后,将2字节的Keyboard ID一个一个回复回去。5 k! v  q! P1 X

) J, F- k* U3 J    * F3h  B0 C4 K% a9 k$ A- |
6 i& Q$ \+ L7 x$ f: M) l; }
设置Typematic Rate/Delay。当Keyboard收到此命令后,将回复一个ACK。然后等待来自于60h的设置字节。一旦收到,将回复一个ACK,然后将Keyboard Rate/Delay设置为相应的值。
6 ^  Z2 z* `3 L+ h9 v6 |2 C: J; e! _% E: T. I8 k! ?
    * F4h7 o% j" ]# {3 _( o  `" {3 S( @

% o* J" e4 t7 }( b: |# q+ {+ G清理键盘的Output Buffer。一旦Keyboard收到此命令,将会将Output buffer清空,然后回复一个ACK。然后继续接受Keyboard的击键。3 Y% r! v- d1 E
# x3 Y5 b- C2 i7 b$ {
    * F5h
1 i; n! t" ]7 e* ^% d$ C, V) F% T4 s  S; V3 t6 ~
设置默认状态(w/Disable)。一旦Keyboard收到此命令,将会将Keyboard完全初始化成默认状态。之前所有对它的设置都将失效——Output buffer被清空,Typematic Rate/Delay被设置成默认值。然后回复一个ACK,接着等待下一个命令。需要注意的是,这个命令被执行后,键盘的击键接受是禁止的。如果想让键盘接受击键输入,必须Enable Keyboard。3 D) U# }- T7 L8 n7 }
8 L4 C2 C) a: g0 J3 h7 u4 g- h
    * F6h
7 k+ j- U; }  N: W% H
2 o. F  J+ @% ~2 ^+ W设置默认状态。和F5命令唯一不同的是,当此命令被执行之后,键盘的击键接收是允许的。, g8 A* [! L- Y) b# I1 j5 c! H

7 w! h7 k9 \4 a+ @% U$ o/ h3 i    * FEh0 W+ H3 z7 ~; W+ k' m! R2 L

* f8 }3 _7 G% B. PResend。如果Keyboard收到此命令,则必须将刚才发送到8042 Output Register中的数据重新发送一遍。当系统检测到一个来自于Keyboard的错误之后,可以使用自命令让Keyboard重新发送刚才发送的字节。% ^- q6 t8 z' D2 x. B5 h- ?' r

4 g$ p5 J# L1 t! u0 O! q& d9 e    * FFh
9 K- B! r; i( j# _
- e9 U; l: a, @$ uReset Keyboard。如果Keyboard收到此命令,则首先回复一个ACK,然后启动自身的Reset程序,并进行自身基本正确性检测(BAT-Basic Assurance Test)。等这一切结束之后,将返回给系统一个单字节的结束码(AAh=Success, FCh=Failed),并将键盘的Scan code set设置为2。
回复

使用道具 举报

发表于 2009-1-14 13:49:16 | 显示全部楼层
好贴!
7 n( N& T2 Z/ J# Y8 d非常详细!
! I7 R4 L4 {% o谢谢!
回复

使用道具 举报

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

使用道具 举报

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

本版积分规则

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

GMT+8, 2024-5-20 06:20 , Processed in 0.156286 second(s), 17 queries .

Powered by Discuz! X3.5

© 2001-2023 Discuz! Team.

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