#include "apposmacro.h"
#undef CPE_30
#ifdef BUP_DIAGS
#define TRUE	1
#define FALSE   0
#define NULL    ((char*)0)
#define ERROR	-1

#define SUCCESS (0)
#define FAILURE (-1)


unsigned int   bup_memTestDataBus(volatile unsigned int * address);
unsigned int * bup_memTestAddressBus(volatile unsigned int * baseAddress, unsigned int nBytes);
unsigned int * bup_memTestDevice(volatile unsigned int * baseAddress, unsigned int nBytes);

extern int printDiags;
extern int userMem;
extern int bup_bme;

/**********************************************************************
 *
 * Function:    memTestDataBus()
 *
 * Description: Test the data bus wiring in a memory region by
 *              performing a walking 1's test at a fixed address
 *              within that region.  The address (and hence the
 *              memory region) is selected by the caller.
 *
 * Notes:       
 *
 * Returns:     0 if the test succeeds.  
 *              A non-zero result is the first pattern that failed.
 *
 **********************************************************************/
unsigned int bup_memTestDataBus(volatile unsigned int * address)
{
unsigned int pattern;

    /*
     * Perform a walking 1's test at the given address.
     */
    for (pattern = 1; pattern != 0; pattern <<= 1)
    {
        /*
         * Write the test pattern.
         */
		testPIOWrite (bup_bme,address,pattern);

        /*
         * Read it back (immediately 
         */
   		if (testPIORead1 (bup_bme,address) != pattern)
        {
            return (pattern);
        }
    }

    return (0);

}   /* memTestDataBus() */


/**********************************************************************
 *
 * Function:    memTestAddressBus()
 *
 * Description: Test the address bus wiring in a memory region by
 *              performing a walking 1's test on the relevant bits
 *              of the address and checking for aliasing. This test
 *              will find single-bit address failures such as stuck
 *              -high, stuck-low, and shorted pins.  The base address
 *              and size of the region are selected by the caller.
 *
 * Returns:     NULL if the test succeeds.  
 *              A non-zero result is the first address at which an
 *              aliasing problem was uncovered.  By examining the
 *              contents of memory, it may be possible to gather
 *              additional information about the problem.
 *
 **********************************************************************/
unsigned int * bup_memTestAddressBus(volatile unsigned int * baseAddress, unsigned int nBytes)
{

register unsigned int addressMask = (nBytes/sizeof(unsigned int) - 1);
register unsigned int offset;
register unsigned int testOffset;

register unsigned int pattern     = (unsigned int) 0xAAAAAAAA;
register unsigned int antipattern = (unsigned int) 0x55555555;
register int i;


    /*
     * Write the default pattern at each of the power-of-two offsets.
     */
    for (offset = 1; (offset & addressMask) != 0; offset <<= 1)
    {
		testPIOWrite (bup_bme,&(baseAddress[offset]),pattern);
//printf("tpw %x %x\n", &(baseAddress[offset]),pattern);
    }

    /* 
     * Check for address bits stuck high.
     */
    testOffset = 0;
	testPIOWrite (bup_bme,&(baseAddress[testOffset]),antipattern);


    for (offset = 1,i=2; (offset & addressMask) != 0; offset <<= 1,i++)
    {
//printf("tpr %x %x %x\n", &(baseAddress[offset]),offset,i);
		 if (testPIORead1 (bup_bme,&(baseAddress[offset])) != pattern)
		 {
			 printf("\t **** Address bit %d bad\n", i);
			 return ((unsigned int *) &baseAddress[offset]);
		 }
    }


	testPIOWrite (bup_bme,&(baseAddress[testOffset]),pattern);

    /*
     * Check for address bits stuck low or shorted.
     */
    for (testOffset = 1; (testOffset & addressMask) != 0; testOffset <<= 1)
    {
		testPIOWrite (bup_bme,&(baseAddress[testOffset]),antipattern);

		if (testPIORead1 (bup_bme,&(baseAddress[0])) != pattern)
		{
					
			printf("Address bit %d bad\n", testOffset);
			return ((unsigned int *) &baseAddress[testOffset]);
		}

        for (offset = 1; (offset & addressMask) != 0; offset <<= 1)
        {
			if ((testPIORead1 (bup_bme,&(baseAddress[0])) != pattern) && (offset != testOffset))
            {
				printf("Address bit %d bad\n", testOffset);
                return ((unsigned int *) &baseAddress[testOffset]);
            }
        }

		testPIOWrite (bup_bme,&(baseAddress[testOffset]),pattern);
    }

    return (0);

}   /* memTestAddressBus() */




int bup_memTestGetMemSz ()
{
int addr;
int offset;
int mem;
volatile unsigned int * baseAddress = (int*) 0x40000000;


    for (offset = 1; (offset & 0xffffff) != 0; offset <<= 1)
	{
		testPIOWrite (bup_bme,&(baseAddress[offset]),0);

	}
	testPIOWrite (bup_bme,0x40000000,0x12345678);

	for (offset = 1; (offset & 0xffffff) != 0; offset <<= 1)
	{

		addr = testPIORead1 (bup_bme,&(baseAddress[offset]));
		if (addr != 0)
		{
			mem = &(baseAddress[offset]);
			mem -= (int)baseAddress;
			if (printDiags) printf("\tMemory Detected 0x%x bytes\n",mem );
			if (mem != userMem)
				printf("\t **** Does not match user entry/default:%x\n",userMem );
			break;

		}
	}
	return mem;
}

int bup_memTestAddrData ()
{
int addr;
int offset;
int mem;
volatile unsigned int * baseAddress = (int*) 0x40000000;


   	if (addr = bup_memTestAddressBus((int*)0x40000000, userMem ))
		printf("\t **** Memory Address Bus Test Failed at address: 0x%x\n", addr);
	else 
		if (printDiags) printf("\tMemory Address Bus Test Passed\n");
	

	if (addr = bup_memTestDataBus((volatile unsigned int*)0x40000000))
	{
		int i =0;
		while (addr) {
			addr >>=1;
			i++;
		}
		printf("\t **** Memory Data Bus Test Failed at data bit : %d\n", i-1);
	}
	else
		if (printDiags) printf("\tMemory Data Bus Test Passed\n");

	// if theres a second chip.. i.e., by 32
	if (addr = bup_memTestDataBus((volatile unsigned int*)0x40000000))
	{
		int i =0;
		while (addr) {
			addr >>=1;
			i++;
		}
		printf("\t **** Memory Data Bus Test Failed at data bit : %d\n", i-1);
	}
	else
		if (printDiags) printf("\tMemory Data Bus Test Passed\n");

	if (addr)
		return FAILURE;
	else
		return 0;


}



#endif
