cmd_mem.c 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850
  1. /*
  2. * (C) Copyright 2000
  3. * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
  4. *
  5. * See file CREDITS for list of people who contributed to this
  6. * project.
  7. *
  8. * This program is free software; you can redistribute it and/or
  9. * modify it under the terms of the GNU General Public License as
  10. * published by the Free Software Foundation; either version 2 of
  11. * the License, or (at your option) any later version.
  12. *
  13. * This program is distributed in the hope that it will be useful,
  14. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. * GNU General Public License for more details.
  17. *
  18. * You should have received a copy of the GNU General Public License
  19. * along with this program; if not, write to the Free Software
  20. * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
  21. * MA 02111-1307 USA
  22. */
  23. /*
  24. * Memory Functions
  25. *
  26. * Copied from FADS ROM, Dan Malek (dmalek@jlc.net)
  27. */
  28. #include <common.h>
  29. #include <command.h>
  30. #include <cmd_mem.h>
  31. #if (CONFIG_COMMANDS & (CFG_CMD_MEMORY | CFG_CMD_PCI | CFG_CMD_I2C))
  32. int cmd_get_data_size(char* arg, int default_size)
  33. {
  34. /* Check for a size specification .b, .w or .l.
  35. */
  36. int len = strlen(arg);
  37. if (len > 2 && arg[len-2] == '.') {
  38. switch(arg[len-1]) {
  39. case 'b':
  40. return 1;
  41. case 'w':
  42. return 2;
  43. case 'l':
  44. return 4;
  45. }
  46. }
  47. return default_size;
  48. }
  49. #endif
  50. #if (CONFIG_COMMANDS & CFG_CMD_MEMORY)
  51. #ifdef CMD_MEM_DEBUG
  52. #define PRINTF(fmt,args...) printf (fmt ,##args)
  53. #else
  54. #define PRINTF(fmt,args...)
  55. #endif
  56. static int mod_mem(cmd_tbl_t *, int, int, int, char *[]);
  57. /* Display values from last command.
  58. * Memory modify remembered values are different from display memory.
  59. */
  60. uint dp_last_addr, dp_last_size;
  61. uint dp_last_length = 0x40;
  62. uint mm_last_addr, mm_last_size;
  63. static ulong base_address = 0;
  64. /* Memory Display
  65. *
  66. * Syntax:
  67. * md{.b, .w, .l} {addr} {len}
  68. */
  69. #define DISP_LINE_LEN 16
  70. int do_mem_md ( cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
  71. {
  72. ulong addr, size, length;
  73. ulong i, nbytes, linebytes;
  74. u_char *cp;
  75. int rc = 0;
  76. /* We use the last specified parameters, unless new ones are
  77. * entered.
  78. */
  79. addr = dp_last_addr;
  80. size = dp_last_size;
  81. length = dp_last_length;
  82. if (argc < 2) {
  83. printf ("Usage:\n%s\n", cmdtp->usage);
  84. return 1;
  85. }
  86. if ((flag & CMD_FLAG_REPEAT) == 0) {
  87. /* New command specified. Check for a size specification.
  88. * Defaults to long if no or incorrect specification.
  89. */
  90. size = cmd_get_data_size(argv[0], 4);
  91. /* Address is specified since argc > 1
  92. */
  93. addr = simple_strtoul(argv[1], NULL, 16);
  94. addr += base_address;
  95. /* If another parameter, it is the length to display.
  96. * Length is the number of objects, not number of bytes.
  97. */
  98. if (argc > 2)
  99. length = simple_strtoul(argv[2], NULL, 16);
  100. }
  101. /* Print the lines.
  102. *
  103. * We buffer all read data, so we can make sure data is read only
  104. * once, and all accesses are with the specified bus width.
  105. */
  106. nbytes = length * size;
  107. do {
  108. char linebuf[DISP_LINE_LEN];
  109. uint *uip = (uint *)linebuf;
  110. ushort *usp = (ushort *)linebuf;
  111. u_char *ucp = (u_char *)linebuf;
  112. printf("%08lx:", addr);
  113. linebytes = (nbytes>DISP_LINE_LEN)?DISP_LINE_LEN:nbytes;
  114. for (i=0; i<linebytes; i+= size) {
  115. if (size == 4) {
  116. printf(" %08x", (*uip++ = *((uint *)addr)));
  117. } else if (size == 2) {
  118. printf(" %04x", (*usp++ = *((ushort *)addr)));
  119. } else {
  120. printf(" %02x", (*ucp++ = *((u_char *)addr)));
  121. }
  122. addr += size;
  123. }
  124. printf(" ");
  125. cp = linebuf;
  126. for (i=0; i<linebytes; i++) {
  127. if ((*cp < 0x20) || (*cp > 0x7e))
  128. printf(".");
  129. else
  130. printf("%c", *cp);
  131. cp++;
  132. }
  133. printf("\n");
  134. nbytes -= linebytes;
  135. if (ctrlc()) {
  136. rc = 1;
  137. break;
  138. }
  139. } while (nbytes > 0);
  140. dp_last_addr = addr;
  141. dp_last_length = length;
  142. dp_last_size = size;
  143. return (rc);
  144. }
  145. int do_mem_mm ( cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
  146. {
  147. return mod_mem (cmdtp, 1, flag, argc, argv);
  148. }
  149. int do_mem_nm ( cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
  150. {
  151. return mod_mem (cmdtp, 0, flag, argc, argv);
  152. }
  153. int do_mem_mw ( cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
  154. {
  155. ulong addr, size, writeval, count;
  156. if ((argc < 3) || (argc > 4)) {
  157. printf ("Usage:\n%s\n", cmdtp->usage);
  158. return 1;
  159. }
  160. /* Check for size specification.
  161. */
  162. size = cmd_get_data_size(argv[0], 4);
  163. /* Address is specified since argc > 1
  164. */
  165. addr = simple_strtoul(argv[1], NULL, 16);
  166. addr += base_address;
  167. /* Get the value to write.
  168. */
  169. writeval = simple_strtoul(argv[2], NULL, 16);
  170. /* Count ? */
  171. if (argc == 4) {
  172. count = simple_strtoul(argv[3], NULL, 16);
  173. } else {
  174. count = 1;
  175. }
  176. while (count-- > 0) {
  177. if (size == 4)
  178. *((ulong *)addr) = (ulong )writeval;
  179. else if (size == 2)
  180. *((ushort *)addr) = (ushort)writeval;
  181. else
  182. *((u_char *)addr) = (u_char)writeval;
  183. addr += size;
  184. }
  185. return 0;
  186. }
  187. int do_mem_cmp (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
  188. {
  189. ulong size, addr1, addr2, count, ngood;
  190. int rcode = 0;
  191. if (argc != 4) {
  192. printf ("Usage:\n%s\n", cmdtp->usage);
  193. return 1;
  194. }
  195. /* Check for size specification.
  196. */
  197. size = cmd_get_data_size(argv[0], 4);
  198. addr1 = simple_strtoul(argv[1], NULL, 16);
  199. addr1 += base_address;
  200. addr2 = simple_strtoul(argv[2], NULL, 16);
  201. addr2 += base_address;
  202. count = simple_strtoul(argv[3], NULL, 16);
  203. ngood = 0;
  204. while (count-- > 0) {
  205. if (size == 4) {
  206. ulong word1 = *(ulong *)addr1;
  207. ulong word2 = *(ulong *)addr2;
  208. if (word1 != word2) {
  209. printf("word at 0x%08lx (0x%08lx) "
  210. "!= word at 0x%08lx (0x%08lx)\n",
  211. addr1, word1, addr2, word2);
  212. rcode = 1;
  213. break;
  214. }
  215. }
  216. else if (size == 2) {
  217. ushort hword1 = *(ushort *)addr1;
  218. ushort hword2 = *(ushort *)addr2;
  219. if (hword1 != hword2) {
  220. printf("halfword at 0x%08lx (0x%04x) "
  221. "!= halfword at 0x%08lx (0x%04x)\n",
  222. addr1, hword1, addr2, hword2);
  223. rcode = 1;
  224. break;
  225. }
  226. }
  227. else {
  228. u_char byte1 = *(u_char *)addr1;
  229. u_char byte2 = *(u_char *)addr2;
  230. if (byte1 != byte2) {
  231. printf("byte at 0x%08lx (0x%02x) "
  232. "!= byte at 0x%08lx (0x%02x)\n",
  233. addr1, byte1, addr2, byte2);
  234. rcode = 1;
  235. break;
  236. }
  237. }
  238. ngood++;
  239. addr1 += size;
  240. addr2 += size;
  241. }
  242. printf("Total of %ld %s%s were the same\n",
  243. ngood, size == 4 ? "word" : size == 2 ? "halfword" : "byte",
  244. ngood == 1 ? "" : "s");
  245. return rcode;
  246. }
  247. int do_mem_cp ( cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
  248. {
  249. ulong addr, size, dest, count;
  250. if (argc != 4) {
  251. printf ("Usage:\n%s\n", cmdtp->usage);
  252. return 1;
  253. }
  254. /* Check for size specification.
  255. */
  256. size = cmd_get_data_size(argv[0], 4);
  257. addr = simple_strtoul(argv[1], NULL, 16);
  258. addr += base_address;
  259. dest = simple_strtoul(argv[2], NULL, 16);
  260. dest += base_address;
  261. count = simple_strtoul(argv[3], NULL, 16);
  262. if (count == 0) {
  263. puts ("Zero length ???\n");
  264. return 1;
  265. }
  266. #ifndef CFG_NO_FLASH
  267. /* check if we are copying to Flash */
  268. if (addr2info(dest) != NULL) {
  269. int rc;
  270. printf ("Copy to Flash... ");
  271. rc = flash_write ((uchar *)addr, dest, count*size);
  272. if (rc != 0) {
  273. flash_perror (rc);
  274. return (1);
  275. }
  276. puts ("done\n");
  277. return 0;
  278. }
  279. #endif
  280. while (count-- > 0) {
  281. if (size == 4)
  282. *((ulong *)dest) = *((ulong *)addr);
  283. else if (size == 2)
  284. *((ushort *)dest) = *((ushort *)addr);
  285. else
  286. *((u_char *)dest) = *((u_char *)addr);
  287. addr += size;
  288. dest += size;
  289. }
  290. return 0;
  291. }
  292. int do_mem_base (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
  293. {
  294. if (argc > 1) {
  295. /* Set new base address.
  296. */
  297. base_address = simple_strtoul(argv[1], NULL, 16);
  298. }
  299. /* Print the current base address.
  300. */
  301. printf("Base Address: 0x%08lx\n", base_address);
  302. return 0;
  303. }
  304. int do_mem_loop (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
  305. {
  306. ulong addr, size, length, i, junk;
  307. volatile uint *longp;
  308. volatile ushort *shortp;
  309. volatile u_char *cp;
  310. if (argc < 3) {
  311. printf ("Usage:\n%s\n", cmdtp->usage);
  312. return 1;
  313. }
  314. /* Check for a size spefication.
  315. * Defaults to long if no or incorrect specification.
  316. */
  317. size = cmd_get_data_size(argv[0], 4);
  318. /* Address is always specified.
  319. */
  320. addr = simple_strtoul(argv[1], NULL, 16);
  321. /* Length is the number of objects, not number of bytes.
  322. */
  323. length = simple_strtoul(argv[2], NULL, 16);
  324. /* We want to optimize the loops to run as fast as possible.
  325. * If we have only one object, just run infinite loops.
  326. */
  327. if (length == 1) {
  328. if (size == 4) {
  329. longp = (uint *)addr;
  330. for (;;)
  331. i = *longp;
  332. }
  333. if (size == 2) {
  334. shortp = (ushort *)addr;
  335. for (;;)
  336. i = *shortp;
  337. }
  338. cp = (u_char *)addr;
  339. for (;;)
  340. i = *cp;
  341. }
  342. if (size == 4) {
  343. for (;;) {
  344. longp = (uint *)addr;
  345. i = length;
  346. while (i-- > 0)
  347. junk = *longp++;
  348. }
  349. }
  350. if (size == 2) {
  351. for (;;) {
  352. shortp = (ushort *)addr;
  353. i = length;
  354. while (i-- > 0)
  355. junk = *shortp++;
  356. }
  357. }
  358. for (;;) {
  359. cp = (u_char *)addr;
  360. i = length;
  361. while (i-- > 0)
  362. junk = *cp++;
  363. }
  364. }
  365. /*
  366. * Perform a memory test. A more complete alternative test can be
  367. * configured using CFG_ALT_MEMTEST. The complete test loops until
  368. * interrupted by ctrl-c or by a failure of one of the sub-tests.
  369. */
  370. int do_mem_mtest (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
  371. {
  372. vu_long *addr, *start, *end;
  373. ulong val;
  374. ulong readback;
  375. #if defined(CFG_ALT_MEMTEST)
  376. vu_long addr_mask;
  377. vu_long offset;
  378. vu_long test_offset;
  379. vu_long pattern;
  380. vu_long temp;
  381. vu_long anti_pattern;
  382. vu_long num_words;
  383. vu_long *dummy = NULL;
  384. int j;
  385. int iterations = 1;
  386. static const ulong bitpattern[] = {
  387. 0x00000001, /* single bit */
  388. 0x00000003, /* two adjacent bits */
  389. 0x00000007, /* three adjacent bits */
  390. 0x0000000F, /* four adjacent bits */
  391. 0x00000005, /* two non-adjacent bits */
  392. 0x00000015, /* three non-adjacent bits */
  393. 0x00000055, /* four non-adjacent bits */
  394. 0xaaaaaaaa, /* alternating 1/0 */
  395. };
  396. #else
  397. ulong incr;
  398. ulong pattern;
  399. int rcode = 0;
  400. #endif
  401. if (argc > 1) {
  402. start = (ulong *)simple_strtoul(argv[1], NULL, 16);
  403. } else {
  404. start = (ulong *)CFG_MEMTEST_START;
  405. }
  406. if (argc > 2) {
  407. end = (ulong *)simple_strtoul(argv[2], NULL, 16);
  408. } else {
  409. end = (ulong *)(CFG_MEMTEST_END);
  410. }
  411. if (argc > 3) {
  412. pattern = (ulong)simple_strtoul(argv[3], NULL, 16);
  413. } else {
  414. pattern = 0;
  415. }
  416. #if defined(CFG_ALT_MEMTEST)
  417. printf ("Testing %08x ... %08x:\n", (uint)start, (uint)end);
  418. PRINTF("%s:%d: start 0x%p end 0x%p\n",
  419. __FUNCTION__, __LINE__, start, end);
  420. for (;;) {
  421. if (ctrlc()) {
  422. putc ('\n');
  423. return 1;
  424. }
  425. printf("Iteration: %6d\r", iterations);
  426. PRINTF("Iteration: %6d\n", iterations);
  427. iterations++;
  428. /*
  429. * Data line test: write a pattern to the first
  430. * location, write the 1's complement to a 'parking'
  431. * address (changes the state of the data bus so a
  432. * floating bus doen't give a false OK), and then
  433. * read the value back. Note that we read it back
  434. * into a variable because the next time we read it,
  435. * it might be right (been there, tough to explain to
  436. * the quality guys why it prints a failure when the
  437. * "is" and "should be" are obviously the same in the
  438. * error message).
  439. *
  440. * Rather than exhaustively testing, we test some
  441. * patterns by shifting '1' bits through a field of
  442. * '0's and '0' bits through a field of '1's (i.e.
  443. * pattern and ~pattern).
  444. */
  445. addr = start;
  446. for (j = 0; j < sizeof(bitpattern)/sizeof(bitpattern[0]); j++) {
  447. val = bitpattern[j];
  448. for(; val != 0; val <<= 1) {
  449. *addr = val;
  450. *dummy = ~val; /* clear the test data off of the bus */
  451. readback = *addr;
  452. if(readback != val) {
  453. printf ("FAILURE (data line): "
  454. "expected %08lx, actual %08lx\n",
  455. val, readback);
  456. }
  457. *addr = ~val;
  458. *dummy = val;
  459. readback = *addr;
  460. if(readback != ~val) {
  461. printf ("FAILURE (data line): "
  462. "Is %08lx, should be %08lx\n",
  463. val, readback);
  464. }
  465. }
  466. }
  467. /*
  468. * Based on code whose Original Author and Copyright
  469. * information follows: Copyright (c) 1998 by Michael
  470. * Barr. This software is placed into the public
  471. * domain and may be used for any purpose. However,
  472. * this notice must not be changed or removed and no
  473. * warranty is either expressed or implied by its
  474. * publication or distribution.
  475. */
  476. /*
  477. * Address line test
  478. *
  479. * Description: Test the address bus wiring in a
  480. * memory region by performing a walking
  481. * 1's test on the relevant bits of the
  482. * address and checking for aliasing.
  483. * This test will find single-bit
  484. * address failures such as stuck -high,
  485. * stuck-low, and shorted pins. The base
  486. * address and size of the region are
  487. * selected by the caller.
  488. *
  489. * Notes: For best results, the selected base
  490. * address should have enough LSB 0's to
  491. * guarantee single address bit changes.
  492. * For example, to test a 64-Kbyte
  493. * region, select a base address on a
  494. * 64-Kbyte boundary. Also, select the
  495. * region size as a power-of-two if at
  496. * all possible.
  497. *
  498. * Returns: 0 if the test succeeds, 1 if the test fails.
  499. *
  500. * ## NOTE ## Be sure to specify start and end
  501. * addresses such that addr_mask has
  502. * lots of bits set. For example an
  503. * address range of 01000000 02000000 is
  504. * bad while a range of 01000000
  505. * 01ffffff is perfect.
  506. */
  507. addr_mask = ((ulong)end - (ulong)start)/sizeof(vu_long);
  508. pattern = (vu_long) 0xaaaaaaaa;
  509. anti_pattern = (vu_long) 0x55555555;
  510. PRINTF("%s:%d: addr mask = 0x%.8lx\n",
  511. __FUNCTION__, __LINE__,
  512. addr_mask);
  513. /*
  514. * Write the default pattern at each of the
  515. * power-of-two offsets.
  516. */
  517. for (offset = 1; (offset & addr_mask) != 0; offset <<= 1) {
  518. start[offset] = pattern;
  519. }
  520. /*
  521. * Check for address bits stuck high.
  522. */
  523. test_offset = 0;
  524. start[test_offset] = anti_pattern;
  525. for (offset = 1; (offset & addr_mask) != 0; offset <<= 1) {
  526. temp = start[offset];
  527. if (temp != pattern) {
  528. printf ("\nFAILURE: Address bit stuck high @ 0x%.8lx:"
  529. " expected 0x%.8lx, actual 0x%.8lx\n",
  530. (ulong)&start[offset], pattern, temp);
  531. return 1;
  532. }
  533. }
  534. start[test_offset] = pattern;
  535. /*
  536. * Check for addr bits stuck low or shorted.
  537. */
  538. for (test_offset = 1; (test_offset & addr_mask) != 0; test_offset <<= 1) {
  539. start[test_offset] = anti_pattern;
  540. for (offset = 1; (offset & addr_mask) != 0; offset <<= 1) {
  541. temp = start[offset];
  542. if ((temp != pattern) && (offset != test_offset)) {
  543. printf ("\nFAILURE: Address bit stuck low or shorted @"
  544. " 0x%.8lx: expected 0x%.8lx, actual 0x%.8lx\n",
  545. (ulong)&start[offset], pattern, temp);
  546. return 1;
  547. }
  548. }
  549. start[test_offset] = pattern;
  550. }
  551. /*
  552. * Description: Test the integrity of a physical
  553. * memory device by performing an
  554. * increment/decrement test over the
  555. * entire region. In the process every
  556. * storage bit in the device is tested
  557. * as a zero and a one. The base address
  558. * and the size of the region are
  559. * selected by the caller.
  560. *
  561. * Returns: 0 if the test succeeds, 1 if the test fails.
  562. */
  563. num_words = ((ulong)end - (ulong)start)/sizeof(vu_long) + 1;
  564. /*
  565. * Fill memory with a known pattern.
  566. */
  567. for (pattern = 1, offset = 0; offset < num_words; pattern++, offset++) {
  568. start[offset] = pattern;
  569. }
  570. /*
  571. * Check each location and invert it for the second pass.
  572. */
  573. for (pattern = 1, offset = 0; offset < num_words; pattern++, offset++) {
  574. temp = start[offset];
  575. if (temp != pattern) {
  576. printf ("\nFAILURE (read/write) @ 0x%.8lx:"
  577. " expected 0x%.8lx, actual 0x%.8lx)\n",
  578. (ulong)&start[offset], pattern, temp);
  579. return 1;
  580. }
  581. anti_pattern = ~pattern;
  582. start[offset] = anti_pattern;
  583. }
  584. /*
  585. * Check each location for the inverted pattern and zero it.
  586. */
  587. for (pattern = 1, offset = 0; offset < num_words; pattern++, offset++) {
  588. anti_pattern = ~pattern;
  589. temp = start[offset];
  590. if (temp != anti_pattern) {
  591. printf ("\nFAILURE (read/write): @ 0x%.8lx:"
  592. " expected 0x%.8lx, actual 0x%.8lx)\n",
  593. (ulong)&start[offset], anti_pattern, temp);
  594. return 1;
  595. }
  596. start[offset] = 0;
  597. }
  598. }
  599. #else /* The original, quickie test */
  600. incr = 1;
  601. for (;;) {
  602. if (ctrlc()) {
  603. putc ('\n');
  604. return 1;
  605. }
  606. printf ("\rPattern %08lX Writing..."
  607. "%12s"
  608. "\b\b\b\b\b\b\b\b\b\b",
  609. pattern, "");
  610. for (addr=start,val=pattern; addr<end; addr++) {
  611. *addr = val;
  612. val += incr;
  613. }
  614. printf("Reading...");
  615. for (addr=start,val=pattern; addr<end; addr++) {
  616. readback = *addr;
  617. if (readback != val) {
  618. printf ("\nMem error @ 0x%08X: "
  619. "found %08lX, expected %08lX\n",
  620. (uint)addr, readback, val);
  621. rcode = 1;
  622. }
  623. val += incr;
  624. }
  625. /*
  626. * Flip the pattern each time to make lots of zeros and
  627. * then, the next time, lots of ones. We decrement
  628. * the "negative" patterns and increment the "positive"
  629. * patterns to preserve this feature.
  630. */
  631. if(pattern & 0x80000000) {
  632. pattern = -pattern; /* complement & increment */
  633. }
  634. else {
  635. pattern = ~pattern;
  636. }
  637. incr = -incr;
  638. }
  639. return rcode;
  640. #endif
  641. }
  642. /* Modify memory.
  643. *
  644. * Syntax:
  645. * mm{.b, .w, .l} {addr}
  646. * nm{.b, .w, .l} {addr}
  647. */
  648. static int
  649. mod_mem(cmd_tbl_t *cmdtp, int incrflag, int flag, int argc, char *argv[])
  650. {
  651. ulong addr, size, i;
  652. int nbytes;
  653. extern char console_buffer[];
  654. if (argc != 2) {
  655. printf ("Usage:\n%s\n", cmdtp->usage);
  656. return 1;
  657. }
  658. #ifdef CONFIG_BOOT_RETRY_TIME
  659. reset_cmd_timeout(); /* got a good command to get here */
  660. #endif
  661. /* We use the last specified parameters, unless new ones are
  662. * entered.
  663. */
  664. addr = mm_last_addr;
  665. size = mm_last_size;
  666. if ((flag & CMD_FLAG_REPEAT) == 0) {
  667. /* New command specified. Check for a size specification.
  668. * Defaults to long if no or incorrect specification.
  669. */
  670. size = cmd_get_data_size(argv[0], 4);
  671. /* Address is specified since argc > 1
  672. */
  673. addr = simple_strtoul(argv[1], NULL, 16);
  674. addr += base_address;
  675. }
  676. /* Print the address, followed by value. Then accept input for
  677. * the next value. A non-converted value exits.
  678. */
  679. do {
  680. printf("%08lx:", addr);
  681. if (size == 4)
  682. printf(" %08x", *((uint *)addr));
  683. else if (size == 2)
  684. printf(" %04x", *((ushort *)addr));
  685. else
  686. printf(" %02x", *((u_char *)addr));
  687. nbytes = readline (" ? ");
  688. if (nbytes == 0 || (nbytes == 1 && console_buffer[0] == '-')) {
  689. /* <CR> pressed as only input, don't modify current
  690. * location and move to next. "-" pressed will go back.
  691. */
  692. if (incrflag)
  693. addr += nbytes ? -size : size;
  694. nbytes = 1;
  695. #ifdef CONFIG_BOOT_RETRY_TIME
  696. reset_cmd_timeout(); /* good enough to not time out */
  697. #endif
  698. }
  699. #ifdef CONFIG_BOOT_RETRY_TIME
  700. else if (nbytes == -2) {
  701. break; /* timed out, exit the command */
  702. }
  703. #endif
  704. else {
  705. char *endp;
  706. i = simple_strtoul(console_buffer, &endp, 16);
  707. nbytes = endp - console_buffer;
  708. if (nbytes) {
  709. #ifdef CONFIG_BOOT_RETRY_TIME
  710. /* good enough to not time out
  711. */
  712. reset_cmd_timeout();
  713. #endif
  714. if (size == 4)
  715. *((uint *)addr) = i;
  716. else if (size == 2)
  717. *((ushort *)addr) = i;
  718. else
  719. *((u_char *)addr) = i;
  720. if (incrflag)
  721. addr += size;
  722. }
  723. }
  724. } while (nbytes);
  725. mm_last_addr = addr;
  726. mm_last_size = size;
  727. return 0;
  728. }
  729. int do_mem_crc (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
  730. {
  731. ulong addr, length;
  732. ulong crc;
  733. ulong *ptr;
  734. if (argc < 3) {
  735. printf ("Usage:\n%s\n", cmdtp->usage);
  736. return 1;
  737. }
  738. addr = simple_strtoul(argv[1], NULL, 16);
  739. addr += base_address;
  740. length = simple_strtoul(argv[2], NULL, 16);
  741. crc = crc32 (0, (const uchar *)addr, length);
  742. printf ("CRC32 for %08lx ... %08lx ==> %08lx\n",
  743. addr, addr + length -1, crc);
  744. if (argc > 3)
  745. {
  746. ptr = (ulong *)simple_strtoul(argv[3], NULL, 16);
  747. *ptr = crc;
  748. }
  749. return 0;
  750. }
  751. #endif /* CFG_CMD_MEMORY */