PCIe-块设备驱动-Single DMA




/*
 * kernel: 4.5.2
 */

#include <linux/module.h>
#include <linux/pci.h>
#include <linux/blkdev.h>
#include <linux/kthread.h>
#include <linux/interrupt.h>	// needed in 4.3.3

#define TEST_PCIE_DEV_NAME "test_pcie"
//#define PCI_VENDOR_ID_XILINX 0x10EE	/* already defined in <linux/pci_ids.h> The default value, 10EEh, is the Vendor ID for Xilinx. */
#define TEST_PCI_DEVICE_ID_XILINX	0x7033	// !!!check here!	/* the default value is 70<link speed><link width>h */

#define TEST_SSD_DEV_NAME		"test_ssd"
#define TEST_SSD_PARTITONS	1
#define TEST_SSD_MINORS 1
#define TEST_DEV_MEM_SZ	(1 << 22)	// 4MB

#define KTHREAD_NAME "test_kthread_fn"

#define COHERENT_DMA_BUF_SZ (1 << 22)	// !!!4MB; no less than 1MB

#define AXIBAR2PCIEBAR0_OFFSET_U 0x8208
#define AXIBAR2PCIEBAR0_OFFSET_L 0x820c
#define AXIBAR2PCIEBAR1_OFFSET_U 0x8210
#define AXIBAR2PCIEBAR1_OFFSET_L 0x8214
#define CDMA_STAT_OFFSET 0xc004
#define AXI_BAR0 0x80800000
#define AXI_BAR1 0X80000000
#define START_DESCRIPTOR 0xc008
#define END_DESCRIPTOR 0xc010
#define BRAM_AXI_ADDR 0x81000000
#define PCIE_BAR 0x81000000		

#define C_BASEADDR	0XC000	// according to hardware project
#define CDMA_CTRL_REG_OFFSET 0X00
#define CDMA_STAT_REG_OFFSET 0X04
#define CDMA_SA_REG_OFFSET 0X18
#define CDMA_DA_REG_OFFSET 0X20
#define CDMA_BTT_REG_OFFSET 0X28

struct io_cmd {
	struct bio *bio;	// !!!
	struct scatterlist *scatlist;
	dma_addr_t dma_addr;	// used by DMA controller of the device
	void *kvaddr;	// kernel virtual address, used by kernel and driver, especially to deal with data from userspace(__bio_kmap_atomic)
	uint32_t len;
};

struct io_que {
	struct bio_list bio_lst;	// !!!composed of bio, a singly-linked list of bios
	struct task_struct *task_s;
	struct io_cmd *io_cmd;	// above
	struct ssd_dev *ssd_dev;	// !!!below
	spinlock_t lock;
	uint8_t volatile is_busy;    // origin: unsigned int, DMA busy flag
};

struct ssd_dev {
	struct pci_dev *pci_dev;
	struct gendisk *disk;	// linux/genhd.h
	void __iomem *pci_bar;	// !!!!!!above, __iomem is needed
	struct io_que *dev_que;	// !!!above
};
/*
static void setup_cmd(struct io_cmd *io_cmd, struct bio *bio, struct io_que *dev_que)
{
	io_cmd->bio = bio;	// !!!!!!save it until test_bio_complete
}
*/
/*
static int setup_scatter_map(struct ssd_dev *ssd_dev, struct io_cmd *io_cmd, unsigned int const phys_segs)
{
	void *kvaddr;	// volatile struct scatter_region *
	dma_addr_t dma_addr;

	// !!!!!!return two params! set here!
	kvaddr = dma_alloc_coherent(&ssd_dev->pci_dev->dev, PAGE_SIZE, &dma_addr, GFP_ATOMIC | GFP_DMA);	
	if (kvaddr == NULL) {
		printk("err_dma_pool_alloc\n");
		return -ENOMEM;
	}

	io_cmd->kvaddr = kvaddr;
	io_cmd->dma_addr = dma_addr;
	io_cmd->len = phys_segs;

	return 0;
}
*/
/*
static int setup_scatter_list(struct io_que *dev_que, struct io_cmd *io_cmd, struct bio *bio)
{
	//struct ssd_dev *ssd_dev;
	struct bio_vec prev_bv, cur_bv;	// !!!
	struct bvec_iter bvec_iter;	// !!!
	struct scatterlist *cur_scatlist = NULL;
	unsigned int phys_segs, bytes_len = 0;
	unsigned char isnt_first_bio_vec = 0u;	// !!!
	int result = -ENOMEM;
	
	phys_segs = bio_phys_segments(dev_que->ssd_dev->disk->queue, bio);	// !!!
	io_cmd->scatlist = (struct scatterlist *)kmalloc(sizeof(struct scatterlist) * phys_segs, GFP_ATOMIC | GFP_DMA);	// !!!
	if (io_cmd->scatlist == NULL) {
		printk("err_alloc_scatterlist\n");
		goto err_alloc_scatterlist;
	}

	sg_init_table(io_cmd->scatlist, phys_segs);	// !!!lib/scatterlist.c

	phys_segs = 0;
	memset(&prev_bv, 0, sizeof(struct bio_vec));	// !!!!!!prev_bv need to be initialized
	bio_for_each_segment(cur_bv, bio, bvec_iter) {	// !!!
		if (isnt_first_bio_vec && BIOVEC_PHYS_MERGEABLE(&prev_bv, &cur_bv)) {	// !!!BIOVEC_PHYS_MERGEABLE is defined in bio.h
			cur_scatlist->length += cur_bv.bv_len;	// !!!
		} else {
			if (isnt_first_bio_vec)
				cur_scatlist++;
			else
				cur_scatlist = io_cmd->scatlist;
			sg_set_page(cur_scatlist, cur_bv.bv_page, cur_bv.bv_len, cur_bv.bv_offset);	// !!!in <linux/scatterlist.h>
			phys_segs++;
		}
		bytes_len += cur_bv.bv_len;	// !!!
		prev_bv = cur_bv;
		isnt_first_bio_vec = 1u;
	}

	sg_mark_end(cur_scatlist);	// !!!<linux/scatterlist.h>

	//ssd_dev = dev_que->ssd_dev;
	result = dma_map_sg(&dev_que->ssd_dev->pci_dev->dev, io_cmd->scatlist, phys_segs,
				bio_data_dir(io_cmd->bio) == READ ? DMA_FROM_DEVICE : DMA_TO_DEVICE);	// !!!???What's its use?
	if (result == 0) {
		printk("err_dma_map_sg\n");
		goto err_dma_map_sg;
	}

	result = setup_scatter_map(dev_que->ssd_dev, io_cmd, phys_segs);
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
xilliix pcie dma 驱动 (基于 xilnx xdma ip核 4.0 的WDF驱动) --- # XDMA Windows Driver This project is Xilinx's sample Windows driver for 'DMA/Bridge Subsystem for PCI Express v4.0' (XDMA) IP. *Please note that this driver and associated software are supplied to give a basic generic reference implementation only. Customers may have specific use-cases and/or requirements for which this driver is not suitable.* ### Dependencies * Target machine running Windows 7 or Windows 10 * Development machine running Windows 7 (or later) * Visual Studio 2015 (or later) installed on development machine * Windows Driver Kit (WDK) version 1703 (or later) installed on development machine ## Directory Structure ``` / |__ build/ - Generated directory containing build output binaries. |__ exe/ - Contains sample client application source code. | |__ simple_dma/ - Sample code for AXI-MM configured XDMA IP. | |__ streaming_dma/ - Sample code for AXI-ST configured XDMA IP. | |__ user_events/ - Sample code for access to user event interrupts. | |__ xdma_info/ - Utility application which prints out the XDMA core ip | | configuration. | |__ xdma_rw/ - Utility for reading/writing to/from xdma device nodes such | | as control, user, bypass, h2c_0, c2h_0 etc. | |__ xdma_test/ - Basic test application which performs H2C/C2H transfers on | all present channels. |__ inc/ - Contains public API header file for XDMA driver. |__ libxdma/ - Static kernel library for XDMA IP. |__ sys/ - Reference driver source code which uses libxdma |__ README.md - This file. |__ XDMA.sln - Visual Studio Solution. ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值