OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [rtos/] [ecos-2.0/] [packages/] [cygmon/] [v2_0/] [misc/] [monitor_cmd.c] - Blame information for rev 725

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 27 unneback
//==========================================================================
2
//
3
//      monitor_cmd.c
4
//
5
//      Monitor commands for the CygMON ROM monitor
6
//
7
//==========================================================================
8
//####ECOSGPLCOPYRIGHTBEGIN####
9
// -------------------------------------------
10
// This file is part of eCos, the Embedded Configurable Operating System.
11
// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
12
//
13
// eCos is free software; you can redistribute it and/or modify it under
14
// the terms of the GNU General Public License as published by the Free
15
// Software Foundation; either version 2 or (at your option) any later version.
16
//
17
// eCos is distributed in the hope that it will be useful, but WITHOUT ANY
18
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
19
// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
20
// for more details.
21
//
22
// You should have received a copy of the GNU General Public License along
23
// with eCos; if not, write to the Free Software Foundation, Inc.,
24
// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
25
//
26
// As a special exception, if other files instantiate templates or use macros
27
// or inline functions from this file, or you compile this file and link it
28
// with other works to produce a work based on this file, this file does not
29
// by itself cause the resulting work to be covered by the GNU General Public
30
// License. However the source code for this file must still be made available
31
// in accordance with section (3) of the GNU General Public License.
32
//
33
// This exception does not invalidate any other reasons why a work based on
34
// this file might be covered by the GNU General Public License.
35
//
36
// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
37
// at http://sources.redhat.com/ecos/ecos-license/
38
// -------------------------------------------
39
//####ECOSGPLCOPYRIGHTEND####
40
//==========================================================================
41
//#####DESCRIPTIONBEGIN####
42
//
43
// Author(s):    
44
// Contributors: gthomas, dmoseley
45
// Date:         1999-10-20
46
// Purpose:      Monitor commands for the CygMON ROM monitor
47
// Description:  
48
//               
49
//
50
//####DESCRIPTIONEND####
51
//
52
//=========================================================================
53
 
54
#ifdef HAVE_BSP
55
#include "cpu_info.h"
56
#include <bsp/bsp.h>
57
#include <bsp/cpu.h>
58
#include <bsp/hex-utils.h>
59
#ifdef __BOARD_HEADER__
60
#include __BOARD_HEADER__
61
#endif
62
#endif
63
#include <board.h>
64
#include <unistd.h>
65
#include <stdlib.h>
66
#include <monitor.h>
67
#include <ledit.h>
68
#include <string.h>
69
#include <ctype.h>
70
 
71
#ifdef HAVE_BSP
72
#include "fmt_util.h"
73
#include "tservice.h"
74
#endif
75
 
76
#ifdef __ECOS__
77
#include <cyg/hal/hal_stub.h>
78
#endif
79
 
80
#if USE_CYGMON_PROTOTYPES
81
/* Use common prototypes */
82
/* Some of the composed board.h files compose these
83
   prototypes redundently, but if they dont,
84
   these are the common definitions */
85
#include "fmt_util.h"   /* Interface to string formatting utilities */
86
#include "tservice.h"   /* Interface to target specific services */
87
#include "generic-stub.h" /* from libstub */
88
#endif /* USE_CYGMON_PROTOTYPES */
89
 
90
static int history_cmd(cmdmode_t mode) ;
91
 
92
#ifndef MAXLINELEN
93
#define MAXLINELEN 80
94
#endif
95
 
96
#define MAXLINES 23
97
 
98
char inbuf[MAXLINELEN] ;
99
static char cmd[MAXLINELEN];
100
 
101
#if ! defined(PROVIDE_CRASH_CMD)
102
#define PROVIDE_CRASH_CMD 0
103
#endif
104
 
105
#if PROVIDE_CRASH_CMD
106
/*
107
 * The crash command is used while debugging cygmon itself
108
 */
109
static int crash_cmd(cmdmode_t mode) ; /* Command to trap into cygmon */
110
#endif
111
 
112
struct cmdentry cmdtab[] = {
113
  {NULL, "baud",        set_serial_speed_cmd},
114
  {"b",  "break",       breakpoint_cmd},
115
#if HAVE_CACHE
116
  {NULL, "cache",       cache_cmd},
117
#endif
118
  {NULL, "copy",        copy_cmd},
119
#if PROVIDE_CRASH_CMD
120
  {NULL, "crash",       crash_cmd},
121
#endif
122
  {NULL, "crc",         checksumcmd},
123
  {"d",  "disassemble", disassemble_cmd},
124
  {NULL, "dump",        dump_cmd},
125
#if defined(NVRAM_ETH_ADDR)
126
  {NULL, "ethaddr",     ethaddr_cmd},
127
#endif
128
  {NULL, "fill",        fill_cmd},
129
  {NULL, "go",          go_cmd},
130
  {NULL, "help",        help_cmd},
131
  {"his","history",     history_cmd},
132
#ifdef MONITOR_CONTROL_INTERRUPTS
133
  {NULL, "interrupt",   int_cmd},
134
#endif
135
#if defined(NVRAM_IP_ADDR)
136
  {NULL, "ipaddr",      ipaddr_cmd},
137
#endif
138
  {NULL, "load",        load_cmd},
139
  {"m",  "memory",      mem_cmd},
140
#ifdef OTHERNAMES_CMD
141
  {"o",  "othernames",  othernames_cmd},
142
#endif
143
  {NULL, "port",        set_serial_port_cmd},
144
  {"r",  "register",    reg_cmd},
145
  {NULL, "reset",       reset_cmd},
146
#ifndef HAVE_BSP
147
  {NULL, "setargs",     set_program_args_cmd},
148
#endif
149
  {"si", "step",        step_cmd},
150
  {NULL, "swapmem",     swapmem_cmd},
151
#if defined(NVRAM_TCP_PORT)
152
  {NULL, "tcpport",     tcpport_cmd},
153
#endif
154
  {NULL, "terminal",    set_term_cmd},
155
#ifdef HAS_TIMER
156
  {NULL, "timer",       timer_cmd},
157
#endif
158
#if !defined(__ECOS__) || defined(CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS)
159
  {NULL, "transfer",    transfer_cmd},
160
#endif
161
  {"u",  "unbreak",     clear_breakpoint_cmd},
162
#if HAVE_USAGE
163
  {NULL, "usage",       memusage_cmd},
164
#endif
165
  {NULL, "version",     version_cmd},
166
  /* Really need to redo the way commands are done--there should be a
167
     dynamic list (perhaps in addition to the static one). */
168
#ifdef TARGET_COMMANDS
169
  TARGET_COMMANDS
170
#endif
171
 
172
  {NULL, NULL, NULL}
173
};
174
 
175
static int
176
alias_compare (char *cmd)
177
{
178
  int m = 0;
179
  int match = -1;
180
  int num_matches = 0;
181
 
182
  while (cmdtab[m].cmd != NULL)
183
    {
184
      if (cmdtab[m].alias != NULL && !strcmp (cmd, cmdtab[m].alias))
185
        {
186
          match = m;
187
          num_matches++;
188
          /* We're expecting that aliases will be defined
189
             uniquely, but just in case, we let the user know
190
             if there is a conflict */
191
          if (num_matches > 1)
192
            {
193
              xprintf ("Alias conflict. Executing last matching alias.\n");
194
            }
195
        }
196
      m++;
197
    }
198
  return match;
199
}
200
 
201
static int
202
command_compare (char *cmd)
203
{
204
  int m = 0;
205
  int match = -1;
206
  int num_matches = 0;
207
  int cmdlen = strlen(cmd) ;
208
  while (cmdtab[m].cmd != NULL)
209
    {
210
      if (!(strncmp (cmd,cmdtab[m].cmd, cmdlen)))
211
        {
212
          /* we found a match */
213
          num_matches++;
214
          if (num_matches == 2)  /* we found a second match */
215
            {
216
              xprintf ("Ambiguous command.  Possibilities are:\n%s\n%s\n",
217
                       cmdtab[match].cmd,
218
                       cmdtab[m].cmd);
219
            }
220
          else if (num_matches > 2)  /* we found another match */
221
            {
222
              /* Show the new possibility we just found */
223
              xprintf ("%s\n", cmdtab[m].cmd);
224
            }
225
          /* Point the match at the command we just looked at.
226
             We have to wait until now so that the first duplicate
227
             found can output the earlier match as well */
228
          match = m;
229
        }
230
      m++;
231
    }
232
  return ((num_matches == 1) ? match : -1);
233
}
234
 
235
#ifdef USE_HELP
236
void
237
usage (char *string)
238
{
239
  xprintf ("Usage: %s\n", string);
240
}
241
 
242
void
243
short_help (char *string)
244
{
245
  xprintf ("%s\n", string);
246
}
247
 
248
void
249
long_help (char *string)
250
{
251
  int linecnt = 0;
252
  int do_leave = 0;
253
 
254
  for (; *string && !do_leave; string++)
255
    {
256
      xprintf ("%c", *string);
257
      if (*string == '\n')
258
        {
259
          linecnt++;
260
          if (linecnt == MAXLINES)
261
            {
262
              int i;
263
 
264
              xprintf ("-More-");
265
              while ((i = input_char ()) >= 0)
266
                {
267
                  if (i == '\r' || i == '\n')
268
                    {
269
                      linecnt--;
270
                      break;
271
                    }
272
                  else if (i == ' ')
273
                    {
274
                      linecnt = 0;
275
                      break;
276
                    }
277
                  else if (i == 'q' || i == 'Q')
278
                    {
279
                      do_leave = 1;
280
                      break;
281
                    }
282
                  else
283
                    beep ();
284
                }
285
            }
286
        }
287
    }
288
  xprintf ("\n");
289
}
290
 
291
void
292
example (char *example)
293
{
294
  xprintf ("Example: %s\n", example);
295
}
296
 
297
#else
298
void
299
no_help (void)
300
{
301
  xprintf ("No help available.\n");
302
}
303
 
304
void
305
no_help_usage (void)
306
{
307
  xprintf ("Incorrect usage.\n");
308
}
309
#endif
310
 
311
int
312
help_cmd (cmdmode_t mode)
313
{
314
  int command_number = -2;
315
 
316
  if (mode == USAGE)
317
    {
318
      usage ("help [command]");
319
      return 0;
320
    }
321
  if (mode == SHORT_HELP)
322
    {
323
      short_help ("The help command");
324
      return 0;
325
    }
326
  if (mode == LONG_HELP)
327
    {
328
      help_cmd (USAGE);
329
      long_help ("\
330
The help command without arguments shows a list of all available commands\n\
331
with a short description of each one.  With a command name as an argument\n\
332
it shows usage for the command and a paragraph describing the command.\n\
333
Usage is shown as command name followed by names of extensions or arguments.\n\
334
Arguments in [brackets] are optional, plain text arguments are required.\n\
335
Note that all commands can be invoked by typing enough of the command name\n\
336
to uniquely specify the command.  Some commands have aliases, which are one\n\
337
letter abbreviations for commands which do not have unique first letters.\n\
338
Aliases for all commands are shown in the help screen, which displays\n\
339
commands in the format:\n\
340
command name: (alias, if any)  description of command \n");
341
      example("\
342
help foo \n\
343
Shows the help screen for the command foo.");
344
      return 0;
345
    }
346
 
347
  if (argvect[1] != NULL)
348
    {
349
      if (argvect[2] == NULL)
350
        {
351
          command_number = command_compare (argvect[1]);
352
          if (command_number < 0)
353
            {
354
              xprintf ("No such command as %s\n", argvect[1]);
355
            }
356
        }
357
 
358
      if (command_number < 0)
359
        {
360
          return help_cmd (USAGE);
361
        }
362
      else
363
        {
364
          return cmdtab[command_number].function (LONG_HELP);
365
        }
366
    }
367
  else
368
    {
369
      int i;
370
 
371
      xprintf ("Available commands are:\n");
372
      for (i = 0; cmdtab[i].cmd != NULL; i++)
373
        {
374
          int x = strlen (cmdtab[i].cmd) + 2;
375
 
376
          xprintf ("%s: ", cmdtab[i].cmd);
377
          if (cmdtab[i].alias != NULL)
378
            {
379
              xprintf("(%s)", cmdtab[i].alias);
380
              x += 2 + strlen(cmdtab[i].alias);
381
            }
382
          for (; x < 20; x++)
383
            {
384
              xprintf (" ");
385
            }
386
          cmdtab[i].function (SHORT_HELP);
387
          if ((i > 0) && (i % MAXLINES) == 0)
388
            {
389
              xprintf ("-More-");
390
              input_char ();
391
              xprintf ("\n");
392
            }
393
        }
394
    }
395
  return 0;
396
}
397
 
398
#if PROVIDE_CRASH_CMD
399
static int crash_cmd(cmdmode_t mode)
400
{
401
  switch (mode)
402
    {
403
    case USAGE : usage("crash")  ; break ;
404
    case SHORT_HELP : short_help("invoke the breakpoint function");
405
      break ;
406
    case LONG_HELP :
407
      long_help("The crash command calls the breakpoint function() which is useful\n\
408
only if you are using an additional debugger to debug this software and,\n\
409
the general exception handler is hooked to the other debugger\n") ;
410
      break ;
411
    case INVOCATION :
412
      dbg_breakpoint() ;
413
      break ;
414
    }
415
  return 0 ;
416
}
417
#endif /* provide_crash_command */
418
 
419
 
420
 
421
static int history_cmd(cmdmode_t mode)
422
{
423
    switch (mode)
424
    {
425
    case USAGE : usage("history")  ; break ;
426
    case SHORT_HELP : short_help("Print help about line editing features.");
427
      break ;
428
    case INVOCATION :
429
      printHistoryList();
430
      break;
431
    case LONG_HELP :
432
      long_help("Cygmon line editing allows you to repeat previously entered
433
commands. The line editing commands are:
434
        CR '\\n'  Execute the currently displayed command
435
        ctl-a    move to Beginning of line
436
        ctl-e    End of line
437
        ctl-f    Forward char
438
        ctl-b    Backward char
439
        ctl-k    Delete to end of line
440
        ctl-y    yank Character (undelete)
441
        ctl-d    Delete current character
442
        ctl-p    edit previous command
443
        ctl-u    Erase Line
444
        ctl-n    Edit next command") ;
445
      break ;
446
    }
447
  return 0 ;
448
} /* history_cmd */
449
 
450
#ifdef OTHERNAMES_CMD
451
/* Switch to using the othernames (ie alternate register names) */
452
int
453
othernames_cmd (cmdmode_t mode)
454
{
455
  if (mode == USAGE)
456
    {
457
      usage ("othernames");
458
      return 0;
459
    }
460
  if (mode == SHORT_HELP)
461
    {
462
      short_help ("Switch between alternate register names.");
463
      return 0;
464
    }
465
  if (mode == LONG_HELP)
466
    {
467
      othernames_cmd (USAGE);
468
      long_help ("\
469
The othernames command allows you to switch between alternate register
470
names for a given target.");
471
      example ("\
472
othernames\n\
473
Switches to the alternate register name set..");
474
      return 0;
475
    }
476
  OTHERNAMES_CMD();
477
 
478
  return 0;
479
}
480
#endif /* OTHERNAMES_CMD */
481
 
482
 
483
#if defined(NVRAM_ETH_ADDR)
484
int
485
ethaddr_cmd (cmdmode_t mode)
486
{
487
  int      i, n;
488
  unsigned char addr[6];
489
  char     *p;
490
 
491
  if (mode == USAGE)
492
    {
493
      usage ("ethaddr [xx:xx:xx:xx:xx:xx]");
494
      return 0;
495
    }
496
  if (mode == SHORT_HELP)
497
    {
498
      short_help ("get/set NVRAM backed ethernet address");
499
      return 0;
500
    }
501
  if (mode == LONG_HELP)
502
    {
503
      ethaddr_cmd (USAGE);
504
      long_help ("\
505
The ethaddr command is used to view and modify the non-volatile ethernet\n\
506
address. The address is specified by 6 colon-seperated 2 digit hexadecimal\n\
507
numbers. If no address is specified, the current address is displayed.\n");
508
      example ("ethaddr 00:00:8B:F1:36:01");
509
      return 0;
510
    }
511
 
512
  if (argvect[1] != NULL)
513
    {
514
      if (strlen(argvect[1]) != 17 || argvect[2] != NULL)
515
        {
516
          return ethaddr_cmd (USAGE);
517
        }
518
 
519
      for (i = 0, p = argvect[1]; i < 6; i++, p++)
520
        {
521
          n = __hex(*p++);
522
          if (n < 0)
523
            return ethaddr_cmd (USAGE);
524
          addr[i] = (n << 4);
525
          n = __hex(*p++);
526
          if (n < 0)
527
            return ethaddr_cmd (USAGE);
528
          addr[i] |= n;
529
 
530
          if (*p != ':' && !(i == 5 && *p == '\0'))
531
            return ethaddr_cmd (USAGE);
532
        }
533
      for (i = 0; i < 6; i++)
534
        NVRAM_ETH_ADDR(i) = addr[i];
535
    }
536
  else
537
    {
538
      for (i = 0; i < 5; i++)
539
        xprintf("%02x:", NVRAM_ETH_ADDR(i));
540
      xprintf("%02x\n", NVRAM_ETH_ADDR(i));
541
    }
542
 
543
  return 0;
544
}
545
#endif /* NVRAM_ETH_ADDR */
546
 
547
 
548
#if defined(NVRAM_IP_ADDR)
549
int
550
ipaddr_cmd (cmdmode_t mode)
551
{
552
  int      i, j, n;
553
  unsigned char addr[4];
554
  char     *p;
555
 
556
  if (mode == USAGE)
557
    {
558
      usage ("ipaddr [n.n.n.n]");
559
      return 0;
560
    }
561
  if (mode == SHORT_HELP)
562
    {
563
      short_help ("get/set NVRAM backed ip address");
564
      return 0;
565
    }
566
  if (mode == LONG_HELP)
567
    {
568
      ipaddr_cmd (USAGE);
569
      long_help ("\
570
The ipaddr command is used to view and modify the non-volatile internet\n\
571
address. The address is specified by 4 dot-seperated 1-3 digit decimal\n\
572
numbers. If no address is specified, the current address is displayed.\n");
573
      example ("ipaddr 192.161.0.1");
574
      return 0;
575
    }
576
 
577
  if (argvect[1] != NULL)
578
    {
579
      if (argvect[2] != NULL)
580
        return ipaddr_cmd (USAGE);
581
 
582
      p = argvect[1];
583
 
584
      for (i = 0; i < 3; i++, p++)
585
        {
586
          for (j = n = 0; j < 3 && isdigit(*p); j++, p++)
587
            n = n*10 + (*p - '0');
588
          if (j == 0 || *p != '.' || n > 255)
589
            return ipaddr_cmd (USAGE);
590
          addr[i] = n;
591
        }
592
      for (j = n = 0; j < 3 && isdigit(*p); j++, p++)
593
        n = n*10 + (*p - '0');
594
      if (j == 0 || *p != '\0' || n > 255)
595
        return ipaddr_cmd (USAGE);
596
      addr[i] = n;
597
 
598
      for (i = 0; i < 4; i++)
599
        NVRAM_IP_ADDR(i) = addr[i];
600
    }
601
  else
602
    {
603
      for (i = 0; i < 3; i++)
604
        xprintf("%d.", NVRAM_IP_ADDR(i));
605
      xprintf("%d\n", NVRAM_IP_ADDR(i));
606
    }
607
 
608
  return 0;
609
}
610
#endif /* NVRAM_IP_ADDR */
611
 
612
#if defined(NVRAM_TCP_PORT)
613
int
614
tcpport_cmd (cmdmode_t mode)
615
{
616
  int  n;
617
  char *p;
618
 
619
  if (mode == USAGE)
620
    {
621
      usage ("ethaddr [xx:xx:xx:xx:xx:xx]");
622
      return 0;
623
    }
624
  if (mode == SHORT_HELP)
625
    {
626
      short_help ("get/set NVRAM backed tcp port number");
627
      return 0;
628
    }
629
  if (mode == LONG_HELP)
630
    {
631
      tcpport_cmd (USAGE);
632
      long_help ("\
633
The tcpport command is used to view and modify the non-volatile tcp port\n\
634
address used for debugging. The address is specified by decimal numer in\n\
635
the range of 1-65535. If no port number is specified, the current port is\n\
636
displayed.\n");
637
      example ("tcpport 1000");
638
      return 0;
639
    }
640
 
641
  if (argvect[1] != NULL)
642
    {
643
      if (argvect[2] != NULL)
644
        return tcpport_cmd (USAGE);
645
 
646
      p = argvect[1];
647
      n = 0;
648
      while (isdigit(*p))
649
        {
650
          n = n*10 + (*p++ - '0');
651
          if (n > 65535)
652
            return tcpport_cmd (USAGE);
653
        }
654
      if (*p != '\0')
655
        return tcpport_cmd (USAGE);
656
 
657
      NVRAM_TCP_PORT(0) = (n >> 8) & 0xff;
658
      NVRAM_TCP_PORT(1) = n & 0xff;
659
    }
660
  else
661
    xprintf("%d\n", (NVRAM_TCP_PORT(0) << 8) + NVRAM_TCP_PORT(1));
662
 
663
  return 0;
664
}
665
#endif /* NVRAM_TCP_PORT */
666
 
667
 
668
#ifdef __ECOS__
669
#  if (CYG_BYTEORDER == CYG_LSBFIRST)
670
#    define LITTLE_ENDIAN_TARGET
671
#  else
672
#    define BIG_ENDIAN_TARGET
673
#  endif
674
#endif
675
 
676
#ifdef LITTLE_ENDIAN_TARGET
677
static int swap_bytes = 1;
678
#else
679
static int swap_bytes = 0;
680
#endif
681
 
682
int
683
get_memory_display_mode (void)
684
{
685
  return swap_bytes;
686
}
687
 
688
void
689
set_memory_display_mode (int mode)
690
{
691
  swap_bytes = mode;
692
}
693
 
694
 
695
/* Just to make DEFAULT_SIZE something usable, this may go elsewhere later.*/
696
#ifndef DEFAULT_SIZE
697
#define DEFAULT_SIZE 1
698
#endif
699
 
700
static int
701
get_cmd_size (void)
702
{
703
  int size = 0;
704
  char *sizestr;
705
 
706
  sizestr = strchr (argvect[0], '.');
707
 
708
  if (sizestr == NULL || sizestr[0] == '\0' || sizestr[1] == '\0')
709
    {
710
      size = DEFAULT_SIZE;
711
    }
712
  else
713
    {
714
      size = str2int (sizestr + 1, 10) / 8;
715
    }
716
  if (size != 1 && size != 2 && size != 4 && size != 8)
717
    {
718
      xprintf ("Invalid size.\n");
719
      return -1;
720
    }
721
  return size;
722
}
723
 
724
 
725
void
726
display_memory (char *value, int size, int littleEndian)
727
{
728
  int x;
729
  int start = littleEndian ? size - 1 : 0 ;
730
  int end = littleEndian ? -1 : size;
731
  int incr = littleEndian ? -1 : 1;
732
 
733
  if (value)
734
    {
735
      for (x = start; x != end; x += incr)
736
        xprintf ("%02x", value[x] & 0xff);
737
    }
738
  else
739
    {
740
      for (x = start; x != end; x += incr)
741
        xprintf ("..");
742
    }
743
}
744
 
745
 
746
static int
747
peek (void)
748
{
749
  mem_addr_t addr;
750
  int size = get_cmd_size ();
751
 
752
  if (size > 0)
753
    {
754
      /* We already checked to see if the command was legal when we called the
755
         function, so there's no need to worry about that here. */
756
 
757
      if (argvect[1] != 0)
758
        {
759
          char value[8];
760
 
761
          str2addr (argvect[1], &addr);
762
          if (read_memory (&addr, size, 1, value))
763
            {
764
              xprintf ("Memory read failed\n");
765
            }
766
          else
767
            {
768
              display_memory (value, size, get_memory_display_mode ());
769
              xprintf ("\n");
770
            }
771
        }
772
      else
773
        {
774
          xprintf ("Not enough arguments\n");
775
          return mem_cmd (USAGE);
776
        }
777
    }
778
  return 0;
779
}
780
 
781
/* Poke a single byte in memory. */
782
 
783
static int
784
poke (void)
785
{
786
  int size = 0;
787
 
788
  size = get_cmd_size ();
789
  if (size > 0)
790
    {
791
      /* We already checked to see if the command was legal when we called the
792
         function, so there's no need to worry about that here. */
793
 
794
      if ((argvect[1] != 0) && (argvect[2] != 0))
795
        {
796
          char value[8];
797
          mem_addr_t addr;
798
 
799
          str2addr (argvect[1], &addr);
800
          hex2bytes (argvect[2], value, size);
801
 
802
          if (get_memory_display_mode ())
803
            {
804
              /* Gotta swap this puppy. */
805
              int x;
806
 
807
              for (x = 0; x < (size / 2); x++)
808
                {
809
                  char tmp = value[x];
810
                  value [x] = value [size - 1 - x];
811
                  value [size - 1 - x] = tmp;
812
                }
813
            }
814
          if (write_memory (&addr, size, 1, value))
815
            {
816
              xprintf ("Memory write failed\n");
817
            }
818
#ifdef HAVE_BSP
819
          bsp_flush_dcache((void *)addr.addr, size);
820
          bsp_flush_icache((void *)addr.addr, size);
821
#endif
822
        }
823
      else
824
        {
825
          xprintf ("Not enough arguments\n");
826
          return mem_cmd (USAGE);
827
        }
828
    }
829
  return 0;
830
}
831
 
832
 
833
/* I am cheap and easy. */
834
int
835
mem_cmd (cmdmode_t mode)
836
{
837
  if (mode == USAGE)
838
    {
839
      usage ("memory[.size] address [value]");
840
      return 0;
841
    }
842
  if (mode == SHORT_HELP)
843
    {
844
      short_help ("read/write memory");
845
      return 0;
846
    }
847
  if (mode == LONG_HELP)
848
    {
849
      mem_cmd (USAGE);
850
      long_help ("\
851
The memory command is used to view and modify single locations in memory.\n\
852
It can take a size extension, which follows the command name or partial\n\
853
command name without a space, and is a period followed by the number of\n\
854
bits to be viewed or modified.  Options are 8, 16, 32, and 64.  Without\n\
855
a size extension, the memory command defaults to displaying or changing 8\n\
856
bits at a time.\n\
857
The memory command can take one or two arguments, independent of\n\
858
whether a size extension is specified.  With one argument, it displays the\n\
859
contents of the specified location.  With two arguments, it replaces the\n\
860
contents of the specified location with the specified value.\n");
861
      example ("\
862
memory.8 45f6b2 57\n\
863
Places the 8 bit value 57 at the location 45f6b2.");
864
      return 0;
865
    }
866
 
867
  if (argvect[1] == NULL || (argvect[2] != NULL && argvect[3] != NULL))
868
    {
869
      return mem_cmd (USAGE);
870
    }
871
  if (argvect[1] != NULL && argvect[2] != NULL)
872
    return poke ();
873
  else
874
    return peek ();
875
}
876
 
877
/* Memory dump function. */
878
 
879
int
880
dump_cmd (cmdmode_t mode)
881
{
882
  mem_addr_t addr;
883
  char value[8];
884
 
885
  if (mode == USAGE)
886
    {
887
      usage ("dump[.size] location [count]");
888
      return 0;
889
    }
890
  if (mode == SHORT_HELP)
891
    {
892
      short_help ("Memory dump command");
893
      return 0;
894
    }
895
  if (mode == LONG_HELP)
896
    {
897
      dump_cmd (USAGE);
898
      long_help ("\
899
The dump command displays a region of memory. If no count value is\n\
900
supplied, the command displays 16 bytes.  It can take a size\n\
901
extension, which follows the command name or partial command name\n\
902
without a space, and is a period followed by the number of bits to be\n\
903
viewed or modified.  Options are 8, 16, 32, and 64.  Without a size\n\
904
extension, the dump command defaults to displaying 8 bits at a time.\n\
905
Addresses are aligned to a 16-byte boundary.  Thus, dump 65 would show\n\
906
all bytes from 60 through 6f.\n");
907
      example ("\
908
dump 44f5\n\
909
Displays 16 bytes starting with 44f0 and ending with 44ff.");
910
      return 0;
911
    }
912
 
913
  if (argvect[1] != 0 && (argvect[2] == NULL || argvect[3] == NULL))
914
    {
915
      mem_addr_t start_addr;
916
      char chardumps[32];
917
      int offset;
918
      int count;
919
      int line;
920
      int size = get_cmd_size ();
921
      int i;
922
 
923
      if (size == -1)
924
          /*
925
           * Invalid size specified.
926
           */
927
          return 0;
928
 
929
      str2addr (argvect[1], &addr);
930
      if (argvect[2] != NULL)
931
        {
932
          count = str2int (argvect[2], 10);
933
          count = (count + 15) / 16;
934
        }
935
      else
936
        {
937
          count = 1;
938
        }
939
      ADD_ALIGN(&addr, &start_addr, 16);
940
      for (line = 0; line < count; line ++)
941
        {
942
          for (offset = 0; offset < 16; offset += size)
943
            {
944
              ADD_OFFSET(&start_addr, &addr, offset + line * 16);
945
 
946
              if (offset == 0)
947
                {
948
                  char buf[32];
949
 
950
                  addr2str (&addr, buf);
951
                  xprintf("%s: ", buf);
952
                }
953
              if (read_memory (&addr, size, 1, value))
954
                {
955
                  display_memory (0, size, get_memory_display_mode ());
956
                  for (i = 0; i < size; i++)
957
                    {
958
                      value[i] = 0;
959
                    }
960
                } else {
961
                  display_memory (value, size, get_memory_display_mode ());
962
                }
963
              xprintf (" ");
964
              for (i = 0; i < size; i++)
965
                {
966
                  chardumps[offset + i] = value[i] & 0x7f;
967
                  if (chardumps[offset + i] < 32)
968
                    chardumps[offset + i] = '.';
969
                }
970
            }
971
          xprintf (" ");
972
          for(i = 0; i < offset; i++)
973
            {
974
              xprintf ("%c", chardumps[i]);
975
            }
976
          xprintf ("\n");
977
        }
978
    }
979
  else
980
    {
981
      dump_cmd (USAGE);
982
    }
983
  return 0;
984
}
985
 
986
static int scnt;
987
static int (*srec_input_char) (void);
988
 
989
static inline int
990
gethexnibble(void)
991
{
992
  int ch;
993
 
994
  inbuf[scnt++] = ch = srec_input_char();
995
  if (ch >= '0' && ch <= '9')
996
    return (ch - '0');
997
  if (ch >= 'a' && ch <= 'f')
998
    return (ch - 'a' + 10);
999
  if (ch >= 'A' && ch <= 'F')
1000
    return (ch - 'A' + 10);
1001
 
1002
  inbuf[scnt] = '\0';
1003
  xprintf("Bad hex char: %s\n", inbuf);
1004
  return -1;
1005
}
1006
 
1007
 
1008
static inline int
1009
gethexbyte(void)
1010
{
1011
  int nib;
1012
  unsigned char n;
1013
 
1014
  if ((nib = gethexnibble()) < 0)
1015
    return -1;
1016
  n = nib << 4;
1017
  if ((nib = gethexnibble()) < 0)
1018
    return -1;
1019
  n |= nib;
1020
  return n;
1021
}
1022
 
1023
static inline int
1024
chk_cksum(unsigned int cksum, int rval)
1025
{
1026
  int n;
1027
 
1028
  if ((n = gethexbyte()) < 0)
1029
    return -1;
1030
 
1031
  cksum = ~cksum & 0xff;
1032
 
1033
  if (cksum != n)
1034
    {
1035
      inbuf[scnt] = '\0';
1036
      xprintf("Bad cksum[%02x]: %s\n", cksum, inbuf);
1037
      return -1;
1038
    }
1039
  return rval;
1040
}
1041
 
1042
int
1043
load_srec(srec_input_func_t inp_func)
1044
{
1045
  int count, dcount, data, n, addr_bytes = 0, is_term, is_comment;
1046
  unsigned int address, cksum;
1047
  unsigned char data_buf[256];
1048
  mem_addr_t memaddr;
1049
 
1050
  srec_input_char = inp_func;
1051
 
1052
  is_comment = is_term = 0;
1053
 
1054
  while (srec_input_char() != 'S')
1055
    ;
1056
 
1057
  scnt = 0;
1058
  inbuf[scnt++] = 'S';
1059
 
1060
  if ((n = gethexnibble()) < 0)
1061
    return -1;
1062
 
1063
  switch (n)
1064
    {
1065
      case 0:
1066
      case 5:
1067
        is_comment = 1;
1068
        break;
1069
 
1070
      case 1:
1071
      case 2:
1072
      case 3:
1073
        addr_bytes = n + 1;
1074
        break;
1075
 
1076
      case 7:
1077
      case 8:
1078
      case 9:
1079
        is_term = 1;
1080
        addr_bytes = 11 - n;
1081
        break;
1082
 
1083
      default:
1084
        inbuf[scnt] = '\0';
1085
        xprintf("Bad record type: %s\n", inbuf);
1086
        return -1;
1087
    }
1088
 
1089
  if ((count = gethexbyte()) < 0)
1090
    return -1;
1091
  cksum = count;
1092
 
1093
  --count; /* don't count chksum */
1094
 
1095
  if (is_comment)
1096
    {
1097
      while (count > 0)
1098
        {
1099
          if ((n = gethexbyte()) < 0)
1100
            return -1;
1101
          cksum += n;
1102
          --count;
1103
        }
1104
      return chk_cksum(cksum, 0);
1105
    }
1106
 
1107
  address = 0;
1108
  while (count > 0 && addr_bytes)
1109
    {
1110
      if ((n = gethexbyte()) < 0)
1111
        return -1;
1112
      cksum += n;
1113
      address = (address << 8) | n;
1114
      --addr_bytes;
1115
      --count;
1116
    }
1117
 
1118
  if (is_term)
1119
    {
1120
      if (count || addr_bytes)
1121
        {
1122
          inbuf[scnt] = '\0';
1123
          xprintf("Malformed record cnt[%d] abytes[%d]: %s\n",
1124
                 count, addr_bytes, inbuf);
1125
          return -1;
1126
        }
1127
      if (chk_cksum(cksum, 1) == 1)
1128
        {
1129
          set_pc (address);
1130
          xprintf("Setting start address: 0x%08x\n", address);
1131
          return 1;
1132
        }
1133
      return -1;
1134
    }
1135
 
1136
  dcount = 0;
1137
 
1138
  while (count > 0)
1139
    {
1140
      if ((data = gethexbyte()) < 0)
1141
        return -1;
1142
      cksum += data;
1143
      data_buf[dcount++] = data;
1144
      --count;
1145
    }
1146
 
1147
  if (chk_cksum(cksum, 0))
1148
    return -1;
1149
 
1150
  MAKE_STD_ADDR (address, &memaddr);
1151
  write_memory (&memaddr, 1, dcount, data_buf);
1152
#ifdef HAVE_BSP
1153
  bsp_flush_dcache((void *)memaddr.addr, dcount);
1154
  bsp_flush_icache((void *)memaddr.addr, dcount);
1155
#endif
1156
 
1157
  return 0;
1158
}
1159
 
1160
 
1161
int
1162
load_cmd (cmdmode_t mode)
1163
{
1164
  if (mode == USAGE)
1165
    {
1166
      usage ("load");
1167
      return 0;
1168
    }
1169
  if (mode == SHORT_HELP)
1170
    {
1171
      short_help ("Load srecords into memory");
1172
      return 0;
1173
    }
1174
  if (mode == LONG_HELP)
1175
    {
1176
      load_cmd (USAGE);
1177
      long_help ("\
1178
The load command switches the monitor into a state where it takes all input
1179
as s-records and stores them in memory.  The monitor exits this mode when a
1180
termination record is hit, or certain errors (such as an invalid s-record)
1181
cause the load to fail.");
1182
      return 0;
1183
    }
1184
 
1185
  if (argvect[1] != NULL)
1186
    {
1187
      return load_cmd (USAGE);
1188
    }
1189
 
1190
  while (!load_srec(xgetchar))
1191
      ;
1192
 
1193
  return 0;
1194
}
1195
 
1196
#ifndef REGNAME_EXAMPLE
1197
# define REGNAME_EXAMPLE "a0"
1198
#endif
1199
 
1200
#if !defined(__ECOS__) || defined(CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS)
1201
int
1202
transfer_cmd (cmdmode_t mode)
1203
{
1204
  if (mode == USAGE)
1205
    {
1206
      usage ("$");
1207
      return 0;
1208
    }
1209
  if (mode == SHORT_HELP)
1210
    {
1211
      short_help ("Transfer to gdb stub");
1212
      return 0;
1213
    }
1214
  if (mode == LONG_HELP)
1215
    {
1216
      transfer_cmd (USAGE);
1217
      long_help ("\
1218
The transfer or $ command transfers control to the gdb stub.  This function\n\
1219
does not actually need to be called by the user, as connecting to the board\n\
1220
with gdb will call it automatically.  The transfer command takes no\n\
1221
arguments.  The $ command does not wait for a return, but executes\n\
1222
immediately.  A telnet setup in line mode will require a return when $ is\n\
1223
executed by the user, as the host computer does not pass any characters to\n\
1224
the monitor until a return is pressed.  Disconnecting from the board in gdb\n\
1225
automatically returns control to the monitor.");
1226
      return 0;
1227
    }
1228
  if (argvect[1] == NULL)
1229
    {
1230
      return transfer_to_stub ();
1231
    }
1232
  else
1233
    {
1234
      transfer_cmd (USAGE);
1235
    }
1236
  return 0;
1237
}
1238
#endif
1239
 
1240
static void
1241
display_group (int which_group)
1242
{
1243
  int len = 0;
1244
  int skipping_group = 0;
1245
  char buf[80];
1246
  int start_entry = 0;
1247
  int i;
1248
 
1249
  if (which_group >= 0)
1250
    {
1251
      start_entry = which_group;
1252
    }
1253
 
1254
  for (i = start_entry; regtab[i].registername != NULL; i++)
1255
    {
1256
      int buflen;
1257
 
1258
      if (regtab[i].registernumber < 0)
1259
        {
1260
          if (which_group >= 0 && i != which_group)
1261
            {
1262
              break;
1263
            }
1264
 
1265
          if (len > 0)
1266
            {
1267
              xprintf ("\n");
1268
              len = 0;
1269
            }
1270
          if (which_group < 0)
1271
            {
1272
              if (regtab[i].registernumber == -2)
1273
                {
1274
                  skipping_group = 1;
1275
                  xprintf ("[skipping %s]\n", regtab[i].registername);
1276
                }
1277
              else
1278
                {
1279
                  skipping_group = 0;
1280
                  xprintf ("[%s]\n", regtab[i].registername);
1281
#if 0
1282
                  len = strlen (regtab[i].registername) + 2;
1283
                  while (len < MAXLINES)
1284
                    {
1285
                      xputchar (' ');
1286
                      len++;
1287
                    }
1288
#endif
1289
                }
1290
            }
1291
        }
1292
      else
1293
        if (!skipping_group)
1294
          {
1295
#ifdef REG_VALID_FIELD_IN_REGSTRUCT
1296
#define REGVALID_VAL regtab[i].registervalid
1297
#else
1298
#define REGVALID_VAL 1
1299
#endif
1300
            xsprintf(buf, "%4s: %s",
1301
                     regtab[i].registername,
1302
                     get_register_str (regtab[i].registernumber, 0 , REGVALID_VAL));
1303
#undef REGVALID_VAL
1304
            buflen = strlen (buf);
1305
            if ((buflen + len + 3) >= 80)
1306
              {
1307
                xprintf ("\n");
1308
                len = 0;
1309
              }
1310
            else if(len > 0)
1311
              {
1312
                xprintf ("   ");
1313
                len += 3;
1314
              }
1315
 
1316
            xprintf (buf);
1317
            len += buflen;
1318
          }
1319
    }
1320
  if (len > 0)
1321
    {
1322
      xprintf ("\n");
1323
    }
1324
}
1325
 
1326
static int
1327
getregister (void)
1328
{
1329
  int i;
1330
 
1331
  if (argvect[1] == 0)
1332
    {
1333
      display_group (-1);
1334
    }
1335
  else
1336
    {
1337
      for (i = 0; regtab[i].registername != NULL; i++)
1338
        {
1339
          if (!(strcmp (argvect[1], regtab[i].registername)))
1340
            {
1341
              break;
1342
            }
1343
        }
1344
      if (regtab[i].registername == NULL)
1345
        {
1346
          xprintf ("No such register\n");
1347
        }
1348
      else
1349
        {
1350
          if (regtab[i].registernumber < 0)
1351
            {
1352
              display_group (i);
1353
            }
1354
          else
1355
            {
1356
#ifdef REG_VALID_FIELD_IN_REGSTRUCT
1357
#define REGVALID_VAL regtab[i].registervalid
1358
#else
1359
#define REGVALID_VAL 1
1360
#endif
1361
              xprintf("%s: %s\n", argvect[1],
1362
                      get_register_str (regtab[i].registernumber, 1, REGVALID_VAL));
1363
#undef REGVALID_VAL
1364
            }
1365
        }
1366
    }
1367
  return 0;
1368
}
1369
 
1370
static int
1371
setregister (void)
1372
{
1373
  int number = -1;
1374
  int i;
1375
  if ((argvect[1] != 0) && (argvect[2] != 0))
1376
    {
1377
      i = 0;
1378
      while (regtab[i].registername != NULL)
1379
        {
1380
          if (!(strcmp (argvect[1], regtab[i].registername)))
1381
            {
1382
              number = regtab[i].registernumber;
1383
              break;
1384
            }
1385
          i++;
1386
        }
1387
      if (number < 0)
1388
        xprintf ("Unknown register name %s\n", argvect[1]);
1389
      else
1390
        store_register (number, argvect[2]);
1391
    }
1392
  else
1393
    {
1394
      xprintf ("Not enough arguments\n");
1395
    }
1396
  return 0;
1397
}
1398
 
1399
 
1400
int
1401
reg_cmd (cmdmode_t mode)
1402
{
1403
  if (mode == USAGE)
1404
    {
1405
      usage ("register [register name] [value]");
1406
      return 0;
1407
    }
1408
  if (mode == SHORT_HELP)
1409
    {
1410
      short_help ("View and manipulate registers");
1411
      return 0;
1412
    }
1413
  if (mode == LONG_HELP)
1414
    {
1415
      reg_cmd (USAGE);
1416
      long_help ("\
1417
The register command allows the viewing and manipulation of register\n\
1418
contents.  It can take zero, one, or two arguments.  When called with zero\n\
1419
arguments, the register command displays the values of all registers.  When\n\
1420
called with only the register name argument, it displays the contents of\n\
1421
the specified register.  When called with both a register name and a value,\n\
1422
it places that value into the specified register.\n");
1423
      example ("\
1424
register " REGNAME_EXAMPLE " 1f\n\
1425
Places the value 1f in the register " REGNAME_EXAMPLE);
1426
      return 0;
1427
    }
1428
 
1429
  if (argvect[1] != NULL && argvect[2] != NULL)
1430
    {
1431
      if (argvect[3] != NULL)
1432
        {
1433
          return reg_cmd (USAGE);
1434
        }
1435
      return setregister ();
1436
    }
1437
  else
1438
    return getregister ();
1439
}
1440
 
1441
 
1442
/* execute the program in memory */
1443
int
1444
go_cmd (cmdmode_t mode)
1445
{
1446
#ifdef HAS_TIMER
1447
  extern tick_type start_tickcount;
1448
#endif
1449
 
1450
  if (mode == USAGE)
1451
    {
1452
      usage ("go [location]");
1453
      return 0;
1454
    }
1455
  if (mode == SHORT_HELP)
1456
    {
1457
      short_help ("Start user program execution");
1458
      return 0;
1459
    }
1460
  if (mode == LONG_HELP)
1461
    {
1462
      go_cmd (USAGE);
1463
      long_help ("\
1464
The go command starts user program execution.  It can take zero or one\n\
1465
argument.  If no argument is provided, go starts execution at the current\n\
1466
pc.  If an argument is specified, go sets the pc to that location, and then\n\
1467
starts execution at that location.\n");
1468
      example ("
1469
go 40020000\n\
1470
Sets the pc to 40020000, and starts program execution.");
1471
      return 0;
1472
    }
1473
 
1474
  if (argvect[1] != NULL && argvect[2] != NULL)
1475
    {
1476
      return go_cmd (USAGE);
1477
    }
1478
  if (argvect[1] != NULL)
1479
    {
1480
      set_pc (str2int (argvect[1], 16));
1481
    }
1482
 
1483
#ifdef HAS_TIMER
1484
  start_tickcount = __read_ticks ();
1485
#endif
1486
  /* We want monitor_loop to exit now. */
1487
  return 1;
1488
}
1489
 
1490
#ifdef HAS_TIMER
1491
int
1492
timer_cmd (cmdmode_t mode)
1493
{
1494
  if (mode == USAGE)
1495
    {
1496
      usage ("timer [state]");
1497
      return 0;
1498
    }
1499
  if (mode == SHORT_HELP)
1500
    {
1501
      short_help ("Enable and disable timer");
1502
      return 0;
1503
    }
1504
  if (mode == LONG_HELP)
1505
    {
1506
      timer_cmd (USAGE);
1507
      long_help ("\
1508
The timer command allows control of the on board timer.  It takes zero\n\
1509
or one argument.  With zero arguments, it displays the state of the timer,\n\
1510
with one argument, which can start with  e or d, it enables or disables the\n\
1511
timer, respectively.\n");
1512
      example ("\
1513
timer e\n\
1514
Enables the timer.");
1515
      return 0;
1516
    }
1517
 
1518
  if (argvect[1] != NULL)
1519
    {
1520
      if (argvect[2] != NULL)
1521
        {
1522
          return timer_cmd (USAGE);
1523
        }
1524
      else if (argvect[1][0] == 'e')
1525
        {
1526
          __settimer (0, 0);
1527
        }
1528
      else if (argvect[1][0] == 'd')
1529
        {
1530
          __disable_timer ();
1531
        }
1532
      else
1533
        {
1534
          timer_cmd (USAGE);
1535
        }
1536
    }
1537
  if (__timer_enabled ())
1538
    {
1539
      xprintf ("Timer is currently enabled.\n");
1540
    }
1541
  else
1542
    {
1543
      xprintf ("Timer is currently disabled.\n");
1544
    }
1545
  return 0;
1546
}
1547
#endif
1548
 
1549
int
1550
clear_breakpoint_cmd (cmdmode_t mode)
1551
{
1552
  if (mode == USAGE)
1553
    {
1554
      usage ("unbreak location");
1555
      return 0;
1556
    }
1557
  if (mode == SHORT_HELP)
1558
    {
1559
      short_help ("Clear breakpoint");
1560
      return 0;
1561
    }
1562
  if (mode == LONG_HELP)
1563
    {
1564
      clear_breakpoint_cmd (USAGE);
1565
      long_help ("\
1566
The unbreak command removes breakpoints from memory.  It takes one\n\
1567
argument, the location to remove the breakpoint from.\n");
1568
      example ("\
1569
unbreak 4ff5\n\
1570
Removes a previously set breakpoint at memory location 4ff5.");
1571
      return 0;
1572
    }
1573
 
1574
  if (argvect[1] == NULL || argvect[2] != NULL)
1575
    {
1576
      clear_breakpoint_cmd (USAGE);
1577
    }
1578
  else
1579
    {
1580
      mem_addr_t location;
1581
      str2addr (argvect[1], &location);
1582
      if (clear_mon_breakpoint (location))
1583
      {
1584
          xprintf("Unable to remove breakpoint at 0x%08lx\n", location.addr);
1585
      }
1586
    }
1587
  return 0;
1588
}
1589
 
1590
 
1591
int
1592
breakpoint_cmd (cmdmode_t mode)
1593
{
1594
  if (mode == USAGE)
1595
    {
1596
      usage ("break [location]");
1597
      return 0;
1598
    }
1599
  if (mode == SHORT_HELP)
1600
    {
1601
      short_help ("Set or display breakpoints");
1602
      return 0;
1603
    }
1604
  if (mode == LONG_HELP)
1605
    {
1606
      breakpoint_cmd (USAGE);
1607
      long_help ("\
1608
The break command displays and sets breakpoints in memory.  It takes zero\n\
1609
or one argument.  With zero arguments, it displays a list of all currently\n\
1610
set breakpoints.  With one argument it sets a new breakpoint at the\n\
1611
specified location.\n");
1612
      example ("\
1613
break 4ff5\n\
1614
Sets a breakpoint at address 4ff5.");
1615
      return 0;
1616
    }
1617
 
1618
  if (argvect[1] == NULL)
1619
    {
1620
      return show_breakpoints ();
1621
    }
1622
  else if (argvect[2] != NULL)
1623
    {
1624
      breakpoint_cmd (USAGE);
1625
    }
1626
  else
1627
    {
1628
      mem_addr_t location;
1629
 
1630
      str2addr (argvect[1], &location);
1631
      if (add_mon_breakpoint (location))
1632
      {
1633
          xprintf("Unable to set breakpoint at 0x%08lx\n", location.addr);
1634
      }
1635
    }
1636
  return 0;
1637
}
1638
 
1639
 
1640
int
1641
version_cmd (cmdmode_t mode)
1642
{
1643
  if (mode == USAGE)
1644
    {
1645
      usage ("version");
1646
      return 0;
1647
    }
1648
  if (mode == SHORT_HELP)
1649
    {
1650
      short_help ("Display version");
1651
      return 0;
1652
    }
1653
  if (mode == LONG_HELP)
1654
    {
1655
      version_cmd (USAGE);
1656
      long_help ("\
1657
The version command displays the version of the monitor.");
1658
      return 0;
1659
    }
1660
 
1661
  if (argvect[1] == NULL)
1662
    {
1663
      version ();
1664
    }
1665
  else
1666
    {
1667
      version_cmd (USAGE);
1668
    }
1669
  return 0;
1670
}
1671
 
1672
int
1673
set_serial_port_cmd (cmdmode_t mode)
1674
{
1675
  if (mode == USAGE)
1676
    {
1677
      usage ("port [port number]");
1678
      return 0;
1679
    }
1680
  if (mode == SHORT_HELP)
1681
    {
1682
      short_help ("Set the active serial port");
1683
      return 0;
1684
    }
1685
  if (mode == LONG_HELP)
1686
    {
1687
      set_serial_port_cmd (USAGE);
1688
      long_help ("\
1689
The port command allows control over the serial port being used by the\n\
1690
monitor.  It takes zero or one argument.  Called with zero arguments it\n\
1691
displays the port currently in use by the monitor.  Called with one\n\
1692
argument it switches the port in use by the monitor to the one specified.\n\
1693
It then prints out a message on the new port to confirm the switch.\n");
1694
      example ("\
1695
port 1\n\
1696
Switches the port in use by the monitor to port 1.");
1697
      return 0;
1698
    }
1699
  if (argvect[1] != NULL && argvect[2] != NULL)
1700
    {
1701
      set_serial_port_cmd (USAGE);
1702
      return 0;
1703
    }
1704
  if (argvect [1] != NULL)
1705
    {
1706
#ifdef HAVE_BSP
1707
      if (bsp_set_debug_comm(str2int (argvect[1], 10)) < 0)
1708
        xprintf("Invalid port number.\n");
1709
      else
1710
        /* Since we are using the new port, we just need to write
1711
           something to tell the user that this is the active port */
1712
        xprintf ("Cygmon I/O now on this port.\n");
1713
#else
1714
      __setTty (str2int (argvect[1], 10));
1715
      /* Since we are using the new port, we just need to write
1716
         something to tell the user that this is the active port */
1717
      xprintf ("Cygmon I/O now on this port.\n");
1718
#endif
1719
    }
1720
  else
1721
    {
1722
      xprintf ("serial port currently set to %d\n", __getTty());
1723
      return 0;
1724
    }
1725
  return 0;
1726
}
1727
 
1728
int
1729
step_cmd (cmdmode_t mode)
1730
{
1731
  if (mode == USAGE)
1732
    {
1733
      usage ("step [location]");
1734
      return 0;
1735
    }
1736
  if (mode == SHORT_HELP)
1737
    {
1738
      short_help ("Single step user program");
1739
      return 0;
1740
    }
1741
  if (mode == LONG_HELP)
1742
    {
1743
      step_cmd (USAGE);
1744
      long_help ("\
1745
The step command causes one instruction of the user program to execute, then\n\
1746
returns control to the monitor.  It can take zero or one argument.  If no\n\
1747
argument is provided, step executes one instruction at the current pc.  If\n\
1748
a location is specified, step executes one instruction at the specified\n\
1749
location.\n");
1750
      example ("
1751
step\n\
1752
Executes one instruction at the current pc.");
1753
      return 0;
1754
    }
1755
 
1756
  if (argvect[1] != NULL && argvect[2] != NULL)
1757
    {
1758
      step_cmd (USAGE);
1759
      return 0;
1760
    }
1761
  if (argvect[1] != NULL)
1762
    set_pc (str2int (argvect[1], 16));
1763
 
1764
  __single_step ();
1765
  return 1;
1766
 
1767
}
1768
 
1769
#if HAVE_CACHE
1770
/* This cache function needs to be in processor-specific files. */
1771
 
1772
int
1773
cache_cmd (cmdmode_t mode)
1774
{
1775
  int x;
1776
  int cache_op = CACHE_NOOP;
1777
  int which_cache = -1;
1778
 
1779
  if (mode == USAGE)
1780
    {
1781
      usage ("cache [type] [state]");
1782
      return 0;
1783
    }
1784
  if (mode == SHORT_HELP)
1785
    {
1786
      short_help ("Manipulate caches");
1787
      return 0;
1788
    }
1789
  if (mode == LONG_HELP)
1790
    {
1791
      cache_cmd (USAGE);
1792
      long_help ("\
1793
The cache command displays and changes the states of the caches.  It takes\n\
1794
zero, one, or two arguments.  With no arguments, it displays the state of\n\
1795
both the instruction cache and the data cache.  With one argument, it\n\
1796
displays the state of the specified type of cache.  With two arguments, it\n\
1797
changes the state of the specified cache to the specified state.\n");
1798
      example ("\
1799
cache i d\n\
1800
Disables the instruction cache.");
1801
      return 0;
1802
    }
1803
 
1804
  if (argvect[1] != NULL && argvect[2] != NULL && argvect[3] != NULL)
1805
    {
1806
      return cache_cmd (USAGE);
1807
    }
1808
  if (argvect[1] != NULL)
1809
    {
1810
      if (argvect[1][0] == 'd')
1811
        which_cache = 0;
1812
      else if (argvect[1][0] == 'i')
1813
        which_cache = 1;
1814
      else
1815
        {
1816
          xprintf ("unknown cache type %s\n", argvect[1]);
1817
          return 0;
1818
        }
1819
      if (argvect[2] != NULL)
1820
        {
1821
          if (argvect[2][0] == 'e')
1822
            cache_op = CACHE_ENABLE;
1823
          else if (argvect[2][0] == 'd')
1824
            cache_op = CACHE_DISABLE;
1825
          else if (argvect[2][0] == 'f')
1826
            cache_op = CACHE_FLUSH;
1827
          else
1828
            {
1829
              xprintf ("Unknown cache op %s\n", argvect[2]);
1830
              return 0;
1831
            }
1832
        }
1833
    }
1834
  if (which_cache == 0 || which_cache == -1)
1835
    {
1836
      __data_cache (cache_op);
1837
      if (cache_op == CACHE_FLUSH)
1838
      {
1839
        xprintf ("Flushed dcache\n");
1840
      }
1841
      x = __data_cache (CACHE_NOOP);
1842
      xprintf ("dcache is ");
1843
      xprintf (x ? "enabled\n" : "disabled\n");
1844
    }
1845
  if (which_cache == 1 || which_cache == -1)
1846
    {
1847
      __instruction_cache (cache_op);
1848
      if (cache_op == CACHE_FLUSH)
1849
      {
1850
        xprintf ("Flushed icache\n");
1851
      }
1852
      x = __instruction_cache (CACHE_NOOP);
1853
      xprintf ("icache is ");
1854
      xprintf (x ? "enabled\n" : "disabled\n");
1855
    }
1856
  return 0;
1857
}
1858
#endif
1859
 
1860
int
1861
set_serial_speed_cmd (cmdmode_t mode)
1862
{
1863
    if (mode == USAGE)
1864
    {
1865
      usage ("baud speed");
1866
      return 0;
1867
    }
1868
  if (mode == SHORT_HELP)
1869
    {
1870
      short_help ("Set serial port baud rate");
1871
      return 0;
1872
    }
1873
  if (mode == LONG_HELP)
1874
    {
1875
      set_serial_speed_cmd (USAGE);
1876
      long_help ("\
1877
The baud command sets the speed of the active serial port.  It takes one\n\
1878
argument, which specifies the speed to which the port will be set.\n");
1879
      example ("\
1880
baud 9600\n\
1881
Sets the speed of the active port to 9600 baud.");
1882
      return 0;
1883
    }
1884
 
1885
  if (argvect[1] == NULL || argvect[2] != NULL)
1886
    {
1887
      return set_serial_speed_cmd (USAGE);
1888
    }
1889
  else
1890
    {
1891
#ifdef HAVE_BSP
1892
      int channel_id = bsp_set_debug_comm(-1);
1893
      int baud = str2int (argvect[1], 10);
1894
 
1895
      xprintf("Setting serial baud rate on channel %d to %d baud\n",
1896
             channel_id, baud);
1897
 
1898
      if (bsp_set_serial_baud(bsp_set_debug_comm(-1),
1899
                              str2int (argvect[1], 10)) < 0)
1900
        xprintf("Invalid baud rate\n");
1901
#else
1902
      __set_baud_rate (str2int (argvect[1], 10));
1903
#endif
1904
    }
1905
  return 0;
1906
}
1907
 
1908
 
1909
int
1910
set_term_cmd (cmdmode_t mode)
1911
{
1912
  if (mode == USAGE)
1913
    {
1914
      usage ("terminal type");
1915
      return 0;
1916
    }
1917
  if (mode == SHORT_HELP)
1918
    {
1919
      short_help ("Set the terminal type");
1920
      return 0;
1921
    }
1922
  if (mode == LONG_HELP)
1923
    {
1924
      set_term_cmd (USAGE);
1925
      long_help ("\
1926
The terminal command sets the type of the current terminal to that specified\n\
1927
in the type argument.  The only available terminal types are vt100 and dumb.\n\
1928
This is used by the line editor to determine how to update the terminal\n\
1929
display.\n");
1930
      example ("\
1931
terminal dumb\n\
1932
Sets the type of the current terminal to a dumb terminal.\n");
1933
      return 0;
1934
    }
1935
 
1936
  if (argvect[1] == NULL || argvect[2] != NULL)
1937
    set_term_cmd (USAGE);
1938
  else
1939
    set_term_name (argvect[1]);
1940
  return 0;
1941
}
1942
 
1943
int
1944
reset_cmd (cmdmode_t mode)
1945
{
1946
    if (mode == USAGE)
1947
    {
1948
      usage ("reset");
1949
      return 0;
1950
    }
1951
  if (mode == SHORT_HELP)
1952
    {
1953
      short_help ("Reset the board (not on all architectures).");
1954
      return 0;
1955
    }
1956
  if (mode == LONG_HELP)
1957
    {
1958
      reset_cmd (USAGE);
1959
      long_help ("\
1960
The reset command resets the board.  This may not be implemented\n\
1961
on all architectures");
1962
      return 0;
1963
    }
1964
 
1965
  if (argvect[1] != NULL)
1966
    {
1967
      reset_cmd (USAGE);
1968
    }
1969
  else
1970
    {
1971
      __reset ();
1972
    }
1973
  return 0;
1974
}
1975
 
1976
#if HAVE_USAGE
1977
int
1978
memusage_cmd (cmdmode_t mode)
1979
{
1980
  extern int sdata, _end;
1981
 
1982
  if (mode == USAGE)
1983
    {
1984
      usage ("usage");
1985
      return 0;
1986
    }
1987
  if (mode == SHORT_HELP)
1988
    {
1989
      short_help ("Show monitor memory usage");
1990
      return 0;
1991
    }
1992
  if (mode == LONG_HELP)
1993
    {
1994
      memusage_cmd (USAGE);
1995
      long_help ("\
1996
The usage command shows the amount of memory being used by the monitor,\n\
1997
broken down by category.  Despite its name, it has nothing to do with the\n\
1998
usage of any other command.\n");
1999
      return 0;
2000
    }
2001
 
2002
  if (argvect[1] != NULL)
2003
    {
2004
      return memusage_cmd (USAGE);
2005
    }
2006
  else
2007
    {
2008
      xprintf ("%d bytes were allocated with sbrk\n", (char *)sbrk (0) - (char *)&_end);
2009
    }
2010
  return 0;
2011
}
2012
#endif /* HAVE_USAGE */
2013
 
2014
int
2015
disassemble_cmd (cmdmode_t mode)
2016
{
2017
#ifdef DISASSEMBLER
2018
  int x;
2019
 
2020
  if (mode == USAGE)
2021
    {
2022
      usage ("disassemble [location]");
2023
      return 0;
2024
    }
2025
  if (mode == SHORT_HELP)
2026
    {
2027
      short_help ("Disassemble memory");
2028
      return 0;
2029
    }
2030
  if (mode == LONG_HELP)
2031
    {
2032
      disassemble_cmd (USAGE);
2033
      long_help ("\
2034
The disassemble command disassembles the contents of memory.  Because of the\n\
2035
way breakpoints are handled, all instructions are shown and breakpoints are\n\
2036
not visible in the disassembled code.  The disassemble command takes zero\n\
2037
or one argument.  When called with zero arguments, it starts disassembling\n\
2038
from the current (user program) pc.  When called with a location, it starts\n\
2039
disassembling from the specified location.  When called after a previous\n\
2040
call and with no arguments, it disassembles the next area of memory after\n\
2041
the one previously disassembled.\n");
2042
      example ("\
2043
disassemble 45667000\n\
2044
Displays disassembled code starting at location 45667000.");
2045
      return 0;
2046
    }
2047
  if (argvect [1] != NULL && argvect[2] != NULL)
2048
    {
2049
      return disassemble_cmd (USAGE);
2050
    }
2051
 
2052
  if(argvect [1] != NULL)
2053
    str2addr (argvect [1], &last_pc);
2054
  for (x = 0; x < 10; x++)
2055
    last_pc = do_dis (&last_pc);
2056
  flush_dis ();
2057
#else
2058
#warning "DISASSEMBLER not implemented"
2059
  xprintf ("disassembler not available\n");
2060
#endif
2061
 
2062
  return 0;
2063
}
2064
 
2065
int
2066
copy_cmd (cmdmode_t mode)
2067
{
2068
  mem_addr_t src, dst;
2069
  target_register_t size;
2070
 
2071
  if (mode == USAGE)
2072
    {
2073
      usage ("copy startaddr destaddr amount");
2074
      return 0;
2075
    }
2076
  if (mode == SHORT_HELP)
2077
    {
2078
      short_help ("Copies one area of memory to another");
2079
      return 0;
2080
    }
2081
  if (mode == LONG_HELP)
2082
    {
2083
      copy_cmd (USAGE);
2084
      long_help ("\
2085
The copy command is used to copy 'amount' bytes of memory\n\
2086
from 'startaddr' to 'destaddr'\n");
2087
      example ("\
2088
copy 10000 20000 300\n\
2089
Copies 0x300 bytes of memory from 0x10000 to 0x20000.");
2090
      return 0;
2091
    }
2092
  if (argvect[1] == NULL || argvect[2] == NULL || argvect[3] == NULL
2093
      || argvect[4] != NULL)
2094
    {
2095
      return copy_cmd (USAGE);
2096
    }
2097
  str2addr (argvect[1], &src);
2098
  str2addr (argvect[2], &dst);
2099
  size = str2int (argvect[3], 16);
2100
  while (size > 0)
2101
    {
2102
      char buf[128];
2103
 
2104
      int msize = (size > 128) ? 128 : size;
2105
      if (read_memory (&src, 1, msize, buf))
2106
        {
2107
          xprintf ("Memory read failed\n");
2108
          break;
2109
        }
2110
      if (write_memory (&dst, 1, msize, buf))
2111
        {
2112
          xprintf ("Memory write failed\n");
2113
          break;
2114
        }
2115
#ifdef HAVE_BSP
2116
      bsp_flush_dcache((void *)dst.addr, msize);
2117
      bsp_flush_icache((void *)dst.addr, msize);
2118
#endif
2119
      ADD_OFFSET (&src, &src, msize);
2120
      ADD_OFFSET (&dst, &dst, msize);
2121
      size -= msize;
2122
    }
2123
  return 0;
2124
}
2125
 
2126
#ifndef HAVE_BSP
2127
int
2128
set_program_args_cmd (cmdmode_t mode)
2129
{
2130
  int argc;
2131
 
2132
  if (mode == USAGE)
2133
    {
2134
      usage ("setargs [args]");
2135
      return 0;
2136
    }
2137
  if (mode == SHORT_HELP)
2138
    {
2139
      short_help ("Sets the program arguments passed to main()");
2140
      return 0;
2141
    }
2142
  if (mode == LONG_HELP)
2143
    {
2144
      set_program_args_cmd (SHORT_HELP);
2145
      return 0;
2146
    }
2147
  for (argc = 1; argvect[argc] != NULL; argc++)
2148
    ;
2149
  __set_program_args (argc - 1, argvect + 1);
2150
  return 0;
2151
}
2152
#endif
2153
 
2154
 
2155
int
2156
fill_cmd (cmdmode_t mode)
2157
{
2158
  if (mode == USAGE)
2159
    {
2160
      usage ("fill[.size] startaddress endaddress [value]");
2161
      return 0;
2162
    }
2163
  if (mode == SHORT_HELP)
2164
    {
2165
      short_help ("Fills memory with a specified value");
2166
      return 0;
2167
    }
2168
  if (mode == LONG_HELP)
2169
    {
2170
      fill_cmd (USAGE);
2171
      long_help("\
2172
The fill command is used to fill a region of memory from 'startaddress'\n\
2173
to 'endaddress' with the value in 'value'.  If no value is specificed,\n\
2174
it uses zero.  It can take a size extension, which follows the command\n\
2175
name or partial command name without a space, and is a period followed\n\
2176
by the size of the writes that are used, in bits.  Options are 8, 16,\n\
2177
32, and 64.  Without a size extension, the fill command defaults to\n\
2178
changing 8 bits at a time.\n");
2179
      example ("\
2180
fill.32 10000 20000 32\n\
2181
Fills the region between 0x10000 and 0x20000 with the 32 bit value 0x32.");
2182
      return 0;
2183
    }
2184
  if ((argvect[1] == NULL || argvect[2] == NULL)
2185
      || (argvect[3] != NULL && argvect[4] != NULL))
2186
    {
2187
      fill_cmd (USAGE);
2188
      return 0;
2189
    } else {
2190
      mem_addr_t start,end;
2191
      char value[8];
2192
      int size = get_cmd_size();
2193
      int amt;
2194
 
2195
      if (size == -1)
2196
          /*
2197
           * Invalid size specified.
2198
           */
2199
          return 0;
2200
 
2201
      if (argvect[3] != NULL)
2202
        {
2203
          hex2bytes (argvect[3], value, size);
2204
        }
2205
      else
2206
        {
2207
          hex2bytes ("0", value, size);
2208
        }
2209
      str2addr (argvect[1], &start);
2210
      str2addr (argvect[2], &end);
2211
      amt = MEM_ADDR_DIFF (end, start);
2212
      if (amt < 0)
2213
        {
2214
          xprintf ("Addresses in incorrect order\n");
2215
        }
2216
      else
2217
        {
2218
          int x;
2219
          if (get_memory_display_mode ())
2220
            {
2221
              /* Gotta swap this puppy. */
2222
              int x;
2223
 
2224
              for (x = 0; x < (size / 2); x++)
2225
                {
2226
                  char tmp = value[x];
2227
                  value [x] = value [size - 1 - x];
2228
                  value [size - 1 - x] = tmp;
2229
                }
2230
            }
2231
 
2232
          xprintf ("Writing %d units\n", amt / size + 1);
2233
          for (x = amt / size; x >= 0; x--)
2234
            {
2235
              if (write_memory (&start, size, 1, value))
2236
                {
2237
                  xprintf ("Memory write failed\n");
2238
                  break;
2239
                }
2240
              ADD_OFFSET (&start, &start, size);
2241
            }
2242
        }
2243
    }
2244
  return 0;
2245
}
2246
 
2247
 
2248
int
2249
swapmem_cmd (cmdmode_t mode)
2250
{
2251
  int display_settings = 0;
2252
 
2253
  if (mode == USAGE)
2254
    {
2255
      usage ("swapmem [little|big]");
2256
      return 0;
2257
    }
2258
  if (mode == SHORT_HELP)
2259
    {
2260
      short_help ("Sets whether or not memory values are byte-swapped");
2261
      return 0;
2262
    }
2263
  if (mode == LONG_HELP)
2264
    {
2265
      swapmem_cmd (USAGE);
2266
 
2267
      long_help("\
2268
The swapmem command is used to determine whether or not memory values are\n\
2269
displayed and written in little or big-endian byte order. By default, values\n\
2270
are read and written to match the byte order of the target CPU.\n\
2271
This command does not alter the CPU state in any way; it only changes the\n\
2272
way memory values are displayed and written within the monitor.\n");
2273
      example("\
2274
swapmem \n\
2275
Displays the byte order that is currently in effect.");
2276
      return 0;
2277
      display_settings = 1;
2278
    }
2279
  else
2280
    {
2281
      if (argvect[1] != NULL && argvect[2] != NULL)
2282
        {
2283
          swapmem_cmd (USAGE);
2284
          return 0;
2285
        }
2286
    }
2287
  if (display_settings || argvect[1] == NULL)
2288
    {
2289
      if (get_memory_display_mode ())
2290
        {
2291
          xprintf ("Memory values are read and written in little-endian byte order.\n");
2292
        }
2293
      else
2294
        {
2295
          xprintf ("Memory values are read and written in big-endian byte order.\n");
2296
        }
2297
      return 0;
2298
    }
2299
  if (strncmp (argvect[1], "little", strlen (argvect[1])) == 0)
2300
    {
2301
      set_memory_display_mode (1);
2302
      xprintf ("Memory values are now read and written in little-endian order.\n");
2303
    }
2304
  else if (strncmp (argvect[1], "big", strlen (argvect[1])) == 0)
2305
    {
2306
      set_memory_display_mode (0);
2307
      xprintf ("Memory values are now read and written in big-endian order.\n");
2308
    }
2309
  else
2310
    {
2311
      return swapmem_cmd (USAGE);
2312
    }
2313
  return 0;
2314
}
2315
 
2316
#ifdef MONITOR_CONTROL_INTERRUPTS
2317
int
2318
int_cmd (cmdmode_t mode)
2319
{
2320
  if (mode == USAGE)
2321
    {
2322
      usage ("interrupt [on|off]");
2323
      return 0;
2324
    }
2325
  if (mode == SHORT_HELP)
2326
    {
2327
      short_help ("Enables or disables interrupts within the monitor");
2328
      return 0;
2329
    }
2330
  if (mode == LONG_HELP)
2331
    {
2332
      int_cmd (USAGE);
2333
      long_help("\
2334
The interrupt command is used to enable or disable interrupts while the\n\
2335
monitor is running.");
2336
      return 0;
2337
    }
2338
  if (argvect[1] != NULL && argvect[2] != NULL)
2339
    {
2340
      int_cmd (USAGE);
2341
      return 0;
2342
    }
2343
  if (argvect[1] != NULL)
2344
    {
2345
      if (strcmp (argvect[1], "on") == 0)
2346
        {
2347
          monitor_enable_interrupts ();
2348
        }
2349
      else if (strcmp (argvect[1], "off") == 0)
2350
        {
2351
          monitor_disable_interrupts ();
2352
        }
2353
      else
2354
        {
2355
          int_cmd (USAGE);
2356
          return 0;
2357
        }
2358
    }
2359
  xprintf ("Interrupts ");
2360
  if (monitor_interrupt_state ())
2361
    {
2362
      xprintf ("enabled\n");
2363
    }
2364
  else
2365
    {
2366
      xprintf ("disabled\n");
2367
    }
2368
  return 0;
2369
}
2370
#endif
2371
 
2372
 
2373
/* Table used by the crc32 function to calcuate the checksum. */
2374
static uint32 crc32_table[256];
2375
static int crc_initted = 0;
2376
 
2377
static uint32
2378
crc32 (unsigned char *buf, int len, uint32 crc)
2379
{
2380
  if (! crc_initted)
2381
    {
2382
      /* Initialize the CRC table and the decoding table. */
2383
      int i, j;
2384
      uint32 c;
2385
 
2386
      crc_initted = 1;
2387
      for (i = 0; i < 256; i++)
2388
        {
2389
          for (c = i << 24, j = 8; j > 0; --j)
2390
            c = c & 0x80000000 ? (c << 1) ^ 0x04c11db7 : (c << 1);
2391
          crc32_table[i] = c;
2392
        }
2393
    }
2394
 
2395
  while (len--)
2396
    {
2397
      crc = (crc << 8) ^ crc32_table[((crc >> 24) ^ *buf) & 255];
2398
      buf++;
2399
    }
2400
  return crc;
2401
}
2402
 
2403
 
2404
int
2405
checksumcmd (cmdmode_t mode)
2406
{
2407
  mem_addr_t start, end;
2408
  uint32 crc = 0xffffffff;
2409
 
2410
  if (mode == USAGE)
2411
    {
2412
      usage ("crc startaddr endaddr");
2413
      return 0;
2414
    }
2415
  if (mode == SHORT_HELP)
2416
    {
2417
      short_help ("checksum an area of memory");
2418
      return 0;
2419
    }
2420
  if (mode == LONG_HELP)
2421
    {
2422
      checksumcmd (USAGE);
2423
      long_help ("\
2424
The crc command is used to calculate a standard CRC32 checksum of the\n\
2425
specified memory region. The checksum is printed out as a hexadecimal\n\
2426
value.");
2427
      return 0;
2428
    }
2429
  if (argvect[1] == NULL || argvect[2] == NULL || argvect[3] != NULL)
2430
    {
2431
      return checksumcmd (USAGE);
2432
    }
2433
 
2434
  str2addr (argvect[1], &start);
2435
  str2addr (argvect[2], &end);
2436
  while (start.addr < end.addr)
2437
    {
2438
      char c[1024];
2439
      int len = end.addr - start.addr;
2440
      if (len > sizeof(c))
2441
        len = sizeof(c);
2442
 
2443
      read_memory (&start, 1, len, c);
2444
      crc = crc32 (c, len, crc);
2445
      start.addr += len;
2446
    }
2447
  xprintf("0x%08lx is checksum\n", crc);
2448
  return 0;
2449
}
2450
 
2451
char **argvect;
2452
static char argvect_cmd[MAXLINELEN];
2453
 
2454
static char **
2455
buildargv (char *input)
2456
{
2457
  static char *arglist[256];
2458
  int numargs = 0;
2459
 
2460
  while (1)
2461
    {
2462
      while (isspace ((unsigned char)*input) && *input != 0)
2463
          input++;
2464
      if (*input == 0)
2465
        break;
2466
      arglist [numargs++] = input;
2467
      while (!isspace ((unsigned char)*input) && *input != 0)
2468
        input++;
2469
      if (*input == 0)
2470
        break;
2471
      *(input++) = 0;
2472
    }
2473
  arglist [numargs] = NULL;
2474
  return arglist;
2475
}
2476
 
2477
 
2478
int
2479
monitor_loop (void)
2480
{
2481
  int state = 1, return_value = 0;
2482
 
2483
  while (state == 1)
2484
    {
2485
      /* Get a line of input, putting it in the input buffer */
2486
      lineedit (PROMPT, inbuf, sizeof (inbuf));
2487
      xprintf ("\n");
2488
 
2489
      if (switch_to_stub_flag)
2490
        {
2491
#ifndef HAVE_BSP
2492
          switch_to_stub_flag = 0;
2493
#endif
2494
          return transfer_to_stub ();
2495
        }
2496
 
2497
      /* Separate off the command from any other stuff on the line */
2498
 
2499
      strcpy (argvect_cmd, inbuf);
2500
      argvect = buildargv (argvect_cmd);
2501
 
2502
      if (argvect[0] != NULL && argvect[0][0] != '\0')
2503
        {
2504
          char *ptr;
2505
          int command_number;
2506
 
2507
          strcpy (cmd, argvect[0]);
2508
 
2509
          /* Function to split off . delimiters. */
2510
          ptr = strchr (cmd, '.');
2511
 
2512
          if (ptr != NULL && *ptr == '.')
2513
            *ptr = '\0';
2514
 
2515
          /* See if it's an alias. */
2516
          command_number = alias_compare (cmd);
2517
 
2518
          /* Compare input to command list, check for conflicts. */
2519
          if (command_number < 0)
2520
            command_number = command_compare (cmd);
2521
 
2522
          /* If we found a command, just run the function */
2523
          if (command_number >= 0)
2524
            {
2525
              int status;
2526
              /* Execute the function, if the function returns a non-zero
2527
                 value, break out of the loop and return. */
2528
              status = (*cmdtab[command_number].function) (INVOCATION);
2529
              if (status)
2530
                {
2531
                  state = 0;
2532
                  if (status < 0)
2533
                    return_value = 1;
2534
                }
2535
            }
2536
          else
2537
            {
2538
              /* If none of the commands or aliases match, complain. */
2539
              xprintf ("Not a legal command\n");
2540
            }
2541
 
2542
          if (inbuf[0] != '\0')
2543
            addHistoryCmd (inbuf);
2544
        }
2545
    }
2546
  return return_value;
2547
}
2548
 
2549
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.