Riffa学习——Linux Driver源码分析
目的
Riffa是一个基于FPGA的PCIe接口通信框架,用于解析PCIe发送的TLP包,并转换成数据流形式的读写请求,主要用于高速数据通信。相比于网上已有的如何在FPGA上使用Riffa的资料,笔者决定采用自顶向下的分析方法,先从Riffa的Linux Driver入手,分析上位机软件是如何完成数据通信的,然后再结合Verilog源码分析其行为,从另一个层面学习Riffa,在此过程也作为学习记录,也进行分享。
驱动源码
根据Riffa2.2公开的源码,下载后可以在driver/linux/riffa_driver.c文件内查看到大部分的Linux驱动。那么接下来将从Driver初始化开始,一步一步进行分析。
初始化
1 /** 2 * Called to initialize the PCI device. 3 */ 4 static int __init fpga_init(void) 5 { 6 int i; 7 int error; 8 9 for (i = 0; i < NUM_FPGAS; i++) 10 atomic_set(&used_fpgas[i], 0); 11 12 error = pci_register_driver(&fpga_driver); 13 if (error != 0) { 14 printk(KERN_ERR "riffa: pci_module_register returned %d\n", error); 15 return (error); 16 } 17 18 error = register_chrdev(MAJOR_NUM, DEVICE_NAME, &fpga_fops); 19 if (error < 0) { 20 printk(KERN_ERR "riffa: register_chrdev returned %d\n", error); 21 return (error); 22 } 23 24 #if LINUX_VERSION_CODE < KERNEL_VERSION(6, 4, 0) 25 mymodule_class = class_create(THIS_MODULE, DEVICE_NAME); 26 #else 27 mymodule_class = class_create(DEVICE_NAME); 28 #endif 29 30 if (IS_ERR(mymodule_class)) { 31 error = PTR_ERR(mymodule_class); 32 printk(KERN_ERR "riffa: class_create() returned %d\n", error); 33 return (error); 34 } 35 36 devt = MKDEV(MAJOR_NUM, 0); 37 device_create(mymodule_class, NULL, devt, "%s", DEVICE_NAME); 38 39 return 0; 40 } 41 42 /** 43 * Called to destroy the PCI device. 44 */ 45 static void __exit fpga_exit(void) 46 { 47 device_destroy(mymodule_class, devt); 48 class_destroy(mymodule_class); 49 pci_unregister_driver(&fpga_driver); 50 unregister_chrdev(MAJOR_NUM, DEVICE_NAME); 51 }