15d83527077c2c0fffe2991b9ad22422d8ef4bc7
[openwrt.git] / package / platform / lantiq / ltq-ptm / src / ifxmips_ptm_test.c
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