1 // SPDX-License-Identifier: GPL-2.0+
8 * Lattice ispVME Embedded code to load Lattice's FPGA:
10 * Copyright 2009 Lattice Semiconductor Corp.
12 * ispVME Embedded allows programming of Lattice's suite of FPGA
13 * devices on embedded systems through the JTAG port. The software
14 * is distributed in source code form and is open to re - distribution
15 * and modification where applicable.
17 * Revision History of ivm_core.c module:
18 * 4/25/06 ht Change some variables from unsigned short or int
19 * to long int to make the code compiler independent.
20 * 5/24/06 ht Support using RESET (TRST) pin as a special purpose
21 * control pin such as triggering the loading of known
23 * 3/6/07 ht added functions to support output to terminals
25 * 09/11/07 NN Type cast mismatch variables
26 * Moved the sclock() function to hardware.c
27 * 08/28/08 NN Added Calculate checksum support.
28 * 4/1/09 Nguyen replaced the recursive function call codes on
29 * the ispVMLCOUNT function
34 #include <linux/string.h>
38 #define vme_out_char(c) printf("%c", c)
39 #define vme_out_hex(c) printf("%x", c)
40 #define vme_out_string(s) printf("%s", s)
44 * Global variables used to specify the flow control and data type.
46 * g_usFlowControl: flow control register. Each bit in the
47 * register can potentially change the
48 * personality of the embedded engine.
49 * g_usDataType: holds the data type of the current row.
53 static unsigned short g_usFlowControl;
54 unsigned short g_usDataType;
58 * Global variables used to specify the ENDDR and ENDIR.
60 * g_ucEndDR: the state that the device goes to after SDR.
61 * g_ucEndIR: the state that the device goes to after SIR.
65 unsigned char g_ucEndDR = DRPAUSE;
66 unsigned char g_ucEndIR = IRPAUSE;
70 * Global variables used to support header/trailer.
72 * g_usHeadDR: the number of lead devices in bypass.
73 * g_usHeadIR: the sum of IR length of lead devices.
74 * g_usTailDR: the number of tail devices in bypass.
75 * g_usTailIR: the sum of IR length of tail devices.
79 static unsigned short g_usHeadDR;
80 static unsigned short g_usHeadIR;
81 static unsigned short g_usTailDR;
82 static unsigned short g_usTailIR;
86 * Global variable to store the number of bits of data or instruction
87 * to be shifted into or out from the device.
91 static unsigned short g_usiDataSize;
95 * Stores the frequency. Default to 1 MHz.
99 static int g_iFrequency = 1000;
103 * Stores the maximum amount of ram needed to hold a row of data.
107 static unsigned short g_usMaxSize;
111 * Stores the LSH or RSH value.
115 static unsigned short g_usShiftValue;
119 * Stores the current repeat loop value.
123 static unsigned short g_usRepeatLoops;
127 * Stores the current vendor.
131 static signed char g_cVendor = LATTICE;
135 * Stores the VME file CRC.
139 unsigned short g_usCalculatedCRC;
143 * Stores the Device Checksum.
146 /* 08/28/08 NN Added Calculate checksum support. */
147 unsigned long g_usChecksum;
148 static unsigned int g_uiChecksumIndex;
152 * Stores the current state of the JTAG state machine.
156 static signed char g_cCurrentJTAGState;
160 * Global variables used to support looping.
162 * g_pucHeapMemory: holds the entire repeat loop.
163 * g_iHeapCounter: points to the current byte in the repeat loop.
164 * g_iHEAPSize: the current size of the repeat in bytes.
168 unsigned char *g_pucHeapMemory;
169 unsigned short g_iHeapCounter;
170 unsigned short g_iHEAPSize;
171 static unsigned short previous_size;
175 * Global variables used to support intelligent programming.
177 * g_usIntelDataIndex: points to the current byte of the
178 * intelligent buffer.
179 * g_usIntelBufferSize: holds the size of the intelligent
184 unsigned short g_usIntelDataIndex;
185 unsigned short g_usIntelBufferSize;
189 * Supported VME versions.
193 const char *const g_szSupportedVersions[] = {
194 "__VME2.0", "__VME3.0", "____12.0", "____12.1", 0};
198 * Holds the maximum size of each respective buffer. These variables are used
199 * to write the HEX files when converting VME to HEX.
203 static unsigned short g_usTDOSize;
204 static unsigned short g_usMASKSize;
205 static unsigned short g_usTDISize;
206 static unsigned short g_usDMASKSize;
207 static unsigned short g_usLCOUNTSize;
208 static unsigned short g_usHDRSize;
209 static unsigned short g_usTDRSize;
210 static unsigned short g_usHIRSize;
211 static unsigned short g_usTIRSize;
212 static unsigned short g_usHeapSize;
216 * Global variables used to store data.
218 * g_pucOutMaskData: local RAM to hold one row of MASK data.
219 * g_pucInData: local RAM to hold one row of TDI data.
220 * g_pucOutData: local RAM to hold one row of TDO data.
221 * g_pucHIRData: local RAM to hold the current SIR header.
222 * g_pucTIRData: local RAM to hold the current SIR trailer.
223 * g_pucHDRData: local RAM to hold the current SDR header.
224 * g_pucTDRData: local RAM to hold the current SDR trailer.
225 * g_pucIntelBuffer: local RAM to hold the current intelligent buffer
226 * g_pucOutDMaskData: local RAM to hold one row of DMASK data.
230 unsigned char *g_pucOutMaskData = NULL,
232 *g_pucOutData = NULL,
233 *g_pucHIRData = NULL,
234 *g_pucTIRData = NULL,
235 *g_pucHDRData = NULL,
236 *g_pucTDRData = NULL,
237 *g_pucIntelBuffer = NULL,
238 *g_pucOutDMaskData = NULL;
242 * JTAG state machine transition table.
247 unsigned char CurState; /* From this state */
248 unsigned char NextState; /* Step to this state */
249 unsigned char Pattern; /* The tragetory of TMS */
250 unsigned char Pulses; /* The number of steps */
251 } g_JTAGTransistions[25] = {
252 { RESET, RESET, 0xFC, 6 }, /* Transitions from RESET */
253 { RESET, IDLE, 0x00, 1 },
254 { RESET, DRPAUSE, 0x50, 5 },
255 { RESET, IRPAUSE, 0x68, 6 },
256 { IDLE, RESET, 0xE0, 3 }, /* Transitions from IDLE */
257 { IDLE, DRPAUSE, 0xA0, 4 },
258 { IDLE, IRPAUSE, 0xD0, 5 },
259 { DRPAUSE, RESET, 0xF8, 5 }, /* Transitions from DRPAUSE */
260 { DRPAUSE, IDLE, 0xC0, 3 },
261 { DRPAUSE, IRPAUSE, 0xF4, 7 },
262 { DRPAUSE, DRPAUSE, 0xE8, 6 },/* 06/14/06 Support POLL STATUS LOOP*/
263 { IRPAUSE, RESET, 0xF8, 5 }, /* Transitions from IRPAUSE */
264 { IRPAUSE, IDLE, 0xC0, 3 },
265 { IRPAUSE, DRPAUSE, 0xE8, 6 },
266 { DRPAUSE, SHIFTDR, 0x80, 2 }, /* Extra transitions using SHIFTDR */
267 { IRPAUSE, SHIFTDR, 0xE0, 5 },
268 { SHIFTDR, DRPAUSE, 0x80, 2 },
269 { SHIFTDR, IDLE, 0xC0, 3 },
270 { IRPAUSE, SHIFTIR, 0x80, 2 },/* Extra transitions using SHIFTIR */
271 { SHIFTIR, IRPAUSE, 0x80, 2 },
272 { SHIFTIR, IDLE, 0xC0, 3 },
273 { DRPAUSE, DRCAPTURE, 0xE0, 4 }, /* 11/15/05 Support DRCAPTURE*/
274 { DRCAPTURE, DRPAUSE, 0x80, 2 },
275 { IDLE, DRCAPTURE, 0x80, 2 },
276 { IRPAUSE, DRCAPTURE, 0xE0, 4 }
281 * List to hold all LVDS pairs.
285 LVDSPair *g_pLVDSList;
286 unsigned short g_usLVDSPairCount;
290 * Function prototypes.
294 static signed char ispVMDataCode(void);
295 static long int ispVMDataSize(void);
296 static void ispVMData(unsigned char *Data);
297 static signed char ispVMShift(signed char Code);
298 static signed char ispVMAmble(signed char Code);
299 static signed char ispVMLoop(unsigned short a_usLoopCount);
300 static signed char ispVMBitShift(signed char mode, unsigned short bits);
301 static void ispVMComment(unsigned short a_usCommentSize);
302 static void ispVMHeader(unsigned short a_usHeaderSize);
303 static signed char ispVMLCOUNT(unsigned short a_usCountSize);
304 static void ispVMClocks(unsigned short Clocks);
305 static void ispVMBypass(signed char ScanType, unsigned short Bits);
306 static void ispVMStateMachine(signed char NextState);
307 static signed char ispVMSend(unsigned short int);
308 static signed char ispVMRead(unsigned short int);
309 static signed char ispVMReadandSave(unsigned short int);
310 static signed char ispVMProcessLVDS(unsigned short a_usLVDSCount);
311 static void ispVMMemManager(signed char types, unsigned short size);
315 * External variables and functions in hardware.c module
318 static signed char g_cCurrentJTAGState;
326 * Returns the state as a string based on the opcode. Only used
327 * for debugging purposes.
331 const char *GetState(unsigned char a_ucState)
346 case DRCAPTURE:/* 11/15/05 support DRCAPTURE*/
359 * Prints the data. Only used for debugging purposes.
363 void PrintData(unsigned short a_iDataSize, unsigned char *a_pucData)
365 /* 09/11/07 NN added local variables initialization */
366 unsigned short usByteSize = 0;
367 unsigned short usBitIndex = 0;
368 signed short usByteIndex = 0;
369 unsigned char ucByte = 0;
370 unsigned char ucFlipByte = 0;
372 if (a_iDataSize % 8) {
373 /* 09/11/07 NN Type cast mismatch variables */
374 usByteSize = (unsigned short)(a_iDataSize / 8 + 1);
376 /* 09/11/07 NN Type cast mismatch variables */
377 usByteSize = (unsigned short)(a_iDataSize / 8);
380 /* 09/11/07 NN Type cast mismatch variables */
381 for (usByteIndex = (signed short)(usByteSize - 1);
382 usByteIndex >= 0; usByteIndex--) {
383 ucByte = a_pucData[usByteIndex];
392 for (usBitIndex = 0; usBitIndex < 8; usBitIndex++) {
403 * Print the flipped byte.
407 printf("%.02X", ucFlipByte);
408 if ((usByteSize - usByteIndex) % 40 == 39) {
418 void ispVMMemManager(signed char cTarget, unsigned short usSize)
423 if (g_pucInData != NULL) {
424 if (previous_size == usSize) {/*memory exist*/
431 g_pucInData = (unsigned char *) malloc(usSize / 8 + 2);
432 previous_size = usSize;
435 if (g_pucOutData != NULL) {
436 if (previous_size == usSize) { /*already exist*/
443 g_pucOutData = (unsigned char *) malloc(usSize / 8 + 2);
444 previous_size = usSize;
447 if (g_pucOutMaskData != NULL) {
448 if (previous_size == usSize) {/*already allocated*/
451 free(g_pucOutMaskData);
452 g_pucOutMaskData = NULL;
455 g_pucOutMaskData = (unsigned char *) malloc(usSize / 8 + 2);
456 previous_size = usSize;
459 if (g_pucHIRData != NULL) {
463 g_pucHIRData = (unsigned char *) malloc(usSize / 8 + 2);
466 if (g_pucTIRData != NULL) {
470 g_pucTIRData = (unsigned char *) malloc(usSize / 8 + 2);
473 if (g_pucHDRData != NULL) {
477 g_pucHDRData = (unsigned char *) malloc(usSize / 8 + 2);
480 if (g_pucTDRData != NULL) {
484 g_pucTDRData = (unsigned char *) malloc(usSize / 8 + 2);
487 if (g_pucHeapMemory != NULL) {
488 free(g_pucHeapMemory);
489 g_pucHeapMemory = NULL;
491 g_pucHeapMemory = (unsigned char *) malloc(usSize + 2);
494 if (g_pucOutDMaskData != NULL) {
495 if (previous_size == usSize) { /*already allocated*/
498 free(g_pucOutDMaskData);
499 g_pucOutDMaskData = NULL;
502 g_pucOutDMaskData = (unsigned char *) malloc(usSize / 8 + 2);
503 previous_size = usSize;
506 if (g_pucIntelBuffer != NULL) {
507 free(g_pucIntelBuffer);
508 g_pucIntelBuffer = NULL;
510 g_pucIntelBuffer = (unsigned char *) malloc(usSize + 2);
513 if (g_pLVDSList != NULL) {
517 g_pLVDSList = (LVDSPair *) malloc(usSize * sizeof(LVDSPair));
519 memset(g_pLVDSList, 0, usSize * sizeof(LVDSPair));
526 void ispVMFreeMem(void)
528 if (g_pucHeapMemory != NULL) {
529 free(g_pucHeapMemory);
530 g_pucHeapMemory = NULL;
533 if (g_pucOutMaskData != NULL) {
534 free(g_pucOutMaskData);
535 g_pucOutMaskData = NULL;
538 if (g_pucInData != NULL) {
543 if (g_pucOutData != NULL) {
548 if (g_pucHIRData != NULL) {
553 if (g_pucTIRData != NULL) {
558 if (g_pucHDRData != NULL) {
563 if (g_pucTDRData != NULL) {
568 if (g_pucOutDMaskData != NULL) {
569 free(g_pucOutDMaskData);
570 g_pucOutDMaskData = NULL;
573 if (g_pucIntelBuffer != NULL) {
574 free(g_pucIntelBuffer);
575 g_pucIntelBuffer = NULL;
578 if (g_pLVDSList != NULL) {
589 * Returns a VME-encoded number, usually used to indicate the
590 * bit length of an SIR/SDR command.
594 long int ispVMDataSize()
596 /* 09/11/07 NN added local variables initialization */
598 signed char cCurrentByte = 0;
599 signed char cIndex = 0;
601 while ((cCurrentByte = GetByte()) & 0x80) {
602 iSize |= ((long int) (cCurrentByte & 0x7F)) << cIndex;
605 iSize |= ((long int) (cCurrentByte & 0x7F)) << cIndex;
613 * This is the heart of the embedded engine. All the high-level opcodes
614 * are extracted here. Once they have been identified, then it
615 * will call other functions to handle the processing.
619 signed char ispVMCode()
621 /* 09/11/07 NN added local variables initialization */
622 unsigned short iRepeatSize = 0;
623 signed char cOpcode = 0;
624 signed char cRetCode = 0;
625 unsigned char ucState = 0;
626 unsigned short usDelay = 0;
627 unsigned short usToggle = 0;
628 unsigned char usByte = 0;
632 * Check the compression flag only if this is the first time
633 * this function is entered. Do not check the compression flag if
634 * it is being called recursively from other functions within
635 * the embedded engine.
639 if (!(g_usDataType & LHEAP_IN) && !(g_usDataType & HEAP_IN)) {
641 if (usByte == 0xf1) {
642 g_usDataType |= COMPRESS;
643 } else if (usByte == 0xf2) {
644 g_usDataType &= ~COMPRESS;
646 return VME_INVALID_FILE;
652 * Begin looping through all the VME opcodes.
656 while ((cOpcode = GetByte()) >= 0) {
662 * Step the JTAG state machine.
668 * Step the JTAG state machine to DRCAPTURE
669 * to support Looping.
672 if ((g_usDataType & LHEAP_IN) &&
673 (ucState == DRPAUSE) &&
674 (g_cCurrentJTAGState == ucState)) {
675 ispVMStateMachine(DRCAPTURE);
678 ispVMStateMachine(ucState);
681 if (g_usDataType & LHEAP_IN) {
682 debug("LDELAY %s ", GetState(ucState));
684 debug("STATE %s;\n", GetState(ucState));
699 if (g_usDataType & LHEAP_IN) {
709 * Shift in data into the device.
713 cRetCode = ispVMShift(cOpcode);
726 /* 09/11/07 NN Type cast mismatch variables */
727 usDelay = (unsigned short) ispVMDataSize();
731 if (usDelay & 0x8000) {
734 * Since MSB is set, the delay time must be
735 * decoded to millisecond. The SVF2VME encodes
736 * the MSB to represent millisecond.
740 if (g_usDataType & LHEAP_IN) {
741 printf("%.2E SEC;\n",
742 (float) usDelay / 1000);
744 printf("RUNTEST %.2E SEC;\n",
745 (float) usDelay / 1000);
749 * Since MSB is not set, the delay time
750 * is given as microseconds.
753 if (g_usDataType & LHEAP_IN) {
754 printf("%.2E SEC;\n",
755 (float) usDelay / 1000000);
757 printf("RUNTEST %.2E SEC;\n",
758 (float) usDelay / 1000000);
766 * Issue clock toggles.
769 /* 09/11/07 NN Type cast mismatch variables */
770 usToggle = (unsigned short) ispVMDataSize();
771 ispVMClocks(usToggle);
774 printf("RUNTEST %d TCK;\n", usToggle);
785 g_ucEndDR = GetByte();
788 printf("ENDDR %s;\n", GetState(g_ucEndDR));
799 g_ucEndIR = GetByte();
802 printf("ENDIR %s;\n", GetState(g_ucEndIR));
827 * Set the header/trailer of the device in order
832 cRetCode = ispVMAmble(cOpcode);
844 * The maximum RAM required to support
845 * processing one row of the VME file.
848 /* 09/11/07 NN Type cast mismatch variables */
849 g_usMaxSize = (unsigned short) ispVMDataSize();
852 printf("// MEMSIZE %d\n", g_usMaxSize);
859 * Set the VENDOR type.
867 puts("// VENDOR LATTICE\n");
873 puts("// VENDOR ALTERA\n");
879 puts("// VENDOR XILINX\n");
890 * Set the flow control. Flow control determines
891 * the personality of the embedded engine.
894 /* 09/11/07 NN Type cast mismatch variables */
895 g_usFlowControl |= (unsigned short) ispVMDataSize();
901 * Unset the flow control.
905 /* 09/11/07 NN Type cast mismatch variables */
906 g_usFlowControl &= (unsigned short) ~(ispVMDataSize());
912 * Allocate heap size to store loops.
916 cRetCode = GetByte();
917 if (cRetCode != SECUREHEAP) {
918 return VME_INVALID_FILE;
920 /* 09/11/07 NN Type cast mismatch variables */
921 g_iHEAPSize = (unsigned short) ispVMDataSize();
924 * Store the maximum size of the HEAP buffer.
925 * Used to convert VME to HEX.
928 if (g_iHEAPSize > g_usHeapSize) {
929 g_usHeapSize = g_iHEAPSize;
932 ispVMMemManager(HEAP, (unsigned short) g_iHEAPSize);
944 /* 09/11/07 NN Type cast mismatch variables */
945 iRepeatSize = (unsigned short) ispVMDataSize();
947 cRetCode = ispVMLoop((unsigned short) iRepeatSize);
956 * Exit point from processing loops.
964 * The only valid exit point that indicates
965 * end of programming.
973 * Right-shift address.
977 g_usFlowControl |= SHIFTRIGHT;
979 /* 09/11/07 NN Type cast mismatch variables */
980 g_usShiftValue = (unsigned short) (g_usRepeatLoops *
981 (unsigned short)GetByte());
986 * Left-shift address.
989 g_usFlowControl |= SHIFTLEFT;
991 /* 09/11/07 NN Type cast mismatch variables */
992 g_usShiftValue = (unsigned short) (g_usRepeatLoops *
993 (unsigned short)GetByte());
1003 /* 09/11/07 NN Type cast mismatch variables */
1004 g_iFrequency = (int) (ispVMDataSize() / 1000);
1005 if (g_iFrequency == 1)
1006 g_iFrequency = 1000;
1009 printf("FREQUENCY %.2E HZ;\n",
1010 (float) g_iFrequency * 1000);
1017 * Process LCOUNT command.
1021 cRetCode = ispVMLCOUNT((unsigned short)ispVMDataSize());
1022 if (cRetCode != 0) {
1030 * Set the flow control to verify USERCODE.
1034 g_usFlowControl |= VERIFYUES;
1044 ispVMComment((unsigned short) ispVMDataSize());
1050 * Process LVDS command.
1054 ispVMProcessLVDS((unsigned short) ispVMDataSize());
1064 ispVMHeader((unsigned short) ispVMDataSize());
1066 /* 03/14/06 Support Toggle ispENABLE signal*/
1068 ucState = GetByte();
1069 if ((ucState == ON) || (ucState == 0x01))
1070 writePort(g_ucPinENABLE, 0x01);
1072 writePort(g_ucPinENABLE, 0x00);
1075 /* 05/24/06 support Toggle TRST pin*/
1077 ucState = GetByte();
1078 if (ucState == 0x01)
1079 writePort(g_ucPinTRST, 0x01);
1081 writePort(g_ucPinTRST, 0x00);
1088 * Invalid opcode encountered.
1093 printf("\nINVALID OPCODE: 0x%.2X\n", cOpcode);
1096 return VME_INVALID_FILE;
1102 * Invalid exit point. Processing the token 'ENDVME' is the only
1103 * valid way to exit the embedded engine.
1107 return VME_INVALID_FILE;
1114 * Processes the TDI/TDO/MASK/DMASK etc of an SIR/SDR command.
1118 signed char ispVMDataCode()
1120 /* 09/11/07 NN added local variables initialization */
1121 signed char cDataByte = 0;
1122 signed char siDataSource = 0; /*source of data from file by default*/
1124 if (g_usDataType & HEAP_IN) {
1125 siDataSource = 1; /*the source of data from memory*/
1130 * Clear the data type register.
1134 g_usDataType &= ~(MASK_DATA + TDI_DATA +
1135 TDO_DATA + DMASK_DATA + CMASK_DATA);
1138 * Iterate through SIR/SDR command and look for TDI,
1142 while ((cDataByte = GetByte()) >= 0) {
1143 ispVMMemManager(cDataByte, g_usMaxSize);
1144 switch (cDataByte) {
1148 * Store the maximum size of the TDI buffer.
1149 * Used to convert VME to HEX.
1152 if (g_usiDataSize > g_usTDISize) {
1153 g_usTDISize = g_usiDataSize;
1156 * Updated data type register to indicate that
1157 * TDI data is currently being used. Process the
1158 * data in the VME file into the TDI buffer.
1161 g_usDataType |= TDI_DATA;
1162 ispVMData(g_pucInData);
1167 * Store the maximum size of the TDO buffer.
1168 * Used to convert VME to HEX.
1171 if (g_usiDataSize > g_usTDOSize) {
1172 g_usTDOSize = g_usiDataSize;
1176 * Updated data type register to indicate that
1177 * TDO data is currently being used.
1180 g_usDataType |= TDO_DATA;
1185 * Store the maximum size of the TDO buffer.
1186 * Used to convert VME to HEX.
1189 if (g_usiDataSize > g_usTDOSize) {
1190 g_usTDOSize = g_usiDataSize;
1194 * Updated data type register to indicate
1195 * that TDO data is currently being used.
1196 * Process the data in the VME file into the
1200 g_usDataType |= TDO_DATA;
1201 ispVMData(g_pucOutData);
1206 * Store the maximum size of the MASK buffer.
1207 * Used to convert VME to HEX.
1210 if (g_usiDataSize > g_usMASKSize) {
1211 g_usMASKSize = g_usiDataSize;
1215 * Updated data type register to indicate that
1216 * MASK data is currently being used. Process
1217 * the data in the VME file into the MASK buffer
1220 g_usDataType |= MASK_DATA;
1221 ispVMData(g_pucOutMaskData);
1226 * Store the maximum size of the DMASK buffer.
1227 * Used to convert VME to HEX.
1230 if (g_usiDataSize > g_usDMASKSize) {
1231 g_usDMASKSize = g_usiDataSize;
1235 * Updated data type register to indicate that
1236 * DMASK data is currently being used. Process
1237 * the data in the VME file into the DMASK
1241 g_usDataType |= DMASK_DATA;
1242 ispVMData(g_pucOutDMaskData);
1247 * Updated data type register to indicate that
1248 * MASK data is currently being used. Process
1249 * the data in the VME file into the MASK buffer
1252 g_usDataType |= CMASK_DATA;
1253 ispVMData(g_pucOutMaskData);
1259 * Encountered invalid opcode.
1261 return VME_INVALID_FILE;
1264 switch (cDataByte) {
1268 * Left bit shift. Used when performing
1269 * algorithm looping.
1272 if (g_usFlowControl & SHIFTLEFT) {
1273 ispVMBitShift(SHL, g_usShiftValue);
1274 g_usFlowControl &= ~SHIFTLEFT;
1278 * Right bit shift. Used when performing
1279 * algorithm looping.
1282 if (g_usFlowControl & SHIFTRIGHT) {
1283 ispVMBitShift(SHR, g_usShiftValue);
1284 g_usFlowControl &= ~SHIFTRIGHT;
1291 g_usDataType |= HEAP_IN; /*restore from memory*/
1295 if (siDataSource) { /*fetch data from heap memory upon return*/
1296 g_usDataType |= HEAP_IN;
1299 if (cDataByte < 0) {
1302 * Encountered invalid opcode.
1305 return VME_INVALID_FILE;
1314 * Extract one row of data operand from the current data type opcode. Perform
1315 * the decompression if necessary. Extra RAM is not required for the
1316 * decompression process. The decompression scheme employed in this module
1317 * is on row by row basis. The format of the data stream:
1318 * [compression code][compressed data stream]
1319 * 0x00 --No compression
1320 * 0x01 --Compress by 0x00.
1322 * Original stream: 0x000000000000000000000001
1323 * Compressed stream: 0x01000901
1324 * Detail: 0x01 is the code, 0x00 is the key,
1325 * 0x09 is the count of 0x00 bytes,
1326 * 0x01 is the uncompressed byte.
1327 * 0x02 --Compress by 0xFF.
1329 * Original stream: 0xFFFFFFFFFFFFFFFFFFFFFF01
1330 * Compressed stream: 0x02FF0901
1331 * Detail: 0x02 is the code, 0xFF is the key,
1332 * 0x09 is the count of 0xFF bytes,
1333 * 0x01 is the uncompressed byte.
1336 * 0xFE -- Compress by nibble blocks.
1338 * Original stream: 0x84210842108421084210
1339 * Compressed stream: 0x0584210
1340 * Detail: 0x05 is the code, means 5 nibbles block.
1341 * 0x84210 is the 5 nibble blocks.
1342 * The whole row is 80 bits given by g_usiDataSize.
1343 * The number of times the block repeat itself
1344 * is found by g_usiDataSize/(4*0x05) which is 4.
1345 * 0xFF -- Compress by the most frequently happen byte.
1347 * Original stream: 0x04020401030904040404
1348 * Compressed stream: 0xFF04(0,1,0x02,0,1,0x01,1,0x03,1,0x09,0,0,0)
1349 * or: 0xFF044090181C240
1350 * Detail: 0xFF is the code, 0x04 is the key.
1351 * a bit of 0 represent the key shall be put into
1352 * the current bit position and a bit of 1
1353 * represent copying the next of 8 bits of data
1358 void ispVMData(unsigned char *ByteData)
1360 /* 09/11/07 NN added local variables initialization */
1361 unsigned short size = 0;
1362 unsigned short i, j, m, getData = 0;
1363 unsigned char cDataByte = 0;
1364 unsigned char compress = 0;
1365 unsigned short FFcount = 0;
1366 unsigned char compr_char = 0xFF;
1367 unsigned short index = 0;
1368 signed char compression = 0;
1370 /*convert number in bits to bytes*/
1371 if (g_usiDataSize % 8 > 0) {
1372 /* 09/11/07 NN Type cast mismatch variables */
1373 size = (unsigned short)(g_usiDataSize / 8 + 1);
1375 /* 09/11/07 NN Type cast mismatch variables */
1376 size = (unsigned short)(g_usiDataSize / 8);
1380 * If there is compression, then check if compress by key
1381 * of 0x00 or 0xFF or by other keys or by nibble blocks
1384 if (g_usDataType & COMPRESS) {
1386 compress = GetByte();
1387 if ((compress == VAR) && (g_usDataType & HEAP_IN)) {
1389 g_usDataType &= ~(HEAP_IN);
1390 compress = GetByte();
1395 /* No compression */
1399 /* Compress by byte 0x00 */
1403 /* Compress by byte 0xFF */
1407 /* Huffman encoding */
1408 compr_char = GetByte();
1410 for (index = 0; index < size; index++) {
1411 ByteData[index] = 0x00;
1413 cDataByte = GetByte();
1416 if ((cDataByte << i++) & 0x80)
1419 ByteData[index] = compr_char;
1423 for (j = 0; j < m; j++) {
1425 cDataByte = GetByte();
1429 ((cDataByte << i++) & 0x80) >> j;
1435 for (index = 0; index < size; index++)
1436 ByteData[index] = 0x00;
1437 for (index = 0; index < compress; index++) {
1439 cDataByte = GetByte();
1440 for (i = 0; i < size * 2 / compress; i++) {
1441 j = (unsigned short)(index +
1442 (i * (unsigned short)compress));
1443 /*clear the nibble to zero first*/
1468 /* Decompress by byte 0x00 or 0xFF */
1469 for (index = 0; index < size; index++) {
1471 cDataByte = GetByte();
1472 if ((cDataByte == VAR) && (g_usDataType&HEAP_IN) &&
1473 !getData && !(g_usDataType&COMPRESS)) {
1475 g_usDataType &= ~(HEAP_IN);
1476 cDataByte = GetByte();
1478 ByteData[index] = cDataByte;
1479 if ((compression) && (cDataByte == compr_char))
1480 /* 09/11/07 NN Type cast mismatch variables */
1481 FFcount = (unsigned short) ispVMDataSize();
1482 /*The number of 0xFF or 0x00 bytes*/
1484 FFcount--; /*Use up the 0xFF chain first*/
1485 ByteData[index] = compr_char;
1490 g_usDataType |= HEAP_IN;
1499 * Processes the SDR/XSDR/SIR commands.
1503 signed char ispVMShift(signed char a_cCode)
1505 /* 09/11/07 NN added local variables initialization */
1506 unsigned short iDataIndex = 0;
1507 unsigned short iReadLoop = 0;
1508 signed char cRetCode = 0;
1511 /* 09/11/07 NN Type cast mismatch variables */
1512 g_usiDataSize = (unsigned short) ispVMDataSize();
1514 /*clear the flags first*/
1515 g_usDataType &= ~(SIR_DATA + EXPRESS + SDR_DATA);
1518 g_usDataType |= SIR_DATA;
1520 * 1/15/04 If performing cascading, then go directly to SHIFTIR.
1521 * Else, go to IRPAUSE before going to SHIFTIR
1523 if (g_usFlowControl & CASCADE) {
1524 ispVMStateMachine(SHIFTIR);
1526 ispVMStateMachine(IRPAUSE);
1527 ispVMStateMachine(SHIFTIR);
1528 if (g_usHeadIR > 0) {
1529 ispVMBypass(HIR, g_usHeadIR);
1535 g_usDataType |= EXPRESS; /*mark simultaneous in and out*/
1537 g_usDataType |= SDR_DATA;
1539 * 1/15/04 If already in SHIFTDR, then do not move state or
1540 * shift in header. This would imply that the previously
1541 * shifted frame was a cascaded frame.
1543 if (g_cCurrentJTAGState != SHIFTDR) {
1545 * 1/15/04 If performing cascading, then go directly
1546 * to SHIFTDR. Else, go to DRPAUSE before going
1549 if (g_usFlowControl & CASCADE) {
1550 if (g_cCurrentJTAGState == DRPAUSE) {
1551 ispVMStateMachine(SHIFTDR);
1553 * 1/15/04 If cascade flag has been seat
1554 * and the current state is DRPAUSE,
1555 * this implies that the first cascaded
1556 * frame is about to be shifted in. The
1557 * header must be shifted prior to
1558 * shifting the first cascaded frame.
1560 if (g_usHeadDR > 0) {
1561 ispVMBypass(HDR, g_usHeadDR);
1565 ispVMStateMachine(SHIFTDR);
1568 ispVMStateMachine(DRPAUSE);
1569 ispVMStateMachine(SHIFTDR);
1570 if (g_usHeadDR > 0) {
1571 ispVMBypass(HDR, g_usHeadDR);
1578 return VME_INVALID_FILE;
1581 cRetCode = ispVMDataCode();
1583 if (cRetCode != 0) {
1584 return VME_INVALID_FILE;
1588 printf("%d ", g_usiDataSize);
1590 if (g_usDataType & TDI_DATA) {
1592 PrintData(g_usiDataSize, g_pucInData);
1595 if (g_usDataType & TDO_DATA) {
1597 PrintData(g_usiDataSize, g_pucOutData);
1600 if (g_usDataType & MASK_DATA) {
1601 puts("\n\t\tMASK ");
1602 PrintData(g_usiDataSize, g_pucOutMaskData);
1605 if (g_usDataType & DMASK_DATA) {
1606 puts("\n\t\tDMASK ");
1607 PrintData(g_usiDataSize, g_pucOutDMaskData);
1613 if (g_usDataType & TDO_DATA || g_usDataType & DMASK_DATA) {
1614 if (g_usDataType & DMASK_DATA) {
1615 cRetCode = ispVMReadandSave(g_usiDataSize);
1617 if (g_usTailDR > 0) {
1619 ispVMBypass(TDR, g_usTailDR);
1621 ispVMStateMachine(DRPAUSE);
1622 ispVMStateMachine(SHIFTDR);
1623 if (g_usHeadDR > 0) {
1624 ispVMBypass(HDR, g_usHeadDR);
1627 for (iDataIndex = 0;
1628 iDataIndex < g_usiDataSize / 8 + 1;
1630 g_pucInData[iDataIndex] =
1631 g_pucOutData[iDataIndex];
1632 g_usDataType &= ~(TDO_DATA + DMASK_DATA);
1633 cRetCode = ispVMSend(g_usiDataSize);
1636 cRetCode = ispVMRead(g_usiDataSize);
1637 if (cRetCode == -1 && g_cVendor == XILINX) {
1638 for (iReadLoop = 0; iReadLoop < 30;
1640 cRetCode = ispVMRead(g_usiDataSize);
1644 /* Always DRPAUSE */
1645 ispVMStateMachine(DRPAUSE);
1647 * Bypass other devices
1650 ispVMBypass(TDR, g_usTailDR);
1651 ispVMStateMachine(g_ucEndDR);
1652 ispVMStateMachine(IDLE);
1658 } else { /*TDI only*/
1659 cRetCode = ispVMSend(g_usiDataSize);
1662 /*transfer the input data to the output buffer for the next verify*/
1663 if ((g_usDataType & EXPRESS) || (a_cCode == SDR)) {
1665 for (iDataIndex = 0; iDataIndex < g_usiDataSize / 8 + 1;
1667 g_pucOutData[iDataIndex] =
1668 g_pucInData[iDataIndex];
1674 /* 1/15/04 If not performing cascading, then shift ENDIR */
1675 if (!(g_usFlowControl & CASCADE)) {
1676 if (g_usTailIR > 0) {
1678 ispVMBypass(TIR, g_usTailIR);
1680 ispVMStateMachine(g_ucEndIR);
1685 /* 1/15/04 If not performing cascading, then shift ENDDR */
1686 if (!(g_usFlowControl & CASCADE)) {
1687 if (g_usTailDR > 0) {
1689 ispVMBypass(TDR, g_usTailDR);
1691 ispVMStateMachine(g_ucEndDR);
1705 * This routine is to extract Header and Trailer parameter for SIR and
1708 * The Header and Trailer parameter are the pre-amble and post-amble bit
1709 * stream need to be shifted into TDI or out of TDO of the devices. Mostly
1710 * is for the purpose of bypassing the leading or trailing devices. ispVM
1711 * supports only shifting data into TDI to bypass the devices.
1713 * For a single device, the header and trailer parameters are all set to 0
1714 * as default by ispVM. If it is for multiple devices, the header and trailer
1715 * value will change as specified by the VME file.
1719 signed char ispVMAmble(signed char Code)
1721 signed char compress = 0;
1722 /* 09/11/07 NN Type cast mismatch variables */
1723 g_usiDataSize = (unsigned short)ispVMDataSize();
1726 printf("%d", g_usiDataSize);
1729 if (g_usiDataSize) {
1732 * Discard the TDI byte and set the compression bit in the data
1733 * type register to false if compression is set because TDI data
1734 * after HIR/HDR/TIR/TDR is not compressed.
1738 if (g_usDataType & COMPRESS) {
1739 g_usDataType &= ~(COMPRESS);
1748 * Store the maximum size of the HIR buffer.
1749 * Used to convert VME to HEX.
1752 if (g_usiDataSize > g_usHIRSize) {
1753 g_usHIRSize = g_usiDataSize;
1757 * Assign the HIR value and allocate memory.
1760 g_usHeadIR = g_usiDataSize;
1762 ispVMMemManager(HIR, g_usHeadIR);
1763 ispVMData(g_pucHIRData);
1767 PrintData(g_usHeadIR, g_pucHIRData);
1774 * Store the maximum size of the TIR buffer.
1775 * Used to convert VME to HEX.
1778 if (g_usiDataSize > g_usTIRSize) {
1779 g_usTIRSize = g_usiDataSize;
1783 * Assign the TIR value and allocate memory.
1786 g_usTailIR = g_usiDataSize;
1788 ispVMMemManager(TIR, g_usTailIR);
1789 ispVMData(g_pucTIRData);
1793 PrintData(g_usTailIR, g_pucTIRData);
1800 * Store the maximum size of the HDR buffer.
1801 * Used to convert VME to HEX.
1804 if (g_usiDataSize > g_usHDRSize) {
1805 g_usHDRSize = g_usiDataSize;
1809 * Assign the HDR value and allocate memory.
1813 g_usHeadDR = g_usiDataSize;
1815 ispVMMemManager(HDR, g_usHeadDR);
1816 ispVMData(g_pucHDRData);
1820 PrintData(g_usHeadDR, g_pucHDRData);
1827 * Store the maximum size of the TDR buffer.
1828 * Used to convert VME to HEX.
1831 if (g_usiDataSize > g_usTDRSize) {
1832 g_usTDRSize = g_usiDataSize;
1836 * Assign the TDR value and allocate memory.
1840 g_usTailDR = g_usiDataSize;
1842 ispVMMemManager(TDR, g_usTailDR);
1843 ispVMData(g_pucTDRData);
1847 PrintData(g_usTailDR, g_pucTDRData);
1857 * Re-enable compression if it was previously set.
1862 g_usDataType |= COMPRESS;
1865 if (g_usiDataSize) {
1867 if (Code == CONTINUE) {
1872 * Encountered invalid opcode.
1875 return VME_INVALID_FILE;
1886 * Perform the function call upon by the REPEAT opcode.
1887 * Memory is to be allocated to store the entire loop from REPEAT to ENDLOOP.
1888 * After the loop is stored then execution begin. The REPEATLOOP flag is set
1889 * on the g_usFlowControl register to indicate the repeat loop is in session
1890 * and therefore fetch opcode from the memory instead of from the file.
1894 signed char ispVMLoop(unsigned short a_usLoopCount)
1896 /* 09/11/07 NN added local variables initialization */
1897 signed char cRetCode = 0;
1898 unsigned short iHeapIndex = 0;
1899 unsigned short iLoopIndex = 0;
1902 for (iHeapIndex = 0; iHeapIndex < g_iHEAPSize; iHeapIndex++) {
1903 g_pucHeapMemory[iHeapIndex] = GetByte();
1906 if (g_pucHeapMemory[iHeapIndex - 1] != ENDLOOP) {
1907 return VME_INVALID_FILE;
1910 g_usFlowControl |= REPEATLOOP;
1911 g_usDataType |= HEAP_IN;
1913 for (iLoopIndex = 0; iLoopIndex < a_usLoopCount; iLoopIndex++) {
1915 cRetCode = ispVMCode();
1922 g_usDataType &= ~(HEAP_IN);
1923 g_usFlowControl &= ~(REPEATLOOP);
1931 * Shift the TDI stream left or right by the number of bits. The data in
1932 * *g_pucInData is of the VME format, so the actual shifting is the reverse of
1933 * IEEE 1532 or SVF format.
1937 signed char ispVMBitShift(signed char mode, unsigned short bits)
1939 /* 09/11/07 NN added local variables initialization */
1940 unsigned short i = 0;
1941 unsigned short size = 0;
1942 unsigned short tmpbits = 0;
1944 if (g_usiDataSize % 8 > 0) {
1945 /* 09/11/07 NN Type cast mismatch variables */
1946 size = (unsigned short)(g_usiDataSize / 8 + 1);
1948 /* 09/11/07 NN Type cast mismatch variables */
1949 size = (unsigned short)(g_usiDataSize / 8);
1954 for (i = 0; i < size; i++) {
1955 if (g_pucInData[i] != 0) {
1957 while (tmpbits > 0) {
1958 g_pucInData[i] <<= 1;
1959 if (g_pucInData[i] == 0) {
1969 for (i = 0; i < size; i++) {
1970 if (g_pucInData[i] != 0) {
1972 while (tmpbits > 0) {
1973 g_pucInData[i] >>= 1;
1974 if (g_pucInData[i] == 0) {
1984 return VME_INVALID_FILE;
1994 * Displays the SVF comments.
1998 void ispVMComment(unsigned short a_usCommentSize)
2001 for (; a_usCommentSize > 0; a_usCommentSize--) {
2004 * Print character to the terminal.
2007 cCurByte = GetByte();
2008 vme_out_char(cCurByte);
2011 vme_out_char(cCurByte);
2018 * Iterate the length of the header and discard it.
2022 void ispVMHeader(unsigned short a_usHeaderSize)
2024 for (; a_usHeaderSize > 0; a_usHeaderSize--) {
2031 * ispVMCalculateCRC32
2033 * Calculate the 32-bit CRC.
2037 void ispVMCalculateCRC32(unsigned char a_ucData)
2039 /* 09/11/07 NN added local variables initialization */
2040 unsigned char ucIndex = 0;
2041 unsigned char ucFlipData = 0;
2042 unsigned short usCRCTableEntry = 0;
2043 unsigned int crc_table[16] = {
2044 0x0000, 0xCC01, 0xD801,
2045 0x1400, 0xF001, 0x3C00,
2046 0x2800, 0xE401, 0xA001,
2047 0x6C00, 0x7800, 0xB401,
2048 0x5000, 0x9C01, 0x8801,
2052 for (ucIndex = 0; ucIndex < 8; ucIndex++) {
2054 if (a_ucData & 0x01) {
2060 /* 09/11/07 NN Type cast mismatch variables */
2061 usCRCTableEntry = (unsigned short)(crc_table[g_usCalculatedCRC & 0xF]);
2062 g_usCalculatedCRC = (unsigned short)((g_usCalculatedCRC >> 4) & 0x0FFF);
2063 g_usCalculatedCRC = (unsigned short)(g_usCalculatedCRC ^
2064 usCRCTableEntry ^ crc_table[ucFlipData & 0xF]);
2065 usCRCTableEntry = (unsigned short)(crc_table[g_usCalculatedCRC & 0xF]);
2066 g_usCalculatedCRC = (unsigned short)((g_usCalculatedCRC >> 4) & 0x0FFF);
2067 g_usCalculatedCRC = (unsigned short)(g_usCalculatedCRC ^
2068 usCRCTableEntry ^ crc_table[(ucFlipData >> 4) & 0xF]);
2075 * Process the intelligent programming loops.
2079 signed char ispVMLCOUNT(unsigned short a_usCountSize)
2081 unsigned short usContinue = 1;
2082 unsigned short usIntelBufferIndex = 0;
2083 unsigned short usCountIndex = 0;
2084 signed char cRetCode = 0;
2085 signed char cRepeatHeap = 0;
2086 signed char cOpcode = 0;
2087 unsigned char ucState = 0;
2088 unsigned short usDelay = 0;
2089 unsigned short usToggle = 0;
2091 g_usIntelBufferSize = (unsigned short)ispVMDataSize();
2094 * Allocate memory for intel buffer.
2098 ispVMMemManager(LHEAP, g_usIntelBufferSize);
2101 * Store the maximum size of the intelligent buffer.
2102 * Used to convert VME to HEX.
2105 if (g_usIntelBufferSize > g_usLCOUNTSize) {
2106 g_usLCOUNTSize = g_usIntelBufferSize;
2110 * Copy intel data to the buffer.
2113 for (usIntelBufferIndex = 0; usIntelBufferIndex < g_usIntelBufferSize;
2114 usIntelBufferIndex++) {
2115 g_pucIntelBuffer[usIntelBufferIndex] = GetByte();
2119 * Set the data type register to get data from the intelligent
2123 g_usDataType |= LHEAP_IN;
2127 * If the HEAP_IN flag is set, temporarily unset the flag so data will be
2128 * retrieved from the status buffer.
2132 if (g_usDataType & HEAP_IN) {
2133 g_usDataType &= ~HEAP_IN;
2138 printf("LCOUNT %d;\n", a_usCountSize);
2142 * Iterate through the intelligent programming command.
2145 for (usCountIndex = 0; usCountIndex < a_usCountSize; usCountIndex++) {
2149 * Initialize the intel data index to 0 before each iteration.
2153 g_usIntelDataIndex = 0;
2162 * Begin looping through all the VME opcodes.
2166 * 4/1/09 Nguyen replaced the recursive function call codes on
2167 * the ispVMLCOUNT function
2170 while (usContinue) {
2171 cOpcode = GetByte();
2178 * Set the header/trailer of the device in order
2179 * to bypass successfully.
2182 ispVMAmble(cOpcode);
2187 * Step the JTAG state machine.
2190 ucState = GetByte();
2192 * Step the JTAG state machine to DRCAPTURE
2193 * to support Looping.
2196 if ((g_usDataType & LHEAP_IN) &&
2197 (ucState == DRPAUSE) &&
2198 (g_cCurrentJTAGState == ucState)) {
2199 ispVMStateMachine(DRCAPTURE);
2201 ispVMStateMachine(ucState);
2203 printf("LDELAY %s ", GetState(ucState));
2211 * Shift in data into the device.
2214 cRetCode = ispVMShift(cOpcode);
2222 * Shift in data into the device.
2225 cRetCode = ispVMShift(cOpcode);
2235 usDelay = (unsigned short)ispVMDataSize();
2236 ispVMDelay(usDelay);
2239 if (usDelay & 0x8000) {
2242 * Since MSB is set, the delay time must
2243 * be decoded to millisecond. The
2244 * SVF2VME encodes the MSB to represent
2249 printf("%.2E SEC;\n",
2250 (float) usDelay / 1000);
2253 * Since MSB is not set, the delay time
2254 * is given as microseconds.
2257 printf("%.2E SEC;\n",
2258 (float) usDelay / 1000000);
2265 * Issue clock toggles.
2268 usToggle = (unsigned short)ispVMDataSize();
2269 ispVMClocks(usToggle);
2272 printf("RUNTEST %d TCK;\n", usToggle);
2278 * Exit point from processing loops.
2289 ispVMComment((unsigned short) ispVMDataSize());
2292 ucState = GetByte();
2293 if ((ucState == ON) || (ucState == 0x01))
2294 writePort(g_ucPinENABLE, 0x01);
2296 writePort(g_ucPinENABLE, 0x00);
2300 if (GetByte() == 0x01)
2301 writePort(g_ucPinTRST, 0x01);
2303 writePort(g_ucPinTRST, 0x00);
2309 * Invalid opcode encountered.
2312 debug("\nINVALID OPCODE: 0x%.2X\n", cOpcode);
2314 return VME_INVALID_FILE;
2317 if (cRetCode >= 0) {
2319 * Break if intelligent programming is successful.
2327 * If HEAP_IN flag was temporarily disabled,
2328 * re-enable it before exiting
2332 g_usDataType |= HEAP_IN;
2336 * Set the data type register to not get data from the
2337 * intelligent data buffer.
2340 g_usDataType &= ~LHEAP_IN;
2347 * Applies the specified number of pulses to TCK.
2351 void ispVMClocks(unsigned short Clocks)
2353 unsigned short iClockIndex = 0;
2354 for (iClockIndex = 0; iClockIndex < Clocks; iClockIndex++) {
2363 * This procedure takes care of the HIR, HDR, TIR, TDR for the
2364 * purpose of putting the other devices into Bypass mode. The
2365 * current state is checked to find out if it is at DRPAUSE or
2366 * IRPAUSE. If it is at DRPAUSE, perform bypass register scan.
2367 * If it is at IRPAUSE, scan into instruction registers the bypass
2372 void ispVMBypass(signed char ScanType, unsigned short Bits)
2374 /* 09/11/07 NN added local variables initialization */
2375 unsigned short iIndex = 0;
2376 unsigned short iSourceIndex = 0;
2377 unsigned char cBitState = 0;
2378 unsigned char cCurByte = 0;
2379 unsigned char *pcSource = NULL;
2387 pcSource = g_pucHIRData;
2390 pcSource = g_pucTIRData;
2393 pcSource = g_pucHDRData;
2396 pcSource = g_pucTDRData;
2404 for (iIndex = 0; iIndex < Bits - 1; iIndex++) {
2405 /* Scan instruction or bypass register */
2406 if (iIndex % 8 == 0) {
2407 cCurByte = pcSource[iSourceIndex++];
2409 cBitState = (unsigned char) (((cCurByte << iIndex % 8) & 0x80)
2411 writePort(g_ucPinTDI, cBitState);
2415 if (iIndex % 8 == 0) {
2416 cCurByte = pcSource[iSourceIndex++];
2419 cBitState = (unsigned char) (((cCurByte << iIndex % 8) & 0x80)
2421 writePort(g_ucPinTDI, cBitState);
2428 * This procedure steps all devices in the daisy chain from a given
2429 * JTAG state to the next desirable state. If the next state is TLR,
2430 * the JTAG state machine is brute forced into TLR by driving TMS
2431 * high and pulse TCK 6 times.
2435 void ispVMStateMachine(signed char cNextJTAGState)
2437 /* 09/11/07 NN added local variables initialization */
2438 signed char cPathIndex = 0;
2439 signed char cStateIndex = 0;
2441 if ((g_cCurrentJTAGState == cNextJTAGState) &&
2442 (cNextJTAGState != RESET)) {
2446 for (cStateIndex = 0; cStateIndex < 25; cStateIndex++) {
2447 if ((g_cCurrentJTAGState ==
2448 g_JTAGTransistions[cStateIndex].CurState) &&
2450 g_JTAGTransistions[cStateIndex].NextState)) {
2455 g_cCurrentJTAGState = cNextJTAGState;
2456 for (cPathIndex = 0;
2457 cPathIndex < g_JTAGTransistions[cStateIndex].Pulses;
2459 if ((g_JTAGTransistions[cStateIndex].Pattern << cPathIndex)
2461 writePort(g_ucPinTMS, (unsigned char) 0x01);
2463 writePort(g_ucPinTMS, (unsigned char) 0x00);
2468 writePort(g_ucPinTDI, 0x00);
2469 writePort(g_ucPinTMS, 0x00);
2476 * Enable the port to the device and set the state to RESET (TLR).
2483 printf("// ISPVM EMBEDDED ADDED\n");
2484 printf("STATE RESET;\n");
2486 g_usFlowControl = 0;
2487 g_usDataType = g_uiChecksumIndex = g_cCurrentJTAGState = 0;
2488 g_usHeadDR = g_usHeadIR = g_usTailDR = g_usTailIR = 0;
2489 g_usMaxSize = g_usShiftValue = g_usRepeatLoops = 0;
2490 g_usTDOSize = g_usMASKSize = g_usTDISize = 0;
2491 g_usDMASKSize = g_usLCOUNTSize = g_usHDRSize = 0;
2492 g_usTDRSize = g_usHIRSize = g_usTIRSize = g_usHeapSize = 0;
2494 g_usLVDSPairCount = 0;
2497 ispVMStateMachine(RESET); /*step devices to RESET state*/
2504 * Set the state of devices to RESET to enable the devices and disable
2512 printf("// ISPVM EMBEDDED ADDED\n");
2513 printf("STATE RESET;\n");
2514 printf("RUNTEST 1.00E-001 SEC;\n");
2517 ispVMStateMachine(RESET); /*step devices to RESET state */
2518 ispVMDelay(1000); /*wake up devices*/
2525 * Send the TDI data stream to devices. The data stream can be
2526 * instructions or data.
2530 signed char ispVMSend(unsigned short a_usiDataSize)
2532 /* 09/11/07 NN added local variables initialization */
2533 unsigned short iIndex = 0;
2534 unsigned short iInDataIndex = 0;
2535 unsigned char cCurByte = 0;
2536 unsigned char cBitState = 0;
2538 for (iIndex = 0; iIndex < a_usiDataSize - 1; iIndex++) {
2539 if (iIndex % 8 == 0) {
2540 cCurByte = g_pucInData[iInDataIndex++];
2542 cBitState = (unsigned char)(((cCurByte << iIndex % 8) & 0x80)
2544 writePort(g_ucPinTDI, cBitState);
2548 if (iIndex % 8 == 0) {
2549 /* Take care of the last bit */
2550 cCurByte = g_pucInData[iInDataIndex];
2553 cBitState = (unsigned char) (((cCurByte << iIndex % 8) & 0x80)
2556 writePort(g_ucPinTDI, cBitState);
2557 if (g_usFlowControl & CASCADE) {
2558 /*1/15/04 Clock in last bit for the first n-1 cascaded frames */
2569 * Read the data stream from devices and verify.
2573 signed char ispVMRead(unsigned short a_usiDataSize)
2575 /* 09/11/07 NN added local variables initialization */
2576 unsigned short usDataSizeIndex = 0;
2577 unsigned short usErrorCount = 0;
2578 unsigned short usLastBitIndex = 0;
2579 unsigned char cDataByte = 0;
2580 unsigned char cMaskByte = 0;
2581 unsigned char cInDataByte = 0;
2582 unsigned char cCurBit = 0;
2583 unsigned char cByteIndex = 0;
2584 unsigned short usBufferIndex = 0;
2585 unsigned char ucDisplayByte = 0x00;
2586 unsigned char ucDisplayFlag = 0x01;
2587 char StrChecksum[256] = {0};
2588 unsigned char g_usCalculateChecksum = 0x00;
2590 /* 09/11/07 NN Type cast mismatch variables */
2591 usLastBitIndex = (unsigned short)(a_usiDataSize - 1);
2595 * If mask is not all zeros, then set the display flag to 0x00,
2596 * otherwise it shall be set to 0x01 to indicate that data read
2597 * from the device shall be displayed. If DEBUG is defined,
2598 * always display data.
2601 for (usDataSizeIndex = 0; usDataSizeIndex < (a_usiDataSize + 7) / 8;
2602 usDataSizeIndex++) {
2603 if (g_usDataType & MASK_DATA) {
2604 if (g_pucOutMaskData[usDataSizeIndex] != 0x00) {
2605 ucDisplayFlag = 0x00;
2608 } else if (g_usDataType & CMASK_DATA) {
2609 g_usCalculateChecksum = 0x01;
2610 ucDisplayFlag = 0x00;
2613 ucDisplayFlag = 0x00;
2621 * Begin shifting data in and out of the device.
2625 for (usDataSizeIndex = 0; usDataSizeIndex < a_usiDataSize;
2626 usDataSizeIndex++) {
2627 if (cByteIndex == 0) {
2630 * Grab byte from TDO buffer.
2633 if (g_usDataType & TDO_DATA) {
2634 cDataByte = g_pucOutData[usBufferIndex];
2638 * Grab byte from MASK buffer.
2641 if (g_usDataType & MASK_DATA) {
2642 cMaskByte = g_pucOutMaskData[usBufferIndex];
2648 * Grab byte from CMASK buffer.
2651 if (g_usDataType & CMASK_DATA) {
2653 g_usCalculateChecksum = 0x01;
2657 * Grab byte from TDI buffer.
2660 if (g_usDataType & TDI_DATA) {
2661 cInDataByte = g_pucInData[usBufferIndex];
2667 cCurBit = readPort();
2669 if (ucDisplayFlag) {
2670 ucDisplayByte <<= 1;
2671 ucDisplayByte |= cCurBit;
2675 * Check if data read from port matches with expected TDO.
2678 if (g_usDataType & TDO_DATA) {
2679 /* 08/28/08 NN Added Calculate checksum support. */
2680 if (g_usCalculateChecksum) {
2681 if (cCurBit == 0x01)
2683 (1 << (g_uiChecksumIndex % 8));
2684 g_uiChecksumIndex++;
2686 if ((((cMaskByte << cByteIndex) & 0x80)
2688 if (cCurBit != (unsigned char)
2689 (((cDataByte << cByteIndex) & 0x80)
2698 * Write TDI data to the port.
2701 writePort(g_ucPinTDI,
2702 (unsigned char)(((cInDataByte << cByteIndex) & 0x80)
2705 if (usDataSizeIndex < usLastBitIndex) {
2708 * Clock data out from the data shift register.
2712 } else if (g_usFlowControl & CASCADE) {
2715 * Clock in last bit for the first N - 1 cascaded frames
2722 * Increment the byte index. If it exceeds 7, then reset it back
2727 if (cByteIndex >= 8) {
2728 if (ucDisplayFlag) {
2731 * Store displayed data in the TDO buffer. By reusing
2732 * the TDO buffer to store displayed data, there is no
2733 * need to allocate a buffer simply to hold display
2734 * data. This will not cause any false verification
2735 * errors because the true TDO byte has already
2739 g_pucOutData[usBufferIndex - 1] = ucDisplayByte;
2745 /* 09/12/07 Nguyen changed to display the 1 bit expected data */
2746 else if (a_usiDataSize == 1) {
2747 if (ucDisplayFlag) {
2750 * Store displayed data in the TDO buffer.
2751 * By reusing the TDO buffer to store displayed
2752 * data, there is no need to allocate
2753 * a buffer simply to hold display data. This
2754 * will not cause any false verification errors
2755 * because the true TDO byte has already
2760 * Flip ucDisplayByte and store it in cDataByte.
2763 for (usBufferIndex = 0; usBufferIndex < 8;
2766 if (ucDisplayByte & 0x01) {
2769 ucDisplayByte >>= 1;
2771 g_pucOutData[0] = cDataByte;
2779 if (ucDisplayFlag) {
2782 debug("RECEIVED TDO (");
2784 vme_out_string("Display Data: 0x");
2787 /* 09/11/07 NN Type cast mismatch variables */
2788 for (usDataSizeIndex = (unsigned short)
2789 ((a_usiDataSize + 7) / 8);
2790 usDataSizeIndex > 0 ; usDataSizeIndex--) {
2791 cMaskByte = g_pucOutData[usDataSizeIndex - 1];
2795 * Flip cMaskByte and store it in cDataByte.
2798 for (usBufferIndex = 0; usBufferIndex < 8;
2801 if (cMaskByte & 0x01) {
2807 printf("%.2X", cDataByte);
2808 if ((((a_usiDataSize + 7) / 8) - usDataSizeIndex)
2813 vme_out_hex(cDataByte);
2820 vme_out_string("\n\n");
2822 /* 09/02/08 Nguyen changed to display the data Checksum */
2823 if (g_usChecksum != 0) {
2824 g_usChecksum &= 0xFFFF;
2825 sprintf(StrChecksum, "Data Checksum: %.4lX\n\n",
2827 vme_out_string(StrChecksum);
2832 if (usErrorCount > 0) {
2833 if (g_usFlowControl & VERIFYUES) {
2835 "USERCODE verification failed. "
2836 "Continue programming......\n\n");
2837 g_usFlowControl &= ~(VERIFYUES);
2842 printf("TOTAL ERRORS: %d\n", usErrorCount);
2845 return VME_VERIFICATION_FAILURE;
2848 if (g_usFlowControl & VERIFYUES) {
2849 vme_out_string("USERCODE verification passed. "
2850 "Programming aborted.\n\n");
2851 g_usFlowControl &= ~(VERIFYUES);
2863 * Support dynamic I/O.
2867 signed char ispVMReadandSave(unsigned short int a_usiDataSize)
2869 /* 09/11/07 NN added local variables initialization */
2870 unsigned short int usDataSizeIndex = 0;
2871 unsigned short int usLastBitIndex = 0;
2872 unsigned short int usBufferIndex = 0;
2873 unsigned short int usOutBitIndex = 0;
2874 unsigned short int usLVDSIndex = 0;
2875 unsigned char cDataByte = 0;
2876 unsigned char cDMASKByte = 0;
2877 unsigned char cInDataByte = 0;
2878 unsigned char cCurBit = 0;
2879 unsigned char cByteIndex = 0;
2880 signed char cLVDSByteIndex = 0;
2882 /* 09/11/07 NN Type cast mismatch variables */
2883 usLastBitIndex = (unsigned short) (a_usiDataSize - 1);
2887 * Iterate through the data bits.
2891 for (usDataSizeIndex = 0; usDataSizeIndex < a_usiDataSize;
2892 usDataSizeIndex++) {
2893 if (cByteIndex == 0) {
2896 * Grab byte from DMASK buffer.
2899 if (g_usDataType & DMASK_DATA) {
2900 cDMASKByte = g_pucOutDMaskData[usBufferIndex];
2906 * Grab byte from TDI buffer.
2909 if (g_usDataType & TDI_DATA) {
2910 cInDataByte = g_pucInData[usBufferIndex];
2916 cCurBit = readPort();
2917 cDataByte = (unsigned char)(((cInDataByte << cByteIndex) & 0x80)
2921 * Initialize the byte to be zero.
2924 if (usOutBitIndex % 8 == 0) {
2925 g_pucOutData[usOutBitIndex / 8] = 0x00;
2929 * Use TDI, DMASK, and device TDO to create new TDI (actually
2930 * stored in g_pucOutData).
2933 if ((((cDMASKByte << cByteIndex) & 0x80) ? 0x01 : 0x00)) {
2936 for (usLVDSIndex = 0;
2937 usLVDSIndex < g_usLVDSPairCount;
2939 if (g_pLVDSList[usLVDSIndex].
2942 g_pLVDSList[usLVDSIndex].
2950 * DMASK bit is 1, use TDI.
2953 g_pucOutData[usOutBitIndex / 8] |= (unsigned char)
2954 (((cDataByte & 0x1) ? 0x01 : 0x00) <<
2955 (7 - usOutBitIndex % 8));
2959 * DMASK bit is 0, use device TDO.
2962 g_pucOutData[usOutBitIndex / 8] |= (unsigned char)
2963 (((cCurBit & 0x1) ? 0x01 : 0x00) <<
2964 (7 - usOutBitIndex % 8));
2968 * Shift in TDI in order to get TDO out.
2972 writePort(g_ucPinTDI, cDataByte);
2973 if (usDataSizeIndex < usLastBitIndex) {
2978 * Increment the byte index. If it exceeds 7, then reset it back
2983 if (cByteIndex >= 8) {
2989 * If g_pLVDSList exists and pairs need updating, then update
2990 * the negative-pair to receive the flipped positive-pair value.
2994 for (usLVDSIndex = 0; usLVDSIndex < g_usLVDSPairCount;
2996 if (g_pLVDSList[usLVDSIndex].ucUpdate) {
2999 * Read the positive value and flip it.
3002 cDataByte = (unsigned char)
3003 (((g_pucOutData[g_pLVDSList[usLVDSIndex].
3004 usPositiveIndex / 8]
3005 << (g_pLVDSList[usLVDSIndex].
3006 usPositiveIndex % 8)) & 0x80) ?
3008 /* 09/11/07 NN Type cast mismatch variables */
3009 cDataByte = (unsigned char) (!cDataByte);
3012 * Get the byte that needs modification.
3016 g_pucOutData[g_pLVDSList[usLVDSIndex].
3017 usNegativeIndex / 8];
3022 * Copy over the current byte and
3023 * set the negative bit to 1.
3027 for (cLVDSByteIndex = 7;
3028 cLVDSByteIndex >= 0;
3032 (g_pLVDSList[usLVDSIndex].
3033 usNegativeIndex % 8) ==
3037 * Set negative bit to 1
3041 } else if (cInDataByte & 0x80) {
3049 * Store the modified byte.
3052 g_pucOutData[g_pLVDSList[usLVDSIndex].
3053 usNegativeIndex / 8] = cDataByte;
3057 * Copy over the current byte and set
3058 * the negative bit to 0.
3062 for (cLVDSByteIndex = 7;
3063 cLVDSByteIndex >= 0;
3067 (g_pLVDSList[usLVDSIndex].
3068 usNegativeIndex % 8) ==
3072 * Set negative bit to 0
3076 } else if (cInDataByte & 0x80) {
3084 * Store the modified byte.
3087 g_pucOutData[g_pLVDSList[usLVDSIndex].
3088 usNegativeIndex / 8] = cDataByte;
3099 signed char ispVMProcessLVDS(unsigned short a_usLVDSCount)
3101 unsigned short usLVDSIndex = 0;
3104 * Allocate memory to hold LVDS pairs.
3107 ispVMMemManager(LVDS, a_usLVDSCount);
3108 g_usLVDSPairCount = a_usLVDSCount;
3111 printf("LVDS %d (", a_usLVDSCount);
3115 * Iterate through each given LVDS pair.
3118 for (usLVDSIndex = 0; usLVDSIndex < g_usLVDSPairCount; usLVDSIndex++) {
3121 * Assign the positive and negative indices of the LVDS pair.
3124 /* 09/11/07 NN Type cast mismatch variables */
3125 g_pLVDSList[usLVDSIndex].usPositiveIndex =
3126 (unsigned short) ispVMDataSize();
3127 /* 09/11/07 NN Type cast mismatch variables */
3128 g_pLVDSList[usLVDSIndex].usNegativeIndex =
3129 (unsigned short)ispVMDataSize();
3132 if (usLVDSIndex < g_usLVDSPairCount - 1) {
3134 g_pLVDSList[usLVDSIndex].usPositiveIndex,
3135 g_pLVDSList[usLVDSIndex].usNegativeIndex);
3138 g_pLVDSList[usLVDSIndex].usPositiveIndex,
3139 g_pLVDSList[usLVDSIndex].usNegativeIndex);