SylixOS PCIe设备驱动开发杂项
1. 参考驱动代码
在SylixOS内核中,有一些PCIe设备驱动代码可以参考,具体的路径在libsylixos/SylixOS/driver/pci下:
其中null下是PCIe设备驱动的模板,sio下是PCIe串口驱动,storage下是sata和nvme设备驱动。
2. VxWorks设备驱动移植
有些客户以前的项目中使用的是VxWorks下的PCIe设备驱动,这些驱动可能是直接读写设备的配置空间来获取BAR地址等信息,并没有使用什么系统提供的驱动框架,这类驱动移植到SylixOS下时就需要使用设备配置空间读写接口来替换VxWorks下的接口。
一般这类设备驱动肯定是事先知道了设备的厂商ID和设备ID,然后我们就可以使用API_PciFindDev 接口来获取设备对应的BDF信息:
int vendorid, deviceid; int bus, dev, func; vendorid = 0x1013; deviceid = 0x00b8; API_PciFindDev(vendorid, deviceid, 0, &bus, &dev, &func);
然后使用API_PciConfigInDword 这类接口直接读写设备的配置空间寄存器:
unsigned int value; API_PciConfigInDword(bus, dev, func, PCI_BASE_ADDRESS_0, &value);
比如上面的PCI_BASE_ADDRESS_0就表示第一个BAR空间寄存器,注意这里读取出来的是BAR寄存器中的原始值,不能直接拿来使用,因为BAR寄存器低4位表示BAR的属性,我们需要将读出来的值低4位清零才表示MEM、IO空间等基址,一个设备BAR空间有多大一般也都提前知道了,这样就可以直接映射为虚拟地址进行访问:
API_PciConfigInDword(bus, dev, func, PCI_BASE_ADDRESS_0, &value); value &= ~0xf; vaddr = API_PciDevIoRemap(value, 4 * 1024 * 1024);
附源码
pci_driver_demo6.c源码:
#define __SYLIXOS_KERNEL #define __SYLIXOS_PCI_DRV #include <SylixOS.h> #include <module.h> #include <string.h> #include <stdio.h> #include <stdlib.h> #include <linux/compat.h> #include <system/device/pci/pciBus.h> #include <system/device/pci/pciMsi.h> #include <system/device/pci/pciLib.h> #include <system/device/pci/pciIds.h> #include <system/device/pci/pciDev.h> int module_init (void) { int vendorid, deviceid; int bus, dev, func; unsigned int value; void *vaddr; vendorid = 0x1013; deviceid = 0x00b8; API_PciFindDev(vendorid, deviceid, 0, &bus, &dev, &func); API_PciConfigInDword(bus, dev, func, PCI_BASE_ADDRESS_0, &value); value &= ~0xf; vaddr = API_PciDevIoRemap(value, 4 * 1024 * 1024); return 0; } void module_exit (void) { printk("hello_module exit!\n"); }
评论