3150 lines
		
	
	
		
			65 KiB
		
	
	
	
		
			C
		
	
	
	
			
		
		
	
	
			3150 lines
		
	
	
		
			65 KiB
		
	
	
	
		
			C
		
	
	
	
| /*
 | |
|  * Porting to u-boot:
 | |
|  *
 | |
|  * (C) Copyright 2010
 | |
|  * Stefano Babic, DENX Software Engineering, sbabic@denx.de.
 | |
|  *
 | |
|  * Lattice ispVME Embedded code to load Lattice's FPGA:
 | |
|  *
 | |
|  * Copyright 2009 Lattice Semiconductor Corp.
 | |
|  *
 | |
|  * ispVME Embedded allows programming of Lattice's suite of FPGA
 | |
|  * devices on embedded systems through the JTAG port.  The software
 | |
|  * is distributed in source code form and is open to re - distribution
 | |
|  * and modification where applicable.
 | |
|  *
 | |
|  * Revision History of ivm_core.c module:
 | |
|  * 4/25/06 ht   Change some variables from unsigned short or int
 | |
|  *              to long int to make the code compiler independent.
 | |
|  * 5/24/06 ht   Support using RESET (TRST) pin as a special purpose
 | |
|  *              control pin such as triggering the loading of known
 | |
|  *              state exit.
 | |
|  * 3/6/07 ht added functions to support output to terminals
 | |
|  *
 | |
|  * 09/11/07 NN Type cast mismatch variables
 | |
|  *		   Moved the sclock() function to hardware.c
 | |
|  * 08/28/08 NN Added Calculate checksum support.
 | |
|  * 4/1/09 Nguyen replaced the recursive function call codes on
 | |
|  *        the ispVMLCOUNT function
 | |
|  * SPDX-License-Identifier:	GPL-2.0+
 | |
|  */
 | |
| 
 | |
| #include <common.h>
 | |
| #include <linux/string.h>
 | |
| #include <malloc.h>
 | |
| #include <lattice.h>
 | |
| 
 | |
| #define vme_out_char(c)	printf("%c", c)
 | |
| #define vme_out_hex(c)	printf("%x", c)
 | |
| #define vme_out_string(s) printf("%s", s)
 | |
| 
 | |
| /*
 | |
|  *
 | |
|  * Global variables used to specify the flow control and data type.
 | |
|  *
 | |
|  *	g_usFlowControl:	flow control register. Each bit in the
 | |
|  *                               register can potentially change the
 | |
|  *                               personality of the embedded engine.
 | |
|  *	g_usDataType:		holds the data type of the current row.
 | |
|  *
 | |
|  */
 | |
| 
 | |
| static unsigned short g_usFlowControl;
 | |
| unsigned short g_usDataType;
 | |
| 
 | |
| /*
 | |
|  *
 | |
|  * Global variables used to specify the ENDDR and ENDIR.
 | |
|  *
 | |
|  *	g_ucEndDR:		the state that the device goes to after SDR.
 | |
|  *	g_ucEndIR:		the state that the device goes to after SIR.
 | |
|  *
 | |
|  */
 | |
| 
 | |
| unsigned char g_ucEndDR = DRPAUSE;
 | |
| unsigned char g_ucEndIR = IRPAUSE;
 | |
| 
 | |
| /*
 | |
|  *
 | |
|  * Global variables used to support header/trailer.
 | |
|  *
 | |
|  *	g_usHeadDR:		the number of lead devices in bypass.
 | |
|  *	g_usHeadIR:		the sum of IR length of lead devices.
 | |
|  *	g_usTailDR:		the number of tail devices in bypass.
 | |
|  *	g_usTailIR:		the sum of IR length of tail devices.
 | |
|  *
 | |
|  */
 | |
| 
 | |
| static unsigned short g_usHeadDR;
 | |
| static unsigned short g_usHeadIR;
 | |
| static unsigned short g_usTailDR;
 | |
| static unsigned short g_usTailIR;
 | |
| 
 | |
| /*
 | |
|  *
 | |
|  * Global variable to store the number of bits of data or instruction
 | |
|  * to be shifted into or out from the device.
 | |
|  *
 | |
|  */
 | |
| 
 | |
| static unsigned short g_usiDataSize;
 | |
| 
 | |
| /*
 | |
|  *
 | |
|  * Stores the frequency. Default to 1 MHz.
 | |
|  *
 | |
|  */
 | |
| 
 | |
| static int g_iFrequency = 1000;
 | |
| 
 | |
| /*
 | |
|  *
 | |
|  * Stores the maximum amount of ram needed to hold a row of data.
 | |
|  *
 | |
|  */
 | |
| 
 | |
| static unsigned short g_usMaxSize;
 | |
| 
 | |
| /*
 | |
|  *
 | |
|  * Stores the LSH or RSH value.
 | |
|  *
 | |
|  */
 | |
| 
 | |
| static unsigned short g_usShiftValue;
 | |
| 
 | |
| /*
 | |
|  *
 | |
|  * Stores the current repeat loop value.
 | |
|  *
 | |
|  */
 | |
| 
 | |
| static unsigned short g_usRepeatLoops;
 | |
| 
 | |
| /*
 | |
|  *
 | |
|  * Stores the current vendor.
 | |
|  *
 | |
|  */
 | |
| 
 | |
| static signed char g_cVendor = LATTICE;
 | |
| 
 | |
| /*
 | |
|  *
 | |
|  * Stores the VME file CRC.
 | |
|  *
 | |
|  */
 | |
| 
 | |
| unsigned short g_usCalculatedCRC;
 | |
| 
 | |
| /*
 | |
|  *
 | |
|  * Stores the Device Checksum.
 | |
|  *
 | |
|  */
 | |
| /* 08/28/08 NN Added Calculate checksum support. */
 | |
| unsigned long g_usChecksum;
 | |
| static unsigned int g_uiChecksumIndex;
 | |
| 
 | |
| /*
 | |
|  *
 | |
|  * Stores the current state of the JTAG state machine.
 | |
|  *
 | |
|  */
 | |
| 
 | |
| static signed char g_cCurrentJTAGState;
 | |
| 
 | |
| /*
 | |
|  *
 | |
|  * Global variables used to support looping.
 | |
|  *
 | |
|  *	g_pucHeapMemory:	holds the entire repeat loop.
 | |
|  *	g_iHeapCounter:		points to the current byte in the repeat loop.
 | |
|  *	g_iHEAPSize:		the current size of the repeat in bytes.
 | |
|  *
 | |
|  */
 | |
| 
 | |
| unsigned char *g_pucHeapMemory;
 | |
| unsigned short g_iHeapCounter;
 | |
| unsigned short g_iHEAPSize;
 | |
| static unsigned short previous_size;
 | |
| 
 | |
| /*
 | |
|  *
 | |
|  * Global variables used to support intelligent programming.
 | |
|  *
 | |
|  *	g_usIntelDataIndex:     points to the current byte of the
 | |
|  *                               intelligent buffer.
 | |
|  *	g_usIntelBufferSize:	holds the size of the intelligent
 | |
|  *                               buffer.
 | |
|  *
 | |
|  */
 | |
| 
 | |
| unsigned short g_usIntelDataIndex;
 | |
| unsigned short g_usIntelBufferSize;
 | |
| 
 | |
| /*
 | |
|  *
 | |
|  * Supported VME versions.
 | |
|  *
 | |
|  */
 | |
| 
 | |
| const char *const g_szSupportedVersions[] = {
 | |
| 	"__VME2.0", "__VME3.0", "____12.0", "____12.1", 0};
 | |
| 
 | |
| /*
 | |
|  *
 | |
|  * Holds the maximum size of each respective buffer. These variables are used
 | |
|  * to write the HEX files when converting VME to HEX.
 | |
|  *
 | |
| */
 | |
| 
 | |
| static unsigned short g_usTDOSize;
 | |
| static unsigned short g_usMASKSize;
 | |
| static unsigned short g_usTDISize;
 | |
| static unsigned short g_usDMASKSize;
 | |
| static unsigned short g_usLCOUNTSize;
 | |
| static unsigned short g_usHDRSize;
 | |
| static unsigned short g_usTDRSize;
 | |
| static unsigned short g_usHIRSize;
 | |
| static unsigned short g_usTIRSize;
 | |
| static unsigned short g_usHeapSize;
 | |
| 
 | |
| /*
 | |
|  *
 | |
|  * Global variables used to store data.
 | |
|  *
 | |
|  *	g_pucOutMaskData:	local RAM to hold one row of MASK data.
 | |
|  *	g_pucInData:		local RAM to hold one row of TDI data.
 | |
|  *	g_pucOutData:		local RAM to hold one row of TDO data.
 | |
|  *	g_pucHIRData:		local RAM to hold the current SIR header.
 | |
|  *	g_pucTIRData:		local RAM to hold the current SIR trailer.
 | |
|  *	g_pucHDRData:		local RAM to hold the current SDR header.
 | |
|  *	g_pucTDRData:		local RAM to hold the current SDR trailer.
 | |
|  *	g_pucIntelBuffer:	local RAM to hold the current intelligent buffer
 | |
|  *	g_pucOutDMaskData:	local RAM to hold one row of DMASK data.
 | |
|  *
 | |
|  */
 | |
| 
 | |
| unsigned char	*g_pucOutMaskData	= NULL,
 | |
| 		*g_pucInData		= NULL,
 | |
| 		*g_pucOutData		= NULL,
 | |
| 		*g_pucHIRData		= NULL,
 | |
| 		*g_pucTIRData		= NULL,
 | |
| 		*g_pucHDRData		= NULL,
 | |
| 		*g_pucTDRData		= NULL,
 | |
| 		*g_pucIntelBuffer	= NULL,
 | |
| 		*g_pucOutDMaskData	= NULL;
 | |
| 
 | |
| /*
 | |
|  *
 | |
|  * JTAG state machine transition table.
 | |
|  *
 | |
|  */
 | |
| 
 | |
| struct {
 | |
| 	 unsigned char  CurState;  /* From this state */
 | |
| 	 unsigned char  NextState; /* Step to this state */
 | |
| 	 unsigned char  Pattern;   /* The tragetory of TMS */
 | |
| 	 unsigned char  Pulses;    /* The number of steps */
 | |
| } g_JTAGTransistions[25] = {
 | |
| { RESET,	RESET,		0xFC, 6 },	/* Transitions from RESET */
 | |
| { RESET,	IDLE,		0x00, 1 },
 | |
| { RESET,	DRPAUSE,	0x50, 5 },
 | |
| { RESET,	IRPAUSE,	0x68, 6 },
 | |
| { IDLE,		RESET,		0xE0, 3 },	/* Transitions from IDLE */
 | |
| { IDLE,		DRPAUSE,	0xA0, 4 },
 | |
| { IDLE,		IRPAUSE,	0xD0, 5 },
 | |
| { DRPAUSE,	RESET,		0xF8, 5 },	/* Transitions from DRPAUSE */
 | |
| { DRPAUSE,	IDLE,		0xC0, 3 },
 | |
| { DRPAUSE,	IRPAUSE,	0xF4, 7 },
 | |
| { DRPAUSE,	DRPAUSE,	0xE8, 6 },/* 06/14/06 Support POLL STATUS LOOP*/
 | |
| { IRPAUSE,	RESET,		0xF8, 5 },	/* Transitions from IRPAUSE */
 | |
| { IRPAUSE,	IDLE,		0xC0, 3 },
 | |
| { IRPAUSE,	DRPAUSE,	0xE8, 6 },
 | |
| { DRPAUSE,	SHIFTDR,	0x80, 2 }, /* Extra transitions using SHIFTDR */
 | |
| { IRPAUSE,	SHIFTDR,	0xE0, 5 },
 | |
| { SHIFTDR,	DRPAUSE,	0x80, 2 },
 | |
| { SHIFTDR,	IDLE,		0xC0, 3 },
 | |
| { IRPAUSE,	SHIFTIR,	0x80, 2 },/* Extra transitions using SHIFTIR */
 | |
| { SHIFTIR,	IRPAUSE,	0x80, 2 },
 | |
| { SHIFTIR,	IDLE,		0xC0, 3 },
 | |
| { DRPAUSE,	DRCAPTURE,	0xE0, 4 }, /* 11/15/05 Support DRCAPTURE*/
 | |
| { DRCAPTURE, DRPAUSE,	0x80, 2 },
 | |
| { IDLE,     DRCAPTURE,	0x80, 2 },
 | |
| { IRPAUSE,  DRCAPTURE,  0xE0, 4 }
 | |
| };
 | |
| 
 | |
| /*
 | |
|  *
 | |
|  * List to hold all LVDS pairs.
 | |
|  *
 | |
|  */
 | |
| 
 | |
| LVDSPair *g_pLVDSList;
 | |
| unsigned short g_usLVDSPairCount;
 | |
| 
 | |
| /*
 | |
|  *
 | |
|  * Function prototypes.
 | |
|  *
 | |
|  */
 | |
| 
 | |
| static signed char ispVMDataCode(void);
 | |
| static long int ispVMDataSize(void);
 | |
| static void ispVMData(unsigned char *Data);
 | |
| static signed char ispVMShift(signed char Code);
 | |
| static signed char ispVMAmble(signed char Code);
 | |
| static signed char ispVMLoop(unsigned short a_usLoopCount);
 | |
| static signed char ispVMBitShift(signed char mode, unsigned short bits);
 | |
| static void ispVMComment(unsigned short a_usCommentSize);
 | |
| static void ispVMHeader(unsigned short a_usHeaderSize);
 | |
| static signed char ispVMLCOUNT(unsigned short a_usCountSize);
 | |
| static void ispVMClocks(unsigned short Clocks);
 | |
| static void ispVMBypass(signed char ScanType, unsigned short Bits);
 | |
| static void ispVMStateMachine(signed char NextState);
 | |
| static signed char ispVMSend(unsigned short int);
 | |
| static signed char ispVMRead(unsigned short int);
 | |
| static signed char ispVMReadandSave(unsigned short int);
 | |
| static signed char ispVMProcessLVDS(unsigned short a_usLVDSCount);
 | |
| static void ispVMMemManager(signed char types, unsigned short size);
 | |
| 
 | |
| /*
 | |
|  *
 | |
|  * External variables and functions in hardware.c module
 | |
|  *
 | |
|  */
 | |
| static signed char g_cCurrentJTAGState;
 | |
| 
 | |
| #ifdef DEBUG
 | |
| 
 | |
| /*
 | |
|  *
 | |
|  * GetState
 | |
|  *
 | |
|  * Returns the state as a string based on the opcode. Only used
 | |
|  * for debugging purposes.
 | |
|  *
 | |
|  */
 | |
| 
 | |
| const char *GetState(unsigned char a_ucState)
 | |
| {
 | |
| 	switch (a_ucState) {
 | |
| 	case RESET:
 | |
| 		return "RESET";
 | |
| 	case IDLE:
 | |
| 		return "IDLE";
 | |
| 	case IRPAUSE:
 | |
| 		return "IRPAUSE";
 | |
| 	case DRPAUSE:
 | |
| 		return "DRPAUSE";
 | |
| 	case SHIFTIR:
 | |
| 		return "SHIFTIR";
 | |
| 	case SHIFTDR:
 | |
| 		return "SHIFTDR";
 | |
| 	case DRCAPTURE:/* 11/15/05 support DRCAPTURE*/
 | |
| 		return "DRCAPTURE";
 | |
| 	default:
 | |
| 		break;
 | |
| 	}
 | |
| 
 | |
| 	return 0;
 | |
| }
 | |
| 
 | |
| /*
 | |
|  *
 | |
|  * PrintData
 | |
|  *
 | |
|  * Prints the data. Only used for debugging purposes.
 | |
|  *
 | |
|  */
 | |
| 
 | |
| void PrintData(unsigned short a_iDataSize, unsigned char *a_pucData)
 | |
| {
 | |
| 	/* 09/11/07 NN added local variables initialization */
 | |
| 	unsigned short usByteSize  = 0;
 | |
| 	unsigned short usBitIndex  = 0;
 | |
| 	signed short usByteIndex   = 0;
 | |
| 	unsigned char ucByte       = 0;
 | |
| 	unsigned char ucFlipByte   = 0;
 | |
| 
 | |
| 	if (a_iDataSize % 8) {
 | |
| 		/* 09/11/07 NN Type cast mismatch variables */
 | |
| 		usByteSize = (unsigned short)(a_iDataSize / 8 + 1);
 | |
| 	} else {
 | |
| 		/* 09/11/07 NN Type cast mismatch variables */
 | |
| 		usByteSize = (unsigned short)(a_iDataSize / 8);
 | |
| 	}
 | |
| 	puts("(");
 | |
| 	/* 09/11/07 NN Type cast mismatch variables */
 | |
| 	for (usByteIndex = (signed short)(usByteSize - 1);
 | |
| 		usByteIndex >= 0; usByteIndex--) {
 | |
| 		ucByte = a_pucData[usByteIndex];
 | |
| 		ucFlipByte = 0x00;
 | |
| 
 | |
| 		/*
 | |
| 		*
 | |
| 		* Flip each byte.
 | |
| 		*
 | |
| 		*/
 | |
| 
 | |
| 		for (usBitIndex = 0; usBitIndex < 8; usBitIndex++) {
 | |
| 			ucFlipByte <<= 1;
 | |
| 			if (ucByte & 0x1) {
 | |
| 				ucFlipByte |= 0x1;
 | |
| 			}
 | |
| 
 | |
| 			ucByte >>= 1;
 | |
| 		}
 | |
| 
 | |
| 		/*
 | |
| 		*
 | |
| 		* Print the flipped byte.
 | |
| 		*
 | |
| 		*/
 | |
| 
 | |
| 		printf("%.02X", ucFlipByte);
 | |
| 		if ((usByteSize - usByteIndex) % 40 == 39) {
 | |
| 			puts("\n\t\t");
 | |
| 		}
 | |
| 		if (usByteIndex < 0)
 | |
| 			break;
 | |
| 	}
 | |
| 	puts(")");
 | |
| }
 | |
| #endif /* DEBUG */
 | |
| 
 | |
| void ispVMMemManager(signed char cTarget, unsigned short usSize)
 | |
| {
 | |
| 	switch (cTarget) {
 | |
| 	case XTDI:
 | |
| 	case TDI:
 | |
| 		if (g_pucInData != NULL) {
 | |
| 			if (previous_size == usSize) {/*memory exist*/
 | |
| 				break;
 | |
| 			} else {
 | |
| 				free(g_pucInData);
 | |
| 				g_pucInData = NULL;
 | |
| 			}
 | |
| 		}
 | |
| 		g_pucInData = (unsigned char *) malloc(usSize / 8 + 2);
 | |
| 		previous_size = usSize;
 | |
| 	case XTDO:
 | |
| 	case TDO:
 | |
| 		if (g_pucOutData != NULL) {
 | |
| 			if (previous_size == usSize) { /*already exist*/
 | |
| 				break;
 | |
| 			} else {
 | |
| 				free(g_pucOutData);
 | |
| 				g_pucOutData = NULL;
 | |
| 			}
 | |
| 		}
 | |
| 		g_pucOutData = (unsigned char *) malloc(usSize / 8 + 2);
 | |
| 		previous_size = usSize;
 | |
| 		break;
 | |
| 	case MASK:
 | |
| 		if (g_pucOutMaskData != NULL) {
 | |
| 			if (previous_size == usSize) {/*already allocated*/
 | |
| 				break;
 | |
| 			} else {
 | |
| 				free(g_pucOutMaskData);
 | |
| 				g_pucOutMaskData = NULL;
 | |
| 			}
 | |
| 		}
 | |
| 		g_pucOutMaskData = (unsigned char *) malloc(usSize / 8 + 2);
 | |
| 		previous_size = usSize;
 | |
| 		break;
 | |
| 	case HIR:
 | |
| 		if (g_pucHIRData != NULL) {
 | |
| 			free(g_pucHIRData);
 | |
| 			g_pucHIRData = NULL;
 | |
| 		}
 | |
| 		g_pucHIRData = (unsigned char *) malloc(usSize / 8 + 2);
 | |
| 		break;
 | |
| 	case TIR:
 | |
| 		if (g_pucTIRData != NULL) {
 | |
| 			free(g_pucTIRData);
 | |
| 			g_pucTIRData = NULL;
 | |
| 		}
 | |
| 		g_pucTIRData = (unsigned char *) malloc(usSize / 8 + 2);
 | |
| 		break;
 | |
| 	case HDR:
 | |
| 		if (g_pucHDRData != NULL) {
 | |
| 			free(g_pucHDRData);
 | |
| 			g_pucHDRData = NULL;
 | |
| 		}
 | |
| 		g_pucHDRData = (unsigned char *) malloc(usSize / 8 + 2);
 | |
| 		break;
 | |
| 	case TDR:
 | |
| 		if (g_pucTDRData != NULL) {
 | |
| 			free(g_pucTDRData);
 | |
| 			g_pucTDRData = NULL;
 | |
| 		}
 | |
| 		g_pucTDRData = (unsigned char *) malloc(usSize / 8 + 2);
 | |
| 		break;
 | |
| 	case HEAP:
 | |
| 		if (g_pucHeapMemory != NULL) {
 | |
| 			free(g_pucHeapMemory);
 | |
| 			g_pucHeapMemory = NULL;
 | |
| 		}
 | |
| 		g_pucHeapMemory = (unsigned char *) malloc(usSize + 2);
 | |
| 		break;
 | |
| 	case DMASK:
 | |
| 		if (g_pucOutDMaskData != NULL) {
 | |
| 			if (previous_size == usSize) { /*already allocated*/
 | |
| 				break;
 | |
| 			} else {
 | |
| 				free(g_pucOutDMaskData);
 | |
| 				g_pucOutDMaskData = NULL;
 | |
| 			}
 | |
| 		}
 | |
| 		g_pucOutDMaskData = (unsigned char *) malloc(usSize / 8 + 2);
 | |
| 		previous_size = usSize;
 | |
| 		break;
 | |
| 	case LHEAP:
 | |
| 		if (g_pucIntelBuffer != NULL) {
 | |
| 			free(g_pucIntelBuffer);
 | |
| 			g_pucIntelBuffer = NULL;
 | |
| 		}
 | |
| 		g_pucIntelBuffer = (unsigned char *) malloc(usSize + 2);
 | |
| 		break;
 | |
| 	case LVDS:
 | |
| 		if (g_pLVDSList != NULL) {
 | |
| 			free(g_pLVDSList);
 | |
| 			g_pLVDSList = NULL;
 | |
| 		}
 | |
| 		g_pLVDSList = (LVDSPair *) malloc(usSize * sizeof(LVDSPair));
 | |
| 		if (g_pLVDSList)
 | |
| 			memset(g_pLVDSList, 0, usSize * sizeof(LVDSPair));
 | |
| 		break;
 | |
| 	default:
 | |
| 		return;
 | |
|     }
 | |
| }
 | |
| 
 | |
| void ispVMFreeMem(void)
 | |
| {
 | |
| 	if (g_pucHeapMemory != NULL) {
 | |
| 		free(g_pucHeapMemory);
 | |
| 		g_pucHeapMemory = NULL;
 | |
| 	}
 | |
| 
 | |
| 	if (g_pucOutMaskData != NULL) {
 | |
| 		free(g_pucOutMaskData);
 | |
| 		g_pucOutMaskData = NULL;
 | |
| 	}
 | |
| 
 | |
| 	if (g_pucInData != NULL) {
 | |
| 		free(g_pucInData);
 | |
| 		g_pucInData = NULL;
 | |
| 	}
 | |
| 
 | |
| 	if (g_pucOutData != NULL) {
 | |
| 		free(g_pucOutData);
 | |
| 		g_pucOutData = NULL;
 | |
| 	}
 | |
| 
 | |
| 	if (g_pucHIRData != NULL) {
 | |
| 		free(g_pucHIRData);
 | |
| 		g_pucHIRData = NULL;
 | |
| 	}
 | |
| 
 | |
| 	if (g_pucTIRData != NULL) {
 | |
| 		free(g_pucTIRData);
 | |
| 		g_pucTIRData = NULL;
 | |
| 	}
 | |
| 
 | |
| 	if (g_pucHDRData != NULL) {
 | |
| 		free(g_pucHDRData);
 | |
| 		g_pucHDRData = NULL;
 | |
| 	}
 | |
| 
 | |
| 	if (g_pucTDRData != NULL) {
 | |
| 		free(g_pucTDRData);
 | |
| 		g_pucTDRData = NULL;
 | |
| 	}
 | |
| 
 | |
| 	if (g_pucOutDMaskData != NULL) {
 | |
| 		free(g_pucOutDMaskData);
 | |
| 		g_pucOutDMaskData = NULL;
 | |
| 	}
 | |
| 
 | |
| 	if (g_pucIntelBuffer != NULL) {
 | |
| 		free(g_pucIntelBuffer);
 | |
| 		g_pucIntelBuffer = NULL;
 | |
| 	}
 | |
| 
 | |
| 	if (g_pLVDSList != NULL) {
 | |
| 		free(g_pLVDSList);
 | |
| 		g_pLVDSList = NULL;
 | |
| 	}
 | |
| }
 | |
| 
 | |
| 
 | |
| /*
 | |
|  *
 | |
|  * ispVMDataSize
 | |
|  *
 | |
|  * Returns a VME-encoded number, usually used to indicate the
 | |
|  * bit length of an SIR/SDR command.
 | |
|  *
 | |
|  */
 | |
| 
 | |
| long int ispVMDataSize()
 | |
| {
 | |
| 	/* 09/11/07 NN added local variables initialization */
 | |
| 	long int iSize           = 0;
 | |
| 	signed char cCurrentByte = 0;
 | |
| 	signed char cIndex       = 0;
 | |
| 	cIndex = 0;
 | |
| 	while ((cCurrentByte = GetByte()) & 0x80) {
 | |
| 		iSize |= ((long int) (cCurrentByte & 0x7F)) << cIndex;
 | |
| 		cIndex += 7;
 | |
| 	}
 | |
| 	iSize |= ((long int) (cCurrentByte & 0x7F)) << cIndex;
 | |
| 	return iSize;
 | |
| }
 | |
| 
 | |
| /*
 | |
|  *
 | |
|  * ispVMCode
 | |
|  *
 | |
|  * This is the heart of the embedded engine. All the high-level opcodes
 | |
|  * are extracted here. Once they have been identified, then it
 | |
|  * will call other functions to handle the processing.
 | |
|  *
 | |
|  */
 | |
| 
 | |
| signed char ispVMCode()
 | |
| {
 | |
| 	/* 09/11/07 NN added local variables initialization */
 | |
| 	unsigned short iRepeatSize = 0;
 | |
| 	signed char cOpcode	   = 0;
 | |
| 	signed char cRetCode       = 0;
 | |
| 	unsigned char ucState      = 0;
 | |
| 	unsigned short usDelay     = 0;
 | |
| 	unsigned short usToggle    = 0;
 | |
| 	unsigned char usByte       = 0;
 | |
| 
 | |
| 	/*
 | |
| 	*
 | |
| 	* Check the compression flag only if this is the first time
 | |
| 	* this function is entered. Do not check the compression flag if
 | |
| 	* it is being called recursively from other functions within
 | |
| 	* the embedded engine.
 | |
| 	*
 | |
| 	*/
 | |
| 
 | |
| 	if (!(g_usDataType & LHEAP_IN) && !(g_usDataType & HEAP_IN)) {
 | |
| 		usByte = GetByte();
 | |
| 		if (usByte == 0xf1) {
 | |
| 			g_usDataType |= COMPRESS;
 | |
| 		} else if (usByte == 0xf2) {
 | |
| 			g_usDataType &= ~COMPRESS;
 | |
| 		} else {
 | |
| 			return VME_INVALID_FILE;
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	/*
 | |
| 	*
 | |
| 	* Begin looping through all the VME opcodes.
 | |
| 	*
 | |
| 	*/
 | |
| 
 | |
| 	while ((cOpcode = GetByte()) >= 0) {
 | |
| 
 | |
| 		switch (cOpcode) {
 | |
| 		case STATE:
 | |
| 
 | |
| 			/*
 | |
| 			 * Step the JTAG state machine.
 | |
| 			 */
 | |
| 
 | |
| 			ucState = GetByte();
 | |
| 
 | |
| 			/*
 | |
| 			 * Step the JTAG state machine to DRCAPTURE
 | |
| 			 * to support Looping.
 | |
| 			 */
 | |
| 
 | |
| 			if ((g_usDataType & LHEAP_IN) &&
 | |
| 				 (ucState == DRPAUSE) &&
 | |
| 				 (g_cCurrentJTAGState == ucState)) {
 | |
| 				ispVMStateMachine(DRCAPTURE);
 | |
| 			}
 | |
| 
 | |
| 			ispVMStateMachine(ucState);
 | |
| 
 | |
| #ifdef DEBUG
 | |
| 			if (g_usDataType & LHEAP_IN) {
 | |
| 				debug("LDELAY %s ", GetState(ucState));
 | |
| 			} else {
 | |
| 				debug("STATE %s;\n", GetState(ucState));
 | |
| 			}
 | |
| #endif /* DEBUG */
 | |
| 			break;
 | |
| 		case SIR:
 | |
| 		case SDR:
 | |
| 		case XSDR:
 | |
| 
 | |
| #ifdef DEBUG
 | |
| 			switch (cOpcode) {
 | |
| 			case SIR:
 | |
| 				puts("SIR ");
 | |
| 				break;
 | |
| 			case SDR:
 | |
| 			case XSDR:
 | |
| 				if (g_usDataType & LHEAP_IN) {
 | |
| 					puts("LSDR ");
 | |
| 				} else {
 | |
| 					puts("SDR ");
 | |
| 				}
 | |
| 				break;
 | |
| 			}
 | |
| #endif /* DEBUG */
 | |
| 			/*
 | |
| 			*
 | |
| 			* Shift in data into the device.
 | |
| 			*
 | |
| 			*/
 | |
| 
 | |
| 			cRetCode = ispVMShift(cOpcode);
 | |
| 			if (cRetCode != 0) {
 | |
| 				return cRetCode;
 | |
| 			}
 | |
| 			break;
 | |
| 		case WAIT:
 | |
| 
 | |
| 			/*
 | |
| 			*
 | |
| 			* Observe delay.
 | |
| 			*
 | |
| 			*/
 | |
| 
 | |
| 			/* 09/11/07 NN Type cast mismatch variables */
 | |
| 			usDelay = (unsigned short) ispVMDataSize();
 | |
| 			ispVMDelay(usDelay);
 | |
| 
 | |
| #ifdef DEBUG
 | |
| 			if (usDelay & 0x8000) {
 | |
| 
 | |
| 				/*
 | |
| 				 * Since MSB is set, the delay time must be
 | |
| 				 * decoded to millisecond. The SVF2VME encodes
 | |
| 				 * the MSB to represent millisecond.
 | |
| 				 */
 | |
| 
 | |
| 				usDelay &= ~0x8000;
 | |
| 				if (g_usDataType & LHEAP_IN) {
 | |
| 					printf("%.2E SEC;\n",
 | |
| 						(float) usDelay / 1000);
 | |
| 				} else {
 | |
| 					printf("RUNTEST %.2E SEC;\n",
 | |
| 						(float) usDelay / 1000);
 | |
| 				}
 | |
| 			} else {
 | |
| 				/*
 | |
| 				 * Since MSB is not set, the delay time
 | |
| 				 * is given as microseconds.
 | |
| 				 */
 | |
| 
 | |
| 				if (g_usDataType & LHEAP_IN) {
 | |
| 					printf("%.2E SEC;\n",
 | |
| 						(float) usDelay / 1000000);
 | |
| 				} else {
 | |
| 					printf("RUNTEST %.2E SEC;\n",
 | |
| 						(float) usDelay / 1000000);
 | |
| 				}
 | |
| 			}
 | |
| #endif /* DEBUG */
 | |
| 			break;
 | |
| 		case TCK:
 | |
| 
 | |
| 			/*
 | |
| 			 * Issue clock toggles.
 | |
| 			*/
 | |
| 
 | |
| 			/* 09/11/07 NN Type cast mismatch variables */
 | |
| 			usToggle = (unsigned short) ispVMDataSize();
 | |
| 			ispVMClocks(usToggle);
 | |
| 
 | |
| #ifdef DEBUG
 | |
| 			printf("RUNTEST %d TCK;\n", usToggle);
 | |
| #endif /* DEBUG */
 | |
| 			break;
 | |
| 		case ENDDR:
 | |
| 
 | |
| 			/*
 | |
| 			*
 | |
| 			* Set the ENDDR.
 | |
| 			*
 | |
| 			*/
 | |
| 
 | |
| 			g_ucEndDR = GetByte();
 | |
| 
 | |
| #ifdef DEBUG
 | |
| 			printf("ENDDR %s;\n", GetState(g_ucEndDR));
 | |
| #endif /* DEBUG */
 | |
| 			break;
 | |
| 		case ENDIR:
 | |
| 
 | |
| 			/*
 | |
| 			*
 | |
| 			* Set the ENDIR.
 | |
| 			*
 | |
| 			*/
 | |
| 
 | |
| 			g_ucEndIR = GetByte();
 | |
| 
 | |
| #ifdef DEBUG
 | |
| 			printf("ENDIR %s;\n", GetState(g_ucEndIR));
 | |
| #endif /* DEBUG */
 | |
| 			break;
 | |
| 		case HIR:
 | |
| 		case TIR:
 | |
| 		case HDR:
 | |
| 		case TDR:
 | |
| 
 | |
| #ifdef DEBUG
 | |
| 			switch (cOpcode) {
 | |
| 			case HIR:
 | |
| 				puts("HIR ");
 | |
| 				break;
 | |
| 			case TIR:
 | |
| 				puts("TIR ");
 | |
| 				break;
 | |
| 			case HDR:
 | |
| 				puts("HDR ");
 | |
| 				break;
 | |
| 			case TDR:
 | |
| 				puts("TDR ");
 | |
| 				break;
 | |
| 			}
 | |
| #endif /* DEBUG */
 | |
| 			/*
 | |
| 			 * Set the header/trailer of the device in order
 | |
| 			 * to bypass
 | |
| 			 * successfully.
 | |
| 			 */
 | |
| 
 | |
| 			cRetCode = ispVMAmble(cOpcode);
 | |
| 			if (cRetCode != 0) {
 | |
| 				return cRetCode;
 | |
| 			}
 | |
| 
 | |
| #ifdef DEBUG
 | |
| 			puts(";\n");
 | |
| #endif /* DEBUG */
 | |
| 			break;
 | |
| 		case MEM:
 | |
| 
 | |
| 			/*
 | |
| 			 * The maximum RAM required to support
 | |
| 			 * processing one row of the VME file.
 | |
| 			 */
 | |
| 
 | |
| 			/* 09/11/07 NN Type cast mismatch variables */
 | |
| 			g_usMaxSize = (unsigned short) ispVMDataSize();
 | |
| 
 | |
| #ifdef DEBUG
 | |
| 			printf("// MEMSIZE %d\n", g_usMaxSize);
 | |
| #endif /* DEBUG */
 | |
| 			break;
 | |
| 		case VENDOR:
 | |
| 
 | |
| 			/*
 | |
| 			*
 | |
| 			* Set the VENDOR type.
 | |
| 			*
 | |
| 			*/
 | |
| 
 | |
| 			cOpcode = GetByte();
 | |
| 			switch (cOpcode) {
 | |
| 			case LATTICE:
 | |
| #ifdef DEBUG
 | |
| 				puts("// VENDOR LATTICE\n");
 | |
| #endif /* DEBUG */
 | |
| 				g_cVendor = LATTICE;
 | |
| 				break;
 | |
| 			case ALTERA:
 | |
| #ifdef DEBUG
 | |
| 				puts("// VENDOR ALTERA\n");
 | |
| #endif /* DEBUG */
 | |
| 				g_cVendor = ALTERA;
 | |
| 				break;
 | |
| 			case XILINX:
 | |
| #ifdef DEBUG
 | |
| 				puts("// VENDOR XILINX\n");
 | |
| #endif /* DEBUG */
 | |
| 				g_cVendor = XILINX;
 | |
| 				break;
 | |
| 			default:
 | |
| 				break;
 | |
| 			}
 | |
| 			break;
 | |
| 		case SETFLOW:
 | |
| 
 | |
| 			/*
 | |
| 			 * Set the flow control. Flow control determines
 | |
| 			 * the personality of the embedded engine.
 | |
| 			 */
 | |
| 
 | |
| 			/* 09/11/07 NN Type cast mismatch variables */
 | |
| 			g_usFlowControl |= (unsigned short) ispVMDataSize();
 | |
| 			break;
 | |
| 		case RESETFLOW:
 | |
| 
 | |
| 			/*
 | |
| 			*
 | |
| 			* Unset the flow control.
 | |
| 			*
 | |
| 			*/
 | |
| 
 | |
| 			/* 09/11/07 NN Type cast mismatch variables */
 | |
| 			g_usFlowControl &= (unsigned short) ~(ispVMDataSize());
 | |
| 			break;
 | |
| 		case HEAP:
 | |
| 
 | |
| 			/*
 | |
| 			*
 | |
| 			* Allocate heap size to store loops.
 | |
| 			*
 | |
| 			*/
 | |
| 
 | |
| 			cRetCode = GetByte();
 | |
| 			if (cRetCode != SECUREHEAP) {
 | |
| 				return VME_INVALID_FILE;
 | |
| 			}
 | |
| 			/* 09/11/07 NN Type cast mismatch variables */
 | |
| 			g_iHEAPSize = (unsigned short) ispVMDataSize();
 | |
| 
 | |
| 			/*
 | |
| 			 * Store the maximum size of the HEAP buffer.
 | |
| 			 * Used to convert VME to HEX.
 | |
| 			 */
 | |
| 
 | |
| 			if (g_iHEAPSize > g_usHeapSize) {
 | |
| 				g_usHeapSize = g_iHEAPSize;
 | |
| 			}
 | |
| 
 | |
| 			ispVMMemManager(HEAP, (unsigned short) g_iHEAPSize);
 | |
| 			break;
 | |
| 		case REPEAT:
 | |
| 
 | |
| 			/*
 | |
| 			*
 | |
| 			* Execute loops.
 | |
| 			*
 | |
| 			*/
 | |
| 
 | |
| 			g_usRepeatLoops = 0;
 | |
| 
 | |
| 			/* 09/11/07 NN Type cast mismatch variables */
 | |
| 			iRepeatSize = (unsigned short) ispVMDataSize();
 | |
| 
 | |
| 			cRetCode = ispVMLoop((unsigned short) iRepeatSize);
 | |
| 			if (cRetCode != 0) {
 | |
| 				return cRetCode;
 | |
| 			}
 | |
| 			break;
 | |
| 		case ENDLOOP:
 | |
| 
 | |
| 			/*
 | |
| 			*
 | |
| 			* Exit point from processing loops.
 | |
| 			*
 | |
| 			*/
 | |
| 
 | |
| 			return cRetCode;
 | |
| 		case ENDVME:
 | |
| 
 | |
| 			/*
 | |
| 			 * The only valid exit point that indicates
 | |
| 			 * end of programming.
 | |
| 			 */
 | |
| 
 | |
| 			return cRetCode;
 | |
| 		case SHR:
 | |
| 
 | |
| 			/*
 | |
| 			*
 | |
| 			* Right-shift address.
 | |
| 			*
 | |
| 			*/
 | |
| 
 | |
| 			g_usFlowControl |= SHIFTRIGHT;
 | |
| 
 | |
| 			/* 09/11/07 NN Type cast mismatch variables */
 | |
| 			g_usShiftValue = (unsigned short) (g_usRepeatLoops *
 | |
| 				(unsigned short)GetByte());
 | |
| 			break;
 | |
| 		case SHL:
 | |
| 
 | |
| 			/*
 | |
| 			 * Left-shift address.
 | |
| 			 */
 | |
| 
 | |
| 			g_usFlowControl |= SHIFTLEFT;
 | |
| 
 | |
| 			/* 09/11/07 NN Type cast mismatch variables */
 | |
| 			g_usShiftValue = (unsigned short) (g_usRepeatLoops *
 | |
| 				(unsigned short)GetByte());
 | |
| 			break;
 | |
| 		case FREQUENCY:
 | |
| 
 | |
| 			/*
 | |
| 			*
 | |
| 			* Set the frequency.
 | |
| 			*
 | |
| 			*/
 | |
| 
 | |
| 			/* 09/11/07 NN Type cast mismatch variables */
 | |
| 			g_iFrequency = (int) (ispVMDataSize() / 1000);
 | |
| 			if (g_iFrequency == 1)
 | |
| 				g_iFrequency = 1000;
 | |
| 
 | |
| #ifdef DEBUG
 | |
| 			printf("FREQUENCY %.2E HZ;\n",
 | |
| 				(float) g_iFrequency * 1000);
 | |
| #endif /* DEBUG */
 | |
| 			break;
 | |
| 		case LCOUNT:
 | |
| 
 | |
| 			/*
 | |
| 			*
 | |
| 			* Process LCOUNT command.
 | |
| 			*
 | |
| 			*/
 | |
| 
 | |
| 			cRetCode = ispVMLCOUNT((unsigned short)ispVMDataSize());
 | |
| 			if (cRetCode != 0) {
 | |
| 				return cRetCode;
 | |
| 			}
 | |
| 			break;
 | |
| 		case VUES:
 | |
| 
 | |
| 			/*
 | |
| 			*
 | |
| 			* Set the flow control to verify USERCODE.
 | |
| 			*
 | |
| 			*/
 | |
| 
 | |
| 			g_usFlowControl |= VERIFYUES;
 | |
| 			break;
 | |
| 		case COMMENT:
 | |
| 
 | |
| 			/*
 | |
| 			*
 | |
| 			* Display comment.
 | |
| 			*
 | |
| 			*/
 | |
| 
 | |
| 			ispVMComment((unsigned short) ispVMDataSize());
 | |
| 			break;
 | |
| 		case LVDS:
 | |
| 
 | |
| 			/*
 | |
| 			*
 | |
| 			* Process LVDS command.
 | |
| 			*
 | |
| 			*/
 | |
| 
 | |
| 			ispVMProcessLVDS((unsigned short) ispVMDataSize());
 | |
| 			break;
 | |
| 		case HEADER:
 | |
| 
 | |
| 			/*
 | |
| 			*
 | |
| 			* Discard header.
 | |
| 			*
 | |
| 			*/
 | |
| 
 | |
| 			ispVMHeader((unsigned short) ispVMDataSize());
 | |
| 			break;
 | |
| 		/* 03/14/06 Support Toggle ispENABLE signal*/
 | |
| 		case ispEN:
 | |
| 			ucState = GetByte();
 | |
| 			if ((ucState == ON) || (ucState == 0x01))
 | |
| 				writePort(g_ucPinENABLE, 0x01);
 | |
| 			else
 | |
| 				writePort(g_ucPinENABLE, 0x00);
 | |
| 			ispVMDelay(1);
 | |
| 			break;
 | |
| 		/* 05/24/06 support Toggle TRST pin*/
 | |
| 		case TRST:
 | |
| 			ucState = GetByte();
 | |
| 			if (ucState == 0x01)
 | |
| 				writePort(g_ucPinTRST, 0x01);
 | |
| 			else
 | |
| 				writePort(g_ucPinTRST, 0x00);
 | |
| 			ispVMDelay(1);
 | |
| 			break;
 | |
| 		default:
 | |
| 
 | |
| 			/*
 | |
| 			*
 | |
| 			* Invalid opcode encountered.
 | |
| 			*
 | |
| 			*/
 | |
| 
 | |
| #ifdef DEBUG
 | |
| 			printf("\nINVALID OPCODE: 0x%.2X\n", cOpcode);
 | |
| #endif /* DEBUG */
 | |
| 
 | |
| 			return VME_INVALID_FILE;
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	/*
 | |
| 	*
 | |
| 	* Invalid exit point. Processing the token 'ENDVME' is the only
 | |
| 	* valid way to exit the embedded engine.
 | |
| 	*
 | |
| 	*/
 | |
| 
 | |
| 	return VME_INVALID_FILE;
 | |
| }
 | |
| 
 | |
| /*
 | |
|  *
 | |
|  * ispVMDataCode
 | |
|  *
 | |
|  * Processes the TDI/TDO/MASK/DMASK etc of an SIR/SDR command.
 | |
|  *
 | |
|  */
 | |
| 
 | |
| signed char ispVMDataCode()
 | |
| {
 | |
| 	/* 09/11/07 NN added local variables initialization */
 | |
| 	signed char cDataByte    = 0;
 | |
| 	signed char siDataSource = 0;  /*source of data from file by default*/
 | |
| 
 | |
| 	if (g_usDataType & HEAP_IN) {
 | |
| 		siDataSource = 1;  /*the source of data from memory*/
 | |
| 	}
 | |
| 
 | |
| 	/*
 | |
| 	*
 | |
| 	* Clear the data type register.
 | |
| 	*
 | |
| 	**/
 | |
| 
 | |
| 	g_usDataType &= ~(MASK_DATA + TDI_DATA +
 | |
| 		TDO_DATA + DMASK_DATA + CMASK_DATA);
 | |
| 
 | |
| 	/*
 | |
| 	 * Iterate through SIR/SDR command and look for TDI,
 | |
| 	 * TDO, MASK, etc.
 | |
| 	 */
 | |
| 
 | |
| 	while ((cDataByte = GetByte()) >= 0) {
 | |
| 			ispVMMemManager(cDataByte, g_usMaxSize);
 | |
| 			switch (cDataByte) {
 | |
| 			case TDI:
 | |
| 
 | |
| 				/*
 | |
| 				 * Store the maximum size of the TDI buffer.
 | |
| 				 * Used to convert VME to HEX.
 | |
| 				 */
 | |
| 
 | |
| 				if (g_usiDataSize > g_usTDISize) {
 | |
| 					g_usTDISize = g_usiDataSize;
 | |
| 				}
 | |
| 				/*
 | |
| 				 * Updated data type register to indicate that
 | |
| 				 * TDI data is currently being used. Process the
 | |
| 				 * data in the VME file into the TDI buffer.
 | |
| 				 */
 | |
| 
 | |
| 				g_usDataType |= TDI_DATA;
 | |
| 				ispVMData(g_pucInData);
 | |
| 				break;
 | |
| 			case XTDO:
 | |
| 
 | |
| 				/*
 | |
| 				 * Store the maximum size of the TDO buffer.
 | |
| 				 * Used to convert VME to HEX.
 | |
| 				 */
 | |
| 
 | |
| 				if (g_usiDataSize > g_usTDOSize) {
 | |
| 					g_usTDOSize = g_usiDataSize;
 | |
| 				}
 | |
| 
 | |
| 				/*
 | |
| 				 * Updated data type register to indicate that
 | |
| 				 * TDO data is currently being used.
 | |
| 				 */
 | |
| 
 | |
| 				g_usDataType |= TDO_DATA;
 | |
| 				break;
 | |
| 			case TDO:
 | |
| 
 | |
| 				/*
 | |
| 				 * Store the maximum size of the TDO buffer.
 | |
| 				 * Used to convert VME to HEX.
 | |
| 				 */
 | |
| 
 | |
| 				if (g_usiDataSize > g_usTDOSize) {
 | |
| 					g_usTDOSize = g_usiDataSize;
 | |
| 				}
 | |
| 
 | |
| 				/*
 | |
| 				 * Updated data type register to indicate
 | |
| 				 * that TDO data is currently being used.
 | |
| 				 * Process the data in the VME file into the
 | |
| 				 * TDO buffer.
 | |
| 				 */
 | |
| 
 | |
| 				g_usDataType |= TDO_DATA;
 | |
| 				ispVMData(g_pucOutData);
 | |
| 				break;
 | |
| 			case MASK:
 | |
| 
 | |
| 				/*
 | |
| 				 * Store the maximum size of the MASK buffer.
 | |
| 				 * Used to convert VME to HEX.
 | |
| 				 */
 | |
| 
 | |
| 				if (g_usiDataSize > g_usMASKSize) {
 | |
| 					g_usMASKSize = g_usiDataSize;
 | |
| 				}
 | |
| 
 | |
| 				/*
 | |
| 				 * Updated data type register to indicate that
 | |
| 				 * MASK data is currently being used. Process
 | |
| 				 * the data in the VME file into the MASK buffer
 | |
| 				 */
 | |
| 
 | |
| 				g_usDataType |= MASK_DATA;
 | |
| 				ispVMData(g_pucOutMaskData);
 | |
| 				break;
 | |
| 			case DMASK:
 | |
| 
 | |
| 				/*
 | |
| 				 * Store the maximum size of the DMASK buffer.
 | |
| 				 * Used to convert VME to HEX.
 | |
| 				 */
 | |
| 
 | |
| 				if (g_usiDataSize > g_usDMASKSize) {
 | |
| 					g_usDMASKSize = g_usiDataSize;
 | |
| 				}
 | |
| 
 | |
| 				/*
 | |
| 				 * Updated data type register to indicate that
 | |
| 				 * DMASK data is currently being used. Process
 | |
| 				 * the data in the VME file into the DMASK
 | |
| 				 * buffer.
 | |
| 				 */
 | |
| 
 | |
| 				g_usDataType |= DMASK_DATA;
 | |
| 				ispVMData(g_pucOutDMaskData);
 | |
| 				break;
 | |
| 			case CMASK:
 | |
| 
 | |
| 				/*
 | |
| 				 * Updated data type register to indicate that
 | |
| 				 * MASK data is currently being used. Process
 | |
| 				 * the data in the VME file into the MASK buffer
 | |
| 				 */
 | |
| 
 | |
| 				g_usDataType |= CMASK_DATA;
 | |
| 				ispVMData(g_pucOutMaskData);
 | |
| 				break;
 | |
| 			case CONTINUE:
 | |
| 				return 0;
 | |
| 			default:
 | |
| 				/*
 | |
| 				 * Encountered invalid opcode.
 | |
| 				 */
 | |
| 				return VME_INVALID_FILE;
 | |
| 			}
 | |
| 
 | |
| 			switch (cDataByte) {
 | |
| 			case TDI:
 | |
| 
 | |
| 				/*
 | |
| 				 * Left bit shift. Used when performing
 | |
| 				 * algorithm looping.
 | |
| 				 */
 | |
| 
 | |
| 				if (g_usFlowControl & SHIFTLEFT) {
 | |
| 					ispVMBitShift(SHL, g_usShiftValue);
 | |
| 					g_usFlowControl &= ~SHIFTLEFT;
 | |
| 				}
 | |
| 
 | |
| 				/*
 | |
| 				 * Right bit shift. Used when performing
 | |
| 				 * algorithm looping.
 | |
| 				 */
 | |
| 
 | |
| 				if (g_usFlowControl & SHIFTRIGHT) {
 | |
| 					ispVMBitShift(SHR, g_usShiftValue);
 | |
| 					g_usFlowControl &= ~SHIFTRIGHT;
 | |
| 				}
 | |
| 			default:
 | |
| 				break;
 | |
| 			}
 | |
| 
 | |
| 			if (siDataSource) {
 | |
| 				g_usDataType |= HEAP_IN; /*restore from memory*/
 | |
| 			}
 | |
| 	}
 | |
| 
 | |
| 	if (siDataSource) {  /*fetch data from heap memory upon return*/
 | |
| 		g_usDataType |= HEAP_IN;
 | |
| 	}
 | |
| 
 | |
| 	if (cDataByte < 0) {
 | |
| 
 | |
| 		/*
 | |
| 		 * Encountered invalid opcode.
 | |
| 		 */
 | |
| 
 | |
| 		return VME_INVALID_FILE;
 | |
| 	} else {
 | |
| 		return 0;
 | |
| 	}
 | |
| }
 | |
| 
 | |
| /*
 | |
|  *
 | |
|  * ispVMData
 | |
|  * Extract one row of data operand from the current data type opcode. Perform
 | |
|  * the decompression if necessary. Extra RAM is not required for the
 | |
|  * decompression process. The decompression scheme employed in this module
 | |
|  * is on row by row basis. The format of the data stream:
 | |
|  * [compression code][compressed data stream]
 | |
|  * 0x00    --No compression
 | |
|  * 0x01    --Compress by 0x00.
 | |
|  *           Example:
 | |
|  *           Original stream:   0x000000000000000000000001
 | |
|  *           Compressed stream: 0x01000901
 | |
|  *           Detail:            0x01 is the code, 0x00 is the key,
 | |
|  *                              0x09 is the count of 0x00 bytes,
 | |
|  *                              0x01 is the uncompressed byte.
 | |
|  * 0x02    --Compress by 0xFF.
 | |
|  *           Example:
 | |
|  *           Original stream:   0xFFFFFFFFFFFFFFFFFFFFFF01
 | |
|  *           Compressed stream: 0x02FF0901
 | |
|  *           Detail:            0x02 is the code, 0xFF is the key,
 | |
|  *                              0x09 is the count of 0xFF bytes,
 | |
|  *                              0x01 is the uncompressed byte.
 | |
|  * 0x03
 | |
|  * : :
 | |
|  * 0xFE   -- Compress by nibble blocks.
 | |
|  *           Example:
 | |
|  *           Original stream:   0x84210842108421084210
 | |
|  *           Compressed stream: 0x0584210
 | |
|  *           Detail:            0x05 is the code, means 5 nibbles block.
 | |
|  *                              0x84210 is the 5 nibble blocks.
 | |
|  *                              The whole row is 80 bits given by g_usiDataSize.
 | |
|  *                              The number of times the block repeat itself
 | |
|  *                              is found by g_usiDataSize/(4*0x05) which is 4.
 | |
|  * 0xFF   -- Compress by the most frequently happen byte.
 | |
|  *           Example:
 | |
|  *           Original stream:   0x04020401030904040404
 | |
|  *           Compressed stream: 0xFF04(0,1,0x02,0,1,0x01,1,0x03,1,0x09,0,0,0)
 | |
|  *                          or: 0xFF044090181C240
 | |
|  *           Detail:            0xFF is the code, 0x04 is the key.
 | |
|  *                              a bit of 0 represent the key shall be put into
 | |
|  *                              the current bit position and a bit of 1
 | |
|  *                              represent copying the next of 8 bits of data
 | |
|  *                              in.
 | |
|  *
 | |
|  */
 | |
| 
 | |
| void ispVMData(unsigned char *ByteData)
 | |
| {
 | |
| 	/* 09/11/07 NN added local variables initialization */
 | |
| 	unsigned short size               = 0;
 | |
| 	unsigned short i, j, m, getData   = 0;
 | |
| 	unsigned char cDataByte           = 0;
 | |
| 	unsigned char compress            = 0;
 | |
| 	unsigned short FFcount            = 0;
 | |
| 	unsigned char compr_char          = 0xFF;
 | |
| 	unsigned short index              = 0;
 | |
| 	signed char compression           = 0;
 | |
| 
 | |
| 	/*convert number in bits to bytes*/
 | |
| 	if (g_usiDataSize % 8 > 0) {
 | |
| 		/* 09/11/07 NN Type cast mismatch variables */
 | |
| 		size = (unsigned short)(g_usiDataSize / 8 + 1);
 | |
| 	} else {
 | |
| 		/* 09/11/07 NN Type cast mismatch variables */
 | |
| 		size = (unsigned short)(g_usiDataSize / 8);
 | |
| 	}
 | |
| 
 | |
| 	/*
 | |
| 	 * If there is compression, then check if compress by key
 | |
| 	 * of 0x00 or 0xFF or by other keys or by nibble blocks
 | |
| 	 */
 | |
| 
 | |
| 	if (g_usDataType & COMPRESS) {
 | |
| 		compression = 1;
 | |
| 		compress = GetByte();
 | |
| 		if ((compress  == VAR) && (g_usDataType & HEAP_IN)) {
 | |
| 			getData = 1;
 | |
| 			g_usDataType &= ~(HEAP_IN);
 | |
| 			compress = GetByte();
 | |
| 		}
 | |
| 
 | |
| 		switch (compress) {
 | |
| 		case 0x00:
 | |
| 			/* No compression */
 | |
| 			compression = 0;
 | |
| 			break;
 | |
| 		case 0x01:
 | |
| 			/* Compress by byte 0x00 */
 | |
| 			compr_char = 0x00;
 | |
| 			break;
 | |
| 		case 0x02:
 | |
| 			/* Compress by byte 0xFF */
 | |
| 			compr_char = 0xFF;
 | |
| 			break;
 | |
| 		case 0xFF:
 | |
| 			/* Huffman encoding */
 | |
| 			compr_char = GetByte();
 | |
| 			i = 8;
 | |
| 			for (index = 0; index < size; index++) {
 | |
| 				ByteData[index] = 0x00;
 | |
| 				if (i > 7) {
 | |
| 					cDataByte = GetByte();
 | |
| 					i = 0;
 | |
| 				}
 | |
| 				if ((cDataByte << i++) & 0x80)
 | |
| 					m = 8;
 | |
| 				else {
 | |
| 					ByteData[index] = compr_char;
 | |
| 					m = 0;
 | |
| 				}
 | |
| 
 | |
| 				for (j = 0; j < m; j++) {
 | |
| 					if (i > 7) {
 | |
| 						cDataByte = GetByte();
 | |
| 						i = 0;
 | |
| 					}
 | |
| 					ByteData[index] |=
 | |
| 					((cDataByte << i++) & 0x80) >> j;
 | |
| 				}
 | |
| 			}
 | |
| 			size = 0;
 | |
| 			break;
 | |
| 		default:
 | |
| 			for (index = 0; index < size; index++)
 | |
| 				ByteData[index] = 0x00;
 | |
| 			for (index = 0; index < compress; index++) {
 | |
| 				if (index % 2 == 0)
 | |
| 					cDataByte = GetByte();
 | |
| 				for (i = 0; i < size * 2 / compress; i++) {
 | |
| 					j = (unsigned short)(index +
 | |
| 						(i * (unsigned short)compress));
 | |
| 					/*clear the nibble to zero first*/
 | |
| 					if (j%2) {
 | |
| 						if (index % 2)
 | |
| 							ByteData[j/2] |=
 | |
| 								cDataByte & 0xF;
 | |
| 						else
 | |
| 							ByteData[j/2] |=
 | |
| 								cDataByte >> 4;
 | |
| 					} else {
 | |
| 						if (index % 2)
 | |
| 							ByteData[j/2] |=
 | |
| 								cDataByte << 4;
 | |
| 						else
 | |
| 							ByteData[j/2] |=
 | |
| 							cDataByte & 0xF0;
 | |
| 					}
 | |
| 				}
 | |
| 			}
 | |
| 			size = 0;
 | |
| 			break;
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	FFcount = 0;
 | |
| 
 | |
| 	/* Decompress by byte 0x00 or 0xFF */
 | |
| 	for (index = 0; index < size; index++) {
 | |
| 		if (FFcount <= 0) {
 | |
| 			cDataByte = GetByte();
 | |
| 			if ((cDataByte == VAR) && (g_usDataType&HEAP_IN) &&
 | |
| 				!getData && !(g_usDataType&COMPRESS)) {
 | |
| 				getData = 1;
 | |
| 				g_usDataType &= ~(HEAP_IN);
 | |
| 				cDataByte = GetByte();
 | |
| 			}
 | |
| 			ByteData[index] = cDataByte;
 | |
| 			if ((compression) && (cDataByte == compr_char))
 | |
| 				/* 09/11/07 NN Type cast mismatch variables */
 | |
| 				FFcount = (unsigned short) ispVMDataSize();
 | |
| 				/*The number of 0xFF or 0x00 bytes*/
 | |
| 		} else {
 | |
| 			FFcount--; /*Use up the 0xFF chain first*/
 | |
| 			ByteData[index] = compr_char;
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	if (getData) {
 | |
| 		g_usDataType |= HEAP_IN;
 | |
| 		getData = 0;
 | |
| 	}
 | |
| }
 | |
| 
 | |
| /*
 | |
|  *
 | |
|  * ispVMShift
 | |
|  *
 | |
|  * Processes the SDR/XSDR/SIR commands.
 | |
|  *
 | |
|  */
 | |
| 
 | |
| signed char ispVMShift(signed char a_cCode)
 | |
| {
 | |
| 	/* 09/11/07 NN added local variables initialization */
 | |
| 	unsigned short iDataIndex  = 0;
 | |
| 	unsigned short iReadLoop   = 0;
 | |
| 	signed char cRetCode       = 0;
 | |
| 
 | |
| 	cRetCode = 0;
 | |
| 	/* 09/11/07 NN Type cast mismatch variables */
 | |
| 	g_usiDataSize = (unsigned short) ispVMDataSize();
 | |
| 
 | |
| 	/*clear the flags first*/
 | |
| 	g_usDataType &= ~(SIR_DATA + EXPRESS + SDR_DATA);
 | |
| 	switch (a_cCode) {
 | |
| 	case SIR:
 | |
| 		g_usDataType |= SIR_DATA;
 | |
| 		/*
 | |
| 		 * 1/15/04 If performing cascading, then go directly to SHIFTIR.
 | |
| 		 *  Else, go to IRPAUSE before going to SHIFTIR
 | |
| 		 */
 | |
| 		if (g_usFlowControl & CASCADE) {
 | |
| 			ispVMStateMachine(SHIFTIR);
 | |
| 		} else {
 | |
| 			ispVMStateMachine(IRPAUSE);
 | |
| 			ispVMStateMachine(SHIFTIR);
 | |
| 			if (g_usHeadIR > 0) {
 | |
| 				ispVMBypass(HIR, g_usHeadIR);
 | |
| 				sclock();
 | |
| 			}
 | |
| 		}
 | |
| 		break;
 | |
| 	case XSDR:
 | |
| 		g_usDataType |= EXPRESS; /*mark simultaneous in and out*/
 | |
| 	case SDR:
 | |
| 		g_usDataType |= SDR_DATA;
 | |
| 		/*
 | |
| 		 * 1/15/04 If already in SHIFTDR, then do not move state or
 | |
| 		 * shift in header.  This would imply that the previously
 | |
| 		 * shifted frame was a cascaded frame.
 | |
| 		 */
 | |
| 		if (g_cCurrentJTAGState != SHIFTDR) {
 | |
| 			/*
 | |
| 			 * 1/15/04 If performing cascading, then go directly
 | |
| 			 * to SHIFTDR.  Else, go to DRPAUSE before going
 | |
| 			 * to SHIFTDR
 | |
| 			 */
 | |
| 			if (g_usFlowControl & CASCADE) {
 | |
| 				if (g_cCurrentJTAGState == DRPAUSE) {
 | |
| 					ispVMStateMachine(SHIFTDR);
 | |
| 					/*
 | |
| 					 * 1/15/04 If cascade flag has been seat
 | |
| 					 * and the current state is DRPAUSE,
 | |
| 					 * this implies that the first cascaded
 | |
| 					 * frame is about to be shifted in.  The
 | |
| 					 * header must be shifted prior to
 | |
| 					 * shifting the first cascaded frame.
 | |
| 					 */
 | |
| 					if (g_usHeadDR > 0) {
 | |
| 						ispVMBypass(HDR, g_usHeadDR);
 | |
| 						sclock();
 | |
| 					}
 | |
| 				} else {
 | |
| 					ispVMStateMachine(SHIFTDR);
 | |
| 				}
 | |
| 			} else {
 | |
| 				ispVMStateMachine(DRPAUSE);
 | |
| 				ispVMStateMachine(SHIFTDR);
 | |
| 				if (g_usHeadDR > 0) {
 | |
| 					ispVMBypass(HDR, g_usHeadDR);
 | |
| 					sclock();
 | |
| 				}
 | |
| 			}
 | |
| 		}
 | |
| 		break;
 | |
| 	default:
 | |
| 		return VME_INVALID_FILE;
 | |
| 	}
 | |
| 
 | |
| 	cRetCode = ispVMDataCode();
 | |
| 
 | |
| 	if (cRetCode != 0) {
 | |
| 		return VME_INVALID_FILE;
 | |
| 	}
 | |
| 
 | |
| #ifdef DEBUG
 | |
| 	printf("%d ", g_usiDataSize);
 | |
| 
 | |
| 	if (g_usDataType & TDI_DATA) {
 | |
| 		puts("TDI ");
 | |
| 		PrintData(g_usiDataSize, g_pucInData);
 | |
| 	}
 | |
| 
 | |
| 	if (g_usDataType & TDO_DATA) {
 | |
| 		puts("\n\t\tTDO ");
 | |
| 		PrintData(g_usiDataSize, g_pucOutData);
 | |
| 	}
 | |
| 
 | |
| 	if (g_usDataType & MASK_DATA) {
 | |
| 		puts("\n\t\tMASK ");
 | |
| 		PrintData(g_usiDataSize, g_pucOutMaskData);
 | |
| 	}
 | |
| 
 | |
| 	if (g_usDataType & DMASK_DATA) {
 | |
| 		puts("\n\t\tDMASK ");
 | |
| 		PrintData(g_usiDataSize, g_pucOutDMaskData);
 | |
| 	}
 | |
| 
 | |
| 	puts(";\n");
 | |
| #endif /* DEBUG */
 | |
| 
 | |
| 	if (g_usDataType & TDO_DATA || g_usDataType & DMASK_DATA) {
 | |
| 		if (g_usDataType & DMASK_DATA) {
 | |
| 			cRetCode = ispVMReadandSave(g_usiDataSize);
 | |
| 			if (!cRetCode) {
 | |
| 				if (g_usTailDR > 0) {
 | |
| 					sclock();
 | |
| 					ispVMBypass(TDR, g_usTailDR);
 | |
| 				}
 | |
| 				ispVMStateMachine(DRPAUSE);
 | |
| 				ispVMStateMachine(SHIFTDR);
 | |
| 				if (g_usHeadDR > 0) {
 | |
| 					ispVMBypass(HDR, g_usHeadDR);
 | |
| 					sclock();
 | |
| 				}
 | |
| 				for (iDataIndex = 0;
 | |
| 					iDataIndex < g_usiDataSize / 8 + 1;
 | |
| 					iDataIndex++)
 | |
| 					g_pucInData[iDataIndex] =
 | |
| 						g_pucOutData[iDataIndex];
 | |
| 				g_usDataType &= ~(TDO_DATA + DMASK_DATA);
 | |
| 				cRetCode = ispVMSend(g_usiDataSize);
 | |
| 			}
 | |
| 		} else {
 | |
| 			cRetCode = ispVMRead(g_usiDataSize);
 | |
| 			if (cRetCode == -1 && g_cVendor == XILINX) {
 | |
| 				for (iReadLoop = 0; iReadLoop < 30;
 | |
| 					iReadLoop++) {
 | |
| 					cRetCode = ispVMRead(g_usiDataSize);
 | |
| 					if (!cRetCode) {
 | |
| 						break;
 | |
| 					} else {
 | |
| 						/* Always DRPAUSE */
 | |
| 						ispVMStateMachine(DRPAUSE);
 | |
| 						/*
 | |
| 						 * Bypass other devices
 | |
| 						 * when appropriate
 | |
| 						 */
 | |
| 						ispVMBypass(TDR, g_usTailDR);
 | |
| 						ispVMStateMachine(g_ucEndDR);
 | |
| 						ispVMStateMachine(IDLE);
 | |
| 						ispVMDelay(1000);
 | |
| 					}
 | |
| 				}
 | |
| 			}
 | |
| 		}
 | |
| 	} else { /*TDI only*/
 | |
| 		cRetCode = ispVMSend(g_usiDataSize);
 | |
| 	}
 | |
| 
 | |
| 	/*transfer the input data to the output buffer for the next verify*/
 | |
| 	if ((g_usDataType & EXPRESS) || (a_cCode == SDR)) {
 | |
| 		if (g_pucOutData) {
 | |
| 			for (iDataIndex = 0; iDataIndex < g_usiDataSize / 8 + 1;
 | |
| 				iDataIndex++)
 | |
| 				g_pucOutData[iDataIndex] =
 | |
| 					g_pucInData[iDataIndex];
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	switch (a_cCode) {
 | |
| 	case SIR:
 | |
| 		/* 1/15/04 If not performing cascading, then shift ENDIR */
 | |
| 		if (!(g_usFlowControl & CASCADE)) {
 | |
| 			if (g_usTailIR > 0) {
 | |
| 				sclock();
 | |
| 				ispVMBypass(TIR, g_usTailIR);
 | |
| 			}
 | |
| 			ispVMStateMachine(g_ucEndIR);
 | |
| 		}
 | |
| 		break;
 | |
| 	case XSDR:
 | |
| 	case SDR:
 | |
| 		/* 1/15/04 If not performing cascading, then shift ENDDR */
 | |
| 		if (!(g_usFlowControl & CASCADE)) {
 | |
| 			if (g_usTailDR > 0) {
 | |
| 				sclock();
 | |
| 				ispVMBypass(TDR, g_usTailDR);
 | |
| 			}
 | |
| 			ispVMStateMachine(g_ucEndDR);
 | |
| 		}
 | |
| 		break;
 | |
| 	default:
 | |
| 		break;
 | |
| 	}
 | |
| 
 | |
| 	return cRetCode;
 | |
| }
 | |
| 
 | |
| /*
 | |
|  *
 | |
|  * ispVMAmble
 | |
|  *
 | |
|  * This routine is to extract Header and Trailer parameter for SIR and
 | |
|  * SDR operations.
 | |
|  *
 | |
|  * The Header and Trailer parameter are the pre-amble and post-amble bit
 | |
|  * stream need to be shifted into TDI or out of TDO of the devices. Mostly
 | |
|  * is for the purpose of bypassing the leading or trailing devices. ispVM
 | |
|  * supports only shifting data into TDI to bypass the devices.
 | |
|  *
 | |
|  * For a single device, the header and trailer parameters are all set to 0
 | |
|  * as default by ispVM. If it is for multiple devices, the header and trailer
 | |
|  * value will change as specified by the VME file.
 | |
|  *
 | |
|  */
 | |
| 
 | |
| signed char ispVMAmble(signed char Code)
 | |
| {
 | |
| 	signed char compress = 0;
 | |
| 	/* 09/11/07 NN Type cast mismatch variables */
 | |
| 	g_usiDataSize = (unsigned short)ispVMDataSize();
 | |
| 
 | |
| #ifdef DEBUG
 | |
| 	printf("%d", g_usiDataSize);
 | |
| #endif /* DEBUG */
 | |
| 
 | |
| 	if (g_usiDataSize) {
 | |
| 
 | |
| 		/*
 | |
| 		 * Discard the TDI byte and set the compression bit in the data
 | |
| 		 * type register to false if compression is set because TDI data
 | |
| 		 * after HIR/HDR/TIR/TDR is not compressed.
 | |
| 		 */
 | |
| 
 | |
| 		GetByte();
 | |
| 		if (g_usDataType & COMPRESS) {
 | |
| 			g_usDataType &= ~(COMPRESS);
 | |
| 			compress = 1;
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	switch (Code) {
 | |
| 	case HIR:
 | |
| 
 | |
| 		/*
 | |
| 		 * Store the maximum size of the HIR buffer.
 | |
| 		 * Used to convert VME to HEX.
 | |
| 		 */
 | |
| 
 | |
| 		if (g_usiDataSize > g_usHIRSize) {
 | |
| 			g_usHIRSize = g_usiDataSize;
 | |
| 		}
 | |
| 
 | |
| 		/*
 | |
| 		 * Assign the HIR value and allocate memory.
 | |
| 		 */
 | |
| 
 | |
| 		g_usHeadIR = g_usiDataSize;
 | |
| 		if (g_usHeadIR) {
 | |
| 			ispVMMemManager(HIR, g_usHeadIR);
 | |
| 			ispVMData(g_pucHIRData);
 | |
| 
 | |
| #ifdef DEBUG
 | |
| 			puts(" TDI ");
 | |
| 			PrintData(g_usHeadIR, g_pucHIRData);
 | |
| #endif /* DEBUG */
 | |
| 		}
 | |
| 		break;
 | |
| 	case TIR:
 | |
| 
 | |
| 		/*
 | |
| 		 * Store the maximum size of the TIR buffer.
 | |
| 		 * Used to convert VME to HEX.
 | |
| 		 */
 | |
| 
 | |
| 		if (g_usiDataSize > g_usTIRSize) {
 | |
| 			g_usTIRSize = g_usiDataSize;
 | |
| 		}
 | |
| 
 | |
| 		/*
 | |
| 		 * Assign the TIR value and allocate memory.
 | |
| 		 */
 | |
| 
 | |
| 		g_usTailIR = g_usiDataSize;
 | |
| 		if (g_usTailIR) {
 | |
| 			ispVMMemManager(TIR, g_usTailIR);
 | |
| 			ispVMData(g_pucTIRData);
 | |
| 
 | |
| #ifdef DEBUG
 | |
| 			puts(" TDI ");
 | |
| 			PrintData(g_usTailIR, g_pucTIRData);
 | |
| #endif /* DEBUG */
 | |
| 		}
 | |
| 		break;
 | |
| 	case HDR:
 | |
| 
 | |
| 		/*
 | |
| 		 * Store the maximum size of the HDR buffer.
 | |
| 		 * Used to convert VME to HEX.
 | |
| 		 */
 | |
| 
 | |
| 		if (g_usiDataSize > g_usHDRSize) {
 | |
| 			g_usHDRSize = g_usiDataSize;
 | |
| 		}
 | |
| 
 | |
| 		/*
 | |
| 		 * Assign the HDR value and allocate memory.
 | |
| 		 *
 | |
| 		 */
 | |
| 
 | |
| 		g_usHeadDR = g_usiDataSize;
 | |
| 		if (g_usHeadDR) {
 | |
| 			ispVMMemManager(HDR, g_usHeadDR);
 | |
| 			ispVMData(g_pucHDRData);
 | |
| 
 | |
| #ifdef DEBUG
 | |
| 			puts(" TDI ");
 | |
| 			PrintData(g_usHeadDR, g_pucHDRData);
 | |
| #endif /* DEBUG */
 | |
| 		}
 | |
| 		break;
 | |
| 	case TDR:
 | |
| 
 | |
| 		/*
 | |
| 		 * Store the maximum size of the TDR buffer.
 | |
| 		 * Used to convert VME to HEX.
 | |
| 		 */
 | |
| 
 | |
| 		if (g_usiDataSize > g_usTDRSize) {
 | |
| 			g_usTDRSize = g_usiDataSize;
 | |
| 		}
 | |
| 
 | |
| 		/*
 | |
| 		 * Assign the TDR value and allocate memory.
 | |
| 		 *
 | |
| 		 */
 | |
| 
 | |
| 		g_usTailDR = g_usiDataSize;
 | |
| 		if (g_usTailDR) {
 | |
| 			ispVMMemManager(TDR, g_usTailDR);
 | |
| 			ispVMData(g_pucTDRData);
 | |
| 
 | |
| #ifdef DEBUG
 | |
| 			puts(" TDI ");
 | |
| 			PrintData(g_usTailDR, g_pucTDRData);
 | |
| #endif /* DEBUG */
 | |
| 		}
 | |
| 		break;
 | |
| 	default:
 | |
| 		break;
 | |
| 	}
 | |
| 
 | |
| 	/*
 | |
| 	*
 | |
| 	* Re-enable compression if it was previously set.
 | |
| 	*
 | |
| 	**/
 | |
| 
 | |
| 	if (compress) {
 | |
| 		g_usDataType |= COMPRESS;
 | |
| 	}
 | |
| 
 | |
| 	if (g_usiDataSize) {
 | |
| 		Code = GetByte();
 | |
| 		if (Code == CONTINUE) {
 | |
| 			return 0;
 | |
| 		} else {
 | |
| 
 | |
| 			/*
 | |
| 			 * Encountered invalid opcode.
 | |
| 			 */
 | |
| 
 | |
| 			return VME_INVALID_FILE;
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	return 0;
 | |
| }
 | |
| 
 | |
| /*
 | |
|  *
 | |
|  * ispVMLoop
 | |
|  *
 | |
|  * Perform the function call upon by the REPEAT opcode.
 | |
|  * Memory is to be allocated to store the entire loop from REPEAT to ENDLOOP.
 | |
|  * After the loop is stored then execution begin. The REPEATLOOP flag is set
 | |
|  * on the g_usFlowControl register to indicate the repeat loop is in session
 | |
|  * and therefore fetch opcode from the memory instead of from the file.
 | |
|  *
 | |
|  */
 | |
| 
 | |
| signed char ispVMLoop(unsigned short a_usLoopCount)
 | |
| {
 | |
| 	/* 09/11/07 NN added local variables initialization */
 | |
| 	signed char cRetCode      = 0;
 | |
| 	unsigned short iHeapIndex = 0;
 | |
| 	unsigned short iLoopIndex = 0;
 | |
| 
 | |
| 	g_usShiftValue = 0;
 | |
| 	for (iHeapIndex = 0; iHeapIndex < g_iHEAPSize; iHeapIndex++) {
 | |
| 		g_pucHeapMemory[iHeapIndex] = GetByte();
 | |
| 	}
 | |
| 
 | |
| 	if (g_pucHeapMemory[iHeapIndex - 1] != ENDLOOP) {
 | |
| 		return VME_INVALID_FILE;
 | |
| 	}
 | |
| 
 | |
| 	g_usFlowControl |= REPEATLOOP;
 | |
| 	g_usDataType |= HEAP_IN;
 | |
| 
 | |
| 	for (iLoopIndex = 0; iLoopIndex < a_usLoopCount; iLoopIndex++) {
 | |
| 		g_iHeapCounter = 0;
 | |
| 		cRetCode = ispVMCode();
 | |
| 		g_usRepeatLoops++;
 | |
| 		if (cRetCode < 0) {
 | |
| 			break;
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	g_usDataType &= ~(HEAP_IN);
 | |
| 	g_usFlowControl &= ~(REPEATLOOP);
 | |
| 	return cRetCode;
 | |
| }
 | |
| 
 | |
| /*
 | |
|  *
 | |
|  * ispVMBitShift
 | |
|  *
 | |
|  * Shift the TDI stream left or right by the number of bits. The data in
 | |
|  * *g_pucInData is of the VME format, so the actual shifting is the reverse of
 | |
|  * IEEE 1532 or SVF format.
 | |
|  *
 | |
|  */
 | |
| 
 | |
| signed char ispVMBitShift(signed char mode, unsigned short bits)
 | |
| {
 | |
| 	/* 09/11/07 NN added local variables initialization */
 | |
| 	unsigned short i       = 0;
 | |
| 	unsigned short size    = 0;
 | |
| 	unsigned short tmpbits = 0;
 | |
| 
 | |
| 	if (g_usiDataSize % 8 > 0) {
 | |
| 		/* 09/11/07 NN Type cast mismatch variables */
 | |
| 		size = (unsigned short)(g_usiDataSize / 8 + 1);
 | |
| 	} else {
 | |
| 		/* 09/11/07 NN Type cast mismatch variables */
 | |
| 		size = (unsigned short)(g_usiDataSize / 8);
 | |
| 	}
 | |
| 
 | |
| 	switch (mode) {
 | |
| 	case SHR:
 | |
| 		for (i = 0; i < size; i++) {
 | |
| 			if (g_pucInData[i] != 0) {
 | |
| 				tmpbits = bits;
 | |
| 				while (tmpbits > 0) {
 | |
| 					g_pucInData[i] <<= 1;
 | |
| 					if (g_pucInData[i] == 0) {
 | |
| 						i--;
 | |
| 						g_pucInData[i] = 1;
 | |
| 					}
 | |
| 					tmpbits--;
 | |
| 				}
 | |
| 			}
 | |
| 		}
 | |
| 		break;
 | |
| 	case SHL:
 | |
| 		for (i = 0; i < size; i++) {
 | |
| 			if (g_pucInData[i] != 0) {
 | |
| 				tmpbits = bits;
 | |
| 				while (tmpbits > 0) {
 | |
| 					g_pucInData[i] >>= 1;
 | |
| 					if (g_pucInData[i] == 0) {
 | |
| 						i--;
 | |
| 						g_pucInData[i] = 8;
 | |
| 					}
 | |
| 					tmpbits--;
 | |
| 				}
 | |
| 			}
 | |
| 		}
 | |
| 		break;
 | |
| 	default:
 | |
| 		return VME_INVALID_FILE;
 | |
| 	}
 | |
| 
 | |
| 	return 0;
 | |
| }
 | |
| 
 | |
| /*
 | |
|  *
 | |
|  * ispVMComment
 | |
|  *
 | |
|  * Displays the SVF comments.
 | |
|  *
 | |
|  */
 | |
| 
 | |
| void ispVMComment(unsigned short a_usCommentSize)
 | |
| {
 | |
| 	char cCurByte = 0;
 | |
| 	for (; a_usCommentSize > 0; a_usCommentSize--) {
 | |
| 		/*
 | |
| 		*
 | |
| 		* Print character to the terminal.
 | |
| 		*
 | |
| 		**/
 | |
| 		cCurByte = GetByte();
 | |
| 		vme_out_char(cCurByte);
 | |
| 	}
 | |
| 	cCurByte = '\n';
 | |
| 	vme_out_char(cCurByte);
 | |
| }
 | |
| 
 | |
| /*
 | |
|  *
 | |
|  * ispVMHeader
 | |
|  *
 | |
|  * Iterate the length of the header and discard it.
 | |
|  *
 | |
|  */
 | |
| 
 | |
| void ispVMHeader(unsigned short a_usHeaderSize)
 | |
| {
 | |
| 	for (; a_usHeaderSize > 0; a_usHeaderSize--) {
 | |
| 		GetByte();
 | |
| 	}
 | |
| }
 | |
| 
 | |
| /*
 | |
|  *
 | |
|  * ispVMCalculateCRC32
 | |
|  *
 | |
|  * Calculate the 32-bit CRC.
 | |
|  *
 | |
|  */
 | |
| 
 | |
| void ispVMCalculateCRC32(unsigned char a_ucData)
 | |
| {
 | |
| 	/* 09/11/07 NN added local variables initialization */
 | |
| 	unsigned char ucIndex          = 0;
 | |
| 	unsigned char ucFlipData       = 0;
 | |
| 	unsigned short usCRCTableEntry = 0;
 | |
| 	unsigned int crc_table[16] = {
 | |
| 		0x0000, 0xCC01, 0xD801,
 | |
| 		0x1400, 0xF001, 0x3C00,
 | |
| 		0x2800, 0xE401, 0xA001,
 | |
| 		0x6C00, 0x7800, 0xB401,
 | |
| 		0x5000, 0x9C01, 0x8801,
 | |
| 		0x4400
 | |
| 	};
 | |
| 
 | |
| 	for (ucIndex = 0; ucIndex < 8; ucIndex++) {
 | |
| 		ucFlipData <<= 1;
 | |
| 		if (a_ucData & 0x01) {
 | |
| 			ucFlipData |= 0x01;
 | |
| 		}
 | |
| 		a_ucData >>= 1;
 | |
| 	}
 | |
| 
 | |
| 	/* 09/11/07 NN Type cast mismatch variables */
 | |
| 	usCRCTableEntry = (unsigned short)(crc_table[g_usCalculatedCRC & 0xF]);
 | |
| 	g_usCalculatedCRC = (unsigned short)((g_usCalculatedCRC >> 4) & 0x0FFF);
 | |
| 	g_usCalculatedCRC = (unsigned short)(g_usCalculatedCRC ^
 | |
| 			usCRCTableEntry ^ crc_table[ucFlipData & 0xF]);
 | |
| 	usCRCTableEntry = (unsigned short)(crc_table[g_usCalculatedCRC & 0xF]);
 | |
| 	g_usCalculatedCRC = (unsigned short)((g_usCalculatedCRC >> 4) & 0x0FFF);
 | |
| 	g_usCalculatedCRC = (unsigned short)(g_usCalculatedCRC ^
 | |
| 		usCRCTableEntry ^ crc_table[(ucFlipData >> 4) & 0xF]);
 | |
| }
 | |
| 
 | |
| /*
 | |
|  *
 | |
|  * ispVMLCOUNT
 | |
|  *
 | |
|  * Process the intelligent programming loops.
 | |
|  *
 | |
|  */
 | |
| 
 | |
| signed char ispVMLCOUNT(unsigned short a_usCountSize)
 | |
| {
 | |
| 	unsigned short usContinue	  = 1;
 | |
| 	unsigned short usIntelBufferIndex = 0;
 | |
| 	unsigned short usCountIndex       = 0;
 | |
| 	signed char cRetCode              = 0;
 | |
| 	signed char cRepeatHeap           = 0;
 | |
| 	signed char cOpcode               = 0;
 | |
| 	unsigned char ucState             = 0;
 | |
| 	unsigned short usDelay            = 0;
 | |
| 	unsigned short usToggle           = 0;
 | |
| 
 | |
| 	g_usIntelBufferSize = (unsigned short)ispVMDataSize();
 | |
| 
 | |
| 	/*
 | |
| 	 * Allocate memory for intel buffer.
 | |
| 	 *
 | |
| 	 */
 | |
| 
 | |
| 	ispVMMemManager(LHEAP, g_usIntelBufferSize);
 | |
| 
 | |
| 	/*
 | |
| 	 * Store the maximum size of the intelligent buffer.
 | |
| 	 * Used to convert VME to HEX.
 | |
| 	 */
 | |
| 
 | |
| 	if (g_usIntelBufferSize > g_usLCOUNTSize) {
 | |
| 		g_usLCOUNTSize = g_usIntelBufferSize;
 | |
| 	}
 | |
| 
 | |
| 	/*
 | |
| 	 * Copy intel data to the buffer.
 | |
| 	 */
 | |
| 
 | |
| 	for (usIntelBufferIndex = 0; usIntelBufferIndex < g_usIntelBufferSize;
 | |
| 		usIntelBufferIndex++) {
 | |
| 		g_pucIntelBuffer[usIntelBufferIndex] = GetByte();
 | |
| 	}
 | |
| 
 | |
| 	/*
 | |
| 	 * Set the data type register to get data from the intelligent
 | |
| 	 * data buffer.
 | |
| 	 */
 | |
| 
 | |
| 	g_usDataType |= LHEAP_IN;
 | |
| 
 | |
| 	/*
 | |
| 	*
 | |
| 	* If the HEAP_IN flag is set, temporarily unset the flag so data will be
 | |
| 	* retrieved from the status buffer.
 | |
| 	*
 | |
| 	**/
 | |
| 
 | |
| 	if (g_usDataType & HEAP_IN) {
 | |
| 		g_usDataType &= ~HEAP_IN;
 | |
| 		cRepeatHeap = 1;
 | |
| 	}
 | |
| 
 | |
| #ifdef DEBUG
 | |
| 	printf("LCOUNT %d;\n", a_usCountSize);
 | |
| #endif /* DEBUG */
 | |
| 
 | |
| 	/*
 | |
| 	 * Iterate through the intelligent programming command.
 | |
| 	*/
 | |
| 
 | |
| 	for (usCountIndex = 0; usCountIndex < a_usCountSize; usCountIndex++) {
 | |
| 
 | |
| 		/*
 | |
| 		*
 | |
| 		* Initialize the intel data index to 0 before each iteration.
 | |
| 		*
 | |
| 		**/
 | |
| 
 | |
| 		g_usIntelDataIndex = 0;
 | |
| 		cOpcode            = 0;
 | |
| 		ucState            = 0;
 | |
| 		usDelay            = 0;
 | |
| 		usToggle           = 0;
 | |
| 		usContinue		   = 1;
 | |
| 
 | |
| 		/*
 | |
| 		*
 | |
| 		* Begin looping through all the VME opcodes.
 | |
| 		*
 | |
| 		*/
 | |
| 		/*
 | |
| 		* 4/1/09 Nguyen replaced the recursive function call codes on
 | |
| 		*        the ispVMLCOUNT function
 | |
| 		*
 | |
| 		*/
 | |
| 		while (usContinue) {
 | |
| 			cOpcode = GetByte();
 | |
| 			switch (cOpcode) {
 | |
| 			case HIR:
 | |
| 			case TIR:
 | |
| 			case HDR:
 | |
| 			case TDR:
 | |
| 				/*
 | |
| 				 * Set the header/trailer of the device in order
 | |
| 				 * to bypass successfully.
 | |
| 				 */
 | |
| 
 | |
| 				ispVMAmble(cOpcode);
 | |
| 			break;
 | |
| 			case STATE:
 | |
| 
 | |
| 				/*
 | |
| 				 * Step the JTAG state machine.
 | |
| 				 */
 | |
| 
 | |
| 				ucState = GetByte();
 | |
| 				/*
 | |
| 				 * Step the JTAG state machine to DRCAPTURE
 | |
| 				 * to support Looping.
 | |
| 				 */
 | |
| 
 | |
| 				if ((g_usDataType & LHEAP_IN) &&
 | |
| 					 (ucState == DRPAUSE) &&
 | |
| 					 (g_cCurrentJTAGState == ucState)) {
 | |
| 					ispVMStateMachine(DRCAPTURE);
 | |
| 				}
 | |
| 				ispVMStateMachine(ucState);
 | |
| #ifdef DEBUG
 | |
| 				printf("LDELAY %s ", GetState(ucState));
 | |
| #endif /* DEBUG */
 | |
| 				break;
 | |
| 			case SIR:
 | |
| #ifdef DEBUG
 | |
| 				printf("SIR ");
 | |
| #endif /* DEBUG */
 | |
| 				/*
 | |
| 				 * Shift in data into the device.
 | |
| 				 */
 | |
| 
 | |
| 				cRetCode = ispVMShift(cOpcode);
 | |
| 				break;
 | |
| 			case SDR:
 | |
| 
 | |
| #ifdef DEBUG
 | |
| 				printf("LSDR ");
 | |
| #endif /* DEBUG */
 | |
| 				/*
 | |
| 				 * Shift in data into the device.
 | |
| 				 */
 | |
| 
 | |
| 				cRetCode = ispVMShift(cOpcode);
 | |
| 				break;
 | |
| 			case WAIT:
 | |
| 
 | |
| 				/*
 | |
| 				*
 | |
| 				* Observe delay.
 | |
| 				*
 | |
| 				*/
 | |
| 
 | |
| 				usDelay = (unsigned short)ispVMDataSize();
 | |
| 				ispVMDelay(usDelay);
 | |
| 
 | |
| #ifdef DEBUG
 | |
| 				if (usDelay & 0x8000) {
 | |
| 
 | |
| 					/*
 | |
| 					 * Since MSB is set, the delay time must
 | |
| 					 * be decoded to millisecond. The
 | |
| 					 * SVF2VME encodes the MSB to represent
 | |
| 					 * millisecond.
 | |
| 					 */
 | |
| 
 | |
| 					usDelay &= ~0x8000;
 | |
| 					printf("%.2E SEC;\n",
 | |
| 						(float) usDelay / 1000);
 | |
| 				} else {
 | |
| 					/*
 | |
| 					 * Since MSB is not set, the delay time
 | |
| 					 * is given as microseconds.
 | |
| 					 */
 | |
| 
 | |
| 					printf("%.2E SEC;\n",
 | |
| 						(float) usDelay / 1000000);
 | |
| 				}
 | |
| #endif /* DEBUG */
 | |
| 				break;
 | |
| 			case TCK:
 | |
| 
 | |
| 				/*
 | |
| 				 * Issue clock toggles.
 | |
| 				 */
 | |
| 
 | |
| 				usToggle = (unsigned short)ispVMDataSize();
 | |
| 				ispVMClocks(usToggle);
 | |
| 
 | |
| #ifdef DEBUG
 | |
| 				printf("RUNTEST %d TCK;\n", usToggle);
 | |
| #endif /* DEBUG */
 | |
| 				break;
 | |
| 			case ENDLOOP:
 | |
| 
 | |
| 				/*
 | |
| 				 * Exit point from processing loops.
 | |
| 				 */
 | |
| 				usContinue = 0;
 | |
| 				break;
 | |
| 
 | |
| 			case COMMENT:
 | |
| 
 | |
| 				/*
 | |
| 				 * Display comment.
 | |
| 				 */
 | |
| 
 | |
| 				ispVMComment((unsigned short) ispVMDataSize());
 | |
| 				break;
 | |
| 			case ispEN:
 | |
| 				ucState = GetByte();
 | |
| 				if ((ucState == ON) || (ucState == 0x01))
 | |
| 					writePort(g_ucPinENABLE, 0x01);
 | |
| 				else
 | |
| 					writePort(g_ucPinENABLE, 0x00);
 | |
| 				ispVMDelay(1);
 | |
| 				break;
 | |
| 			case TRST:
 | |
| 				if (GetByte() == 0x01)
 | |
| 					writePort(g_ucPinTRST, 0x01);
 | |
| 				else
 | |
| 					writePort(g_ucPinTRST, 0x00);
 | |
| 				ispVMDelay(1);
 | |
| 				break;
 | |
| 			default:
 | |
| 
 | |
| 				/*
 | |
| 				 * Invalid opcode encountered.
 | |
| 				 */
 | |
| 
 | |
| 				debug("\nINVALID OPCODE: 0x%.2X\n", cOpcode);
 | |
| 
 | |
| 				return VME_INVALID_FILE;
 | |
| 			}
 | |
| 		}
 | |
| 		if (cRetCode >= 0) {
 | |
| 			/*
 | |
| 			 * Break if intelligent programming is successful.
 | |
| 			 */
 | |
| 
 | |
| 			break;
 | |
| 		}
 | |
| 
 | |
| 	}
 | |
| 	/*
 | |
| 	 * If HEAP_IN flag was temporarily disabled,
 | |
| 	 * re-enable it before exiting
 | |
| 	 */
 | |
| 
 | |
| 	if (cRepeatHeap) {
 | |
| 		g_usDataType |= HEAP_IN;
 | |
| 	}
 | |
| 
 | |
| 	/*
 | |
| 	 * Set the data type register to not get data from the
 | |
| 	 * intelligent data buffer.
 | |
| 	 */
 | |
| 
 | |
| 	g_usDataType &= ~LHEAP_IN;
 | |
| 	return cRetCode;
 | |
| }
 | |
| /*
 | |
|  *
 | |
|  * ispVMClocks
 | |
|  *
 | |
|  * Applies the specified number of pulses to TCK.
 | |
|  *
 | |
|  */
 | |
| 
 | |
| void ispVMClocks(unsigned short Clocks)
 | |
| {
 | |
| 	unsigned short iClockIndex = 0;
 | |
| 	for (iClockIndex = 0; iClockIndex < Clocks; iClockIndex++) {
 | |
| 		sclock();
 | |
| 	}
 | |
| }
 | |
| 
 | |
| /*
 | |
|  *
 | |
|  * ispVMBypass
 | |
|  *
 | |
|  * This procedure takes care of the HIR, HDR, TIR, TDR for the
 | |
|  * purpose of putting the other devices into Bypass mode. The
 | |
|  * current state is checked to find out if it is at DRPAUSE or
 | |
|  * IRPAUSE. If it is at DRPAUSE, perform bypass register scan.
 | |
|  * If it is at IRPAUSE, scan into instruction registers the bypass
 | |
|  * instruction.
 | |
|  *
 | |
|  */
 | |
| 
 | |
| void ispVMBypass(signed char ScanType, unsigned short Bits)
 | |
| {
 | |
| 	/* 09/11/07 NN added local variables initialization */
 | |
| 	unsigned short iIndex       = 0;
 | |
| 	unsigned short iSourceIndex = 0;
 | |
| 	unsigned char cBitState     = 0;
 | |
| 	unsigned char cCurByte      = 0;
 | |
| 	unsigned char *pcSource    = NULL;
 | |
| 
 | |
| 	if (Bits <= 0) {
 | |
| 		return;
 | |
| 	}
 | |
| 
 | |
| 	switch (ScanType) {
 | |
| 	case HIR:
 | |
| 		pcSource = g_pucHIRData;
 | |
| 		break;
 | |
| 	case TIR:
 | |
| 		pcSource = g_pucTIRData;
 | |
| 		break;
 | |
| 	case HDR:
 | |
| 		pcSource = g_pucHDRData;
 | |
| 		break;
 | |
| 	case TDR:
 | |
| 		pcSource = g_pucTDRData;
 | |
| 		break;
 | |
| 	default:
 | |
| 		break;
 | |
| 	}
 | |
| 
 | |
| 	iSourceIndex = 0;
 | |
| 	cBitState = 0;
 | |
| 	for (iIndex = 0; iIndex < Bits - 1; iIndex++) {
 | |
| 		/* Scan instruction or bypass register */
 | |
| 		if (iIndex % 8 == 0) {
 | |
| 			cCurByte = pcSource[iSourceIndex++];
 | |
| 		}
 | |
| 		cBitState = (unsigned char) (((cCurByte << iIndex % 8) & 0x80)
 | |
| 			? 0x01 : 0x00);
 | |
| 		writePort(g_ucPinTDI, cBitState);
 | |
| 		sclock();
 | |
| 	}
 | |
| 
 | |
| 	if (iIndex % 8 == 0)  {
 | |
| 		cCurByte = pcSource[iSourceIndex++];
 | |
| 	}
 | |
| 
 | |
| 	cBitState = (unsigned char) (((cCurByte << iIndex % 8) & 0x80)
 | |
| 		? 0x01 : 0x00);
 | |
| 	writePort(g_ucPinTDI, cBitState);
 | |
| }
 | |
| 
 | |
| /*
 | |
|  *
 | |
|  * ispVMStateMachine
 | |
|  *
 | |
|  * This procedure steps all devices in the daisy chain from a given
 | |
|  * JTAG state to the next desirable state. If the next state is TLR,
 | |
|  * the JTAG state machine is brute forced into TLR by driving TMS
 | |
|  * high and pulse TCK 6 times.
 | |
|  *
 | |
|  */
 | |
| 
 | |
| void ispVMStateMachine(signed char cNextJTAGState)
 | |
| {
 | |
| 	/* 09/11/07 NN added local variables initialization */
 | |
| 	signed char cPathIndex  = 0;
 | |
| 	signed char cStateIndex = 0;
 | |
| 
 | |
| 	if ((g_cCurrentJTAGState == cNextJTAGState) &&
 | |
| 		(cNextJTAGState != RESET)) {
 | |
| 		return;
 | |
| 	}
 | |
| 
 | |
| 	for (cStateIndex = 0; cStateIndex < 25; cStateIndex++) {
 | |
| 		if ((g_cCurrentJTAGState ==
 | |
| 			 g_JTAGTransistions[cStateIndex].CurState) &&
 | |
| 			(cNextJTAGState ==
 | |
| 				 g_JTAGTransistions[cStateIndex].NextState)) {
 | |
| 			break;
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	g_cCurrentJTAGState = cNextJTAGState;
 | |
| 	for (cPathIndex = 0;
 | |
| 		cPathIndex < g_JTAGTransistions[cStateIndex].Pulses;
 | |
| 		cPathIndex++) {
 | |
| 		if ((g_JTAGTransistions[cStateIndex].Pattern << cPathIndex)
 | |
| 			& 0x80) {
 | |
| 			writePort(g_ucPinTMS, (unsigned char) 0x01);
 | |
| 		} else {
 | |
| 			writePort(g_ucPinTMS, (unsigned char) 0x00);
 | |
| 		}
 | |
| 		sclock();
 | |
| 	}
 | |
| 
 | |
| 	writePort(g_ucPinTDI, 0x00);
 | |
| 	writePort(g_ucPinTMS, 0x00);
 | |
| }
 | |
| 
 | |
| /*
 | |
|  *
 | |
|  * ispVMStart
 | |
|  *
 | |
|  * Enable the port to the device and set the state to RESET (TLR).
 | |
|  *
 | |
|  */
 | |
| 
 | |
| void ispVMStart()
 | |
| {
 | |
| #ifdef DEBUG
 | |
| 	printf("// ISPVM EMBEDDED ADDED\n");
 | |
| 	printf("STATE RESET;\n");
 | |
| #endif
 | |
| 	g_usFlowControl	= 0;
 | |
| 	g_usDataType = g_uiChecksumIndex = g_cCurrentJTAGState = 0;
 | |
| 	g_usHeadDR = g_usHeadIR = g_usTailDR = g_usTailIR = 0;
 | |
| 	g_usMaxSize = g_usShiftValue = g_usRepeatLoops = 0;
 | |
| 	g_usTDOSize =  g_usMASKSize = g_usTDISize = 0;
 | |
| 	g_usDMASKSize = g_usLCOUNTSize = g_usHDRSize = 0;
 | |
| 	g_usTDRSize = g_usHIRSize = g_usTIRSize =  g_usHeapSize	= 0;
 | |
| 	g_pLVDSList = NULL;
 | |
| 	g_usLVDSPairCount = 0;
 | |
| 	previous_size = 0;
 | |
| 
 | |
| 	ispVMStateMachine(RESET);    /*step devices to RESET state*/
 | |
| }
 | |
| 
 | |
| /*
 | |
|  *
 | |
|  * ispVMEnd
 | |
|  *
 | |
|  * Set the state of devices to RESET to enable the devices and disable
 | |
|  * the port.
 | |
|  *
 | |
|  */
 | |
| 
 | |
| void ispVMEnd()
 | |
| {
 | |
| #ifdef DEBUG
 | |
| 	printf("// ISPVM EMBEDDED ADDED\n");
 | |
| 	printf("STATE RESET;\n");
 | |
| 	printf("RUNTEST 1.00E-001 SEC;\n");
 | |
| #endif
 | |
| 
 | |
| 	ispVMStateMachine(RESET);   /*step devices to RESET state */
 | |
| 	ispVMDelay(1000);              /*wake up devices*/
 | |
| }
 | |
| 
 | |
| /*
 | |
|  *
 | |
|  * ispVMSend
 | |
|  *
 | |
|  * Send the TDI data stream to devices. The data stream can be
 | |
|  * instructions or data.
 | |
|  *
 | |
|  */
 | |
| 
 | |
| signed char ispVMSend(unsigned short a_usiDataSize)
 | |
| {
 | |
| 	/* 09/11/07 NN added local variables initialization */
 | |
| 	unsigned short iIndex       = 0;
 | |
| 	unsigned short iInDataIndex = 0;
 | |
| 	unsigned char cCurByte      = 0;
 | |
| 	unsigned char cBitState     = 0;
 | |
| 
 | |
| 	for (iIndex = 0; iIndex < a_usiDataSize - 1; iIndex++) {
 | |
| 		if (iIndex % 8 == 0) {
 | |
| 			cCurByte = g_pucInData[iInDataIndex++];
 | |
| 		}
 | |
| 		cBitState = (unsigned char)(((cCurByte << iIndex % 8) & 0x80)
 | |
| 			? 0x01 : 0x00);
 | |
| 		writePort(g_ucPinTDI, cBitState);
 | |
| 		sclock();
 | |
| 	}
 | |
| 
 | |
| 	if (iIndex % 8 == 0) {
 | |
| 		/* Take care of the last bit */
 | |
| 		cCurByte = g_pucInData[iInDataIndex];
 | |
| 	}
 | |
| 
 | |
| 	cBitState = (unsigned char) (((cCurByte << iIndex % 8) & 0x80)
 | |
| 		? 0x01 : 0x00);
 | |
| 
 | |
| 	writePort(g_ucPinTDI, cBitState);
 | |
| 	if (g_usFlowControl & CASCADE) {
 | |
| 		/*1/15/04 Clock in last bit for the first n-1 cascaded frames */
 | |
| 		sclock();
 | |
| 	}
 | |
| 
 | |
| 	return 0;
 | |
| }
 | |
| 
 | |
| /*
 | |
|  *
 | |
|  * ispVMRead
 | |
|  *
 | |
|  * Read the data stream from devices and verify.
 | |
|  *
 | |
|  */
 | |
| 
 | |
| signed char ispVMRead(unsigned short a_usiDataSize)
 | |
| {
 | |
| 	/* 09/11/07 NN added local variables initialization */
 | |
| 	unsigned short usDataSizeIndex    = 0;
 | |
| 	unsigned short usErrorCount       = 0;
 | |
| 	unsigned short usLastBitIndex     = 0;
 | |
| 	unsigned char cDataByte           = 0;
 | |
| 	unsigned char cMaskByte           = 0;
 | |
| 	unsigned char cInDataByte         = 0;
 | |
| 	unsigned char cCurBit             = 0;
 | |
| 	unsigned char cByteIndex          = 0;
 | |
| 	unsigned short usBufferIndex      = 0;
 | |
| 	unsigned char ucDisplayByte       = 0x00;
 | |
| 	unsigned char ucDisplayFlag       = 0x01;
 | |
| 	char StrChecksum[256]            = {0};
 | |
| 	unsigned char g_usCalculateChecksum = 0x00;
 | |
| 
 | |
| 	/* 09/11/07 NN Type cast mismatch variables */
 | |
| 	usLastBitIndex = (unsigned short)(a_usiDataSize - 1);
 | |
| 
 | |
| #ifndef DEBUG
 | |
| 	/*
 | |
| 	 * If mask is not all zeros, then set the display flag to 0x00,
 | |
| 	 * otherwise it shall be set to 0x01 to indicate that data read
 | |
| 	 * from the device shall be displayed. If DEBUG is defined,
 | |
| 	 * always display data.
 | |
| 	 */
 | |
| 
 | |
| 	for (usDataSizeIndex = 0; usDataSizeIndex < (a_usiDataSize + 7) / 8;
 | |
| 		usDataSizeIndex++) {
 | |
| 		if (g_usDataType & MASK_DATA) {
 | |
| 			if (g_pucOutMaskData[usDataSizeIndex] != 0x00) {
 | |
| 				ucDisplayFlag = 0x00;
 | |
| 				break;
 | |
| 			}
 | |
| 		} else if (g_usDataType & CMASK_DATA) {
 | |
| 			g_usCalculateChecksum = 0x01;
 | |
| 			ucDisplayFlag = 0x00;
 | |
| 			break;
 | |
| 		} else {
 | |
| 			ucDisplayFlag = 0x00;
 | |
| 			break;
 | |
| 		}
 | |
| 	}
 | |
| #endif /* DEBUG */
 | |
| 
 | |
| 	/*
 | |
| 	*
 | |
| 	* Begin shifting data in and out of the device.
 | |
| 	*
 | |
| 	**/
 | |
| 
 | |
| 	for (usDataSizeIndex = 0; usDataSizeIndex < a_usiDataSize;
 | |
| 		usDataSizeIndex++) {
 | |
| 		if (cByteIndex == 0) {
 | |
| 
 | |
| 			/*
 | |
| 			 * Grab byte from TDO buffer.
 | |
| 			 */
 | |
| 
 | |
| 			if (g_usDataType & TDO_DATA) {
 | |
| 				cDataByte = g_pucOutData[usBufferIndex];
 | |
| 			}
 | |
| 
 | |
| 			/*
 | |
| 			 * Grab byte from MASK buffer.
 | |
| 			 */
 | |
| 
 | |
| 			if (g_usDataType & MASK_DATA) {
 | |
| 				cMaskByte = g_pucOutMaskData[usBufferIndex];
 | |
| 			} else {
 | |
| 				cMaskByte = 0xFF;
 | |
| 			}
 | |
| 
 | |
| 			/*
 | |
| 			 * Grab byte from CMASK buffer.
 | |
| 			 */
 | |
| 
 | |
| 			if (g_usDataType & CMASK_DATA) {
 | |
| 				cMaskByte = 0x00;
 | |
| 				g_usCalculateChecksum = 0x01;
 | |
| 			}
 | |
| 
 | |
| 			/*
 | |
| 			 * Grab byte from TDI buffer.
 | |
| 			 */
 | |
| 
 | |
| 			if (g_usDataType & TDI_DATA) {
 | |
| 				cInDataByte = g_pucInData[usBufferIndex];
 | |
| 			}
 | |
| 
 | |
| 			usBufferIndex++;
 | |
| 		}
 | |
| 
 | |
| 		cCurBit = readPort();
 | |
| 
 | |
| 		if (ucDisplayFlag) {
 | |
| 			ucDisplayByte <<= 1;
 | |
| 			ucDisplayByte |= cCurBit;
 | |
| 		}
 | |
| 
 | |
| 		/*
 | |
| 		 * Check if data read from port matches with expected TDO.
 | |
| 		 */
 | |
| 
 | |
| 		if (g_usDataType & TDO_DATA) {
 | |
| 			/* 08/28/08 NN Added Calculate checksum support. */
 | |
| 			if (g_usCalculateChecksum) {
 | |
| 				if (cCurBit == 0x01)
 | |
| 					g_usChecksum +=
 | |
| 						(1 << (g_uiChecksumIndex % 8));
 | |
| 				g_uiChecksumIndex++;
 | |
| 			} else {
 | |
| 				if ((((cMaskByte << cByteIndex) & 0x80)
 | |
| 					? 0x01 : 0x00)) {
 | |
| 					if (cCurBit != (unsigned char)
 | |
| 					(((cDataByte << cByteIndex) & 0x80)
 | |
| 						? 0x01 : 0x00)) {
 | |
| 						usErrorCount++;
 | |
| 					}
 | |
| 				}
 | |
| 			}
 | |
| 		}
 | |
| 
 | |
| 		/*
 | |
| 		 * Write TDI data to the port.
 | |
| 		 */
 | |
| 
 | |
| 		writePort(g_ucPinTDI,
 | |
| 			(unsigned char)(((cInDataByte << cByteIndex) & 0x80)
 | |
| 				? 0x01 : 0x00));
 | |
| 
 | |
| 		if (usDataSizeIndex < usLastBitIndex) {
 | |
| 
 | |
| 			/*
 | |
| 			 * Clock data out from the data shift register.
 | |
| 			 */
 | |
| 
 | |
| 			sclock();
 | |
| 		} else if (g_usFlowControl & CASCADE) {
 | |
| 
 | |
| 			/*
 | |
| 			 * Clock in last bit for the first N - 1 cascaded frames
 | |
| 			 */
 | |
| 
 | |
| 			sclock();
 | |
| 		}
 | |
| 
 | |
| 		/*
 | |
| 		 * Increment the byte index. If it exceeds 7, then reset it back
 | |
| 		 * to zero.
 | |
| 		 */
 | |
| 
 | |
| 		cByteIndex++;
 | |
| 		if (cByteIndex >= 8) {
 | |
| 			if (ucDisplayFlag) {
 | |
| 
 | |
| 			/*
 | |
| 			 * Store displayed data in the TDO buffer. By reusing
 | |
| 			 * the TDO buffer to store displayed data, there is no
 | |
| 			 * need to allocate a buffer simply to hold display
 | |
| 			 * data. This will not cause any false verification
 | |
| 			 * errors because the true TDO byte has already
 | |
| 			 * been consumed.
 | |
| 			 */
 | |
| 
 | |
| 				g_pucOutData[usBufferIndex - 1] = ucDisplayByte;
 | |
| 				ucDisplayByte = 0;
 | |
| 			}
 | |
| 
 | |
| 			cByteIndex = 0;
 | |
| 		}
 | |
| 		/* 09/12/07 Nguyen changed to display the 1 bit expected data */
 | |
| 		else if (a_usiDataSize == 1) {
 | |
| 			if (ucDisplayFlag) {
 | |
| 
 | |
| 				/*
 | |
| 				 * Store displayed data in the TDO buffer.
 | |
| 				 * By reusing the TDO buffer to store displayed
 | |
| 				 * data, there is no need to allocate
 | |
| 				 * a buffer simply to hold display data. This
 | |
| 				 * will not cause any false verification errors
 | |
| 				 * because the true TDO byte has already
 | |
| 				 * been consumed.
 | |
| 				 */
 | |
| 
 | |
| 				/*
 | |
| 				 * Flip ucDisplayByte and store it in cDataByte.
 | |
| 				 */
 | |
| 				cDataByte = 0x00;
 | |
| 				for (usBufferIndex = 0; usBufferIndex < 8;
 | |
| 					usBufferIndex++) {
 | |
| 					cDataByte <<= 1;
 | |
| 					if (ucDisplayByte & 0x01) {
 | |
| 						cDataByte |= 0x01;
 | |
| 					}
 | |
| 					ucDisplayByte >>= 1;
 | |
| 				}
 | |
| 				g_pucOutData[0] = cDataByte;
 | |
| 				ucDisplayByte = 0;
 | |
| 			}
 | |
| 
 | |
| 			cByteIndex = 0;
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	if (ucDisplayFlag) {
 | |
| 
 | |
| #ifdef DEBUG
 | |
| 		debug("RECEIVED TDO (");
 | |
| #else
 | |
| 		vme_out_string("Display Data: 0x");
 | |
| #endif /* DEBUG */
 | |
| 
 | |
| 		/* 09/11/07 NN Type cast mismatch variables */
 | |
| 		for (usDataSizeIndex = (unsigned short)
 | |
| 				((a_usiDataSize + 7) / 8);
 | |
| 			usDataSizeIndex > 0 ; usDataSizeIndex--) {
 | |
| 			cMaskByte = g_pucOutData[usDataSizeIndex - 1];
 | |
| 			cDataByte = 0x00;
 | |
| 
 | |
| 			/*
 | |
| 			 * Flip cMaskByte and store it in cDataByte.
 | |
| 			 */
 | |
| 
 | |
| 			for (usBufferIndex = 0; usBufferIndex < 8;
 | |
| 				usBufferIndex++) {
 | |
| 				cDataByte <<= 1;
 | |
| 				if (cMaskByte & 0x01) {
 | |
| 					cDataByte |= 0x01;
 | |
| 				}
 | |
| 				cMaskByte >>= 1;
 | |
| 			}
 | |
| #ifdef DEBUG
 | |
| 			printf("%.2X", cDataByte);
 | |
| 			if ((((a_usiDataSize + 7) / 8) - usDataSizeIndex)
 | |
| 				% 40 == 39) {
 | |
| 				printf("\n\t\t");
 | |
| 			}
 | |
| #else
 | |
| 			vme_out_hex(cDataByte);
 | |
| #endif /* DEBUG */
 | |
| 		}
 | |
| 
 | |
| #ifdef DEBUG
 | |
| 		printf(")\n\n");
 | |
| #else
 | |
| 		vme_out_string("\n\n");
 | |
| #endif /* DEBUG */
 | |
| 		/* 09/02/08 Nguyen changed to display the data Checksum */
 | |
| 		if (g_usChecksum != 0) {
 | |
| 			g_usChecksum &= 0xFFFF;
 | |
| 			sprintf(StrChecksum, "Data Checksum: %.4lX\n\n",
 | |
| 				g_usChecksum);
 | |
| 			vme_out_string(StrChecksum);
 | |
| 			g_usChecksum = 0;
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	if (usErrorCount > 0) {
 | |
| 		if (g_usFlowControl & VERIFYUES) {
 | |
| 			vme_out_string(
 | |
| 				"USERCODE verification failed.   "
 | |
| 				"Continue programming......\n\n");
 | |
| 			g_usFlowControl &= ~(VERIFYUES);
 | |
| 			return 0;
 | |
| 		} else {
 | |
| 
 | |
| #ifdef DEBUG
 | |
| 			printf("TOTAL ERRORS: %d\n", usErrorCount);
 | |
| #endif /* DEBUG */
 | |
| 
 | |
| 			return VME_VERIFICATION_FAILURE;
 | |
| 		}
 | |
| 	} else {
 | |
| 		if (g_usFlowControl & VERIFYUES) {
 | |
| 			vme_out_string("USERCODE verification passed.    "
 | |
| 				"Programming aborted.\n\n");
 | |
| 			g_usFlowControl &= ~(VERIFYUES);
 | |
| 			return 1;
 | |
| 		} else {
 | |
| 			return 0;
 | |
| 		}
 | |
| 	}
 | |
| }
 | |
| 
 | |
| /*
 | |
|  *
 | |
|  * ispVMReadandSave
 | |
|  *
 | |
|  * Support dynamic I/O.
 | |
|  *
 | |
|  */
 | |
| 
 | |
| signed char ispVMReadandSave(unsigned short int a_usiDataSize)
 | |
| {
 | |
| 	/* 09/11/07 NN added local variables initialization */
 | |
| 	unsigned short int usDataSizeIndex = 0;
 | |
| 	unsigned short int usLastBitIndex  = 0;
 | |
| 	unsigned short int usBufferIndex   = 0;
 | |
| 	unsigned short int usOutBitIndex   = 0;
 | |
| 	unsigned short int usLVDSIndex     = 0;
 | |
| 	unsigned char cDataByte            = 0;
 | |
| 	unsigned char cDMASKByte           = 0;
 | |
| 	unsigned char cInDataByte          = 0;
 | |
| 	unsigned char cCurBit              = 0;
 | |
| 	unsigned char cByteIndex           = 0;
 | |
| 	signed char cLVDSByteIndex         = 0;
 | |
| 
 | |
| 	/* 09/11/07 NN Type cast mismatch variables */
 | |
| 	usLastBitIndex = (unsigned short) (a_usiDataSize - 1);
 | |
| 
 | |
| 	/*
 | |
| 	*
 | |
| 	* Iterate through the data bits.
 | |
| 	*
 | |
| 	*/
 | |
| 
 | |
| 	for (usDataSizeIndex = 0; usDataSizeIndex < a_usiDataSize;
 | |
| 		usDataSizeIndex++) {
 | |
| 		if (cByteIndex == 0) {
 | |
| 
 | |
| 			/*
 | |
| 			 * Grab byte from DMASK buffer.
 | |
| 			 */
 | |
| 
 | |
| 			if (g_usDataType & DMASK_DATA) {
 | |
| 				cDMASKByte = g_pucOutDMaskData[usBufferIndex];
 | |
| 			} else {
 | |
| 				cDMASKByte = 0x00;
 | |
| 			}
 | |
| 
 | |
| 			/*
 | |
| 			 * Grab byte from TDI buffer.
 | |
| 			 */
 | |
| 
 | |
| 			if (g_usDataType & TDI_DATA) {
 | |
| 				cInDataByte = g_pucInData[usBufferIndex];
 | |
| 			}
 | |
| 
 | |
| 			usBufferIndex++;
 | |
| 		}
 | |
| 
 | |
| 		cCurBit = readPort();
 | |
| 		cDataByte = (unsigned char)(((cInDataByte << cByteIndex) & 0x80)
 | |
| 			? 0x01 : 0x00);
 | |
| 
 | |
| 		/*
 | |
| 		 * Initialize the byte to be zero.
 | |
| 		 */
 | |
| 
 | |
| 		if (usOutBitIndex % 8 == 0) {
 | |
| 			g_pucOutData[usOutBitIndex / 8] = 0x00;
 | |
| 		}
 | |
| 
 | |
| 		/*
 | |
| 		 * Use TDI, DMASK, and device TDO to create new TDI (actually
 | |
| 		 * stored in g_pucOutData).
 | |
| 		 */
 | |
| 
 | |
| 		if ((((cDMASKByte << cByteIndex) & 0x80) ? 0x01 : 0x00)) {
 | |
| 
 | |
| 			if (g_pLVDSList) {
 | |
| 				for (usLVDSIndex = 0;
 | |
| 					 usLVDSIndex < g_usLVDSPairCount;
 | |
| 					usLVDSIndex++) {
 | |
| 					if (g_pLVDSList[usLVDSIndex].
 | |
| 						usNegativeIndex ==
 | |
| 						usDataSizeIndex) {
 | |
| 						g_pLVDSList[usLVDSIndex].
 | |
| 							ucUpdate = 0x01;
 | |
| 						break;
 | |
| 					}
 | |
| 				}
 | |
| 			}
 | |
| 
 | |
| 			/*
 | |
| 			 * DMASK bit is 1, use TDI.
 | |
| 			 */
 | |
| 
 | |
| 			g_pucOutData[usOutBitIndex / 8] |= (unsigned char)
 | |
| 				(((cDataByte & 0x1) ? 0x01 : 0x00) <<
 | |
| 				(7 - usOutBitIndex % 8));
 | |
| 		} else {
 | |
| 
 | |
| 			/*
 | |
| 			 * DMASK bit is 0, use device TDO.
 | |
| 			 */
 | |
| 
 | |
| 			g_pucOutData[usOutBitIndex / 8] |= (unsigned char)
 | |
| 				(((cCurBit & 0x1) ? 0x01 : 0x00) <<
 | |
| 				(7 - usOutBitIndex % 8));
 | |
| 		}
 | |
| 
 | |
| 		/*
 | |
| 		 * Shift in TDI in order to get TDO out.
 | |
| 		 */
 | |
| 
 | |
| 		usOutBitIndex++;
 | |
| 		writePort(g_ucPinTDI, cDataByte);
 | |
| 		if (usDataSizeIndex < usLastBitIndex) {
 | |
| 			sclock();
 | |
| 		}
 | |
| 
 | |
| 		/*
 | |
| 		 * Increment the byte index. If it exceeds 7, then reset it back
 | |
| 		 * to zero.
 | |
| 		 */
 | |
| 
 | |
| 		cByteIndex++;
 | |
| 		if (cByteIndex >= 8) {
 | |
| 			cByteIndex = 0;
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	/*
 | |
| 	 * If g_pLVDSList exists and pairs need updating, then update
 | |
| 	 * the negative-pair to receive the flipped positive-pair value.
 | |
| 	 */
 | |
| 
 | |
| 	if (g_pLVDSList) {
 | |
| 		for (usLVDSIndex = 0; usLVDSIndex < g_usLVDSPairCount;
 | |
| 			usLVDSIndex++) {
 | |
| 			if (g_pLVDSList[usLVDSIndex].ucUpdate) {
 | |
| 
 | |
| 				/*
 | |
| 				 * Read the positive value and flip it.
 | |
| 				 */
 | |
| 
 | |
| 				cDataByte = (unsigned char)
 | |
| 				 (((g_pucOutData[g_pLVDSList[usLVDSIndex].
 | |
| 					usPositiveIndex / 8]
 | |
| 					<< (g_pLVDSList[usLVDSIndex].
 | |
| 					usPositiveIndex % 8)) & 0x80) ?
 | |
| 					0x01 : 0x00);
 | |
| 				/* 09/11/07 NN Type cast mismatch variables */
 | |
| 				cDataByte = (unsigned char) (!cDataByte);
 | |
| 
 | |
| 				/*
 | |
| 				 * Get the byte that needs modification.
 | |
| 				 */
 | |
| 
 | |
| 				cInDataByte =
 | |
| 				g_pucOutData[g_pLVDSList[usLVDSIndex].
 | |
| 					usNegativeIndex / 8];
 | |
| 
 | |
| 				if (cDataByte) {
 | |
| 
 | |
| 					/*
 | |
| 					 * Copy over the current byte and
 | |
| 					 * set the negative bit to 1.
 | |
| 					 */
 | |
| 
 | |
| 					cDataByte = 0x00;
 | |
| 					for (cLVDSByteIndex = 7;
 | |
| 						cLVDSByteIndex >= 0;
 | |
| 						cLVDSByteIndex--) {
 | |
| 						cDataByte <<= 1;
 | |
| 						if (7 -
 | |
| 						(g_pLVDSList[usLVDSIndex].
 | |
| 							usNegativeIndex % 8) ==
 | |
| 							cLVDSByteIndex) {
 | |
| 
 | |
| 							/*
 | |
| 							 * Set negative bit to 1
 | |
| 							 */
 | |
| 
 | |
| 							cDataByte |= 0x01;
 | |
| 						} else if (cInDataByte & 0x80) {
 | |
| 							cDataByte |= 0x01;
 | |
| 						}
 | |
| 
 | |
| 						cInDataByte <<= 1;
 | |
| 					}
 | |
| 
 | |
| 					/*
 | |
| 					 * Store the modified byte.
 | |
| 					 */
 | |
| 
 | |
| 					g_pucOutData[g_pLVDSList[usLVDSIndex].
 | |
| 					usNegativeIndex / 8] = cDataByte;
 | |
| 				} else {
 | |
| 
 | |
| 					/*
 | |
| 					 * Copy over the current byte and set
 | |
| 					 * the negative bit to 0.
 | |
| 					 */
 | |
| 
 | |
| 					cDataByte = 0x00;
 | |
| 					for (cLVDSByteIndex = 7;
 | |
| 						cLVDSByteIndex >= 0;
 | |
| 						cLVDSByteIndex--) {
 | |
| 						cDataByte <<= 1;
 | |
| 						if (7 -
 | |
| 						(g_pLVDSList[usLVDSIndex].
 | |
| 						usNegativeIndex % 8) ==
 | |
| 						cLVDSByteIndex) {
 | |
| 
 | |
| 							/*
 | |
| 							 * Set negative bit to 0
 | |
| 							 */
 | |
| 
 | |
| 							cDataByte |= 0x00;
 | |
| 						} else if (cInDataByte & 0x80) {
 | |
| 							cDataByte |= 0x01;
 | |
| 						}
 | |
| 
 | |
| 						cInDataByte <<= 1;
 | |
| 					}
 | |
| 
 | |
| 					/*
 | |
| 					 * Store the modified byte.
 | |
| 					 */
 | |
| 
 | |
| 					g_pucOutData[g_pLVDSList[usLVDSIndex].
 | |
| 					usNegativeIndex / 8] = cDataByte;
 | |
| 				}
 | |
| 
 | |
| 				break;
 | |
| 			}
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	return 0;
 | |
| }
 | |
| 
 | |
| signed char ispVMProcessLVDS(unsigned short a_usLVDSCount)
 | |
| {
 | |
| 	unsigned short usLVDSIndex = 0;
 | |
| 
 | |
| 	/*
 | |
| 	 * Allocate memory to hold LVDS pairs.
 | |
| 	 */
 | |
| 
 | |
| 	ispVMMemManager(LVDS, a_usLVDSCount);
 | |
| 	g_usLVDSPairCount = a_usLVDSCount;
 | |
| 
 | |
| #ifdef DEBUG
 | |
| 	printf("LVDS %d (", a_usLVDSCount);
 | |
| #endif /* DEBUG */
 | |
| 
 | |
| 	/*
 | |
| 	 * Iterate through each given LVDS pair.
 | |
| 	 */
 | |
| 
 | |
| 	for (usLVDSIndex = 0; usLVDSIndex < g_usLVDSPairCount; usLVDSIndex++) {
 | |
| 
 | |
| 		/*
 | |
| 		 * Assign the positive and negative indices of the LVDS pair.
 | |
| 		 */
 | |
| 
 | |
| 		/* 09/11/07 NN Type cast mismatch variables */
 | |
| 		g_pLVDSList[usLVDSIndex].usPositiveIndex =
 | |
| 			(unsigned short) ispVMDataSize();
 | |
| 		/* 09/11/07 NN Type cast mismatch variables */
 | |
| 		g_pLVDSList[usLVDSIndex].usNegativeIndex =
 | |
| 			(unsigned short)ispVMDataSize();
 | |
| 
 | |
| #ifdef DEBUG
 | |
| 		if (usLVDSIndex < g_usLVDSPairCount - 1) {
 | |
| 			printf("%d:%d, ",
 | |
| 				g_pLVDSList[usLVDSIndex].usPositiveIndex,
 | |
| 				g_pLVDSList[usLVDSIndex].usNegativeIndex);
 | |
| 		} else {
 | |
| 			printf("%d:%d",
 | |
| 				g_pLVDSList[usLVDSIndex].usPositiveIndex,
 | |
| 				g_pLVDSList[usLVDSIndex].usNegativeIndex);
 | |
| 		}
 | |
| #endif /* DEBUG */
 | |
| 
 | |
| 	}
 | |
| 
 | |
| #ifdef DEBUG
 | |
| 	printf(");\n", a_usLVDSCount);
 | |
| #endif /* DEBUG */
 | |
| 
 | |
| 	return 0;
 | |
| }
 |