]> cloudbase.mooo.com Git - z180-stamp.git/blame - avr/cmd_mem.c
include cleanup
[z180-stamp.git] / avr / cmd_mem.c
CommitLineData
72f58822
L
1/*
2 * (C) Copyright 2000
3 * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
4 *
5 * SPDX-License-Identifier: GPL-2.0+
6 */
7
8/*
9 * Memory Functions
10 *
11 * Copied from FADS ROM, Dan Malek (dmalek@jlc.net)
12 */
13
14#include "common.h"
15#include <stdlib.h>
16#include <ctype.h>
17
72f58822
L
18#include "command.h"
19#include "cli_readline.h"
8f23e84c 20#include "print-utils.h"
72f58822
L
21#include "con-utils.h"
22#include "z80-if.h"
8f23e84c 23//#include "debug.h"
72f58822 24
72f58822
L
25
26#ifndef CONFIG_SYS_MEMTEST_SCRATCH
27#define CONFIG_SYS_MEMTEST_SCRATCH 0
28#endif
29
72f58822
L
30/* Display values from last command.
31 * Memory modify remembered values are different from display memory.
32 */
33static uint32_t dp_last_addr;
34static uint32_t dp_last_length = 0x100;
35static uint32_t mm_last_addr;
36
37static uint32_t base_address = 0;
38
39/*--------------------------------------------------------------------------*/
40
72f58822
L
41int z180_dump_mem(uint32_t startaddr, uint32_t len, const char *title)
42{
43 uint8_t buf[16];
44 uint8_t llen = 16;
45 uint8_t pre = startaddr % 16;
46 uint32_t addr = startaddr & ~0x0f;
47 len += pre;
48 uint8_t i;
6035a17b 49
72f58822
L
50 if (title && *title)
51 printf_P(PSTR("%s\n"),title);
6035a17b 52
72f58822
L
53 while (len) {
54 if (len < 16)
55 llen = len;
56
62f624d3 57 z80_bus_cmd(Request);
72f58822
L
58 for (i = pre; i < llen; i++)
59 buf[i] = z80_read(addr + i);
62f624d3 60 z80_bus_cmd(Release);
72f58822
L
61
62 printf_P(PSTR("%.5lx:"), addr);
63#if 0
64 print_blanks(3 * pre);
65
66 /* Print hex values */
67 for (i = pre; i < llen; i++)
68 printf_P(PSTR(" %.2x"), buf[i]);
69#else
70 for (i = 0; i < llen; i++) {
71 if ((i % 8) == 0)
72 putchar(' ');
73 if (i < pre)
74 printf_P(PSTR(".. "));
75 else
76 printf_P(PSTR("%.2x "), buf[i]);
77 }
78#endif
79 /* fill line with whitespace for nice ASCII print */
80#if 1
81 print_blanks(3 * (16u - i) + (16u-i)/8 + 1 + pre);
82#else
83
84#endif
85 /* Print data in ASCII characters */
86 for (i = pre; i < llen; i++)
87 printf_P(PSTR("%c"), isprint(buf[i]) ? buf[i] : '.');
88 putchar('\n');
89
90 pre = 0;
91 addr += 16;
92 len -= llen;
93
94 if (ctrlc())
95 return -1;
96 }
97 return 0;
98}
99
100
101/*--------------------------------------------------------------------------*/
102
103/* Memory Display
104 *
105 * Syntax:
106 * md {addr} {len}
107 */
d0581f88 108command_ret_t do_mem_md(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
72f58822
L
109{
110 uint32_t addr, length;
6035a17b 111
72f58822
L
112 (void) cmdtp;
113
6035a17b 114#if 0
72f58822
L
115 printf_P(PSTR("flag: %d, argc: %d"), flag, argc);
116 for (int i = 0; i < argc; i++) {
117 printf_P(PSTR(", argv[%d]: %s"), i, argv[i] ? argv[i] : "<NULL>");
118 }
119 putchar('\n');
120#endif
121
122 /* We use the last specified parameters, unless new ones are
123 * entered.
124 */
125 addr = dp_last_addr;
126 length = dp_last_length;
127
128 if (argc < 2)
129 return CMD_RET_USAGE;
130
131 if ((flag & CMD_FLAG_REPEAT) == 0) {
132 /* Address is specified since argc > 1 */
133 addr = strtoul(argv[1], NULL, 16);
134 addr += base_address;
135
136 /* If another parameter, it is the length to display. */
137 if (argc > 2)
138 length = strtoul(argv[2], NULL, 16);
139 }
140
141 /* Print the lines. */
142 z180_dump_mem(addr, length, NULL);
143
144 dp_last_addr = addr + length;
145 dp_last_length = length;
d0581f88 146 return CMD_RET_SUCCESS;
72f58822
L
147}
148
d0581f88
L
149/* Modify memory.
150 *
151 * Syntax:
152 * mm {addr}
153 * nm {addr}
154 */
155static command_ret_t
156mod_mem(cmd_tbl_t *cmdtp, int incrflag, int flag, int argc, char * const argv[])
157{
158 uint32_t addr;
159 uint8_t data;
160 int nbytes;
161
162 (void) cmdtp;
163
164 if (argc != 2)
165 return CMD_RET_USAGE;
166
167 /* We use the last specified parameters, unless new ones are
168 * entered.
169 */
170 addr = mm_last_addr;
171
172 if ((flag & CMD_FLAG_REPEAT) == 0) {
173 /* New command specified.
174 */
175
176 /* Address is specified since argc > 1
177 */
178 addr = strtoul(argv[1], NULL, 16);
179 addr += base_address;
180 }
181
182 /* Print the address, followed by value. Then accept input for
183 * the next value. A non-converted value exits.
184 */
185 do {
186 z80_bus_cmd(Request);
187 data = z80_read(addr);
69988dc1 188 printf_P(PSTR("%05lx: %02x"), addr, data);
d0581f88
L
189 z80_bus_cmd(Release);
190
191 nbytes = cli_readline(PSTR(" ? "));
192 if (nbytes == 0 || (nbytes == 1 && console_buffer[0] == '-')) {
193 /* <CR> pressed as only input, don't modify current
194 * location and move to next. "-" pressed will go back.
195 */
196 if (incrflag)
197 addr += nbytes ? -1 : 1;
198 nbytes = 1;
199 }
200 else {
201 char *endp;
202 data = strtoul(console_buffer, &endp, 16);
203 nbytes = endp - console_buffer;
204 if (nbytes) {
205 z80_bus_cmd(Request);
206 z80_write(addr, data);
207 z80_bus_cmd(Release);
208 if (incrflag)
209 addr++;
210 }
211 }
212 } while (nbytes);
213
214 mm_last_addr = addr;
215 return CMD_RET_SUCCESS;
216}
217
218
219command_ret_t do_mem_mm(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
72f58822
L
220{
221 return mod_mem (cmdtp, 1, flag, argc, argv);
222}
d0581f88 223command_ret_t do_mem_nm(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
72f58822
L
224{
225 return mod_mem (cmdtp, 0, flag, argc, argv);
226}
227
d0581f88 228command_ret_t do_mem_mw(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
72f58822
L
229{
230 uint8_t writeval;
231 uint32_t addr, count;
232
233 (void) cmdtp;
234 (void) flag;
235
236 if ((argc < 3) || (argc > 4))
237 return CMD_RET_USAGE;
238
239 /* Address is specified since argc > 1
240 */
241 addr = strtoul(argv[1], NULL, 16);
242 addr += base_address;
243
244 /* Get the value to write.
245 */
246 writeval = (uint8_t) strtoul(argv[2], NULL, 16);
247
248 /* Count ? */
249 if (argc == 4) {
250 count = strtoul(argv[3], NULL, 16);
251 } else {
252 count = 1;
253 }
254
62f624d3 255 z80_bus_cmd(Request);
72f58822
L
256 while (count-- > 0) {
257 z80_write(addr, writeval);
6035a17b 258 ++addr;
72f58822 259 }
62f624d3 260 z80_bus_cmd(Release);
72f58822 261
d0581f88 262 return CMD_RET_SUCCESS;
72f58822
L
263}
264
265#ifdef CONFIG_MX_CYCLIC
d0581f88 266command_ret_t do_mem_mdc ( cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
72f58822
L
267{
268 int i;
269 uint32_t count;
270
271 if (argc < 4)
272 return CMD_RET_USAGE;
273
274 count = strtoul(argv[3], NULL, 10);
275
276 for (;;) {
277 do_mem_md (NULL, 0, 3, argv);
278
279 /* delay for <count> ms... */
280/* TODO: use timer */
281 for (i=0; i<count; i++)
282 udelay (1000);
283
284 /* check for ctrl-c to abort... */
285 if (ctrlc()) {
69988dc1 286 my_puts_P(PSTR("Abort\n"));
d0581f88 287 return CMD_RET_SUCCESS;
72f58822
L
288 }
289 }
290
d0581f88 291 return CMD_RET_SUCCESS;
72f58822
L
292}
293
d0581f88 294command_ret_t do_mem_mwc ( cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
72f58822
L
295{
296 int i;
297 uint32_t count;
298
299 if (argc < 4)
300 return CMD_RET_USAGE;
301
302 count = strtoul(argv[3], NULL, 10);
303
304 for (;;) {
305 do_mem_mw (NULL, 0, 3, argv);
306
307 /* delay for <count> ms... */
308/* TODO: use timer */
309 for (i=0; i<count; i++)
310 udelay (1000);
311
312 /* check for ctrl-c to abort... */
313 if (ctrlc()) {
69988dc1 314 my_puts_P(PSTR("Abort\n"));
d0581f88 315 return CMD_RET_SUCCESS;
72f58822
L
316 }
317 }
318
d0581f88 319 return CMD_RET_SUCCESS;
72f58822
L
320}
321#endif /* CONFIG_MX_CYCLIC */
322
d0581f88 323command_ret_t do_mem_cmp(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
72f58822
L
324{
325 uint32_t addr1, addr2, count, ngood;
d0581f88 326 command_ret_t rcode = CMD_RET_SUCCESS;
72f58822
L
327 uint8_t byte1, byte2;
328
329 (void) cmdtp;
330 (void) flag;
331
332 if (argc != 4)
333 return CMD_RET_USAGE;
334
335
336 addr1 = strtoul(argv[1], NULL, 16);
337 addr1 += base_address;
338 addr2 = strtoul(argv[2], NULL, 16);
339 addr2 += base_address;
340 count = strtoul(argv[3], NULL, 16);
341
342 for (ngood = 0; ngood < count; ++ngood) {
62f624d3 343 z80_bus_cmd(Request);
72f58822
L
344 byte1 = z80_read(addr1);
345 byte2 = z80_read(addr2);
62f624d3 346 z80_bus_cmd(Release);
72f58822 347 if (byte1 != byte2) {
6035a17b
L
348 printf_P(PSTR("byte at 0x%05lx (%#02x) != "
349 "byte at 0x%05lx (%#02x)\n"),
72f58822 350 addr1, byte1, addr2, byte2);
d0581f88 351 rcode = CMD_RET_FAILURE;
72f58822
L
352 break;
353 }
354 addr1++;
355 addr2++;
356
357 /* check for ctrl-c to abort... */
358 if (ctrlc()) {
69988dc1 359 my_puts_P(PSTR("Abort\n"));
d0581f88 360 return CMD_RET_SUCCESS;
72f58822
L
361 }
362 }
363
69988dc1 364 printf_P(PSTR("Total of %ld byte(s) (0x%lx) were the same\n"), ngood, ngood);
72f58822
L
365 return rcode;
366}
367
d0581f88 368command_ret_t do_mem_cp(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
72f58822
L
369{
370 uint32_t src, dest, count;
371 int_fast8_t step;
372
373 (void) cmdtp;
374 (void) flag;
375
376 if (argc != 4)
377 return CMD_RET_USAGE;
378
379 src = strtoul(argv[1], NULL, 16);
380 src += base_address;
381 dest = strtoul(argv[2], NULL, 16);
382 dest += base_address;
383 count = strtoul(argv[3], NULL, 16);
384
385 if (count == 0) {
69988dc1 386 my_puts_P(PSTR("Zero length?\n"));
d0581f88 387 return CMD_RET_FAILURE;
72f58822 388 }
6035a17b 389
72f58822
L
390 if (dest > src) {
391 src += count - 1;
392 dest += count - 1;
393 step = -1;
394 } else
395 step = 1;
396
397 while (count-- > 0) {
398 uint8_t data;
62f624d3 399 z80_bus_cmd(Request);
72f58822
L
400 data = z80_read(src);
401 z80_write(dest, data);
62f624d3 402 z80_bus_cmd(Release);
72f58822
L
403 src += step;
404 dest += step;
405
406 /* check for ctrl-c to abort... */
407 if (ctrlc()) {
69988dc1 408 my_puts_P(PSTR("Abort\n"));
d0581f88 409 return CMD_RET_SUCCESS;
72f58822
L
410 }
411 }
d0581f88 412 return CMD_RET_SUCCESS;
72f58822
L
413}
414
d0581f88 415command_ret_t do_mem_base(cmd_tbl_t *cmdtp, int flag, int argc,
72f58822
L
416 char * const argv[])
417{
418 (void) cmdtp;
419 (void) flag;
420
421 if (argc > 1) {
422 /* Set new base address. */
423 base_address = strtoul(argv[1], NULL, 16);
424 }
425 /* Print the current base address. */
69988dc1 426 printf_P(PSTR("Base Address: 0x%05lx\n"), base_address);
d0581f88 427 return CMD_RET_SUCCESS;
72f58822
L
428}
429
d0581f88 430command_ret_t do_mem_loop(cmd_tbl_t *cmdtp, int flag, int argc,
72f58822
L
431 char * const argv[])
432{
433 uint32_t addr, length;
434
435 (void) cmdtp;
436 (void) flag;
437
438 if (argc < 3)
439 return CMD_RET_USAGE;
440
441 /* Address is always specified. */
442 addr = strtoul(argv[1], NULL, 16);
443
444 /* Length is the number of bytes. */
445 length = strtoul(argv[2], NULL, 16);
446
447
448 /* We want to optimize the loops to run as fast as possible.
449 * If we have only one object, just run infinite loops.
450 */
451 if (length == 1) {
62f624d3 452 z80_bus_cmd(Request);
72f58822
L
453 for (;;)
454 z80_read(addr);
62f624d3 455 z80_bus_cmd(Release);
72f58822
L
456 }
457
62f624d3 458 z80_bus_cmd(Request);
72f58822
L
459 for (;;) {
460 uint32_t i = length;
461 uint32_t p = addr;
462 while (i-- > 0)
463 z80_read(p++);
464 }
62f624d3 465 z80_bus_cmd(Release);
72f58822 466
d0581f88 467 return CMD_RET_SUCCESS;
72f58822
L
468}
469
470#ifdef CONFIG_LOOPW
d0581f88 471command_ret_t do_mem_loopw (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
72f58822
L
472{
473 uint32_t addr, length;
474 uint8_t data;
475
476 (void) cmdtp;
477 (void) flag;
478
479 if (argc < 4)
480 return CMD_RET_USAGE;
481
482 /* Address is always specified. */
483 addr = strtoul(argv[1], NULL, 16);
484
485 /* Length is the number of bytes. */
486 length = strtoul(argv[2], NULL, 16);
487
488 data = strtoul(argv[3], NULL, 16);
489
490 /* We want to optimize the loops to run as fast as possible.
491 * If we have only one object, just run infinite loops.
492 */
493 if (length == 1) {
62f624d3 494 z80_bus_cmd(Request);
72f58822
L
495 for (;;)
496 z80_write(addr, data);
497 }
498
499 for (;;) {
500 uint32_t i = length;
501 uint32_t p = addr;
502 while (i-- > 0)
503 z80_write(p++, data);
504 }
505}
506#endif /* CONFIG_LOOPW */
507
508#ifdef CONFIG_CMD_MEMTEST
509static uint32_t mem_test_alt(vu_long *buf, uint32_t start_addr, uint32_t end_addr,
510 vu_long *dummy)
511{
512 vu_long *addr;
513 uint32_t errs = 0;
514 uint32_t val, readback;
515 int j;
516 vu_long offset;
517 vu_long test_offset;
518 vu_long pattern;
519 vu_long temp;
520 vu_long anti_pattern;
521 vu_long num_words;
522 static const FLASH uint32_t bitpattern[] = {
523 0x00000001, /* single bit */
524 0x00000003, /* two adjacent bits */
525 0x00000007, /* three adjacent bits */
526 0x0000000F, /* four adjacent bits */
527 0x00000005, /* two non-adjacent bits */
528 0x00000015, /* three non-adjacent bits */
529 0x00000055, /* four non-adjacent bits */
530 0xaaaaaaaa, /* alternating 1/0 */
531 };
532
533 num_words = (end_addr - start_addr) / sizeof(vu_long);
534
535 /*
536 * Data line test: write a pattern to the first
537 * location, write the 1's complement to a 'parking'
538 * address (changes the state of the data bus so a
539 * floating bus doesn't give a false OK), and then
540 * read the value back. Note that we read it back
541 * into a variable because the next time we read it,
542 * it might be right (been there, tough to explain to
543 * the quality guys why it prints a failure when the
544 * "is" and "should be" are obviously the same in the
545 * error message).
546 *
547 * Rather than exhaustively testing, we test some
548 * patterns by shifting '1' bits through a field of
549 * '0's and '0' bits through a field of '1's (i.e.
550 * pattern and ~pattern).
551 */
552 addr = buf;
553 for (j = 0; j < sizeof(bitpattern) / sizeof(bitpattern[0]); j++) {
554 val = bitpattern[j];
555 for (; val != 0; val <<= 1) {
556 *addr = val;
557 *dummy = ~val; /* clear the test data off the bus */
558 readback = *addr;
559 if (readback != val) {
69988dc1
L
560 printf_P(PSTR("FAILURE (data line): "
561 "expected %05lx, actual %05lx\n"),
72f58822
L
562 val, readback);
563 errs++;
564 if (ctrlc())
565 return -1;
566 }
567 *addr = ~val;
568 *dummy = val;
569 readback = *addr;
570 if (readback != ~val) {
69988dc1
L
571 printf_P(PSTR("FAILURE (data line): "
572 "Is %05lx, should be %05lx\n"),
72f58822
L
573 readback, ~val);
574 errs++;
575 if (ctrlc())
576 return -1;
577 }
578 }
579 }
580
581 /*
582 * Based on code whose Original Author and Copyright
583 * information follows: Copyright (c) 1998 by Michael
584 * Barr. This software is placed into the public
585 * domain and may be used for any purpose. However,
586 * this notice must not be changed or removed and no
587 * warranty is either expressed or implied by its
588 * publication or distribution.
589 */
590
591 /*
592 * Address line test
593
594 * Description: Test the address bus wiring in a
595 * memory region by performing a walking
596 * 1's test on the relevant bits of the
597 * address and checking for aliasing.
598 * This test will find single-bit
599 * address failures such as stuck-high,
600 * stuck-low, and shorted pins. The base
601 * address and size of the region are
602 * selected by the caller.
603
604 * Notes: For best results, the selected base
605 * address should have enough LSB 0's to
606 * guarantee single address bit changes.
607 * For example, to test a 64-Kbyte
608 * region, select a base address on a
609 * 64-Kbyte boundary. Also, select the
610 * region size as a power-of-two if at
611 * all possible.
612 *
613 * Returns: 0 if the test succeeds, 1 if the test fails.
614 */
615 pattern = (vu_long) 0xaaaaaaaa;
616 anti_pattern = (vu_long) 0x55555555;
617
618 debug("%s:%d: length = 0x%.5lx\n", __func__, __LINE__, num_words);
619 /*
620 * Write the default pattern at each of the
621 * power-of-two offsets.
622 */
623 for (offset = 1; offset < num_words; offset <<= 1)
624 addr[offset] = pattern;
625
626 /*
627 * Check for address bits stuck high.
628 */
629 test_offset = 0;
630 addr[test_offset] = anti_pattern;
631
632 for (offset = 1; offset < num_words; offset <<= 1) {
633 temp = addr[offset];
634 if (temp != pattern) {
69988dc1
L
635 printf_P(PSTR("\nFAILURE: Address bit stuck high @ 0x%.5lx:"
636 " expected 0x%.5lx, actual 0x%.5lx\n"),
72f58822
L
637 start_addr + offset*sizeof(vu_long),
638 pattern, temp);
639 errs++;
640 if (ctrlc())
641 return -1;
642 }
643 }
644 addr[test_offset] = pattern;
645
646 /*
647 * Check for addr bits stuck low or shorted.
648 */
649 for (test_offset = 1; test_offset < num_words; test_offset <<= 1) {
650 addr[test_offset] = anti_pattern;
651
652 for (offset = 1; offset < num_words; offset <<= 1) {
653 temp = addr[offset];
654 if ((temp != pattern) && (offset != test_offset)) {
69988dc1 655 printf_P(PSTR("\nFAILURE: Address bit stuck low or"
72f58822 656 " shorted @ 0x%.5lx: expected 0x%.5lx,"
69988dc1 657 " actual 0x%.5lx\n"),
72f58822
L
658 start_addr + offset*sizeof(vu_long),
659 pattern, temp);
660 errs++;
661 if (ctrlc())
662 return -1;
663 }
664 }
665 addr[test_offset] = pattern;
666 }
667
668 /*
669 * Description: Test the integrity of a physical
670 * memory device by performing an
671 * increment/decrement test over the
672 * entire region. In the process every
673 * storage bit in the device is tested
674 * as a zero and a one. The base address
675 * and the size of the region are
676 * selected by the caller.
677 *
678 * Returns: 0 if the test succeeds, 1 if the test fails.
679 */
680 num_words++;
681
682 /*
683 * Fill memory with a known pattern.
684 */
685 for (pattern = 1, offset = 0; offset < num_words; pattern++, offset++) {
686 addr[offset] = pattern;
687 }
688
689 /*
690 * Check each location and invert it for the second pass.
691 */
692 for (pattern = 1, offset = 0; offset < num_words; pattern++, offset++) {
693 temp = addr[offset];
694 if (temp != pattern) {
69988dc1
L
695 printf_P(PSTR("\nFAILURE (read/write) @ 0x%.5lx:"
696 " expected 0x%.5lx, actual 0x%.5lx)\n"),
72f58822
L
697 start_addr + offset*sizeof(vu_long),
698 pattern, temp);
699 errs++;
700 if (ctrlc())
701 return -1;
702 }
703
704 anti_pattern = ~pattern;
705 addr[offset] = anti_pattern;
706 }
707
708 /*
709 * Check each location for the inverted pattern and zero it.
710 */
711 for (pattern = 1, offset = 0; offset < num_words; pattern++, offset++) {
712 WATCHDOG_RESET();
713 anti_pattern = ~pattern;
714 temp = addr[offset];
715 if (temp != anti_pattern) {
69988dc1
L
716 printf_P(PSTR("\nFAILURE (read/write): @ 0x%.5lx:"
717 " expected 0x%.5lx, actual 0x%.5lx)\n"),
72f58822
L
718 start_addr + offset*sizeof(vu_long),
719 anti_pattern, temp);
720 errs++;
721 if (ctrlc())
722 return -1;
723 }
724 addr[offset] = 0;
725 }
726
727 return 0;
728}
729
730static uint32_t mem_test_quick(vu_long *buf, uint32_t start_addr, uint32_t end_addr,
731 vu_long pattern, int iteration)
732{
733 vu_long *end;
734 vu_long *addr;
735 uint32_t errs = 0;
736 uint32_t incr, length;
737 uint32_t val, readback;
738
739 /* Alternate the pattern */
740 incr = 1;
741 if (iteration & 1) {
742 incr = -incr;
743 /*
744 * Flip the pattern each time to make lots of zeros and
745 * then, the next time, lots of ones. We decrement
746 * the "negative" patterns and increment the "positive"
747 * patterns to preserve this feature.
748 */
749 if (pattern & 0x80000000)
750 pattern = -pattern; /* complement & increment */
751 else
752 pattern = ~pattern;
753 }
754 length = (end_addr - start_addr) / sizeof(uint32_t);
755 end = buf + length;
69988dc1 756 printf_P(PSTR("\rPattern %08lX Writing..."
72f58822 757 "%12s"
69988dc1 758 "\b\b\b\b\b\b\b\b\b\b"),
72f58822
L
759 pattern, "");
760
761 for (addr = buf, val = pattern; addr < end; addr++) {
762 *addr = val;
763 val += incr;
764 }
765
69988dc1 766 my_puts_P(PSTR("Reading..."));
72f58822
L
767
768 for (addr = buf, val = pattern; addr < end; addr++) {
769 readback = *addr;
770 if (readback != val) {
771 uint32_t offset = addr - buf;
772
69988dc1
L
773 printf_P(PSTR("\nMem error @ 0x%08X: "
774 "found %08lX, expected %08lX\n"),
72f58822
L
775 (unsigned int)(uintptr_t)(start_addr + offset*sizeof(vu_long)),
776 readback, val);
777 errs++;
778 if (ctrlc())
779 return -1;
780 }
781 val += incr;
782 }
783
784 return 0;
785}
786
787/*
788 * Perform a memory test. A more complete alternative test can be
789 * configured using CONFIG_SYS_ALT_MEMTEST. The complete test loops until
790 * interrupted by ctrl-c or by a failure of one of the sub-tests.
791 */
d0581f88 792command_ret_t do_mem_mtest(cmd_tbl_t *cmdtp, int flag, int argc,
72f58822
L
793 char * const argv[])
794{
795 uint32_t start, end;
796 vu_long *buf, *dummy;
797 int iteration_limit;
d0581f88 798/* TODO: command_ret_t */
72f58822
L
799 int ret;
800 uint32_t errs = 0; /* number of errors, or -1 if interrupted */
801 uint32_t pattern;
802 int iteration;
803#if defined(CONFIG_SYS_ALT_MEMTEST)
804 const int alt_test = 1;
805#else
806 const int alt_test = 0;
807#endif
808
809 if (argc > 1)
810 start = strtoul(argv[1], NULL, 16);
811 else
812 start = CONFIG_SYS_MEMTEST_START;
813
814 if (argc > 2)
815 end = strtoul(argv[2], NULL, 16);
816 else
817 end = CONFIG_SYS_MEMTEST_END;
818
819 if (argc > 3)
820 pattern = (uint32_t)strtoul(argv[3], NULL, 16);
821 else
822 pattern = 0;
823
824 if (argc > 4)
825 iteration_limit = (uint32_t)strtoul(argv[4], NULL, 16);
826 else
827 iteration_limit = 0;
828
69988dc1 829 printf_P(PSTR("Testing %08x ... %08x:\n"), (unsigned int)start, (unsigned int)end);
72f58822
L
830 debug("%s:%d: start %#05lx end %#05lx\n", __func__, __LINE__,
831 start, end);
832
833/* TODO: */
834// buf = map_sysmem(start, end - start);
835// dummy = map_sysmem(CONFIG_SYS_MEMTEST_SCRATCH, sizeof(vu_long));
836 for (iteration = 0;
837 !iteration_limit || iteration < iteration_limit;
838 iteration++) {
839 if (ctrlc()) {
840 errs = -1UL;
841 break;
842 }
843
69988dc1 844 printf_P(PSTR("Iteration: %6d\r"), iteration + 1);
72f58822
L
845 debug("\n");
846 if (alt_test) {
847 errs = mem_test_alt(buf, start, end, dummy);
848 } else {
849 errs = mem_test_quick(buf, start, end, pattern,
850 iteration);
851 }
852 if (errs == -1UL)
853 break;
854 }
855
856 if (errs == -1UL) {
857 /* Memory test was aborted - write a newline to finish off */
858 putc('\n');
859 ret = 1;
860 } else {
69988dc1 861 printf_P(PSTR("Tested %d iteration(s) with %lu errors.\n"),
72f58822
L
862 iteration, errs);
863 ret = errs != 0;
864 }
865
866 return ret; /* not reached */
867}
868#endif /* CONFIG_CMD_MEMTEST */