站台总线

简介

“平台总线”一词是指源代码位于 //fuchsia/src/devices/bus/drivers/platform/ 的特定 Fuchsia 驱动程序。不过,该术语还指管理 Fuchsia 中较低级别驱动程序的框架。在本文档中,平台总线驱动程序是指特定的驱动程序,平台总线则是指通用框架。

平台总线整体包含多种类型的驱动程序:

  • 平台总线驱动程序,用于管理平台总线。这是一个没有硬件特定功能的通用驱动程序。系统启动时,驱动程序管理器会自动启动平台总线驱动程序。

  • 开发板驱动程序,即平台总线驱动程序加载的第一个驱动程序。 板驱动程序包含平台总线所需的所有平台特定信息,并控制平台总线将加载的其他驱动程序。在 arm64 平台上,平台总线驱动程序使用引导加载程序或启动 shim 中的信息来绑定运行该平台的正确板驱动程序。在 x86 平台上,平台总线驱动程序始终会加载 x86 开发板驱动程序,并根据来自 ACPI 的信息创建平台设备。

  • 平台设备驱动程序是 Fuchsia 中更高层级驱动程序的基础。 这些驱动程序对特定功能(例如 USB、eMMC 或 NAND 存储等)提供最低级别的支持,并在其基础上加载更高级别的驱动程序。

  • 协议实现驱动程序是用于提供开发板驱动程序所需的协议的驱动程序。一种常见的示例是 GPIO 驱动程序,板驱动程序经常需要使用该驱动程序来进行引脚多路复用。过去,平台总线也会将这些驱动程序的协议代理到平台设备,但现在我们改用复合设备。随着时间的推移,我们可能会逐步停止在平台总线中使用协议实现驱动程序,并改用一种不需要阻塞以等待驱动程序加载的新方法。

  • 最后是平台代理驱动程序,它是平台总线驱动程序的配套驱动程序,可加载到平台设备驱动程序主机中。此驱动程序支持将平台设备协议和其他资源协议从平台设备驱动程序代理到平台总线驱动程序和协议实现驱动程序。之所以需要这么做,是因为平台设备驱动程序在与平台总线驱动程序和协议实现驱动程序不同的驱动程序主机进程中运行。

Fuchsia Platform Bus 示意图 来源

平台总线初始化

平台总线驱动程序由驱动程序管理器在启动时自动启动。由于平台总线驱动程序是一个通用驱动程序,不包含有关其运行所在平台的信息,因此它会首先加载板驱动程序,以处理平台专用逻辑。为了确定要加载哪个开发板驱动程序,平台总线驱动程序会从引导加载程序传递的 ZBI 数据中读取 ZBI_TYPE_PLATFORM_ID 记录。然后,它会添加协议 ZX_PROTOCOL_PBUS 的设备,其中 BIND_PLATFORM_DEV_VIDBIND_PLATFORM_DEV_PID 绑定变量设置为 vid,并且执行自平台数据记录。正确的开发板驱动程序将绑定到此设备,并继续完成平台总线初始化过程。在 x86 平台上,系统会自动加载 x86 开发板驱动程序。

开发板驱动程序使用平台总线协议与平台总线驱动程序进行通信。 完成自己的初始化后,开发板驱动程序便会使用平台总线协议中的 ProtocolDeviceAdd() 调用来加载协议实现驱动程序。协议实现驱动程序加载后,必须通过调用平台总线 RegisterProtocol() API 向平台总线驱动程序注册其协议。在驱动程序调用 RegisterProtocol() 之前,ProtocolDeviceAdd() 将一直处于阻塞状态,因此开发板驱动程序必须从自己的线程之一(而不是通过驱动程序管理器回调(如 Bind())调用 RegisterProtocol()

添加协议设备后,板驱动程序将调用平台总线协议中的 DeviceAdd() 调用来创建平台设备,这将导致平台设备驱动程序在其自己的驱动程序主机中加载每个设备。创建平台设备后,平台总线初始化完成。

复合平台设备

平台总线还支持添加平台设备,以用作复合设备中的组件。平台总线 CompositeDeviceAdd() 调用会添加一个复合设备,第零个组件是由提供的 PBusDev 结构体描述的平台设备。其余组件的绑定规则由 components 参数提供。primary_fragment 用于指定应在哪个驱动程序主机中创建复合设备。指定 NULL 会为复合设备创建新的驱动程序主机,而与一个 fragment 名称相等的有效字符串会将复合设备添加到另一个 fragment 的驱动程序主机中。不允许传递“pdev”,因为我们不希望将复合设备添加到平台总线驱动程序的驱动程序主机中。

复合平台设备的内部构件与非复合型设备略有不同。驱动程序管理器组件和组件代理驱动程序会代理平台设备协议,而不是使用平台代理驱动程序。例如,在上图中,我们有一个用于音频驱动程序的复合设备,其中平台设备作为第一个组件,I2C 通道作为其第二个组件。音频驱动程序在新的驱动程序主机中启动,驱动程序管理器组件和组件代理驱动程序负责将 PDEV 和 I2C 协议代理到音频驱动程序。

平台设备协议

平台设备协议 (ZX_PROTOCOL_PDEV) 是平台总线向平台设备驱动程序提供的主要协议。此协议可让平台设备驱动程序访问 MMIO 范围、中断、BTI 和 SMC 范围等资源。系统不会通过物理地址或 IRQ 号码请求 MMIO 和中断,而是通过从零开始的索引来请求这些资源。这样,我们就可以为特定 IP 提供适用于多个平台的平台设备驱动程序,因为驱动程序不需要知道确切的 MMIO 地址和中断编号。而是改为在通过 AddDevice() 传递的 PbusDev 结构体中配置 MMIO 地址和 IRQ 编号。

平台设备协议也适用于协议实现驱动程序。例如,GPIO 驱动程序可以使用平台设备协议访问其 MMIO 和中断。 这样就可以在不同的 SOC 变体之间共享协议实现驱动程序,在这些变体中,功能可能相同,但 MMIO 地址和中断编号可能不同。

平台总线协议

平台总线协议 (ZX_PROTOCOL_PBUS) 供板驱动程序和协议实现驱动程序用于与平台总线驱动程序进行通信。它仅适用于在平台总线的驱动程序主机中运行的驱动程序(具体而言,平台设备驱动程序无法访问它)。本协议旨在让开发板驱动程序加载协议实现驱动程序,以及启动平台设备驱动程序。协议实现驱动程序也使用该 API 向平台总线注册其协议,以便其协议可供平台设备驱动程序使用。