Blame view
samples/kfifo/dma-example.c
3.39 KB
5bf2b1932
|
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 |
/* * Sample fifo dma implementation * * Copyright (C) 2010 Stefani Seibold <stefani@seibold.net> * * Released under the GPL version 2 only. * */ #include <linux/init.h> #include <linux/module.h> #include <linux/kfifo.h> /* * This module shows how to handle fifo dma operations. */ /* fifo size in elements (bytes) */ #define FIFO_SIZE 32 static struct kfifo fifo; static int __init example_init(void) { int i; unsigned int ret; |
399f1e30a
|
27 |
unsigned int nents; |
5bf2b1932
|
28 29 30 31 32 33 |
struct scatterlist sg[10]; printk(KERN_INFO "DMA fifo test start "); if (kfifo_alloc(&fifo, FIFO_SIZE, GFP_KERNEL)) { |
a25effa4d
|
34 35 36 |
printk(KERN_WARNING "error kfifo_alloc "); return -ENOMEM; |
5bf2b1932
|
37 38 39 40 41 42 43 44 |
} printk(KERN_INFO "queue size: %u ", kfifo_size(&fifo)); kfifo_in(&fifo, "test", 4); for (i = 0; i != 9; i++) |
498d319bb
|
45 |
kfifo_put(&fifo, i); |
5bf2b1932
|
46 47 |
/* kick away first byte */ |
a25effa4d
|
48 |
kfifo_skip(&fifo); |
5bf2b1932
|
49 50 51 |
printk(KERN_INFO "queue len: %u ", kfifo_len(&fifo)); |
a25effa4d
|
52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 |
/* * Configure the kfifo buffer to receive data from DMA input. * * .--------------------------------------. * | 0 | 1 | 2 | ... | 12 | 13 | ... | 31 | * |---|------------------|---------------| * \_/ \________________/ \_____________/ * \ \ \ * \ \_allocated data \ * \_*free space* \_*free space* * * We need two different SG entries: one for the free space area at the * end of the kfifo buffer (19 bytes) and another for the first free * byte at the beginning, after the kfifo_skip(). */ |
7b34d5257
|
67 |
sg_init_table(sg, ARRAY_SIZE(sg)); |
399f1e30a
|
68 69 70 71 |
nents = kfifo_dma_in_prepare(&fifo, sg, ARRAY_SIZE(sg), FIFO_SIZE); printk(KERN_INFO "DMA sgl entries: %d ", nents); if (!nents) { |
a25effa4d
|
72 73 74 75 76 |
/* fifo is full and no sgl was created */ printk(KERN_WARNING "error kfifo_dma_in_prepare "); return -EIO; } |
5bf2b1932
|
77 |
|
a25effa4d
|
78 79 80 |
/* receive data */ printk(KERN_INFO "scatterlist for receive: "); |
399f1e30a
|
81 |
for (i = 0; i < nents; i++) { |
a25effa4d
|
82 83 |
printk(KERN_INFO "sg[%d] -> " |
9263969a4
|
84 85 86 |
"page %p offset 0x%.8x length 0x%.8x ", i, sg_page(&sg[i]), sg[i].offset, sg[i].length); |
5bf2b1932
|
87 |
|
a25effa4d
|
88 89 90 |
if (sg_is_last(&sg[i])) break; } |
5bf2b1932
|
91 |
|
a25effa4d
|
92 93 |
/* put here your code to setup and exectute the dma operation */ /* ... */ |
5bf2b1932
|
94 |
|
a25effa4d
|
95 96 |
/* example: zero bytes received */ ret = 0; |
5bf2b1932
|
97 |
|
a25effa4d
|
98 99 |
/* finish the dma operation and update the received data */ kfifo_dma_in_finish(&fifo, ret); |
5bf2b1932
|
100 |
|
a25effa4d
|
101 |
/* Prepare to transmit data, example: 8 bytes */ |
399f1e30a
|
102 103 104 105 |
nents = kfifo_dma_out_prepare(&fifo, sg, ARRAY_SIZE(sg), 8); printk(KERN_INFO "DMA sgl entries: %d ", nents); if (!nents) { |
a25effa4d
|
106 107 108 109 110 |
/* no data was available and no sgl was created */ printk(KERN_WARNING "error kfifo_dma_out_prepare "); return -EIO; } |
5bf2b1932
|
111 |
|
a25effa4d
|
112 113 |
printk(KERN_INFO "scatterlist for transmit: "); |
399f1e30a
|
114 |
for (i = 0; i < nents; i++) { |
a25effa4d
|
115 116 |
printk(KERN_INFO "sg[%d] -> " |
9263969a4
|
117 118 119 |
"page %p offset 0x%.8x length 0x%.8x ", i, sg_page(&sg[i]), sg[i].offset, sg[i].length); |
5bf2b1932
|
120 |
|
a25effa4d
|
121 122 123 |
if (sg_is_last(&sg[i])) break; } |
5bf2b1932
|
124 |
|
a25effa4d
|
125 126 |
/* put here your code to setup and exectute the dma operation */ /* ... */ |
5bf2b1932
|
127 |
|
a25effa4d
|
128 129 |
/* example: 5 bytes transmitted */ ret = 5; |
5bf2b1932
|
130 |
|
a25effa4d
|
131 132 |
/* finish the dma operation and update the transmitted data */ kfifo_dma_out_finish(&fifo, ret); |
5bf2b1932
|
133 |
|
a25effa4d
|
134 |
ret = kfifo_len(&fifo); |
5bf2b1932
|
135 136 |
printk(KERN_INFO "queue len: %u ", kfifo_len(&fifo)); |
a25effa4d
|
137 138 139 140 141 142 |
if (ret != 7) { printk(KERN_WARNING "size mismatch: test failed"); return -EIO; } printk(KERN_INFO "test passed "); |
5bf2b1932
|
143 144 145 146 147 |
return 0; } static void __exit example_exit(void) { |
d83a71c42
|
148 |
kfifo_free(&fifo); |
5bf2b1932
|
149 150 151 152 153 154 |
} module_init(example_init); module_exit(example_exit); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Stefani Seibold <stefani@seibold.net>"); |