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