主板的键盘有一块专用的接口芯片,一般是采用一块单片微处理器8042(现在大多已集成在南桥或SIO里)。它控制整个键盘的工作,包括加电自检、键盘扫描码的缓冲以及与主板的通讯。
+ V+ b }( A9 y7 D' a7 Q# Y o! n: S4 i8 K% y* ~' G9 U
6 a% p0 [8 A0 q0 o9 B* x0 N
两个重要的中断: 计匠网论坛" L; }+ _. d1 y9 a" ?* o
INT 09H是H/W中断,对应IRQ1,INT 16H是一个S/W中断。当键盘的一个键被按下时,键盘接口芯片根据被按下的位置,INT 09H负责把键值转换成INT16H认识的值,返回给INT 16H。INT 16H再把该值根据OS所选定的不同语系键盘而转换成相应的二进制字符传给OS或应用程序。当用户敲击键盘速度过快,使主CPU来不及处理时,则先将所键入的内容送往住存储器的键盘缓冲区,等CPU能处理时,便从缓冲区中取出,送入CPU进行分析和执行。一般在PC机的内存中安排了大约20个字符的键盘缓冲区。 , O0 I. K3 n2 O4 i# a& z
主板的键盘有一块专用的接口芯片,一般是采用一块单片微处理器8042(现在大多已集成在南桥或SIO里)。它控制整个键盘的工作,包括加电自检、键盘扫描码的缓冲以及与主板的通讯。 D) f, C# Z% t# I
计匠网论坛, D2 M+ N0 c5 P N
(Award Code ,In file ATORGS.ASM, INT 09h( KBDINT_VECT JMP KBC_INT<at AKBRD.ASM> ) and INT 16h(KBD_VECT JMP keyboard) ) www.ufoit.com% J; F" ^& B2 f% L! ^2 y
7 \4 J& w6 z. f! A+ n# R计匠网论坛对缓冲和命令的处理: , t- I3 k$ r" V; u7 k/ Y
' z; r7 e1 g: o! ?' w
8042分输入缓冲和输出缓冲,它的数据传输在I/O口60H和64H进行。基本上,I/O 64H是命令和状态口,I/O 60H是数据口,它们同时可做读写动作,在读和写时有着不同的意义。I/O 64H的bit 0、1置位分别代表输出/输入缓冲满。如果发现输入缓冲满(即判断出I/O 64H[1]=1),要从I/O 60H将数据读完。BIOS在自检时如果确定输入/输出缓冲都没有问题,会发“AAH”给I/O 64H,让它自测试。等到输入缓冲空(说明上一个命令已执行完),输出缓冲满(KB控制器对自测试命令有反应),再读I/O 60H是否为“55H”(IBM PC/AT规范)。如果是,则表示KB没有问题,若等不到输出缓冲满,说明有问题。
* ?3 t% U! Z/ e6 Y' L $ K0 B5 N5 w, b' ^% q3 X4 J7 r$ w/ Z
在写命令之前,必须对I/O 64H口送一个60H的值,并等到输入缓冲空,再操作I/O 60H。同样,在读状态之前,也必须对I/O 64H口送一个20H的值,并等到输出缓冲满(表示有状态输出),再操作I/O 60H。这时,我们可以把64H看作索引口,而60H看作数据口。
- X" T4 ^% R. s" ? 3 \% y2 X! l% b) r$ ]+ Q
A20地址线的切换: * o; I2 D- h3 u |
; t! ~0 E* l5 H2 N
键盘接口芯片除了接受来自键盘的信息外,还要负责A20地址线的切换,因为当CPU从实模式切换到保护模式时便是通过A20地址线的切换完成的。平常A20为“0”时,CPU工作于DOS的实模式;当A20切换为“1”时,便可进入保护模式。但由于键盘接口芯片切换A20地址线的速度不够快,目前多由主板上的芯片组以模拟方式取代,这样也就省去了一块键盘接口芯片。 & Y+ W& S& T" g! ~
8042 端口的操作:
) H& u5 [" J; ^' y1 }; ]: U2 _www.ufoit.com通过8042芯片,可以:
: m' h/ F* j# s$ c2 y; D2 B9 v1 L2 a计匠网论坛 1. 向8042芯片发布命令(通过64h),并通过60h读取命令的返回结果(如果有的话),或通过60h端口写入命令所需的数据(如果需要的话)。
) ? _8 t$ L! ~* @ m6 ]# ~2 `4 W0 o 2.读取Status Register的内容(通过64h);
. Q e) q5 \* w% S, O 3.向8048发布命令(通过60h);
& I6 r' |6 I' ~! R1 I1 b 4.读取来自于Keyboard的数据(通过60h)。这些数据包括Scan Code(由按键和释放键引起的),对8048发送的命令的确认字节(ACK)及回复数据。 & x5 ] z i. {- D$ P [
再次强调一遍,Command(命令)分为发送给8042芯片的命令和发送给8048的命令。它们是不相同的,并且使用的端口也是不相同的(分别为64h和60h)。
5 y0 U' u1 x4 W- ]7 ~4 P 0 W s( Z- l: [5 z
: r- L# G5 F! U3 J
64h端口(读操作) 8 }1 X" L; E8 y. I1 J
对64h端口进行读操作,会读取Status Register的内容。
4 }# Y C! q/ J/ `3 g X. t0 Hwww.ufoit.com in al, 0x64 计匠网论坛" z( @" P/ A8 } A4 V) O! o+ o
执行这个指令之后,AL寄存器中存放的就是Status Register的内容。
; ^* A, j/ `3 l
1 F+ W# }7 Y2 B7 l( ]www.ufoit.com64h端口(写操作) ; ?* {) h8 r& _9 N1 K
向64h端口写入的字节,被认为是对8042芯片发布的命令(Command): 写入的字节将会被存放在Input Register中; 同时会引起Status Register的Bit-3自动被设置为1,表示现在放在Input Register中的数据是一个Command,而不是一个Data; www.ufoit.com- a: E' v$ Q0 \
计匠网论坛8 G% Z, n% F. G* F
在向64h端口写某些命令之前必须确保键盘是被禁止的,因为这些被写入的命令的返回结果将会放到Output Register中,而键盘如果不被禁止,则也会将数据放入到Output Register中,会引起相互之间的数据覆盖; 9 J; |9 l0 @; H. S* g
在向64h端口写数据之前必须确保Input Register是空的(通过判断Status Register的Bit-1是否为0)。 " {/ }9 l: p' t G2 _
计匠网论坛/ A% W- C a' `
60h端口(读操作)
6 M, Q4 X6 `7 v6 C5 c' y1 C+ u 对60h端口进行读操作,将会读取Output Register的内容。Output Register的内容可能是: . 来自于8048的数据。这些数据包括Scan Code,对8048发送的命令的确认字节(ACK)及回复数据。 . 通过64h端口对8042发布的命令的返回结果。 www.ufoit.com: j: v: u1 c3 ]/ o
在向60h端口读取数据之前必须确保Output Register中有数据(通过判断Status Register的Bit-0是否为1)。 ( ?) N$ M5 U$ C0 |
60h端口(写操作) % b9 N5 \# B' I# s2 I7 L( s) ^- e
向60h端口写入的字节,有两种可能: 1.如果之前通过64h端口向8042芯片发布的命令需要进一步的数据,则此时写入的字节就被认为是数据; 2.否则,此字节被认为是发送给8048的命令。 在向60h端口写数据之前,必须确保Input Register是空的(通过判断Status Register的Bit-1是否为0)。
+ V+ b }( A9 y7 D' a7 Q# Y o! n: S4 i8 K% y* ~' G9 U
6 a% p0 [8 A0 q0 o9 B* x0 N
两个重要的中断: 计匠网论坛" L; }+ _. d1 y9 a" ?* o
INT 09H是H/W中断,对应IRQ1,INT 16H是一个S/W中断。当键盘的一个键被按下时,键盘接口芯片根据被按下的位置,INT 09H负责把键值转换成INT16H认识的值,返回给INT 16H。INT 16H再把该值根据OS所选定的不同语系键盘而转换成相应的二进制字符传给OS或应用程序。当用户敲击键盘速度过快,使主CPU来不及处理时,则先将所键入的内容送往住存储器的键盘缓冲区,等CPU能处理时,便从缓冲区中取出,送入CPU进行分析和执行。一般在PC机的内存中安排了大约20个字符的键盘缓冲区。 , O0 I. K3 n2 O4 i# a& z
主板的键盘有一块专用的接口芯片,一般是采用一块单片微处理器8042(现在大多已集成在南桥或SIO里)。它控制整个键盘的工作,包括加电自检、键盘扫描码的缓冲以及与主板的通讯。 D) f, C# Z% t# I
计匠网论坛, D2 M+ N0 c5 P N
(Award Code ,In file ATORGS.ASM, INT 09h( KBDINT_VECT JMP KBC_INT<at AKBRD.ASM> ) and INT 16h(KBD_VECT JMP keyboard) ) www.ufoit.com% J; F" ^& B2 f% L! ^2 y
7 \4 J& w6 z. f! A+ n# R计匠网论坛对缓冲和命令的处理: , t- I3 k$ r" V; u7 k/ Y
' z; r7 e1 g: o! ?' w
8042分输入缓冲和输出缓冲,它的数据传输在I/O口60H和64H进行。基本上,I/O 64H是命令和状态口,I/O 60H是数据口,它们同时可做读写动作,在读和写时有着不同的意义。I/O 64H的bit 0、1置位分别代表输出/输入缓冲满。如果发现输入缓冲满(即判断出I/O 64H[1]=1),要从I/O 60H将数据读完。BIOS在自检时如果确定输入/输出缓冲都没有问题,会发“AAH”给I/O 64H,让它自测试。等到输入缓冲空(说明上一个命令已执行完),输出缓冲满(KB控制器对自测试命令有反应),再读I/O 60H是否为“55H”(IBM PC/AT规范)。如果是,则表示KB没有问题,若等不到输出缓冲满,说明有问题。
* ?3 t% U! Z/ e6 Y' L $ K0 B5 N5 w, b' ^% q3 X4 J7 r$ w/ Z
在写命令之前,必须对I/O 64H口送一个60H的值,并等到输入缓冲空,再操作I/O 60H。同样,在读状态之前,也必须对I/O 64H口送一个20H的值,并等到输出缓冲满(表示有状态输出),再操作I/O 60H。这时,我们可以把64H看作索引口,而60H看作数据口。
- X" T4 ^% R. s" ? 3 \% y2 X! l% b) r$ ]+ Q
A20地址线的切换: * o; I2 D- h3 u |
; t! ~0 E* l5 H2 N
键盘接口芯片除了接受来自键盘的信息外,还要负责A20地址线的切换,因为当CPU从实模式切换到保护模式时便是通过A20地址线的切换完成的。平常A20为“0”时,CPU工作于DOS的实模式;当A20切换为“1”时,便可进入保护模式。但由于键盘接口芯片切换A20地址线的速度不够快,目前多由主板上的芯片组以模拟方式取代,这样也就省去了一块键盘接口芯片。 & Y+ W& S& T" g! ~
8042 端口的操作:
) H& u5 [" J; ^' y1 }; ]: U2 _www.ufoit.com通过8042芯片,可以:
: m' h/ F* j# s$ c2 y; D2 B9 v1 L2 a计匠网论坛 1. 向8042芯片发布命令(通过64h),并通过60h读取命令的返回结果(如果有的话),或通过60h端口写入命令所需的数据(如果需要的话)。
) ? _8 t$ L! ~* @ m6 ]# ~2 `4 W0 o 2.读取Status Register的内容(通过64h);
. Q e) q5 \* w% S, O 3.向8048发布命令(通过60h);
& I6 r' |6 I' ~! R1 I1 b 4.读取来自于Keyboard的数据(通过60h)。这些数据包括Scan Code(由按键和释放键引起的),对8048发送的命令的确认字节(ACK)及回复数据。 & x5 ] z i. {- D$ P [
再次强调一遍,Command(命令)分为发送给8042芯片的命令和发送给8048的命令。它们是不相同的,并且使用的端口也是不相同的(分别为64h和60h)。
5 y0 U' u1 x4 W- ]7 ~4 P 0 W s( Z- l: [5 z
: r- L# G5 F! U3 J
64h端口(读操作) 8 }1 X" L; E8 y. I1 J
对64h端口进行读操作,会读取Status Register的内容。
4 }# Y C! q/ J/ `3 g X. t0 Hwww.ufoit.com in al, 0x64 计匠网论坛" z( @" P/ A8 } A4 V) O! o+ o
执行这个指令之后,AL寄存器中存放的就是Status Register的内容。
; ^* A, j/ `3 l
1 F+ W# }7 Y2 B7 l( ]www.ufoit.com64h端口(写操作) ; ?* {) h8 r& _9 N1 K
向64h端口写入的字节,被认为是对8042芯片发布的命令(Command): 写入的字节将会被存放在Input Register中; 同时会引起Status Register的Bit-3自动被设置为1,表示现在放在Input Register中的数据是一个Command,而不是一个Data; www.ufoit.com- a: E' v$ Q0 \
计匠网论坛8 G% Z, n% F. G* F
在向64h端口写某些命令之前必须确保键盘是被禁止的,因为这些被写入的命令的返回结果将会放到Output Register中,而键盘如果不被禁止,则也会将数据放入到Output Register中,会引起相互之间的数据覆盖; 9 J; |9 l0 @; H. S* g
在向64h端口写数据之前必须确保Input Register是空的(通过判断Status Register的Bit-1是否为0)。 " {/ }9 l: p' t G2 _
计匠网论坛/ A% W- C a' `
60h端口(读操作)
6 M, Q4 X6 `7 v6 C5 c' y1 C+ u 对60h端口进行读操作,将会读取Output Register的内容。Output Register的内容可能是: . 来自于8048的数据。这些数据包括Scan Code,对8048发送的命令的确认字节(ACK)及回复数据。 . 通过64h端口对8042发布的命令的返回结果。 www.ufoit.com: j: v: u1 c3 ]/ o
在向60h端口读取数据之前必须确保Output Register中有数据(通过判断Status Register的Bit-0是否为1)。 ( ?) N$ M5 U$ C0 |
60h端口(写操作) % b9 N5 \# B' I# s2 I7 L( s) ^- e
向60h端口写入的字节,有两种可能: 1.如果之前通过64h端口向8042芯片发布的命令需要进一步的数据,则此时写入的字节就被认为是数据; 2.否则,此字节被认为是发送给8048的命令。 在向60h端口写数据之前,必须确保Input Register是空的(通过判断Status Register的Bit-1是否为0)。
***********************************************************************************
***********************************************************************************
B5
R_ALT E0,38 E0,B8
R_ALT E0,38 E0,B8
HOME E0,47 E0,C7
UP ARROW E0,48 E0,C8
PG UP E0,49 E0,C9
UP ARROW E0,48 E0,C8
PG UP E0,49 E0,C9
L ARROW E0,4B E0,CB
R ARROW E0,4D E0,CD
R ARROW E0,4D E0,CD
END E0,4F E0,CF
D ARROW E0,50 E0,D0
PG DN E0,51 E0,D1
INSERT E0,52 E0,D2
DELETE E0,53 E0,D3
D ARROW E0,50 E0,D0
PG DN E0,51 E0,D1
INSERT E0,52 E0,D2
DELETE E0,53 E0,D3
L GUI E0,5B E0,DB
R GUI E0,5C E0,DC
APPS E0,5D E0,DD
R GUI E0,5C E0,DC
APPS E0,5D E0,DD
PRNT SCRN E0,2A, E0,37 E0,B7, E0,AA
PAUSE E1,1D,45 E1,9D,C5 -NONE
这里说几句对驱动没有帮助的题外话,记不清是由于先有了关于 Scan Code 的值的猜测,才去按这个顺序列 Scan Code ,还是先这样列 Scan Code ,才有了关于 Scan Code 的值的猜测。总之,用这个 Make Code 的顺序,和我们现在键盘上键的布局做对照,我们大致就能猜到为什么 A 键的 Make Code 值为 0x1e,为什么 H 键的 Make Code 值为 0x23。我们拿其中的一小段举例子,A 1E,S 1F,D 20,F 21,G 22,H 23,看看键盘上 A,S,D,F,G,H 的位置吧。能感觉到些什么吧,感觉不到就算了,这个和驱动是无关的。从 Scan Code Set 1,可能还能推测出来最早的键盘的样子。以及发生在键盘上的一些变化。我们注意到 F10 和 F11,F12 的 Make Code 不是连在一起的,估计比较早的键盘只有10个功能键,而不是现在的12个功能键。从键的 Make Code 来看,有可能曾经使用的一些键,现在已经不出现在键盘上了。
还有一个值得注意的是,如果有 Make Code 为 0x60 的键,那么它的 Break Code 应该为 0x60+0x80=0xE0。那么这个键的 Break Code 将会和 表示扩展码的 0xE0 搞混。不过还好,并没有 Make Code 为 0x60 的键,所以不会发生搞混的情况。
1.4 i8042 键盘控制器
键盘驱动直接读写 i8042 芯片,通过 i8042 间接的向键盘中的 i8048 发命令。所以对于驱动来说,直接发生联系的只有 i8042 ,因此我们只介绍 i8042 ,不介绍 i8048。
象 i8042,i8048 这样的芯片,本身就是一个小的处理器,它的内部有自己的处理器,有自己的 Ram,有自己的寄存器,等等。
i8042 有 4 个 8 bits 的寄存器,他们是 Status Register(状态寄存器),Output Buffer(输出缓冲器),Input Buffer(输入缓冲器),Control Register(控制寄存器)。使用两个 IO 端口,60h 和 64h。
Status Register(状态寄存器)
状态寄存器是一个8位只读寄存器,任何时刻均可被cpu读取。其各位定义如下
Bit7: PARITY-EVEN(P_E): 从键盘获得的数据奇偶校验错误
Bit6: RCV-TMOUT(R_T): 接收超时,置1
Bit5: TRANS_TMOUT(T_T): 发送超时,置1
Bit4: KYBD_INH(K_I): 为1,键盘没有被禁止。为0,键盘被禁止。
Bit3: CMD_DATA(C_D): 为1,输入缓冲器中的内容为命令,为0,输入缓冲器中的内容为数据。
Bit2: SYS_FLAG(S_F): 系统标志,加电启动置0,自检通过后置1
Bit1: INPUT_BUF_FULL(I_B_F): 输入缓冲器满置1,i8042 取走后置0
BitO: OUT_BUF_FULL(O_B_F): 输出缓冲器满置1,CPU读取后置0
Bit6: RCV-TMOUT(R_T): 接收超时,置1
Bit5: TRANS_TMOUT(T_T): 发送超时,置1
Bit4: KYBD_INH(K_I): 为1,键盘没有被禁止。为0,键盘被禁止。
Bit3: CMD_DATA(C_D): 为1,输入缓冲器中的内容为命令,为0,输入缓冲器中的内容为数据。
Bit2: SYS_FLAG(S_F): 系统标志,加电启动置0,自检通过后置1
Bit1: INPUT_BUF_FULL(I_B_F): 输入缓冲器满置1,i8042 取走后置0
BitO: OUT_BUF_FULL(O_B_F): 输出缓冲器满置1,CPU读取后置0
Output Buffer(输出缓冲器)
输出缓冲器是一个8位只读寄存器。驱动从这个寄存器中读取数据。这些数据包括,扫描码,发往 i8042 命令的响应,间接的发往 i8048 命令的响应。
Input Buffer(输入缓冲器)
输入缓冲器是一个8位只写寄存器。缓冲驱动发来的内容。这些内容包括,发往 i8042 的命令,通过 i8042 间接发往 i8048 的命令,以及作为命令参数的数据。
Control Register(控制寄存器)
也被称作 Controller Command Byte (控制器命令字节)。其各位定义如下
Bit7: 保留,应该为0
Bit6: 将第二套扫描码翻译为第一套
Bit5: 置1,禁止鼠标
Bit4: 置1,禁止键盘
Bit3: 置1,忽略状态寄存器中的 Bit4
Bit2: 设置状态寄存器中的 Bit2
Bit1: 置1,enable 鼠标中断
BitO: 置1,enable 键盘中断
Bit6: 将第二套扫描码翻译为第一套
Bit5: 置1,禁止鼠标
Bit4: 置1,禁止键盘
Bit3: 置1,忽略状态寄存器中的 Bit4
Bit2: 设置状态寄存器中的 Bit2
Bit1: 置1,enable 鼠标中断
BitO: 置1,enable 键盘中断
2个端口 0x60,0x64
驱动中把 0x60 叫数据端口
驱动中把 0x64 叫命令端口
驱动中把 0x64 叫命令端口
1.5 命令
驱动可以直接给 i8042 发命令,可以通过 i8042 间接给 i8048 发命令。命令这部分内容直接来自 < 参考资料 [1] >。
1.5.1 发给i8042的命令
驱动对键盘控制器发送命令是通过写端口64h实现的,共有12条命令,分别为
20h
准备读取8042芯片的Command Byte;其行为是将当前8042 Command Byte的内容放置于Output Register中,下一个从60H端口的读操作将会将其读取出来。
准备读取8042芯片的Command Byte;其行为是将当前8042 Command Byte的内容放置于Output Register中,下一个从60H端口的读操作将会将其读取出来。
60h
准备写入8042芯片的Command Byte;下一个通过60h写入的字节将会被放入Command Byte。
准备写入8042芯片的Command Byte;下一个通过60h写入的字节将会被放入Command Byte。
A4h
测试一下键盘密码是否被设置;测试结果放置在Output Register,然后可以通过60h读取出来。测试结果可以有两种值:FAh=密码被设置;F1h=没有密码。
测试一下键盘密码是否被设置;测试结果放置在Output Register,然后可以通过60h读取出来。测试结果可以有两种值:FAh=密码被设置;F1h=没有密码。
A5h
设置键盘密码。其结果被按照顺序通过60h端口一个一个被放置在Input Register中。密码的最后是一个空字节(内容为0)。
设置键盘密码。其结果被按照顺序通过60h端口一个一个被放置在Input Register中。密码的最后是一个空字节(内容为0)。
A6h
让密码生效。在发布这个命令之前,必须首先使用A5h命令设置密码。
让密码生效。在发布这个命令之前,必须首先使用A5h命令设置密码。
AAh
自检。诊断结果放置在Output Register中,可以通过60h读取。55h=OK。
自检。诊断结果放置在Output Register中,可以通过60h读取。55h=OK。
ADh
禁止键盘接口。Command Byte的bit-4被设置。当此命令被发布后,Keyboard将被禁止发送数据到Output Register。
禁止键盘接口。Command Byte的bit-4被设置。当此命令被发布后,Keyboard将被禁止发送数据到Output Register。
AEh
打开键盘接口。Command Byte的bit-4被清除。当此命令被发布后,Keyboard将被允许发送数据到Output Register。
打开键盘接口。Command Byte的bit-4被清除。当此命令被发布后,Keyboard将被允许发送数据到Output Register。
C0h
准备读取Input Port。Input Port的内容被放置于Output Register中,随后可以通过60h端口读取。
准备读取Input Port。Input Port的内容被放置于Output Register中,随后可以通过60h端口读取。
D0h
准备读取Outport端口。结果被放在Output Register中,随后通过60h端口读取出来。
准备读取Outport端口。结果被放在Output Register中,随后通过60h端口读取出来。
D1h
准备写Output端口。随后通过60h端口写入的字节,会被放置在Output Port中。
准备写Output端口。随后通过60h端口写入的字节,会被放置在Output Port中。
D2h
准备写数据到Output Register中。随后通过60h写入到Input Register的字节会被放入到Output Register中,此功能被用来模拟来自于Keyboard发送的数据。如果中断被允许,则会触发一个中断。
1.5.2 发给8048的命令
共有10条命令,分别为
EDh
设置LED。Keyboard收到此命令后,一个LED设置会话开始。Keyboard首先回复一个ACK(FAh),然后等待从60h端口写入的LED设置字节,如果等到一个,则再次回复一个ACK,然后根据此字节设置LED。然后接着等待。。。直到等到一个非LED设置字节(高位被设置),此时LED设置会话结束。
设置LED。Keyboard收到此命令后,一个LED设置会话开始。Keyboard首先回复一个ACK(FAh),然后等待从60h端口写入的LED设置字节,如果等到一个,则再次回复一个ACK,然后根据此字节设置LED。然后接着等待。。。直到等到一个非LED设置字节(高位被设置),此时LED设置会话结束。
EEh
诊断Echo。此命令纯粹为了检测Keyboard是否正常,如果正常,当Keyboard收到此命令后,将会回复一个EEh字节。
诊断Echo。此命令纯粹为了检测Keyboard是否正常,如果正常,当Keyboard收到此命令后,将会回复一个EEh字节。
F0h
选择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代码所要求的。
选择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代码所要求的。
F2h
读取Keyboard ID。由于8042芯片后不仅仅能够接Keyboard。此命令是为了读取8042后所接的设备ID。设备ID为2个字节,Keyboard ID为83ABh。当键盘收到此命令后,会首先回复一个ACK,然后,将2字节的Keyboard ID一个一个回复回去。
读取Keyboard ID。由于8042芯片后不仅仅能够接Keyboard。此命令是为了读取8042后所接的设备ID。设备ID为2个字节,Keyboard ID为83ABh。当键盘收到此命令后,会首先回复一个ACK,然后,将2字节的Keyboard ID一个一个回复回去。
F3h
设置Typematic Rate/Delay。当Keyboard收到此命令后,将回复一个ACK。然后等待来自于60h的设置字节。一旦收到,将回复一个ACK,然后将Keyboard Rate/Delay设置为相应的值。
设置Typematic Rate/Delay。当Keyboard收到此命令后,将回复一个ACK。然后等待来自于60h的设置字节。一旦收到,将回复一个ACK,然后将Keyboard Rate/Delay设置为相应的值。
F4h
清理键盘的Output Buffer。一旦Keyboard收到此命令,将会将Output buffer清空,然后回复一个ACK。然后继续接受Keyboard的击键。
清理键盘的Output Buffer。一旦Keyboard收到此命令,将会将Output buffer清空,然后回复一个ACK。然后继续接受Keyboard的击键。
F5h
设置默认状态(w/Disable)。一旦Keyboard收到此命令,将会将Keyboard完全初始化成默认状态。之前所有对它的设置都将失效——Output buffer被清空,Typematic Rate/Delay被设置成默认值。然后回复一个ACK,接着等待下一个命令。需要注意的是,这个命令被执行后,键盘的击键接受是禁止的。如果想让键盘接受击键输入,必须Enable Keyboard。
设置默认状态(w/Disable)。一旦Keyboard收到此命令,将会将Keyboard完全初始化成默认状态。之前所有对它的设置都将失效——Output buffer被清空,Typematic Rate/Delay被设置成默认值。然后回复一个ACK,接着等待下一个命令。需要注意的是,这个命令被执行后,键盘的击键接受是禁止的。如果想让键盘接受击键输入,必须Enable Keyboard。
F6h
设置默认状态。和F5命令唯一不同的是,当此命令被执行之后,键盘的击键接收是允许的。
设置默认状态。和F5命令唯一不同的是,当此命令被执行之后,键盘的击键接收是允许的。
FEh
Resend。如果Keyboard收到此命令,则必须将刚才发送到8042 Output Register中的数据重新发送一遍。当系统检测到一个来自于Keyboard的错误之后,可以使用自命令让Keyboard重新发送刚才发送的字节。
Resend。如果Keyboard收到此命令,则必须将刚才发送到8042 Output Register中的数据重新发送一遍。当系统检测到一个来自于Keyboard的错误之后,可以使用自命令让Keyboard重新发送刚才发送的字节。
FFh
Reset Keyboard。如果Keyboard收到此命令,则首先回复一个ACK,然后启动自身的Reset程序,并进行自身基本正确性检测(BAT-Basic Assurance Test)。等这一切结束之后,将返回给系统一个单字节的结束码(AAh=Success, FCh=Failed),并将键盘的Scan code set设置为2。
Reset Keyboard。如果Keyboard收到此命令,则首先回复一个ACK,然后启动自身的Reset程序,并进行自身基本正确性检测(BAT-Basic Assurance Test)。等这一切结束之后,将返回给系统一个单字节的结束码(AAh=Success, FCh=Failed),并将键盘的Scan code set设置为2。
1.5.3 读到的数据
00h/FFh
当击键或释放键时检测到错误时,则在Output Bufer后放入此字节,如果Output Buffer已满,则会将Output Buffer的最后一个字节替代为此字节。使用Scan code set 1时使用00h,Scan code 2和Scan Code 3使用FFh。
AAh
BAT完成代码。如果键盘检测成功,则会将此字节发送到8042 Output Register中。
BAT完成代码。如果键盘检测成功,则会将此字节发送到8042 Output Register中。
EEh
Echo响应。Keyboard使用EEh响应从60h发来的Echo请求。
Echo响应。Keyboard使用EEh响应从60h发来的Echo请求。
F0h
在Scan code set 2和Scan code set 3中,被用作Break Code的前缀。
在Scan code set 2和Scan code set 3中,被用作Break Code的前缀。
FAh
ACK。当Keyboard任何时候收到一个来自于60h端口的合法命令或合法数据之后,都回复一个FAh。
ACK。当Keyboard任何时候收到一个来自于60h端口的合法命令或合法数据之后,都回复一个FAh。
FCh
BAT失败代码。如果键盘检测失败,则会将此字节发送到8042 Output Register中。
BAT失败代码。如果键盘检测失败,则会将此字节发送到8042 Output Register中。
FEh
Resend。当Keyboard任何时候收到一个来自于60h端口的非法命令或非法数据之后,或者数据的奇偶交验错误,都回复一个FEh,要求系统重新发送相关命令或数据。
Resend。当Keyboard任何时候收到一个来自于60h端口的非法命令或非法数据之后,或者数据的奇偶交验错误,都回复一个FEh,要求系统重新发送相关命令或数据。
83ABh
当键盘收到一个来自于60h的F2h命令之后,会依次回复83h,ABh。83AB是键盘的ID。
当键盘收到一个来自于60h的F2h命令之后,会依次回复83h,ABh。83AB是键盘的ID。
Scan code
除了上述那些特殊字节以外,剩下的都是Scan code。
除了上述那些特殊字节以外,剩下的都是Scan code。
1.6 端口操作
首先介绍一下端口的读写操作,驱动中使用函数 READ_PORT_UCHAR 进行读操作,