SylixOS注册PCIe控制器驱动
PCIe驱动主要分为两大类,PCIe控制器驱动和PCIe设备驱动。PCIe控制器驱动主要负责配置空间读写方法的实现、中断号获取和BAR地址自动配置功能,设备驱动根据PCIe设备的功能不同而不同,简单的可能就是个普通的字符设备驱动,复杂的可能就是网卡、存储设备驱动等等。
在SylixOS中,使用内核PCI相关接口时需要在源文件抬头加上__SYLIXOS_KERNEL 和 __SYLIXOS_PCI_DRV 这两个宏。
#define __SYLIXOS_KERNEL #define __SYLIXOS_PCI_DRV #include <SylixOS.h>
根据驱动不同的需要可能还需要包含内核PCI相关的头文件。
#define __SYLIXOS_KERNEL #define __SYLIXOS_PCI_DRV #include <SylixOS.h> #include <system/device/pci/pciBus.h> #include <system/device/pci/pciMsi.h> #include <system/device/pci/pciLib.h>
在SylixOS中,使用 PCI_CTRL_CB 这个数据结构来表示一个PCIe控制器。
typedef struct { LW_LIST_LINE PCI_lineDevNode; /* 设备管理节点 */ INT PCI_iIndex; /* 控制器索引(当前支持单控制器) */ INT PCI_iBusMax; LW_SPINLOCK_DEFINE (PCI_slLock); /* 底层操作自旋锁 */ union { PCI_DRV_FUNCS0 *PCIF_pDrvFuncs0; PCI_DRV_FUNCS12 *PCIF_pDrvFuncs12; } f; #define PCI_pDrvFuncs0 f.PCIF_pDrvFuncs0 #define PCI_pDrvFuncs12 f.PCIF_pDrvFuncs12 #define PCI_MECHANISM_0 0 #define PCI_MECHANISM_1 1 #define PCI_MECHANISM_2 2 UINT8 PCI_ucMechanism; /* * 下面地址仅适用于 PCI_MECHANISM_1 与 PCI_MECHANISM_2 */ addr_t PCI_ulConfigAddr; addr_t PCI_ulConfigData; addr_t PCI_ulConfigBase; /* only for PCI_MECHANISM_2 */ PCI_AUTO_CB PCI_tAutoConfig; /* 用于自动配置 */ PVOID PCI_pvPriv; /* 私有数据 */ } PCI_CTRL_CB; typedef PCI_CTRL_CB *PCI_CTRL_HANDLE;
注意:目前SylixOS内核只支持单控制器,也就是控制器驱动只能注册一个PCI_CTRL_CB 数据结构,和VxWorks、Linux这类支持多控制器的系统是不一样的。
一般在驱动中定义一个全局变量来表示主控制器。
static PCI_CTRL_CB pci_host;
驱动初始化好PCI_CTRL_CB 数据结构后,使用API_PciCtrlCreate 这个接口来注册控制器驱动,这个接口函数原型为:
PCI_CTRL_HANDLE API_PciCtrlCreate(PCI_CTRL_HANDLE hCtrl);
驱动注册后,会遍历所有总线上的设备信息,这些设备信息可以通过使用pcis 和 lspci 命令来查看,关于这两个命令的使用会在后面PCIe设备驱动开发章节中详细介绍。
附源码
pci_host_driver_demo1.c源码:
#define __SYLIXOS_KERNEL #define __SYLIXOS_PCI_DRV #include <SylixOS.h> #include <module.h> #include <system/device/pci/pciBus.h> #include <system/device/pci/pciMsi.h> #include <system/device/pci/pciLib.h> static PCI_CTRL_CB pci_host; int pci_host_probe (void) { API_PciCtrlCreate(&pci_host); return 0; } int module_init (void) { pci_host_probe(); return 0; } void module_exit (void) { }
评论