#include "fiq_debugger_ringbuf.h"
#define DEBUG_MAX 64
+#define CMD_COUNT 0x0f
#define MAX_UNHANDLED_FIQ_COUNT 1000000
#define THREAD_INFO(sp) ((struct thread_info *) \
char debug_buf[DEBUG_MAX];
int debug_count;
+ char cmd_buf[CMD_COUNT+1][DEBUG_MAX];
+ int back_pointer;
+ int current_pointer;
+
bool no_sleep;
bool debug_enable;
bool ignore_next_wakeup_irq;
/* This function CANNOT be called in FIQ context */
static void debug_irq_exec(struct fiq_debugger_state *state, char *cmd)
{
+ int invalid_cmd = 0;
if (!strcmp(cmd, "ps"))
do_ps(state);
- if (!strcmp(cmd, "sysrq"))
+ else if (!strcmp(cmd, "sysrq"))
do_sysrq(state, 'h');
- if (!strncmp(cmd, "sysrq ", 6))
+ else if (!strncmp(cmd, "sysrq ", 6))
do_sysrq(state, cmd[6]);
+ else {
+ invalid_cmd = 1;
+ memset(state->debug_buf, 0, DEBUG_MAX);
+ }
+
+ if (invalid_cmd == 0) {
+ state->current_pointer = (state->current_pointer-1) & CMD_COUNT;
+ if (strcmp(state->cmd_buf[state->current_pointer], state->debug_buf)) {
+ state->current_pointer = (state->current_pointer+1) & CMD_COUNT;
+ memset(state->cmd_buf[state->current_pointer], 0, DEBUG_MAX);
+ strcpy(state->cmd_buf[state->current_pointer], state->debug_buf);
+ }
+ memset(state->debug_buf, 0, DEBUG_MAX);
+ state->current_pointer = (state->current_pointer+1) & CMD_COUNT;
+ state->back_pointer = state->current_pointer;
+ }
}
+static char cmd_buf[][16] = {
+ {"pc"},
+ {"regs"},
+ {"allregs"},
+ {"bt"},
+ {"reboot"},
+ {"irqs"},
+ {"kmsg"},
+ {"version"},
+ {"sleep"},
+ {"nosleep"},
+ {"console"},
+ {"cpu"},
+ {"ps"},
+ {"sysrq"},
+};
+
static void debug_help(struct fiq_debugger_state *state)
{
debug_printf(state, "FIQ Debugger commands:\n"
return state->pdata->uart_getc(state->pdev);
}
+
+static int debug_cmd_check_back(struct fiq_debugger_state *state, char c)
+{
+ char *s;
+ int i = 0;
+ if (c == 'A') {
+ state->back_pointer = (state->back_pointer-1) & CMD_COUNT;
+ if (state->back_pointer != state->current_pointer) {
+ s = state->cmd_buf[state->back_pointer];
+ if (*s != 0) {
+ for(i = 0; i < strlen(state->debug_buf)-1; i++) {
+ state->pdata->uart_putc(state->pdev, 8);
+ state->pdata->uart_putc(state->pdev, ' ');
+ state->pdata->uart_putc(state->pdev, 8);
+ }
+ memset(state->debug_buf, 0, DEBUG_MAX);
+ strcpy(state->debug_buf, s);
+ state->debug_count = strlen(state->debug_buf);
+ debug_printf(state, state->debug_buf);
+ } else {
+ state->back_pointer = (state->back_pointer+1) & CMD_COUNT;
+ }
+
+ } else {
+ state->back_pointer = (state->back_pointer+1) & CMD_COUNT;
+ }
+ } else if (c == 'B') {
+
+ if (state->back_pointer != state->current_pointer) {
+ state->back_pointer = (state->back_pointer+1) & CMD_COUNT;
+ if(state->back_pointer == state->current_pointer){
+ goto cmd_clear;
+ } else {
+ s = state->cmd_buf[state->back_pointer];
+ if (*s != 0) {
+ for(i = 0; i < strlen(state->debug_buf)-1; i++) {
+ state->pdata->uart_putc(state->pdev, 8);
+ state->pdata->uart_putc(state->pdev, ' ');
+ state->pdata->uart_putc(state->pdev, 8);
+ }
+ memset(state->debug_buf, 0, DEBUG_MAX);
+ strcpy(state->debug_buf, s);
+ state->debug_count = strlen(state->debug_buf);
+ debug_printf(state, state->debug_buf);
+ }
+ }
+ } else {
+cmd_clear:
+ for(i = 0; i < strlen(state->debug_buf)-1; i++) {
+ state->pdata->uart_putc(state->pdev, 8);
+ state->pdata->uart_putc(state->pdev, ' ');
+ state->pdata->uart_putc(state->pdev, 8);
+ }
+ memset(state->debug_buf, 0, DEBUG_MAX);
+ state->debug_count = 0;
+ }
+ }
+ return 0;
+}
+
+static void debug_cmd_tab(struct fiq_debugger_state *state)
+{
+ int i,j;
+ int count = 0;
+
+ for (i = 0; i < ARRAY_SIZE(cmd_buf); i++) {
+ cmd_buf[i][15] = 1;
+ }
+
+ for (j = 1; j <= strlen(state->debug_buf); j++) {
+ count = 0;
+ for (i = 0; i < ARRAY_SIZE(cmd_buf); i++) {
+ if (cmd_buf[i][15] == 1) {
+ if (strncmp(state->debug_buf, cmd_buf[i], j)) {
+ cmd_buf[i][15] = 0;
+ } else {
+ count++;
+ }
+ }
+ }
+ if (count == 0)
+ break;
+ }
+
+ if (count == 1) {
+ for (i = 0; i < ARRAY_SIZE(cmd_buf); i++) {
+ if (cmd_buf[i][15] == 1)
+ break;
+ }
+
+ for(j = 0; j < strlen(state->debug_buf); j++) {
+ state->pdata->uart_putc(state->pdev, 8);
+ state->pdata->uart_putc(state->pdev, ' ');
+ state->pdata->uart_putc(state->pdev, 8);
+ }
+ memset(state->debug_buf, 0, DEBUG_MAX);
+ strcpy(state->debug_buf, cmd_buf[i]);
+ state->debug_count = strlen(state->debug_buf);
+ debug_printf(state, state->debug_buf);
+
+ }
+}
+
static bool debug_handle_uart_interrupt(struct fiq_debugger_state *state,
int this_cpu, void *regs, void *svc_sp)
{
state->console_enable = false;
debug_puts(state, "fiq debugger mode\n");
state->debug_count = 0;
+ state->back_pointer = CMD_COUNT;
+ state->current_pointer = CMD_COUNT;
+ memset(state->cmd_buf, 0, (CMD_COUNT+1)*DEBUG_MAX);
debug_prompt(state);
#ifdef CONFIG_FIQ_DEBUGGER_CONSOLE
} else if (state->console_enable && state->tty_rbuf) {
fiq_debugger_ringbuf_push(state->tty_rbuf, c);
signal_helper = true;
#endif
+ } else if (last_c == '[' && (c == 'A' || c == 'B' || c == 'C' || c == 'D')) {
+ if (state->debug_count > 0) {
+ state->debug_count--;
+ state->pdata->uart_putc(state->pdev, 8);
+ state->pdata->uart_putc(state->pdev, ' ');
+ state->pdata->uart_putc(state->pdev, 8);
+ }
+ debug_cmd_check_back(state, c);
+ //tab
+ } else if (c == 9) {
+ debug_cmd_tab(state);
} else if ((c >= ' ') && (c < 127)) {
if (state->debug_count < (DEBUG_MAX - 1)) {
state->debug_buf[state->debug_count++] = c;
state->pdata->uart_putc(state->pdev, 8);
state->pdata->uart_putc(state->pdev, ' ');
state->pdata->uart_putc(state->pdev, 8);
+ state->debug_buf[state->debug_count] = 0;
}
} else if ((c == 13) || (c == 10)) {
if (c == '\r' || (c == '\n' && last_c != '\r')) {
signal_helper |=
debug_fiq_exec(state, state->debug_buf,
regs, svc_sp);
+ if (signal_helper == false) {
+ state->current_pointer = (state->current_pointer-1) & CMD_COUNT;
+ if (strcmp(state->cmd_buf[state->current_pointer], state->debug_buf)) {
+ state->current_pointer = (state->current_pointer+1) & CMD_COUNT;
+ memset(state->cmd_buf[state->current_pointer], 0, DEBUG_MAX);
+ strcpy(state->cmd_buf[state->current_pointer], state->debug_buf);
+ }
+ memset(state->debug_buf, 0, DEBUG_MAX);
+ state->current_pointer = (state->current_pointer+1) & CMD_COUNT;
+ state->back_pointer = state->current_pointer;
+ }
} else {
debug_prompt(state);
}