PCIE那些事之linux下EP驱动实现方式二

本文探讨了PCI Express(PCIe)Endpoint(EP)设备在Linux下的驱动实现,重点在于RC侧的驱动代码原理。内容涵盖EP设备驱动架构,包括RC控制器驱动和EP设备驱动的分层结构,以及EP侧的Block图。此外,文章还分析了RC侧驱动如何进行数据地址的拷贝和DMA数据传输,并提及了`pci-endpoint-test`设备驱动在TI芯片级联中的应用,为其他平台的移植和调试提供了参考。
摘要由CSDN通过智能技术生成

EP设备驱动架构

EP设备驱动,主要运行在RC侧,用于控制总线地址上的数据传输使用, 提供给应用层接口,应用层调用此接口完成数据传输,主要的分层结构如下
RC侧包含RC控制器驱动 和EP设备驱动
EP侧包含EP控制器驱动和EP端口驱动 (无需关心,一般厂商提供)
实现的主要是EP设备驱动
在这里插入图片描述

EP侧 Block图

主要分三层 PCI控制器层、EP中间层、EP功能层
pci-epf-test.c是EP功能层驱动 以上驱动不在本文分析范围

在这里插入图片描述

RC侧驱动代码原理

主要完成数据地址的拷贝,支持DMA数据传输
在这里插入图片描述

pci-endpoint-test设备驱动

这个驱动是TI写的,用于TI芯片进行PCIE级联使用,其他的平台可以参考此驱动进行移植调试
该驱动对大家写PCIE EP的设备驱动提供了很好的帮助,它提供了一种EP框架思路,可以加快PCIE的调试流程

#include <linux/crc32.h>
#include <linux/delay.h>
#include <linux/fs.h>
#include <linux/io.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/miscdevice.h>
#include <linux/module.h>
#include <linux/mutex.h>
#include <linux/random.h>
#include <linux/slab.h>
#include <linux/pci.h>
#include <linux/pci_ids.h>

#include <linux/pci_regs.h>

#include <uapi/linux/pcitest.h>

#define DRV_MODULE_NAME			"pci-endpoint-test"

#define PCI_ENDPOINT_TEST_MAGIC		0x0

#define PCI_ENDPOINT_TEST_COMMAND	0x4
#define COMMAND_RAISE_LEGACY_IRQ	BIT(0)
#define COMMAND_RAISE_MSI_IRQ		BIT(1)
#define MSI_NUMBER_SHIFT		2
/* 6 bits for MSI number */
#define COMMAND_READ                    BIT(8)
#define COMMAND_WRITE                   BIT(9)
#define COMMAND_COPY                    BIT(10)

#define PCI_ENDPOINT_TEST_STATUS	0x8
#define STATUS_READ_SUCCESS             BIT(0)
#define STATUS_READ_FAIL                BIT(1)
#define STATUS_WRITE_SUCCESS            BIT(2)
#define STATUS_WRITE_FAIL               BIT(3)
#define STATUS_COPY_SUCCESS             BIT(4)
#define STATUS_COPY_FAIL                BIT(5)
#define STATUS_IRQ_RAISED               BIT(6)
#define STATUS_SRC_ADDR_INVALID         BIT(7)
#define STATUS_DST_ADDR_INVALID         BIT(8)

#define PCI_ENDPOINT_TEST_LOWER_SRC_ADDR	0xc
#define PCI_ENDPOINT_TEST_UPPER_SRC_ADDR	0x10

#define PCI_ENDPOINT_TEST_LOWER_DST_ADDR	0x14
#define PCI_ENDPOINT_TEST_UPPER_DST_ADDR	0x18

#define PCI_ENDPOINT_TEST_SIZE		0x1c
#define PCI_ENDPOINT_TEST_CHECKSUM	0x20

static DEFINE_IDA(pci_endpoint_test_ida);

#define to_endpoint_test(priv) container_of((priv), struct pci_endpoint_test, \
					    miscdev)

static bool no_msi;
module_param(no_msi, bool, 0444);
MODULE_PARM_DESC(no_msi, "Disable MSI interrupt in pci_endpoint_test");

enum pci_barno {
   
	BAR_0,
	BAR_1,
	BAR_2,
	BAR_3,
	BAR_4,
	BAR_5,
};

struct pci_endpoint_test {
   
	struct pci_dev	*pdev;
	void __iomem	*base;
	void __iomem	*bar[6];
	struct completion irq_raised;
	int		last_irq;
	/* mutex to protect the ioctls */
	struct mutex	mutex;
	struct miscdevice miscdev;
	enum pci_barno test_reg_bar;
	size_t alignment;
};

struct pci_endpoint_test_data {
   
	enum pci_barno test_reg_bar;
	size_t alignment;
	bool no_msi;
};

static inline u32 pci_endpoint_test_readl(struct pci_endpoint_test *test,
					  u32 offset)
{
   
	return readl(test->base + offset);
}

static inline void pci_endpoint_test_writel(struct pci_endpoint_test *test,
					    u32 offset, u32 value)
{
   
	writel(value, test->base + offset);
}

static inline u32 pci_endpoint_test_bar_readl(struct pci_endpoint_test 
  • 2
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值