/*	PiTrace.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.
*/

#include <stdio.h>
#include <string.h>

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

void pi_kbd(void);
void pitraceit(void);
void pitrinit(long a);
void pitrtest(long test);
void pitrread(long a, long b, long c);
void pitrwrite(long a, long b, long c, long d);
void pitrsave(char *str, long here, long there);

void pixmdoit(void);
void pixminit(long a);
void pixmtest(long test);
void pixmread(long a, long b, long c, long d);
void pixmwrite(long a, long b, long c, long d, long e);
void pixmsave(char *str, long a, long b, long c);
void pitrstatus(void);

unsigned char tr_controla;
unsigned char tr_controlb;
unsigned char tr_controlc;
unsigned char xm_controla;
unsigned char xm_controlb;
unsigned char xm_controlc;
unsigned char pxtrconfig;

long pxtrstart;
long pxtrstop;
long pxtrcounta;
long pxtrcountb;
long pxmaxt;
long pxmaxm;
long pxmaxp;
char pxxmap0;
char pxxmap1;
char pxxmap2;
char pxxmap3;
long bigone = 0;
#define	SHOWORD	0x00000001
#define	SHOWALL	0x00000002
#define	SHOWBIG	0x00000004
#define	SHOWBUG	0x00000008

FILE *pxtrfile;
long pxtrflags = 0;
#define	TRINIT	0x00000001
#define	TRWORD	0x00000002
#define	TRSNEW	0x00000004
#define	TRSIZE	0x00000008
#define	TRSAVE	0x08000000

long curtp=0;


#define FROM	0
#define TO		1
#define FLAG	2
#define OVER	3
#define SKIP	4
#define TRASE	5
#define CSIZE	6
#define DELTA	7
#define RCLK	8
#define XCLK	9
#define	BRK0	10
#define	BRK1	11
#define CODEC	12
#define FINEG	13
#define MAP0	14
#define MAP1	15
#define MAP2	16
#define MAP3	17

#define	TC512	0x10
#define	MEMR2	0x20
#define	BIGCC	0x20

union
{
	long a;
	short b[2];
	char c[4];
} xy;

char trinity[] = 
{
	MG_CONTROL,MGD_JTAG,
	JT_CONTROL,0,
	MG_CONTROL,MGD_XMAP,
	XM_CONTROLA,0,
	XM_CONTROLB,0,
	XM_CONTROLC,0,
	MG_CONTROL,MGD_TRACE,
	TR_CONTROLA,0,
	TR_CONTROLB,0,
	TR_CONTROLC,0,
	MG_CONTROL,MGD_SELF
};

PICONFIG *cx;

/* CODE TRACE INTERFACE */
/* `pitraceit` - take the tarace per user args */

void pitraceit()
{
	long address, value, pointer;

	if (!(pxtrflags&TRINIT))
		pitrinit(0);
	if (pxerror)
		return;

	picmd(0,TR_RX|CM_NORSP,2,MG_CONTROL,MGD_AI,0,0,0);
	picmd(0,TR_RX|CM_NORSP,2,A2_CONTROL,0,0,0,0);
 	tr_controla = TRA_START;
	if (pxtrconfig & TC512)
		tr_controla |= TRA_SIZE;
	tr_controlb = 0;
	tr_controlc = 0;

	pxtrstart = 0;
	pxtrstop = 0;
	pxtrcounta = 0;
	pxtrcountb = 0;

	if ((ps_trace[FROM] != -1) && (ps_trace[TO] != -1))
		tr_controlb = TRB_STRSTP;
	else
	{
		if (ps_trace[FROM] != -1)
			tr_controlb = TRB_START;
		else
		{
			if (ps_trace[TO] != -1)
				tr_controlb = TRB_STOP;
			else
				tr_controlb = TRB_ALL;
		}
	}

	if (ps_trace[FLAG] != -2)
		tr_controlb |= TRB_RANGE;

	if (ps_trace[OVER] == -2)
		tr_controlb |= TRB_OVER;

	if (ps_trace[SKIP] != -1)
	{
		pxtrcounta = ps_trace[SKIP];
		tr_controlb |= TRB_COUNTA;
	}
	
	if (ps_trace[TRASE] != -1)
	{
		pxtrcountb = ps_trace[TRASE];
		tr_controlb |= TRB_COUNTB;
	}

	if (ps_trace[CSIZE] == 32)
	{
		tr_controla |= TRA_CSIZE;
		pxtrflags |= TRSIZE;
	}
	else
		pxtrflags &= ~TRSIZE;

	switch(ps_trace[DELTA])
	{
	case -2:
		tr_controla |= TRA_GENWRT;
		break;
	case 1:
		tr_controlc |= TRC_DELAY0;
		break;
	case 2:
		tr_controlc |= TRC_DELAY1;
		break;
	case 3:
		tr_controlc |= TRC_DELAY0|TRC_DELAY1;
		break;
	default:
		break;
	}

	if (ps_trace[RCLK] != -2)
		tr_controlc |= TRC_USETCLK;
	if (ps_trace[XCLK] == -2)
		tr_controlc |= TRC_USEXCLK;

	if (ps_trace[FROM] != -1)
		pxtrstart = ps_trace[FROM];
	if (ps_trace[TO] != -1)
		pxtrstop = ps_trace[TO];

	if (ps_trace[BRK0] != -1)
	{
		pxtrstart = ps_trace[BRK0];
		tr_controlc |= TRC_BREAKS;
		if (tr_controlb&TRB_COUNTA)
		{
			tr_controlb &= ~TRB_COUNTA;
			tr_controlc |= TRC_BREAKCA;
		}
	}
	if (ps_trace[BRK1] != -1)
	{
		pxtrstop = ps_trace[BRK1];
		tr_controlc |= TRC_BREAKP;
		if (tr_controlb&TRB_COUNTB)
		{
			tr_controlb &= ~TRB_COUNTB;
			tr_controlc |= TRC_BREAKCB;
		}
	}

	cx = pxcfg;
	if (bigone&SHOWORD)
	{
		pxtrstart = pxtrstart >> (cx->words-1);
		pxtrstop = pxtrstop >> (cx->words-1);
	}

	picmd(0,TR_RX|CM_NORSP,2,MG_CONTROL,MGD_TRACE,0,0,0);
	picmd(0,TR_RX|CM_NORSP,2,TR_CONTROLA,0,0,0,0);
	picmd(0,TR_RX|CM_NORSP,2,TR_CONTROLB,0,0,0,0);
	picmd(0,TR_RX|CM_NORSP,2,TR_CONTROLC,0,0,0,0);
	picmd(0,TR_RX|CM_NORSP,2,TR_CONTROLA,TRA_REGBANK,0,0,0);
	address = pxtrstart;
	if (!(bigone&SHOWALL))
		address |= pxrom[0].amask;
	if (bigone&SHOWBUG)
		printf("\nStartAddress=0x%08X", address);
	picmd(0,TR_RX|CM_NORSP,2,TR_STARTAX,(char)(address>>24),0,0,0);
	picmd(0,TR_RX|CM_NORSP,2,TR_STARTAH,(char)(address>>16),0,0,0);
	picmd(0,TR_RX|CM_NORSP,2,TR_STARTAM,(char)(address>>8),0,0,0);
	picmd(0,TR_RX|CM_NORSP,2,TR_STARTAL,(char)address,0,0,0);
	address = pxtrstop;
	if (!(bigone&SHOWALL))
		address |= pxrom[0].amask;
	if (bigone&SHOWBUG)
		printf("  StopAddress=0x%08X", address); 
	picmd(0,TR_RX|CM_NORSP,2,TR_STOPAX,(char)(address>>24),0,0,0);
	picmd(0,TR_RX|CM_NORSP,2,TR_STOPAH,(char)(address>>16),0,0,0);
	picmd(0,TR_RX|CM_NORSP,2,TR_STOPAM,(char)(address>>8),0,0,0);
	picmd(0,TR_RX|CM_NORSP,2,TR_STOPAL,(char)address,0,0,0);
   	value = -pxtrcounta;
	if (bigone&SHOWBUG)
		printf("\nSkipCounter=0x%04X (%d)", value, value); 
	picmd(0,TR_RX|CM_NORSP,2,TR_COUNTAH,(char)(value>>8),0,0,0);
	picmd(0,TR_RX|CM_NORSP,2,TR_COUNTAL,(char)value,0,0,0);
	value = -pxtrcountb;
	if (bigone&SHOWBUG)
		printf("\nTraceCounter=0x%04X (%d)", value, value); 
	picmd(0,TR_RX|CM_NORSP,2,TR_COUNTBH,(char)(value>>8),0,0,0);
	picmd(0,TR_RX|CM_NORSP,2,TR_COUNTBL,(char)value,0,0,0);
	picmd(0,TR_RX|CM_NORSP,2,TR_CONTROLA,0,0,0,0);
	pointer = 0;
	picmd(0,TR_RX|CM_NORSP,2,TR_ADDRESSX,(char)(pointer>>16),0,0,0);
	picmd(0,TR_RX|CM_NORSP,2,TR_ADDRESSH,(char)(pointer>>8),0,0,0);
	picmd(0,TR_RX|CM_NORSP,2,TR_ADDRESSL,(char)pointer,0,0,0);

	picmd(0,TR_RX|CM_NORSP,2,TR_CONTROLC,tr_controlc,0,0,0);
	picmd(0,TR_RX|CM_NORSP,2,TR_CONTROLB,tr_controlb,0,0,0);
   	picmd(0,TR_RX|CM_NORSP,2,TR_CONTROLA,tr_controla,0,0,0);
	pxtrflags |= TRSNEW;
}


/* `pitrtest` - test the trace memory */

void pitrtest(long test)
{
	if (!(pxtrflags&TRINIT))
		pitrinit(0);
	if (pxerror)
		return;

	printf("\n\nDownloading Test Pattern\n");
	pitrwrite(0, pxmaxt, 0, 1);
	printf("\n\nReading and Comparing Data\n");
	pitrread(0, pxmaxt,1);
	printf("\n\nTest Complete, Tested %ld locations", pxmaxt+1);
	printf("\n if no errors were reported then memory is good");
}

/* `pitrread` - read trace data */

void pitrread(long start, long end, long flag)
{
	unsigned long spat = 0x5ACDAD95;
	unsigned long pinc = 0x82102131;
	unsigned long *lp;
	char *tstr;
	char buf[32];
	union
	{
		char c[4];
		long d;
	} trace;

	long i,j,printit=0,printed=0,once=0;


	if (!(pxtrflags&TRINIT))
		pitrinit(0);
	if (pxerror)
		return;

	tstr = &buf[0];

	if (end == -1)
		end = pxmaxt;
	if (end < start)
		end = start + end;

	picmd(0,TR_RX|CM_NORSP,2,MG_CONTROL,MGD_AI,0,0,0);
	picmd(0,TR_RX|CM_NORSP,2,A2_CONTROL,0,0,0,0);
	picmd(0,TR_RX|CM_NORSP,2,MG_CONTROL,MGD_TRACE,0,0,0);

	if (!flag)
	{
		pitrstatus();
		picmd(0,TR_RX|CM_NORSP,2,TR_CONTROLB,0,0,0,0);
		picmd(0,TR_RX|CM_TREAD,2,TR_ADDRESSX,4,0,0,0);
		printf("\nCurrentTracePointer\t= %02X%02X%02X",pxrsp[PIDT]&0xff,pxrsp[PIDT+2]&0xff,
				pxrsp[PIDT+3]&0xff);
		if (pxtrflags&TRSNEW)
			curtp = (((pxrsp[PIDT]&0xff)<<16)|((pxrsp[PIDT+2]&0xff)<<8)|(pxrsp[PIDT+3]&0xff));
	}

	picmd(0,TR_RX|CM_NORSP,2,TR_CONTROLA,0,0,0,0);
	picmd(0,TR_RX|CM_NORSP,2,TR_CONTROLB,0,0,0,0);
	picmd(0,TR_RX|CM_NORSP,2,TR_CONTROLA,TRA_REGBANK,0,0,0);
	picmd(0,TR_RX|CM_NORSP,2,TR_COUNTBH,0,0,0,0);
	picmd(0,TR_RX|CM_NORSP,2,TR_COUNTBL,0,0,0,0);
	picmd(0,TR_RX|CM_NORSP,2,TR_COUNTAH,0,0,0,0);
	picmd(0,TR_RX|CM_NORSP,2,TR_COUNTAL,0,0,0,0);
	picmd(0,TR_RX|CM_NORSP,2,TR_CONTROLA,0,0,0,0);
	picmd(0,TR_RX|CM_NORSP,2,TR_ADDRESSX,(char)(start>>16),0,0,0);
	picmd(0,TR_RX|CM_NORSP,2,TR_ADDRESSH,(char)(start>>8),0,0,0);
	picmd(0,TR_RX|CM_NORSP,2,TR_ADDRESSL,(char)start,0,0,0);
	picmd(0,TR_RX|CM_TREAD,2,TR_ADDRESSX,4,0,0,0);
	if (!flag)
		printf("\nTracePointerIs\t= %02X%02X%02X",pxrsp[PIDT]&0xff,pxrsp[PIDT+2]&0xff,
			pxrsp[PIDT+3]&0xff);
	picmd(0,TR_RX|CM_NORSP,2,TR_CONTROLA,TRA_START|TRA_MINE,0,0,0);

	if (!flag)
	{
		start &= ~7;
		end = ((end+7)&~7);
	}
	for (i=0; i<(end-start); i+=64)
	{
		pi_kbd();
		if (pxerror) break;
		picmd(0,TR_RX|CM_TRDATA|CM_TREAD,1,0,0,0,0,0);
		if (flag)
		{
			lp =(unsigned long *) &pxrsp[PIDT];
			for (j=0; j<64; j++)
			{
				if (spat != *lp)
				{
					printf("\n error at %06X - wanted %08X - got %08X",i+(j*4),spat, *lp);
				}
				spat += pinc;
				lp++;
			}
			if (!(i%4096)) printf(".");
		}
		else
		{
			printit = 0;
			for (j=0; j<256; j++)
				if (pxrsp[PIDT+j])
				{
					printit++;
					break;
				}
			cx = pxcfg;		
			for (j=0; j<256 && j<(end-start+1)*4; j+=4)
			{
				trace.c[0] = pxrsp[PIDT+j];
				trace.c[1] = pxrsp[PIDT+1+j];
				trace.c[2] = pxrsp[PIDT+2+j];
				trace.c[3] = pxrsp[PIDT+3+j];
				if (!(bigone&SHOWALL))
				{
					trace.d &= ~(pxrom[0].amask);
					trace.d &= 0xFFFFFF;
				}
				if (bigone&SHOWORD)
					trace.d = trace.d << (cx->words-1);
				if (pxtrflags&TRSAVE)
				{
					if (bigone&SHOWALL)
					{
						if (j%32)
							sprintf(tstr, " %08X",trace.d);
						else
							sprintf(tstr, "\n%05X: %08X",start+i+j/4,trace.d);
					}
					else
					{
						if (j%32)
							sprintf(tstr, " %06X",trace.d);
						else
							sprintf(tstr, "\n%05X: %06X",start+i+j/4,trace.d);
					}
					fwrite(tstr, 1, strlen(tstr), pxtrfile);
					if (!(i%4096)&&!j)
						printf(".");
				}
				else
				{
					if (printit || !once)
					{
						printed++;
						if (!(bigone&SHOWALL))
						{
						if (j%32)
							printf(" %06X",trace.d);
						else
							printf("\n%05X: %06X",start+i+j/4,trace.d);
						}
						else
						{
						if (j%32)
							printf(" %08X",trace.d);
						else
							printf("\n%05X: %08X",start+i+j/4,trace.d);
						}
					}
					else
					{
					if (!(i%4096)&&!j)
						printf(".");
					}
				}
			}
		if (printed)
			printf("\n.");
		printed = 0;
		once++;
		}
	}
	picmd(0,TR_RX|CM_NORSP,2,TR_CONTROLA,0,0,0,0);
	picmd(0,TR_RX|CM_TREAD,2,TR_ADDRESSX,4,0,0,0);
	if (!flag)
		printf("\nTracePointerWas\t= %02X%02X%02X",pxrsp[PIDT]&0xff,pxrsp[PIDT+2]&0xff,
			pxrsp[PIDT+3]&0xff);
}

/* `pitrwrite` - fill or write trace memory */

void pitrwrite(long start, long stop, long data, long flag)
{
	long i,j;
	unsigned long spat = 0x5ACDAD95;
	unsigned long pinc = 0x82102131;
	unsigned long *lp;

	if (!(pxtrflags&TRINIT))
		pitrinit(0);
	if (pxerror)
		return;

	if (stop == -1)
		stop = pxmaxt;
	if (stop < start)
		stop = start + stop;

	picmd(0,TR_RX|CM_NORSP,2,MG_CONTROL,MGD_AI,0,0,0);
	picmd(0,TR_RX|CM_NORSP,2,A2_CONTROL,0,0,0,0);

	picmd(0,TR_RX|CM_NORSP,2,MG_CONTROL,MGD_TRACE,0,0,0);
	picmd(0,TR_RX|CM_NORSP,2,TR_CONTROLA,0,0,0,0);
	picmd(0,TR_RX|CM_NORSP,2,TR_CONTROLB,0,0,0,0);

	if (!flag)
	{
		picmd(0,TR_RX|CM_TREAD,2,TR_ADDRESSX,4,0,0,0);
		printf("\nTracePointerWas\t= %02X%02X%02X",pxrsp[PIDT]&0xff,pxrsp[PIDT+2]&0xff,
				pxrsp[PIDT+3]&0xff);
	}
	picmd(0,TR_RX|CM_NORSP,2,TR_CONTROLA,TRA_REGBANK,0,0,0);
	picmd(0,TR_RX|CM_NORSP,2,TR_COUNTBH,0,0,0,0);
	picmd(0,TR_RX|CM_NORSP,2,TR_COUNTBL,0,0,0,0);
	picmd(0,TR_RX|CM_NORSP,2,TR_COUNTAH,0,0,0,0);
	picmd(0,TR_RX|CM_NORSP,2,TR_COUNTAL,0,0,0,0);
	picmd(0,TR_RX|CM_NORSP,2,TR_CONTROLA,0,0,0,0);
	picmd(0,TR_RX|CM_NORSP,2,TR_ADDRESSX,(char)(start>>16),0,0,0);
	picmd(0,TR_RX|CM_NORSP,2,TR_ADDRESSH,(char)(start>>8),0,0,0);
	picmd(0,TR_RX|CM_NORSP,2,TR_ADDRESSL,(char)start,0,0,0);
	picmd(0,TR_RX|CM_TREAD,2,TR_ADDRESSX,4,0,0,0);
	if (!flag)
		printf("\nTracePointerIs\t= 0x%02X%02X%02X",pxrsp[PIDT]&0xff,pxrsp[PIDT+2]&0xff,
			pxrsp[PIDT+3]&0xff);

	picmd(0,TR_RX|CM_NORSP,2,TR_CONTROLA,TRA_START|TRA_MINE|TRA_WRITE,0,0,0);

	pxcmd[PIID] = 0;
	pxcmd[PICM] = TR_RX|CM_NORSP|CM_TRDATA;

	if (stop-start+1 < 64)
		pxcmdl = (stop-start+1)*4+3;
	else
		pxcmdl = 259;
	pxcmd[PICT] = pxcmdl-3;

	if (flag)
		data = spat;

	for (i=0; i<(stop-start+1); i+=64)
	{
		pi_kbd();
		if (pxerror) break;

		lp =(unsigned long *) &pxcmd[PIDT];

		for (j=0; j<64; j++)
		{
			*lp = data;
			lp++;
			if (flag)
				data += pinc;
		}
		pi_cmd();
		if (!(i%4096))
			printf(".");
	}  
	picmd(0,TR_RX|CM_NORSP,2,TR_CONTROLA,0,0,0,0);
	picmd(0,TR_RX|CM_TREAD,2,TR_ADDRESSX,4,0,0,0);
	if (!flag)
		printf("\nTracePointerWas\t= %02X%02X%02X",pxrsp[PIDT]&0xff,pxrsp[PIDT+2]&0xff,
			pxrsp[PIDT+3]&0xff);
}

/* `pitrsave` - save the stuff to a file */

void pitrsave(char *file, long start, long stop)
{
	if (!(pxtrflags&TRINIT))
		pitrinit(0);
	if (pxerror)
		return;

	printf("\nOpening file %s for saving trace data",file);

	if ((pxtrfile=fopen(file,"w")) == NULL)
		perror("Open failed:");

	if (stop == -1)
		stop = pxmaxt;

	pxtrflags |= TRSAVE;
	pitrread(start,stop,0);
	pxtrflags &= ~TRSAVE;
	fclose(pxtrfile);
	printf("\nDone");
}

/* `pitrfind` - find stuff in trace */

void pitrfind(long find, long start, long stop)
{
	long i,j,printit;
	union
	{
		char c[4];
		long d;
	} trace;

	if (!(pxtrflags&TRINIT))
		pitrinit(0);
	if (pxerror)
		return;

	if (stop == -1)
		stop = pxmaxt;
	if (stop < start)
		stop = start + stop;

	picmd(0,TR_RX|CM_NORSP,2,MG_CONTROL,MGD_AI,0,0,0);
	picmd(0,TR_RX|CM_NORSP,2,A2_CONTROL,0,0,0,0);


	picmd(0,TR_RX|CM_NORSP,2,MG_CONTROL,MGD_TRACE,0,0,0);
	picmd(0,TR_RX|CM_NORSP,2,TR_CONTROLA,0,0,0,0);
	picmd(0,TR_RX|CM_NORSP,2,TR_CONTROLB,0,0,0,0);
	picmd(0,TR_RX|CM_NORSP,2,TR_CONTROLA,TRA_REGBANK,0,0,0);
	picmd(0,TR_RX|CM_NORSP,2,TR_COUNTBH,0,0,0,0);
	picmd(0,TR_RX|CM_NORSP,2,TR_COUNTBL,0,0,0,0);
	picmd(0,TR_RX|CM_NORSP,2,TR_COUNTAH,0,0,0,0);
	picmd(0,TR_RX|CM_NORSP,2,TR_COUNTAL,0,0,0,0);
	picmd(0,TR_RX|CM_NORSP,2,TR_CONTROLA,0,0,0,0);
	picmd(0,TR_RX|CM_NORSP,2,TR_ADDRESSX,(char)(start>>16),0,0,0);
	picmd(0,TR_RX|CM_NORSP,2,TR_ADDRESSH,(char)(start>>8),0,0,0);
	picmd(0,TR_RX|CM_NORSP,2,TR_ADDRESSL,(char)start,0,0,0);
	picmd(0,TR_RX|CM_TREAD,2,TR_ADDRESSX,4,0,0,0);
	picmd(0,TR_RX|CM_NORSP,2,TR_CONTROLA,TRA_START|TRA_MINE,0,0,0);

	printf("\n");
	for (i=0; i<(stop-start); i+=64)
	{
		pi_kbd();
		if (pxerror) break;
		picmd(0,TR_RX|CM_TRDATA|CM_TREAD,1,0,0,0,0,0);
		printit = 0;
		for (j=0; j<256; j++)
		{
			trace.c[0] = pxrsp[PIDT+j];
			trace.c[1] = pxrsp[PIDT+1+j];
			trace.c[2] = pxrsp[PIDT+2+j];
			trace.c[3] = pxrsp[PIDT+3+j];
			if (!(bigone&SHOWALL))
			{
				trace.d &= ~(pxrom[0].amask);
				trace.d &= 0xFFFFFF;
			}
			if (bigone&SHOWORD)
				trace.d = trace.d << (cx->words-1);
			if (find == trace.d)
			{
				printf("\n1st find->\t\t%05X: %06X",start+i+j/4,trace.d);
				printit++;
				break;
			}
		}
		for (j=0; j<256 && j<(stop-start+1)*4; j+=4)
		{
			trace.c[0] = pxrsp[PIDT+j];
			trace.c[1] = pxrsp[PIDT+1+j];
			trace.c[2] = pxrsp[PIDT+2+j];
			trace.c[3] = pxrsp[PIDT+3+j];
			if (!(bigone&SHOWALL))
			{
				trace.d &= ~(pxrom[0].amask);
				trace.d &= 0xFFFFFF;
			}
			if (bigone&SHOWORD)
				trace.d = trace.d << (cx->words-1);

			if (printit)
			{
				if (!(bigone&SHOWALL))
				{
				if (j%32)
					printf(" %06X",trace.d);
				else
					printf("\n%05X: %06X",start+i+j/4,trace.d);
				}
				else
				{
				if (j%32)
					printf(" %08X",trace.d);
				else
					printf("\n%05X: %08X",start+i+j/4,trace.d);
				}
			}
		}
		if (printit)
			printf("\n");
		if (!(i%4096))
			printf(".");
	}
}


/* CODE COVERAGE INTERFACE */
/* `pixmdoit` - take the tarace per user args */

void pixmdoit()
{
	long value, pointer;

	if (!(pxtrflags&TRINIT))
		pitrinit(0);
	if (pxerror)
		return;


	xm_controla = XMA_START;
	if (pxtrconfig&TC512 || pxtrconfig&BIGCC)
		xm_controla |= XMA_SIZE;
	xm_controlb = XMB_ALWAYS;
	xm_controlc = XMC_COVER;

	if (ps_trace[MAP0] != -1)
	{
		pxxmap0 = (char)ps_trace[MAP0];
		xm_controlb = (char)(pxxmap0>>8);
		xm_controlc |= XMC_MAPENB0;
	}
	if (ps_trace[MAP1] != -1)
	{
		pxxmap1 = (char)ps_trace[MAP1];
		xm_controlb = pxxmap1>>8;
		xm_controlc |= XMC_MAPENB1;
	}
	if (ps_trace[MAP2] != -1)
	{
		if (pxtrconfig&TC512 && pxtrconfig&MEMR2)
		{
			pxerror = PGE_BAA;
			return;
		}
		else
		{
		pxxmap2 = (char)ps_trace[MAP2];
		xm_controlb = pxxmap2>>8;
		xm_controlc |= XMC_MAPENB2;
		}
	}
	if (ps_trace[MAP3] != -1)
	{
		if (pxtrconfig&TC512 && pxtrconfig&MEMR2)
		{
			pxerror = PGE_BAA;
			return;
		}
		else
		{
		pxxmap3 = (char)ps_trace[MAP3];
		xm_controlb = pxxmap3>>8;
		xm_controlc |= XMC_MAPENB3;
		}
	}
	switch(ps_trace[DELTA])
	{
	case -2:
		xm_controla |= XMA_GENWRT;
		break;
	case 1:
		xm_controla |= XMA_DELAY0;
		break;
	case 2:
		xm_controla |= XMA_DELAY1;
		break;
	case 3:
		xm_controla |= XMA_DELAY0|XMA_DELAY1;
		break;
	default:
		break;
	}

	if (ps_trace[RCLK] != 0)
		xm_controlc |= XMC_USETCLK;
	if (ps_trace[XCLK] == -2)
		xm_controlc |= XMC_USEXCLK;

	picmd(0,TR_RX|CM_NORSP,2,MG_CONTROL,MGD_XMAP,0,0,0);
	picmd(0,TR_RX|CM_NORSP,2,XM_CONTROLA,0,0,0,0);
	picmd(0,TR_RX|CM_NORSP,2,XM_CONTROLB,0,0,0,0);
	picmd(0,TR_RX|CM_NORSP,2,XM_CONTROLC,0,0,0,0);
   	value = 0;
	picmd(0,TR_RX|CM_NORSP,2,XM_COUNTAH,(char)(value>>8),0,0,0);
	picmd(0,TR_RX|CM_NORSP,2,XM_COUNTAL,(char)value,0,0,0);
	value = 0;
	picmd(0,TR_RX|CM_NORSP,2,XM_COUNTBH,(char)(value>>8),0,0,0);
	picmd(0,TR_RX|CM_NORSP,2,XM_COUNTBL,(char)value,0,0,0);
	pointer = 0;
	picmd(0,TR_RX|CM_NORSP,2,XM_ADDRESSX,(char)(pointer>>16),0,0,0);
	picmd(0,TR_RX|CM_NORSP,2,XM_ADDRESSH,(char)(pointer>>8),0,0,0);
	picmd(0,TR_RX|CM_NORSP,2,XM_ADDRESSL,(char)pointer,0,0,0);

	if (xm_controlc & XMC_MAPENB0)
		picmd(0,TR_RX|CM_NORSP,2,XM_MAPENB0, pxxmap0,0,0,0);
	if (xm_controlc & XMC_MAPENB1)
		picmd(0,TR_RX|CM_NORSP,2,XM_MAPENB1, pxxmap1,0,0,0);
	if (xm_controlc & XMC_MAPENB2)
		picmd(0,TR_RX|CM_NORSP,2,XM_MAPENB2, pxxmap2,0,0,0);
	if (xm_controlc & XMC_MAPENB3)
		picmd(0,TR_RX|CM_NORSP,2,XM_MAPENB3, pxxmap3,0,0,0);

	picmd(0,TR_RX|CM_NORSP,2,XM_CONTROLC,xm_controlc,0,0,0);
	picmd(0,TR_RX|CM_NORSP,2,XM_CONTROLB,xm_controlb,0,0,0);
   	picmd(0,TR_RX|CM_NORSP,2,XM_CONTROLA,xm_controla,0,0,0);
}


/* `pixmtest` - test the map memory */

void pixmtest(long test)
{
	if (!(pxtrflags&TRINIT))
		pitrinit(0);
	if (pxerror)
		return;

	printf("\n\nDownloading Test Pattern");
	pixmwrite(0, pxmaxm, 0, 1, -1);
	printf("\n\nReading and Comparing Data\n.");
	pixmread(0, pxmaxm,1, -1);
	printf("\n\nTest Complete, Tested %ld locations", pxmaxm+1);
	printf("\n if no errors were reported then memory is good");
}

/* `pixmread` - read XMAP data */

void pixmread(long start, long end, long flag, long map)
{
	long i,j,a,printit,printed,once;
	unsigned long spat = 0x5ACDAD95;
	unsigned long pinc = 0x82102131;
	unsigned long *lp;
	char *tstr;
	char buf[32];

	if (!(pxtrflags&TRINIT))
		pitrinit(0);
	if (pxerror)
		return;

	if (end == -1)
		end = pxmaxm;
	if (end < start)
		end = start + end;
	if (map >= 0)
	{
		start = pxmaxp * map;
		end = start + pxmaxp - 1;
	}

	tstr = &buf[0];
	picmd(0,TR_RX|CM_NORSP,2,MG_CONTROL,MGD_XMAP,0,0,0);
	picmd(0,TR_RX|CM_NORSP,2,XM_CONTROLA,0,0,0,0);
	picmd(0,TR_RX|CM_NORSP,2,XM_CONTROLB,0,0,0,0);
	picmd(0,TR_RX|CM_NORSP,2,XM_CONTROLC,0,0,0,0);
	picmd(0,TR_RX|CM_NORSP,2,XM_ADDRESSX,(char)(start>>16),0,0,0);
	picmd(0,TR_RX|CM_NORSP,2,XM_ADDRESSH,(char)(start>>8),0,0,0);
	picmd(0,TR_RX|CM_NORSP,2,XM_ADDRESSL,(char)start,0,0,0);
	picmd(0,TR_RX|CM_NORSP,2,XM_CONTROLA,XMA_MINE,0,0,0);
	if (pxtrconfig&TC512 || pxtrconfig&BIGCC)
		picmd(0,TR_RX|CM_NORSP,2,XM_CONTROLA,XMA_START|XMA_MINE|XMA_SIZE,0,0,0);
	else
		picmd(0,TR_RX|CM_NORSP,2,XM_CONTROLA,XMA_START|XMA_MINE,0,0,0);
	printit = printed = once = 0;
	if (bigone&SHOWBIG)
	{
		start &= ~15;
		end = (end+15)&~15;
	}
	else
	{
		start &= ~31;
		end = (end+31)&~31;
	}
	for (i=0; i<(end-start); i+=256)
	{
		pi_kbd();
		if (pxerror) break;
		printit = 0;
		picmd(0,(char)(TR_RX|CM_TRXMAP|CM_TREAD),1,0,0,0,0,0);
		if (flag)
		{
			lp =(unsigned long *) &pxrsp[PIDT];
			for (j=0; j<64; j++)
			{
				if (spat != *lp)
				{
					printf("\n error at %06X - wanted %08X - got %08X",i+(j*4),spat, *lp);
				}
				spat += pinc;
				lp++;
			}
			if (!(i%8192)) printf(".");
		}
		else
		{
			if (pxtrflags&TRSAVE)
			{
				for (j=0; j<256; j++)
				{
					if (bigone&SHOWBIG)
					{
						if (j%16)
							if (j%8)
								sprintf(tstr," %02X",pxrsp[PIDT+j]&0xff);
							else
								sprintf(tstr,"  %02X",pxrsp[PIDT+j]&0xff);
						else
							sprintf(tstr,"\n%06lX: %02X%",start+i+j,pxrsp[PIDT+j]&0xff);
					}
					else
					{
						if (pxrsp[PIDT+j])
							a = 1;
						else
							a = 0;
						if (j%32)
							if (j%16)
								sprintf(tstr," %01X",a);
							else
								sprintf(tstr,"  %01X",a);
						else
							sprintf(tstr,"\n%06lX: %01X%",start+i+j,a);
					}
				fwrite(tstr, 1, strlen(tstr), pxtrfile);
				}
			if (!(i%8192))
				printf(".");
			}
			else
			{
				for (j=0; j<256; j++)
				{
					if (pxrsp[PIDT+j])
					{
						printit++;
						break;
					}
				}
				if (printit || !once)
				{
					printed++;
					once++;
					for (j=0; j<256 && j<(end-start+1); j++)
					{
						if (bigone&SHOWBIG)
						{
							if (j%16)
								if (j%8)
									printf(" %02X",pxrsp[PIDT+j]&0xff);
								else
									printf("  %02X",pxrsp[PIDT+j]&0xff);
							else
								printf("\n%06lX: %02X%",start+i+j,pxrsp[PIDT+j]&0xff);
						}
						else
						{
							if (pxrsp[PIDT+j])
								a = 1;
							else
								a = 0;
							if (j%32)
								if (j%16)
									printf(" %01X",a);
								else
									printf("  %01X",a);
							else
								printf("\n%06lX: %01X%",start+i+j,a);
						}
					}
				}
				else
				{
					if (printed)
						printf("\n.");
					else
						if (!(i%8192)) printf(".");
					printed = 0;
				}
			}
		}
	}
	picmd(0,TR_RX|CM_NORSP,2,XM_CONTROLA,0,0,0,0);
}

/* `pimxwrite` - fill or write XMAP memory */

void pixmwrite(long start, long stop, long data, long flag, long map)
{
	long i,k;
	unsigned long spat = 0x5ACDAD95;
	unsigned long pinc = 0x82102131;
	unsigned long *lp;

	if (!(pxtrflags&TRINIT))
		pitrinit(0);
	if (pxerror)
		return;

	if (stop == -1)
		stop = pxmaxm;

	if (stop < start)
		stop = start + stop;

	if (map >= 0)
	{
		start = pxmaxp * map;
		stop = start + pxmaxp - 1;
	}


	picmd(0,TR_RX|CM_NORSP,2,MG_CONTROL,MGD_XMAP,0,0,0);
	picmd(0,TR_RX|CM_NORSP,2,XM_CONTROLA,0,0,0,0);
	picmd(0,TR_RX|CM_NORSP,2,XM_CONTROLB,0,0,0,0);
	picmd(0,TR_RX|CM_NORSP,2,XM_CONTROLC,0,0,0,0);
	picmd(0,TR_RX|CM_NORSP,2,XM_ADDRESSX,(char)(start>>16),0,0,0);
	picmd(0,TR_RX|CM_NORSP,2,XM_ADDRESSH,(char)(start>>8),0,0,0);
	picmd(0,TR_RX|CM_NORSP,2,XM_ADDRESSL,(char)start,0,0,0);
	picmd(0,TR_RX|CM_NORSP,2,XM_CONTROLA,XMA_MINE|XMA_WRITE,0,0,0);
	if (pxtrconfig&TC512 || pxtrconfig&BIGCC)
		picmd(0,TR_RX|CM_NORSP,2,XM_CONTROLA,XMA_START|XMA_MINE|XMA_WRITE|XMA_SIZE,0,0,0);
	else
		picmd(0,TR_RX|CM_NORSP,2,XM_CONTROLA,XMA_START|XMA_MINE|XMA_WRITE,0,0,0);
	for (i=0; i<259; i++)
		pxcmd[i] = (char)data;
	pxcmd[PIID] = 0;
	pxcmd[PICM] = (char)(TR_RX|CM_NORSP|CM_TRXMAP);
	if (stop-start+1 < 256)
		pxcmdl = stop-start+4;
	else
		pxcmdl = 259;
	pxcmd[PICT] = pxcmdl-3;
	printf("\n.");
	for (i=0; i<(stop-start+1); i+=256)
	{
		pi_kbd();
		if (pxerror) break;
		if (flag)
		{
			lp =(unsigned long *) &pxcmd[PIDT];
			for (k=0; k<64; k++)
			{
				*lp = spat;
				spat += pinc;
				lp++;
			}
		}
		pi_cmd();
		if (!(i%8192)) printf(".");
	}  
	picmd(0,TR_RX|CM_NORSP,2,XM_CONTROLA,0,0,0,0);
}

/* `pixmsave` - save the stuff to a file */

void pixmsave(char *file, long start, long stop, long map)
{
	if (!(pxtrflags&TRINIT))
		pitrinit(0);
	if (pxerror)
		return;

	if (stop == -1)
		stop = pxmaxm;

	if (map >= 0)
	{
		start = pxmaxp * map;
		stop = start + pxmaxp - 1;
	}


	printf("\nOpening file %s for saving code coverage data\n",file);

	if ((pxtrfile=fopen(file,"w")) == NULL)
		perror("Open failed:");

	pxtrflags |= TRSAVE;
	pixmread(start,stop,0,-1);
	pxtrflags &= ~TRSAVE;
	fclose(pxtrfile);
	printf("\nDone");
}

 /* `pitrinit` - initialize the trace board */

void pitrinit(long control)
{
	register char *cp = pxcmd;
	long i,length = sizeof(trinity);

	if (!(pxrom[0].res&TRACE))
	{
		pxerror = PGE_RES;
		return;
	}

	*cp++ = 0;
	*cp++ = TR_RX|CM_NORSP;
	*cp++ = (char)length;
	pxcmdl = length + 3;
	for (i=0; i<length; i++)
		*cp++ = trinity[i];

	pi_cmd();
	picmd(0,TR_RX,2,MG_CONFIGD,0,0,0,0);
	picmd(0,TR_RX|CM_TREAD,2,MG_CONFIGD,1,0,0,0);
	pxtrconfig = ~pxrsp[PIDT];
	printf("\nInitialized the Trace Board:\n Config: 0x%02X",pxtrconfig);
	if (pxtrconfig&TC512)
	{
		pxmaxt = 0x7ffff;
		pxmaxp = 0x80000;
		if (pxtrconfig&MEMR2)
		{
			printf(" Model 512-1 (512K CodeTrace / 1M CodeCoverage)");
			pxmaxm = 0xfffff;
		}
		else
		{
			printf(" Model 512-2 (512K CodeTrace / 2M CodeCoverage)");
			pxmaxm = 0x1fffff;
		}
	}
	else
	{
		if (pxtrconfig&BIGCC)
		{
		printf(" Model 128-2 (128K CodeTrace / 2M CodeCoverage)");
		pxmaxt = 0x1ffff;
		pxmaxp = 0x80000;
		pxmaxm = 0x1fffff;
		}
		else
		{
		printf(" Model 128-1 (128K CodeTrace / 512K CodeCoverage)");
		pxmaxt = 0x1ffff;
		pxmaxp = 0x20000;
		pxmaxm = 0x7ffff;
		}
	}
	bigone = control;
	pxtrflags |= TRINIT;
}

void pitrstatus(void)
{
	if (!(pxtrflags&TRINIT))
		return;
	picmd(0,TR_RX|CM_NORSP,2,MG_CONTROL,0,0,0,0);
	picmd(0,TR_RX|CM_TREAD,2,MG_CONTROL,1,0,0,0);
	printf("\n\nAI2 INTERFACE STATUS: ");
	if (pxrsp[PIDT]&0x80) printf("XINT ");
	if (pxrsp[PIDT]&0x40) printf("TRACESEEN ");
	if (pxrsp[PIDT]&0x20) printf("TRACESTOPED ");
	if (pxrsp[PIDT]&0x10) printf("XTRACESTOPED ");
	if (pxrsp[PIDT]&0x08) printf("BREAKSEEN ");
	if (pxrsp[PIDT]&0x04) printf("XBREAKSEEN ");
	if (pxrsp[PIDT]&0x02) printf("AIHDA ");
	if (pxrsp[PIDT]&0x01) printf("AITDA ");
	if (!pxrsp[PIDT]) printf("NONE");
	picmd(0,TR_RX|CM_NORSP,2,MG_CONTROL,MGD_TRACE,0,0,0);
	picmd(0,TR_RX|CM_TREAD,2,TR_CONTROLA,1,0,0,0);
	printf("\nTRACE STATUS: ");
	if (pxrsp[PIDT]&0x20) printf("TraceStoped ");
	if (pxrsp[PIDT]&0x10) printf("SkipCounterOver ");
	if (pxrsp[PIDT]&0x08) printf("TraceCounterOver ");
	if (pxrsp[PIDT]&0x04) printf("TraceBufferFull ");
	if (pxrsp[PIDT]&0x02) printf("BreakSeen ");
	if (pxrsp[PIDT]&0x01) printf("TraceSeen ");
	if (!pxrsp[PIDT]) printf("NONE");
	if (pxrsp[PIDT]&0x20)
	{
		picmd(0,TR_RX|CM_TREAD,2,TR_ADDRESSX,4,0,0,0);
		printf("\nCurrentTracePointer\t= %02X%02X%02X",pxrsp[PIDT]&0xff,pxrsp[PIDT+2]&0xff,
				pxrsp[PIDT+3]&0xff);
		if (pxtrflags&TRSNEW)
			curtp = (((pxrsp[PIDT]&0xff)<<16)|((pxrsp[PIDT+2]&0xff)<<8)|(pxrsp[PIDT+3]&0xff));
	}
	else
		printf("\nLastKnownGoodTracePointer = 0x%X (%d)",curtp, curtp);
}
