/*	FiUtil.c - Edit 1

	LoadICE Version 4
	Copyright (C) 1990-99 Grammar Engine, Inc.
	All rights reserved
	
	NOTICE:  This software source is a licensed copy of Grammar Engine's
	property.  It is supplied to you as part of support and maintenance
	of some Grammar Engine products that you may have purchased.  Use of
	this software is strictly limited to use with such products.  Any
	other use constitutes a violation of this license to you.
*/

/*	 - FlashICE utility functions:
		firemon - FlashICE Resource Monitor
		fishows - show sector info
		fishowc - show chip info
		fiinit  - init any globals
*/
#include <stdio.h>
#ifndef UNIX
#include <dos.h>
#include <io.h>
#include <conio.h>
#endif

#include "piconfig.h"
#include "pistruct.h"
#include "pierror.h"
#include "pidriver.h"
#include "pidata.h"

static void fidobp(void);
static void fidoce(void);
static void fidose(void);
static void fiemu(void);
static void filod(void);
extern void pcrstt(short id, short len);
extern void piread(void);
extern void piwrite(void);
extern void pifixcfg(void);

#define	BPT0	0
#define	BPT1	1
#define	BPAN	2
#define	BPWO	3

static short fid=0;
static unsigned char r[6],r0,r1,sta,stb;
static	PIFLASH *fp = &pxflash[0];

/* `firemon` - FlashICE Resource Monitor */

void firemon()
	{
	int i;

	printf("\n\nFlashICE Monitor");

	for (fid=0; fid<pxprom; fid++)
		{
		fp = &pxflash[fid];
		if (!(fp->fiflags&MC_FIHO))
			continue;
		r[0] = r[1] = 0;
		sta = stb = 0;
		fp->fictl &= ~FIC_ICLR;

		if (!fp->once)
		 	{
			fp->fimoe |= MC_FIHO;
			fp->fimoe &= ~MC_FINO;
			picmd((char)fid,FI_RW,2,FIW_CLR,0,0,0,0);
			picmd((char)fid,PI_CM,1,fp->fimoe,0,0,0,0);
			pcrstt((char)fid,0);
			fp->once = 1;
			fp->doclra++;
			}	

		picmd((char)fid,FI_RW,2,FIW_CTL|FIW_UCTL,fp->fictl,0,0,0);
		picmd((char)fid,FI_RW|CM_CHANGE,5,fp->fiman,fp->fidev,fp->fidv2,fp->fispd,0);

		while (!pxerror)
			{
			if (fp->doclra)
				{
				picmd((char)fid,FI_RW,2,FIW_CLR,0,0,0,0);
				fp->doclra = 0;
				r0 = r1 = 0;
				if (fp->fiflags & FiBRF)
					printf("\n READY");
				}
#ifndef UNIX
			if (kbhit())
				{
				fp->fiflags &= ~FiFON;
				break;
				}
#endif
/*			pxnotot = 1; */
			picmd((char)fid,(char)FI_RR,1,(char)FIR_RR6,0,0,0,0);
/*			while (pxerror == PGE_TMO)
//				{
//				pirsp();
//				}
*/			for (i=0; i<6; i++)
				r[i] = pxrsp[PIDT+i];
			if ((r0 == r[0]) && (r1 == r[1]))
				continue;

			if (fp->fiflags & FiBRF)
				printf("\n%02X%02X %02X%02X%02X %02X",r[0],r[1],r[2],r[3],r[4],r[5]);
			sta = (unsigned char)((r0 ^ r[0]) & r[0]);
			stb = (unsigned char)((r1 ^ r[1]) & r[1]);
			r0 = r[0];
			r1 = r[1];

			if (fp->fiflags&FiLOG)
				{
				write(fclog,&r[0],6);
				}
			if (fp->fiflags & FiBRF)
				{
				if (sta & FIA_BPS)
					printf("\n Byte Program Seen");
				if (sta & FIA_BPN)
					printf("\n Byte Program Cycle");
				if (sta & FIA_ICS)
					printf("\n Illegal Command Seen");
				if (stb & FIB_ERS)
					printf("\n Erase Seen");
				if (sta & FIA_SUS)
					printf("\n Suspend Erase Seen");
				if (sta & FIA_SES)
					printf("\n Sector Erase Seen");
				if (sta & FIA_CES)
					printf("\n Chip Erase Seen");
				if (stb & FIB_ASS)
					printf("\n Auto Select Entered");
				if (stb & FIB_RRS)
					printf("\n Read Reset Seen");
				if (stb & FIB_SMA)
					printf("\n Unlock Sequence Entered");
				if (stb & FIB_SMB)
					printf("\n Unlock Sequence Complete");
				}
			if (fp->etls)
				{
				if (r1&FIB_RRS)
					{
					fp->etls = 0;
					fp->doclra++;
					}
				if (r0&FIA_ICS)
					fp->fillcs++;
				continue;
				}
			if (r1 & FIB_ERS)
				{
	 			if (r0 & FIA_CES)
					{
					fidoce();
					if (!(fp->fiflags & FiALL))
						fp->fiflags &= ~(FiCEA|FiCEO|FiCET);
					}
				else
					{
	 				if (r0 & FIA_SES)
						{
						fidose();
						if (!(fp->fiflags & FiALL))
							fp->fiflags &= ~(FiSEA|FiSEO|FiSET);
						}
					else
						{
						if ((r0 & FIA_BPS) || (r1 & FIB_ASS))
							{
							if (fp->fiflags & FiBRF)
								printf("\n Illegal Command Sequence");
							fp->fillcs++;
							fp->doclra++;
							continue;
							}
						}
					}
				}
			else
				{
				if ((r0 & FIA_BPN) && (r0 & FIA_BPS))
					{
					fidobp();
					if (!(fp->fiflags & FiALL))
						fp->fiflags &= ~(FiPEA|FiPEO|FiPET);
					}
				}
			if (r0&FIA_ICS)
				fp->fillcs++;

			if ((r1 & FIB_RRS) || (r0 & FIA_ICS))
				fp->doclra++;
			}
/*			pxnotot = 0; */
		}
	}

/* `firexit` - exit the FlashICE monitor */

void firexit(short thisone)
	{

	fp = &pxflash[thisone];
	fp->once = 0;
	fp->fictl |= FIC_ICLR;
	fp->fiflags &= ~FiFON;
	if (fp->fimoe & MC_FIHO)
		{
		fp->fimoe &= ~MC_FIHO;
		picmd((char)thisone,PI_CM,1,fp->fimoe,0,0,0,0);
		}
	picmd((char)thisone,FI_RW,2,FIW_CTL|FIW_UCTL,fp->fictl,0,0,0);
	picmd((char)thisone,PI_MO,1,(char)(pxmode1|MO_AUTO),0,0,0,0);
	}

void fienb(short thisone)
	{
	fp = &pxflash[thisone];
	fp->fimoe &= ~(MC_FINO|MC_FIHO);
	if (piflags&PiUP)
		{
		picmd((char)thisone,FI_RW,2,FIW_CLR,0,0,0,0);
		picmd((char)thisone,PI_CM,1,fp->fimoe,0,0,0,0);
		}
	else
		fp->fiflags |= FiENB;
	}

/* `fidobp` - process program byte command */

void fidobp()
	{
	unsigned long addr;
	unsigned char sn,sset=0;

	if (!(r0 & FIA_ICS))
		{
		pxxloc = (long)(((long)r[2])<<16)|(long)(((long)r[3])<<8)|(long)r[4];
		if (fp->fictl&FIC_F040)
			pxxloc &= 0x7ffff;
		else
			pxxloc &= 0x1ffff;
		if (fp->fiflags & FiBRF)
			printf("\n  byte program: address=%lX data=%X ",pxxloc,r[5]);
		if (fp->fictl&FIC_F040)
			{
			sn = (char)((pxxloc>>16)&(long)0x07);
			addr = pxxloc & (long)0xffff;
			}
		else
			{
			sn = (char)((pxxloc>>14)&(long)0x07);
			addr = pxxloc & (long)0x3fff;
			}
		if (fp->fiflags & FiBRF)
			printf("\tSector %d Offset %lX\n",sn,addr);
		fp->fibpc[sn]++;
		fp->fitbp[sn]++;
		fp->figbp++;
		if (fp->fispd&(1<<sn))
			{
			if (fp->fiflags & FiBRF)
				printf("\n  Can not program byte - Sector is protected");
			fp->fibpcp[sn]++;
			sset = 0;
			}
		else
			{
			if (fp->fiflags & FiPET)
				{
				if (fp->fiflags & FiBRF)
					printf("\n  byte program: setting ETL (timeout error)");
				picmd((char)fid,FI_RW,2,FIW_CTL,(char)(fp->fictl|FIC_ETL),0,0,0);
				fp->fibpct[sn]++;
				fp->etls++;
				return;
				}
			if (fp->fiflags&(FiPEA|FiPEO))
				{
				if (fp->fiflags & FiBRF)
					printf(" Creating BIT error(s)");
				if (fp->fiflags & FiPEA)
					r[5] &= fp->fipem;
				if (fp->fiflags & FiPEO)
					r[5] |= fp->fipem;
				}
				pxxbf[0] = r[5];
				pxxbc = 1;
				filod();
			pxyloc = pxxloc;
			pxybc = 1;
			piread();
			if (!pxerror)
				{
				sset = 0;
				sn = (unsigned char)(pxybf[0]&0x0ff);
				if (fp->fiflags & FiBRF)
					printf("\n  byte program: data was %02X ",sn);
				switch(fp->fiopt&3)
					{
					case BPWO:
						if (fp->fiflags & FiBRF)
							printf("\n  byte program: data move");
						sn = r[5];
						break;
					case BPAN:
						if (fp->fiflags & FiBRF)
							printf("\n  byte program: data AND");
						sn &= r[5];
						break;
					case BPT0:
						if ((sn&r[5]) != r[5])
							sset++;
						else
							{
							if (fp->fiflags & FiBRF)
								printf("\n  byte program: data AND");
							sn &= r[5];
							}
						break;
					case BPT1:
						if (sn != 0x0ff)
							sset++;
						else
							{
							if (fp->fiflags & FiBRF)
								printf("\n  byte program: was FF");
							sn = r[5];
							}
						break;
					}
				if (sset)
					{
					if (fp->fiflags & FiBRF)
						printf("\n  byte program: programming 0->1 setting ETL");
					picmd((char)fid,FI_RW,2,FIW_CTL,(char)(fp->fictl|FIC_ETL),0,0,0);
					fp->fibpct[sn]++;
					fp->etls++;
					}
				else
					{
					pxxbf[0] = sn;
					piwrite();
					}
				}
			fiemu();
			}
		if (!sset)
			fp->doclra++;
		}
	}

/* `fidoce` - process chip erase command */

void fidoce()
	{
	unsigned char fc;
	int sc;
	long i,tct;
	PIROM *rp;
	PICONFIG *tcfg;

	if (!(r0 & FIA_ICS))
		{
		fp->ficec++;
		if (fp->fiflags & FiCET)
			{
			if (fp->fiflags & FiBRF)
				printf("\n  chip erase: setting ETL (timeout error)");
			picmd((char)fid,FI_RW,2,FIW_CTL,(char)(fp->fictl|FIC_ETL),0,0,0);
			fp->etls++;
			return;
			}
		if (fp->fiflags & FiBRF)
			printf("\n  chip erase: in progress");
		tcfg = pxcfg;
		rp = &pxrom[0];
		fc = 0x0ff;
		pxcfg = &pxaltcfg;
		pxcfg->words = 1;
		pxcfg->uid[0] = 0;
		pifixcfg();
		if (rp->fstart == rp->fend)
			{
			tct = rp->esize;
			pxxloc = pxcfg->start;
			}
		else
			{
			tct = rp->fend - rp->fstart + 1;
			pxxloc = rp->fstart;
			}
		pxdlc = 0;
		filod();
		for (sc=0; sc<8; sc++)
			{
			if ((1<<sc)&fp->fispd)
				continue;
			tct = pxrom[0].esize/8;
			pxxloc = sc * tct;
			while (tct && !pxerror)
				{
				if (tct > PIC_BS)
					pxxbc = PIC_BS;
				else
					pxxbc = tct;
				tct -= pxxbc;
				for (i=0; i<pxxbc; i++)
					{
					pxxbf[i] = fc;
					}
				piwrite();
				pxxloc += pxxbc;
				}
			}
		pxcfg = tcfg;
		fiemu();
		fp->doclra++;
		}
	}

/* `fidose` - process sector erase command */

void fidose()
	{
	unsigned char fc;
	int sc;
	long i,tct;
	PIROM *rp;
	PICONFIG *tcfg;

	if (!(r0 & FIA_ICS))
		{
		picmd((char)fid,FI_RR,1,FIR_SED,0,0,0,0);
		fp->fised = pxrsp[PIDT];
		if (fp->fiflags & FiBRF)
			{
			printf("\n  sector erase: SED=0x%02X",fp->fised);
			printf("\n  sector erase: setting SET (Sector Erase Timer)");
			}
		picmd((char)fid,FI_RW,2,FIW_CTL,(char)(fp->fictl|FIC_SET),0,0,0);
		tcfg = pxcfg;
		rp = &pxrom[0];
		fc = 0x0ff;
		pxcfg = &pxaltcfg;
		pxcfg->words = 1;
		pxcfg->uid[0] = 0;
		pifixcfg();
		rp->fstart = 0;
		filod();
		pxdlc = 0;
		for (sc=0; sc<8; sc++)
			{
			if (!((1<<sc)&fp->fised))
				continue;
			fp->fisec[sc]++;
			fp->figsc++;
			if ((1<<sc)&fp->fispd)
				{

				if (fp->fiflags & FiBRF)
					printf("\n  sector erase: sector %d is protected",sc);
				fp->fisecp[sc]++;
				continue;
				}
			if (fp->fiflags & FiBRF)
				printf("\n  sector erase: erasing %d - in progress",sc);
			fp->fibpc[sc] = 0;
			tct = pxrom[0].esize/8;
			pxxloc = sc * tct;
			while (tct && !pxerror)
				{
				if (tct > PIC_BS)
					pxxbc = PIC_BS;
				else
					pxxbc = tct;
				tct -= pxxbc;
				for (i=0; i<pxxbc; i++)
					{
					pxxbf[i] = fc;
					}
				piwrite();
				pxxloc += pxxbc;
				}

			picmd((char)fid,FI_RR,1,FIR_RR2,0,0,0,0);
			r[0] = pxrsp[PIDT];
			r[1] = pxrsp[PIDT+1];
			if (r[0]&FIA_ICS || r[1]&FIB_RRS)
				{
				fp->fiseca[sc]++;
				break;
				}
			if (!(r[0]&FIA_SUS))
				continue;
			if (fp->fiflags & FiBRF)
				printf("\n  sector erase: suspend erase seen");
			picmd((char)fid,FI_RW,2,FIW_CTL,(char)(fp->fictl|FIC_TARA),0,0,0);
			fiemu();
			fp->fisecs[sc]++;
			fp->fisuc++;
			if (fp->fiflags & FiBRF)
				printf("\n  sector erase: operation suspended");
			do	{
				picmd((char)fid,FI_RR,1,FIR_RR2,0,0,0,0);
				r[0] = pxrsp[PIDT];
				r[1] = pxrsp[PIDT+1];
				} while (r[0]&FIA_SUS && !(r[0]&FIA_ICS||r[1]&FIB_RRS));
			if (r[0]&FIA_ICS || r[1]&FIB_RRS)
				{
				fp->fiseca[sc]++;
				break;
				}
			if (fp->fiflags & FiBRF)
				printf("\n  sector erase: resume erase seen");
			picmd((char)fid,FI_RW,2,FIW_CTL,fp->fictl,0,0,0);
			filod();
			if (fp->fiflags & FiBRF)
				printf("\n  sector erase: operation resumed");
			fp->fisecr[sc]++;
			}
		pxcfg = tcfg;
		picmd((char)fid,FI_RW,2,FIW_CTL,fp->fictl,0,0,0);
		fiemu();
		fp->doclra++;
		}
	}

/* `fishows` - show info on a sector of Flash */

void fishows(char sn)
	{
	printf("\nSector %d erased %ld times and %ld bytes were programmed in it",
		(short)sn, fp->fisec[sn], fp->fibpc[sn]);
	}

/* `fishowc` - show info on the Flash chip */

void fishowc()
	{
	short i;
	char *ctype = "AM29F010";

	if (fp->fictl&FIC_F040)
		ctype = "AM29F040";
	printf("\n\nCHIP STATISTICS FOR %s:\n",ctype);
	printf("\n\t Chip Erase Count ->\t%ld",fp->ficec);
	printf("\n\t Bytes Programmed ->\t%ld",fp->figbp);
	printf("\n\t Sector Erase Count ->\t%ld",fp->figsc);
	printf("\n\t Erase Suspend Count ->\t%ld",fp->fisuc);
	printf("\n\t Illegal commands ->\t%ld",fp->fillcs);
	printf("\n\n\n Sector number\t0\t1\t2\t3\t4\t5\t6\t7");
	printf("\n              \t-\t-\t-\t-\t-\t-\t-\t-");
	printf("\n Protected?");
	for (i=0; i<FIC_NS; i++)
		{
		if (fp->fispd&(1<<i))
			printf("\tYES");
		else
			printf("\tNO");
		}
	printf("\n Erase Count");
	for (i=0; i<FIC_NS; i++)
		{
		printf("\t%ld",fp->fisec[i]);
		}
	printf("\n Suspend Erase");
	for (i=0; i<FIC_NS; i++)
		{
		printf("\t%ld",fp->fisecs[i]);
		}
	printf("\n Resume Erase");
	for (i=0; i<FIC_NS; i++)
		{
		printf("\t%ld",fp->fisecr[i]);
		}
	printf("\n Prot'd Erase");
	for (i=0; i<FIC_NS; i++)
		{
		printf("\t%ld",fp->fisecp[i]);
		}
	printf("\n Aborted Erase");
	for (i=0; i<FIC_NS; i++)
		{
		printf("\t%ld",fp->fiseca[i]);
		}

	printf("\n Bytes Pgm'd");
	for (i=0; i<FIC_NS; i++)
		{
		printf("\t%ld",fp->fibpc[i]);
		}
	printf("\n  err-ETL");
	for (i=0; i<FIC_NS; i++)
		{
		printf("\t%ld",fp->fibpct[i]);
		}
	printf("\n  err-Prot'd");
	for (i=0; i<FIC_NS; i++)
		{
		printf("\t%ld",fp->fibpcp[i]);
		}

	printf("\n TotBytesPgm'd");
	for (i=0; i<FIC_NS; i++)
		{
		printf("\t%ld",fp->fitbp[i]);
		}
	printf("\n\nEND OF CHIP STATISTICS");
	}

/* `fiemu` - set current flashice emulating */

void fiemu()
	{
	picmd((char)fid,PI_MO|CM_NORSP,1,(char)(pxmode1&~MO_LOAD),0,0,0,0);
	}

/* `filod` - set current flashice to load mode */

void filod()
	{
	picmd((char)fid,PI_MO|CM_NORSP,1,(char)(pxmode1|MO_LOAD),0,0,0,0);
	}

/* `fiinit` - initialize the globals */

void fiinit()
	{
	short i;

	fp->fispd = 0;
	fp->ficec = 0;
	fp->figbp = 0;
	fp->figsc = 0;
	fp->fisuc = 0;
	fp->fiset = 0;
	fp->fiopt = 0;
	fp->fisem = 0;
	fp->fipem = 0;
	fp->ficem = 0;
	fclog = -1;
	fp->fillcs = 0;
	fp->fiflags = 0;
	for (i=0; i<FIC_NS; i++)
		{
		fp->fisec[i] = 0;
		fp->fisecp[i] = 0;
		fp->fiseca[i] = 0;
		fp->fisecs[i] = 0;
		fp->fisecr[i] = 0;
		fp->fibpc[i] = 0;
		fp->fibpct[i] = 0;
		fp->fitbp[i] = 0;
		fp->fimap[i] = (char *)0;
		}
	fp->fictl = FIC_ICLR;
	fp->fimoe = MC_FIMO;
	fp->fiman = 0x01;
	fp->fidev = (char)0xA4;
	fp->fidv2 = 0;
	fp->doclra = 0;
	fp->etls = 0;
	fp->once = 0;
	}
