bzr branch
http://suren.me/webbzr/alps/pcitool
412
by Suren A. Chilingaryan
Added patch to r221 enabling kmem writes (for future reference) |
1 |
Index: pcitool-kmemwrite/cli.c
|
2 |
===================================================================
|
|
3 |
--- pcitool-kmemwrite/cli.c (revision pcitool-kmemwrite,197)
|
|
4 |
+++ pcitool-kmemwrite/cli.c (revision pcitool-kmemwrite,222)
|
|
5 |
@@ -78,4 +78,5 @@
|
|
6 |
MODE_LIST_DMA_BUFFERS, |
|
7 |
MODE_READ_DMA_BUFFER, |
|
8 |
+ MODE_WRITE_DMA_BUFFER,
|
|
9 |
MODE_ENABLE_IRQ, |
|
10 |
MODE_DISABLE_IRQ, |
|
11 |
@@ -85,4 +86,5 @@
|
|
12 |
MODE_LIST_KMEM, |
|
13 |
MODE_READ_KMEM, |
|
14 |
+ MODE_WRITE_KMEM,
|
|
15 |
MODE_FREE_KMEM |
|
16 |
} MODE; |
|
17 |
@@ -145,4 +147,5 @@
|
|
18 |
OPT_LIST_DMA_BUFFERS, |
|
19 |
OPT_READ_DMA_BUFFER, |
|
20 |
+ OPT_WRITE_DMA_BUFFER,
|
|
21 |
OPT_START_DMA, |
|
22 |
OPT_STOP_DMA, |
|
23 |
@@ -156,4 +159,5 @@
|
|
24 |
OPT_FREE_KMEM, |
|
25 |
OPT_READ_KMEM, |
|
26 |
+ OPT_WRITE_KMEM,
|
|
27 |
OPT_BLOCK_SIZE, |
|
28 |
OPT_ALIGNMENT, |
|
29 |
@@ -197,4 +201,5 @@
|
|
30 |
{"list-dma-buffers", required_argument, 0, OPT_LIST_DMA_BUFFERS }, |
|
31 |
{"read-dma-buffer", required_argument, 0, OPT_READ_DMA_BUFFER }, |
|
32 |
+ {"write-dma-buffer", required_argument, 0, OPT_WRITE_DMA_BUFFER },
|
|
33 |
{"enable-irq", optional_argument, 0, OPT_ENABLE_IRQ }, |
|
34 |
{"disable-irq", optional_argument, 0, OPT_DISABLE_IRQ }, |
|
35 |
@@ -203,4 +208,5 @@
|
|
36 |
{"list-kernel-memory", optional_argument, 0, OPT_LIST_KMEM }, |
|
37 |
{"read-kernel-memory", required_argument, 0, OPT_READ_KMEM }, |
|
38 |
+ {"write-kernel-memory", required_argument, 0, OPT_WRITE_KMEM },
|
|
39 |
{"alloc-kernel-memory", required_argument, 0, OPT_ALLOC_KMEM }, |
|
40 |
{"free-kernel-memory", required_argument, 0, OPT_FREE_KMEM }, |
|
41 |
@@ -261,4 +267,5 @@
|
|
42 |
" --list-dma-buffers <dma> - List buffers for specified DMA engine\n" |
|
43 |
" --read-dma-buffer <dma:buf> - Read the specified buffer\n" |
|
44 |
+" --write-dma-buffer <dma:buf>- Write the specified buffer\n"
|
|
45 |
"\n" |
|
46 |
" Kernel Modes:\n" |
|
47 |
@@ -266,4 +273,5 @@
|
|
48 |
" --read-kernel-memory <blk> - Read the specified block of the kernel memory\n" |
|
49 |
" block is specified as: use:block_number\n" |
|
50 |
+" --write-kernel-memory <blk> - Write the specified block of the kernel memory\n"
|
|
51 |
" --alloc-kernel-memory <use> - Allocate kernel buffers (DANGEROUS)\n" |
|
52 |
" --free-kernel-memory <use> - Cleans lost kernel space buffers (DANGEROUS)\n" |
|
53 |
@@ -2061,8 +2069,79 @@
|
|
54 |
} |
|
55 |
||
56 |
+ err = pcilib_kmem_sync_block(handle, kbuf, PCILIB_KMEM_SYNC_TODEVICE, block);
|
|
57 |
+ if (err) {
|
|
58 |
+ pcilib_free_kernel_memory(handle, kbuf, KMEM_FLAG_REUSE);
|
|
59 |
+ Error("The synchronization of kernel buffer has failed\n");
|
|
60 |
+ return 0;
|
|
61 |
+ }
|
|
62 |
+
|
|
63 |
pcilib_free_kernel_memory(handle, kbuf, KMEM_FLAG_REUSE); |
|
64 |
||
65 |
return 0; |
|
66 |
} |
|
67 |
+
|
|
68 |
+
|
|
69 |
+int WriteKMEM(pcilib_t *handle, const char *device, pcilib_kmem_use_t useid, size_t block, size_t max_size, access_t access, int endianess, char **src) {
|
|
70 |
+ int err;
|
|
71 |
+ void *data;
|
|
72 |
+ void *buf;
|
|
73 |
+ char *src_value;
|
|
74 |
+ int res = 0, i;
|
|
75 |
+ size_t n, size;
|
|
76 |
+ pcilib_kmem_handle_t *kbuf;
|
|
77 |
+
|
|
78 |
+ if (block == (size_t)-1) block = 0;
|
|
79 |
+
|
|
80 |
+ kbuf = pcilib_alloc_kernel_memory(handle, 0, block + 1, 0, 0, useid, PCILIB_KMEM_FLAG_REUSE|PCILIB_KMEM_FLAG_TRY);
|
|
81 |
+ if (!kbuf) {
|
|
82 |
+ Error("The specified kernel buffer is not allocated\n");
|
|
83 |
+ return 0;
|
|
84 |
+ }
|
|
85 |
+
|
|
86 |
+ err = pcilib_kmem_sync_block(handle, kbuf, PCILIB_KMEM_SYNC_FROMDEVICE, block);
|
|
87 |
+ if (err) {
|
|
88 |
+ pcilib_free_kernel_memory(handle, kbuf, KMEM_FLAG_REUSE);
|
|
89 |
+ Error("The synchronization of kernel buffer has failed\n");
|
|
90 |
+ return 0;
|
|
91 |
+ }
|
|
92 |
+
|
|
93 |
+ data = pcilib_kmem_get_block_ua(handle, kbuf, block);
|
|
94 |
+ if (data) {
|
|
95 |
+ size = pcilib_kmem_get_block_size(handle, kbuf, block);
|
|
96 |
+ if ((max_size)&&(size > max_size)) size = max_size;
|
|
97 |
+
|
|
98 |
+ err = posix_memalign( (void**)&buf, 256, size);
|
|
99 |
+ if ((err)||(!buf)) Error("Allocation of %i bytes of memory have failed", size);
|
|
100 |
+
|
|
101 |
+ n = size / access;
|
|
102 |
+
|
|
103 |
+ for (i = 0; i < n; i++) {
|
|
104 |
+ src_value = max_size?src[i]:src[0];
|
|
105 |
+
|
|
106 |
+ switch (access) {
|
|
107 |
+ case 1: res = sscanf(src_value, "%hhx", ((uint8_t*)buf)+i); break;
|
|
108 |
+ case 2: res = sscanf(src_value, "%hx", ((uint16_t*)buf)+i); break;
|
|
109 |
+ case 4: res = sscanf(src_value, "%x", ((uint32_t*)buf)+i); break;
|
|
110 |
+ case 8: res = sscanf(src_value, "%lx", ((uint64_t*)buf)+i); break;
|
|
111 |
+ default: Error("Unexpected data size (%lu)", access);
|
|
112 |
+ }
|
|
113 |
+ if ((res != 1)||(!isxnumber(src_value))) Error("Can't parse data value at poition %i, (%s) is not valid hex number", i, src_value);
|
|
114 |
+ }
|
|
115 |
+ if (endianess) pcilib_swap(buf, buf, abs(access), n);
|
|
116 |
+
|
|
117 |
+ printf("%x %x %i %i\n", *((uint32_t*)buf), *((uint32_t*)data), n * access, access);
|
|
118 |
+ memcpy(data, buf, n * access);
|
|
119 |
+ printf("%x %x %i %i\n", *((uint32_t*)buf), *((uint32_t*)data), n * access, access);
|
|
120 |
+ } else {
|
|
121 |
+ pcilib_free_kernel_memory(handle, kbuf, KMEM_FLAG_REUSE);
|
|
122 |
+ Error("The specified block is not existing\n");
|
|
123 |
+ return 0;
|
|
124 |
+ }
|
|
125 |
+
|
|
126 |
+ pcilib_free_kernel_memory(handle, kbuf, KMEM_FLAG_REUSE);
|
|
127 |
+
|
|
128 |
+ return 0;
|
|
129 |
+}
|
|
130 |
+
|
|
131 |
||
132 |
int AllocKMEM(pcilib_t *handle, const char *device, const char *use, const char *type, size_t size, size_t block_size, size_t alignment) { |
|
133 |
@@ -2301,4 +2380,47 @@
|
|
134 |
||
135 |
return ReadKMEM(handle, device, ((dma&0x7F)|((dma_direction == PCILIB_DMA_TO_DEVICE)?0x80:0x00))|(PCILIB_KMEM_USE_DMA_PAGES<<16), block, size, o); |
|
136 |
+}
|
|
137 |
+
|
|
138 |
+int WriteBuffer(pcilib_t *handle, const char *device, pcilib_model_description_t *model_info, pcilib_dma_engine_addr_t dma, pcilib_dma_direction_t dma_direction, size_t block, size_t size, access_t access, int endianess, char **src) {
|
|
139 |
+ int err;
|
|
140 |
+ pcilib_dma_engine_t dmaid;
|
|
141 |
+ pcilib_dma_engine_status_t status;
|
|
142 |
+ pcilib_dma_buffer_status_t *buffer;
|
|
143 |
+
|
|
144 |
+ dmaid = pcilib_find_dma_by_addr(handle, dma_direction, dma);
|
|
145 |
+ if (dmaid == PCILIB_DMA_ENGINE_INVALID) Error("The specified DMA engine is not found");
|
|
146 |
+
|
|
147 |
+ err = pcilib_start_dma(handle, dmaid, 0);
|
|
148 |
+ if (err) Error("Error starting the specified DMA engine");
|
|
149 |
+
|
|
150 |
+ err = pcilib_get_dma_status(handle, dmaid, &status, 0, NULL);
|
|
151 |
+ if (err) Error("Failed to obtain status of the specified DMA engine");
|
|
152 |
+
|
|
153 |
+ buffer = (pcilib_dma_buffer_status_t*)malloc(status.ring_size*sizeof(pcilib_dma_buffer_status_t));
|
|
154 |
+ if (!buffer) Error("Failed to allocate memory for status buffer");
|
|
155 |
+
|
|
156 |
+ err = pcilib_get_dma_status(handle, dmaid, &status, status.ring_size, buffer);
|
|
157 |
+ if (err) Error("Failed to obtain extended status of the specified DMA engine");
|
|
158 |
+
|
|
159 |
+ if (block == (size_t)-1) {
|
|
160 |
+ // get current
|
|
161 |
+ }
|
|
162 |
+
|
|
163 |
+ if (size) {
|
|
164 |
+ if (size > buffer[block].size)
|
|
165 |
+ size = buffer[block].size;
|
|
166 |
+ }
|
|
167 |
+/*
|
|
168 |
+ // We don't care if extra space will be overwritten
|
|
169 |
+ else {
|
|
170 |
+ size = buffer[block].size;
|
|
171 |
+ }
|
|
172 |
+*/
|
|
173 |
+
|
|
174 |
+ free(buffer);
|
|
175 |
+
|
|
176 |
+ pcilib_stop_dma(handle, dmaid, 0);
|
|
177 |
+
|
|
178 |
+ return WriteKMEM(handle, device, ((dma&0x7F)|((dma_direction == PCILIB_DMA_TO_DEVICE)?0x80:0x00))|(PCILIB_KMEM_USE_DMA_PAGES<<16), block, size, access, endianess, src);
|
|
179 |
} |
|
180 |
||
181 |
@@ -2513,4 +2635,20 @@
|
|
182 |
dma_channel = optarg; |
|
183 |
break; |
|
184 |
+ case OPT_WRITE_DMA_BUFFER:
|
|
185 |
+ if (mode != MODE_INVALID) Usage(argc, argv, "Multiple operations are not supported");
|
|
186 |
+
|
|
187 |
+ mode = MODE_WRITE_DMA_BUFFER;
|
|
188 |
+
|
|
189 |
+ num_offset = strchr(optarg, ':');
|
|
190 |
+
|
|
191 |
+ if (num_offset) {
|
|
192 |
+ if (sscanf(num_offset + 1, "%zu", &block) != 1)
|
|
193 |
+ Usage(argc, argv, "Invalid buffer is specified (%s)", num_offset + 1);
|
|
194 |
+
|
|
195 |
+ *(char*)num_offset = 0;
|
|
196 |
+ } else block = (size_t)-1;
|
|
197 |
+
|
|
198 |
+ dma_channel = optarg;
|
|
199 |
+ break;
|
|
200 |
case OPT_START_DMA: |
|
201 |
if (mode != MODE_INVALID) Usage(argc, argv, "Multiple operations are not supported"); |
|
202 |
@@ -2609,4 +2747,20 @@
|
|
203 |
if (mode != MODE_INVALID) Usage(argc, argv, "Multiple operations are not supported"); |
|
204 |
mode = MODE_READ_KMEM; |
|
205 |
+
|
|
206 |
+ num_offset = strchr(optarg, ':');
|
|
207 |
+
|
|
208 |
+ if (num_offset) {
|
|
209 |
+ if (sscanf(num_offset + 1, "%zu", &block) != 1)
|
|
210 |
+ Usage(argc, argv, "Invalid block number is specified (%s)", num_offset + 1);
|
|
211 |
+
|
|
212 |
+ *(char*)num_offset = 0;
|
|
213 |
+ }
|
|
214 |
+
|
|
215 |
+ use = optarg;
|
|
216 |
+ useid = ParseUse(use);
|
|
217 |
+ break;
|
|
218 |
+ case OPT_WRITE_KMEM:
|
|
219 |
+ if (mode != MODE_INVALID) Usage(argc, argv, "Multiple operations are not supported");
|
|
220 |
+ mode = MODE_WRITE_KMEM;
|
|
221 |
||
222 |
num_offset = strchr(optarg, ':'); |
|
223 |
@@ -2842,4 +2996,6 @@
|
|
224 |
||
225 |
switch (mode) { |
|
226 |
+ case MODE_WRITE_DMA_BUFFER:
|
|
227 |
+ case MODE_WRITE_KMEM:
|
|
228 |
case MODE_WRITE: |
|
229 |
if (((argc - optind) == 1)&&(*argv[optind] == '*')) { |
|
230 |
@@ -2864,4 +3020,6 @@
|
|
231 |
} else if ((argc - optind) == size) data = argv + optind; |
|
232 |
else Usage(argc, argv, "The %i data values is specified, but %i required", argc - optind, size); |
|
233 |
+
|
|
234 |
+ if (mode != MODE_WRITE) break;
|
|
235 |
case MODE_READ: |
|
236 |
if (!addr) { |
|
237 |
@@ -2872,8 +3030,15 @@
|
|
238 |
} |
|
239 |
break; |
|
240 |
+ default:
|
|
241 |
+ if (argc > optind) Usage(argc, argv, "Invalid non-option parameters are supplied");
|
|
242 |
+ }
|
|
243 |
+
|
|
244 |
+
|
|
245 |
+ switch (mode) {
|
|
246 |
case MODE_START_DMA: |
|
247 |
case MODE_STOP_DMA: |
|
248 |
case MODE_LIST_DMA_BUFFERS: |
|
249 |
case MODE_READ_DMA_BUFFER: |
|
250 |
+ case MODE_WRITE_DMA_BUFFER:
|
|
251 |
if ((dma_channel)&&(*dma_channel)) { |
|
252 |
itmp = strlen(dma_channel) - 1; |
|
253 |
@@ -2900,5 +3065,5 @@
|
|
254 |
break; |
|
255 |
default: |
|
256 |
- if (argc > optind) Usage(argc, argv, "Invalid non-option parameters are supplied");
|
|
257 |
+ ;
|
|
258 |
} |
|
259 |
||
260 |
@@ -3057,4 +3222,7 @@
|
|
261 |
ReadBuffer(handle, fpga_device, model_info, dma, dma_direction, block, ofile); |
|
262 |
break; |
|
263 |
+ case MODE_WRITE_DMA_BUFFER:
|
|
264 |
+ WriteBuffer(handle, fpga_device, model_info, dma, dma_direction, block, size_set?size:0, access, endianess, data);
|
|
265 |
+ break;
|
|
266 |
case MODE_START_DMA: |
|
267 |
StartStopDMA(handle, model_info, dma, dma_direction, 1); |
|
268 |
@@ -3082,4 +3250,7 @@
|
|
269 |
ReadKMEM(handle, fpga_device, useid, block, 0, ofile); |
|
270 |
break; |
|
271 |
+ case MODE_WRITE_KMEM:
|
|
272 |
+ WriteKMEM(handle, fpga_device, useid, block, size_set?size:0, access, endianess, data);
|
|
273 |
+ break;
|
|
274 |
case MODE_ALLOC_KMEM: |
|
275 |
AllocKMEM(handle, fpga_device, use, type, size, block_size, alignment); |