USB键盘背后的那些事儿--Legacy USB实现 .

来自: http://blog.csdn.net/prostar/article/details/4088521

 

最近晚上闲来无事,决定写几篇技术文章和大家共享一下。关于议题,我想了很久,觉得还是重点写些大家平时接触不到,或者说不容易在其他地方见到的一些概念吧。这样可以一方面开拓大家的知识面,另一方面我也想打破目前BIOS技术过于封闭的局面。现在的BIOS业界的确是过于封闭了,有句话说的不错:在我们这个行业,就那么几个人,大家在不同的公司跳来跳去……原因就在这个行业技术上过于封闭。不是BIOS从业的工程师,很难自学BIOS编程的。

 

于是呼,我第一篇就选择了谈谈Legacy USB。

 

 

1. Legacy USB是什么?

 

USB我们每天都在用,那么什么又是Leacgy USB呢?随便Google一下,网上什么说法都有,但是很少有说对的。大多数朋友都知道这是一个主板BIOS上的选项,并且几乎都设置成了Enable,但是在问及这个东东到底是干什么的时候,就基本上没人知道了。很多朋友误认为这是USB 1.1支持选项。这是完全错误的,任何一项技术都应该默认做到backward compatibility(向后兼容),如果USB因为升级到2.0就不再支持大量的1.1设备,那么我想估计就没人用USB了。

 

所以Legacy USB不是USB 1.1支持选项!那么它到底是干什么用的呢?我们不妨来做个实验,现在就重启你的电脑,进入BIOS,将这一项设置成Disable,然后进DOS,接着试试你的USB键盘,看看现在还能不能用呢?或者不进DOS,我们对WinXP来一次非正常关机,然后重启,OS应该会出现一个菜单,接着读秒,提示非正常关机,按任意键继续这样的话,这个时候按下你的USB键盘,看看这个任意键能否被OS识别呢?答案势必是不行。不过在读秒完成后,进入OS,我们的USB键盘又活了。呵呵

 

所谓的Legacy USB是在传统的环境下,对USB设置(主要是USB键盘,鼠标)提供支持的选项。所谓的传统的环境,是指DOS,或者那些直接去访问8042兼容键盘控制器的程序,或者那些使用BIOS调用INT 9H来取键盘响应的程序。这样的程序一般都比较老,但是在某些场合他们仍然在起作用,况且在OS起来之前,几乎100%都是Legacy USB的应用场合。

 

那么为什么会有这个问题呢?说起来就远了,大家只要大致明白就可。之前在USB设备出来之前,尤其是USB键盘出来之前,人们并没有想象到未来的某一天还会有个USB键盘这个东西,那个时候我们的PC比较老实,键盘的工业标准是8042,同时访问8042的编程标准则是两个I/O端口,60H和64H。

 

本文不想变成又一篇描述如何控制8042的启蒙文章,大家只要知道,过去我们一直是通过访问上述两个端口来给8042发一些指令,如读键盘缓冲区,打开/关闭键盘上的LED灯,来进行等等这样的类似的操作。而8042也可以被配置成轮询或者中断模式,在中断模式下,如果键盘缓冲区里有足够多的键,那么8042产生一个中断,接着一个键盘驱动就会取走这些键,然后处理。

 

一切都那么完美?不是吗?很不幸,当我们的USB键盘出现后,这一切都不是那么完美了。USB键盘并不归8042管辖,当然也不可能使用60/64来通信。这可把那些过去直接使用60/64的程序幽了一默。这些直接访问8042的程序无法对USB键盘的按键做出任何响应。更重要的是,DOS也这么干。一般来说,当你新安装一个设备,如果不能使用,你会想到:啊,那我安装它的驱动啊!的确是这样,但是对于键盘这样一个设备来说,很难想象如果它不能使用还能否安装驱动(也许用户根本无法操作计算机)。换言之,用户希望对自己原来的程序不加修改,就能直接使用USB键盘。

 

为了保护用户投资,我们必须找到一个方法,使得那些老的系统,老的程序能够能够在不认识USB键盘的条件下,仍然能够使用USB键盘/鼠标。

 

我仍然记得,在我刚刚入行的时候,我的老板对我说道:你知道吗?在PC里,什么设备最难编程?是小小的键盘!我当时十分不解,一个小小的键盘怎么会最难呢?后来我惊讶的发现,Legacy USB竟然是各家BIOS Vendor竞争的一个焦点所在。谁能提供这个支持,谁就能竞争占据有利地位。那都是因为这个技术太难。

 

从一个高层程序员的角度,他可能永远都不明白为什么这个问题如此困难。将两完全不一样的硬件做到软件兼容,的确有些难度。不,是很有难度。

 

2. Legacy USB:实现

 

那么如何实现呢?问的好!答案是模拟。既然系统可以认识PS/2,那么我们就把USB设备模拟成PS/2设备好了。但是如何模拟呢?

 

我们必须能够截获所有的USB中断,然后判断这个中断是不是一个来自键盘/鼠标的数据传输中断。如果是的话,读取USB键盘/鼠标里的数据,之后判断一下是不是一个新按的键,如果是,把这个键译码成PS/2使用的Scan code Set 2.然后把这个键写到8042缓冲区里去,换言之,目前我们模拟了一次PS/2键盘按键。如果按键缓冲区满,模拟程序还必须主动触发一个IRQ1以便叫那些访问60端口的程序能够工作。

 

以上就是Legacy USB的大致实现,实际的实现要复杂的多,而且这必须被实现成SMI,一旦涉及到SMI,那么事情将变得特别复杂。光是想想SMI能够在内存里搬来搬去就令人头晕N次了。

 

 

请问如何模拟触发IRQ1呢?没有8042的时候,可以实现触发IRQ1吗?To wj0225:本来俺不打算在这写个普通大众的文章里过多的涉及底层的实现,不过既然你问到啦,我就说说看 :)实现legacy usb,现在有很多时候系统不带8042了。。尤其是那些legacy free的系统。Intel的ICH可以用软件触发IRQ1/12。方法大致是TCObase 10H有个寄存器叫SW_IRQ_GEN(某些文档,主要是BWG上,这个寄存器也叫LEGACY_ELIM)。这个寄存器就干这个的。以ICH9为例,查阅ICH9 EDS,(这个文档过去是RS的,现在是public的,所以我可以说说它的内容了)Bit Description7:2 Reserved1 IRQ12_CAUSE — R/W. When software sets this bit to 1, IRQ12 will be asserted. Whensoftware sets this bit to 0, IRQ12 will be deasserted.0 IRQ1_CAUSE — R/W. When software sets this bit to 1, IRQ1 will be asserted. Whensoftware sets this bit to 0, IRQ1 will be deasserted.

 

你可能感兴趣的:(Legacy,USB)