-
Notifications
You must be signed in to change notification settings - Fork 12
/
Copy pathfpga_mem.c
148 lines (126 loc) · 3.5 KB
/
fpga_mem.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
#include <linux/init.h>
#include <linux/module.h>
#include <linux/types.h>
#include <linux/fs.h>
#include <linux/cdev.h>
#include <asm/uaccess.h>
#include <asm/io.h> //virt_to_phys
#include <linux/ioport.h> //request_mem_region
#include <linux/slab.h> //kmalloc and kfree
#include <linux/mm.h> //remap_pfn_range
#include <linux/device.h> //class_create
#include "fpga_mem.h"
unsigned int *base_vir_addr=NULL;
struct resource *base_vir_mem_addr=NULL;
dev_t fpga_mem_num;
struct cdev *p_fpga_mem=NULL;
static int fpga_mem_major = 0;
struct class *fpga_mem_class = NULL;
static int fpga_mem_open(struct inode *inode, struct file *filp)
{
//printk(KERN_EMERG "fpga mem is open!\n");
return 0;
}
static ssize_t fpga_mem_mmap(struct file *filp, struct vm_area_struct *vma)
{
int ret;
//printk(KERN_EMERG "In axi_fpga_dev_mmap!\n");
vma->vm_flags |= VM_IO;
vma->vm_flags |= (VM_DONTEXPAND | VM_DONTDUMP);
vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); //禁止了相关页的cache和写缓冲(write buffer)
ret = remap_pfn_range(vma,
vma->vm_start,
(FPGA_MEM_START_ADDR + FPGA_MEM_OFFSET_ADDR) >> PAGE_SHIFT,
//vma->vm_pgoff,
vma->vm_end-vma->vm_start,
vma->vm_page_prot);
if(ret != 0)
{
printk("fpga_mem_mmap error!\n");
return -9;
}
return 0;
}
static int fpga_mem_release(struct inode *node, struct file* filp)
{
//printk(KERN_EMERG "fpga mem is released!\n");
return 0;
}
static const struct file_operations fpga_mem_fops =
{
.owner = THIS_MODULE,
.open = fpga_mem_open,
.mmap = fpga_mem_mmap,
.release = fpga_mem_release,
};
static int __init fpga_mem_init(void)
{
int ret;
char *p = "fpga_vir_mem";
printk("In fpga mem driver!\n");
if(fpga_mem_major)
{
fpga_mem_num = MKDEV(fpga_mem_major, 0);
ret = register_chrdev_region(fpga_mem_num, 1, "fpga_mem");
}
else
{
ret = alloc_chrdev_region(&fpga_mem_num, 0, 1, "fpga_mem");
}
if(ret < 0)
{
printk("alloc fpga_mem fail!\n");
return ret;
}
p_fpga_mem = kmalloc(sizeof(struct cdev), GFP_KERNEL);
if(!p_fpga_mem)
{
printk("kmalloc cdev fail!\n");
return -10;
}
cdev_init(p_fpga_mem, &fpga_mem_fops);
p_fpga_mem->owner = THIS_MODULE;
ret = cdev_add(p_fpga_mem, fpga_mem_num, 1);
if(ret)
{
printk("add fpga_mem fail!\n");
return -11;
}
base_vir_mem_addr = request_mem_region(FPGA_MEM_START_ADDR + FPGA_MEM_OFFSET_ADDR, FPGA_MEM_LEN, p);
if(!base_vir_mem_addr)
{
printk("request_mem_region failed!\n");
return -12;
}
printk("request_mem_region OK!\n");
base_vir_addr = ioremap(FPGA_MEM_START_ADDR + FPGA_MEM_OFFSET_ADDR, FPGA_MEM_LEN);
if(!base_vir_addr)
{
printk("ioremap fail!\n");
printk("!!!*base_vir_addr = 0x%x\n", (unsigned int)base_vir_addr);
return -13;
}
printk("fpga mem virtual address is 0x%x\n", (unsigned int)base_vir_addr);
fpga_mem_class = class_create(THIS_MODULE, "fpga_mem");
if (IS_ERR(fpga_mem_class))
{
printk("Err:failed in creating fpga mem class.\n");
return -14;
}
device_create(fpga_mem_class, NULL, fpga_mem_num, NULL, "fpga_mem");
return 0;
}
static void __exit fpga_mem_exit(void)
{
unregister_chrdev_region(fpga_mem_num, 1);
cdev_del(p_fpga_mem);
kfree(p_fpga_mem);
iounmap(base_vir_addr);
release_mem_region(FPGA_MEM_START_ADDR + FPGA_MEM_OFFSET_ADDR, FPGA_MEM_LEN);
device_destroy(fpga_mem_class, fpga_mem_num);
class_destroy(fpga_mem_class);
printk("Bye Bye fpga mem driver!\n");
}
module_init(fpga_mem_init);
module_exit(fpga_mem_exit);
MODULE_LICENSE("Dual BSD/GPL");