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

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

[复制链接]
发表于 2008-7-14 00:04:00 | 显示全部楼层 |阅读模式
bini殇,能帮详细解释一下bios post过程中的所有发给ec的60/64命令号码和意义吗?数据量比较大,截不住。
发表于 2008-7-14 12:09:38 | 显示全部楼层
转个别人发的,不知道LZ能不能用上  
4 Q4 @/ w3 I4 N  O1 v" W$ Y9 m/ O- Y3 `2 u: [# D- I
4.2.7 Command" C3 z  {9 X% s6 i

, J0 p* b; O7 ?8 ^7 n通过8042芯片,可以:
! U3 Y/ O" k; D4 J/ X向8042芯片发布命令(通过64h),并通过60h读取命令的返回结果(如果有的话),或通过60h端口写入命令所需的数据(如果需要的话)。
& S& l5 e# h9 n2 [4 T4 E* r读取Status Register的内容(通过64h);
" P1 G2 |' I: b- ~. b向8048发布命令(通过60h);0 E9 }5 J+ y0 }) {
读取来自于Keyboard的数据(通过60h)。这些数据包括Scan Code(由按键和释放键引起的),对8048发送的命令的确认字节(ACK)及回复数据。3 p9 @( j- I" @+ t/ K
  p1 f# X8 z; e1 s8 {1 @4 J" H
再次强调一遍,Command(命令)分为发送给8042芯片的命令和发送给8048的命令。它们是不相同的,并且使用的端口也是不相同的(分别为64h和60h)。
  G+ Q  @4 e5 U! h+ l& Z2 A
3 X( ^2 g0 q1 g0 K& v
' s0 h" u3 A2 `! i' E8 K: A7 g* q8 W. ^5 U* I0 E. y3 j. s
    * 64h端口(读操作)
9 C0 K: [, {2 B, K% v" y) V6 g. O
9 \; b$ \# n  y% M; @5 l& L
对64h端口进行读操作,会读取Status Register的内容。
4 }) W( o! z& ^7 E% M$ j0 |+ D5 k# i
inb %0x64
3 Z/ B; ^" J8 P( W) z, T6 E执行这个指令之后,AL寄存器中存放的就是Status Register的内容。3 E6 Y0 [/ Q0 i& A. S
& w. U' f& q& V, s9 u: ~
    * 64h端口(写操作)
* W4 F) i! W" g0 `; G
7 q* F0 G5 t  h3 P  H向64h端口写入的字节,被认为是对8042芯片发布的命令(Command):
) s, y2 w( w4 `Ÿ
) C6 k% s. I: o0 }写入的字节将会被存放在Input Register中;
/ p' Z0 ?3 E3 X" e. Z0 b& ]Ÿ
8 ?6 B" e% j/ H# g& q% J同时会引起Status Register的Bit-3自动被设置为1,表示现在放在Input Register中的数据是一个Command,而不是一个Data;+ ~/ x6 g' b9 v6 {! r( o- n8 P
Ÿ
7 p/ f+ G1 Z) C/ W: V在向64h端口写某些命令之前必须确保键盘是被禁止的,因为这些被写入的命令的返回结果将会放到Output Register中,而键盘如果不被禁止,则也会将数据放入到Output Register中,会引起相互之间的数据覆盖;
0 ~8 R( r9 n8 v# R4 cŸ5 \0 R( t! O' l) _9 U) [; H
在向64h端口写数据之前必须确保Input Register是空的(通过判断Status Register的Bit-1是否为0)。
3 E9 o0 S$ f; e9 e1 |3 _# d
' ?4 }% B6 r; n$ b" i6 I; Uvoid wait_input_empty(void)& H) H" D# n5 ~" t2 N
{
# {9 d! ?8 F2 P   char __b;
2 \0 v  A# }. Z* P
! k+ H; s$ N( g   do{; q. u# m7 j6 J5 T
     __b = inb(0x64);5 D) V5 n1 `9 A
   }while(!(__b&0x02));
# o4 w# C8 T8 w4 `}' v' {& L7 p! u0 C4 _

% Z, C$ `$ }  j# b! dvoid disable_keyboard(void)/ {8 ]" d$ c! a- x* q
{
4 I2 w" I' L3 w   wait_input_empty();( t) X: J+ ~' ?4 Y
   outb(0x64, 0xAD);
; D2 C0 f/ l6 z0 ~. b# @, c: q! N}[size=+0]
6 _$ \! P2 {  _# }' B& o
) _6 v  d! A1 Q2 G% O; O5 {/ _# G1 o    * 60h端口(读操作)
/ W) ?9 _, n' p# w/ E/ U1 a6 c
: Q) r* t( D3 V' S8 |0 r* K对60h端口进行读操作,将会读取Output Register的内容。Output Register的内容可能是:
$ B; F# K$ S; A3 `* S' @Ÿ           来自于8048的数据。这些数据包括Scan Code,对8048发送的命令的确认字节(ACK)及回复数据。
/ z. q7 V# h) H  D* W9 W+ B$ cŸ           通过64h端口对8042发布的命令的返回结果。% x1 O0 ]& |3 J" {5 h% F
$ n0 k9 L( E, b5 i/ D
在向60h端口读取数据之前必须确保Output Register中有数据(通过判断Status Register的Bit-0是否为1)。
' V% ?% i" X# z9 k+ l2 H5 Bvoid wait_output_full(void)4 b) ~/ x" g: G$ f2 B' t
{
9 E) Y) w) S* l6 I8 c+ ^8 v   char __b;& O0 p' [7 q2 h1 L8 U0 F8 z

! |% q/ ^# Y. p3 j+ T, r   do{
  N1 u/ u$ x% P# g7 L' }$ c     __b = inb(0x64);
9 U, Z. |3 ^+ ]( O! U   }while(__b&0x01);
$ z7 Q  Y& [) M) g- S6 ~# e5 s- X}
" L  f: _+ Y9 V  O# _& z! V$ m: t" p
unsigned char read_output(void)
9 t- H5 w  ?0 N3 B{$ Q. H( s( r( ^9 q
   wait_output_full();
6 ]! ], O6 r2 X. M   return inb(0x60);' k# l8 D. p, S, n4 J% j, ?
}4 \4 z8 X$ E* X9 X* y
' i  s5 {" E& u. x0 s: r& e7 Z. Z
    * 60h端口(写操作)
' D9 |0 z; @/ h( [" ~6 U3 ^7 _, V0 |" ~
向60h端口写入的字节,有两种可能:
6 i" Q- g" `2 u' X( x+ y1.如果之前通过64h端口向8042芯片发布的命令需要进一步的数据,则此时写入的字节就被认为是数据;
" c, M, Q4 q/ o; Q2.否则,此字节被认为是发送给8048的命令。
, Z5 z1 U& i  F9 J8 O
7 i0 o  O/ m* ]7 [' m2 @在向60h端口写数据之前,必须确保Input Register是空的(通过判断Status Register的Bit-1是否为0)。
8 u; z' W, V  m9 M
: {8 p$ g# Q) g* D( {& i. T& z% `+ V8 @9 G9 _8 ?; m) M+ }
[size=+0]4.2.7.1 发给8042的命令
$ L/ W+ z  L# p6 `  i* a: R6 t+ o% z% v
    * 20h ! z2 b9 P/ y  c1 @. K" c; Q0 s- D
* Z, W- m* [% U2 Z6 L' ^
准备读取8042芯片的Command Byte;其行为是将当前8042 Command Byte的内容放置于Output Register中,下一个从60H端口的读操作将会将其读取出来。5 h/ H& Y4 H( m( ~3 `
( _, o* g) o7 G# b" Y( ]

: O# W: R- [# T; S- F/ G/ Runsigned char read_command_byte(void)8 G9 R- m/ S8 X) M6 w
{: \$ r2 j6 |6 c9 q+ h
   wait_input_empty();) ~5 h* {; T8 J0 D
   outb(0x64,0x20);5 ~) F8 f3 v. i1 p
   wait_output_full();
5 e: s; p8 V: p, c( {4 l' j   return inb(0x60);   " O+ A7 V5 L% \  c! Y, L/ r9 N
}
0 W, ~& ?- Z' A3 h. r" G% N- R* h( T3 r6 j- r
    * 60h
8 t. q6 K# t" b7 z, Y$ ?8 O7 E. [* K% W: u8 e  H; ~2 S9 v
准备写入8042芯片的Command Byte;下一个通过60h写入的字节将会被放入Command Byte。
* b5 U, T( a) b$ n8 a4 p$ Q% \! b! Y9 Z

# V! l  o( ?3 m$ Mvoid write_command_byte(unsigned char command_byte)) w3 f9 Z0 K/ {5 c5 c" ]
{) p4 X4 ^9 J& O! ^
   wait_input_empty();, @( t+ |  H% ]& S
   outb(0x64,0x60);
: T* S7 f7 A) A& h$ K   wait_input_empty();
: S$ ~/ Q6 v0 h   outb(0x60,command_byte);
' i- ]/ V/ X" M  N$ D}8 n9 E4 E+ O$ a+ K
6 w4 Y' K: W# R$ Y) V( S; y
& k& m8 h: Q4 {
    * A4h, G6 h4 L* o: v
$ N% T6 O" A5 `: V
测试一下键盘密码是否被设置;测试结果放置在Output Register,然后可以通过60h读取出来。测试结果可以有两种值:FAh=密码被设置;F1h=没有密码。
3 h9 m1 u8 \9 c$ K4 C! rbool is_set_password(void)
! J; b( t: ~8 k; \: l  H/ ]{
8 q( `* [( E4 G2 m6 v& S   wait_input_empty();, L6 @& x) }1 j& F  f, x
   outb(0x64,0xA4);
( c: _9 h$ l) V! B7 g   wait_output_full();  E2 I+ g* Z+ d: \; v
   return inb(0x60)==0xFA?true:false;   
5 ?1 B* Z/ n8 O% d}
1 j) N$ e5 u" y
% b6 {' d4 c! h! g    * A5h
9 k' O+ G# y  O) w  I+ Q6 a, |9 r" o% A& P& ]- _2 p
设置键盘密码。其结果被按照顺序通过60h端口一个一个被放置在Input Register中。密码的最后是一个空字节(内容为0)。
3 N% c4 o  r8 B6 I0 a7 gvoid set_password(unsigned char* password)
* ~6 g! d6 H: t0 p: H{8 M- K9 j0 q4 S! j5 c
   char* p = password;
2 L2 t- R+ x4 q# P+ ~% e0 c4 }, B6 x- W  e
   if(p == NULL)" P; A7 ^, r' E* S; `
      return;+ }- ]6 a! T3 }; Z. I

! ~+ v- m6 H+ W$ c   wait_input_empty();! b' ]( d3 o2 l2 S( j5 W
   outb(0x64,0xA5);+ V! ]2 T/ U0 v- O. i1 ^/ B' W
, j- N+ Y3 u  P, \0 B9 D
   do{9 W4 k) C- y1 ^( v2 ]1 _
      wait_input_empty();" r3 j' x; w  H7 w7 T
      outb(0x60, *p);4 H. A: k; Y0 f1 _0 N
   }while(*p++ != 0);- ?% U5 o- q" ~
}
. O3 E+ Q/ e( E/ `" `0 a" D# F: O* r7 E  P  |" c; m3 U: H
    * A6h
. i( V/ @  [# I# \9 b. u% Q3 m" z% @: W0 m
让密码生效。在发布这个命令之前,必须首先使用A5h命令设置密码。7 W# `/ u8 B0 o( `  L
void enable_password(void)+ [" c' Y0 k$ E
{3 `9 l& t. H4 l( u& Z# |
   if(!is_set_password())
/ Y# |" |# K- K      return;, r) p! u, Y1 ?; K0 o5 l

) L1 }5 X) c0 G1 F   wait_input_empty();) N+ [8 `2 G- K0 F; r
   outb(0x64,0xA6);   
& S6 L5 b+ E0 u& T1 G}
7 L: D* S0 ^% k, W2 b4 \9 |
6 J6 ?, c3 q- ]    * AAh
! j9 N% V# Z/ `5 I: n. j% m) P  O' x9 _- [( W1 Q3 O% B
自检。诊断结果放置在Output Register中,可以通过60h读取。55h=OK。- o/ m' z; c+ T& ^* k
! `& e  l2 l8 l9 R# i9 P0 @% y
& T$ s9 X- ~$ X' N3 U: _/ |
bool is_test_ok(void)% L2 ^3 w# @9 u8 P# C5 v8 s6 }
{9 X: W/ r, @6 l0 W- ]8 V3 x
   wait_input_empty();- A/ O: A9 N9 a& o* c4 l
   outb(0x64,0xAA);" B( T) W7 S* t

/ r' n6 W; g2 M! w* ^+ n
" X+ d  m0 H# I! |   wait_output_full();
# x( H, e$ V' }# N9 S- ?   return inb(0x60)==0x55?true:false;   + c4 O9 Z* L8 L4 _0 q
}, v& w7 X& @% ?  U- o9 M6 g# ^. X8 b
/ T% \" B" d( U0 R: J# A/ W

3 t8 d5 k4 V: l3 ]2 x    * ADh
3 n  U. ?$ ?9 D9 x: b7 m! U+ @: K& s; j- Y- C6 {& Y, u
禁止键盘接口。Command Byte的bit-4被设置。当此命令被发布后,Keyboard将被禁止发送数据到Output Register。
9 w1 q4 G& p% |+ _2 [, m% u1 C0 ~void disable_keyboard(void)0 L' }  I$ F+ a  B
{
; |" S- `2 f4 `* E( L& ~   wait_input_empty();
4 m4 H& |4 U! G   outb(0x64,0xAD);& r' E+ |1 y$ l+ a' {6 p' }
. E1 m7 l/ J1 m
}
/ [/ `6 E- v( Q4 v2 d) H
! ^) `- Y0 X! w+ C$ X0 p1 ?/ q    * AEh7 c- n7 A2 z- c" f: ]1 X- ?+ }4 q, [4 a
7 @0 g+ y. }+ k. o/ ]& ^, w, {
打开键盘接口。Command Byte的bit-4被清除。当此命令被发布后,Keyboard将被允许发送数据到Output Register。' I8 n/ x4 D5 H& c2 l
void enable_keyboard(void)) w2 e1 @. r3 h7 ^
{6 o! W# K5 u  V
   wait_input_empty();# m( T$ O, S  y9 ^) d/ ]! ]
   outb(0x64,0xAE);
$ y) X6 x; a# [+ \# p) l: s$ D
" ?& R: \  y9 y5 D# E}
7 t; Q0 \( o+ F% Y# J2 b+ L; M' v5 r: j
    * C0h
6 t8 G2 H/ f6 d+ T: s& c1 R# W8 I. ], g3 E$ Z7 }( |
准备读取Input Port。Input Port的内容被放置于Output Register中,随后可以通过60h端口读取。
& H# y6 c, W6 J# Bunsigned char read_input_port(void)4 {0 g: f7 T. |& H7 r
{
( w% [, y- C  l  N* W5 Z7 y$ I3 M   wait_input_empty();
+ F: {# u& e% H0 s5 Q/ E; C) n, G# t6 j   outb(0x64,0xC0);) U3 w1 m  w$ \) f  E  z* |

$ s" q) V8 H/ ]% r+ F- ]  A   wait_output_full();: t. ?- j8 @3 q3 P# h* `! u

1 A# |. C- _! U; p   return inb(0x60);
, D' C! J' v( j$ D; q; Y- |9 K$ Z}
4 I; N5 F, r5 \5 C, b/ n0 b, u- C: i9 j
    * D0h# U0 g* q1 b: W* U5 p
: ?) y8 g" d) N
准备读取Outport端口。结果被放在Output Register中,随后通过60h端口读取出来。) x/ z2 \* z( B( Z
unsigned char read_output_port(void)
( x7 A1 [& N' M, {$ [/ p{; ~2 I. u' W' M3 ]) P
   wait_input_empty();* Y1 V% l5 a( t) s  ^
   outb(0x64,0xD0);3 i! X% c9 a. J. G
* S0 |% g( b( k9 W0 X9 v1 f
   wait_output_full();
) C1 P5 m: k! B* f" O- \) `: R6 {" H$ j. Z5 h* [
   return inb(0x60);) b+ V) e9 @: ~2 ^, x  i
}0 O' U3 U2 Q. }4 d

5 s. L2 |, b+ a2 R/ V  m1 ^! f    * D1h
" U! ^& Y' o' ]5 n4 b1 I
7 p) M  ^1 U/ L; M7 ?9 x2 Z准备写Output端口。随后通过60h端口写入的字节,会被放置在Output Port中。7 C5 z9 d4 h, N6 d7 ?0 [
void write_output_port(unsigned char __c)% Z* D# x" R2 X( j9 G5 F. i/ @
{8 |0 b& g% M/ U+ w5 i
   wait_input_empty();% M9 M$ a& {+ P! l5 B
   outb(0x64,0xD1);" r& @* B3 n0 s8 [/ S& F3 f
9 M7 }  R) s9 d8 f
   wait_input_empty();
) O7 a5 r: ?, }2 W9 D/ a7 C# }# {   outb(0x60,__c);/ U. Q) N4 B- y: f1 I# a) q8 p

( V4 O$ U. m. E9 D8 a}
; @9 }" R4 X2 p4 n1 a: i
0 m6 ~" J, `4 D& a( r" L' j3 P8 ^6 g8 w" @) I
    * D2h
% B6 k, t/ G) D5 {8 T9 ?- c' b1 l7 E# v' M: O: J
准备写数据到Output Register中。随后通过60h写入到Input Register的字节会被放入到Output Register中,此功能被用来模拟来自于Keyboard发送的数据。如果中断被允许,则会触发一个中断。
/ J; L! p; \1 [7 Mvoid put_data_to_output_register(unsigned char __data)
% \' c2 c: R$ H5 Q) G! D1 ?{
% R  J% Q2 N9 \: B; I% G) F: d   wait_input_empty();
. i8 ~  H! K8 ]( j   outb(0x64,0xD2);
- l" H4 [4 a0 J8 E2 p' }" x
, f; p* r0 T+ e9 y   wait_input_empty();6 a8 Q1 z; k) x' p
   outb(0x60,__c);
# v+ Y6 j2 f5 k' H}
- S  h5 E8 |* Q1 p/ v* o  O  J# m8 C; I
4.2.7.2 发给8048的命令/ @- k5 X) y, @% O6 X' E
' o  S) ]. r: S& I0 V6 d

; o9 C5 ^$ y3 u2 _    * EDh' @2 ?' z0 a+ T. B5 T  i7 ^
) K  Z  P6 |1 G% D
设置LED。Keyboard收到此命令后,一个LED设置会话开始。Keyboard首先回复一个ACK(FAh),然后等待从60h端口写入的LED设置字节,如果等到一个,则再次回复一个ACK,然后根据此字节设置LED。然后接着等待。。。直到等到一个非LED设置字节(高位被设置),此时LED设置会话结束。
8 @; z( X: g% U0 C) M
' Y, @; I# S5 `$ \6 X, q    * EEh8 J3 ?! u4 `% [6 X# b7 c
2 Q2 f) _9 I8 H, A! i
诊断Echo。此命令纯粹为了检测Keyboard是否正常,如果正常,当Keyboard收到此命令后,将会回复一个EEh字节。% |8 E2 l7 O# z
& c( h- w$ b5 t& m
    * F0h) \: J2 `' Z5 Q+ n/ }( F* O' S

  z- ^5 C2 Y3 K- }6 C8 T  {选择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代码所要求的。
: C! V2 c8 j5 {  {0 D* z9 {) T/ d* R. ]" P8 \% h
    * F2
4 ?0 }# K* W. ]6 G0 d4 `! F. u! k3 }. w* M
读取Keyboard ID。由于8042芯片后不仅仅能够接Keyboard。此命令是为了读取8042后所接的设备ID。设备ID为2个字节,Keyboard ID为83ABh。当键盘收到此命令后,会首先回复一个ACK,然后,将2字节的Keyboard ID一个一个回复回去。
/ A( N# _. m! \# `% m& e% u8 q5 `  }3 ]7 |7 b
    * F3h/ }: n7 m7 R6 G6 d3 L8 S$ V1 A2 P9 }
! N# G6 \; v. l* h+ D
设置Typematic Rate/Delay。当Keyboard收到此命令后,将回复一个ACK。然后等待来自于60h的设置字节。一旦收到,将回复一个ACK,然后将Keyboard Rate/Delay设置为相应的值。9 W! k: c  X, Z1 O" E' k, G

& H# _4 _3 c) E5 f    * F4h* r. V8 J: X. w1 o& H: V/ ~5 J+ w
' ~5 O1 h% R: S2 T/ [. @
清理键盘的Output Buffer。一旦Keyboard收到此命令,将会将Output buffer清空,然后回复一个ACK。然后继续接受Keyboard的击键。
8 @  e5 P. M2 z( U% A1 }6 A+ `
/ z7 w3 X7 O& Y( Q' ]2 x    * F5h
9 i  k6 o( v: e  n, z6 E
9 ~  m" i2 z: o/ K1 P9 U设置默认状态(w/Disable)。一旦Keyboard收到此命令,将会将Keyboard完全初始化成默认状态。之前所有对它的设置都将失效——Output buffer被清空,Typematic Rate/Delay被设置成默认值。然后回复一个ACK,接着等待下一个命令。需要注意的是,这个命令被执行后,键盘的击键接受是禁止的。如果想让键盘接受击键输入,必须Enable Keyboard。, @) J. U5 J7 U: {

8 K9 l  a: @/ Q' t: E4 e" b' k8 H) E    * F6h6 p) W# x8 w# w- p  p  O

3 ?* ^; o) U, w, ^: G设置默认状态。和F5命令唯一不同的是,当此命令被执行之后,键盘的击键接收是允许的。
( q! A9 d5 f/ a
- ~) ^2 h9 V1 K* \    * FEh8 v$ r2 k* ]8 M0 `
$ Y& w/ i7 E# T# z/ b0 W  E; r
Resend。如果Keyboard收到此命令,则必须将刚才发送到8042 Output Register中的数据重新发送一遍。当系统检测到一个来自于Keyboard的错误之后,可以使用自命令让Keyboard重新发送刚才发送的字节。
0 b& t3 N. A9 }0 q
# ?* c5 N1 G1 V9 C3 Q    * FFh
9 S# e- l4 ]% g2 g5 J- R  J# Z4 C' A* l' D
Reset Keyboard。如果Keyboard收到此命令,则首先回复一个ACK,然后启动自身的Reset程序,并进行自身基本正确性检测(BAT-Basic Assurance Test)。等这一切结束之后,将返回给系统一个单字节的结束码(AAh=Success, FCh=Failed),并将键盘的Scan code set设置为2。
回复

使用道具 举报

发表于 2009-1-14 13:49:16 | 显示全部楼层
好贴!
( @' x& [3 f/ E8 Q+ X# B非常详细!1 s/ R: ~1 T# u! n; S# `
谢谢!
回复

使用道具 举报

发表于 2009-2-25 17:37:28 | 显示全部楼层
2楼好帖!在helppc的Hardware Data and Specifications栏里有相应的寄存器和命令详细描述。9 D( r8 X: d& f$ k- O( a* [
/ b; b% Q( A  ~" R8 u. ~
我的问题是,上述描述应该是针对老的8042的,在目前的使用EC的系统中,这些status register和command描述在哪个文档中可以找到?比如intel的santarosa,使用renessas的H8s 2104 EC,按道理上述状态寄存器,命令等的描述应该在2104 datasheet里,但是我怎么找都没有。还是有某个spec定义了这些命令格式?新手问题,高手莫笑
回复

使用道具 举报

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

本版积分规则

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

GMT+8, 2025-6-16 12:30 , Processed in 0.055244 second(s), 17 queries .

Powered by Discuz! X3.5

© 2001-2023 Discuz! Team.

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