1 /*
2  * Example showing how to pin down a range of virtual pages from user-space
3  * to be able to do for example DMA directly into them.
4  *
5  * It is necessary because the pages the virtual pointers reference, might
6  * not exist in memory (could be mapped to the zero-page, filemapped etc)
7  * and DMA cannot trigger the MMU to force them in (and would have time
8  * contraints making it impossible to wait for it anyway).
9  *
10  * Copyright (c) 2001, 2002, 2003  Axis Communications AB
11  *
12  * Author:  Bjorn Wesen
13  *
14  */
15 
16 #include <linux/module.h>
17 #include <linux/sched.h>
18 #include <linux/slab.h>
19 #include <linux/errno.h>
20 #include <linux/kernel.h>
21 #include <linux/fs.h>
22 #include <linux/string.h>
23 #include <linux/init.h>
24 #include <linux/mm.h>
25 #include <linux/iobuf.h>
26 
27 #define KIOBUFTEST_MAJOR 124  /* in the local range, experimental */
28 
29 static ssize_t
kiobuf_read(struct file * filp,char * buf,size_t len,loff_t * ppos)30 kiobuf_read(struct file *filp, char *buf, size_t len, loff_t *ppos)
31 {
32 	struct kiobuf *iobuf;
33 	int res, i;
34 
35 	/*
36 	 * Make a kiobuf that maps the entire length the reader has given us.
37 	 */
38 
39 	res = alloc_kiovec(1, &iobuf);
40 	if (res)
41 		return res;
42 
43 	if ((res = map_user_kiobuf(READ, iobuf, (unsigned long)buf, len))) {
44 		printk("map_user_kiobuf failed, return %d\n", res);
45 		free_kiovec(1, &iobuf);
46 		return res;
47 	}
48 
49 	/*
50 	 * At this point, the virtual area buf[0] -> buf[len-1] will have
51 	 * corresponding pages mapped in physical memory and locked until
52 	 * we unmap the kiobuf. They cannot be swapped out or moved around.
53 	 */
54 
55 	printk("nr_pages == %d\noffset == %d\nlength == %d\n",
56 	       iobuf->nr_pages, iobuf->offset, iobuf->length);
57 
58 	for (i = 0; i < iobuf->nr_pages; i++) {
59 		printk("page_add(maplist[%d]) == 0x%x\n", i,
60 		       page_address(iobuf->maplist[i]));
61 	}
62 
63 	/*
64 	 * This is the place to create the necessary scatter-gather vector
65 	 * for the DMA using the iobuf->maplist array and page_address (don't
66 	 * forget __pa if the DMA needs the actual physical DRAM address)
67 	 * and run it.
68 	 */
69 
70 
71 
72 	/* Release the mapping and exit */
73 
74 	unmap_kiobuf(iobuf); /* The unlock_kiobuf is implicit here */
75 	free_kiovec(1, &iobuf);
76 
77 	return len;
78 }
79 
80 
81 static struct file_operations kiobuf_fops = {
82 	owner:    THIS_MODULE,
83 	read:     kiobuf_read
84 };
85 
86 static int __init
kiobuftest_init(void)87 kiobuftest_init(void)
88 {
89 	int res;
90 
91 	/* register char device */
92 
93 	res = register_chrdev(KIOBUFTEST_MAJOR, "kiobuftest", &kiobuf_fops);
94 	if (res < 0) {
95 		printk(KERN_ERR "kiobuftest: couldn't get a major number.\n");
96 		return res;
97 	}
98 
99 	printk("Initializing kiobuf-test device\n");
100 }
101 
102 static void __exit
kiobuftest_exit(void)103 kiobuftest_exit(void)
104 {
105 	unregister_chrdev(KIOBUFTEST_MAJOR, "kiobuftest");
106 }
107 
108 module_init(kiobuftest_init);
109 module_exit(kiobuftest_exit);
110