返回

UEFI开发探索14 – 访问PCI/PCI-E设备2

闲谈

前言

在上一篇博客中,我们已经介绍了如何访问PCI设备。在本篇博客中,我们将继续深入探讨这一主题,并介绍如何理解PCI设备,以及在X86平台下访问PCIe设备的基本原理。

PCI设备的理解

要访问PCI设备,首先需要了解PCI设备的结构和工作原理。PCI设备通常由以下几个部分组成:

  • PCI设备ID :用于标识PCI设备的唯一标识符。
  • PCI地址 :用于寻址PCI设备的地址。
  • PCI配置空间 :用于配置PCI设备的寄存器集。
  • PCI中断线 :用于处理PCI设备中断的线路。
  • PCI总线 :用于连接PCI设备的总线。

访问PCIe设备

在X86平台下,访问PCIe设备与访问PCI设备类似。然而,由于PCIe设备是一种高速设备,因此在访问PCIe设备时需要考虑一些特殊因素。

  • PCIe设备的配置空间 :PCIe设备的配置空间与PCI设备的配置空间类似,但PCIe设备的配置空间更大。
  • PCIe设备的中断线 :PCIe设备的中断线与PCI设备的中断线类似,但PCIe设备的中断线更多。
  • PCIe总线 :PCIe总线与PCI总线类似,但PCIe总线的速度更快。

访问PCI/PCI-E设备的示例代码

为了帮助您理解如何访问PCI/PCI-E设备,我们提供了一个示例代码。该示例代码演示了如何访问PCI/PCI-E设备的配置空间和中断线。

#include <efi.h>
#include <uefi/pi/pi.h>
#include <uefi/pi/pci.h>

EFI_STATUS
EFIAPI
UefiMain(
  IN EFI_HANDLE        ImageHandle,
  IN EFI_SYSTEM_TABLE  *SystemTable
  )
{
  EFI_STATUS                Status;
  EFI_HANDLE                PciRootHandle;
  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL  *PciRootBridgeIo;
  EFI_PCI_IO_PROTOCOL       *PciIo;
  UINT64                    PciAddress;
  UINT8                     Data;

  // 获取PCI根桥接IO协议
  Status = SystemTable->BootServices->LocateProtocol(
    &gEfiPciRootBridgeIoProtocolGuid,
    NULL,
    (VOID **)&PciRootBridgeIo
  );
  if (EFI_ERROR(Status)) {
    return Status;
  }

  // 获取PCI IO协议
  Status = PciRootBridgeIo->GetVirtualDeviceIo(
    PciRootBridgeIo,
    EFI_PCI_IO_PROTOCOL_PCI_ROOT_BRIDGES_IO,
    &PciIo
  );
  if (EFI_ERROR(Status)) {
    return Status;
  }

  // 获取PCI设备地址
  Status = PciIo->GetLocation(
    PciIo,
    &PciAddress
  );
  if (EFI_ERROR(Status)) {
    return Status;
  }

  // 读取PCI设备配置空间
  Status = PciIo->Pci.Read(
    PciIo,
    EfiPciWidthUint8,
    0,
    1,
    &Data
  );
  if (EFI_ERROR(Status)) {
    return Status;
  }

  // 打印PCI设备配置空间
  Print(L"PCI设备配置空间:%x\n", Data);

  // 获取PCI设备中断线
  Status = PciIo->GetInterruptLine(
    PciIo,
    &Data
  );
  if (EFI_ERROR(Status)) {
    return Status;
  }

  // 打印PCI设备中断线
  Print(L"PCI设备中断线:%d\n", Data);

  return EFI_SUCCESS;
}

结语

本文介绍了如何理解PCI设备,以及如何在X86平台下访问PCIe设备的基本原理。我们还提供了一个示例代码,演示了如何访问PCI/PCI-E设备的配置空间和中断线。希望本文对您有所帮助。