1.新建内核模块工程
在 module_init函数中调用pci初始化函数。
2.pci初始化函数
lspci -xxx
1.使用pcis命令查看当前设备的设备厂商,ID等信息,如下图:
2. 使用 lspci -vvv 查看设备更多信息
3.使用 lspci -xxx 可以查看pci配置寄存器值,如下图
每个pci设备的配置寄存器值都会显示出来,具体寄存器对应值参照pci标准如下图:
Vendor ID,Device ID:标记了一个设备的生产厂商和具体的设备,比如Intel的设备Vendor ID通常是0x8086,Device ID就需要厂家自定义了。
Revision ID 和Class Code 寄存器:该组寄存器只读,其中Reversion ID 寄存器记载PCI 设备的版本号,该寄存器可以认为是Deveice ID 寄存器的扩展,而Class Code 寄存器记载了PCI设备的分类。
Status:设备状态字,具体每个BIT的意义见下图
Command:设备状态字:
Base Address Registers:决定PCI/PCIe设备空间映射到系统空间具体位置的寄存器,映射方式有两种,分别是IO(IO为x86平台特有,arm,mips等没有IO)和Memory映射,一个设备最多可以有6个基址空间:
配置空间中的 capability Pointer 是扩展信息地址,这个寄存器的是可选的,但是PCI-X 和PCIe必须支持这个寄存器。
结构如下,每个capability都有一个唯一的ID号,每个capability都有一个指针指向下一个capability,行成链表。
Interrupt Line 寄存器:该寄存器是系统软件对pci设备进行配置时写入的,记录当前PCI设备使用的中断向量号,设备驱动程序可以通过这个寄存器,判断当前PCI设备使用处理器系统中的那个中断向量号。
Interrupt pin 寄存器 :该寄存器保存PCI设备使用的中断引脚。PCI总线提供了四个中断引脚:INTA,INTB,INTC,INTD,1表示使用INTA,2表示INTB,3表示INTC,4表示INTD。
下图是初始化函数
在初始化函数中声明pci驱动,PCI_DRV_CB与 PCI_DRV_HANDEL 是SylixOS封装好的结构体,首先需要填充支持设备表,设备表结构体定义如下
实例:
注册完成设备支持列表后,需要注册探测函数 PCIDRV_pfuncDevProbe,系统会在发现设备表中对应的设备时调用相应的probe函数。进入到pro函数后获取基地址和中断号,并可以probe中注册其他字符驱动,块设备驱动,网卡驱动等等。
在SylixOS中可以直接调用相应的API将获得的物理基地址映射为虚拟地址,如下图
在获取到基地址后就可以像正常的驱动一样 操作寄存器,完成相应的驱动。如果需要使用中断,SylixOS支持INTx和MSI中断两种,通过API_pciDevMsiEnableSet函数来控制当前使用哪种中断,当MSI中断使能后系统会自动禁用INTX中断。
在使用INTX中断时一个设备最多只能有一个中断号,通过系统函数获取中断号,如下图:
使用MSI中断时使用API_PciDevMsiRangeEnable申请一段连续的中断,但是不一定会成功,需要检测是否申请到足够的中断。在PCIe设备必须支持MSI,MSI 使用了MSI capability 结构体来实现中断请求,PCI设备在提交MSI中断请求时总是向这种Capability结构体中的Message Address 的地址写Message Data ,从而组成一个寄存器写TLP。MSI capability 结构体如下图
MSI capability 有几种类型根据位数和mask进行区分, 当capability ID为05 表示是MSI的ID号,
实例:
通过查看配置空间当前capability pointer 值为50,也就是扩展空间地址为50,50位置对应的capability ID是05 ,说明设备支持MSI中断。
Message control :该字段存放当前设备使用MSI机制进行中断请求的状态与控制信息。
Message Address/message Upoer Address:存放目的地址
Message Data:用来存放MSI 报文使用的数据。
Mask Bits:一个PCIe设备使用的MSI机制时,最多可以使用32个中断,对应到这里的32位。BIT置1表示屏蔽中断。
pending Bits : 该字段对于系统软件只读,也是32位,对应到可用的32个中断。
当Mask Bits 字段的相应位为1时。如果PCIe设备需要发送对应的中断请求,Pending Bits 字段对应位将被PCIe设备的内部逻辑置为1,此时PCIe设备并不会使用MSI报文向中断控制寄存器提交请求,但是系统软件将Mask bits字段的相应位从1改写为0时,PCIe设备将发送MSI 报文向出来提交中断请求,同时将Pending Bits 字段对应的内容清零。
在使用MSI时向系统申请一段连续中断向量后,需要获取申请的中断向量首个向量号,并将中断向量号绑定中断函数。在申请MSI成功后系统会自动将MSI控制块中对用的MSI信息进行填充
通过MSI获得中断数量,首个中断号,然后把中断号依次使用API_PciDevInterConnect函数进行中断函数绑定。
3.pci设备卸载
通过注册时使用的驱动名称查找对用的PCI句柄,找到后调用 API_PciDrvDevDel 函数删除,API_PciDrvDevDel会调用在pci初始化时注册好的PCIDRV_pfuncDevRemove 。
在Remove函数中做相应的删除处理