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