Cstyle的UEFI导读之USB Driver Stack

来源:互联网 发布:淘宝女旗袍配的皮鞋 编辑:程序博客网 时间:2024/06/11 02:47
    说完了PCI driver再来看下USB,跟PCI一样USB driver也分为三个层次:USB host controller driver,USB bus driver,USB device driver。

USB host controller driver:Consumes PCI I/O Protocol on the USB host controller handle and produces the USB2  Host Controller Protocol.
USB bus driver:Consumes the USB2 Host Controller Protocol and produces a child handle for each USB controller  on the USB bus. Installs the Device Path Protocol and USB I/O Protocol onto each child handle.
USB device driver:Consumes the USB I/O Protocol and produces an I/O abstraction that provides services for the console devices and boot devices required to boot an EFI-conformant operating system.

下图是一个示例,一个pci总线下挂了一个USB host controller,usb host controller下挂了三个设备,键盘鼠标,和usb存储设备(ext . U盘),三种不同的driver消费和生产protocol的情况。
各种USB相关的protocol 数据类型定义:
 

USB Host Controller Driver:
根据控制器的实现标准不同,USB控制器大概分为4类,他们遵循UEFI driver modle消费EFI_PCI_IO_PROTOCOL并生产EFI_USB2_HC_PROTOCOL,在udk/MdeModulePkg/Bus/Pci/...中有他们的实现实例:
• Open Host Controller Interface (OHCI) (USB 1.0 and USB 1.1)
• Universal Host Controller Interface (UHCI) (USB 1.0 and USB 1.1)
• Enhanced Host Controller Interface (EHCI) (USB 2.0)
• Extended Host Controller Interface (XHCI) (USB 3.0)

USB Host Controller Driver Binding Protocol: Supported()
和其他的driver一样它会先locate由pci bus driver 产生的pci io protocol然后使用其提供的服务去access设备的pci配置空间,读取vid/did/class code看driver是否能够认识到该设备。

USB Host Controller Driver Binding Protocol: Start()
使用EFI_OPEN_PROTOCOL_BY_DRIVER参数去locate pci io protocol最终会install EFI_USB2_HC_PROTOCOL。

USB Host Controller Driver Binding Protocol: Stop()

EFI_USB2_HC_PROTOCOL实现:
上图可知,该protocol提供的服务大体分为4类:
• Host controller general information
• GetCapability()
• Root hub–related services(硬件相关):
• GetRootHubPortStatus()
• SetRootHubPortFeature()
• ClearRootHubPortFeature()
• Host controller state–related services(硬件相关):
• GetState()
• SetState()
• Reset()
• USB transfer–related services:
• ControlTransfer() --同步传输
• BulkTransfer() --同步传输
• AsyncInterruptTransfer()-异步传输
• SyncInterruptTransfer() --同步传输
• IsochronousTransfer() --同步传输
• AsyncIsochronousTransfer()-异步传输

Synchronous transfer:
    以BulkTransfer为例通常会有以下几个步骤:
1.Preparation:做一些传输前的准备工作,比如清状态寄存器。
2.Setting up the DMA direction:根据地址信息,设置DMI传输的方向,map  PCI DMA 操作,设定PCI bus master的读或写操作。
3.Building the transfer context:根据usb规范建立数据传输帧结构。
4.Executing the TD and getting the result:对准备好的数据进行传输,等待传输结束,返回传输结果,状态
5.Cleaning up:清除帧缓冲,unmap  PCI DMA 操作.

Asynchronous transfer:
    异步传输通常会用到periodic timer event,USB Host Controller Driver通常会为所有的异步传输任务维护一个队列。每当timer event 被signaled的时候,evernt的callback服务会去检索任务队列看异步传输任务是否完成。如果状态显示还没完成,哪么他就什么都不做;如果状态显示完成了,USB host controller driver就会把接收到的数据拷贝到一个预先定义的缓冲区当中,并删除帧缓冲。在此之后还会调用transfer callback服务,USB host controller driver根据transfer complete status来决定下一步的动作(update the transfer data status accordingly/leave the error recovery work to the related USB device driver);

USB Bus Driver:
    USB bus deriver 是一个通用的总线驱动,他管理着所有的USB hub devices包括root hub,USB hub devices是不需要usb device driver的.它消费EFI_USB2_HC_PROTOCOL并生产EFI_DEVICE_PATH_PROTOCOL和EFI_USB_IO_PROTOCOL一般我们不建议修改它。如果要移植到新平台的话,一般我们只需要修改USB host controller driver,如果有新的设备接入到usb hub上的时候,我们可能还需要修改USB Device Drivers。

USB Device Driver:
    它是一个遵循UEFI driver modle的driver,消费EFI_USB_IO_PROTOCOL生产一个活多个对设备I/O抽象的protocol,但是他不控制usb hub。参考实现:
• USB Keyboard: MdeModulePkg/Bus/Usb/UsbKbDxe
• USB Mouse: MdeModulePkg/Bus/Usb/UsbMouseDxe
• USB Mouse: MdeModulePkg/Bus/Usb/UsbMouseAbsolutePointerDxe
• USB Mass Storage: MdeModulePkg/Bus/Usb/UsbMassStorageDxe

USB Device Driver Driver Binding Protocol Supported():
    driver遵循UEFI driver modle,和所有的其他的driver一样,driver binding protocol是不能少的,在supported()服务里面会检测该driver是否能够管理传递进来的controller handle,当然首先还是要去locateEFI_USB_IO_PROTOCOL,然后使用它提供的各种服务来访问设备。跟pci设备驱动类似一般分为两步如下:

1.先看看传递进来的controller handle是否有installEFI_USB_IO_PROTOCOL ,如果没有的话就表示这个不是一个usb设备。
2.使用locate的efi usb io protocol去获取usb的接口描述符(interface descriptor),然后确认设备的InterfaceClass, InterfaceSubClass以及InterfaceProtocol,类似于检查pci设备的vid,did一样。同时由于supported服务会被调用很多次,为了优化性能避免每次都要去获取设备的接口描述符,在usb bus driver里面可以先记录下设备的信息,避免重复读取操作。 

下面以一个存储设备为例来说明start和stop服务,设备的基本配置如下:它配有4个端点 1 xcontrol endpoint/ 1xinterrupt endpoint(同步)/ 2 xbulk endpoints(一个输入一个输出)如下图是该设备的私有建模或者说是私有数据结构(之前有博文有讲过):

USB Device Driver Driver Binding Protocol Start():
实现这个服务一般有以下几个步骤:
1.在传入的 ControllerHandle上使用 EFI_OPEN_PROTOCOL_BY_DRIVER locate并打开 USB I/O Protocol。
2.和supported服务一样使用EFI_USB_IO_PROTOCOL.UsbGetInterfaceDescriptor()获取端点接口描述符
3.准备设备的私有数据结构的初始化,如上图中分配内存,初始化Signature,usbio,InterfaceDescriptor。
4.使用第二步中我们获取的段的接口描述符来检测和初始化InterfaceDescriptor字段。
5.最后我们要Install Block I/O protocol.

USB Device Driver Driver Binding Protocol Stop():
完成和start()相反的动作,uninstall Block I/O Protocol,close USB I/O Protocol,并释放私有数据的内存空间。

USB就暂时先说到这里,具体细节需要结合code去仔细研究,以后有时间再补上。


转载请注明出处Cstyle.z.zhou@gmail.com//http://blog.csdn.net/CStyle_0x007
原创粉丝点击