概括来讲,设备驱动程序的任务是为特定设备提供统一的接口,同时隐藏特定于设备实现的细节。
例如,两种不同的以太网驱动程序都允许客户端使用完全相同的 C 语言函数向接口发送数据包。每个驱动程序都负责通过让客户端接口完全相同的方式管理自己的硬件,即使硬件不同也是如此。
请注意,驱动程序提供的接口可能是“中间”接口,也就是说,它们不一定代表链中的“最终”设备。
假设使用的是基于 PCI 的以太网设备。 首先,需要一个基础 PCI 驱动程序,该驱动程序了解如何与 PCI 总线本身进行通信。此驱动程序对以太网一无所知,但知道如何处理机器上的特定 PCI 芯片组。
它会枚举该总线上的设备,从每台设备上的各种寄存器收集信息,并提供允许其客户端(例如基于 PCI 的以太网驱动程序)执行 PCI 操作(例如分配中断或 DMA 通道)的功能。
因此,该基础 PCI 驱动程序为以太网驱动程序提供服务,使以太网驱动程序能够管理其关联硬件。
同时,其他设备(例如显卡)也可以采用类似的方式使用基本 PCI 驱动程序来管理其硬件。
Fuchsia 模型
为了提供最大的灵活性,Fuchsia 中的驱动程序可以绑定到匹配的“父”设备,并发布自己的“子”。这种层次结构可以根据需要进行扩展:一个驱动程序可以发布一个子项,只是为了让另一个驱动程序将该子项视为其父项,第二个驱动程序发布自己的子项,依此类推。
为了解其工作原理,我们参考基于 PCI 的以太网示例。
系统首先提供特殊的“PCI 根”父项。实际上,意思是“我知道此系统上有 PCI 总线,当您找到它时,请在此处绑定它。”
系统会评估驱动程序(搜索目录),匹配的驱动程序会自动绑定。
在这种情况下,系统会找到并绑定绑定到“PCI 根”父级的驱动程序。
这是基本 PCI 驱动程序。 它的作用是配置 PCI 总线,并枚举总线上的外围设备。
PCI 总线具有特定的外围设备标识惯例:供应商 ID (VID) 和设备 ID (DID) 的组合可以唯一标识所有可能的 PCI 设备。在枚举期间,系统会从外围设备读取这些值,并发布包含检测到的 VID 和 DID(以及大量其他信息)的新父节点。
每次发布新设备时,系统都会重复上述(针对初始 PCI 根设备出版物)所述的过程;也就是说,系统会评估驱动程序,以搜索与新父级的特性匹配的驱动程序。
对于 PCI 根设备,我们要搜索的是与某种功能(称为“协议”,我们很快会介绍)匹配的驱动程序;但在这种情况下,我们要搜索的是匹配不同协议的驱动程序,即满足“是 PCI 设备且具有给定 VID 和 DID”要求的驱动程序。
如果找到合适的驱动程序(与所需协议、VID 和 DID 匹配的驱动程序),则会将其绑定到父级。
在绑定过程中,我们会初始化驱动程序,这涉及到设置卡以便执行操作、启动接口以及发布此设备的一个或多个子项等操作。对于 PCI 以太网驱动程序,它将发布“以太网”接口,该接口符合另一种协议,称为“以太网实现”协议。此协议代表了接近客户端所用函数的通用协议(但移除了一步,我们会再次提及)。