// AMD 29F080 BITS:8 BUS:32 ACCESS:INTEGER
/*#include "vm.h"*/
#ifdef USE_VXWORKS /* IXDP425 */
#include "vxWorks.h"
#include "config.h"
#include "ioLib.h"
#include "iosLib.h"
#include "memLib.h"
#include "errnoLib.h"
#endif
#include "string.h"
#include "stdlib.h"
#include "stdio.h"
#ifdef USE_VXWORKS
#include "bootlib.h"
#include "ftplib.h"
#include "fiolib.h"
#include "remlib.h"
#include "taskLib.h"
#endif
#include "flash.h"

typedef float	FLOAT;
typedef double	DOUBLE;

#define IOSync()	asm ("	eieio")

#if __PACKUNALIGNED__
typedef __packed__ struct tSOURCE
{
	int Integer;
} _PackedType tSOURCE;
#define ReadUnaligned(x)    ((tSOURCE *)(x))->Integer
#else
#define ReadUnaligned(x)	*(int *)(x)
#endif

#ifdef __LITTLE_ENDIAN__
#define	MASKSHIFTOP1	<<
#define MASKSHIFTOP2	>>
#else
#define MASKSHIFTOP1	>>
#define MASKSHIFTOP2	<<
#endif

typedef union tFLASH
{
	int Integer;
	int Float;
} tFLASH;

#ifdef FLASH_BITSWAP
static const tFLASH Unlock1 =	{ 0x55555555 };
static const tFLASH Unlock2 =	{ 0xAAAAAAAA };
static const tFLASH Erase1 = 	{ 0x01010101 };
static const tFLASH Erase2 = 	{ 0x0c0c0c0c };
static const tFLASH Program =	{ 0x05050505 };
static const tFLASH ReadArray =	{ 0x0F0F0F0F };
static const tFLASH Erased =	{ (int)-1 };
#else
static const tFLASH Unlock1 =	{ 0xAAAAAAAA };
static const tFLASH Unlock2 =	{ 0x55555555 };
static const tFLASH Erase1 = 	{ 0x80808080 };
static const tFLASH Erase2 = 	{ 0x30303030 };
static const tFLASH Program =	{ 0xA0A0A0A0 };
static const tFLASH ReadArray =	{ 0xF0F0F0F0 };
static const tFLASH Erased =	{ (int)-1 };
#endif
                                                         


extern int intLock();
extern void intUnlock(int);

extern int FlashWriteVW(volatile char *pDest, char *pSource,
		int Length)
{ 
#ifdef MPC855 /*Flash write disabled for IXDP425 board */
	volatile char *pChip = (volatile char *)((unsigned int)pDest
			& ~(0x400000 - 1));
	unsigned int OriginalLength = Length;
	int Mask;
	tFLASH Data;
	unsigned short n;

/*	SetFlashTimer(5000);		// 5 second timeout*/
	while(Length)
	{
		if ((n = ((unsigned int)pDest & (4 - 1))))
		{
			pDest -= n;
			pSource -= n;
			Mask = (int)-1 MASKSHIFTOP1 (8 * n);
		}
		else
			Mask = (int)-1;

		if ((n + Length) < 4)
			Mask &= (int)-1 MASKSHIFTOP2 (8 * (4 - (n + Length)));

		Data.Integer = ReadUnaligned(pSource) & Mask;
		Data.Integer |= *(int *)pDest & (~Mask);
		pSource += 4;
		*(volatile int *)(pChip + 0x15554) = Unlock1.Float;
		IOSync();
		*(volatile int *)(pChip + 0xAAA8) = Unlock2.Float;
		IOSync();
		*(volatile int *)(pChip + 0x15554) = Program.Float;
		IOSync();
		*(volatile int *)pDest = Data.Float;


		while ((*(volatile int *)pDest != Data.Integer))
			;
		pDest += 4;
		Length -= min(4 - n, Length);
	}

/*	KillTimer(&FlashTimer);*/
	*(volatile int *)(pDest - 4) = ReadArray.Float;
	return OriginalLength - Length;
#endif 
}

extern int FlashEraseSectorVW(volatile char *pSector)
{
#ifdef MPC_855 /*Flash Erase sector disabled for IXDP425 board */
	volatile char *pChip = (volatile char *)((unsigned int)pSector
			& ~(0x400000 - 1));

/*	SetFlashTimer(5000);*/

	*(volatile int *)(pChip + 0x15554) = Unlock1.Float;
	IOSync();
	*(volatile int *)(pChip + 0xAAA8) = Unlock2.Float;
	IOSync();
	*(volatile int *)(pChip + 0x15554) = Erase1.Float;
	IOSync();
	*(volatile int *)(pChip + 0x15554) = Unlock1.Float;
	IOSync();
	*(volatile int *)(pChip + 0xAAA8) = Unlock2.Float;
	IOSync();
	*(volatile int *)pSector = Erase2.Float;
	IOSync();

	while ((*(volatile int *)pSector != Erased.Integer))
		;

/*	KillTimer(&FlashTimer);*/
	*(volatile int *)pSector = ReadArray.Float;
	return (*(volatile int *)pSector != Erased.Integer);
#endif 
	return 0;
}

FLASHOBJECT FO_29F080x4 =
{
	FlashWriteVW,
	FlashEraseSectorVW,
	0x40000,
	"AMD 29F080 ("
	"1024 x 8"
	") 4 Device"
	"s"
};

void wtSect(volatile char *adr, char *ptr, int size)
{
    int lock;
#ifdef MPC_855 /*Flash write sector disabled for IXDP425 board */
    lock = intLock();
    FlashEraseSectorVW((unsigned char volatile*)adr);
    FlashWriteVW ((volatile char *)adr, ptr, FLASH_SECT_SIZE);
    intUnlock(lock);
#endif
}
