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