当前位置: 首页 > news >正文

jsp做物流网站佛山做网站推广的公司

jsp做物流网站,佛山做网站推广的公司,网站建设服务发票费率,邯郸有建网站的吗一、支持访问PCI/PCIE设备的Protocol UEFI中提供了两个主要的模块来支持PCI总线,一是PCI Host Bridge(PCI主桥)控制器驱动,另一个是PCI总线驱动。这两个模块是和特定的平台硬件绑定的,在这种机制下,屏蔽了…

一、支持访问PCI/PCIE设备的Protocol

UEFI中提供了两个主要的模块来支持PCI总线,一是PCI Host Bridge(PCI主桥)控制器驱动,另一个是PCI总线驱动。这两个模块是和特定的平台硬件绑定的,在这种机制下,屏蔽了不同的CPU架构差异,为软件开发者提供了比较一致的Protocol接口。

UEFI标准中提供了两类访问PCI/PCIE设备的Protocol——EFI_PCI_ROOT_BRIDGE_IO_PROTOCOLEFI_PCI_IO_PROTOCOL。前者为PCI根桥提供了抽象的IO功能,它由PCI Host Bus Controller(PCI主总线驱动器)产生,一般由PCI/PCIe总线驱动用来枚举设备、获得Option ROM、分配PCI设备资源等;后者由PCI/PCIE总线驱动为PCI/PCIE设备产生,一般由PCI/PCIE设备驱动用来访问PCI/PCIE设备的IO空间、Memory空间和配置空间。

1.1 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL

EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL提供了基本的内存、输入/输出(I/O)、PCI配置和直接访问内存的接口,这些接口用于将PCI控制器后面的PCI根桥控制器的访问进行抽象。

typedef struct _EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL;
/// Provides the basic Memory, I/O, PCI configuration, and DMA interfaces that are
/// used to abstract accesses to PCI controllers behind a PCI Root Bridge Controller.
///提供了基本内存,I/O,PCI配置和直接内存访问(DMA)接口,这些接口用于抽象PCI控制器后PCI根桥的访问
struct _EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL {////// The EFI_HANDLE of the PCI Host Bridge of which this PCI Root Bridge is a member./// 这是PCI根桥所属的PCI主机桥的EFI_HANDLEEFI_HANDLE                                         ParentHandle; //包含这个PCI根桥的PCI主机桥的HandleEFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_POLL_IO_MEM        PollMem; //一个函数指针,指向用于轮询内存映射I/O空间的协议方法EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_POLL_IO_MEM        PollIo; //一个函数指针,指向用于轮询I/O空间的协议的方法EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_ACCESS             Mem; //一个函数指针,指向用于访问内存的协议方法EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_ACCESS             Io; //一个函数指针,指向用于访问I/O空间的协议方法EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_ACCESS             Pci; //一个函数指针,指向用于访问PCI配置空间的协议方法EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_COPY_MEM           CopyMem; //一个函数指针,指向用于复制内存的协议方法EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_MAP                Map; //一个函数指针,指向用于映射内存或I/O空间的协议方法EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_UNMAP              Unmap; //一个函数指针,指向用于取消映射内存或I/O空间的协议方法EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_ALLOCATE_BUFFER    AllocateBuffer; //一个函数指针,用于指向分配内存缓冲区的协议方法EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_FREE_BUFFER        FreeBuffer; //一个函数指针,指向释放内存缓冲区的协议方法EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_FLUSH              Flush; //一个函数指针,指向用于刷新缓存的协议方法EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_GET_ATTRIBUTES     GetAttributes; //一个函数指针,指向用于获取PCI根桥属性的协议方法EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_SET_ATTRIBUTES     SetAttributes; //一个函数指针,指向用于设置PCI根桥属性的协议方法EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_CONFIGURATION      Configuration; //一个函数指针,指向配置PCI根桥的协议方法////// The segment number that this PCI root bridge resides. PCI根桥所在的段号///UINT32                                             SegmentNumber;
};

在这里只介绍访问内存的接口Mem、访问I/O空间的接口Io、访问PCI配置空间的接口Pci。这三个接口的参数类型是一样的,都是EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_ACCESS

typedef struct {/// Read PCI controller registers in the PCI root bridge memory space./// 读数据EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_IO_MEM    Read;/// Write PCI controller registers in the PCI root bridge memory space./// 写数据EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_IO_MEM    Write;
} EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_ACCESS;typedef
EFI_STATUS
(EFIAPI *EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_IO_MEM)(IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL              *This, //指向protocol实例IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH    Width, //标识内存操作的宽度,一般有8位、16位、32位、64位几种IN     UINT64                                   Address, //内存操作的基地址IN     UINTN                                    Count, //读写的数据个数,以width为单位IN OUT VOID                                     *Buffer);

其中,参数Adress在访问I/O空间、内存空间、配置空间时是不一样的,

对于配置空间,Address由BDF地址和Register偏移决定,与一般使用宏EFI_PCI_ADDRESS来组合BDF和Register偏移,在EDK2中,宏定义如下:

#define EFI_PCI_ADDRESS(bus, dev, func, reg) \(UINT64) ( \(((UINTN) bus) << 24) | \(((UINTN) dev) << 16) | \(((UINTN) func) << 8) | \(((UINTN) (reg)) < 256 ? ((UINTN) (reg)) : (UINT64) (LShiftU64 ((UINT64) (reg), 32))))

对于IO空间而言,参数Address是指PCI设备IO空间的IO地址;

对于Memory空间而言,参数Address是指PCI设备Memory空间的Memory地址。

它们是由BAR和偏移量决定的 。

1.2  EFI_PCI_IO_PROTOCOL

在PCI/PCIE设备驱动中,一般使用EFI_PCI_IO_PROTOCOL来访问设备的内部资源,Protocol挂载在PCI/PCIE控制器上,运行在EFI启动环境中,对PCI/PCIE设备进行Memory空间和I/O空间访问。

/// Global ID for the PCI I/O Protocol
///
#define EFI_PCI_IO_PROTOCOL_GUID \{ \0x4cf5b200, 0x68b8, 0x4ca5, {0x9e, 0xec, 0xb2, 0x3e, 0x3f, 0x50, 0x2, 0x9a } \}typedef struct _EFI_PCI_IO_PROTOCOL EFI_PCI_IO_PROTOCOL;

 EFI_PCI_IO_PROTOCOL的接口如下:

///
/// The EFI_PCI_IO_PROTOCOL provides the basic Memory, I/O, PCI configuration,
/// and DMA interfaces used to abstract accesses to PCI controllers.
/// There is one EFI_PCI_IO_PROTOCOL instance for each PCI controller on a PCI bus.
/// A device driver that wishes to manage a PCI controller in a system will have to
/// retrieve the EFI_PCI_IO_PROTOCOL instance that is associated with the PCI controller.
///
struct _EFI_PCI_IO_PROTOCOL {EFI_PCI_IO_PROTOCOL_POLL_IO_MEM           PollMem;EFI_PCI_IO_PROTOCOL_POLL_IO_MEM           PollIo;EFI_PCI_IO_PROTOCOL_ACCESS                Mem;EFI_PCI_IO_PROTOCOL_ACCESS                Io;EFI_PCI_IO_PROTOCOL_CONFIG_ACCESS         Pci;EFI_PCI_IO_PROTOCOL_COPY_MEM              CopyMem;EFI_PCI_IO_PROTOCOL_MAP                   Map;EFI_PCI_IO_PROTOCOL_UNMAP                 Unmap;EFI_PCI_IO_PROTOCOL_ALLOCATE_BUFFER       AllocateBuffer;EFI_PCI_IO_PROTOCOL_FREE_BUFFER           FreeBuffer;EFI_PCI_IO_PROTOCOL_FLUSH                 Flush;EFI_PCI_IO_PROTOCOL_GET_LOCATION          GetLocation;EFI_PCI_IO_PROTOCOL_ATTRIBUTES            Attributes;EFI_PCI_IO_PROTOCOL_GET_BAR_ATTRIBUTES    GetBarAttributes;EFI_PCI_IO_PROTOCOL_SET_BAR_ATTRIBUTES    SetBarAttributes;////// The size, in bytes, of the ROM image.///UINT64                                    RomSize;////// A pointer to the in memory copy of the ROM image. The PCI Bus Driver is responsible/// for allocating memory for the ROM image, and copying the contents of the ROM to memory./// The contents of this buffer are either from the PCI option ROM that can be accessed/// through the ROM BAR of the PCI controller, or it is from a platform-specific location./// The Attributes() function can be used to determine from which of these two sources/// the RomImage buffer was initialized.///VOID    *RomImage;
};

【注!!!】在这里需要注意的是EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL的实例,在大部分办公用的个人电脑中只存在一个,因此直接用全局指针变量gPCIRootBridgeIO存储;而EFI_PCI_IO_PROTOCOL的实例存在多个,一般有多少个PCI/PCIE设备,就存在多少个实例,因此使用全局指针数组gPCIIOArray[256]来存储这些实例。

二、访问PCI/PCIE设备的简单实现

2.1 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL遍历PCI设备

在使用EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL获取PCI/PCIE设备的时,首先需要获取EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL的所有句柄,获取句柄可以利用gBS->LocateHandleBuffer()函数,当获取到句柄后,利用gBS->HandleProtocol()函数获取到protocol实例,然后就可以调用其中的函数接口了。利用BDF找到某个设备,读取设备的配置空间。

PCI设备的配置空间用结构体PCI_TYPE00表示,其代码原型为:

/// PCI Device Configuration Spacetypedef struct {PCI_DEVICE_INDEPENDENT_REGION    Hdr;PCI_DEVICE_HEADER_TYPE_REGION    Device;
} PCI_TYPE00;

其中Hdr表示PCI配置空间的通用头部区域,其包括的字段:

// Common header region in PCI Configuration Spacetypedef struct {UINT16    VendorId;UINT16    DeviceId;UINT16    Command;UINT16    Status;UINT8     RevisionID;UINT8     ClassCode[3];UINT8     CacheLineSize;UINT8     LatencyTimer;UINT8     HeaderType;UINT8     BIST;
} PCI_DEVICE_INDEPENDENT_REGION;

 Device表示PCI设备配置空间中的头部区域

/// PCI Device header region in PCI Configuration Spacetypedef struct {UINT32    Bar[6];UINT32    CISPtr;UINT16    SubsystemVendorID;UINT16    SubsystemID;UINT32    ExpansionRomBar;UINT8     CapabilityPtr;UINT8     Reserved1[3];UINT32    Reserved2;UINT8     InterruptLine;UINT8     InterruptPin;UINT8     MinGnt;UINT8     MaxLat;
} PCI_DEVICE_HEADER_TYPE_REGION;

利用EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL来访问PCIe设备的应用简单实现:

编写MyPCIEProtocol.c代码:

#include <Uefi.h>
#include <Library/UefiBootServicesTableLib.h>
#include <Library/ShellCEntryLib.h>
#include <Library/DebugLib.h>#include <Protocol/PciIo.h>
#include <Protocol/PciRootBridgeIo.h>
#include <IndustryStandard/Pci.h>EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *gPciRootBridgeIo; //创建一个EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL类型的指针变量EFI_STATUS LocatePciRootBridgeIo(void); //函数声明,告诉编译器函数名称、返回值类型、参数类型;如果函数定义在函数调用之后,那么在函数调用之前必须进行函数声明//函数声明
EFI_STATUS PciDevicePresent(IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL * PciRootBridgeIo,OUT PCI_TYPE00 * Pci,IN UINT8 Bus,IN UINT8 Device,IN UINT8 Func);EFI_STATUS ListPciInformation(void); //函数声明EFI_STATUS
EFIAPI
UefiMain (IN EFI_HANDLE        ImageHandle,IN EFI_SYSTEM_TABLE  *SystemTable)
{EFI_STATUS Status;Status = LocatePciRootBridgeIo(); //调用LocatePciRootBridgeIo()函数,定位根桥if(EFI_ERROR(Status)){DEBUG((DEBUG_ERROR, "[CSDN]Call LocatePciRootBridgeIo failed,Can't find protocol!\n"));}else{DEBUG((DEBUG_ERROR, "[CSDN]Call LocatePciRootBridgeIo successed,Find protocol!\n"));}//列出PCI设备的信息ListPciInformation();return EFI_SUCCESS;
}EFI_STATUS LocatePciRootBridgeIo()
{EFI_STATUS Status;EFI_HANDLE *PciHandleBuffer = NULL;UINTN      HandleIndex = 0;UINTN      HandleCount = 0;//获取 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL的所有句柄Status = gBS->LocateHandleBuffer(ByProtocol, //查找句柄的方式,这里采用返回指定协议的句柄&gEfiPciRootBridgeIoProtocolGuid, //要查找的协议的GUIDNULL,&HandleCount, //输出参数,缓冲区中返回的句柄数量&PciHandleBuffer  //输出参数,指向用于返回支持协议的请求句柄数组的缓冲区的指针。);if(EFI_ERROR(Status))  return Status; //如果没成功找到,直接结束程序//查找支持 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL句柄的protocol实例for(HandleIndex = 0; HandleIndex < HandleCount; HandleIndex++){Status = gBS->HandleProtocol(PciHandleBuffer[HandleIndex],&gEfiPciRootBridgeIoProtocolGuid,(VOID **)&gPciRootBridgeIo);if(EFI_ERROR(Status))  continue; //如果没找到就继续寻找else                   return EFI_SUCCESS; //如果找到了就退出程序//这里找到就退出的原因是大部分办公用的个人电脑中就只存在一个EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL}return Status;}EFI_STATUS ListPciInformation()
{EFI_STATUS Status = EFI_SUCCESS;PCI_TYPE00 Pci; //PCI_TYPE00是一个结构体,表示PCI的配置空间UINT16 Dev,Func,Bus,PciDevicecount = 0;DEBUG((DEBUG_ERROR, "[CSDN] PciDeviceNo\tBus\tDev\tFunc | Vendor.Device.ClassCode\n"));for(Bus=0; Bus<256; Bus++)for(Dev=0; Dev<= PCI_MAX_DEVICE; Dev++)for(Func=0; Func<=PCI_MAX_FUNC; Func++){//判断设备是否存在Status = PciDevicePresent(gPciRootBridgeIo,&Pci,(UINT8)Bus,(UINT8)Dev,(UINT8)Func);if(Status == EFI_SUCCESS){//如果找到了设备,PCI设备数量加1PciDevicecount++;//打印设备信息DEBUG((DEBUG_ERROR, "[CSDN] %d\t\t%x\t%x\t%x\t",PciDevicecount,(UINT8)Bus,(UINT8)Dev,(UINT8)Func));DEBUG((DEBUG_ERROR, "%x\t%x\t%x\n",Pci.Hdr.VendorId,Pci.Hdr.DeviceId,Pci.Hdr.ClassCode[0]));}}return EFI_SUCCESS;
}EFI_STATUS
PciDevicePresent (IN  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL     *PciRootBridgeIo,OUT PCI_TYPE00                          *Pci,IN  UINT8                               Bus,IN  UINT8                               Device,IN  UINT8                               Func)
{UINT64      Address;EFI_STATUS  Status;//// Create PCI address map in terms of Bus, Device and Func//Address = EFI_PCI_ADDRESS (Bus, Device, Func, 0);//// Read the Vendor ID register//Status = PciRootBridgeIo->Pci.Read (PciRootBridgeIo,EfiPciWidthUint32,Address,1,Pci);if (!EFI_ERROR (Status) && (Pci->Hdr).VendorId != 0xffff) { //0xffff通常标识一个无效的,未分配的VentorId,如果能读取设备信息就进行打印。//// Read the entire config header for the device//Status = PciRootBridgeIo->Pci.Read (PciRootBridgeIo,EfiPciWidthUint32,Address,sizeof (PCI_TYPE00) / sizeof (UINT32),Pci);return EFI_SUCCESS;}return EFI_NOT_FOUND;
}

 编写INF文件,并运行,运行结果为:

 

2.2 EFI_PCI_IO_PROTOCOL遍历PCI设备

使用EFI_PCI_IO_PROTOCOL遍历设备比较简单,因此为之前所得到的Protocol的实例,就是为PCI/PCIE设备产生的,实际上相当于找到了宿设备,只需要将设备的信息打印出来即可。 

#include <Uefi.h>
#include <Library/UefiBootServicesTableLib.h>
#include <Library/ShellCEntryLib.h>
#include <Library/DebugLib.h>#include <Protocol/PciIo.h>
#include <Protocol/PciRootBridgeIo.h>
#include <IndustryStandard/Pci.h>EFI_PCI_IO_PROTOCOL *gPciIoArray[256];
UINTN gPciIoCount = 0;
EFI_STATUS LocatePciIo(void);EFI_STATUS ListPciInformation(void);EFI_STATUS
EFIAPI
UefiMain (IN EFI_HANDLE        ImageHandle,IN EFI_SYSTEM_TABLE  *SystemTable)
{EFI_STATUS Status;Status = LocatePciIo();if(EFI_ERROR(Status)){DEBUG((DEBUG_ERROR, "[CSDN]Call LocatePciIo failed,Can't find protocol!\n"));}else{DEBUG((DEBUG_ERROR, "[CSDN]Call LocatePciIo successed,Find protocol!\n"));}ListPciInformation();return EFI_SUCCESS;
}EFI_STATUS LocatePciIo()
{EFI_STATUS Status;EFI_HANDLE *PciHandleBuffer = NULL;UINTN      HandleIndex = 0;UINTN      HandleCount = 0;Status = gBS->LocateHandleBuffer(ByProtocol,&gEfiPciIoProtocolGuid,NULL,&HandleCount,&PciHandleBuffer );if(EFI_ERROR(Status))  return Status;gPciIoCount = HandleCount;DEBUG((DEBUG_ERROR, "[CSDN] the number of PCIn devices is %d", HandleCount));for(HandleIndex = 0; HandleIndex < HandleCount; HandleIndex++){Status = gBS->HandleProtocol(PciHandleBuffer[HandleIndex],&gEfiPciIoProtocolGuid,(VOID **)&(gPciIoArray[HandleIndex]));}return Status;}EFI_STATUS ListPciInformation()
{UINTN i, count = 0;PCI_TYPE00 Pci;DEBUG((DEBUG_ERROR, "[CSDN] PciDeviceNo VendorID DeviceID ClassCode\n"));for (i = 0; i < gPciIoCount;i++){gPciIoArray[i]->Pci.Read(gPciIoArray[i],EfiPciIoWidthUint32,0,sizeof(Pci)/sizeof(PCI_TYPE00),&Pci);++count;DEBUG((DEBUG_ERROR, "[CSDN] %d\t\t%x\t%x\t%x\n", count, Pci.Hdr.VendorId, Pci.Hdr.DeviceId, Pci.Hdr.ClassCode[0]));}return EFI_SUCCESS;
}

 运行结果如下,发现读到的Class Code[0]的数据不一样,不知道为什么?

 

http://www.dinnco.com/news/26877.html

相关文章:

  • 淘客网站做单品类免费的行情网站
  • 上海it培训机构seo网站优化方法
  • 微信菜单怎么做微网站凡科建站模板
  • 免费商城网站建设搜索引擎营销的特点包括
  • 网站底部悬浮代码wordpress百度营销官网
  • 杭州市下城区建设局门户网站营销模式有几种
  • 长沙做网站开发价格多少seo技术中心
  • 美国有网站建设公司吗微信营销的方法有哪些
  • 注册城乡规划师报考条件2022石家庄网站建设seo公司
  • 厦门电子商务网站建设推广普通话宣传语手抄报
  • 黄埔商城网站建设广州seo招聘
  • 惠州网站建设哪里找今日头条重大消息
  • 网站开发设计资讯如何找外包的销售团队
  • 请问门户网站是什么意思制作小程序的软件
  • 1 设计一个企业网站友链互换平台推荐
  • 建网站公司下载快手营销模式有哪些 新型
  • 常熟市建设局网站凡科建站靠谱吗
  • 海珠定制型网站建设百度大搜是什么
  • 最新军事新闻伊朗一站传媒seo优化
  • 重庆做网站seo优化选哪家好医疗器械龙头股
  • 县电子政务办网站建设工作思路做百度推广效果怎么样
  • 一级消防工程师考试题库2000题大众点评seo关键词优化
  • 广东知名网站上海全网推广
  • 能自己做效果图的网站360免费建站官网
  • 网站建设合伙人上海seo排名
  • 外贸做那种网站有哪些大地资源网在线观看免费
  • 在线旅游电商网站有哪些发布软文是什么意思
  • 网站开发常去的论坛百度做广告多少钱一天
  • 自建站服务如何推广一个产品
  • 做网站的公司没有技术新闻稿发布软文平台