/*
 * diag_ram.c
 *
 * Matthew Millman
 */

#include <common.h>
#include <linux/ctype.h>
#include <diag.h>
#include <asm/io.h>

DECLARE_GLOBAL_DATA_PTR;

static u32 diag_dot_or_quit(void);

const u8	pattern_g[] = {	0x01, 0x02, 0x04, 0x08, 
							 	0x10, 0x20, 0x40, 0x80,
								0x80, 0x40, 0x20, 0x10,
								0x08, 0x04, 0x02, 0x01 };

/* A memory test pattern of 527 64-byte words. 527 is a prime number so the pattern
 * should not repeat very often on a similar memory boundary. The pattern is made
 * up of pairs of complementary 64-bit words so that lots of bits change
 */
const u32	pattern[] =
{
	0xaa555555, 0xaa555555, 0x55aaaaaa, 0x55aaaaaa, 0x44444444, 0x44444444, 0xcccccccc, 0xcccccccc, 
	0x555555aa, 0x555555aa, 0xaaaaaa55, 0xaaaaaa55, 0xfedcba98, 0xfedcba98, 0x01234567, 0x01234567, 
	0xdeadbeef, 0xdeadbeef, 0x32534220, 0x32534220, 0xf1f1f1f1, 0xf1f1f1f1, 0x1f1f1f1f, 0x1f1f1f1f, 
	0xd2d2d2d2, 0xd2d2d2d2, 0x2d2d2d2d, 0x2d2d2d2d, 0xa5a5a5a5, 0xa5a5a5a5, 0x5a5a5a5a, 0x5a5a5a5a, 
	0xffffffff, 0xffffffff, 0x00000000, 0x00000000, 0xa5a5a5a5, 0xa5a5a5a5, 0x5a5a5a5a, 0x5a5a5a5a, 
	0xe2e2e2e2, 0xe2e2e2e2, 0x2e2e2e2e, 0x2e2e2e2e, 0x00000000, 0x00000000, 0xffffffff, 0xffffffff, 
	0xc4c4c4c4, 0xc4c4c4c4, 0x4c4c4c4c, 0x4c4c4c4c, 0xbaabaaba, 0xbaabaaba, 0x45545545, 0x45545545, 
	0x96969696, 0x96969696, 0x69696969, 0x69696969, 0xaaaa5555, 0xaaaa5555, 0x5555aaaa, 0x5555aaaa, 
	0xdeadbeef, 0xdeadbeef, 0x32534220, 0x32534220, 0x12345678, 0x12345678, 0xedcba987, 0xedcba987, 
	0x12345678, 0x12345678, 0xedcba987, 0xedcba987, 0xaaaa5555, 0xaaaa5555, 0x5555aaaa, 0x5555aaaa, 
	0x11111111, 0x11111111, 0xffffffff, 0xffffffff, 0x87878787, 0x87878787, 0x78787878, 0x78787878, 
	0x33333333, 0x33333333, 0xdddddddd, 0xdddddddd, 0x1f1f1f1f, 0x1f1f1f1f, 0xf1f1f1f1, 0xf1f1f1f1, 
	0x55555555, 0x55555555, 0xaaaaaaaa, 0xaaaaaaaa, 0xf1f1f1f1, 0xf1f1f1f1, 0x1f1f1f1f, 0x1f1f1f1f, 
	0xc4c4c4c4, 0xc4c4c4c4, 0x4c4c4c4c, 0x4c4c4c4c, 0xbaabaaba, 0xbaabaaba, 0x45545545, 0x45545545, 
	0xa5a5a5a5, 0xa5a5a5a5, 0x5a5a5a5a, 0x5a5a5a5a, 0xd3d3d3d3, 0xd3d3d3d3, 0x3d3d3d3d, 0x3d3d3d3d, 
	0xaabaabaa, 0xaabaabaa, 0x55455455, 0x55455455, 0x22222222, 0x22222222, 0xeeeeeeee, 0xeeeeeeee, 

	0xaa555555, 0xaa555555, 0x55aaaaaa, 0x55aaaaaa, 0xfedcba98, 0xfedcba98, 0x01234567, 0x01234567, 
	0x555555aa, 0x555555aa, 0xaaaaaa55, 0xaaaaaa55, 0xfedcba98, 0xfedcba98, 0x01234567, 0x01234567, 
	0xb4b4b4b4, 0xb4b4b4b4, 0x4b4b4b4b, 0x4b4b4b4b, 0xbaabaaba, 0xbaabaaba, 0x45545545, 0x45545545, 
	0xd2d2d2d2, 0xd2d2d2d2, 0x2d2d2d2d, 0x2d2d2d2d, 0xa5a5a5a5, 0xa5a5a5a5, 0x5a5a5a5a, 0x5a5a5a5a, 
	0xffffffff, 0xffffffff, 0x00000000, 0x00000000, 0x55555555, 0x55555555, 0xaaaaaaaa, 0xaaaaaaaa, 
	0xe2e2e2e2, 0xe2e2e2e2, 0x2e2e2e2e, 0x2e2e2e2e, 0x32534220, 0x32534220, 0xdeadbeef, 0xdeadbeef, 
	0xc4c4c4c4, 0xc4c4c4c4, 0x4c4c4c4c, 0x4c4c4c4c, 0xa5a5a5a5, 0xa5a5a5a5, 0x5a5a5a5a, 0x5a5a5a5a, 
	0x96969696, 0x96969696, 0x69696969, 0x69696969, 0xd3d3d3d3, 0xd3d3d3d3, 0x3d3d3d3d, 0x3d3d3d3d, 
	0xdeadbeef, 0xdeadbeef, 0x32534220, 0x32534220, 0xf1f1f1f1, 0xf1f1f1f1, 0x1f1f1f1f, 0x1f1f1f1f, 
	0x12345678, 0x12345678, 0xedcba987, 0xedcba987, 0x00000000, 0x00000000, 0xffffffff, 0xffffffff, 
	0xaa555555, 0xaa555555, 0x55aaaaaa, 0x55aaaaaa, 0xfedcba98, 0xfedcba98, 0x01234567, 0x01234567, 
	0x33333333, 0x33333333, 0xdddddddd, 0xdddddddd, 0x3c3c3c3c, 0x3c3c3c3c, 0xc3c3c3c3, 0xc3c3c3c3, 
	0xbaabaaba, 0xbaabaaba, 0x45545545, 0x45545545, 0x22222222, 0x22222222, 0xeeeeeeee, 0xeeeeeeee, 
	0xa5a5a5a5, 0xa5a5a5a5, 0x5a5a5a5a, 0x5a5a5a5a, 0x3c3c3c3c, 0x3c3c3c3c, 0xc3c3c3c3, 0xc3c3c3c3, 
	0x87878787, 0x87878787, 0x78787878, 0x78787878, 0x44444444, 0x44444444, 0xcccccccc, 0xcccccccc, 
	0xc4c4c4c4, 0xc4c4c4c4, 0x4c4c4c4c, 0x4c4c4c4c, 0xbaabaaba, 0xbaabaaba, 0x45545545, 0x45545545, 

	0xaa555555, 0xaa555555, 0x55aaaaaa, 0x55aaaaaa, 0x00000000, 0x00000000, 0xffffffff, 0xffffffff, 
	0x555555aa, 0x555555aa, 0xaaaaaa55, 0xaaaaaa55, 0xf1f1f1f1, 0xf1f1f1f1, 0x1f1f1f1f, 0x1f1f1f1f, 
	0xb4b4b4b4, 0xb4b4b4b4, 0x4b4b4b4b, 0x4b4b4b4b, 0x1f1f1f1f, 0x1f1f1f1f, 0xf1f1f1f1, 0xf1f1f1f1, 
	0xd2d2d2d2, 0xd2d2d2d2, 0x2d2d2d2d, 0x2d2d2d2d, 0x32534220, 0x32534220, 0xdeadbeef, 0xdeadbeef, 
	0xffffffff, 0xffffffff, 0x00000000, 0x00000000, 0xa5a5a5a5, 0xa5a5a5a5, 0x5a5a5a5a, 0x5a5a5a5a, 
	0xe2e2e2e2, 0xe2e2e2e2, 0x2e2e2e2e, 0x2e2e2e2e, 0xa5a5a5a5, 0xa5a5a5a5, 0x5a5a5a5a, 0x5a5a5a5a, 
	0xc4c4c4c4, 0xc4c4c4c4, 0x4c4c4c4c, 0x4c4c4c4c, 0x66666666, 0x66666666, 0x99999999, 0x99999999, 
	0x96969696, 0x96969696, 0x69696969, 0x69696969, 0x87878787, 0x87878787, 0x78787878, 0x78787878, 
	0xdeadbeef, 0xdeadbeef, 0x32534220, 0x32534220, 0x55555555, 0x55555555, 0xaaaaaaaa, 0xaaaaaaaa, 
	0x12345678, 0x12345678, 0xedcba987, 0xedcba987, 0x00000000, 0x00000000, 0xffffffff, 0xffffffff, 
	0x11111111, 0x11111111, 0xffffffff, 0xffffffff, 0xa5a5a5a5, 0xa5a5a5a5, 0x5a5a5a5a, 0x5a5a5a5a, 
	0x33333333, 0x33333333, 0xdddddddd, 0xdddddddd, 0x55555555, 0x55555555, 0xaaaaaaaa, 0xaaaaaaaa, 
	0x55555555, 0x55555555, 0xaaaaaaaa, 0xaaaaaaaa, 0xaabaabaa, 0xaabaabaa, 0x55455455, 0x55455455, 
	0x77777777, 0x77777777, 0x88888888, 0x88888888, 0x32534220, 0x32534220, 0xdeadbeef, 0xdeadbeef, 
	0xa5a5a5a5, 0xa5a5a5a5, 0x5a5a5a5a, 0x5a5a5a5a, 0x1f1f1f1f, 0x1f1f1f1f, 0xf1f1f1f1, 0xf1f1f1f1, 
	0xe2e2e2e2, 0xe2e2e2e2, 0x2e2e2e2e, 0x2e2e2e2e, 0x00000000, 0x00000000, 0xffffffff, 0xffffffff, 

	0xaa555555, 0xaa555555, 0x55aaaaaa, 0x55aaaaaa, 0x44444444, 0x44444444, 0xcccccccc, 0xcccccccc, 
	0x555555aa, 0x555555aa, 0xaaaaaa55, 0xaaaaaa55, 0xfedcba98, 0xfedcba98, 0x01234567, 0x01234567, 
	0xb4b4b4b4, 0xb4b4b4b4, 0x4b4b4b4b, 0x4b4b4b4b, 0x3c3c3c3c, 0x3c3c3c3c, 0xc3c3c3c3, 0xc3c3c3c3, 
	0xd2d2d2d2, 0xd2d2d2d2, 0x2d2d2d2d, 0x2d2d2d2d, 0xa5a5a5a5, 0xa5a5a5a5, 0x5a5a5a5a, 0x5a5a5a5a, 
	0xffffffff, 0xffffffff, 0x00000000, 0x00000000, 0xa5a5a5a5, 0xa5a5a5a5, 0x5a5a5a5a, 0x5a5a5a5a, 
	0xe2e2e2e2, 0xe2e2e2e2, 0x2e2e2e2e, 0x2e2e2e2e, 0x00000000, 0x00000000, 0xffffffff, 0xffffffff, 
	0xc4c4c4c4, 0xc4c4c4c4, 0x4c4c4c4c, 0x4c4c4c4c, 0xbaabaaba, 0xbaabaaba, 0x45545545, 0x45545545, 
	0xaa555555, 0xaa555555, 0x55aaaaaa, 0x55aaaaaa, 0xfedcba98, 0xfedcba98, 0x01234567, 0x01234567, 
	0xc4c4c4c4, 0xc4c4c4c4, 0x4c4c4c4c, 0x4c4c4c4c, 0x66666666, 0x66666666, 0x99999999, 0x99999999, 
	0x96969696, 0x96969696, 0x69696969, 0x69696969, 0x87878787, 0x87878787, 0x78787878, 0x78787878, 
	0xdeadbeef, 0xdeadbeef, 0x32534220, 0x32534220, 0x55555555, 0x55555555, 0xaaaaaaaa, 0xaaaaaaaa, 
	0x11111111, 0x11111111, 0xffffffff, 0xffffffff, 0xa5a5a5a5, 0xa5a5a5a5, 0x5a5a5a5a, 0x5a5a5a5a, 
	0x33333333, 0x33333333, 0xdddddddd, 0xdddddddd, 0x55555555, 0x55555555, 0xaaaaaaaa, 0xaaaaaaaa, 
	0xc4c4c4c4, 0xc4c4c4c4, 0x4c4c4c4c, 0x4c4c4c4c, 0xbaabaaba, 0xbaabaaba, 0x45545545, 0x45545545, 
	0x55555555, 0x55555555, 0xaaaaaaaa, 0xaaaaaaaa, 0xaabaabaa, 0xaabaabaa, 0x55455455, 0x55455455, 
	0x77777777, 0x77777777, 0x88888888, 0x88888888, 0x32534220, 0x32534220, 0xdeadbeef, 0xdeadbeef, 

	0x555555aa, 0x555555aa, 0xaaaaaa55, 0xaaaaaa55, 0xfedcba98, 0xfedcba98, 0x01234567, 0x01234567, 
	0xb4b4b4b4, 0xb4b4b4b4, 0x4b4b4b4b, 0x4b4b4b4b, 0xbaabaaba, 0xbaabaaba, 0x45545545, 0x45545545, 
	0xaabaabaa, 0xaabaabaa, 0x55455455, 0x55455455, 0x22222222, 0x22222222, 0xeeeeeeee, 0xeeeeeeee, 
	0xffffffff, 0xffffffff, 0x00000000, 0x00000000, 0x55555555, 0x55555555, 0xaaaaaaaa, 0xaaaaaaaa, 
	0xe2e2e2e2, 0xe2e2e2e2, 0x2e2e2e2e, 0x2e2e2e2e, 0x32534220, 0x32534220, 0xdeadbeef, 0xdeadbeef, 
	0xc4c4c4c4, 0xc4c4c4c4, 0x4c4c4c4c, 0x4c4c4c4c, 0xa5a5a5a5, 0xa5a5a5a5, 0x5a5a5a5a, 0x5a5a5a5a, 
	0x96969696, 0x96969696, 0x69696969, 0x69696969, 0xd3d3d3d3, 0xd3d3d3d3, 0x3d3d3d3d, 0x3d3d3d3d, 
	0xdeadbeef, 0xdeadbeef, 0x32534220, 0x32534220, 0xf1f1f1f1, 0xf1f1f1f1, 0x1f1f1f1f, 0x1f1f1f1f, 
	0x12345678, 0x12345678, 0xedcba987, 0xedcba987, 0x00000000, 0x00000000, 0xffffffff, 0xffffffff, 
	0xe2e2e2e2, 0xe2e2e2e2, 0x2e2e2e2e, 0x2e2e2e2e, 0x32534220, 0x32534220, 0xdeadbeef, 0xdeadbeef, 
	0x33333333, 0x33333333, 0xdddddddd, 0xdddddddd, 0x3c3c3c3c, 0x3c3c3c3c, 0xc3c3c3c3, 0xc3c3c3c3, 
	0xbaabaaba, 0xbaabaaba, 0x45545545, 0x45545545, 0x22222222, 0x22222222, 0xeeeeeeee, 0xeeeeeeee, 
	0xa5a5a5a5, 0xa5a5a5a5, 0x5a5a5a5a, 0x5a5a5a5a, 0x3c3c3c3c, 0x3c3c3c3c, 0xc3c3c3c3, 0xc3c3c3c3, 
	0xffffffff, 0xffffffff, 0x00000000, 0x00000000, 0xa5a5a5a5, 0xa5a5a5a5, 0x5a5a5a5a, 0x5a5a5a5a, 
	0xa5a5a5a5, 0xa5a5a5a5, 0x5a5a5a5a, 0x5a5a5a5a, 0x1f1f1f1f, 0x1f1f1f1f, 0xf1f1f1f1, 0xf1f1f1f1, 
	0xaabaabaa, 0xaabaabaa, 0x55455455, 0x55455455, 0x22222222, 0x22222222, 0xeeeeeeee, 0xeeeeeeee, 

	0xaa555555, 0xaa555555, 0x55aaaaaa, 0x55aaaaaa, 0x00000000, 0x00000000, 0xffffffff, 0xffffffff, 
	0x555555aa, 0x555555aa, 0xaaaaaa55, 0xaaaaaa55, 0xf1f1f1f1, 0xf1f1f1f1, 0x1f1f1f1f, 0x1f1f1f1f, 
	0xb4b4b4b4, 0xb4b4b4b4, 0x4b4b4b4b, 0x4b4b4b4b, 0x1f1f1f1f, 0x1f1f1f1f, 0xf1f1f1f1, 0xf1f1f1f1, 
	0x12345678, 0x12345678, 0xedcba987, 0xedcba987, 0x44444444, 0x44444444, 0xcccccccc, 0xcccccccc, 
	0xd2d2d2d2, 0xd2d2d2d2, 0x2d2d2d2d, 0x2d2d2d2d, 0x32534220, 0x32534220, 0xdeadbeef, 0xdeadbeef, 
	0xffffffff, 0xffffffff, 0x00000000, 0x00000000, 0xa5a5a5a5, 0xa5a5a5a5, 0x5a5a5a5a, 0x5a5a5a5a, 
	0xe2e2e2e2, 0xe2e2e2e2, 0x2e2e2e2e, 0x2e2e2e2e, 0xa5a5a5a5, 0xa5a5a5a5, 0x5a5a5a5a, 0x5a5a5a5a, 
	0x96969696, 0x96969696, 0x69696969, 0x69696969, 0xaaaa5555, 0xaaaa5555, 0x5555aaaa, 0x5555aaaa, 
	0xdeadbeef, 0xdeadbeef, 0x32534220, 0x32534220, 0x12345678, 0x12345678, 0xedcba987, 0xedcba987, 
	0x12345678, 0x12345678, 0xedcba987, 0xedcba987, 0xaaaa5555, 0xaaaa5555, 0x5555aaaa, 0x5555aaaa, 
	0x11111111, 0x11111111, 0xffffffff, 0xffffffff, 0x87878787, 0x87878787, 0x78787878, 0x78787878, 
	0x33333333, 0x33333333, 0xdddddddd, 0xdddddddd, 0x1f1f1f1f, 0x1f1f1f1f, 0xf1f1f1f1, 0xf1f1f1f1, 
	0x55555555, 0x55555555, 0xaaaaaaaa, 0xaaaaaaaa, 0xf1f1f1f1, 0xf1f1f1f1, 0x1f1f1f1f, 0x1f1f1f1f, 
	0x77777777, 0x77777777, 0x88888888, 0x88888888, 0xd2d2d2d2, 0xd2d2d2d2, 0x2d2d2d2d, 0x2d2d2d2d, 
	0xa5a5a5a5, 0xa5a5a5a5, 0x5a5a5a5a, 0x5a5a5a5a, 0xd3d3d3d3, 0xd3d3d3d3, 0x3d3d3d3d, 0x3d3d3d3d, 
	0xaabaabaa, 0xaabaabaa, 0x55455455, 0x55455455, 0x22222222, 0x22222222, 0xeeeeeeee, 0xeeeeeeee, 

	0xffffffff, 0xffffffff, 0x00000000, 0x00000000, 0xa5a5a5a5, 0xa5a5a5a5, 0x5a5a5a5a, 0x5a5a5a5a, 
	0xe2e2e2e2, 0xe2e2e2e2, 0x2e2e2e2e, 0x2e2e2e2e, 0xa5a5a5a5, 0xa5a5a5a5, 0x5a5a5a5a, 0x5a5a5a5a, 
	0xc4c4c4c4, 0xc4c4c4c4, 0x4c4c4c4c, 0x4c4c4c4c, 0x66666666, 0x66666666, 0x99999999, 0x99999999, 
	0x96969696, 0x96969696, 0x69696969, 0x69696969, 0x87878787, 0x87878787, 0x78787878, 0x78787878, 
	0xdeadbeef, 0xdeadbeef, 0x32534220, 0x32534220, 0x55555555, 0x55555555, 0xaaaaaaaa, 0xaaaaaaaa, 
	0x12345678, 0x12345678, 0xedcba987, 0xedcba987, 0x44444444, 0x44444444, 0xcccccccc, 0xcccccccc, 
	0x11111111, 0x11111111, 0xffffffff, 0xffffffff, 0xa5a5a5a5, 0xa5a5a5a5, 0x5a5a5a5a, 0x5a5a5a5a, 
	0x33333333, 0x33333333, 0xdddddddd, 0xdddddddd, 0x55555555, 0x55555555, 0xaaaaaaaa, 0xaaaaaaaa, 
	0x96969696, 0x96969696, 0x69696969, 0x69696969, 0xd3d3d3d3, 0xd3d3d3d3, 0x3d3d3d3d, 0x3d3d3d3d, 
	0x77777777, 0x77777777, 0x88888888, 0x88888888, 0x32534220, 0x32534220, 0xdeadbeef, 0xdeadbeef, 
	0xa5a5a5a5, 0xa5a5a5a5, 0x5a5a5a5a, 0x5a5a5a5a, 0x1f1f1f1f, 0x1f1f1f1f, 0xf1f1f1f1, 0xf1f1f1f1, 
	0xaabaabaa, 0xaabaabaa, 0x55455455, 0x55455455, 0x22222222, 0x22222222, 0xeeeeeeee, 0xeeeeeeee, 
	0xe2e2e2e2, 0xe2e2e2e2, 0x2e2e2e2e, 0x2e2e2e2e, 0xa5a5a5a5, 0xa5a5a5a5, 0x5a5a5a5a, 0x5a5a5a5a, 
	0x96969696, 0x96969696, 0x69696969, 0x69696969, 0xaaaa5555, 0xaaaa5555, 0x5555aaaa, 0x5555aaaa, 
	0xdeadbeef, 0xdeadbeef, 0x32534220, 0x32534220, 0x12345678, 0x12345678, 0xedcba987, 0xedcba987, 
	0x12345678, 0x12345678, 0xedcba987, 0xedcba987, 0xaaaa5555, 0xaaaa5555, 0x5555aaaa, 0x5555aaaa, 

	0xaa555555, 0xaa555555, 0x55aaaaaa, 0x55aaaaaa, 0x44444444, 0x44444444, 0xcccccccc, 0xcccccccc, 
	0x555555aa, 0x555555aa, 0xaaaaaa55, 0xaaaaaa55, 0xfedcba98, 0xfedcba98, 0x01234567, 0x01234567, 
	0xb4b4b4b4, 0xb4b4b4b4, 0x4b4b4b4b, 0x4b4b4b4b, 0x3c3c3c3c, 0x3c3c3c3c, 0xc3c3c3c3, 0xc3c3c3c3, 
	0xd2d2d2d2, 0xd2d2d2d2, 0x2d2d2d2d, 0x2d2d2d2d, 0xa5a5a5a5, 0xa5a5a5a5, 0x5a5a5a5a, 0x5a5a5a5a, 
	0xc4c4c4c4, 0xc4c4c4c4, 0x4c4c4c4c, 0x4c4c4c4c, 0xa5a5a5a5, 0xa5a5a5a5, 0x5a5a5a5a, 0x5a5a5a5a, 
	0xe2e2e2e2, 0xe2e2e2e2, 0x2e2e2e2e, 0x2e2e2e2e, 0x00000000, 0x00000000, 0xffffffff, 0xffffffff, 
	0xdeadbeef, 0xdeadbeef, 0x32534220, 0x32534220, 0x55555555, 0x55555555, 0xaaaaaaaa, 0xaaaaaaaa, 
	0x11111111, 0x11111111, 0xffffffff, 0xffffffff, 0xa5a5a5a5, 0xa5a5a5a5, 0x5a5a5a5a, 0x5a5a5a5a, 
	0xe2e2e2e2, 0xe2e2e2e2, 0x2e2e2e2e, 0x2e2e2e2e, 0xa5a5a5a5, 0xa5a5a5a5, 0x5a5a5a5a, 0x5a5a5a5a, 
	0xc4c4c4c4, 0xc4c4c4c4, 0x4c4c4c4c, 0x4c4c4c4c, 0xbaabaaba, 0xbaabaaba, 0x45545545, 0x45545545, 
	0x55555555, 0x55555555, 0xaaaaaaaa, 0xaaaaaaaa, 0xaabaabaa, 0xaabaabaa, 0x55455455, 0x55455455, 
	0x77777777, 0x77777777, 0x88888888, 0x88888888, 0x32534220, 0x32534220, 0xdeadbeef, 0xdeadbeef, 
	0x12345678, 0x12345678, 0xedcba987, 0xedcba987, 0x44444444, 0x44444444, 0xcccccccc, 0xcccccccc, 
	0xd2d2d2d2, 0xd2d2d2d2, 0x2d2d2d2d, 0x2d2d2d2d, 0x32534220, 0x32534220, 0xdeadbeef, 0xdeadbeef, 
	0xffffffff, 0xffffffff, 0x00000000, 0x00000000, 0xa5a5a5a5, 0xa5a5a5a5, 0x5a5a5a5a, 0x5a5a5a5a, 
	0xe2e2e2e2, 0xe2e2e2e2, 0x2e2e2e2e, 0x2e2e2e2e, 0xa5a5a5a5, 0xa5a5a5a5, 0x5a5a5a5a, 0x5a5a5a5a, 

	0x555555aa, 0x555555aa, 0xaaaaaa55, 0xaaaaaa55, 0xfedcba98, 0xfedcba98, 0x01234567, 0x01234567, 
	0xb4b4b4b4, 0xb4b4b4b4, 0x4b4b4b4b, 0x4b4b4b4b, 0xbaabaaba, 0xbaabaaba, 0x45545545, 0x45545545, 
	0x55555555, 0x55555555, 0xaaaaaaaa, 0xaaaaaaaa, 0xaaaa5555, 0xaaaa5555, 0x5555aaaa, 0x5555aaaa, 
	0xffffffff, 0xffffffff, 0x00000000, 0x00000000, 0x55555555, 0x55555555
};

static ulong diag_ram_size(void)
{
#if defined(CONFIG_ARM)
	int i;
	ulong size = 0;

	for (i=0; i<CONFIG_NR_DRAM_BANKS; i++) {
		size += gd->bd->bi_dram[i].size;
	}
	return size;
#else
	return gd->ram_size;
#endif
}

u8 diag_quick_ram_test(u32 offset)
{
	u32	ramSizeMb;
	u32	i;
	u32	address;
	u8	diagnosticsOn;
	
	diagnosticsOn = 0;
	
	ramSizeMb = diag_ram_size() / 1024 / 1024;

/*	Write the pattern into the start of every megabyte of RAM
 */
	for (i = 4; i < ramSizeMb; i++)
	{
		address = offset + 0x00100000 * i;

		memcpy((void *)(address + 0), pattern_g, sizeof(pattern_g));
		memcpy((void *)(address + 0x80000), pattern_g, sizeof(pattern_g));
	}
	
/*	Flush the data cache, to force the data reads to come from main RAM
 */
	//This was done in NST, but not here.
	//
	//Flushing data cache = bad idea, this code is running out of the data cache, and, 
	//the data cache is locked from caching any actual data, so this is not needed.

/*	Check the pattern
 */
	for (i = 4; i < ramSizeMb; i++)
	{
		address = offset + 0x00100000 * i;
		
		if (diagnosticsOn)
		{
			serial_putc( 'r' );
		}

		if (memcmp((void *)(address + 0), pattern_g, sizeof(pattern_g)) != 0 ||
			memcmp((void *)(address + 0x80000), pattern_g, sizeof(pattern_g)) != 0)
		{
			serial_puts("\nError: Failed basic RAM test. System cannot continue\n");
			for (;;)
				;
		}
	}
	
	return 1;

}

#ifdef CONFIG_X600
extern void unlock_some_cache(void);
extern void relock_some_cache(void);
#endif /* CONFIG_X600 */

void diag_ram_pattern_test(u8 quickTest)
{
	u32		* ramPt;
	const u32	* patternPt;
	const u32	* patternEnd;
	u32		i;
	u32		totalErrors;
	u32		quit;
	u32		loopCount;
	u32		passNum;
	u32		dotModulo;
	u32		ramStart = 0;
	u32		offset = 0;
	u32		data;
	unsigned char	key;

#ifdef CONFIG_E500
	/* normally multi-bit ecc errors would result in a machine check
	 * interrupt, to allow the test to report the error and continue
	 * we'll clear the MBED bit */
	volatile ccsr_ddr_t *ddr = (void *)(CONFIG_SYS_MPC85xx_DDR_ADDR);
	setbits_be32(&ddr->err_disable, 0x8);
#endif

#ifdef CONFIG_X600
	/* Allow some data cache to be used for writing to RAM */
	unlock_some_cache();
#endif

#ifdef CONFIG_DIAG_RAM_START
	ramStart = CONFIG_DIAG_RAM_START;
#endif
#ifdef CONFIG_DIAG_RAM_SKIP_SIZE
	offset = CONFIG_DIAG_RAM_SKIP_SIZE;
#endif
	if ( quickTest )
	{
		serial_puts( "Quick RAM test - press Q to quit, S to skip when failing" );
	}
	else
	{
		serial_puts( "Full RAM test - press Q to quit, S to skip when failing" );
	}

	totalErrors = 0;
	quit = 0;
	passNum = 0;	/* Number of test passes */
	
	loopCount = (diag_ram_size() - offset) / 4;		/* Number of uint32's */
	dotModulo = ( loopCount - 1 ) >> 5;		/* 32 dots per line */

	while ( !quit )
	{
/*		Write the pattern
 */
		serial_puts( "\r\nWriting pattern  " );
		ramPt = (u32 *) (ramStart + offset);
		patternPt = &pattern[ 0 ];
		patternEnd = &pattern[ 0 ] + ( sizeof( pattern ) / sizeof( u32 ) );
		for ( i = 0; i < loopCount && !quit; i++ )
		{
			*ramPt++ = *patternPt++;

			if ( patternPt == patternEnd )
			{
				patternPt = &pattern[ 0 ];	/* Loop over pattern */
			}	
			
			if ( ( i & dotModulo ) == 0 )
			{
				if ( !diag_dot_or_quit() )	/* Check for quit or print dot */
					quit = 1;		/* User wants to quit */
			}
		}

/*		Flush the data cache
 */
		//This was done in NST, but not here.
		//
		//Flushing data cache = bad idea, this code is running out of the data cache, and, 
		//the data cache is locked from caching any actual data, so this is not needed.

/*		Check the pattern
 */
		if ( !quit )
		{
			serial_puts( "\r\nChecking pattern " );
		}
		ramPt = (u32 *) (ramStart + offset);
		patternPt = &pattern[ 0 ];
		patternEnd = &pattern[ 0 ] + ( sizeof( pattern ) / sizeof( u32 ) );
		for ( i = 0; i < loopCount && !quit; i++ )
		{
			data = *ramPt;
			if ( data != *patternPt )
			{
				serial_puts( "\r\nMemory error - address: " );
				diag_hex4byte_out( (u32) ramPt );
				serial_puts( "  should be " );
				diag_hex4byte_out( *patternPt );
				serial_puts( "  but is " );
				diag_hex4byte_out( data );
				totalErrors++;
				if (tstc())
				{
					key = serial_getc();
					if ( key == 'S' || key == 's' )
					{
						break;
					}
				}
			}
			ramPt++;
			patternPt++;

			if ( patternPt == patternEnd )
			{
				patternPt = &pattern[ 0 ];
			}
			if ( ( i & dotModulo ) == 0 )
			{
				if ( !diag_dot_or_quit() )
					quit = 1;
			}
		}
		
/*		Write the complemented pattern
 */
		if ( !quit )
		{
			serial_puts( "\r\nWriting complemented pattern  " );
		}
		ramPt = (u32 *) (ramStart + offset);
		patternPt = &pattern[ 0 ];
		patternEnd = &pattern[ 0 ] + ( sizeof( pattern ) / sizeof( u32 ) );
		for ( i = 0; i < loopCount && !quit; i++ )
		{
			*ramPt++ = ~( *patternPt++ );

			if ( patternPt == patternEnd )
			{
				patternPt = &pattern[ 0 ];
			}
			if ( ( i & dotModulo ) == 0 )
			{
				if ( !diag_dot_or_quit() )
					quit = 1;
			}
		}

/*		Check the complemented pattern
 */
		if ( !quit )
		{
			serial_puts( "\r\nChecking complemented pattern " );
		}
		ramPt = (u32 *) (ramStart + offset);
		patternPt = &pattern[ 0 ];
		patternEnd = &pattern[ 0 ] + ( sizeof( pattern ) / sizeof( u32 ) );
		for ( i = 0; i < loopCount && !quit; i++ )
		{
			data = *ramPt;
			if ( data != ~( *patternPt ) )
			{
				serial_puts( "\r\nMemory error - address: " );
				diag_hex4byte_out( (u32) ramPt );
				serial_puts( "  should be " );
				diag_hex4byte_out( ~( *patternPt ) );
				serial_puts( "  but is " );
				diag_hex4byte_out( data );
				totalErrors++;
				if (tstc())
				{
					key = serial_getc();
					
					if ( key == 'S' || key == 's' )
					{
						break;
					}
				}
			}
			ramPt++;
			patternPt++;

			if ( patternPt == patternEnd )
			{
				patternPt = &pattern[ 0 ];
			}
			if ( ( i & dotModulo ) == 0 )
			{
				if ( !diag_dot_or_quit() )
					quit = 1;
			}
		}
		if ( !quit )
		{
			passNum++;
			serial_puts( "\r\nPass " );
			diag_decimal_out( passNum );
			serial_puts( "  total errors " );
			diag_decimal_out( totalErrors );
		}
		if ( quickTest )
		{
			quit = 1;
			if ( totalErrors == 0 )
			{
				serial_puts( "  PASS" );
			}
			else
			{
				serial_puts( "  FAIL" );
			}
		}
	}
	serial_putc('\n');
	serial_putc('\n');
#ifdef CONFIG_X600
	/* Put the data cache back the way we found it */
	relock_some_cache();
#endif
}

#ifdef CONFIG_NVS_SIZE
#if defined(CONFIG_X200_GE) || defined(CONFIG_X200_X400_FE) || defined(CONFIG_X210_ATRD) || defined(CONFIG_X510)
void diag_nvs_pattern_test(void)
{
	u8		* ramPt;
	const u8	* patternPt;
	const u8	* patternEnd;
	u32		i;
	u32		totalErrors;
	u32		quit;
	u32		loopCount;
	u32		passNum;
	u32		dotModulo;
	u8		data;
	u8		notpattern;
	unsigned char	key;

	serial_puts( "\n  WARNING: This option will destroy the contents of the NVS file system."
	             "\n  Press Y to proceed, or any other key to return to the previous menu ==> " );

	key = serial_getc();

	if ((key >= 0x20) && (key <= 0x7E))
	{
		serial_putc( key );
	}

	if (key != 'y' && key != 'Y')
		return;

	serial_puts( "\n\n  Battery backed RAM (NVS) test in progress - press Q to quit...\r\n" );

/*	Run the NVS test
 */
	totalErrors = 0;
	quit = 0;
	passNum = 0;	/* Number of test passes */

	loopCount = CONFIG_NVS_SIZE;	/* Number of uint8's */
	dotModulo = ( loopCount - 1 ) >> 5;		/* 32 dots per line */
	patternEnd = (const u8 *)&pattern[ 0 ] + ( sizeof( pattern ) );

	while ( !quit )
	{
/*		Write the pattern
 */
		serial_puts( "\r\nWriting pattern  " );
		ramPt = (u8 *) CONFIG_NVS_LOCATION + CONFIG_DIAG_NVS_BYTE_OFFSET;
		patternPt = (const u8 *)&pattern[ 0 ];
		for ( i = 0; i < loopCount && !quit; i++ )
		{
			*ramPt = *patternPt++;
			ramPt += 2;

			if ( patternPt == patternEnd )
			{
				patternPt = (const u8 *)&pattern[ 0 ];	/* Loop over pattern */
			}

			if ( ( i & dotModulo ) == 0 )
			{
				if ( !diag_dot_or_quit() )	/* Check for quit or print dot */
					quit = 1;		/* User wants to quit */
			}
		}

/*		Flush the data cache
 */
		//This was done in NST, but not here.
		//
		//Flushing data cache = bad idea, this code is running out of the data cache, and,
		//the data cache is locked from caching any actual data, so this is not needed.

/*		Check the pattern
 */
		if ( !quit )
		{
			serial_puts( "\r\nChecking pattern " );
		}
		ramPt = (u8 *) CONFIG_NVS_LOCATION + CONFIG_DIAG_NVS_BYTE_OFFSET;
		patternPt = (const u8 *)&pattern[ 0 ];
		for ( i = 0; i < loopCount && !quit; i++ )
		{
			data = *ramPt;
			if ( data != *patternPt )
			{
				serial_puts( "\r\nMemory error - address: " );
				diag_hex4byte_out( (u32) ramPt );
				serial_puts( "  should be " );
				diag_hexbyte_out( *patternPt );
				serial_puts( "  but is " );
				diag_hexbyte_out( data );
				totalErrors++;
				if (tstc())
				{
					key = serial_getc();
					if ( key == 'S' || key == 's' )
					{
						break;
					}
				}
			}
			ramPt += 2;
			patternPt++;

			if ( patternPt == patternEnd )
			{
				patternPt = (const u8 *)&pattern[ 0 ];
			}
			if ( ( i & dotModulo ) == 0 )
			{
				if ( !diag_dot_or_quit() )
					quit = 1;
			}
		}

/*		Write the complemented pattern
 */
		if ( !quit )
		{
			serial_puts( "\r\nWriting complemented pattern  " );
		}
		ramPt = (u8 *) CONFIG_NVS_LOCATION + CONFIG_DIAG_NVS_BYTE_OFFSET;
		patternPt = (const u8 *)&pattern[ 0 ];
		for ( i = 0; i < loopCount && !quit; i++ )
		{
			*ramPt = ~( *patternPt++ );
			ramPt += 2;

			if ( patternPt == patternEnd )
			{
				patternPt = (const u8 *)&pattern[ 0 ];
			}
			if ( ( i & dotModulo ) == 0 )
			{
				if ( !diag_dot_or_quit() )
					quit = 1;
			}
		}

/*		Check the complemented pattern
 */
		if ( !quit )
		{
			serial_puts( "\r\nChecking complemented pattern " );
		}
		ramPt = (u8 *) CONFIG_NVS_LOCATION + CONFIG_DIAG_NVS_BYTE_OFFSET;
		patternPt = (const u8 *)&pattern[ 0 ];
		for ( i = 0; i < loopCount && !quit; i++ )
		{
			notpattern = *patternPt;
			data = *ramPt;
			if ( data != (0xff ^ notpattern) )
//			if ( *ramPt != ~( *patternPt ) )
			{
				serial_puts( "\r\nMemory error - address: " );
				diag_hex4byte_out( (u32) ramPt );
				serial_puts( "  should be " );
				diag_hexbyte_out( ~( *patternPt ) );
				serial_puts( "  but is " );
				diag_hexbyte_out( data );
				totalErrors++;
				if (tstc())
				{
					key = serial_getc();

					if ( key == 'S' || key == 's' )
					{
						break;
					}
				}
			}
			ramPt += 2;
			patternPt++;

			if ( patternPt == patternEnd )
			{
				patternPt = (const u8 *)&pattern[ 0 ];
			}
			if ( ( i & dotModulo ) == 0 )
			{
				if ( !diag_dot_or_quit() )
					quit = 1;
			}
		}
		if ( !quit )
		{
			passNum++;
			serial_puts( "\r\nPass " );
			diag_decimal_out( passNum );
			serial_puts( "  total errors " );
			diag_decimal_out( totalErrors );
		}
	}
	serial_putc('\n');
	serial_putc('\n');
}
#else
void diag_nvs_pattern_test(void)
{
	u32		* ramPt;
	const u32	* patternPt;
	const u32	* patternEnd;
	u32		i;
	u32		totalErrors;
	u32		quit;
	u32		loopCount;
	u32		passNum;
	u32		dotModulo;
	u32		data;
	unsigned char	key;

	serial_puts( "\n  WARNING: This option will destroy the contents of the NVS file system."
	             "\n  Press Y to proceed, or any other key to return to the previous menu ==> " );

	key = serial_getc();

	if ((key >= 0x20) && (key <= 0x7E))
	{
		serial_putc( key );
	}

	if (key != 'y' && key != 'Y')
		return;

	serial_puts( "\n\n  Battery backed RAM (NVS) test in progress - press Q to quit...\r\n" );	

/*	Run the NVS test
 */
	totalErrors = 0;
	quit = 0;
	passNum = 0;	/* Number of test passes */
	
	loopCount = CONFIG_NVS_SIZE / 4;	/* Number of uint32's */
	dotModulo = ( loopCount - 1 ) >> 5;		/* 32 dots per line */
	patternEnd = &pattern[ 0 ] + ( sizeof( pattern ) / sizeof( u32 ) );

	while ( !quit )
	{
/*		Write the pattern
 */
		serial_puts( "\r\nWriting pattern  " );
		ramPt = (u32 *) CONFIG_NVS_LOCATION;
		patternPt = &pattern[ 0 ];
		for ( i = 0; i < loopCount && !quit; i++ )
		{
			*ramPt++ = *patternPt++;

			if ( patternPt == patternEnd )
			{
				patternPt = &pattern[ 0 ];	/* Loop over pattern */
			}	
			
			if ( ( i & dotModulo ) == 0 )
			{
				if ( !diag_dot_or_quit() )	/* Check for quit or print dot */
					quit = 1;		/* User wants to quit */
			}
		}

/*		Flush the data cache
 */
		//This was done in NST, but not here.
		//
		//Flushing data cache = bad idea, this code is running out of the data cache, and, 
		//the data cache is locked from caching any actual data, so this is not needed.

/*		Check the pattern
 */
		if ( !quit )
		{
			serial_puts( "\r\nChecking pattern " );
		}
		ramPt = (u32 *) CONFIG_NVS_LOCATION;
		patternPt = &pattern[ 0 ];
		for ( i = 0; i < loopCount && !quit; i++ )
		{
			data = *ramPt;
			if ( data != *patternPt )
			{
				serial_puts( "\r\nMemory error - address: " );
				diag_hex4byte_out( (u32) ramPt );
				serial_puts( "  should be " );
				diag_hex4byte_out( *patternPt );
				serial_puts( "  but is " );
				diag_hex4byte_out( data );
				totalErrors++;
				if (tstc())
				{
					key = serial_getc();
					if ( key == 'S' || key == 's' )
					{
						break;
					}
				}
			}
			ramPt++;
			patternPt++;

			if ( patternPt == patternEnd )
			{
				patternPt = &pattern[ 0 ];
			}
			if ( ( i & dotModulo ) == 0 )
			{
				if ( !diag_dot_or_quit() )
					quit = 1;
			}
		}
		
/*		Write the complemented pattern
 */
		if ( !quit )
		{
			serial_puts( "\r\nWriting complemented pattern  " );
		}
		ramPt = (u32 *) CONFIG_NVS_LOCATION;
		patternPt = &pattern[ 0 ];
		for ( i = 0; i < loopCount && !quit; i++ )
		{
			*ramPt++ = ~( *patternPt++ );

			if ( patternPt == patternEnd )
			{
				patternPt = &pattern[ 0 ];
			}
			if ( ( i & dotModulo ) == 0 )
			{
				if ( !diag_dot_or_quit() )
					quit = 1;
			}
		}

/*		Check the complemented pattern
 */
		if ( !quit )
		{
			serial_puts( "\r\nChecking complemented pattern " );
		}
		ramPt = (u32 *) CONFIG_NVS_LOCATION;
		patternPt = &pattern[ 0 ];
		for ( i = 0; i < loopCount && !quit; i++ )
		{
			data = *ramPt;
			if ( data != ~( *patternPt ) )
			{
				serial_puts( "\r\nMemory error - address: " );
				diag_hex4byte_out( (u32) ramPt );
				serial_puts( "  should be " );
				diag_hex4byte_out( ~( *patternPt ) );
				serial_puts( "  but is " );
				diag_hex4byte_out( data );
				totalErrors++;
				if (tstc())
				{
					key = serial_getc();
					
					if ( key == 'S' || key == 's' )
					{
						break;
					}
				}
			}
			ramPt++;
			patternPt++;

			if ( patternPt == patternEnd )
			{
				patternPt = &pattern[ 0 ];
			}
			if ( ( i & dotModulo ) == 0 )
			{
				if ( !diag_dot_or_quit() )
					quit = 1;
			}
		}
		if ( !quit )
		{
			passNum++;
			serial_puts( "\r\nPass " );
			diag_decimal_out( passNum );
			serial_puts( "  total errors " );
			diag_decimal_out( totalErrors );
		}
	}
	serial_putc('\n');
	serial_putc('\n');
}
#endif /* CONFIG_X200_GE || CONFIG_X200_X400_FE || CONFIG_X210_ATRD || CONFIG_X510 */
#endif /* CONFIG_NVS_SIZE */


/*
 * If a 'q' or 'Q' has been received on the console then return FALSE, otherwise
 * output a '.' and return 1.
 */
static u32 diag_dot_or_quit(void)
{
	unsigned char		key;
	u32	retValue;
	
	retValue = 0;

	if (tstc())
	{
		key = serial_getc();
		if ( key == 'Q' || key == 'q' )
		{
			retValue = 0;
		}
	}
	else
	{
		serial_puts( "." );
		retValue = 1;
	}	
	return( retValue );

}
