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 */
75static inline void proc_file_create(void);
76static inline void proc_file_delete(void);
77
78/*
79 *  Proc Help Functions
80 */
81static int proc_write_mem(struct file *, const char *, unsigned long, void *);
82static int proc_read_pp32(char *, char **, off_t, int, int *, void *);
83static int proc_write_pp32(struct file *, const char *, unsigned long, void *);
84static int stricmp(const char *, const char *);
85static int strincmp(const char *, const char *, int);
86static int get_token(char **, char **, int *, int *);
87static int get_number(char **, int *, int);
88static 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
106static 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
129static 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
136static 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
148static 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
254static 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
333static 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
446static 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
610static 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
783static 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
800static 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
818static 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
862static 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
903static 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
928static int __init ifx_ptm_test_init(void)
929{
930    proc_file_create();
931
932    return 0;
933}
934
935static void __exit ifx_ptm_test_exit(void)
936{
937    proc_file_delete();
938}
939
940module_init(ifx_ptm_test_init);
941module_exit(ifx_ptm_test_exit);
942
943#endif
944