BIOS工程师手边事—Keyboard


键盘作入计算机系统中的人机交互输入设备,其重要性不言而喻。USB键盘驱动较为复杂,需要USB控制器驱动,USB总线驱动和USB键盘驱动,内容比较繁杂。以后有空再来整理这方面的内容。今天重点整理一下笔记本中的矩阵键盘相关知识。

嵌入式BIOS部分:

1,配置矩阵键盘表:

BIOS工程师手边事—Keyboard_第1张图片

查看如上图所示的矩阵键盘丝印图,对照键盘接口配置矩阵键盘表。虽然各个EC厂商代码的矩阵键盘表配置方式都不一样,但核心思想是一致的。矩阵键盘功能一般分为三部分:

(1)普通键,直接将键值填入相应RC表中,有些矩阵位置没有按键,但有IBM值,这时候也应该将其值录入,一劳永逸,避免以后因使用不同国家的键盘而重复劳动。

(2)FN功能键,按住FN键的时候,置FN标志位,和其他键组合使用。此时,该键值一般作为索引,在代码中,再写FN功能键的各个功能函数。

(3)Overlay键,该键值也是索引,按NUMLOCK键时,驱动会下命令,置NUMLOCK指示灯,我们根据灯的状态来区别所按下键是数字键功能还是做字母键功能。

注:如果OEM主板厂商不差钱,可以自已弄丝印图和键盘接口,然后丢给键盘厂商,让键盘厂商根据它们来开模。当然如果主板厂商不想这样做,买别人现成的产品,根据键盘线排键盘接口也是可以的。

2,配置寄存器

除了配置矩阵键盘表,EC与HOST端访问的“通路”也要打开。有一些相关寄存器需要配置:像键盘IBF的中断使能,SCANIN中断使能,还有Keyboard的逻辑设备初始化所牵涉的寄存器(当然,这部分也可以让系统BIOS来配置)。

一般来说,嵌入式BIOS工程师做完以上两种事,键盘的功能也就做完了。至于矩阵键盘扫描以及与HOST端的交互,不了解它们也不妨碍我们做项目,当然了解最好。当我们遇到比较棘手的问题,了解整个代码流程,对于我们快速解决问题有大大的帮助。

键盘扫描流程:

1) SCANIN中断,SCANIN有8根PIN,共亨一个中断。平时此8根PIN电平为高,一旦按下矩阵键盘,就会触发中断,此时扫描程序正式开始。

2) 扫描时间并不是固定的,我们可以用1ms,2ms也可以用5ms的时间间隔来进行一次键盘扫描。

3) 扫描按照逐列扫描进行,每次将要扫描的列置低,其他列置高。如果有检测到8个SCANIN有某个变低,就说明该列和该行有按键按下。按键被按键下,我们需要去抖,以防止有静电或其他原因导致键盘扫描被误触发。去抖过后,我们就可以将扫描到的行列交叉点记录的键盘送给相关处理函数,相关处理函数会将传过来的行数列数值变成SCANCODE第二套码值送给键盘BUFFER。

4) 键盘BUFFER传送函数会将SCANCODE SET2转换成SCANCODE SET1传给上层驱动。虽说驱动可以决定接收SET1还是SET2的码值,但我见过的驱动都要SET1,没有要SET2的。不知道有没有驱动能认SET2的?

 

系统BIOS部分:

1,解码IO资源并使能键盘逻辑设备

解码IO资源前,应该先看ISA配置空间是否支持subtractive decoding,如果支持,不需要我们做解码工作,反之,我们需要手动decoding。

如果是EC,可以自已使能键盘逻辑设备,但如果是SuperIO,我们就必须在系统BIOS中添加使能逻辑设备的代码。

使能之前,一定要先确定Base Address是2E/2F,4E/4F还是164E/164F。然后根据寄存器对来访问逻辑设备。

OutPortB(0x2E,LDN);OutPortB(0x2F,LDNNumber);

   OutPortB(0x2E,ActiveByte); OutPortB(0x2F,1);

2,支援ACPI OS加载PS2键盘驱动

为了使ACPI OS能够正常加载PS2键盘驱动,我们需要在ASL中加入PS2 Device的宣告。这样操作系统内核就在AML中找到HID为PNP0303的Device后,变会加载PS2键盘驱动。

3,确保PS2键盘驱动在EFI环境下正常挂载

作为系统BIOS工程师,首先要确保PS2驱动能够正常挂载到controller上。为此我们要确保两件事:第一,我们的驱动会被正常编译,即dsc文件有包含键盘驱动inf文件;第二,PS2键盘的DevicePath会被正常创建。对于针对Platform的BIOS工程师来说,只要这两个条件满足了,PS2键盘就能在EFI环境下正常使用。

下面我们来看下,DevicePath是如何被创建的:

在Isabus.c的IsaCreateDevice()函数中,有如下代码段:

BIOS工程师手边事—Keyboard_第2张图片

这里就是创建DevicePath的地方了。但如何创建PS2键盘的DevicePath呢?根据代码可以知道,IsaBus驱动在start时,会枚举ISA设备,并读取资源配置。

BIOS工程师手边事—Keyboard_第3张图片

据此,我们追踪DeviceEnumerate()或GetCurResource()函数的原型。

BIOS工程师手边事—Keyboard_第4张图片

让我们再来看下IsaDeviceLoopUp()的函数体:

BIOS工程师手边事—Keyboard_第5张图片


很明显, gPcatIsaAcpiDeviceList[]数组就是我们所要找寻的源头。我们只需要将PS2键盘的资源和设备ID放入这个数组就可以了。




UDK2014是这样来添加PS2键盘的DevicePath的。虽然各个BIOS厂商的做法和这个并不一样,但思路都是一样的。


那么PS2键盘驱动Start函数做了什么动作呢?

其实它主要工作就是为控制台提供一个键盘型输入设备。EFI设计有一条理念就是模块化。各个输入设备驱动都是一个模块,最终都是为控制台服务的。用户只会使用gRT->ConIn而不会使用Ps2Keyboard.c的协议。PS2键盘作为一个输入设备,要为控制台提供的主要服务主要有:Reset(),ReadKeyStroke(),WaitForKey事件以及TimerEvent事件。

1,Reset

这个函数主要处理PS2键盘的初始化,并且重置键盘相关的变量和寄存器。这些过程需要下一些PS2命令来完成,这就牵涉到4个寄存器,当然从系统BIOS的角度来说,这四个寄存器可以看成是2个IO端口。这4个寄存器如下所示:


SystemBIOS读命令步骤:

1)读Data寄存器60H(有没有这一步骤均可,严谨说来应该需要)

2)读Status寄存器64H,OBF=1执行3,否则等待,超时退出

3)读Data寄存器60H

SystemBIOS写命令步骤:

1) 读Status寄存器64H,IBF=0执行2,否则等待,超时退出

2) 写Command寄存器64H

 

这些命令主要有:

#defineKEYBOARD_8042_COMMAND_READ                          0x20

#defineKEYBOARD_8042_COMMAND_WRITE                         0x60

#defineKEYBOARD_8042_COMMAND_DISABLE_MOUSE_INTERFACE       0xA7

#defineKEYBOARD_8042_COMMAND_ENABLE_MOUSE_INTERFACE        0xA8

#defineKEYBOARD_8042_COMMAND_CONTROLLER_SELF_TEST          0xAA

#defineKEYBOARD_8042_COMMAND_KEYBOARD_INTERFACE_SELF_TEST  0xAB

#defineKEYBOARD_8042_COMMAND_DISABLE_KEYBOARD_INTERFACE    0xAD

 

#defineKEYBOARD_8048_COMMAND_CLEAR_OUTPUT_DATA             0xF4

#defineKEYBOARD_8048_COMMAND_RESET                         0xFF

#defineKEYBOARD_8048_COMMAND_SELECT_SCAN_CODE_SET          0xF0

以及0xED,设置LED的命令

 

如果这些命令检测没有通过,这个设备就无法在EFI Console环境下使用。这个阶段一般不会出问题。我曾遇到VxWorks下使用WindML库,PS2键盘无法使用的问题,经过调试,我去掉一个Command检测就好了(键盘firmware并不一定每个command都回应)。所以为了兼容更多的键盘,这些命令保留最基本的就好,不需要用太多。

 

2,TimerEvent事件

这个事件一般设置为20ms一次。把读到的PS2 Set1 scancode转成EFI所认识的UnicodeChar。


*****马太福音25章25节:凡有的,还要加给他,叫他有余。没有的,连他所有的,也要夺过来*****

你可能感兴趣的:(BIOS)