OpenWrt – Blame information for rev 4
?pathlinks?
Rev | Author | Line No. | Line |
---|---|---|---|
4 | office | 1 | /****************************************************************************** |
2 | ** |
||
3 | ** FILE NAME : ifxmips_ptm_vdsl.c |
||
4 | ** PROJECT : UEIP |
||
5 | ** MODULES : PTM |
||
6 | ** |
||
7 | ** DATE : 7 Jul 2009 |
||
8 | ** AUTHOR : Xu Liang |
||
9 | ** DESCRIPTION : PTM driver common source file (core functions for VR9) |
||
10 | ** COPYRIGHT : Copyright (c) 2006 |
||
11 | ** Infineon Technologies AG |
||
12 | ** Am Campeon 1-12, 85579 Neubiberg, Germany |
||
13 | ** |
||
14 | ** This program is free software; you can redistribute it and/or modify |
||
15 | ** it under the terms of the GNU General Public License as published by |
||
16 | ** the Free Software Foundation; either version 2 of the License, or |
||
17 | ** (at your option) any later version. |
||
18 | ** |
||
19 | ** HISTORY |
||
20 | ** $Date $Author $Comment |
||
21 | ** 07 JUL 2009 Xu Liang Init Version |
||
22 | *******************************************************************************/ |
||
23 | |||
24 | |||
25 | |||
26 | #ifdef CONFIG_IFX_PTM_TEST_PROC |
||
27 | |||
28 | /* |
||
29 | * #################################### |
||
30 | * Head File |
||
31 | * #################################### |
||
32 | */ |
||
33 | |||
34 | /* |
||
35 | * Common Head File |
||
36 | */ |
||
37 | #include <linux/kernel.h> |
||
38 | #include <linux/module.h> |
||
39 | #include <linux/version.h> |
||
40 | #include <linux/types.h> |
||
41 | #include <linux/errno.h> |
||
42 | #include <linux/proc_fs.h> |
||
43 | #include <linux/init.h> |
||
44 | #include <linux/ioctl.h> |
||
45 | #include <linux/etherdevice.h> |
||
46 | |||
47 | /* |
||
48 | * Chip Specific Head File |
||
49 | */ |
||
50 | #include <asm/ifx/ifx_types.h> |
||
51 | #include <asm/ifx/ifx_regs.h> |
||
52 | #include <asm/ifx/common_routines.h> |
||
53 | #include "ifxmips_ptm_common.h" |
||
54 | #include "ifxmips_ptm_ppe_common.h" |
||
55 | |||
56 | |||
57 | |||
58 | /* |
||
59 | * #################################### |
||
60 | * Definition |
||
61 | * #################################### |
||
62 | */ |
||
63 | |||
64 | |||
65 | |||
66 | /* |
||
67 | * #################################### |
||
68 | * Declaration |
||
69 | * #################################### |
||
70 | */ |
||
71 | |||
72 | /* |
||
73 | * Proc File Functions |
||
74 | */ |
||
75 | static inline void proc_file_create(void); |
||
76 | static inline void proc_file_delete(void); |
||
77 | |||
78 | /* |
||
79 | * Proc Help Functions |
||
80 | */ |
||
81 | static int proc_write_mem(struct file *, const char *, unsigned long, void *); |
||
82 | static int proc_read_pp32(char *, char **, off_t, int, int *, void *); |
||
83 | static int proc_write_pp32(struct file *, const char *, unsigned long, void *); |
||
84 | static int stricmp(const char *, const char *); |
||
85 | static int strincmp(const char *, const char *, int); |
||
86 | static int get_token(char **, char **, int *, int *); |
||
87 | static int get_number(char **, int *, int); |
||
88 | static inline void ignore_space(char **, int *); |
||
89 | |||
90 | |||
91 | |||
92 | /* |
||
93 | * #################################### |
||
94 | * Local Variable |
||
95 | * #################################### |
||
96 | */ |
||
97 | |||
98 | |||
99 | |||
100 | /* |
||
101 | * #################################### |
||
102 | * Local Function |
||
103 | * #################################### |
||
104 | */ |
||
105 | |||
106 | static inline void proc_file_create(void) |
||
107 | { |
||
108 | struct proc_dir_entry *res; |
||
109 | |||
110 | res = create_proc_entry("driver/ifx_ptm/mem", |
||
111 | 0, |
||
112 | NULL); |
||
113 | if ( res != NULL ) |
||
114 | res->write_proc = proc_write_mem; |
||
115 | else |
||
116 | printk("%s:%s:%d: failed to create proc mem!", __FILE__, __func__, __LINE__); |
||
117 | |||
118 | res = create_proc_entry("driver/ifx_ptm/pp32", |
||
119 | 0, |
||
120 | NULL); |
||
121 | if ( res != NULL ) { |
||
122 | res->read_proc = proc_read_pp32; |
||
123 | res->write_proc = proc_write_pp32; |
||
124 | } |
||
125 | else |
||
126 | printk("%s:%s:%d: failed to create proc pp32!", __FILE__, __func__, __LINE__); |
||
127 | } |
||
128 | |||
129 | static inline void proc_file_delete(void) |
||
130 | { |
||
131 | remove_proc_entry("driver/ifx_ptm/pp32", NULL); |
||
132 | |||
133 | remove_proc_entry("driver/ifx_ptm/mem", NULL); |
||
134 | } |
||
135 | |||
136 | static inline unsigned long sb_addr_to_fpi_addr_convert(unsigned long sb_addr) |
||
137 | { |
||
138 | #define PP32_SB_ADDR_END 0xFFFF |
||
139 | |||
140 | if ( sb_addr < PP32_SB_ADDR_END) { |
||
141 | return (unsigned long ) SB_BUFFER(sb_addr); |
||
142 | } |
||
143 | else { |
||
144 | return sb_addr; |
||
145 | } |
||
146 | } |
||
147 | |||
148 | static int proc_write_mem(struct file *file, const char *buf, unsigned long count, void *data) |
||
149 | { |
||
150 | char *p1, *p2; |
||
151 | int len; |
||
152 | int colon; |
||
153 | unsigned long *p; |
||
154 | char local_buf[1024]; |
||
155 | int i, n, l; |
||
156 | |||
157 | len = sizeof(local_buf) < count ? sizeof(local_buf) - 1 : count; |
||
158 | len = len - copy_from_user(local_buf, buf, len); |
||
159 | local_buf[len] = 0; |
||
160 | |||
161 | p1 = local_buf; |
||
162 | colon = 1; |
||
163 | while ( get_token(&p1, &p2, &len, &colon) ) |
||
164 | { |
||
165 | if ( stricmp(p1, "w") == 0 || stricmp(p1, "write") == 0 || stricmp(p1, "r") == 0 || stricmp(p1, "read") == 0 ) |
||
166 | break; |
||
167 | |||
168 | p1 = p2; |
||
169 | colon = 1; |
||
170 | } |
||
171 | |||
172 | if ( *p1 == 'w' ) |
||
173 | { |
||
174 | ignore_space(&p2, &len); |
||
175 | p = (unsigned long *)get_number(&p2, &len, 1); |
||
176 | p = (unsigned long *)sb_addr_to_fpi_addr_convert( (unsigned long) p); |
||
177 | |||
178 | if ( (u32)p >= KSEG0 ) |
||
179 | while ( 1 ) |
||
180 | { |
||
181 | ignore_space(&p2, &len); |
||
182 | if ( !len || !((*p2 >= '0' && *p2 <= '9') || (*p2 >= 'a' && *p2 <= 'f') || (*p2 >= 'A' && *p2 <= 'F')) ) |
||
183 | break; |
||
184 | |||
185 | *p++ = (u32)get_number(&p2, &len, 1); |
||
186 | } |
||
187 | } |
||
188 | else if ( *p1 == 'r' ) |
||
189 | { |
||
190 | ignore_space(&p2, &len); |
||
191 | p = (unsigned long *)get_number(&p2, &len, 1); |
||
192 | p = (unsigned long *)sb_addr_to_fpi_addr_convert( (unsigned long) p); |
||
193 | |||
194 | if ( (u32)p >= KSEG0 ) |
||
195 | { |
||
196 | ignore_space(&p2, &len); |
||
197 | n = (int)get_number(&p2, &len, 0); |
||
198 | if ( n ) |
||
199 | { |
||
200 | char str[32] = {0}; |
||
201 | char *pch = str; |
||
202 | int k; |
||
203 | u32 data; |
||
204 | char c; |
||
205 | |||
206 | n += (l = ((int)p >> 2) & 0x03); |
||
207 | p = (unsigned long *)((u32)p & ~0x0F); |
||
208 | for ( i = 0; i < n; i++ ) |
||
209 | { |
||
210 | if ( (i & 0x03) == 0 ) |
||
211 | { |
||
212 | printk("%08X:", (u32)p); |
||
213 | pch = str; |
||
214 | } |
||
215 | if ( i < l ) |
||
216 | { |
||
217 | printk(" "); |
||
218 | sprintf(pch, " "); |
||
219 | } |
||
220 | else |
||
221 | { |
||
222 | data = (u32)*p; |
||
223 | printk(" %08X", data); |
||
224 | for ( k = 0; k < 4; k++ ) |
||
225 | { |
||
226 | c = ((char*)&data)[k]; |
||
227 | pch[k] = c < ' ' ? '.' : c; |
||
228 | } |
||
229 | } |
||
230 | p++; |
||
231 | pch += 4; |
||
232 | if ( (i & 0x03) == 0x03 ) |
||
233 | { |
||
234 | pch[0] = 0; |
||
235 | printk(" ; %s\n", str); |
||
236 | } |
||
237 | } |
||
238 | if ( (n & 0x03) != 0x00 ) |
||
239 | { |
||
240 | for ( k = 4 - (n & 0x03); k > 0; k-- ) |
||
241 | printk(" "); |
||
242 | pch[0] = 0; |
||
243 | printk(" ; %s\n", str); |
||
244 | } |
||
245 | } |
||
246 | } |
||
247 | } |
||
248 | |||
249 | return count; |
||
250 | } |
||
251 | |||
252 | #ifdef CONFIG_DANUBE |
||
253 | |||
254 | static int proc_read_pp32(char *page, char **start, off_t off, int count, int *eof, void *data) |
||
255 | { |
||
256 | static const char *halt_stat[] = { |
||
257 | "reset", |
||
258 | "break in line", |
||
259 | "stop", |
||
260 | "step", |
||
261 | "code", |
||
262 | "data0", |
||
263 | "data1" |
||
264 | }; |
||
265 | static const char *brk_src_data[] = { |
||
266 | "off", |
||
267 | "read", |
||
268 | "write", |
||
269 | "read/write", |
||
270 | "write_equal", |
||
271 | "N/A", |
||
272 | "N/A", |
||
273 | "N/A" |
||
274 | }; |
||
275 | static const char *brk_src_code[] = { |
||
276 | "off", |
||
277 | "on" |
||
278 | }; |
||
279 | |||
280 | int len = 0; |
||
281 | int cur_task; |
||
282 | int i, j; |
||
283 | int k; |
||
284 | unsigned long bit; |
||
285 | |||
286 | len += sprintf(page + off + len, "Task No %d, PC %04x\n", *PP32_DBG_TASK_NO & 0x03, *PP32_DBG_CUR_PC & 0xFFFF); |
||
287 | |||
288 | if ( !(*PP32_HALT_STAT & 0x01) ) |
||
289 | len += sprintf(page + off + len, " Halt State: Running\n"); |
||
290 | else |
||
291 | { |
||
292 | len += sprintf(page + off + len, " Halt State: Stopped"); |
||
293 | k = 0; |
||
294 | for ( bit = 2, i = 0; bit <= (1 << 7); bit <<= 1, i++ ) |
||
295 | if ( (*PP32_HALT_STAT & bit) ) |
||
296 | { |
||
297 | if ( !k ) |
||
298 | { |
||
299 | len += sprintf(page + off + len, ", "); |
||
300 | k++; |
||
301 | } |
||
302 | else |
||
303 | len += sprintf(page + off + len, " | "); |
||
304 | len += sprintf(page + off + len, halt_stat[i]); |
||
305 | } |
||
306 | |||
307 | len += sprintf(page + off + len, "\n"); |
||
308 | |||
309 | cur_task = *PP32_DBG_TASK_NO & 0x03; |
||
310 | len += sprintf(page + off + len, "General Purpose Register (Task %d):\n", cur_task); |
||
311 | for ( i = 0; i < 4; i++ ) |
||
312 | { |
||
313 | for ( j = 0; j < 4; j++ ) |
||
314 | len += sprintf(page + off + len, " %2d: %08x", i + j * 4, *PP32_DBG_TASK_GPR(cur_task, i + j * 4)); |
||
315 | len += sprintf(page + off + len, "\n"); |
||
316 | } |
||
317 | } |
||
318 | |||
319 | len += sprintf(page + off + len, " Break Src: data1 - %s, data0 - %s, pc3 - %s, pc2 - %s, pc1 - %s, pc0 - %s\n", |
||
320 | brk_src_data[(*PP32_BRK_SRC >> 11) & 0x07], brk_src_data[(*PP32_BRK_SRC >> 8) & 0x07], brk_src_code[(*PP32_BRK_SRC >> 3) & 0x01], brk_src_code[(*PP32_BRK_SRC >> 2) & 0x01], brk_src_code[(*PP32_BRK_SRC >> 1) & 0x01], brk_src_code[*PP32_BRK_SRC & 0x01]); |
||
321 | |||
322 | for ( i = 0; i < 4; i++ ) |
||
323 | len += sprintf(page + off + len, " pc%d: %04x - %04x\n", i, *PP32_DBG_PC_MIN(i), *PP32_DBG_PC_MAX(i)); |
||
324 | |||
325 | for ( i = 0; i < 2; i++ ) |
||
326 | len += sprintf(page + off + len, " data%d: %04x - %04x (%08x)\n", i, *PP32_DBG_DATA_MIN(i), *PP32_DBG_DATA_MAX(i), *PP32_DBG_DATA_VAL(i)); |
||
327 | |||
328 | *eof = 1; |
||
329 | |||
330 | return len; |
||
331 | } |
||
332 | |||
333 | static int proc_write_pp32(struct file *file, const char *buf, unsigned long count, void *data) |
||
334 | { |
||
335 | char str[2048]; |
||
336 | char *p; |
||
337 | int len, rlen; |
||
338 | |||
339 | int id; |
||
340 | u32 addr; |
||
341 | u32 cmd; |
||
342 | |||
343 | len = count < sizeof(str) ? count : sizeof(str) - 1; |
||
344 | rlen = len - copy_from_user(str, buf, len); |
||
345 | while ( rlen && str[rlen - 1] <= ' ' ) |
||
346 | rlen--; |
||
347 | str[rlen] = 0; |
||
348 | for ( p = str; *p && *p <= ' '; p++, rlen-- ); |
||
349 | if ( !*p ) |
||
350 | { |
||
351 | return 0; |
||
352 | } |
||
353 | |||
354 | if ( stricmp(str, "start") == 0 ) |
||
355 | *PP32_DBG_CTRL = DBG_CTRL_START_SET(1); |
||
356 | else if ( stricmp(str, "stop") == 0 ) |
||
357 | *PP32_DBG_CTRL = DBG_CTRL_STOP_SET(1); |
||
358 | else if ( stricmp(str, "step") == 0 ) |
||
359 | *PP32_DBG_CTRL = DBG_CTRL_STEP_SET(1); |
||
360 | else if ( strincmp(p, "pc", 2) == 0 && p[2] >= '0' && p[2] <= '3' && p[3] == ' ' ) |
||
361 | { |
||
362 | id = (int)(p[2] - '0'); |
||
363 | p += 4; |
||
364 | rlen -= 4; |
||
365 | *PP32_BRK_SRC &= ~PP32_BRK_SRC_PC(id); |
||
366 | if ( stricmp(p, "off") != 0 ) |
||
367 | { |
||
368 | ignore_space(&p, &rlen); |
||
369 | *PP32_DBG_PC_MIN(id) = *PP32_DBG_PC_MAX(id) = get_number(&p, &rlen, 1); |
||
370 | ignore_space(&p, &rlen); |
||
371 | if ( rlen > 0 ) |
||
372 | { |
||
373 | addr = get_number(&p, &rlen, 1); |
||
374 | if ( addr >= *PP32_DBG_PC_MIN(id) ) |
||
375 | *PP32_DBG_PC_MAX(id) = addr; |
||
376 | else |
||
377 | *PP32_DBG_PC_MIN(id) = addr; |
||
378 | } |
||
379 | *PP32_BRK_SRC |= PP32_BRK_SRC_PC(id); |
||
380 | } |
||
381 | } |
||
382 | else if ( strincmp(p, "daddr", 5) == 0 && p[5] >= '0' && p[5] <= '1' && p[6] == ' ' ) |
||
383 | { |
||
384 | id = (int)(p[5] - '0'); |
||
385 | p += 7; |
||
386 | rlen -= 7; |
||
387 | *PP32_BRK_SRC &= ~PP32_BRK_SRC_DATA(id, 7); |
||
388 | if ( stricmp(p, "off") != 0 ) |
||
389 | { |
||
390 | ignore_space(&p, &rlen); |
||
391 | *PP32_DBG_DATA_MIN(id) = *PP32_DBG_DATA_MAX(id) = get_number(&p, &rlen, 1); |
||
392 | cmd = 1; |
||
393 | ignore_space(&p, &rlen); |
||
394 | if ( rlen > 0 && ((*p >= '0' && *p <= '9') || (*p >= 'a' && *p <= 'f') || (*p >= 'A' && *p <= 'F')) ) |
||
395 | { |
||
396 | addr = get_number(&p, &rlen, 1); |
||
397 | if ( addr >= *PP32_DBG_PC_MIN(id) ) |
||
398 | *PP32_DBG_DATA_MAX(id) = addr; |
||
399 | else |
||
400 | *PP32_DBG_DATA_MIN(id) = addr; |
||
401 | ignore_space(&p, &rlen); |
||
402 | } |
||
403 | if ( *p == 'w' ) |
||
404 | cmd = 2; |
||
405 | else if ( *p == 'r' && p[1] == 'w' ) |
||
406 | { |
||
407 | cmd = 3; |
||
408 | p++; |
||
409 | rlen--; |
||
410 | } |
||
411 | p++; |
||
412 | rlen--; |
||
413 | if ( rlen > 0 ) |
||
414 | { |
||
415 | ignore_space(&p, &rlen); |
||
416 | if ( (*p >= '0' && *p <= '9') || (*p >= 'a' && *p <= 'f') || (*p >= 'A' && *p <= 'F')) |
||
417 | { |
||
418 | *PP32_DBG_DATA_VAL(id) = get_number(&p, &rlen, 1); |
||
419 | cmd = 4; |
||
420 | } |
||
421 | } |
||
422 | *PP32_BRK_SRC |= PP32_BRK_SRC_DATA(id, cmd); |
||
423 | } |
||
424 | } |
||
425 | else |
||
426 | { |
||
427 | printk("echo \"<command>\" > /proc/driver/ifx_ptm/pp32\n"); |
||
428 | printk(" command:\n"); |
||
429 | printk(" start - run pp32\n"); |
||
430 | printk(" stop - stop pp32\n"); |
||
431 | printk(" step - run pp32 with one step only\n"); |
||
432 | printk(" pc0 - pc0 <addr_min [addr_max]>/off, set break point PC0\n"); |
||
433 | printk(" pc1 - pc1 <addr_min [addr_max]>/off, set break point PC1\n"); |
||
434 | printk(" pc2 - pc2 <addr_min [addr_max]>/off, set break point PC2\n"); |
||
435 | printk(" pc3 - pc3 <addr_min [addr_max]>/off, set break point PC3\n"); |
||
436 | printk(" daddr0 - daddr0 <addr_min [addr_max] r/w/rw [value]>/off, set break point data address 0\n"); |
||
437 | printk(" daddr1 - daddr1 <addr_min [addr_max] r/w/rw [value]>/off, set break point data address 1\n"); |
||
438 | printk(" help - print this screen\n"); |
||
439 | } |
||
440 | |||
441 | return count; |
||
442 | } |
||
443 | |||
444 | #else |
||
445 | |||
446 | static int proc_read_pp32(char *page, char **start, off_t off, int count, int *eof, void *data) |
||
447 | { |
||
448 | static const char *stron = " on"; |
||
449 | static const char *stroff = "off"; |
||
450 | |||
451 | int len = 0; |
||
452 | int cur_context; |
||
453 | int f_stopped; |
||
454 | char str[256]; |
||
455 | char strlength; |
||
456 | int i, j; |
||
457 | |||
458 | int pp32; |
||
459 | |||
460 | for ( pp32 = 0; pp32 < NUM_OF_PP32; pp32++ ) |
||
461 | { |
||
462 | f_stopped = 0; |
||
463 | |||
464 | len += sprintf(page + off + len, "===== pp32 core %d =====\n", pp32); |
||
465 | |||
466 | #ifdef CONFIG_VR9 |
||
467 | if ( (*PP32_FREEZE & (1 << (pp32 << 4))) != 0 ) |
||
468 | { |
||
469 | sprintf(str, "freezed"); |
||
470 | f_stopped = 1; |
||
471 | } |
||
472 | #else |
||
473 | if ( 0 ) |
||
474 | { |
||
475 | } |
||
476 | #endif |
||
477 | else if ( PP32_CPU_USER_STOPPED(pp32) || PP32_CPU_USER_BREAKIN_RCV(pp32) || PP32_CPU_USER_BREAKPOINT_MET(pp32) ) |
||
478 | { |
||
479 | strlength = 0; |
||
480 | if ( PP32_CPU_USER_STOPPED(pp32) ) |
||
481 | strlength += sprintf(str + strlength, "stopped"); |
||
482 | if ( PP32_CPU_USER_BREAKPOINT_MET(pp32) ) |
||
483 | strlength += sprintf(str + strlength, strlength ? " | breakpoint" : "breakpoint"); |
||
484 | if ( PP32_CPU_USER_BREAKIN_RCV(pp32) ) |
||
485 | strlength += sprintf(str + strlength, strlength ? " | breakin" : "breakin"); |
||
486 | f_stopped = 1; |
||
487 | } |
||
488 | else if ( PP32_CPU_CUR_PC(pp32) == PP32_CPU_CUR_PC(pp32) ) |
||
489 | { |
||
490 | unsigned int pc_value[64] = {0}; |
||
491 | |||
492 | f_stopped = 1; |
||
493 | for ( i = 0; f_stopped && i < NUM_ENTITY(pc_value); i++ ) |
||
494 | { |
||
495 | pc_value[i] = PP32_CPU_CUR_PC(pp32); |
||
496 | for ( j = 0; j < i; j++ ) |
||
497 | if ( pc_value[j] != pc_value[i] ) |
||
498 | { |
||
499 | f_stopped = 0; |
||
500 | break; |
||
501 | } |
||
502 | } |
||
503 | if ( f_stopped ) |
||
504 | sprintf(str, "hang"); |
||
505 | } |
||
506 | if ( !f_stopped ) |
||
507 | sprintf(str, "running"); |
||
508 | cur_context = PP32_BRK_CUR_CONTEXT(pp32); |
||
509 | len += sprintf(page + off + len, "Context: %d, PC: 0x%04x, %s\n", cur_context, PP32_CPU_CUR_PC(pp32), str); |
||
510 | |||
511 | if ( PP32_CPU_USER_BREAKPOINT_MET(pp32) ) |
||
512 | { |
||
513 | strlength = 0; |
||
514 | if ( PP32_BRK_PC_MET(pp32, 0) ) |
||
515 | strlength += sprintf(str + strlength, "pc0"); |
||
516 | if ( PP32_BRK_PC_MET(pp32, 1) ) |
||
517 | strlength += sprintf(str + strlength, strlength ? " | pc1" : "pc1"); |
||
518 | if ( PP32_BRK_DATA_ADDR_MET(pp32, 0) ) |
||
519 | strlength += sprintf(str + strlength, strlength ? " | daddr0" : "daddr0"); |
||
520 | if ( PP32_BRK_DATA_ADDR_MET(pp32, 1) ) |
||
521 | strlength += sprintf(str + strlength, strlength ? " | daddr1" : "daddr1"); |
||
522 | if ( PP32_BRK_DATA_VALUE_RD_MET(pp32, 0) ) |
||
523 | { |
||
524 | strlength += sprintf(str + strlength, strlength ? " | rdval0" : "rdval0"); |
||
525 | if ( PP32_BRK_DATA_VALUE_RD_LO_EQ(pp32, 0) ) |
||
526 | { |
||
527 | if ( PP32_BRK_DATA_VALUE_RD_GT_EQ(pp32, 0) ) |
||
528 | strlength += sprintf(str + strlength, " =="); |
||
529 | else |
||
530 | strlength += sprintf(str + strlength, " <="); |
||
531 | } |
||
532 | else if ( PP32_BRK_DATA_VALUE_RD_GT_EQ(pp32, 0) ) |
||
533 | strlength += sprintf(str + strlength, " >="); |
||
534 | } |
||
535 | if ( PP32_BRK_DATA_VALUE_RD_MET(pp32, 1) ) |
||
536 | { |
||
537 | strlength += sprintf(str + strlength, strlength ? " | rdval1" : "rdval1"); |
||
538 | if ( PP32_BRK_DATA_VALUE_RD_LO_EQ(pp32, 1) ) |
||
539 | { |
||
540 | if ( PP32_BRK_DATA_VALUE_RD_GT_EQ(pp32, 1) ) |
||
541 | strlength += sprintf(str + strlength, " =="); |
||
542 | else |
||
543 | strlength += sprintf(str + strlength, " <="); |
||
544 | } |
||
545 | else if ( PP32_BRK_DATA_VALUE_RD_GT_EQ(pp32, 1) ) |
||
546 | strlength += sprintf(str + strlength, " >="); |
||
547 | } |
||
548 | if ( PP32_BRK_DATA_VALUE_WR_MET(pp32, 0) ) |
||
549 | { |
||
550 | strlength += sprintf(str + strlength, strlength ? " | wtval0" : "wtval0"); |
||
551 | if ( PP32_BRK_DATA_VALUE_WR_LO_EQ(pp32, 0) ) |
||
552 | { |
||
553 | if ( PP32_BRK_DATA_VALUE_WR_GT_EQ(pp32, 0) ) |
||
554 | strlength += sprintf(str + strlength, " =="); |
||
555 | else |
||
556 | strlength += sprintf(str + strlength, " <="); |
||
557 | } |
||
558 | else if ( PP32_BRK_DATA_VALUE_WR_GT_EQ(pp32, 0) ) |
||
559 | strlength += sprintf(str + strlength, " >="); |
||
560 | } |
||
561 | if ( PP32_BRK_DATA_VALUE_WR_MET(pp32, 1) ) |
||
562 | { |
||
563 | strlength += sprintf(str + strlength, strlength ? " | wtval1" : "wtval1"); |
||
564 | if ( PP32_BRK_DATA_VALUE_WR_LO_EQ(pp32, 1) ) |
||
565 | { |
||
566 | if ( PP32_BRK_DATA_VALUE_WR_GT_EQ(pp32, 1) ) |
||
567 | strlength += sprintf(str + strlength, " =="); |
||
568 | else |
||
569 | strlength += sprintf(str + strlength, " <="); |
||
570 | } |
||
571 | else if ( PP32_BRK_DATA_VALUE_WR_GT_EQ(pp32, 1) ) |
||
572 | strlength += sprintf(str + strlength, " >="); |
||
573 | } |
||
574 | len += sprintf(page + off + len, "break reason: %s\n", str); |
||
575 | } |
||
576 | |||
577 | if ( f_stopped ) |
||
578 | { |
||
579 | len += sprintf(page + off + len, "General Purpose Register (Context %d):\n", cur_context); |
||
580 | for ( i = 0; i < 4; i++ ) |
||
581 | { |
||
582 | for ( j = 0; j < 4; j++ ) |
||
583 | len += sprintf(page + off + len, " %2d: %08x", i + j * 4, *PP32_GP_CONTEXTi_REGn(pp32, cur_context, i + j * 4)); |
||
584 | len += sprintf(page + off + len, "\n"); |
||
585 | } |
||
586 | } |
||
587 | |||
588 | len += sprintf(page + off + len, "break out on: break in - %s, stop - %s\n", |
||
589 | PP32_CTRL_OPT_BREAKOUT_ON_BREAKIN(pp32) ? stron : stroff, |
||
590 | PP32_CTRL_OPT_BREAKOUT_ON_STOP(pp32) ? stron : stroff); |
||
591 | len += sprintf(page + off + len, " stop on: break in - %s, break point - %s\n", |
||
592 | PP32_CTRL_OPT_STOP_ON_BREAKIN(pp32) ? stron : stroff, |
||
593 | PP32_CTRL_OPT_STOP_ON_BREAKPOINT(pp32) ? stron : stroff); |
||
594 | len += sprintf(page + off + len, "breakpoint:\n"); |
||
595 | len += sprintf(page + off + len, " pc0: 0x%08x, %s\n", *PP32_BRK_PC(pp32, 0), PP32_BRK_GRPi_PCn(pp32, 0, 0) ? "group 0" : "off"); |
||
596 | len += sprintf(page + off + len, " pc1: 0x%08x, %s\n", *PP32_BRK_PC(pp32, 1), PP32_BRK_GRPi_PCn(pp32, 1, 1) ? "group 1" : "off"); |
||
597 | len += sprintf(page + off + len, " daddr0: 0x%08x, %s\n", *PP32_BRK_DATA_ADDR(pp32, 0), PP32_BRK_GRPi_DATA_ADDRn(pp32, 0, 0) ? "group 0" : "off"); |
||
598 | len += sprintf(page + off + len, " daddr1: 0x%08x, %s\n", *PP32_BRK_DATA_ADDR(pp32, 1), PP32_BRK_GRPi_DATA_ADDRn(pp32, 1, 1) ? "group 1" : "off"); |
||
599 | len += sprintf(page + off + len, " rdval0: 0x%08x\n", *PP32_BRK_DATA_VALUE_RD(pp32, 0)); |
||
600 | len += sprintf(page + off + len, " rdval1: 0x%08x\n", *PP32_BRK_DATA_VALUE_RD(pp32, 1)); |
||
601 | len += sprintf(page + off + len, " wrval0: 0x%08x\n", *PP32_BRK_DATA_VALUE_WR(pp32, 0)); |
||
602 | len += sprintf(page + off + len, " wrval1: 0x%08x\n", *PP32_BRK_DATA_VALUE_WR(pp32, 1)); |
||
603 | } |
||
604 | |||
605 | *eof = 1; |
||
606 | |||
607 | return len; |
||
608 | } |
||
609 | |||
610 | static int proc_write_pp32(struct file *file, const char *buf, unsigned long count, void *data) |
||
611 | { |
||
612 | char str[2048]; |
||
613 | char *p; |
||
614 | int len, rlen; |
||
615 | |||
616 | int pp32 = 0; |
||
617 | u32 addr; |
||
618 | |||
619 | len = count < sizeof(str) ? count : sizeof(str) - 1; |
||
620 | rlen = len - copy_from_user(str, buf, len); |
||
621 | while ( rlen && str[rlen - 1] <= ' ' ) |
||
622 | rlen--; |
||
623 | str[rlen] = 0; |
||
624 | for ( p = str; *p && *p <= ' '; p++, rlen-- ); |
||
625 | if ( !*p ) |
||
626 | return 0; |
||
627 | |||
628 | if ( strincmp(p, "pp32 ", 5) == 0 ) |
||
629 | { |
||
630 | p += 5; |
||
631 | rlen -= 5; |
||
632 | |||
633 | while ( rlen > 0 && *p >= '0' && *p <= '9' ) |
||
634 | { |
||
635 | pp32 += *p - '0'; |
||
636 | p++; |
||
637 | rlen--; |
||
638 | } |
||
639 | while ( rlen > 0 && *p && *p <= ' ' ) |
||
640 | { |
||
641 | p++; |
||
642 | rlen--; |
||
643 | } |
||
644 | |||
645 | if ( pp32 >= NUM_OF_PP32 ) |
||
646 | { |
||
647 | printk(KERN_ERR __FILE__ ":%d:%s: incorrect pp32 index - %d\n", __LINE__, __FUNCTION__, pp32); |
||
648 | return count; |
||
649 | } |
||
650 | } |
||
651 | |||
652 | if ( stricmp(p, "start") == 0 ) |
||
653 | { |
||
654 | #ifdef CONFIG_AMAZON_SE |
||
655 | *PP32_CTRL_CMD(pp32) = 0; |
||
656 | #endif |
||
657 | *PP32_CTRL_CMD(pp32) = PP32_CTRL_CMD_RESTART; |
||
658 | } |
||
659 | else if ( stricmp(p, "stop") == 0 ) |
||
660 | { |
||
661 | #ifdef CONFIG_AMAZON_SE |
||
662 | *PP32_CTRL_CMD(pp32) = 0; |
||
663 | #endif |
||
664 | *PP32_CTRL_CMD(pp32) = PP32_CTRL_CMD_STOP; |
||
665 | } |
||
666 | else if ( stricmp(p, "step") == 0 ) |
||
667 | { |
||
668 | #ifdef CONFIG_AMAZON_SE |
||
669 | *PP32_CTRL_CMD(pp32) = 0; |
||
670 | #endif |
||
671 | *PP32_CTRL_CMD(pp32) = PP32_CTRL_CMD_STEP; |
||
672 | } |
||
673 | #ifdef CONFIG_VR9 |
||
674 | else if ( stricmp(p, "unfreeze") == 0 ) |
||
675 | *PP32_FREEZE &= ~(1 << (pp32 << 4)); |
||
676 | else if ( stricmp(p, "freeze") == 0 ) |
||
677 | *PP32_FREEZE |= 1 << (pp32 << 4); |
||
678 | #else |
||
679 | else if ( stricmp(p, "unfreeze") == 0 ) |
||
680 | *PP32_DBG_CTRL(pp32) = DBG_CTRL_RESTART; |
||
681 | else if ( stricmp(p, "freeze") == 0 ) |
||
682 | *PP32_DBG_CTRL(pp32) = DBG_CTRL_STOP; |
||
683 | #endif |
||
684 | else if ( strincmp(p, "pc0 ", 4) == 0 ) |
||
685 | { |
||
686 | p += 4; |
||
687 | rlen -= 4; |
||
688 | if ( stricmp(p, "off") == 0 ) |
||
689 | { |
||
690 | *PP32_BRK_TRIG(pp32) = PP32_BRK_GRPi_PCn_OFF(0, 0); |
||
691 | *PP32_BRK_PC_MASK(pp32, 0) = PP32_BRK_CONTEXT_MASK_EN; |
||
692 | *PP32_BRK_PC(pp32, 0) = 0; |
||
693 | } |
||
694 | else |
||
695 | { |
||
696 | addr = get_number(&p, &rlen, 1); |
||
697 | *PP32_BRK_PC(pp32, 0) = addr; |
||
698 | *PP32_BRK_PC_MASK(pp32, 0) = PP32_BRK_CONTEXT_MASK_EN | PP32_BRK_CONTEXT_MASK(0) | PP32_BRK_CONTEXT_MASK(1) | PP32_BRK_CONTEXT_MASK(2) | PP32_BRK_CONTEXT_MASK(3); |
||
699 | *PP32_BRK_TRIG(pp32) = PP32_BRK_GRPi_PCn_ON(0, 0); |
||
700 | } |
||
701 | } |
||
702 | else if ( strincmp(p, "pc1 ", 4) == 0 ) |
||
703 | { |
||
704 | p += 4; |
||
705 | rlen -= 4; |
||
706 | if ( stricmp(p, "off") == 0 ) |
||
707 | { |
||
708 | *PP32_BRK_TRIG(pp32) = PP32_BRK_GRPi_PCn_OFF(1, 1); |
||
709 | *PP32_BRK_PC_MASK(pp32, 1) = PP32_BRK_CONTEXT_MASK_EN; |
||
710 | *PP32_BRK_PC(pp32, 1) = 0; |
||
711 | } |
||
712 | else |
||
713 | { |
||
714 | addr = get_number(&p, &rlen, 1); |
||
715 | *PP32_BRK_PC(pp32, 1) = addr; |
||
716 | *PP32_BRK_PC_MASK(pp32, 1) = PP32_BRK_CONTEXT_MASK_EN | PP32_BRK_CONTEXT_MASK(0) | PP32_BRK_CONTEXT_MASK(1) | PP32_BRK_CONTEXT_MASK(2) | PP32_BRK_CONTEXT_MASK(3); |
||
717 | *PP32_BRK_TRIG(pp32) = PP32_BRK_GRPi_PCn_ON(1, 1); |
||
718 | } |
||
719 | } |
||
720 | else if ( strincmp(p, "daddr0 ", 7) == 0 ) |
||
721 | { |
||
722 | p += 7; |
||
723 | rlen -= 7; |
||
724 | if ( stricmp(p, "off") == 0 ) |
||
725 | { |
||
726 | *PP32_BRK_TRIG(pp32) = PP32_BRK_GRPi_DATA_ADDRn_OFF(0, 0); |
||
727 | *PP32_BRK_DATA_ADDR_MASK(pp32, 0) = PP32_BRK_CONTEXT_MASK_EN; |
||
728 | *PP32_BRK_DATA_ADDR(pp32, 0) = 0; |
||
729 | } |
||
730 | else |
||
731 | { |
||
732 | addr = get_number(&p, &rlen, 1); |
||
733 | *PP32_BRK_DATA_ADDR(pp32, 0) = addr; |
||
734 | *PP32_BRK_DATA_ADDR_MASK(pp32, 0) = PP32_BRK_CONTEXT_MASK_EN | PP32_BRK_CONTEXT_MASK(0) | PP32_BRK_CONTEXT_MASK(1) | PP32_BRK_CONTEXT_MASK(2) | PP32_BRK_CONTEXT_MASK(3); |
||
735 | *PP32_BRK_TRIG(pp32) = PP32_BRK_GRPi_DATA_ADDRn_ON(0, 0); |
||
736 | } |
||
737 | } |
||
738 | else if ( strincmp(p, "daddr1 ", 7) == 0 ) |
||
739 | { |
||
740 | p += 7; |
||
741 | rlen -= 7; |
||
742 | if ( stricmp(p, "off") == 0 ) |
||
743 | { |
||
744 | *PP32_BRK_TRIG(pp32) = PP32_BRK_GRPi_DATA_ADDRn_OFF(1, 1); |
||
745 | *PP32_BRK_DATA_ADDR_MASK(pp32, 1) = PP32_BRK_CONTEXT_MASK_EN; |
||
746 | *PP32_BRK_DATA_ADDR(pp32, 1) = 0; |
||
747 | } |
||
748 | else |
||
749 | { |
||
750 | addr = get_number(&p, &rlen, 1); |
||
751 | *PP32_BRK_DATA_ADDR(pp32, 1) = addr; |
||
752 | *PP32_BRK_DATA_ADDR_MASK(pp32, 1) = PP32_BRK_CONTEXT_MASK_EN | PP32_BRK_CONTEXT_MASK(0) | PP32_BRK_CONTEXT_MASK(1) | PP32_BRK_CONTEXT_MASK(2) | PP32_BRK_CONTEXT_MASK(3); |
||
753 | *PP32_BRK_TRIG(pp32) = PP32_BRK_GRPi_DATA_ADDRn_ON(1, 1); |
||
754 | } |
||
755 | } |
||
756 | else |
||
757 | { |
||
758 | |||
759 | printk("echo \"<command>\" > /proc/driver/ifx_ptm/pp32\n"); |
||
760 | printk(" command:\n"); |
||
761 | printk(" unfreeze - unfreeze pp32\n"); |
||
762 | printk(" freeze - freeze pp32\n"); |
||
763 | printk(" start - run pp32\n"); |
||
764 | printk(" stop - stop pp32\n"); |
||
765 | printk(" step - run pp32 with one step only\n"); |
||
766 | printk(" pc0 - pc0 <addr>/off, set break point PC0\n"); |
||
767 | printk(" pc1 - pc1 <addr>/off, set break point PC1\n"); |
||
768 | printk(" daddr0 - daddr0 <addr>/off, set break point data address 0\n"); |
||
769 | printk(" daddr1 - daddr1 <addr>/off, set break point data address 1\n"); |
||
770 | printk(" help - print this screen\n"); |
||
771 | } |
||
772 | |||
773 | if ( *PP32_BRK_TRIG(pp32) ) |
||
774 | *PP32_CTRL_OPT(pp32) = PP32_CTRL_OPT_STOP_ON_BREAKPOINT_ON; |
||
775 | else |
||
776 | *PP32_CTRL_OPT(pp32) = PP32_CTRL_OPT_STOP_ON_BREAKPOINT_OFF; |
||
777 | |||
778 | return count; |
||
779 | } |
||
780 | |||
781 | #endif |
||
782 | |||
783 | static int stricmp(const char *p1, const char *p2) |
||
784 | { |
||
785 | int c1, c2; |
||
786 | |||
787 | while ( *p1 && *p2 ) |
||
788 | { |
||
789 | c1 = *p1 >= 'A' && *p1 <= 'Z' ? *p1 + 'a' - 'A' : *p1; |
||
790 | c2 = *p2 >= 'A' && *p2 <= 'Z' ? *p2 + 'a' - 'A' : *p2; |
||
791 | if ( (c1 -= c2) ) |
||
792 | return c1; |
||
793 | p1++; |
||
794 | p2++; |
||
795 | } |
||
796 | |||
797 | return *p1 - *p2; |
||
798 | } |
||
799 | |||
800 | static int strincmp(const char *p1, const char *p2, int n) |
||
801 | { |
||
802 | int c1 = 0, c2; |
||
803 | |||
804 | while ( n && *p1 && *p2 ) |
||
805 | { |
||
806 | c1 = *p1 >= 'A' && *p1 <= 'Z' ? *p1 + 'a' - 'A' : *p1; |
||
807 | c2 = *p2 >= 'A' && *p2 <= 'Z' ? *p2 + 'a' - 'A' : *p2; |
||
808 | if ( (c1 -= c2) ) |
||
809 | return c1; |
||
810 | p1++; |
||
811 | p2++; |
||
812 | n--; |
||
813 | } |
||
814 | |||
815 | return n ? *p1 - *p2 : c1; |
||
816 | } |
||
817 | |||
818 | static int get_token(char **p1, char **p2, int *len, int *colon) |
||
819 | { |
||
820 | int tlen = 0; |
||
821 | |||
822 | while ( *len && !((**p1 >= 'A' && **p1 <= 'Z') || (**p1 >= 'a' && **p1<= 'z')) ) |
||
823 | { |
||
824 | (*p1)++; |
||
825 | (*len)--; |
||
826 | } |
||
827 | if ( !*len ) |
||
828 | return 0; |
||
829 | |||
830 | if ( *colon ) |
||
831 | { |
||
832 | *colon = 0; |
||
833 | *p2 = *p1; |
||
834 | while ( *len && **p2 > ' ' && **p2 != ',' ) |
||
835 | { |
||
836 | if ( **p2 == ':' ) |
||
837 | { |
||
838 | *colon = 1; |
||
839 | break; |
||
840 | } |
||
841 | (*p2)++; |
||
842 | (*len)--; |
||
843 | tlen++; |
||
844 | } |
||
845 | **p2 = 0; |
||
846 | } |
||
847 | else |
||
848 | { |
||
849 | *p2 = *p1; |
||
850 | while ( *len && **p2 > ' ' && **p2 != ',' ) |
||
851 | { |
||
852 | (*p2)++; |
||
853 | (*len)--; |
||
854 | tlen++; |
||
855 | } |
||
856 | **p2 = 0; |
||
857 | } |
||
858 | |||
859 | return tlen; |
||
860 | } |
||
861 | |||
862 | static int get_number(char **p, int *len, int is_hex) |
||
863 | { |
||
864 | int ret = 0; |
||
865 | int n = 0; |
||
866 | |||
867 | if ( (*p)[0] == '0' && (*p)[1] == 'x' ) |
||
868 | { |
||
869 | is_hex = 1; |
||
870 | (*p) += 2; |
||
871 | (*len) -= 2; |
||
872 | } |
||
873 | |||
874 | if ( is_hex ) |
||
875 | { |
||
876 | while ( *len && ((**p >= '0' && **p <= '9') || (**p >= 'a' && **p <= 'f') || (**p >= 'A' && **p <= 'F')) ) |
||
877 | { |
||
878 | if ( **p >= '0' && **p <= '9' ) |
||
879 | n = **p - '0'; |
||
880 | else if ( **p >= 'a' && **p <= 'f' ) |
||
881 | n = **p - 'a' + 10; |
||
882 | else if ( **p >= 'A' && **p <= 'F' ) |
||
883 | n = **p - 'A' + 10; |
||
884 | ret = (ret << 4) | n; |
||
885 | (*p)++; |
||
886 | (*len)--; |
||
887 | } |
||
888 | } |
||
889 | else |
||
890 | { |
||
891 | while ( *len && **p >= '0' && **p <= '9' ) |
||
892 | { |
||
893 | n = **p - '0'; |
||
894 | ret = ret * 10 + n; |
||
895 | (*p)++; |
||
896 | (*len)--; |
||
897 | } |
||
898 | } |
||
899 | |||
900 | return ret; |
||
901 | } |
||
902 | |||
903 | static inline void ignore_space(char **p, int *len) |
||
904 | { |
||
905 | while ( *len && (**p <= ' ' || **p == ':' || **p == '.' || **p == ',') ) |
||
906 | { |
||
907 | (*p)++; |
||
908 | (*len)--; |
||
909 | } |
||
910 | } |
||
911 | |||
912 | |||
913 | |||
914 | /* |
||
915 | * #################################### |
||
916 | * Global Function |
||
917 | * #################################### |
||
918 | */ |
||
919 | |||
920 | |||
921 | |||
922 | /* |
||
923 | * #################################### |
||
924 | * Init/Cleanup API |
||
925 | * #################################### |
||
926 | */ |
||
927 | |||
928 | static int __init ifx_ptm_test_init(void) |
||
929 | { |
||
930 | proc_file_create(); |
||
931 | |||
932 | return 0; |
||
933 | } |
||
934 | |||
935 | static void __exit ifx_ptm_test_exit(void) |
||
936 | { |
||
937 | proc_file_delete(); |
||
938 | } |
||
939 | |||
940 | module_init(ifx_ptm_test_init); |
||
941 | module_exit(ifx_ptm_test_exit); |
||
942 | |||
943 | #endif |