xref: /openbmc/u-boot/drivers/fpga/ivm_core.c (revision 4e3349b6)
1 /*
2  * Porting to u-boot:
3  *
4  * (C) Copyright 2010
5  * Stefano Babic, DENX Software Engineering, sbabic@denx.de.
6  *
7  * Lattice ispVME Embedded code to load Lattice's FPGA:
8  *
9  * Copyright 2009 Lattice Semiconductor Corp.
10  *
11  * ispVME Embedded allows programming of Lattice's suite of FPGA
12  * devices on embedded systems through the JTAG port.  The software
13  * is distributed in source code form and is open to re - distribution
14  * and modification where applicable.
15  *
16  * Revision History of ivm_core.c module:
17  * 4/25/06 ht   Change some variables from unsigned short or int
18  *              to long int to make the code compiler independent.
19  * 5/24/06 ht   Support using RESET (TRST) pin as a special purpose
20  *              control pin such as triggering the loading of known
21  *              state exit.
22  * 3/6/07 ht added functions to support output to terminals
23  *
24  * 09/11/07 NN Type cast mismatch variables
25  *		   Moved the sclock() function to hardware.c
26  * 08/28/08 NN Added Calculate checksum support.
27  * 4/1/09 Nguyen replaced the recursive function call codes on
28  *        the ispVMLCOUNT function
29  * See file CREDITS for list of people who contributed to this
30  * project.
31  *
32  * This program is free software; you can redistribute it and/or
33  * modify it under the terms of the GNU General Public License as
34  * published by the Free Software Foundation; either version 2 of
35  * the License, or (at your option) any later version.
36  *
37  * This program is distributed in the hope that it will be useful,
38  * but WITHOUT ANY WARRANTY; without even the implied warranty of
39  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
40  * GNU General Public License for more details.
41  *
42  * You should have received a copy of the GNU General Public License
43  * along with this program; if not, write to the Free Software
44  * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
45  * MA 02111-1307 USA
46  */
47 
48 #include <common.h>
49 #include <linux/string.h>
50 #include <malloc.h>
51 #include <lattice.h>
52 
53 #define vme_out_char(c)	printf("%c", c)
54 #define vme_out_hex(c)	printf("%x", c)
55 #define vme_out_string(s) printf("%s", s)
56 
57 /*
58  *
59  * Global variables used to specify the flow control and data type.
60  *
61  *	g_usFlowControl:	flow control register. Each bit in the
62  *                               register can potentially change the
63  *                               personality of the embedded engine.
64  *	g_usDataType:		holds the data type of the current row.
65  *
66  */
67 
68 static unsigned short g_usFlowControl;
69 unsigned short g_usDataType;
70 
71 /*
72  *
73  * Global variables used to specify the ENDDR and ENDIR.
74  *
75  *	g_ucEndDR:		the state that the device goes to after SDR.
76  *	g_ucEndIR:		the state that the device goes to after SIR.
77  *
78  */
79 
80 unsigned char g_ucEndDR = DRPAUSE;
81 unsigned char g_ucEndIR = IRPAUSE;
82 
83 /*
84  *
85  * Global variables used to support header/trailer.
86  *
87  *	g_usHeadDR:		the number of lead devices in bypass.
88  *	g_usHeadIR:		the sum of IR length of lead devices.
89  *	g_usTailDR:		the number of tail devices in bypass.
90  *	g_usTailIR:		the sum of IR length of tail devices.
91  *
92  */
93 
94 static unsigned short g_usHeadDR;
95 static unsigned short g_usHeadIR;
96 static unsigned short g_usTailDR;
97 static unsigned short g_usTailIR;
98 
99 /*
100  *
101  * Global variable to store the number of bits of data or instruction
102  * to be shifted into or out from the device.
103  *
104  */
105 
106 static unsigned short g_usiDataSize;
107 
108 /*
109  *
110  * Stores the frequency. Default to 1 MHz.
111  *
112  */
113 
114 static int g_iFrequency = 1000;
115 
116 /*
117  *
118  * Stores the maximum amount of ram needed to hold a row of data.
119  *
120  */
121 
122 static unsigned short g_usMaxSize;
123 
124 /*
125  *
126  * Stores the LSH or RSH value.
127  *
128  */
129 
130 static unsigned short g_usShiftValue;
131 
132 /*
133  *
134  * Stores the current repeat loop value.
135  *
136  */
137 
138 static unsigned short g_usRepeatLoops;
139 
140 /*
141  *
142  * Stores the current vendor.
143  *
144  */
145 
146 static signed char g_cVendor = LATTICE;
147 
148 /*
149  *
150  * Stores the VME file CRC.
151  *
152  */
153 
154 unsigned short g_usCalculatedCRC;
155 
156 /*
157  *
158  * Stores the Device Checksum.
159  *
160  */
161 /* 08/28/08 NN Added Calculate checksum support. */
162 unsigned long g_usChecksum;
163 static unsigned int g_uiChecksumIndex;
164 
165 /*
166  *
167  * Stores the current state of the JTAG state machine.
168  *
169  */
170 
171 static signed char g_cCurrentJTAGState;
172 
173 /*
174  *
175  * Global variables used to support looping.
176  *
177  *	g_pucHeapMemory:	holds the entire repeat loop.
178  *	g_iHeapCounter:		points to the current byte in the repeat loop.
179  *	g_iHEAPSize:		the current size of the repeat in bytes.
180  *
181  */
182 
183 unsigned char *g_pucHeapMemory;
184 unsigned short g_iHeapCounter;
185 unsigned short g_iHEAPSize;
186 static unsigned short previous_size;
187 
188 /*
189  *
190  * Global variables used to support intelligent programming.
191  *
192  *	g_usIntelDataIndex:     points to the current byte of the
193  *                               intelligent buffer.
194  *	g_usIntelBufferSize:	holds the size of the intelligent
195  *                               buffer.
196  *
197  */
198 
199 unsigned short g_usIntelDataIndex;
200 unsigned short g_usIntelBufferSize;
201 
202 /*
203  *
204  * Supported VME versions.
205  *
206  */
207 
208 const char *const g_szSupportedVersions[] = {
209 	"__VME2.0", "__VME3.0", "____12.0", "____12.1", 0};
210 
211 /*
212  *
213  * Holds the maximum size of each respective buffer. These variables are used
214  * to write the HEX files when converting VME to HEX.
215  *
216 */
217 
218 static unsigned short g_usTDOSize;
219 static unsigned short g_usMASKSize;
220 static unsigned short g_usTDISize;
221 static unsigned short g_usDMASKSize;
222 static unsigned short g_usLCOUNTSize;
223 static unsigned short g_usHDRSize;
224 static unsigned short g_usTDRSize;
225 static unsigned short g_usHIRSize;
226 static unsigned short g_usTIRSize;
227 static unsigned short g_usHeapSize;
228 
229 /*
230  *
231  * Global variables used to store data.
232  *
233  *	g_pucOutMaskData:	local RAM to hold one row of MASK data.
234  *	g_pucInData:		local RAM to hold one row of TDI data.
235  *	g_pucOutData:		local RAM to hold one row of TDO data.
236  *	g_pucHIRData:		local RAM to hold the current SIR header.
237  *	g_pucTIRData:		local RAM to hold the current SIR trailer.
238  *	g_pucHDRData:		local RAM to hold the current SDR header.
239  *	g_pucTDRData:		local RAM to hold the current SDR trailer.
240  *	g_pucIntelBuffer:	local RAM to hold the current intelligent buffer
241  *	g_pucOutDMaskData:	local RAM to hold one row of DMASK data.
242  *
243  */
244 
245 unsigned char	*g_pucOutMaskData	= NULL,
246 		*g_pucInData		= NULL,
247 		*g_pucOutData		= NULL,
248 		*g_pucHIRData		= NULL,
249 		*g_pucTIRData		= NULL,
250 		*g_pucHDRData		= NULL,
251 		*g_pucTDRData		= NULL,
252 		*g_pucIntelBuffer	= NULL,
253 		*g_pucOutDMaskData	= NULL;
254 
255 /*
256  *
257  * JTAG state machine transition table.
258  *
259  */
260 
261 struct {
262 	 unsigned char  CurState;  /* From this state */
263 	 unsigned char  NextState; /* Step to this state */
264 	 unsigned char  Pattern;   /* The tragetory of TMS */
265 	 unsigned char  Pulses;    /* The number of steps */
266 } g_JTAGTransistions[25] = {
267 { RESET,	RESET,		0xFC, 6 },	/* Transitions from RESET */
268 { RESET,	IDLE,		0x00, 1 },
269 { RESET,	DRPAUSE,	0x50, 5 },
270 { RESET,	IRPAUSE,	0x68, 6 },
271 { IDLE,		RESET,		0xE0, 3 },	/* Transitions from IDLE */
272 { IDLE,		DRPAUSE,	0xA0, 4 },
273 { IDLE,		IRPAUSE,	0xD0, 5 },
274 { DRPAUSE,	RESET,		0xF8, 5 },	/* Transitions from DRPAUSE */
275 { DRPAUSE,	IDLE,		0xC0, 3 },
276 { DRPAUSE,	IRPAUSE,	0xF4, 7 },
277 { DRPAUSE,	DRPAUSE,	0xE8, 6 },/* 06/14/06 Support POLL STATUS LOOP*/
278 { IRPAUSE,	RESET,		0xF8, 5 },	/* Transitions from IRPAUSE */
279 { IRPAUSE,	IDLE,		0xC0, 3 },
280 { IRPAUSE,	DRPAUSE,	0xE8, 6 },
281 { DRPAUSE,	SHIFTDR,	0x80, 2 }, /* Extra transitions using SHIFTDR */
282 { IRPAUSE,	SHIFTDR,	0xE0, 5 },
283 { SHIFTDR,	DRPAUSE,	0x80, 2 },
284 { SHIFTDR,	IDLE,		0xC0, 3 },
285 { IRPAUSE,	SHIFTIR,	0x80, 2 },/* Extra transitions using SHIFTIR */
286 { SHIFTIR,	IRPAUSE,	0x80, 2 },
287 { SHIFTIR,	IDLE,		0xC0, 3 },
288 { DRPAUSE,	DRCAPTURE,	0xE0, 4 }, /* 11/15/05 Support DRCAPTURE*/
289 { DRCAPTURE, DRPAUSE,	0x80, 2 },
290 { IDLE,     DRCAPTURE,	0x80, 2 },
291 { IRPAUSE,  DRCAPTURE,  0xE0, 4 }
292 };
293 
294 /*
295  *
296  * List to hold all LVDS pairs.
297  *
298  */
299 
300 LVDSPair *g_pLVDSList;
301 unsigned short g_usLVDSPairCount;
302 
303 /*
304  *
305  * Function prototypes.
306  *
307  */
308 
309 static signed char ispVMDataCode(void);
310 static long int ispVMDataSize(void);
311 static void ispVMData(unsigned char *Data);
312 static signed char ispVMShift(signed char Code);
313 static signed char ispVMAmble(signed char Code);
314 static signed char ispVMLoop(unsigned short a_usLoopCount);
315 static signed char ispVMBitShift(signed char mode, unsigned short bits);
316 static void ispVMComment(unsigned short a_usCommentSize);
317 static void ispVMHeader(unsigned short a_usHeaderSize);
318 static signed char ispVMLCOUNT(unsigned short a_usCountSize);
319 static void ispVMClocks(unsigned short Clocks);
320 static void ispVMBypass(signed char ScanType, unsigned short Bits);
321 static void ispVMStateMachine(signed char NextState);
322 static signed char ispVMSend(unsigned short int);
323 static signed char ispVMRead(unsigned short int);
324 static signed char ispVMReadandSave(unsigned short int);
325 static signed char ispVMProcessLVDS(unsigned short a_usLVDSCount);
326 static void ispVMMemManager(signed char types, unsigned short size);
327 
328 /*
329  *
330  * External variables and functions in hardware.c module
331  *
332  */
333 static signed char g_cCurrentJTAGState;
334 
335 #ifdef DEBUG
336 
337 /*
338  *
339  * GetState
340  *
341  * Returns the state as a string based on the opcode. Only used
342  * for debugging purposes.
343  *
344  */
345 
346 const char *GetState(unsigned char a_ucState)
347 {
348 	switch (a_ucState) {
349 	case RESET:
350 		return "RESET";
351 	case IDLE:
352 		return "IDLE";
353 	case IRPAUSE:
354 		return "IRPAUSE";
355 	case DRPAUSE:
356 		return "DRPAUSE";
357 	case SHIFTIR:
358 		return "SHIFTIR";
359 	case SHIFTDR:
360 		return "SHIFTDR";
361 	case DRCAPTURE:/* 11/15/05 support DRCAPTURE*/
362 		return "DRCAPTURE";
363 	default:
364 		break;
365 	}
366 
367 	return 0;
368 }
369 
370 /*
371  *
372  * PrintData
373  *
374  * Prints the data. Only used for debugging purposes.
375  *
376  */
377 
378 void PrintData(unsigned short a_iDataSize, unsigned char *a_pucData)
379 {
380 	/* 09/11/07 NN added local variables initialization */
381 	unsigned short usByteSize  = 0;
382 	unsigned short usBitIndex  = 0;
383 	signed short usByteIndex   = 0;
384 	unsigned char ucByte       = 0;
385 	unsigned char ucFlipByte   = 0;
386 
387 	if (a_iDataSize % 8) {
388 		/* 09/11/07 NN Type cast mismatch variables */
389 		usByteSize = (unsigned short)(a_iDataSize / 8 + 1);
390 	} else {
391 		/* 09/11/07 NN Type cast mismatch variables */
392 		usByteSize = (unsigned short)(a_iDataSize / 8);
393 	}
394 	puts("(");
395 	/* 09/11/07 NN Type cast mismatch variables */
396 	for (usByteIndex = (signed short)(usByteSize - 1);
397 		usByteIndex >= 0; usByteIndex--) {
398 		ucByte = a_pucData[usByteIndex];
399 		ucFlipByte = 0x00;
400 
401 		/*
402 		*
403 		* Flip each byte.
404 		*
405 		*/
406 
407 		for (usBitIndex = 0; usBitIndex < 8; usBitIndex++) {
408 			ucFlipByte <<= 1;
409 			if (ucByte & 0x1) {
410 				ucFlipByte |= 0x1;
411 			}
412 
413 			ucByte >>= 1;
414 		}
415 
416 		/*
417 		*
418 		* Print the flipped byte.
419 		*
420 		*/
421 
422 		printf("%.02X", ucFlipByte);
423 		if ((usByteSize - usByteIndex) % 40 == 39) {
424 			puts("\n\t\t");
425 		}
426 		if (usByteIndex < 0)
427 			break;
428 	}
429 	puts(")");
430 }
431 #endif /* DEBUG */
432 
433 void ispVMMemManager(signed char cTarget, unsigned short usSize)
434 {
435 	switch (cTarget) {
436 	case XTDI:
437 	case TDI:
438 		if (g_pucInData != NULL) {
439 			if (previous_size == usSize) {/*memory exist*/
440 				break;
441 			} else {
442 				free(g_pucInData);
443 				g_pucInData = NULL;
444 			}
445 		}
446 		g_pucInData = (unsigned char *) malloc(usSize / 8 + 2);
447 		previous_size = usSize;
448 	case XTDO:
449 	case TDO:
450 		if (g_pucOutData != NULL) {
451 			if (previous_size == usSize) { /*already exist*/
452 				break;
453 			} else {
454 				free(g_pucOutData);
455 				g_pucOutData = NULL;
456 			}
457 		}
458 		g_pucOutData = (unsigned char *) malloc(usSize / 8 + 2);
459 		previous_size = usSize;
460 		break;
461 	case MASK:
462 		if (g_pucOutMaskData != NULL) {
463 			if (previous_size == usSize) {/*already allocated*/
464 				break;
465 			} else {
466 				free(g_pucOutMaskData);
467 				g_pucOutMaskData = NULL;
468 			}
469 		}
470 		g_pucOutMaskData = (unsigned char *) malloc(usSize / 8 + 2);
471 		previous_size = usSize;
472 		break;
473 	case HIR:
474 		if (g_pucHIRData != NULL) {
475 			free(g_pucHIRData);
476 			g_pucHIRData = NULL;
477 		}
478 		g_pucHIRData = (unsigned char *) malloc(usSize / 8 + 2);
479 		break;
480 	case TIR:
481 		if (g_pucTIRData != NULL) {
482 			free(g_pucTIRData);
483 			g_pucTIRData = NULL;
484 		}
485 		g_pucTIRData = (unsigned char *) malloc(usSize / 8 + 2);
486 		break;
487 	case HDR:
488 		if (g_pucHDRData != NULL) {
489 			free(g_pucHDRData);
490 			g_pucHDRData = NULL;
491 		}
492 		g_pucHDRData = (unsigned char *) malloc(usSize / 8 + 2);
493 		break;
494 	case TDR:
495 		if (g_pucTDRData != NULL) {
496 			free(g_pucTDRData);
497 			g_pucTDRData = NULL;
498 		}
499 		g_pucTDRData = (unsigned char *) malloc(usSize / 8 + 2);
500 		break;
501 	case HEAP:
502 		if (g_pucHeapMemory != NULL) {
503 			free(g_pucHeapMemory);
504 			g_pucHeapMemory = NULL;
505 		}
506 		g_pucHeapMemory = (unsigned char *) malloc(usSize + 2);
507 		break;
508 	case DMASK:
509 		if (g_pucOutDMaskData != NULL) {
510 			if (previous_size == usSize) { /*already allocated*/
511 				break;
512 			} else {
513 				free(g_pucOutDMaskData);
514 				g_pucOutDMaskData = NULL;
515 			}
516 		}
517 		g_pucOutDMaskData = (unsigned char *) malloc(usSize / 8 + 2);
518 		previous_size = usSize;
519 		break;
520 	case LHEAP:
521 		if (g_pucIntelBuffer != NULL) {
522 			free(g_pucIntelBuffer);
523 			g_pucIntelBuffer = NULL;
524 		}
525 		g_pucIntelBuffer = (unsigned char *) malloc(usSize + 2);
526 		break;
527 	case LVDS:
528 		if (g_pLVDSList != NULL) {
529 			free(g_pLVDSList);
530 			g_pLVDSList = NULL;
531 		}
532 		g_pLVDSList = (LVDSPair *) malloc(usSize * sizeof(LVDSPair));
533 		if (g_pLVDSList)
534 			memset(g_pLVDSList, 0, usSize * sizeof(LVDSPair));
535 		break;
536 	default:
537 		return;
538     }
539 }
540 
541 void ispVMFreeMem(void)
542 {
543 	if (g_pucHeapMemory != NULL) {
544 		free(g_pucHeapMemory);
545 		g_pucHeapMemory = NULL;
546 	}
547 
548 	if (g_pucOutMaskData != NULL) {
549 		free(g_pucOutMaskData);
550 		g_pucOutMaskData = NULL;
551 	}
552 
553 	if (g_pucInData != NULL) {
554 		free(g_pucInData);
555 		g_pucInData = NULL;
556 	}
557 
558 	if (g_pucOutData != NULL) {
559 		free(g_pucOutData);
560 		g_pucOutData = NULL;
561 	}
562 
563 	if (g_pucHIRData != NULL) {
564 		free(g_pucHIRData);
565 		g_pucHIRData = NULL;
566 	}
567 
568 	if (g_pucTIRData != NULL) {
569 		free(g_pucTIRData);
570 		g_pucTIRData = NULL;
571 	}
572 
573 	if (g_pucHDRData != NULL) {
574 		free(g_pucHDRData);
575 		g_pucHDRData = NULL;
576 	}
577 
578 	if (g_pucTDRData != NULL) {
579 		free(g_pucTDRData);
580 		g_pucTDRData = NULL;
581 	}
582 
583 	if (g_pucOutDMaskData != NULL) {
584 		free(g_pucOutDMaskData);
585 		g_pucOutDMaskData = NULL;
586 	}
587 
588 	if (g_pucIntelBuffer != NULL) {
589 		free(g_pucIntelBuffer);
590 		g_pucIntelBuffer = NULL;
591 	}
592 
593 	if (g_pLVDSList != NULL) {
594 		free(g_pLVDSList);
595 		g_pLVDSList = NULL;
596 	}
597 }
598 
599 
600 /*
601  *
602  * ispVMDataSize
603  *
604  * Returns a VME-encoded number, usually used to indicate the
605  * bit length of an SIR/SDR command.
606  *
607  */
608 
609 long int ispVMDataSize()
610 {
611 	/* 09/11/07 NN added local variables initialization */
612 	long int iSize           = 0;
613 	signed char cCurrentByte = 0;
614 	signed char cIndex       = 0;
615 	cIndex = 0;
616 	while ((cCurrentByte = GetByte()) & 0x80) {
617 		iSize |= ((long int) (cCurrentByte & 0x7F)) << cIndex;
618 		cIndex += 7;
619 	}
620 	iSize |= ((long int) (cCurrentByte & 0x7F)) << cIndex;
621 	return iSize;
622 }
623 
624 /*
625  *
626  * ispVMCode
627  *
628  * This is the heart of the embedded engine. All the high-level opcodes
629  * are extracted here. Once they have been identified, then it
630  * will call other functions to handle the processing.
631  *
632  */
633 
634 signed char ispVMCode()
635 {
636 	/* 09/11/07 NN added local variables initialization */
637 	unsigned short iRepeatSize = 0;
638 	signed char cOpcode	   = 0;
639 	signed char cRetCode       = 0;
640 	unsigned char ucState      = 0;
641 	unsigned short usDelay     = 0;
642 	unsigned short usToggle    = 0;
643 	unsigned char usByte       = 0;
644 
645 	/*
646 	*
647 	* Check the compression flag only if this is the first time
648 	* this function is entered. Do not check the compression flag if
649 	* it is being called recursively from other functions within
650 	* the embedded engine.
651 	*
652 	*/
653 
654 	if (!(g_usDataType & LHEAP_IN) && !(g_usDataType & HEAP_IN)) {
655 		usByte = GetByte();
656 		if (usByte == 0xf1) {
657 			g_usDataType |= COMPRESS;
658 		} else if (usByte == 0xf2) {
659 			g_usDataType &= ~COMPRESS;
660 		} else {
661 			return VME_INVALID_FILE;
662 		}
663 	}
664 
665 	/*
666 	*
667 	* Begin looping through all the VME opcodes.
668 	*
669 	*/
670 
671 	while ((cOpcode = GetByte()) >= 0) {
672 
673 		switch (cOpcode) {
674 		case STATE:
675 
676 			/*
677 			 * Step the JTAG state machine.
678 			 */
679 
680 			ucState = GetByte();
681 
682 			/*
683 			 * Step the JTAG state machine to DRCAPTURE
684 			 * to support Looping.
685 			 */
686 
687 			if ((g_usDataType & LHEAP_IN) &&
688 				 (ucState == DRPAUSE) &&
689 				 (g_cCurrentJTAGState == ucState)) {
690 				ispVMStateMachine(DRCAPTURE);
691 			}
692 
693 			ispVMStateMachine(ucState);
694 
695 #ifdef DEBUG
696 			if (g_usDataType & LHEAP_IN) {
697 				debug("LDELAY %s ", GetState(ucState));
698 			} else {
699 				debug("STATE %s;\n", GetState(ucState));
700 			}
701 #endif /* DEBUG */
702 			break;
703 		case SIR:
704 		case SDR:
705 		case XSDR:
706 
707 #ifdef DEBUG
708 			switch (cOpcode) {
709 			case SIR:
710 				puts("SIR ");
711 				break;
712 			case SDR:
713 			case XSDR:
714 				if (g_usDataType & LHEAP_IN) {
715 					puts("LSDR ");
716 				} else {
717 					puts("SDR ");
718 				}
719 				break;
720 			}
721 #endif /* DEBUG */
722 			/*
723 			*
724 			* Shift in data into the device.
725 			*
726 			*/
727 
728 			cRetCode = ispVMShift(cOpcode);
729 			if (cRetCode != 0) {
730 				return cRetCode;
731 			}
732 			break;
733 		case WAIT:
734 
735 			/*
736 			*
737 			* Observe delay.
738 			*
739 			*/
740 
741 			/* 09/11/07 NN Type cast mismatch variables */
742 			usDelay = (unsigned short) ispVMDataSize();
743 			ispVMDelay(usDelay);
744 
745 #ifdef DEBUG
746 			if (usDelay & 0x8000) {
747 
748 				/*
749 				 * Since MSB is set, the delay time must be
750 				 * decoded to millisecond. The SVF2VME encodes
751 				 * the MSB to represent millisecond.
752 				 */
753 
754 				usDelay &= ~0x8000;
755 				if (g_usDataType & LHEAP_IN) {
756 					printf("%.2E SEC;\n",
757 						(float) usDelay / 1000);
758 				} else {
759 					printf("RUNTEST %.2E SEC;\n",
760 						(float) usDelay / 1000);
761 				}
762 			} else {
763 				/*
764 				 * Since MSB is not set, the delay time
765 				 * is given as microseconds.
766 				 */
767 
768 				if (g_usDataType & LHEAP_IN) {
769 					printf("%.2E SEC;\n",
770 						(float) usDelay / 1000000);
771 				} else {
772 					printf("RUNTEST %.2E SEC;\n",
773 						(float) usDelay / 1000000);
774 				}
775 			}
776 #endif /* DEBUG */
777 			break;
778 		case TCK:
779 
780 			/*
781 			 * Issue clock toggles.
782 			*/
783 
784 			/* 09/11/07 NN Type cast mismatch variables */
785 			usToggle = (unsigned short) ispVMDataSize();
786 			ispVMClocks(usToggle);
787 
788 #ifdef DEBUG
789 			printf("RUNTEST %d TCK;\n", usToggle);
790 #endif /* DEBUG */
791 			break;
792 		case ENDDR:
793 
794 			/*
795 			*
796 			* Set the ENDDR.
797 			*
798 			*/
799 
800 			g_ucEndDR = GetByte();
801 
802 #ifdef DEBUG
803 			printf("ENDDR %s;\n", GetState(g_ucEndDR));
804 #endif /* DEBUG */
805 			break;
806 		case ENDIR:
807 
808 			/*
809 			*
810 			* Set the ENDIR.
811 			*
812 			*/
813 
814 			g_ucEndIR = GetByte();
815 
816 #ifdef DEBUG
817 			printf("ENDIR %s;\n", GetState(g_ucEndIR));
818 #endif /* DEBUG */
819 			break;
820 		case HIR:
821 		case TIR:
822 		case HDR:
823 		case TDR:
824 
825 #ifdef DEBUG
826 			switch (cOpcode) {
827 			case HIR:
828 				puts("HIR ");
829 				break;
830 			case TIR:
831 				puts("TIR ");
832 				break;
833 			case HDR:
834 				puts("HDR ");
835 				break;
836 			case TDR:
837 				puts("TDR ");
838 				break;
839 			}
840 #endif /* DEBUG */
841 			/*
842 			 * Set the header/trailer of the device in order
843 			 * to bypass
844 			 * successfully.
845 			 */
846 
847 			cRetCode = ispVMAmble(cOpcode);
848 			if (cRetCode != 0) {
849 				return cRetCode;
850 			}
851 
852 #ifdef DEBUG
853 			puts(";\n");
854 #endif /* DEBUG */
855 			break;
856 		case MEM:
857 
858 			/*
859 			 * The maximum RAM required to support
860 			 * processing one row of the VME file.
861 			 */
862 
863 			/* 09/11/07 NN Type cast mismatch variables */
864 			g_usMaxSize = (unsigned short) ispVMDataSize();
865 
866 #ifdef DEBUG
867 			printf("// MEMSIZE %d\n", g_usMaxSize);
868 #endif /* DEBUG */
869 			break;
870 		case VENDOR:
871 
872 			/*
873 			*
874 			* Set the VENDOR type.
875 			*
876 			*/
877 
878 			cOpcode = GetByte();
879 			switch (cOpcode) {
880 			case LATTICE:
881 #ifdef DEBUG
882 				puts("// VENDOR LATTICE\n");
883 #endif /* DEBUG */
884 				g_cVendor = LATTICE;
885 				break;
886 			case ALTERA:
887 #ifdef DEBUG
888 				puts("// VENDOR ALTERA\n");
889 #endif /* DEBUG */
890 				g_cVendor = ALTERA;
891 				break;
892 			case XILINX:
893 #ifdef DEBUG
894 				puts("// VENDOR XILINX\n");
895 #endif /* DEBUG */
896 				g_cVendor = XILINX;
897 				break;
898 			default:
899 				break;
900 			}
901 			break;
902 		case SETFLOW:
903 
904 			/*
905 			 * Set the flow control. Flow control determines
906 			 * the personality of the embedded engine.
907 			 */
908 
909 			/* 09/11/07 NN Type cast mismatch variables */
910 			g_usFlowControl |= (unsigned short) ispVMDataSize();
911 			break;
912 		case RESETFLOW:
913 
914 			/*
915 			*
916 			* Unset the flow control.
917 			*
918 			*/
919 
920 			/* 09/11/07 NN Type cast mismatch variables */
921 			g_usFlowControl &= (unsigned short) ~(ispVMDataSize());
922 			break;
923 		case HEAP:
924 
925 			/*
926 			*
927 			* Allocate heap size to store loops.
928 			*
929 			*/
930 
931 			cRetCode = GetByte();
932 			if (cRetCode != SECUREHEAP) {
933 				return VME_INVALID_FILE;
934 			}
935 			/* 09/11/07 NN Type cast mismatch variables */
936 			g_iHEAPSize = (unsigned short) ispVMDataSize();
937 
938 			/*
939 			 * Store the maximum size of the HEAP buffer.
940 			 * Used to convert VME to HEX.
941 			 */
942 
943 			if (g_iHEAPSize > g_usHeapSize) {
944 				g_usHeapSize = g_iHEAPSize;
945 			}
946 
947 			ispVMMemManager(HEAP, (unsigned short) g_iHEAPSize);
948 			break;
949 		case REPEAT:
950 
951 			/*
952 			*
953 			* Execute loops.
954 			*
955 			*/
956 
957 			g_usRepeatLoops = 0;
958 
959 			/* 09/11/07 NN Type cast mismatch variables */
960 			iRepeatSize = (unsigned short) ispVMDataSize();
961 
962 			cRetCode = ispVMLoop((unsigned short) iRepeatSize);
963 			if (cRetCode != 0) {
964 				return cRetCode;
965 			}
966 			break;
967 		case ENDLOOP:
968 
969 			/*
970 			*
971 			* Exit point from processing loops.
972 			*
973 			*/
974 
975 			return cRetCode;
976 		case ENDVME:
977 
978 			/*
979 			 * The only valid exit point that indicates
980 			 * end of programming.
981 			 */
982 
983 			return cRetCode;
984 		case SHR:
985 
986 			/*
987 			*
988 			* Right-shift address.
989 			*
990 			*/
991 
992 			g_usFlowControl |= SHIFTRIGHT;
993 
994 			/* 09/11/07 NN Type cast mismatch variables */
995 			g_usShiftValue = (unsigned short) (g_usRepeatLoops *
996 				(unsigned short)GetByte());
997 			break;
998 		case SHL:
999 
1000 			/*
1001 			 * Left-shift address.
1002 			 */
1003 
1004 			g_usFlowControl |= SHIFTLEFT;
1005 
1006 			/* 09/11/07 NN Type cast mismatch variables */
1007 			g_usShiftValue = (unsigned short) (g_usRepeatLoops *
1008 				(unsigned short)GetByte());
1009 			break;
1010 		case FREQUENCY:
1011 
1012 			/*
1013 			*
1014 			* Set the frequency.
1015 			*
1016 			*/
1017 
1018 			/* 09/11/07 NN Type cast mismatch variables */
1019 			g_iFrequency = (int) (ispVMDataSize() / 1000);
1020 			if (g_iFrequency == 1)
1021 				g_iFrequency = 1000;
1022 
1023 #ifdef DEBUG
1024 			printf("FREQUENCY %.2E HZ;\n",
1025 				(float) g_iFrequency * 1000);
1026 #endif /* DEBUG */
1027 			break;
1028 		case LCOUNT:
1029 
1030 			/*
1031 			*
1032 			* Process LCOUNT command.
1033 			*
1034 			*/
1035 
1036 			cRetCode = ispVMLCOUNT((unsigned short)ispVMDataSize());
1037 			if (cRetCode != 0) {
1038 				return cRetCode;
1039 			}
1040 			break;
1041 		case VUES:
1042 
1043 			/*
1044 			*
1045 			* Set the flow control to verify USERCODE.
1046 			*
1047 			*/
1048 
1049 			g_usFlowControl |= VERIFYUES;
1050 			break;
1051 		case COMMENT:
1052 
1053 			/*
1054 			*
1055 			* Display comment.
1056 			*
1057 			*/
1058 
1059 			ispVMComment((unsigned short) ispVMDataSize());
1060 			break;
1061 		case LVDS:
1062 
1063 			/*
1064 			*
1065 			* Process LVDS command.
1066 			*
1067 			*/
1068 
1069 			ispVMProcessLVDS((unsigned short) ispVMDataSize());
1070 			break;
1071 		case HEADER:
1072 
1073 			/*
1074 			*
1075 			* Discard header.
1076 			*
1077 			*/
1078 
1079 			ispVMHeader((unsigned short) ispVMDataSize());
1080 			break;
1081 		/* 03/14/06 Support Toggle ispENABLE signal*/
1082 		case ispEN:
1083 			ucState = GetByte();
1084 			if ((ucState == ON) || (ucState == 0x01))
1085 				writePort(g_ucPinENABLE, 0x01);
1086 			else
1087 				writePort(g_ucPinENABLE, 0x00);
1088 			ispVMDelay(1);
1089 			break;
1090 		/* 05/24/06 support Toggle TRST pin*/
1091 		case TRST:
1092 			ucState = GetByte();
1093 			if (ucState == 0x01)
1094 				writePort(g_ucPinTRST, 0x01);
1095 			else
1096 				writePort(g_ucPinTRST, 0x00);
1097 			ispVMDelay(1);
1098 			break;
1099 		default:
1100 
1101 			/*
1102 			*
1103 			* Invalid opcode encountered.
1104 			*
1105 			*/
1106 
1107 #ifdef DEBUG
1108 			printf("\nINVALID OPCODE: 0x%.2X\n", cOpcode);
1109 #endif /* DEBUG */
1110 
1111 			return VME_INVALID_FILE;
1112 		}
1113 	}
1114 
1115 	/*
1116 	*
1117 	* Invalid exit point. Processing the token 'ENDVME' is the only
1118 	* valid way to exit the embedded engine.
1119 	*
1120 	*/
1121 
1122 	return VME_INVALID_FILE;
1123 }
1124 
1125 /*
1126  *
1127  * ispVMDataCode
1128  *
1129  * Processes the TDI/TDO/MASK/DMASK etc of an SIR/SDR command.
1130  *
1131  */
1132 
1133 signed char ispVMDataCode()
1134 {
1135 	/* 09/11/07 NN added local variables initialization */
1136 	signed char cDataByte    = 0;
1137 	signed char siDataSource = 0;  /*source of data from file by default*/
1138 
1139 	if (g_usDataType & HEAP_IN) {
1140 		siDataSource = 1;  /*the source of data from memory*/
1141 	}
1142 
1143 	/*
1144 	*
1145 	* Clear the data type register.
1146 	*
1147 	**/
1148 
1149 	g_usDataType &= ~(MASK_DATA + TDI_DATA +
1150 		TDO_DATA + DMASK_DATA + CMASK_DATA);
1151 
1152 	/*
1153 	 * Iterate through SIR/SDR command and look for TDI,
1154 	 * TDO, MASK, etc.
1155 	 */
1156 
1157 	while ((cDataByte = GetByte()) >= 0) {
1158 			ispVMMemManager(cDataByte, g_usMaxSize);
1159 			switch (cDataByte) {
1160 			case TDI:
1161 
1162 				/*
1163 				 * Store the maximum size of the TDI buffer.
1164 				 * Used to convert VME to HEX.
1165 				 */
1166 
1167 				if (g_usiDataSize > g_usTDISize) {
1168 					g_usTDISize = g_usiDataSize;
1169 				}
1170 				/*
1171 				 * Updated data type register to indicate that
1172 				 * TDI data is currently being used. Process the
1173 				 * data in the VME file into the TDI buffer.
1174 				 */
1175 
1176 				g_usDataType |= TDI_DATA;
1177 				ispVMData(g_pucInData);
1178 				break;
1179 			case XTDO:
1180 
1181 				/*
1182 				 * Store the maximum size of the TDO buffer.
1183 				 * Used to convert VME to HEX.
1184 				 */
1185 
1186 				if (g_usiDataSize > g_usTDOSize) {
1187 					g_usTDOSize = g_usiDataSize;
1188 				}
1189 
1190 				/*
1191 				 * Updated data type register to indicate that
1192 				 * TDO data is currently being used.
1193 				 */
1194 
1195 				g_usDataType |= TDO_DATA;
1196 				break;
1197 			case TDO:
1198 
1199 				/*
1200 				 * Store the maximum size of the TDO buffer.
1201 				 * Used to convert VME to HEX.
1202 				 */
1203 
1204 				if (g_usiDataSize > g_usTDOSize) {
1205 					g_usTDOSize = g_usiDataSize;
1206 				}
1207 
1208 				/*
1209 				 * Updated data type register to indicate
1210 				 * that TDO data is currently being used.
1211 				 * Process the data in the VME file into the
1212 				 * TDO buffer.
1213 				 */
1214 
1215 				g_usDataType |= TDO_DATA;
1216 				ispVMData(g_pucOutData);
1217 				break;
1218 			case MASK:
1219 
1220 				/*
1221 				 * Store the maximum size of the MASK buffer.
1222 				 * Used to convert VME to HEX.
1223 				 */
1224 
1225 				if (g_usiDataSize > g_usMASKSize) {
1226 					g_usMASKSize = g_usiDataSize;
1227 				}
1228 
1229 				/*
1230 				 * Updated data type register to indicate that
1231 				 * MASK data is currently being used. Process
1232 				 * the data in the VME file into the MASK buffer
1233 				 */
1234 
1235 				g_usDataType |= MASK_DATA;
1236 				ispVMData(g_pucOutMaskData);
1237 				break;
1238 			case DMASK:
1239 
1240 				/*
1241 				 * Store the maximum size of the DMASK buffer.
1242 				 * Used to convert VME to HEX.
1243 				 */
1244 
1245 				if (g_usiDataSize > g_usDMASKSize) {
1246 					g_usDMASKSize = g_usiDataSize;
1247 				}
1248 
1249 				/*
1250 				 * Updated data type register to indicate that
1251 				 * DMASK data is currently being used. Process
1252 				 * the data in the VME file into the DMASK
1253 				 * buffer.
1254 				 */
1255 
1256 				g_usDataType |= DMASK_DATA;
1257 				ispVMData(g_pucOutDMaskData);
1258 				break;
1259 			case CMASK:
1260 
1261 				/*
1262 				 * Updated data type register to indicate that
1263 				 * MASK data is currently being used. Process
1264 				 * the data in the VME file into the MASK buffer
1265 				 */
1266 
1267 				g_usDataType |= CMASK_DATA;
1268 				ispVMData(g_pucOutMaskData);
1269 				break;
1270 			case CONTINUE:
1271 				return 0;
1272 			default:
1273 				/*
1274 				 * Encountered invalid opcode.
1275 				 */
1276 				return VME_INVALID_FILE;
1277 			}
1278 
1279 			switch (cDataByte) {
1280 			case TDI:
1281 
1282 				/*
1283 				 * Left bit shift. Used when performing
1284 				 * algorithm looping.
1285 				 */
1286 
1287 				if (g_usFlowControl & SHIFTLEFT) {
1288 					ispVMBitShift(SHL, g_usShiftValue);
1289 					g_usFlowControl &= ~SHIFTLEFT;
1290 				}
1291 
1292 				/*
1293 				 * Right bit shift. Used when performing
1294 				 * algorithm looping.
1295 				 */
1296 
1297 				if (g_usFlowControl & SHIFTRIGHT) {
1298 					ispVMBitShift(SHR, g_usShiftValue);
1299 					g_usFlowControl &= ~SHIFTRIGHT;
1300 				}
1301 			default:
1302 				break;
1303 			}
1304 
1305 			if (siDataSource) {
1306 				g_usDataType |= HEAP_IN; /*restore from memory*/
1307 			}
1308 	}
1309 
1310 	if (siDataSource) {  /*fetch data from heap memory upon return*/
1311 		g_usDataType |= HEAP_IN;
1312 	}
1313 
1314 	if (cDataByte < 0) {
1315 
1316 		/*
1317 		 * Encountered invalid opcode.
1318 		 */
1319 
1320 		return VME_INVALID_FILE;
1321 	} else {
1322 		return 0;
1323 	}
1324 }
1325 
1326 /*
1327  *
1328  * ispVMData
1329  * Extract one row of data operand from the current data type opcode. Perform
1330  * the decompression if necessary. Extra RAM is not required for the
1331  * decompression process. The decompression scheme employed in this module
1332  * is on row by row basis. The format of the data stream:
1333  * [compression code][compressed data stream]
1334  * 0x00    --No compression
1335  * 0x01    --Compress by 0x00.
1336  *           Example:
1337  *           Original stream:   0x000000000000000000000001
1338  *           Compressed stream: 0x01000901
1339  *           Detail:            0x01 is the code, 0x00 is the key,
1340  *                              0x09 is the count of 0x00 bytes,
1341  *                              0x01 is the uncompressed byte.
1342  * 0x02    --Compress by 0xFF.
1343  *           Example:
1344  *           Original stream:   0xFFFFFFFFFFFFFFFFFFFFFF01
1345  *           Compressed stream: 0x02FF0901
1346  *           Detail:            0x02 is the code, 0xFF is the key,
1347  *                              0x09 is the count of 0xFF bytes,
1348  *                              0x01 is the uncompressed byte.
1349  * 0x03
1350  * : :
1351  * 0xFE   -- Compress by nibble blocks.
1352  *           Example:
1353  *           Original stream:   0x84210842108421084210
1354  *           Compressed stream: 0x0584210
1355  *           Detail:            0x05 is the code, means 5 nibbles block.
1356  *                              0x84210 is the 5 nibble blocks.
1357  *                              The whole row is 80 bits given by g_usiDataSize.
1358  *                              The number of times the block repeat itself
1359  *                              is found by g_usiDataSize/(4*0x05) which is 4.
1360  * 0xFF   -- Compress by the most frequently happen byte.
1361  *           Example:
1362  *           Original stream:   0x04020401030904040404
1363  *           Compressed stream: 0xFF04(0,1,0x02,0,1,0x01,1,0x03,1,0x09,0,0,0)
1364  *                          or: 0xFF044090181C240
1365  *           Detail:            0xFF is the code, 0x04 is the key.
1366  *                              a bit of 0 represent the key shall be put into
1367  *                              the current bit position and a bit of 1
1368  *                              represent copying the next of 8 bits of data
1369  *                              in.
1370  *
1371  */
1372 
1373 void ispVMData(unsigned char *ByteData)
1374 {
1375 	/* 09/11/07 NN added local variables initialization */
1376 	unsigned short size               = 0;
1377 	unsigned short i, j, m, getData   = 0;
1378 	unsigned char cDataByte           = 0;
1379 	unsigned char compress            = 0;
1380 	unsigned short FFcount            = 0;
1381 	unsigned char compr_char          = 0xFF;
1382 	unsigned short index              = 0;
1383 	signed char compression           = 0;
1384 
1385 	/*convert number in bits to bytes*/
1386 	if (g_usiDataSize % 8 > 0) {
1387 		/* 09/11/07 NN Type cast mismatch variables */
1388 		size = (unsigned short)(g_usiDataSize / 8 + 1);
1389 	} else {
1390 		/* 09/11/07 NN Type cast mismatch variables */
1391 		size = (unsigned short)(g_usiDataSize / 8);
1392 	}
1393 
1394 	/*
1395 	 * If there is compression, then check if compress by key
1396 	 * of 0x00 or 0xFF or by other keys or by nibble blocks
1397 	 */
1398 
1399 	if (g_usDataType & COMPRESS) {
1400 		compression = 1;
1401 		compress = GetByte();
1402 		if ((compress  == VAR) && (g_usDataType & HEAP_IN)) {
1403 			getData = 1;
1404 			g_usDataType &= ~(HEAP_IN);
1405 			compress = GetByte();
1406 		}
1407 
1408 		switch (compress) {
1409 		case 0x00:
1410 			/* No compression */
1411 			compression = 0;
1412 			break;
1413 		case 0x01:
1414 			/* Compress by byte 0x00 */
1415 			compr_char = 0x00;
1416 			break;
1417 		case 0x02:
1418 			/* Compress by byte 0xFF */
1419 			compr_char = 0xFF;
1420 			break;
1421 		case 0xFF:
1422 			/* Huffman encoding */
1423 			compr_char = GetByte();
1424 			i = 8;
1425 			for (index = 0; index < size; index++) {
1426 				ByteData[index] = 0x00;
1427 				if (i > 7) {
1428 					cDataByte = GetByte();
1429 					i = 0;
1430 				}
1431 				if ((cDataByte << i++) & 0x80)
1432 					m = 8;
1433 				else {
1434 					ByteData[index] = compr_char;
1435 					m = 0;
1436 				}
1437 
1438 				for (j = 0; j < m; j++) {
1439 					if (i > 7) {
1440 						cDataByte = GetByte();
1441 						i = 0;
1442 					}
1443 					ByteData[index] |=
1444 					((cDataByte << i++) & 0x80) >> j;
1445 				}
1446 			}
1447 			size = 0;
1448 			break;
1449 		default:
1450 			for (index = 0; index < size; index++)
1451 				ByteData[index] = 0x00;
1452 			for (index = 0; index < compress; index++) {
1453 				if (index % 2 == 0)
1454 					cDataByte = GetByte();
1455 				for (i = 0; i < size * 2 / compress; i++) {
1456 					j = (unsigned short)(index +
1457 						(i * (unsigned short)compress));
1458 					/*clear the nibble to zero first*/
1459 					if (j%2) {
1460 						if (index % 2)
1461 							ByteData[j/2] |=
1462 								cDataByte & 0xF;
1463 						else
1464 							ByteData[j/2] |=
1465 								cDataByte >> 4;
1466 					} else {
1467 						if (index % 2)
1468 							ByteData[j/2] |=
1469 								cDataByte << 4;
1470 						else
1471 							ByteData[j/2] |=
1472 							cDataByte & 0xF0;
1473 					}
1474 				}
1475 			}
1476 			size = 0;
1477 			break;
1478 		}
1479 	}
1480 
1481 	FFcount = 0;
1482 
1483 	/* Decompress by byte 0x00 or 0xFF */
1484 	for (index = 0; index < size; index++) {
1485 		if (FFcount <= 0) {
1486 			cDataByte = GetByte();
1487 			if ((cDataByte == VAR) && (g_usDataType&HEAP_IN) &&
1488 				!getData && !(g_usDataType&COMPRESS)) {
1489 				getData = 1;
1490 				g_usDataType &= ~(HEAP_IN);
1491 				cDataByte = GetByte();
1492 			}
1493 			ByteData[index] = cDataByte;
1494 			if ((compression) && (cDataByte == compr_char))
1495 				/* 09/11/07 NN Type cast mismatch variables */
1496 				FFcount = (unsigned short) ispVMDataSize();
1497 				/*The number of 0xFF or 0x00 bytes*/
1498 		} else {
1499 			FFcount--; /*Use up the 0xFF chain first*/
1500 			ByteData[index] = compr_char;
1501 		}
1502 	}
1503 
1504 	if (getData) {
1505 		g_usDataType |= HEAP_IN;
1506 		getData = 0;
1507 	}
1508 }
1509 
1510 /*
1511  *
1512  * ispVMShift
1513  *
1514  * Processes the SDR/XSDR/SIR commands.
1515  *
1516  */
1517 
1518 signed char ispVMShift(signed char a_cCode)
1519 {
1520 	/* 09/11/07 NN added local variables initialization */
1521 	unsigned short iDataIndex  = 0;
1522 	unsigned short iReadLoop   = 0;
1523 	signed char cRetCode       = 0;
1524 
1525 	cRetCode = 0;
1526 	/* 09/11/07 NN Type cast mismatch variables */
1527 	g_usiDataSize = (unsigned short) ispVMDataSize();
1528 
1529 	/*clear the flags first*/
1530 	g_usDataType &= ~(SIR_DATA + EXPRESS + SDR_DATA);
1531 	switch (a_cCode) {
1532 	case SIR:
1533 		g_usDataType |= SIR_DATA;
1534 		/*
1535 		 * 1/15/04 If performing cascading, then go directly to SHIFTIR.
1536 		 *  Else, go to IRPAUSE before going to SHIFTIR
1537 		 */
1538 		if (g_usFlowControl & CASCADE) {
1539 			ispVMStateMachine(SHIFTIR);
1540 		} else {
1541 			ispVMStateMachine(IRPAUSE);
1542 			ispVMStateMachine(SHIFTIR);
1543 			if (g_usHeadIR > 0) {
1544 				ispVMBypass(HIR, g_usHeadIR);
1545 				sclock();
1546 			}
1547 		}
1548 		break;
1549 	case XSDR:
1550 		g_usDataType |= EXPRESS; /*mark simultaneous in and out*/
1551 	case SDR:
1552 		g_usDataType |= SDR_DATA;
1553 		/*
1554 		 * 1/15/04 If already in SHIFTDR, then do not move state or
1555 		 * shift in header.  This would imply that the previously
1556 		 * shifted frame was a cascaded frame.
1557 		 */
1558 		if (g_cCurrentJTAGState != SHIFTDR) {
1559 			/*
1560 			 * 1/15/04 If performing cascading, then go directly
1561 			 * to SHIFTDR.  Else, go to DRPAUSE before going
1562 			 * to SHIFTDR
1563 			 */
1564 			if (g_usFlowControl & CASCADE) {
1565 				if (g_cCurrentJTAGState == DRPAUSE) {
1566 					ispVMStateMachine(SHIFTDR);
1567 					/*
1568 					 * 1/15/04 If cascade flag has been seat
1569 					 * and the current state is DRPAUSE,
1570 					 * this implies that the first cascaded
1571 					 * frame is about to be shifted in.  The
1572 					 * header must be shifted prior to
1573 					 * shifting the first cascaded frame.
1574 					 */
1575 					if (g_usHeadDR > 0) {
1576 						ispVMBypass(HDR, g_usHeadDR);
1577 						sclock();
1578 					}
1579 				} else {
1580 					ispVMStateMachine(SHIFTDR);
1581 				}
1582 			} else {
1583 				ispVMStateMachine(DRPAUSE);
1584 				ispVMStateMachine(SHIFTDR);
1585 				if (g_usHeadDR > 0) {
1586 					ispVMBypass(HDR, g_usHeadDR);
1587 					sclock();
1588 				}
1589 			}
1590 		}
1591 		break;
1592 	default:
1593 		return VME_INVALID_FILE;
1594 	}
1595 
1596 	cRetCode = ispVMDataCode();
1597 
1598 	if (cRetCode != 0) {
1599 		return VME_INVALID_FILE;
1600 	}
1601 
1602 #ifdef DEBUG
1603 	printf("%d ", g_usiDataSize);
1604 
1605 	if (g_usDataType & TDI_DATA) {
1606 		puts("TDI ");
1607 		PrintData(g_usiDataSize, g_pucInData);
1608 	}
1609 
1610 	if (g_usDataType & TDO_DATA) {
1611 		puts("\n\t\tTDO ");
1612 		PrintData(g_usiDataSize, g_pucOutData);
1613 	}
1614 
1615 	if (g_usDataType & MASK_DATA) {
1616 		puts("\n\t\tMASK ");
1617 		PrintData(g_usiDataSize, g_pucOutMaskData);
1618 	}
1619 
1620 	if (g_usDataType & DMASK_DATA) {
1621 		puts("\n\t\tDMASK ");
1622 		PrintData(g_usiDataSize, g_pucOutDMaskData);
1623 	}
1624 
1625 	puts(";\n");
1626 #endif /* DEBUG */
1627 
1628 	if (g_usDataType & TDO_DATA || g_usDataType & DMASK_DATA) {
1629 		if (g_usDataType & DMASK_DATA) {
1630 			cRetCode = ispVMReadandSave(g_usiDataSize);
1631 			if (!cRetCode) {
1632 				if (g_usTailDR > 0) {
1633 					sclock();
1634 					ispVMBypass(TDR, g_usTailDR);
1635 				}
1636 				ispVMStateMachine(DRPAUSE);
1637 				ispVMStateMachine(SHIFTDR);
1638 				if (g_usHeadDR > 0) {
1639 					ispVMBypass(HDR, g_usHeadDR);
1640 					sclock();
1641 				}
1642 				for (iDataIndex = 0;
1643 					iDataIndex < g_usiDataSize / 8 + 1;
1644 					iDataIndex++)
1645 					g_pucInData[iDataIndex] =
1646 						g_pucOutData[iDataIndex];
1647 				g_usDataType &= ~(TDO_DATA + DMASK_DATA);
1648 				cRetCode = ispVMSend(g_usiDataSize);
1649 			}
1650 		} else {
1651 			cRetCode = ispVMRead(g_usiDataSize);
1652 			if (cRetCode == -1 && g_cVendor == XILINX) {
1653 				for (iReadLoop = 0; iReadLoop < 30;
1654 					iReadLoop++) {
1655 					cRetCode = ispVMRead(g_usiDataSize);
1656 					if (!cRetCode) {
1657 						break;
1658 					} else {
1659 						/* Always DRPAUSE */
1660 						ispVMStateMachine(DRPAUSE);
1661 						/*
1662 						 * Bypass other devices
1663 						 * when appropriate
1664 						 */
1665 						ispVMBypass(TDR, g_usTailDR);
1666 						ispVMStateMachine(g_ucEndDR);
1667 						ispVMStateMachine(IDLE);
1668 						ispVMDelay(1000);
1669 					}
1670 				}
1671 			}
1672 		}
1673 	} else { /*TDI only*/
1674 		cRetCode = ispVMSend(g_usiDataSize);
1675 	}
1676 
1677 	/*transfer the input data to the output buffer for the next verify*/
1678 	if ((g_usDataType & EXPRESS) || (a_cCode == SDR)) {
1679 		if (g_pucOutData) {
1680 			for (iDataIndex = 0; iDataIndex < g_usiDataSize / 8 + 1;
1681 				iDataIndex++)
1682 				g_pucOutData[iDataIndex] =
1683 					g_pucInData[iDataIndex];
1684 		}
1685 	}
1686 
1687 	switch (a_cCode) {
1688 	case SIR:
1689 		/* 1/15/04 If not performing cascading, then shift ENDIR */
1690 		if (!(g_usFlowControl & CASCADE)) {
1691 			if (g_usTailIR > 0) {
1692 				sclock();
1693 				ispVMBypass(TIR, g_usTailIR);
1694 			}
1695 			ispVMStateMachine(g_ucEndIR);
1696 		}
1697 		break;
1698 	case XSDR:
1699 	case SDR:
1700 		/* 1/15/04 If not performing cascading, then shift ENDDR */
1701 		if (!(g_usFlowControl & CASCADE)) {
1702 			if (g_usTailDR > 0) {
1703 				sclock();
1704 				ispVMBypass(TDR, g_usTailDR);
1705 			}
1706 			ispVMStateMachine(g_ucEndDR);
1707 		}
1708 		break;
1709 	default:
1710 		break;
1711 	}
1712 
1713 	return cRetCode;
1714 }
1715 
1716 /*
1717  *
1718  * ispVMAmble
1719  *
1720  * This routine is to extract Header and Trailer parameter for SIR and
1721  * SDR operations.
1722  *
1723  * The Header and Trailer parameter are the pre-amble and post-amble bit
1724  * stream need to be shifted into TDI or out of TDO of the devices. Mostly
1725  * is for the purpose of bypassing the leading or trailing devices. ispVM
1726  * supports only shifting data into TDI to bypass the devices.
1727  *
1728  * For a single device, the header and trailer parameters are all set to 0
1729  * as default by ispVM. If it is for multiple devices, the header and trailer
1730  * value will change as specified by the VME file.
1731  *
1732  */
1733 
1734 signed char ispVMAmble(signed char Code)
1735 {
1736 	signed char compress = 0;
1737 	/* 09/11/07 NN Type cast mismatch variables */
1738 	g_usiDataSize = (unsigned short)ispVMDataSize();
1739 
1740 #ifdef DEBUG
1741 	printf("%d", g_usiDataSize);
1742 #endif /* DEBUG */
1743 
1744 	if (g_usiDataSize) {
1745 
1746 		/*
1747 		 * Discard the TDI byte and set the compression bit in the data
1748 		 * type register to false if compression is set because TDI data
1749 		 * after HIR/HDR/TIR/TDR is not compressed.
1750 		 */
1751 
1752 		GetByte();
1753 		if (g_usDataType & COMPRESS) {
1754 			g_usDataType &= ~(COMPRESS);
1755 			compress = 1;
1756 		}
1757 	}
1758 
1759 	switch (Code) {
1760 	case HIR:
1761 
1762 		/*
1763 		 * Store the maximum size of the HIR buffer.
1764 		 * Used to convert VME to HEX.
1765 		 */
1766 
1767 		if (g_usiDataSize > g_usHIRSize) {
1768 			g_usHIRSize = g_usiDataSize;
1769 		}
1770 
1771 		/*
1772 		 * Assign the HIR value and allocate memory.
1773 		 */
1774 
1775 		g_usHeadIR = g_usiDataSize;
1776 		if (g_usHeadIR) {
1777 			ispVMMemManager(HIR, g_usHeadIR);
1778 			ispVMData(g_pucHIRData);
1779 
1780 #ifdef DEBUG
1781 			puts(" TDI ");
1782 			PrintData(g_usHeadIR, g_pucHIRData);
1783 #endif /* DEBUG */
1784 		}
1785 		break;
1786 	case TIR:
1787 
1788 		/*
1789 		 * Store the maximum size of the TIR buffer.
1790 		 * Used to convert VME to HEX.
1791 		 */
1792 
1793 		if (g_usiDataSize > g_usTIRSize) {
1794 			g_usTIRSize = g_usiDataSize;
1795 		}
1796 
1797 		/*
1798 		 * Assign the TIR value and allocate memory.
1799 		 */
1800 
1801 		g_usTailIR = g_usiDataSize;
1802 		if (g_usTailIR) {
1803 			ispVMMemManager(TIR, g_usTailIR);
1804 			ispVMData(g_pucTIRData);
1805 
1806 #ifdef DEBUG
1807 			puts(" TDI ");
1808 			PrintData(g_usTailIR, g_pucTIRData);
1809 #endif /* DEBUG */
1810 		}
1811 		break;
1812 	case HDR:
1813 
1814 		/*
1815 		 * Store the maximum size of the HDR buffer.
1816 		 * Used to convert VME to HEX.
1817 		 */
1818 
1819 		if (g_usiDataSize > g_usHDRSize) {
1820 			g_usHDRSize = g_usiDataSize;
1821 		}
1822 
1823 		/*
1824 		 * Assign the HDR value and allocate memory.
1825 		 *
1826 		 */
1827 
1828 		g_usHeadDR = g_usiDataSize;
1829 		if (g_usHeadDR) {
1830 			ispVMMemManager(HDR, g_usHeadDR);
1831 			ispVMData(g_pucHDRData);
1832 
1833 #ifdef DEBUG
1834 			puts(" TDI ");
1835 			PrintData(g_usHeadDR, g_pucHDRData);
1836 #endif /* DEBUG */
1837 		}
1838 		break;
1839 	case TDR:
1840 
1841 		/*
1842 		 * Store the maximum size of the TDR buffer.
1843 		 * Used to convert VME to HEX.
1844 		 */
1845 
1846 		if (g_usiDataSize > g_usTDRSize) {
1847 			g_usTDRSize = g_usiDataSize;
1848 		}
1849 
1850 		/*
1851 		 * Assign the TDR value and allocate memory.
1852 		 *
1853 		 */
1854 
1855 		g_usTailDR = g_usiDataSize;
1856 		if (g_usTailDR) {
1857 			ispVMMemManager(TDR, g_usTailDR);
1858 			ispVMData(g_pucTDRData);
1859 
1860 #ifdef DEBUG
1861 			puts(" TDI ");
1862 			PrintData(g_usTailDR, g_pucTDRData);
1863 #endif /* DEBUG */
1864 		}
1865 		break;
1866 	default:
1867 		break;
1868 	}
1869 
1870 	/*
1871 	*
1872 	* Re-enable compression if it was previously set.
1873 	*
1874 	**/
1875 
1876 	if (compress) {
1877 		g_usDataType |= COMPRESS;
1878 	}
1879 
1880 	if (g_usiDataSize) {
1881 		Code = GetByte();
1882 		if (Code == CONTINUE) {
1883 			return 0;
1884 		} else {
1885 
1886 			/*
1887 			 * Encountered invalid opcode.
1888 			 */
1889 
1890 			return VME_INVALID_FILE;
1891 		}
1892 	}
1893 
1894 	return 0;
1895 }
1896 
1897 /*
1898  *
1899  * ispVMLoop
1900  *
1901  * Perform the function call upon by the REPEAT opcode.
1902  * Memory is to be allocated to store the entire loop from REPEAT to ENDLOOP.
1903  * After the loop is stored then execution begin. The REPEATLOOP flag is set
1904  * on the g_usFlowControl register to indicate the repeat loop is in session
1905  * and therefore fetch opcode from the memory instead of from the file.
1906  *
1907  */
1908 
1909 signed char ispVMLoop(unsigned short a_usLoopCount)
1910 {
1911 	/* 09/11/07 NN added local variables initialization */
1912 	signed char cRetCode      = 0;
1913 	unsigned short iHeapIndex = 0;
1914 	unsigned short iLoopIndex = 0;
1915 
1916 	g_usShiftValue = 0;
1917 	for (iHeapIndex = 0; iHeapIndex < g_iHEAPSize; iHeapIndex++) {
1918 		g_pucHeapMemory[iHeapIndex] = GetByte();
1919 	}
1920 
1921 	if (g_pucHeapMemory[iHeapIndex - 1] != ENDLOOP) {
1922 		return VME_INVALID_FILE;
1923 	}
1924 
1925 	g_usFlowControl |= REPEATLOOP;
1926 	g_usDataType |= HEAP_IN;
1927 
1928 	for (iLoopIndex = 0; iLoopIndex < a_usLoopCount; iLoopIndex++) {
1929 		g_iHeapCounter = 0;
1930 		cRetCode = ispVMCode();
1931 		g_usRepeatLoops++;
1932 		if (cRetCode < 0) {
1933 			break;
1934 		}
1935 	}
1936 
1937 	g_usDataType &= ~(HEAP_IN);
1938 	g_usFlowControl &= ~(REPEATLOOP);
1939 	return cRetCode;
1940 }
1941 
1942 /*
1943  *
1944  * ispVMBitShift
1945  *
1946  * Shift the TDI stream left or right by the number of bits. The data in
1947  * *g_pucInData is of the VME format, so the actual shifting is the reverse of
1948  * IEEE 1532 or SVF format.
1949  *
1950  */
1951 
1952 signed char ispVMBitShift(signed char mode, unsigned short bits)
1953 {
1954 	/* 09/11/07 NN added local variables initialization */
1955 	unsigned short i       = 0;
1956 	unsigned short size    = 0;
1957 	unsigned short tmpbits = 0;
1958 
1959 	if (g_usiDataSize % 8 > 0) {
1960 		/* 09/11/07 NN Type cast mismatch variables */
1961 		size = (unsigned short)(g_usiDataSize / 8 + 1);
1962 	} else {
1963 		/* 09/11/07 NN Type cast mismatch variables */
1964 		size = (unsigned short)(g_usiDataSize / 8);
1965 	}
1966 
1967 	switch (mode) {
1968 	case SHR:
1969 		for (i = 0; i < size; i++) {
1970 			if (g_pucInData[i] != 0) {
1971 				tmpbits = bits;
1972 				while (tmpbits > 0) {
1973 					g_pucInData[i] <<= 1;
1974 					if (g_pucInData[i] == 0) {
1975 						i--;
1976 						g_pucInData[i] = 1;
1977 					}
1978 					tmpbits--;
1979 				}
1980 			}
1981 		}
1982 		break;
1983 	case SHL:
1984 		for (i = 0; i < size; i++) {
1985 			if (g_pucInData[i] != 0) {
1986 				tmpbits = bits;
1987 				while (tmpbits > 0) {
1988 					g_pucInData[i] >>= 1;
1989 					if (g_pucInData[i] == 0) {
1990 						i--;
1991 						g_pucInData[i] = 8;
1992 					}
1993 					tmpbits--;
1994 				}
1995 			}
1996 		}
1997 		break;
1998 	default:
1999 		return VME_INVALID_FILE;
2000 	}
2001 
2002 	return 0;
2003 }
2004 
2005 /*
2006  *
2007  * ispVMComment
2008  *
2009  * Displays the SVF comments.
2010  *
2011  */
2012 
2013 void ispVMComment(unsigned short a_usCommentSize)
2014 {
2015 	char cCurByte = 0;
2016 	for (; a_usCommentSize > 0; a_usCommentSize--) {
2017 		/*
2018 		*
2019 		* Print character to the terminal.
2020 		*
2021 		**/
2022 		cCurByte = GetByte();
2023 		vme_out_char(cCurByte);
2024 	}
2025 	cCurByte = '\n';
2026 	vme_out_char(cCurByte);
2027 }
2028 
2029 /*
2030  *
2031  * ispVMHeader
2032  *
2033  * Iterate the length of the header and discard it.
2034  *
2035  */
2036 
2037 void ispVMHeader(unsigned short a_usHeaderSize)
2038 {
2039 	for (; a_usHeaderSize > 0; a_usHeaderSize--) {
2040 		GetByte();
2041 	}
2042 }
2043 
2044 /*
2045  *
2046  * ispVMCalculateCRC32
2047  *
2048  * Calculate the 32-bit CRC.
2049  *
2050  */
2051 
2052 void ispVMCalculateCRC32(unsigned char a_ucData)
2053 {
2054 	/* 09/11/07 NN added local variables initialization */
2055 	unsigned char ucIndex          = 0;
2056 	unsigned char ucFlipData       = 0;
2057 	unsigned short usCRCTableEntry = 0;
2058 	unsigned int crc_table[16] = {
2059 		0x0000, 0xCC01, 0xD801,
2060 		0x1400, 0xF001, 0x3C00,
2061 		0x2800, 0xE401, 0xA001,
2062 		0x6C00, 0x7800, 0xB401,
2063 		0x5000, 0x9C01, 0x8801,
2064 		0x4400
2065 	};
2066 
2067 	for (ucIndex = 0; ucIndex < 8; ucIndex++) {
2068 		ucFlipData <<= 1;
2069 		if (a_ucData & 0x01) {
2070 			ucFlipData |= 0x01;
2071 		}
2072 		a_ucData >>= 1;
2073 	}
2074 
2075 	/* 09/11/07 NN Type cast mismatch variables */
2076 	usCRCTableEntry = (unsigned short)(crc_table[g_usCalculatedCRC & 0xF]);
2077 	g_usCalculatedCRC = (unsigned short)((g_usCalculatedCRC >> 4) & 0x0FFF);
2078 	g_usCalculatedCRC = (unsigned short)(g_usCalculatedCRC ^
2079 			usCRCTableEntry ^ crc_table[ucFlipData & 0xF]);
2080 	usCRCTableEntry = (unsigned short)(crc_table[g_usCalculatedCRC & 0xF]);
2081 	g_usCalculatedCRC = (unsigned short)((g_usCalculatedCRC >> 4) & 0x0FFF);
2082 	g_usCalculatedCRC = (unsigned short)(g_usCalculatedCRC ^
2083 		usCRCTableEntry ^ crc_table[(ucFlipData >> 4) & 0xF]);
2084 }
2085 
2086 /*
2087  *
2088  * ispVMLCOUNT
2089  *
2090  * Process the intelligent programming loops.
2091  *
2092  */
2093 
2094 signed char ispVMLCOUNT(unsigned short a_usCountSize)
2095 {
2096 	unsigned short usContinue	  = 1;
2097 	unsigned short usIntelBufferIndex = 0;
2098 	unsigned short usCountIndex       = 0;
2099 	signed char cRetCode              = 0;
2100 	signed char cRepeatHeap           = 0;
2101 	signed char cOpcode               = 0;
2102 	unsigned char ucState             = 0;
2103 	unsigned short usDelay            = 0;
2104 	unsigned short usToggle           = 0;
2105 
2106 	g_usIntelBufferSize = (unsigned short)ispVMDataSize();
2107 
2108 	/*
2109 	 * Allocate memory for intel buffer.
2110 	 *
2111 	 */
2112 
2113 	ispVMMemManager(LHEAP, g_usIntelBufferSize);
2114 
2115 	/*
2116 	 * Store the maximum size of the intelligent buffer.
2117 	 * Used to convert VME to HEX.
2118 	 */
2119 
2120 	if (g_usIntelBufferSize > g_usLCOUNTSize) {
2121 		g_usLCOUNTSize = g_usIntelBufferSize;
2122 	}
2123 
2124 	/*
2125 	 * Copy intel data to the buffer.
2126 	 */
2127 
2128 	for (usIntelBufferIndex = 0; usIntelBufferIndex < g_usIntelBufferSize;
2129 		usIntelBufferIndex++) {
2130 		g_pucIntelBuffer[usIntelBufferIndex] = GetByte();
2131 	}
2132 
2133 	/*
2134 	 * Set the data type register to get data from the intelligent
2135 	 * data buffer.
2136 	 */
2137 
2138 	g_usDataType |= LHEAP_IN;
2139 
2140 	/*
2141 	*
2142 	* If the HEAP_IN flag is set, temporarily unset the flag so data will be
2143 	* retrieved from the status buffer.
2144 	*
2145 	**/
2146 
2147 	if (g_usDataType & HEAP_IN) {
2148 		g_usDataType &= ~HEAP_IN;
2149 		cRepeatHeap = 1;
2150 	}
2151 
2152 #ifdef DEBUG
2153 	printf("LCOUNT %d;\n", a_usCountSize);
2154 #endif /* DEBUG */
2155 
2156 	/*
2157 	 * Iterate through the intelligent programming command.
2158 	*/
2159 
2160 	for (usCountIndex = 0; usCountIndex < a_usCountSize; usCountIndex++) {
2161 
2162 		/*
2163 		*
2164 		* Initialize the intel data index to 0 before each iteration.
2165 		*
2166 		**/
2167 
2168 		g_usIntelDataIndex = 0;
2169 		cOpcode            = 0;
2170 		ucState            = 0;
2171 		usDelay            = 0;
2172 		usToggle           = 0;
2173 		usContinue		   = 1;
2174 
2175 		/*
2176 		*
2177 		* Begin looping through all the VME opcodes.
2178 		*
2179 		*/
2180 		/*
2181 		* 4/1/09 Nguyen replaced the recursive function call codes on
2182 		*        the ispVMLCOUNT function
2183 		*
2184 		*/
2185 		while (usContinue) {
2186 			cOpcode = GetByte();
2187 			switch (cOpcode) {
2188 			case HIR:
2189 			case TIR:
2190 			case HDR:
2191 			case TDR:
2192 				/*
2193 				 * Set the header/trailer of the device in order
2194 				 * to bypass successfully.
2195 				 */
2196 
2197 				ispVMAmble(cOpcode);
2198 			break;
2199 			case STATE:
2200 
2201 				/*
2202 				 * Step the JTAG state machine.
2203 				 */
2204 
2205 				ucState = GetByte();
2206 				/*
2207 				 * Step the JTAG state machine to DRCAPTURE
2208 				 * to support Looping.
2209 				 */
2210 
2211 				if ((g_usDataType & LHEAP_IN) &&
2212 					 (ucState == DRPAUSE) &&
2213 					 (g_cCurrentJTAGState == ucState)) {
2214 					ispVMStateMachine(DRCAPTURE);
2215 				}
2216 				ispVMStateMachine(ucState);
2217 #ifdef DEBUG
2218 				printf("LDELAY %s ", GetState(ucState));
2219 #endif /* DEBUG */
2220 				break;
2221 			case SIR:
2222 #ifdef DEBUG
2223 				printf("SIR ");
2224 #endif /* DEBUG */
2225 				/*
2226 				 * Shift in data into the device.
2227 				 */
2228 
2229 				cRetCode = ispVMShift(cOpcode);
2230 				break;
2231 			case SDR:
2232 
2233 #ifdef DEBUG
2234 				printf("LSDR ");
2235 #endif /* DEBUG */
2236 				/*
2237 				 * Shift in data into the device.
2238 				 */
2239 
2240 				cRetCode = ispVMShift(cOpcode);
2241 				break;
2242 			case WAIT:
2243 
2244 				/*
2245 				*
2246 				* Observe delay.
2247 				*
2248 				*/
2249 
2250 				usDelay = (unsigned short)ispVMDataSize();
2251 				ispVMDelay(usDelay);
2252 
2253 #ifdef DEBUG
2254 				if (usDelay & 0x8000) {
2255 
2256 					/*
2257 					 * Since MSB is set, the delay time must
2258 					 * be decoded to millisecond. The
2259 					 * SVF2VME encodes the MSB to represent
2260 					 * millisecond.
2261 					 */
2262 
2263 					usDelay &= ~0x8000;
2264 					printf("%.2E SEC;\n",
2265 						(float) usDelay / 1000);
2266 				} else {
2267 					/*
2268 					 * Since MSB is not set, the delay time
2269 					 * is given as microseconds.
2270 					 */
2271 
2272 					printf("%.2E SEC;\n",
2273 						(float) usDelay / 1000000);
2274 				}
2275 #endif /* DEBUG */
2276 				break;
2277 			case TCK:
2278 
2279 				/*
2280 				 * Issue clock toggles.
2281 				 */
2282 
2283 				usToggle = (unsigned short)ispVMDataSize();
2284 				ispVMClocks(usToggle);
2285 
2286 #ifdef DEBUG
2287 				printf("RUNTEST %d TCK;\n", usToggle);
2288 #endif /* DEBUG */
2289 				break;
2290 			case ENDLOOP:
2291 
2292 				/*
2293 				 * Exit point from processing loops.
2294 				 */
2295 				usContinue = 0;
2296 				break;
2297 
2298 			case COMMENT:
2299 
2300 				/*
2301 				 * Display comment.
2302 				 */
2303 
2304 				ispVMComment((unsigned short) ispVMDataSize());
2305 				break;
2306 			case ispEN:
2307 				ucState = GetByte();
2308 				if ((ucState == ON) || (ucState == 0x01))
2309 					writePort(g_ucPinENABLE, 0x01);
2310 				else
2311 					writePort(g_ucPinENABLE, 0x00);
2312 				ispVMDelay(1);
2313 				break;
2314 			case TRST:
2315 				if (GetByte() == 0x01)
2316 					writePort(g_ucPinTRST, 0x01);
2317 				else
2318 					writePort(g_ucPinTRST, 0x00);
2319 				ispVMDelay(1);
2320 				break;
2321 			default:
2322 
2323 				/*
2324 				 * Invalid opcode encountered.
2325 				 */
2326 
2327 				debug("\nINVALID OPCODE: 0x%.2X\n", cOpcode);
2328 
2329 				return VME_INVALID_FILE;
2330 			}
2331 		}
2332 		if (cRetCode >= 0) {
2333 			/*
2334 			 * Break if intelligent programming is successful.
2335 			 */
2336 
2337 			break;
2338 		}
2339 
2340 	}
2341 	/*
2342 	 * If HEAP_IN flag was temporarily disabled,
2343 	 * re-enable it before exiting
2344 	 */
2345 
2346 	if (cRepeatHeap) {
2347 		g_usDataType |= HEAP_IN;
2348 	}
2349 
2350 	/*
2351 	 * Set the data type register to not get data from the
2352 	 * intelligent data buffer.
2353 	 */
2354 
2355 	g_usDataType &= ~LHEAP_IN;
2356 	return cRetCode;
2357 }
2358 /*
2359  *
2360  * ispVMClocks
2361  *
2362  * Applies the specified number of pulses to TCK.
2363  *
2364  */
2365 
2366 void ispVMClocks(unsigned short Clocks)
2367 {
2368 	unsigned short iClockIndex = 0;
2369 	for (iClockIndex = 0; iClockIndex < Clocks; iClockIndex++) {
2370 		sclock();
2371 	}
2372 }
2373 
2374 /*
2375  *
2376  * ispVMBypass
2377  *
2378  * This procedure takes care of the HIR, HDR, TIR, TDR for the
2379  * purpose of putting the other devices into Bypass mode. The
2380  * current state is checked to find out if it is at DRPAUSE or
2381  * IRPAUSE. If it is at DRPAUSE, perform bypass register scan.
2382  * If it is at IRPAUSE, scan into instruction registers the bypass
2383  * instruction.
2384  *
2385  */
2386 
2387 void ispVMBypass(signed char ScanType, unsigned short Bits)
2388 {
2389 	/* 09/11/07 NN added local variables initialization */
2390 	unsigned short iIndex       = 0;
2391 	unsigned short iSourceIndex = 0;
2392 	unsigned char cBitState     = 0;
2393 	unsigned char cCurByte      = 0;
2394 	unsigned char *pcSource    = NULL;
2395 
2396 	if (Bits <= 0) {
2397 		return;
2398 	}
2399 
2400 	switch (ScanType) {
2401 	case HIR:
2402 		pcSource = g_pucHIRData;
2403 		break;
2404 	case TIR:
2405 		pcSource = g_pucTIRData;
2406 		break;
2407 	case HDR:
2408 		pcSource = g_pucHDRData;
2409 		break;
2410 	case TDR:
2411 		pcSource = g_pucTDRData;
2412 		break;
2413 	default:
2414 		break;
2415 	}
2416 
2417 	iSourceIndex = 0;
2418 	cBitState = 0;
2419 	for (iIndex = 0; iIndex < Bits - 1; iIndex++) {
2420 		/* Scan instruction or bypass register */
2421 		if (iIndex % 8 == 0) {
2422 			cCurByte = pcSource[iSourceIndex++];
2423 		}
2424 		cBitState = (unsigned char) (((cCurByte << iIndex % 8) & 0x80)
2425 			? 0x01 : 0x00);
2426 		writePort(g_ucPinTDI, cBitState);
2427 		sclock();
2428 	}
2429 
2430 	if (iIndex % 8 == 0)  {
2431 		cCurByte = pcSource[iSourceIndex++];
2432 	}
2433 
2434 	cBitState = (unsigned char) (((cCurByte << iIndex % 8) & 0x80)
2435 		? 0x01 : 0x00);
2436 	writePort(g_ucPinTDI, cBitState);
2437 }
2438 
2439 /*
2440  *
2441  * ispVMStateMachine
2442  *
2443  * This procedure steps all devices in the daisy chain from a given
2444  * JTAG state to the next desirable state. If the next state is TLR,
2445  * the JTAG state machine is brute forced into TLR by driving TMS
2446  * high and pulse TCK 6 times.
2447  *
2448  */
2449 
2450 void ispVMStateMachine(signed char cNextJTAGState)
2451 {
2452 	/* 09/11/07 NN added local variables initialization */
2453 	signed char cPathIndex  = 0;
2454 	signed char cStateIndex = 0;
2455 
2456 	if ((g_cCurrentJTAGState == cNextJTAGState) &&
2457 		(cNextJTAGState != RESET)) {
2458 		return;
2459 	}
2460 
2461 	for (cStateIndex = 0; cStateIndex < 25; cStateIndex++) {
2462 		if ((g_cCurrentJTAGState ==
2463 			 g_JTAGTransistions[cStateIndex].CurState) &&
2464 			(cNextJTAGState ==
2465 				 g_JTAGTransistions[cStateIndex].NextState)) {
2466 			break;
2467 		}
2468 	}
2469 
2470 	g_cCurrentJTAGState = cNextJTAGState;
2471 	for (cPathIndex = 0;
2472 		cPathIndex < g_JTAGTransistions[cStateIndex].Pulses;
2473 		cPathIndex++) {
2474 		if ((g_JTAGTransistions[cStateIndex].Pattern << cPathIndex)
2475 			& 0x80) {
2476 			writePort(g_ucPinTMS, (unsigned char) 0x01);
2477 		} else {
2478 			writePort(g_ucPinTMS, (unsigned char) 0x00);
2479 		}
2480 		sclock();
2481 	}
2482 
2483 	writePort(g_ucPinTDI, 0x00);
2484 	writePort(g_ucPinTMS, 0x00);
2485 }
2486 
2487 /*
2488  *
2489  * ispVMStart
2490  *
2491  * Enable the port to the device and set the state to RESET (TLR).
2492  *
2493  */
2494 
2495 void ispVMStart()
2496 {
2497 #ifdef DEBUG
2498 	printf("// ISPVM EMBEDDED ADDED\n");
2499 	printf("STATE RESET;\n");
2500 #endif
2501 	g_usFlowControl	= 0;
2502 	g_usDataType = g_uiChecksumIndex = g_cCurrentJTAGState = 0;
2503 	g_usHeadDR = g_usHeadIR = g_usTailDR = g_usTailIR = 0;
2504 	g_usMaxSize = g_usShiftValue = g_usRepeatLoops = 0;
2505 	g_usTDOSize =  g_usMASKSize = g_usTDISize = 0;
2506 	g_usDMASKSize = g_usLCOUNTSize = g_usHDRSize = 0;
2507 	g_usTDRSize = g_usHIRSize = g_usTIRSize =  g_usHeapSize	= 0;
2508 	g_pLVDSList = NULL;
2509 	g_usLVDSPairCount = 0;
2510 	previous_size = 0;
2511 
2512 	ispVMStateMachine(RESET);    /*step devices to RESET state*/
2513 }
2514 
2515 /*
2516  *
2517  * ispVMEnd
2518  *
2519  * Set the state of devices to RESET to enable the devices and disable
2520  * the port.
2521  *
2522  */
2523 
2524 void ispVMEnd()
2525 {
2526 #ifdef DEBUG
2527 	printf("// ISPVM EMBEDDED ADDED\n");
2528 	printf("STATE RESET;\n");
2529 	printf("RUNTEST 1.00E-001 SEC;\n");
2530 #endif
2531 
2532 	ispVMStateMachine(RESET);   /*step devices to RESET state */
2533 	ispVMDelay(1000);              /*wake up devices*/
2534 }
2535 
2536 /*
2537  *
2538  * ispVMSend
2539  *
2540  * Send the TDI data stream to devices. The data stream can be
2541  * instructions or data.
2542  *
2543  */
2544 
2545 signed char ispVMSend(unsigned short a_usiDataSize)
2546 {
2547 	/* 09/11/07 NN added local variables initialization */
2548 	unsigned short iIndex       = 0;
2549 	unsigned short iInDataIndex = 0;
2550 	unsigned char cCurByte      = 0;
2551 	unsigned char cBitState     = 0;
2552 
2553 	for (iIndex = 0; iIndex < a_usiDataSize - 1; iIndex++) {
2554 		if (iIndex % 8 == 0) {
2555 			cCurByte = g_pucInData[iInDataIndex++];
2556 		}
2557 		cBitState = (unsigned char)(((cCurByte << iIndex % 8) & 0x80)
2558 			? 0x01 : 0x00);
2559 		writePort(g_ucPinTDI, cBitState);
2560 		sclock();
2561 	}
2562 
2563 	if (iIndex % 8 == 0) {
2564 		/* Take care of the last bit */
2565 		cCurByte = g_pucInData[iInDataIndex];
2566 	}
2567 
2568 	cBitState = (unsigned char) (((cCurByte << iIndex % 8) & 0x80)
2569 		? 0x01 : 0x00);
2570 
2571 	writePort(g_ucPinTDI, cBitState);
2572 	if (g_usFlowControl & CASCADE) {
2573 		/*1/15/04 Clock in last bit for the first n-1 cascaded frames */
2574 		sclock();
2575 	}
2576 
2577 	return 0;
2578 }
2579 
2580 /*
2581  *
2582  * ispVMRead
2583  *
2584  * Read the data stream from devices and verify.
2585  *
2586  */
2587 
2588 signed char ispVMRead(unsigned short a_usiDataSize)
2589 {
2590 	/* 09/11/07 NN added local variables initialization */
2591 	unsigned short usDataSizeIndex    = 0;
2592 	unsigned short usErrorCount       = 0;
2593 	unsigned short usLastBitIndex     = 0;
2594 	unsigned char cDataByte           = 0;
2595 	unsigned char cMaskByte           = 0;
2596 	unsigned char cInDataByte         = 0;
2597 	unsigned char cCurBit             = 0;
2598 	unsigned char cByteIndex          = 0;
2599 	unsigned short usBufferIndex      = 0;
2600 	unsigned char ucDisplayByte       = 0x00;
2601 	unsigned char ucDisplayFlag       = 0x01;
2602 	char StrChecksum[256]            = {0};
2603 	unsigned char g_usCalculateChecksum = 0x00;
2604 
2605 	/* 09/11/07 NN Type cast mismatch variables */
2606 	usLastBitIndex = (unsigned short)(a_usiDataSize - 1);
2607 
2608 #ifndef DEBUG
2609 	/*
2610 	 * If mask is not all zeros, then set the display flag to 0x00,
2611 	 * otherwise it shall be set to 0x01 to indicate that data read
2612 	 * from the device shall be displayed. If DEBUG is defined,
2613 	 * always display data.
2614 	 */
2615 
2616 	for (usDataSizeIndex = 0; usDataSizeIndex < (a_usiDataSize + 7) / 8;
2617 		usDataSizeIndex++) {
2618 		if (g_usDataType & MASK_DATA) {
2619 			if (g_pucOutMaskData[usDataSizeIndex] != 0x00) {
2620 				ucDisplayFlag = 0x00;
2621 				break;
2622 			}
2623 		} else if (g_usDataType & CMASK_DATA) {
2624 			g_usCalculateChecksum = 0x01;
2625 			ucDisplayFlag = 0x00;
2626 			break;
2627 		} else {
2628 			ucDisplayFlag = 0x00;
2629 			break;
2630 		}
2631 	}
2632 #endif /* DEBUG */
2633 
2634 	/*
2635 	*
2636 	* Begin shifting data in and out of the device.
2637 	*
2638 	**/
2639 
2640 	for (usDataSizeIndex = 0; usDataSizeIndex < a_usiDataSize;
2641 		usDataSizeIndex++) {
2642 		if (cByteIndex == 0) {
2643 
2644 			/*
2645 			 * Grab byte from TDO buffer.
2646 			 */
2647 
2648 			if (g_usDataType & TDO_DATA) {
2649 				cDataByte = g_pucOutData[usBufferIndex];
2650 			}
2651 
2652 			/*
2653 			 * Grab byte from MASK buffer.
2654 			 */
2655 
2656 			if (g_usDataType & MASK_DATA) {
2657 				cMaskByte = g_pucOutMaskData[usBufferIndex];
2658 			} else {
2659 				cMaskByte = 0xFF;
2660 			}
2661 
2662 			/*
2663 			 * Grab byte from CMASK buffer.
2664 			 */
2665 
2666 			if (g_usDataType & CMASK_DATA) {
2667 				cMaskByte = 0x00;
2668 				g_usCalculateChecksum = 0x01;
2669 			}
2670 
2671 			/*
2672 			 * Grab byte from TDI buffer.
2673 			 */
2674 
2675 			if (g_usDataType & TDI_DATA) {
2676 				cInDataByte = g_pucInData[usBufferIndex];
2677 			}
2678 
2679 			usBufferIndex++;
2680 		}
2681 
2682 		cCurBit = readPort();
2683 
2684 		if (ucDisplayFlag) {
2685 			ucDisplayByte <<= 1;
2686 			ucDisplayByte |= cCurBit;
2687 		}
2688 
2689 		/*
2690 		 * Check if data read from port matches with expected TDO.
2691 		 */
2692 
2693 		if (g_usDataType & TDO_DATA) {
2694 			/* 08/28/08 NN Added Calculate checksum support. */
2695 			if (g_usCalculateChecksum) {
2696 				if (cCurBit == 0x01)
2697 					g_usChecksum +=
2698 						(1 << (g_uiChecksumIndex % 8));
2699 				g_uiChecksumIndex++;
2700 			} else {
2701 				if ((((cMaskByte << cByteIndex) & 0x80)
2702 					? 0x01 : 0x00)) {
2703 					if (cCurBit != (unsigned char)
2704 					(((cDataByte << cByteIndex) & 0x80)
2705 						? 0x01 : 0x00)) {
2706 						usErrorCount++;
2707 					}
2708 				}
2709 			}
2710 		}
2711 
2712 		/*
2713 		 * Write TDI data to the port.
2714 		 */
2715 
2716 		writePort(g_ucPinTDI,
2717 			(unsigned char)(((cInDataByte << cByteIndex) & 0x80)
2718 				? 0x01 : 0x00));
2719 
2720 		if (usDataSizeIndex < usLastBitIndex) {
2721 
2722 			/*
2723 			 * Clock data out from the data shift register.
2724 			 */
2725 
2726 			sclock();
2727 		} else if (g_usFlowControl & CASCADE) {
2728 
2729 			/*
2730 			 * Clock in last bit for the first N - 1 cascaded frames
2731 			 */
2732 
2733 			sclock();
2734 		}
2735 
2736 		/*
2737 		 * Increment the byte index. If it exceeds 7, then reset it back
2738 		 * to zero.
2739 		 */
2740 
2741 		cByteIndex++;
2742 		if (cByteIndex >= 8) {
2743 			if (ucDisplayFlag) {
2744 
2745 			/*
2746 			 * Store displayed data in the TDO buffer. By reusing
2747 			 * the TDO buffer to store displayed data, there is no
2748 			 * need to allocate a buffer simply to hold display
2749 			 * data. This will not cause any false verification
2750 			 * errors because the true TDO byte has already
2751 			 * been consumed.
2752 			 */
2753 
2754 				g_pucOutData[usBufferIndex - 1] = ucDisplayByte;
2755 				ucDisplayByte = 0;
2756 			}
2757 
2758 			cByteIndex = 0;
2759 		}
2760 		/* 09/12/07 Nguyen changed to display the 1 bit expected data */
2761 		else if (a_usiDataSize == 1) {
2762 			if (ucDisplayFlag) {
2763 
2764 				/*
2765 				 * Store displayed data in the TDO buffer.
2766 				 * By reusing the TDO buffer to store displayed
2767 				 * data, there is no need to allocate
2768 				 * a buffer simply to hold display data. This
2769 				 * will not cause any false verification errors
2770 				 * because the true TDO byte has already
2771 				 * been consumed.
2772 				 */
2773 
2774 				/*
2775 				 * Flip ucDisplayByte and store it in cDataByte.
2776 				 */
2777 				cDataByte = 0x00;
2778 				for (usBufferIndex = 0; usBufferIndex < 8;
2779 					usBufferIndex++) {
2780 					cDataByte <<= 1;
2781 					if (ucDisplayByte & 0x01) {
2782 						cDataByte |= 0x01;
2783 					}
2784 					ucDisplayByte >>= 1;
2785 				}
2786 				g_pucOutData[0] = cDataByte;
2787 				ucDisplayByte = 0;
2788 			}
2789 
2790 			cByteIndex = 0;
2791 		}
2792 	}
2793 
2794 	if (ucDisplayFlag) {
2795 
2796 #ifdef DEBUG
2797 		debug("RECEIVED TDO (");
2798 #else
2799 		vme_out_string("Display Data: 0x");
2800 #endif /* DEBUG */
2801 
2802 		/* 09/11/07 NN Type cast mismatch variables */
2803 		for (usDataSizeIndex = (unsigned short)
2804 				((a_usiDataSize + 7) / 8);
2805 			usDataSizeIndex > 0 ; usDataSizeIndex--) {
2806 			cMaskByte = g_pucOutData[usDataSizeIndex - 1];
2807 			cDataByte = 0x00;
2808 
2809 			/*
2810 			 * Flip cMaskByte and store it in cDataByte.
2811 			 */
2812 
2813 			for (usBufferIndex = 0; usBufferIndex < 8;
2814 				usBufferIndex++) {
2815 				cDataByte <<= 1;
2816 				if (cMaskByte & 0x01) {
2817 					cDataByte |= 0x01;
2818 				}
2819 				cMaskByte >>= 1;
2820 			}
2821 #ifdef DEBUG
2822 			printf("%.2X", cDataByte);
2823 			if ((((a_usiDataSize + 7) / 8) - usDataSizeIndex)
2824 				% 40 == 39) {
2825 				printf("\n\t\t");
2826 			}
2827 #else
2828 			vme_out_hex(cDataByte);
2829 #endif /* DEBUG */
2830 		}
2831 
2832 #ifdef DEBUG
2833 		printf(")\n\n");
2834 #else
2835 		vme_out_string("\n\n");
2836 #endif /* DEBUG */
2837 		/* 09/02/08 Nguyen changed to display the data Checksum */
2838 		if (g_usChecksum != 0) {
2839 			g_usChecksum &= 0xFFFF;
2840 			sprintf(StrChecksum, "Data Checksum: %.4lX\n\n",
2841 				g_usChecksum);
2842 			vme_out_string(StrChecksum);
2843 			g_usChecksum = 0;
2844 		}
2845 	}
2846 
2847 	if (usErrorCount > 0) {
2848 		if (g_usFlowControl & VERIFYUES) {
2849 			vme_out_string(
2850 				"USERCODE verification failed.   "
2851 				"Continue programming......\n\n");
2852 			g_usFlowControl &= ~(VERIFYUES);
2853 			return 0;
2854 		} else {
2855 
2856 #ifdef DEBUG
2857 			printf("TOTAL ERRORS: %d\n", usErrorCount);
2858 #endif /* DEBUG */
2859 
2860 			return VME_VERIFICATION_FAILURE;
2861 		}
2862 	} else {
2863 		if (g_usFlowControl & VERIFYUES) {
2864 			vme_out_string("USERCODE verification passed.    "
2865 				"Programming aborted.\n\n");
2866 			g_usFlowControl &= ~(VERIFYUES);
2867 			return 1;
2868 		} else {
2869 			return 0;
2870 		}
2871 	}
2872 }
2873 
2874 /*
2875  *
2876  * ispVMReadandSave
2877  *
2878  * Support dynamic I/O.
2879  *
2880  */
2881 
2882 signed char ispVMReadandSave(unsigned short int a_usiDataSize)
2883 {
2884 	/* 09/11/07 NN added local variables initialization */
2885 	unsigned short int usDataSizeIndex = 0;
2886 	unsigned short int usLastBitIndex  = 0;
2887 	unsigned short int usBufferIndex   = 0;
2888 	unsigned short int usOutBitIndex   = 0;
2889 	unsigned short int usLVDSIndex     = 0;
2890 	unsigned char cDataByte            = 0;
2891 	unsigned char cDMASKByte           = 0;
2892 	unsigned char cInDataByte          = 0;
2893 	unsigned char cCurBit              = 0;
2894 	unsigned char cByteIndex           = 0;
2895 	signed char cLVDSByteIndex         = 0;
2896 
2897 	/* 09/11/07 NN Type cast mismatch variables */
2898 	usLastBitIndex = (unsigned short) (a_usiDataSize - 1);
2899 
2900 	/*
2901 	*
2902 	* Iterate through the data bits.
2903 	*
2904 	*/
2905 
2906 	for (usDataSizeIndex = 0; usDataSizeIndex < a_usiDataSize;
2907 		usDataSizeIndex++) {
2908 		if (cByteIndex == 0) {
2909 
2910 			/*
2911 			 * Grab byte from DMASK buffer.
2912 			 */
2913 
2914 			if (g_usDataType & DMASK_DATA) {
2915 				cDMASKByte = g_pucOutDMaskData[usBufferIndex];
2916 			} else {
2917 				cDMASKByte = 0x00;
2918 			}
2919 
2920 			/*
2921 			 * Grab byte from TDI buffer.
2922 			 */
2923 
2924 			if (g_usDataType & TDI_DATA) {
2925 				cInDataByte = g_pucInData[usBufferIndex];
2926 			}
2927 
2928 			usBufferIndex++;
2929 		}
2930 
2931 		cCurBit = readPort();
2932 		cDataByte = (unsigned char)(((cInDataByte << cByteIndex) & 0x80)
2933 			? 0x01 : 0x00);
2934 
2935 		/*
2936 		 * Initialize the byte to be zero.
2937 		 */
2938 
2939 		if (usOutBitIndex % 8 == 0) {
2940 			g_pucOutData[usOutBitIndex / 8] = 0x00;
2941 		}
2942 
2943 		/*
2944 		 * Use TDI, DMASK, and device TDO to create new TDI (actually
2945 		 * stored in g_pucOutData).
2946 		 */
2947 
2948 		if ((((cDMASKByte << cByteIndex) & 0x80) ? 0x01 : 0x00)) {
2949 
2950 			if (g_pLVDSList) {
2951 				for (usLVDSIndex = 0;
2952 					 usLVDSIndex < g_usLVDSPairCount;
2953 					usLVDSIndex++) {
2954 					if (g_pLVDSList[usLVDSIndex].
2955 						usNegativeIndex ==
2956 						usDataSizeIndex) {
2957 						g_pLVDSList[usLVDSIndex].
2958 							ucUpdate = 0x01;
2959 						break;
2960 					}
2961 				}
2962 			}
2963 
2964 			/*
2965 			 * DMASK bit is 1, use TDI.
2966 			 */
2967 
2968 			g_pucOutData[usOutBitIndex / 8] |= (unsigned char)
2969 				(((cDataByte & 0x1) ? 0x01 : 0x00) <<
2970 				(7 - usOutBitIndex % 8));
2971 		} else {
2972 
2973 			/*
2974 			 * DMASK bit is 0, use device TDO.
2975 			 */
2976 
2977 			g_pucOutData[usOutBitIndex / 8] |= (unsigned char)
2978 				(((cCurBit & 0x1) ? 0x01 : 0x00) <<
2979 				(7 - usOutBitIndex % 8));
2980 		}
2981 
2982 		/*
2983 		 * Shift in TDI in order to get TDO out.
2984 		 */
2985 
2986 		usOutBitIndex++;
2987 		writePort(g_ucPinTDI, cDataByte);
2988 		if (usDataSizeIndex < usLastBitIndex) {
2989 			sclock();
2990 		}
2991 
2992 		/*
2993 		 * Increment the byte index. If it exceeds 7, then reset it back
2994 		 * to zero.
2995 		 */
2996 
2997 		cByteIndex++;
2998 		if (cByteIndex >= 8) {
2999 			cByteIndex = 0;
3000 		}
3001 	}
3002 
3003 	/*
3004 	 * If g_pLVDSList exists and pairs need updating, then update
3005 	 * the negative-pair to receive the flipped positive-pair value.
3006 	 */
3007 
3008 	if (g_pLVDSList) {
3009 		for (usLVDSIndex = 0; usLVDSIndex < g_usLVDSPairCount;
3010 			usLVDSIndex++) {
3011 			if (g_pLVDSList[usLVDSIndex].ucUpdate) {
3012 
3013 				/*
3014 				 * Read the positive value and flip it.
3015 				 */
3016 
3017 				cDataByte = (unsigned char)
3018 				 (((g_pucOutData[g_pLVDSList[usLVDSIndex].
3019 					usPositiveIndex / 8]
3020 					<< (g_pLVDSList[usLVDSIndex].
3021 					usPositiveIndex % 8)) & 0x80) ?
3022 					0x01 : 0x00);
3023 				/* 09/11/07 NN Type cast mismatch variables */
3024 				cDataByte = (unsigned char) (!cDataByte);
3025 
3026 				/*
3027 				 * Get the byte that needs modification.
3028 				 */
3029 
3030 				cInDataByte =
3031 				g_pucOutData[g_pLVDSList[usLVDSIndex].
3032 					usNegativeIndex / 8];
3033 
3034 				if (cDataByte) {
3035 
3036 					/*
3037 					 * Copy over the current byte and
3038 					 * set the negative bit to 1.
3039 					 */
3040 
3041 					cDataByte = 0x00;
3042 					for (cLVDSByteIndex = 7;
3043 						cLVDSByteIndex >= 0;
3044 						cLVDSByteIndex--) {
3045 						cDataByte <<= 1;
3046 						if (7 -
3047 						(g_pLVDSList[usLVDSIndex].
3048 							usNegativeIndex % 8) ==
3049 							cLVDSByteIndex) {
3050 
3051 							/*
3052 							 * Set negative bit to 1
3053 							 */
3054 
3055 							cDataByte |= 0x01;
3056 						} else if (cInDataByte & 0x80) {
3057 							cDataByte |= 0x01;
3058 						}
3059 
3060 						cInDataByte <<= 1;
3061 					}
3062 
3063 					/*
3064 					 * Store the modified byte.
3065 					 */
3066 
3067 					g_pucOutData[g_pLVDSList[usLVDSIndex].
3068 					usNegativeIndex / 8] = cDataByte;
3069 				} else {
3070 
3071 					/*
3072 					 * Copy over the current byte and set
3073 					 * the negative bit to 0.
3074 					 */
3075 
3076 					cDataByte = 0x00;
3077 					for (cLVDSByteIndex = 7;
3078 						cLVDSByteIndex >= 0;
3079 						cLVDSByteIndex--) {
3080 						cDataByte <<= 1;
3081 						if (7 -
3082 						(g_pLVDSList[usLVDSIndex].
3083 						usNegativeIndex % 8) ==
3084 						cLVDSByteIndex) {
3085 
3086 							/*
3087 							 * Set negative bit to 0
3088 							 */
3089 
3090 							cDataByte |= 0x00;
3091 						} else if (cInDataByte & 0x80) {
3092 							cDataByte |= 0x01;
3093 						}
3094 
3095 						cInDataByte <<= 1;
3096 					}
3097 
3098 					/*
3099 					 * Store the modified byte.
3100 					 */
3101 
3102 					g_pucOutData[g_pLVDSList[usLVDSIndex].
3103 					usNegativeIndex / 8] = cDataByte;
3104 				}
3105 
3106 				break;
3107 			}
3108 		}
3109 	}
3110 
3111 	return 0;
3112 }
3113 
3114 signed char ispVMProcessLVDS(unsigned short a_usLVDSCount)
3115 {
3116 	unsigned short usLVDSIndex = 0;
3117 
3118 	/*
3119 	 * Allocate memory to hold LVDS pairs.
3120 	 */
3121 
3122 	ispVMMemManager(LVDS, a_usLVDSCount);
3123 	g_usLVDSPairCount = a_usLVDSCount;
3124 
3125 #ifdef DEBUG
3126 	printf("LVDS %d (", a_usLVDSCount);
3127 #endif /* DEBUG */
3128 
3129 	/*
3130 	 * Iterate through each given LVDS pair.
3131 	 */
3132 
3133 	for (usLVDSIndex = 0; usLVDSIndex < g_usLVDSPairCount; usLVDSIndex++) {
3134 
3135 		/*
3136 		 * Assign the positive and negative indices of the LVDS pair.
3137 		 */
3138 
3139 		/* 09/11/07 NN Type cast mismatch variables */
3140 		g_pLVDSList[usLVDSIndex].usPositiveIndex =
3141 			(unsigned short) ispVMDataSize();
3142 		/* 09/11/07 NN Type cast mismatch variables */
3143 		g_pLVDSList[usLVDSIndex].usNegativeIndex =
3144 			(unsigned short)ispVMDataSize();
3145 
3146 #ifdef DEBUG
3147 		if (usLVDSIndex < g_usLVDSPairCount - 1) {
3148 			printf("%d:%d, ",
3149 				g_pLVDSList[usLVDSIndex].usPositiveIndex,
3150 				g_pLVDSList[usLVDSIndex].usNegativeIndex);
3151 		} else {
3152 			printf("%d:%d",
3153 				g_pLVDSList[usLVDSIndex].usPositiveIndex,
3154 				g_pLVDSList[usLVDSIndex].usNegativeIndex);
3155 		}
3156 #endif /* DEBUG */
3157 
3158 	}
3159 
3160 #ifdef DEBUG
3161 	printf(");\n", a_usLVDSCount);
3162 #endif /* DEBUG */
3163 
3164 	return 0;
3165 }
3166