硬件外设通过总线(如 PCI 总线)连接到 CPU。
在启动过程中,BIOS(或等效平台启动软件)会发现连接到 PCI 总线的所有外围设备。系统会为每个外设分配资源(特别是中断矢量和配置寄存器的地址范围)。
这样做的影响是,分配给每个外围设备的实际资源在重新启动后可能有所不同。 当操作系统软件启动时,它会枚举总线并启动所有受支持设备的驱动程序。然后,驱动程序会调用 PCI 函数来获取有关其设备的配置信息,以便它们映射寄存器并绑定到中断。
基址注册
基址寄存器 (BAR) 是每个 PCI 设备上存在的配置寄存器。BIOS 是在其中存储有关设备的信息,例如分配的中断矢量和控制寄存器的地址。其他与设备有关的信息也会存储在这个文件夹中。
调用 Pci::MapMmio(),使 BAR 寄存器映射到驱动程序主机的地址空间:
#include <lib/device-protocol/pci.h>
zx_status_t Pci::MapMmio(uint32_t bar_id, uint32_t cache_policy,
std::optional<fdf::MmioBuffer>* mmio);
ddk::Pci
类是用于与 PCI 总线通信的接口驱动程序。
第一个参数 bar_id
是 BAR 寄存器编号,以 0
开头。
第二个参数 cache_policy
决定了访问的缓存政策,并可以采用以下值:
cache_policy 的值 |
含义 |
---|---|
ZX_CACHE_POLICY_CACHED |
使用硬件缓存 |
ZX_CACHE_POLICY_UNCACHED |
停用缓存 |
ZX_CACHE_POLICY_UNCACHED_DEVICE |
停用缓存,并将其视为设备内存 |
ZX_CACHE_POLICY_WRITE_COMBINING |
使用组合写入未缓存 |
请注意,ZX_CACHE_POLICY_UNCACHED_DEVICE
依赖于架构,在某些架构上实际上可能等同于 ZX_CACHE_POLICY_UNCACHED
。
最后一个参数是所创建的缓冲区的输出参数。
读取和写入内存
Pci::MapMmio() 函数返回有效结果后,您可以通过 MmioBuffer
接口访问 BAR,例如:
#include <lib/device-protocol/pci.h>
#include <lib/mmio/mmio-buffer.h>
std::optional<fdf::MmioBuffer> mmio;
zx_status_t status = pci.MapMmio(0, ZX_CACHE_POLICY_UNCACHED_DEVICE, &mmio);
if (status == ZX_OK) {
mmio.Write32(0x1234, REGISTER_X); // configure register X for deep sleep mode
}