平台总线

简介

平台总线指代码在//fuchsia/src/devices/bus/drivers/platform/中的Fuchsia驱动。 尽管这个术语同样指在Fuchsia中管理底层驱动的框架。但是在本文档中,平台总线驱动指特定驱动,平台总线指代通用框架。

平台总线总体包含以下几种类型的驱动:

  • 平台总线驱动,用来管理平台总线。这是一种没有特定硬件功能的通用驱动。平台总线驱动通过系统启动时驱动管理来完成自动启动。
  • 板卡驱动,是平台总线驱动加载的第一个驱动。板卡驱动包含所有平台总线需要的平台特定信息和其他平台总线加载的驱动控制。 在 arm64 平台上,平台总线驱动使用 bootloader 或 boot shim 中的信息来为所运行的平台绑定正确的板卡驱动。 在 x86 平台上,平台总线驱动总是加载 x86 板卡驱动并且基于 ACPI 中的信息创建平台设备。
  • 平台设备驱动是 Fuchsia 中高层驱动的基础。这些驱动提供了特定功能的最底层支持,例如 USB , eMMC 或者 NAND 存储等,用于高层驱动加载。
  • 协议实现驱动是提供板卡驱动所需协议的驱动。一个通用示例为 GPIO 驱动,板卡驱动经常用于引脚混用功能。在过去平台总线曾经也将这些驱动的协议代理给平台设备,但是现在我们使用复合设备来代替。 久而久之,我们可能逐步淘汰平台总线中的协议实现驱动使用,并用一种新的方法来取代它,这种方法不需要阻塞来等待驱动加载。
  • 最后,平台代理驱动是一个平台总线驱动的配套设备,可载入平台设备驱动主机。这个驱动支持从平台设备驱动到平台总线驱动和协议实现驱动中的代理平台设备协议和其他资源协议,之所以这样做,是因为平台设备驱动运行在与平台总线驱动程序和协议实现不同的驱动主机进程中。

Fuchsia Platform Bus diagram Source: https://goto.google.com/zircon-platform-bus-diagram

平台总线初始化

平台总线驱动在启动时由驱动管理自动启动。因为平台总线驱动是一个不包含平台运行信息的通用驱动,它首先加载处理平台特殊逻辑的板卡驱动。为了决定哪个驱动被加载,平台总线驱动读取从 bootloader 传递的 ZBI data中的ZBI_TYPE_PLATFORM_ID。然后使用协议 ZX_PROTOCOL_PBUSBIND_PLATFORM_DEV_VIDBIND_PLATFORM_DEV_PID绑定从平台数据记录中设置变量 vid 和 did 来添加设备。正确的板卡驱动将绑定该设备然后继续平台总线初始化进程。在 x86 平台上, x86 板卡驱动自动加载。

板卡驱动使用平台总线协议来和平台总线驱动通信。当它完成自身初始化后,板卡驱动使用 ProtocolDeviceAdd()调用到平台总线协议加载协议实现驱动。在协议实现驱动加载后,它必须通过调用平台总线 RegisterProtocol() API 注册协议到平台总线驱动中。 RegisterProtocol()将阻塞直到驱动调用RegisterProtocol(),所以板卡驱动必须从它自己的线程中调用RegisterProtocol(),而不是从例如Bind()的回调中。

当协议设备被添加后,板卡驱动将在平台总线协议中调用DeviceAdd() 来创建平台设备,这将导致平台设备驱动依次加载到它自己的驱动主机中。 平台设备创建后,平台总线初始化就算完成了。

复合平台设备

平台总线同样支持添加平台设备作为一个复合设备中的组件来使用。平台总线CompositeDeviceAdd() 接口为添加一个复合设备,它的第零位组件是一个提供的 PBusDev 结构体描述的平台设备。对于剩余组件的绑定规则由components参数来提供。coresident_device_index被用于明确复合设备应当被创建在哪一个驱动主机中。UINT32_MAX 的值将导致为复合设备创建一个新的驱动主机,当值从1到n时,将添加复合设备到其他组件的驱动主机中。传递0是不允许的,因为我们不希望复合设备被添加到平台总线驱动主机中。

复合平台设备内部是结构与非复合情况有些不同。不使用平台代理驱动,而使用驱动管理组件组件代理驱动代替使用平台代理驱动。例如在上述框架图中我们有一个音频驱动的复合设备,以平台设备作为它第一个组件, I2C 通道作为其第二个组件的复合设备。 在一个新的驱动主机中启动音频驱动,驱动管理器组件和组件代理驱动负责代理音频驱动的 PDEV 和 I2C 协议。

平台设备协议

平台设备协议ZX_PROTOCOL_PDEV)是平台总线对平台设备驱动提供的主要协议。这个协议提供对资源例如平台设备驱动 MMIO ,中断,BTIs 和 SMC 的访问。这些资源通过基于0的指针请求,而不是通过物理地址或者 IRQ 数请求 MMIOs 和中断。这使我们能够为特定的 IP 提供多种平台的平台设备驱动,因为确切的 MMIO 地址和中断号不需要由驱动程序知道。取而代之的是,板卡驱动使用接口AddDevice()传递PbusDev结构体来配置 MMIO 地址和 IRQ 数。

平台总线协议

平台总线协议ZX_PROTOCOL_PBUS)用于板卡驱动和协议实现驱动来和平台总线驱动通信。仅对运行在平台总线驱动主机上的驱动有效(特别的是它不能被平台设备驱动访问)。这个协议的目的在于对板卡驱动来加载协议实现驱动和启动平台设备驱动。它同样也用于协议实现驱动来使用平台总线注册它们的协议,让平台设备驱动可使用。