Logo Search packages:      
Sourcecode: u-boot-linaro version File versions  Download package

micro.c

/*
 * (C) Copyright 2003
 * Stefan Roese, esd gmbh germany, stefan.roese@esd-electronics.com
 *
 * See file CREDITS for list of people who contributed to this
 * project.
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License as
 * published by the Free Software Foundation; either version 2 of
 * the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 * MA 02111-1307 USA
 */

/*****************************************************************************
 * file:         micro.c
 * abstract:     This file contains the function, xsvfExecute(),
 *               call for interpreting the XSVF commands.
 * Usage:        Call xsvfExecute() to process XSVF data.
 *               The XSVF data is retrieved by readByte() in ports.c
 *               Remove the main function if you already have one.
 * Options:      XSVF_SUPPORT_COMPRESSION
 *                   This define supports the XC9500/XL compression scheme.
 *                   This define adds support for XSDRINC and XSETSDRMASKS.
 *               XSVF_SUPPORT_ERRORCODES
 *                   This define causes the xsvfExecute function to return
 *                   an error code for specific errors.  See error codes below.
 *                   If this is not defined, the return value defaults to the
 *                   legacy values for backward compatibility:
 *                   1 = success;  0 = failure.
 * Debugging:    DEBUG_MODE (Legacy name)
 *               Define DEBUG_MODE to compile with debugging features.
 *               Both micro.c and ports.c must be compiled with the DEBUG_MODE
 *               defined to enable the standalone main implementation in
 *               micro.c that reads XSVF from a file.
 * History:      v2.00   - Original XSVF implementation.
 *               v4.04   - Added delay at end of XSIR for XC18v00 support.
 *                         Added new commands for CoolRunner support:
 *                         XSTATE, XENDIR, XENDDR
 *               v4.05   - Cleanup micro.c but leave ports.c intact.
 *               v4.06   - Fix xsvfGotoTapState for retry transition.
 *               v4.07   - Update example waitTime implementations for
 *                         compatibility with Virtex-II.
 *               v4.10   - Add new XSIR2 command that supports a 2-byte
 *                         IR-length parameter for IR shifts > 255 bits.
 *               v4.11   - No change.  Update version to match SVF2XSVF xlator.
 *               v4.14   - Added XCOMMENT.
 *               v5.00   - Improve XSTATE support.
 *                         Added XWAIT.
 *****************************************************************************/

#include <common.h>
#include <command.h>
#include <asm/processor.h>

#include "micro.h"
#include "lenval.h"
#include "ports.h"

const unsigned char *xsvfdata;

/*============================================================================
 * XSVF #define
 ============================================================================*/

#define XSVF_VERSION    "5.00"

/*****************************************************************************
 * Define:       XSVF_SUPPORT_COMPRESSION
 * Description:  Define this to support the XC9500/XL XSVF data compression
 *               scheme.
 *               Code size can be reduced by NOT supporting this feature.
 *               However, you must use the -nc (no compress) option when
 *               translating SVF to XSVF using the SVF2XSVF translator.
 *               Corresponding, uncompressed XSVF may be larger.
 *****************************************************************************/
#ifndef XSVF_SUPPORT_COMPRESSION
#define XSVF_SUPPORT_COMPRESSION    1
#endif

/*****************************************************************************
 * Define:       XSVF_SUPPORT_ERRORCODES
 * Description:  Define this to support the new XSVF error codes.
 *               (The original XSVF player just returned 1 for success and
 *               0 for an unspecified failure.)
 *****************************************************************************/
#ifndef XSVF_SUPPORT_ERRORCODES
#define XSVF_SUPPORT_ERRORCODES     1
#endif

#ifdef  XSVF_SUPPORT_ERRORCODES
#define XSVF_ERRORCODE(errorCode)   errorCode
#else   /* Use legacy error code */
#define XSVF_ERRORCODE(errorCode)   ((errorCode==XSVF_ERROR_NONE)?1:0)
#endif  /* XSVF_SUPPORT_ERRORCODES */


/*============================================================================
 * DEBUG_MODE #define
 ============================================================================*/
#define DEBUG_MODE

#ifdef  DEBUG_MODE
#define XSVFDBG_PRINTF(iDebugLevel,pzFormat) \
            { if ( xsvf_iDebugLevel >= iDebugLevel ) \
                printf( pzFormat ); }
#define XSVFDBG_PRINTF1(iDebugLevel,pzFormat,arg1) \
            { if ( xsvf_iDebugLevel >= iDebugLevel ) \
                printf( pzFormat, arg1 ); }
#define XSVFDBG_PRINTF2(iDebugLevel,pzFormat,arg1,arg2) \
            { if ( xsvf_iDebugLevel >= iDebugLevel ) \
                printf( pzFormat, arg1, arg2 ); }
#define XSVFDBG_PRINTF3(iDebugLevel,pzFormat,arg1,arg2,arg3) \
            { if ( xsvf_iDebugLevel >= iDebugLevel ) \
                printf( pzFormat, arg1, arg2, arg3 ); }
#define XSVFDBG_PRINTLENVAL(iDebugLevel,plenVal) \
            { if ( xsvf_iDebugLevel >= iDebugLevel ) \
                xsvfPrintLenVal(plenVal); }
#else   /* !DEBUG_MODE */
#define XSVFDBG_PRINTF(iDebugLevel,pzFormat)
#define XSVFDBG_PRINTF1(iDebugLevel,pzFormat,arg1)
#define XSVFDBG_PRINTF2(iDebugLevel,pzFormat,arg1,arg2)
#define XSVFDBG_PRINTF3(iDebugLevel,pzFormat,arg1,arg2,arg3)
#define XSVFDBG_PRINTLENVAL(iDebugLevel,plenVal)
#endif  /* DEBUG_MODE */


/*============================================================================
 * XSVF Type Declarations
 ============================================================================*/

/*****************************************************************************
 * Struct:       SXsvfInfo
 * Description:  This structure contains all of the data used during the
 *               execution of the XSVF.  Some data is persistent, predefined
 *               information (e.g. lRunTestTime).  The bulk of this struct's
 *               size is due to the lenVal structs (defined in lenval.h)
 *               which contain buffers for the active shift data.  The MAX_LEN
 *               #define in lenval.h defines the size of these buffers.
 *               These buffers must be large enough to store the longest
 *               shift data in your XSVF file.  For example:
 *                   MAX_LEN >= ( longest_shift_data_in_bits / 8 )
 *               Because the lenVal struct dominates the space usage of this
 *               struct, the rough size of this struct is:
 *                   sizeof( SXsvfInfo ) ~= MAX_LEN * 7 (number of lenVals)
 *               xsvfInitialize() contains initialization code for the data
 *               in this struct.
 *               xsvfCleanup() contains cleanup code for the data in this
 *               struct.
 *****************************************************************************/
typedef struct tagSXsvfInfo
{
      /* XSVF status information */
      unsigned char   ucComplete;         /* 0 = running; 1 = complete */
      unsigned char   ucCommand;          /* Current XSVF command byte */
      long            lCommandCount;      /* Number of commands processed */
      int             iErrorCode;         /* An error code. 0 = no error. */

      /* TAP state/sequencing information */
      unsigned char   ucTapState;         /* Current TAP state */
      unsigned char   ucEndIR;            /* ENDIR TAP state (See SVF) */
      unsigned char   ucEndDR;            /* ENDDR TAP state (See SVF) */

      /* RUNTEST information */
      unsigned char   ucMaxRepeat;        /* Max repeat loops (for xc9500/xl) */
      long            lRunTestTime;       /* Pre-specified RUNTEST time (usec) */

      /* Shift Data Info and Buffers */
      long            lShiftLengthBits;   /* Len. current shift data in bits */
      short           sShiftLengthBytes;  /* Len. current shift data in bytes */

      lenVal          lvTdi;              /* Current TDI shift data */
      lenVal          lvTdoExpected;      /* Expected TDO shift data */
      lenVal          lvTdoCaptured;      /* Captured TDO shift data */
      lenVal          lvTdoMask;          /* TDO mask: 0=dontcare; 1=compare */

#ifdef  XSVF_SUPPORT_COMPRESSION
      /* XSDRINC Data Buffers */
      lenVal          lvAddressMask;      /* Address mask for XSDRINC */
      lenVal          lvDataMask;         /* Data mask for XSDRINC */
      lenVal          lvNextData;         /* Next data for XSDRINC */
#endif  /* XSVF_SUPPORT_COMPRESSION */
} SXsvfInfo;

/* Declare pointer to functions that perform XSVF commands */
typedef int (*TXsvfDoCmdFuncPtr)( SXsvfInfo* );

/*============================================================================
 * XSVF Command Bytes
 ============================================================================*/

/* encodings of xsvf instructions */
#define XCOMPLETE        0
#define XTDOMASK         1
#define XSIR             2
#define XSDR             3
#define XRUNTEST         4
/* Reserved              5 */
/* Reserved              6 */
#define XREPEAT          7
#define XSDRSIZE         8
#define XSDRTDO          9
#define XSETSDRMASKS     10
#define XSDRINC          11
#define XSDRB            12
#define XSDRC            13
#define XSDRE            14
#define XSDRTDOB         15
#define XSDRTDOC         16
#define XSDRTDOE         17
#define XSTATE           18         /* 4.00 */
#define XENDIR           19         /* 4.04 */
#define XENDDR           20         /* 4.04 */
#define XSIR2            21         /* 4.10 */
#define XCOMMENT         22         /* 4.14 */
#define XWAIT            23         /* 5.00 */
/* Insert new commands here */
/* and add corresponding xsvfDoCmd function to xsvf_pfDoCmd below. */
#define XLASTCMD         24         /* Last command marker */


/*============================================================================
 * XSVF Command Parameter Values
 ============================================================================*/

#define XSTATE_RESET     0          /* 4.00 parameter for XSTATE */
#define XSTATE_RUNTEST   1          /* 4.00 parameter for XSTATE */

#define XENDXR_RUNTEST   0          /* 4.04 parameter for XENDIR/DR */
#define XENDXR_PAUSE     1          /* 4.04 parameter for XENDIR/DR */

/* TAP states */
#define XTAPSTATE_RESET     0x00
#define XTAPSTATE_RUNTEST   0x01    /* a.k.a. IDLE */
#define XTAPSTATE_SELECTDR  0x02
#define XTAPSTATE_CAPTUREDR 0x03
#define XTAPSTATE_SHIFTDR   0x04
#define XTAPSTATE_EXIT1DR   0x05
#define XTAPSTATE_PAUSEDR   0x06
#define XTAPSTATE_EXIT2DR   0x07
#define XTAPSTATE_UPDATEDR  0x08
#define XTAPSTATE_IRSTATES  0x09    /* All IR states begin here */
#define XTAPSTATE_SELECTIR  0x09
#define XTAPSTATE_CAPTUREIR 0x0A
#define XTAPSTATE_SHIFTIR   0x0B
#define XTAPSTATE_EXIT1IR   0x0C
#define XTAPSTATE_PAUSEIR   0x0D
#define XTAPSTATE_EXIT2IR   0x0E
#define XTAPSTATE_UPDATEIR  0x0F

/*============================================================================
 * XSVF Function Prototypes
 ============================================================================*/

int xsvfDoIllegalCmd( SXsvfInfo* pXsvfInfo );   /* Illegal command function */
int xsvfDoXCOMPLETE( SXsvfInfo* pXsvfInfo );
int xsvfDoXTDOMASK( SXsvfInfo* pXsvfInfo );
int xsvfDoXSIR( SXsvfInfo* pXsvfInfo );
int xsvfDoXSIR2( SXsvfInfo* pXsvfInfo );
int xsvfDoXSDR( SXsvfInfo* pXsvfInfo );
int xsvfDoXRUNTEST( SXsvfInfo* pXsvfInfo );
int xsvfDoXREPEAT( SXsvfInfo* pXsvfInfo );
int xsvfDoXSDRSIZE( SXsvfInfo* pXsvfInfo );
int xsvfDoXSDRTDO( SXsvfInfo* pXsvfInfo );
int xsvfDoXSETSDRMASKS( SXsvfInfo* pXsvfInfo );
int xsvfDoXSDRINC( SXsvfInfo* pXsvfInfo );
int xsvfDoXSDRBCE( SXsvfInfo* pXsvfInfo );
int xsvfDoXSDRTDOBCE( SXsvfInfo* pXsvfInfo );
int xsvfDoXSTATE( SXsvfInfo* pXsvfInfo );
int xsvfDoXENDXR( SXsvfInfo* pXsvfInfo );
int xsvfDoXCOMMENT( SXsvfInfo* pXsvfInfo );
int xsvfDoXWAIT( SXsvfInfo* pXsvfInfo );
/* Insert new command functions here */

/*============================================================================
 * XSVF Global Variables
 ============================================================================*/

/* Array of XSVF command functions.  Must follow command byte value order! */
/* If your compiler cannot take this form, then convert to a switch statement*/
TXsvfDoCmdFuncPtr   xsvf_pfDoCmd[]  =
{
      xsvfDoXCOMPLETE,        /*  0 */
      xsvfDoXTDOMASK,         /*  1 */
      xsvfDoXSIR,             /*  2 */
      xsvfDoXSDR,             /*  3 */
      xsvfDoXRUNTEST,         /*  4 */
      xsvfDoIllegalCmd,       /*  5 */
      xsvfDoIllegalCmd,       /*  6 */
      xsvfDoXREPEAT,          /*  7 */
      xsvfDoXSDRSIZE,         /*  8 */
      xsvfDoXSDRTDO,          /*  9 */
#ifdef  XSVF_SUPPORT_COMPRESSION
      xsvfDoXSETSDRMASKS,     /* 10 */
      xsvfDoXSDRINC,          /* 11 */
#else
      xsvfDoIllegalCmd,       /* 10 */
      xsvfDoIllegalCmd,       /* 11 */
#endif  /* XSVF_SUPPORT_COMPRESSION */
      xsvfDoXSDRBCE,          /* 12 */
      xsvfDoXSDRBCE,          /* 13 */
      xsvfDoXSDRBCE,          /* 14 */
      xsvfDoXSDRTDOBCE,       /* 15 */
      xsvfDoXSDRTDOBCE,       /* 16 */
      xsvfDoXSDRTDOBCE,       /* 17 */
      xsvfDoXSTATE,           /* 18 */
      xsvfDoXENDXR,           /* 19 */
      xsvfDoXENDXR,           /* 20 */
      xsvfDoXSIR2,            /* 21 */
      xsvfDoXCOMMENT,         /* 22 */
      xsvfDoXWAIT             /* 23 */
/* Insert new command functions here */
};

#ifdef  DEBUG_MODE
char* xsvf_pzCommandName[]  =
{
      "XCOMPLETE",
      "XTDOMASK",
      "XSIR",
      "XSDR",
      "XRUNTEST",
      "Reserved5",
      "Reserved6",
      "XREPEAT",
      "XSDRSIZE",
      "XSDRTDO",
      "XSETSDRMASKS",
      "XSDRINC",
      "XSDRB",
      "XSDRC",
      "XSDRE",
      "XSDRTDOB",
      "XSDRTDOC",
      "XSDRTDOE",
      "XSTATE",
      "XENDIR",
      "XENDDR",
      "XSIR2",
      "XCOMMENT",
      "XWAIT"
};

char*   xsvf_pzErrorName[]  =
{
      "No error",
      "ERROR:  Unknown",
      "ERROR:  TDO mismatch",
      "ERROR:  TDO mismatch and exceeded max retries",
      "ERROR:  Unsupported XSVF command",
      "ERROR:  Illegal state specification",
      "ERROR:  Data overflows allocated MAX_LEN buffer size"
};

char*   xsvf_pzTapState[] =
{
      "RESET",        /* 0x00 */
      "RUNTEST/IDLE", /* 0x01 */
      "DRSELECT",     /* 0x02 */
      "DRCAPTURE",    /* 0x03 */
      "DRSHIFT",      /* 0x04 */
      "DREXIT1",      /* 0x05 */
      "DRPAUSE",      /* 0x06 */
      "DREXIT2",      /* 0x07 */
      "DRUPDATE",     /* 0x08 */
      "IRSELECT",     /* 0x09 */
      "IRCAPTURE",    /* 0x0A */
      "IRSHIFT",      /* 0x0B */
      "IREXIT1",      /* 0x0C */
      "IRPAUSE",      /* 0x0D */
      "IREXIT2",      /* 0x0E */
      "IRUPDATE"      /* 0x0F */
};
#endif  /* DEBUG_MODE */

/*#ifdef DEBUG_MODE     */
/*    FILE* in;   /XXX* Legacy DEBUG_MODE file pointer */
int xsvf_iDebugLevel;
/*#endif /XXX* DEBUG_MODE */

/*============================================================================
 * Utility Functions
 ============================================================================*/

/*****************************************************************************
 * Function:     xsvfPrintLenVal
 * Description:  Print the lenval value in hex.
 * Parameters:   plv     - ptr to lenval.
 * Returns:      void.
 *****************************************************************************/
#ifdef  DEBUG_MODE
void xsvfPrintLenVal( lenVal *plv )
{
      int i;

      if ( plv )
      {
            printf( "0x" );
            for ( i = 0; i < plv->len; ++i )
            {
                  printf( "%02x", ((unsigned int)(plv->val[ i ])) );
            }
      }
}
#endif  /* DEBUG_MODE */


/*****************************************************************************
 * Function:     xsvfInfoInit
 * Description:  Initialize the xsvfInfo data.
 * Parameters:   pXsvfInfo   - ptr to the XSVF info structure.
 * Returns:      int         - 0 = success; otherwise error.
 *****************************************************************************/
int xsvfInfoInit( SXsvfInfo* pXsvfInfo )
{
      XSVFDBG_PRINTF1( 4, "    sizeof( SXsvfInfo ) = %d bytes\n",
                   sizeof( SXsvfInfo ) );

      pXsvfInfo->ucComplete       = 0;
      pXsvfInfo->ucCommand        = XCOMPLETE;
      pXsvfInfo->lCommandCount    = 0;
      pXsvfInfo->iErrorCode       = XSVF_ERROR_NONE;
      pXsvfInfo->ucMaxRepeat      = 0;
      pXsvfInfo->ucTapState       = XTAPSTATE_RESET;
      pXsvfInfo->ucEndIR          = XTAPSTATE_RUNTEST;
      pXsvfInfo->ucEndDR          = XTAPSTATE_RUNTEST;
      pXsvfInfo->lShiftLengthBits = 0L;
      pXsvfInfo->sShiftLengthBytes= 0;
      pXsvfInfo->lRunTestTime     = 0L;

      return( 0 );
}

/*****************************************************************************
 * Function:     xsvfInfoCleanup
 * Description:  Cleanup the xsvfInfo data.
 * Parameters:   pXsvfInfo   - ptr to the XSVF info structure.
 * Returns:      void.
 *****************************************************************************/
void xsvfInfoCleanup( SXsvfInfo* pXsvfInfo )
{
}

/*****************************************************************************
 * Function:     xsvfGetAsNumBytes
 * Description:  Calculate the number of bytes the given number of bits
 *               consumes.
 * Parameters:   lNumBits    - the number of bits.
 * Returns:      short       - the number of bytes to store the number of bits.
 *****************************************************************************/
short xsvfGetAsNumBytes( long lNumBits )
{
      return( (short)( ( lNumBits + 7L ) / 8L ) );
}

/*****************************************************************************
 * Function:     xsvfTmsTransition
 * Description:  Apply TMS and transition TAP controller by applying one TCK
 *               cycle.
 * Parameters:   sTms    - new TMS value.
 * Returns:      void.
 *****************************************************************************/
void xsvfTmsTransition( short sTms )
{
      setPort( TMS, sTms );
      setPort( TCK, 0 );
      setPort( TCK, 1 );
}

/*****************************************************************************
 * Function:     xsvfGotoTapState
 * Description:  From the current TAP state, go to the named TAP state.
 *               A target state of RESET ALWAYS causes TMS reset sequence.
 *               All SVF standard stable state paths are supported.
 *               All state transitions are supported except for the following
 *               which cause an XSVF_ERROR_ILLEGALSTATE:
 *                   - Target==DREXIT2;  Start!=DRPAUSE
 *                   - Target==IREXIT2;  Start!=IRPAUSE
 * Parameters:   pucTapState     - Current TAP state; returns final TAP state.
 *               ucTargetState   - New target TAP state.
 * Returns:      int             - 0 = success; otherwise error.
 *****************************************************************************/
int xsvfGotoTapState( unsigned char*   pucTapState,
                  unsigned char    ucTargetState )
{
      int i;
      int iErrorCode;

      iErrorCode  = XSVF_ERROR_NONE;
      if ( ucTargetState == XTAPSTATE_RESET )
      {
            /* If RESET, always perform TMS reset sequence to reset/sync TAPs */
            xsvfTmsTransition( 1 );
            for ( i = 0; i < 5; ++i )
            {
                  setPort( TCK, 0 );
                  setPort( TCK, 1 );
            }
            *pucTapState    = XTAPSTATE_RESET;
            XSVFDBG_PRINTF( 3, "   TMS Reset Sequence -> Test-Logic-Reset\n" );
            XSVFDBG_PRINTF1( 3, "   TAP State = %s\n",
                         xsvf_pzTapState[ *pucTapState ] );
      } else if ( ( ucTargetState != *pucTapState ) &&
              ( ( ( ucTargetState == XTAPSTATE_EXIT2DR ) && ( *pucTapState != XTAPSTATE_PAUSEDR ) ) ||
                ( ( ucTargetState == XTAPSTATE_EXIT2IR ) && ( *pucTapState != XTAPSTATE_PAUSEIR ) ) ) )
      {
            /* Trap illegal TAP state path specification */
            iErrorCode      = XSVF_ERROR_ILLEGALSTATE;
      } else {
            if ( ucTargetState == *pucTapState )
            {
                  /* Already in target state.  Do nothing except when in DRPAUSE
                     or in IRPAUSE to comply with SVF standard */
                  if ( ucTargetState == XTAPSTATE_PAUSEDR )
                  {
                        xsvfTmsTransition( 1 );
                        *pucTapState    = XTAPSTATE_EXIT2DR;
                        XSVFDBG_PRINTF1( 3, "   TAP State = %s\n",
                                     xsvf_pzTapState[ *pucTapState ] );
                  }
                  else if ( ucTargetState == XTAPSTATE_PAUSEIR )
                  {
                        xsvfTmsTransition( 1 );
                        *pucTapState    = XTAPSTATE_EXIT2IR;
                        XSVFDBG_PRINTF1( 3, "   TAP State = %s\n",
                                     xsvf_pzTapState[ *pucTapState ] );
                  }
            }

            /* Perform TAP state transitions to get to the target state */
            while ( ucTargetState != *pucTapState )
            {
                  switch ( *pucTapState )
                  {
                  case XTAPSTATE_RESET:
                        xsvfTmsTransition( 0 );
                        *pucTapState    = XTAPSTATE_RUNTEST;
                        break;
                  case XTAPSTATE_RUNTEST:
                        xsvfTmsTransition( 1 );
                        *pucTapState    = XTAPSTATE_SELECTDR;
                        break;
                  case XTAPSTATE_SELECTDR:
                        if ( ucTargetState >= XTAPSTATE_IRSTATES )
                        {
                              xsvfTmsTransition( 1 );
                              *pucTapState    = XTAPSTATE_SELECTIR;
                        }
                        else
                        {
                              xsvfTmsTransition( 0 );
                              *pucTapState    = XTAPSTATE_CAPTUREDR;
                        }
                        break;
                  case XTAPSTATE_CAPTUREDR:
                        if ( ucTargetState == XTAPSTATE_SHIFTDR )
                        {
                              xsvfTmsTransition( 0 );
                              *pucTapState    = XTAPSTATE_SHIFTDR;
                        }
                        else
                        {
                              xsvfTmsTransition( 1 );
                              *pucTapState    = XTAPSTATE_EXIT1DR;
                        }
                        break;
                  case XTAPSTATE_SHIFTDR:
                        xsvfTmsTransition( 1 );
                        *pucTapState    = XTAPSTATE_EXIT1DR;
                        break;
                  case XTAPSTATE_EXIT1DR:
                        if ( ucTargetState == XTAPSTATE_PAUSEDR )
                        {
                              xsvfTmsTransition( 0 );
                              *pucTapState    = XTAPSTATE_PAUSEDR;
                        }
                        else
                        {
                              xsvfTmsTransition( 1 );
                              *pucTapState    = XTAPSTATE_UPDATEDR;
                        }
                        break;
                  case XTAPSTATE_PAUSEDR:
                        xsvfTmsTransition( 1 );
                        *pucTapState    = XTAPSTATE_EXIT2DR;
                        break;
                  case XTAPSTATE_EXIT2DR:
                        if ( ucTargetState == XTAPSTATE_SHIFTDR )
                        {
                              xsvfTmsTransition( 0 );
                              *pucTapState    = XTAPSTATE_SHIFTDR;
                        }
                        else
                        {
                              xsvfTmsTransition( 1 );
                              *pucTapState    = XTAPSTATE_UPDATEDR;
                        }
                        break;
                  case XTAPSTATE_UPDATEDR:
                        if ( ucTargetState == XTAPSTATE_RUNTEST )
                        {
                              xsvfTmsTransition( 0 );
                              *pucTapState    = XTAPSTATE_RUNTEST;
                        }
                        else
                        {
                              xsvfTmsTransition( 1 );
                              *pucTapState    = XTAPSTATE_SELECTDR;
                        }
                        break;
                  case XTAPSTATE_SELECTIR:
                        xsvfTmsTransition( 0 );
                        *pucTapState    = XTAPSTATE_CAPTUREIR;
                        break;
                  case XTAPSTATE_CAPTUREIR:
                        if ( ucTargetState == XTAPSTATE_SHIFTIR )
                        {
                              xsvfTmsTransition( 0 );
                              *pucTapState    = XTAPSTATE_SHIFTIR;
                        }
                        else
                        {
                              xsvfTmsTransition( 1 );
                              *pucTapState    = XTAPSTATE_EXIT1IR;
                        }
                        break;
                  case XTAPSTATE_SHIFTIR:
                        xsvfTmsTransition( 1 );
                        *pucTapState    = XTAPSTATE_EXIT1IR;
                        break;
                  case XTAPSTATE_EXIT1IR:
                        if ( ucTargetState == XTAPSTATE_PAUSEIR )
                        {
                              xsvfTmsTransition( 0 );
                              *pucTapState    = XTAPSTATE_PAUSEIR;
                        }
                        else
                        {
                              xsvfTmsTransition( 1 );
                              *pucTapState    = XTAPSTATE_UPDATEIR;
                        }
                        break;
                  case XTAPSTATE_PAUSEIR:
                        xsvfTmsTransition( 1 );
                        *pucTapState    = XTAPSTATE_EXIT2IR;
                        break;
                  case XTAPSTATE_EXIT2IR:
                        if ( ucTargetState == XTAPSTATE_SHIFTIR )
                        {
                              xsvfTmsTransition( 0 );
                              *pucTapState    = XTAPSTATE_SHIFTIR;
                        }
                        else
                        {
                              xsvfTmsTransition( 1 );
                              *pucTapState    = XTAPSTATE_UPDATEIR;
                        }
                        break;
                  case XTAPSTATE_UPDATEIR:
                        if ( ucTargetState == XTAPSTATE_RUNTEST )
                        {
                              xsvfTmsTransition( 0 );
                              *pucTapState    = XTAPSTATE_RUNTEST;
                        }
                        else
                        {
                              xsvfTmsTransition( 1 );
                              *pucTapState    = XTAPSTATE_SELECTDR;
                        }
                        break;
                  default:
                        iErrorCode      = XSVF_ERROR_ILLEGALSTATE;
                        *pucTapState    = ucTargetState;    /* Exit while loop */
                        break;
                  }
                  XSVFDBG_PRINTF1( 3, "   TAP State = %s\n",
                               xsvf_pzTapState[ *pucTapState ] );
            }
      }

      return( iErrorCode );
}

/*****************************************************************************
 * Function:     xsvfShiftOnly
 * Description:  Assumes that starting TAP state is SHIFT-DR or SHIFT-IR.
 *               Shift the given TDI data into the JTAG scan chain.
 *               Optionally, save the TDO data shifted out of the scan chain.
 *               Last shift cycle is special:  capture last TDO, set last TDI,
 *               but does not pulse TCK.  Caller must pulse TCK and optionally
 *               set TMS=1 to exit shift state.
 * Parameters:   lNumBits        - number of bits to shift.
 *               plvTdi          - ptr to lenval for TDI data.
 *               plvTdoCaptured  - ptr to lenval for storing captured TDO data.
 *               iExitShift      - 1=exit at end of shift; 0=stay in Shift-DR.
 * Returns:      void.
 *****************************************************************************/
void xsvfShiftOnly( long    lNumBits,
                lenVal* plvTdi,
                lenVal* plvTdoCaptured,
                int     iExitShift )
{
      unsigned char*  pucTdi;
      unsigned char*  pucTdo;
      unsigned char   ucTdiByte;
      unsigned char   ucTdoByte;
      unsigned char   ucTdoBit;
      int             i;

      /* assert( ( ( lNumBits + 7 ) / 8 ) == plvTdi->len ); */

      /* Initialize TDO storage len == TDI len */
      pucTdo  = 0;
      if ( plvTdoCaptured )
      {
            plvTdoCaptured->len = plvTdi->len;
            pucTdo              = plvTdoCaptured->val + plvTdi->len;
      }

      /* Shift LSB first.  val[N-1] == LSB.  val[0] == MSB. */
      pucTdi  = plvTdi->val + plvTdi->len;
      while ( lNumBits )
      {
            /* Process on a byte-basis */
            ucTdiByte   = (*(--pucTdi));
            ucTdoByte   = 0;
            for ( i = 0; ( lNumBits && ( i < 8 ) ); ++i )
            {
                  --lNumBits;
                  if ( iExitShift && !lNumBits )
                  {
                        /* Exit Shift-DR state */
                        setPort( TMS, 1 );
                  }

                  /* Set the new TDI value */
                  setPort( TDI, (short)(ucTdiByte & 1) );
                  ucTdiByte   >>= 1;

                  /* Set TCK low */
                  setPort( TCK, 0 );

                  if ( pucTdo )
                  {
                        /* Save the TDO value */
                        ucTdoBit    = readTDOBit();
                        ucTdoByte   |= ( ucTdoBit << i );
                  }

                  /* Set TCK high */
                  setPort( TCK, 1 );
            }

            /* Save the TDO byte value */
            if ( pucTdo )
            {
                  (*(--pucTdo))   = ucTdoByte;
            }
      }
}

/*****************************************************************************
 * Function:     xsvfShift
 * Description:  Goes to the given starting TAP state.
 *               Calls xsvfShiftOnly to shift in the given TDI data and
 *               optionally capture the TDO data.
 *               Compares the TDO captured data against the TDO expected
 *               data.
 *               If a data mismatch occurs, then executes the exception
 *               handling loop upto ucMaxRepeat times.
 * Parameters:   pucTapState     - Ptr to current TAP state.
 *               ucStartState    - Starting shift state: Shift-DR or Shift-IR.
 *               lNumBits        - number of bits to shift.
 *               plvTdi          - ptr to lenval for TDI data.
 *               plvTdoCaptured  - ptr to lenval for storing TDO data.
 *               plvTdoExpected  - ptr to expected TDO data.
 *               plvTdoMask      - ptr to TDO mask.
 *               ucEndState      - state in which to end the shift.
 *               lRunTestTime    - amount of time to wait after the shift.
 *               ucMaxRepeat     - Maximum number of retries on TDO mismatch.
 * Returns:      int             - 0 = success; otherwise TDO mismatch.
 * Notes:        XC9500XL-only Optimization:
 *               Skip the waitTime() if plvTdoMask->val[0:plvTdoMask->len-1]
 *               is NOT all zeros and sMatch==1.
 *****************************************************************************/
int xsvfShift( unsigned char*   pucTapState,
             unsigned char    ucStartState,
             long             lNumBits,
             lenVal*          plvTdi,
             lenVal*          plvTdoCaptured,
             lenVal*          plvTdoExpected,
             lenVal*          plvTdoMask,
             unsigned char    ucEndState,
             long             lRunTestTime,
             unsigned char    ucMaxRepeat )
{
      int             iErrorCode;
      int             iMismatch;
      unsigned char   ucRepeat;
      int             iExitShift;

      iErrorCode  = XSVF_ERROR_NONE;
      iMismatch   = 0;
      ucRepeat    = 0;
      iExitShift  = ( ucStartState != ucEndState );

      XSVFDBG_PRINTF1( 3, "   Shift Length = %ld\n", lNumBits );
      XSVFDBG_PRINTF( 4, "    TDI          = ");
      XSVFDBG_PRINTLENVAL( 4, plvTdi );
      XSVFDBG_PRINTF( 4, "\n");
      XSVFDBG_PRINTF( 4, "    TDO Expected = ");
      XSVFDBG_PRINTLENVAL( 4, plvTdoExpected );
      XSVFDBG_PRINTF( 4, "\n");

      if ( !lNumBits )
      {
            /* Compatibility with XSVF2.00:  XSDR 0 = no shift, but wait in RTI */
            if ( lRunTestTime )
            {
                  /* Wait for prespecified XRUNTEST time */
                  xsvfGotoTapState( pucTapState, XTAPSTATE_RUNTEST );
                  XSVFDBG_PRINTF1( 3, "   Wait = %ld usec\n", lRunTestTime );
                  waitTime( lRunTestTime );
            }
      }
      else
      {
            do
            {
                  /* Goto Shift-DR or Shift-IR */
                  xsvfGotoTapState( pucTapState, ucStartState );

                  /* Shift TDI and capture TDO */
                  xsvfShiftOnly( lNumBits, plvTdi, plvTdoCaptured, iExitShift );

                  if ( plvTdoExpected )
                  {
                        /* Compare TDO data to expected TDO data */
                        iMismatch   = !EqualLenVal( plvTdoExpected,
                                              plvTdoCaptured,
                                              plvTdoMask );
                  }

                  if ( iExitShift )
                  {
                        /* Update TAP state:  Shift->Exit */
                        ++(*pucTapState);
                        XSVFDBG_PRINTF1( 3, "   TAP State = %s\n",
                                     xsvf_pzTapState[ *pucTapState ] );

                        if ( iMismatch && lRunTestTime && ( ucRepeat < ucMaxRepeat ) )
                        {
                              XSVFDBG_PRINTF( 4, "    TDO Expected = ");
                              XSVFDBG_PRINTLENVAL( 4, plvTdoExpected );
                              XSVFDBG_PRINTF( 4, "\n");
                              XSVFDBG_PRINTF( 4, "    TDO Captured = ");
                              XSVFDBG_PRINTLENVAL( 4, plvTdoCaptured );
                              XSVFDBG_PRINTF( 4, "\n");
                              XSVFDBG_PRINTF( 4, "    TDO Mask     = ");
                              XSVFDBG_PRINTLENVAL( 4, plvTdoMask );
                              XSVFDBG_PRINTF( 4, "\n");
                              XSVFDBG_PRINTF1( 3, "   Retry #%d\n", ( ucRepeat + 1 ) );
                              /* Do exception handling retry - ShiftDR only */
                              xsvfGotoTapState( pucTapState, XTAPSTATE_PAUSEDR );
                              /* Shift 1 extra bit */
                              xsvfGotoTapState( pucTapState, XTAPSTATE_SHIFTDR );
                              /* Increment RUNTEST time by an additional 25% */
                              lRunTestTime    += ( lRunTestTime >> 2 );
                        }
                        else
                        {
                              /* Do normal exit from Shift-XR */
                              xsvfGotoTapState( pucTapState, ucEndState );
                        }

                        if ( lRunTestTime )
                        {
                              /* Wait for prespecified XRUNTEST time */
                              xsvfGotoTapState( pucTapState, XTAPSTATE_RUNTEST );
                              XSVFDBG_PRINTF1( 3, "   Wait = %ld usec\n", lRunTestTime );
                              waitTime( lRunTestTime );
                        }
                  }
            } while ( iMismatch && ( ucRepeat++ < ucMaxRepeat ) );
      }

      if ( iMismatch )
      {
            XSVFDBG_PRINTF( 1, " TDO Expected = ");
            XSVFDBG_PRINTLENVAL( 1, plvTdoExpected );
            XSVFDBG_PRINTF( 1, "\n");
            XSVFDBG_PRINTF( 1, " TDO Captured = ");
            XSVFDBG_PRINTLENVAL( 1, plvTdoCaptured );
            XSVFDBG_PRINTF( 1, "\n");
            XSVFDBG_PRINTF( 1, " TDO Mask     = ");
            XSVFDBG_PRINTLENVAL( 1, plvTdoMask );
            XSVFDBG_PRINTF( 1, "\n");
            if ( ucMaxRepeat && ( ucRepeat > ucMaxRepeat ) )
            {
                  iErrorCode  = XSVF_ERROR_MAXRETRIES;
            }
            else
            {
                  iErrorCode  = XSVF_ERROR_TDOMISMATCH;
            }
      }

      return( iErrorCode );
}

/*****************************************************************************
 * Function:     xsvfBasicXSDRTDO
 * Description:  Get the XSDRTDO parameters and execute the XSDRTDO command.
 *               This is the common function for all XSDRTDO commands.
 * Parameters:   pucTapState         - Current TAP state.
 *               lShiftLengthBits    - number of bits to shift.
 *               sShiftLengthBytes   - number of bytes to read.
 *               plvTdi              - ptr to lenval for TDI data.
 *               lvTdoCaptured       - ptr to lenval for storing TDO data.
 *               iEndState           - state in which to end the shift.
 *               lRunTestTime        - amount of time to wait after the shift.
 *               ucMaxRepeat         - maximum xc9500/xl retries.
 * Returns:      int                 - 0 = success; otherwise TDO mismatch.
 *****************************************************************************/
int xsvfBasicXSDRTDO( unsigned char*    pucTapState,
                  long              lShiftLengthBits,
                  short             sShiftLengthBytes,
                  lenVal*           plvTdi,
                  lenVal*           plvTdoCaptured,
                  lenVal*           plvTdoExpected,
                  lenVal*           plvTdoMask,
                  unsigned char     ucEndState,
                  long              lRunTestTime,
                  unsigned char     ucMaxRepeat )
{
      readVal( plvTdi, sShiftLengthBytes );
      if ( plvTdoExpected )
      {
            readVal( plvTdoExpected, sShiftLengthBytes );
      }
      return( xsvfShift( pucTapState, XTAPSTATE_SHIFTDR, lShiftLengthBits,
                     plvTdi, plvTdoCaptured, plvTdoExpected, plvTdoMask,
                     ucEndState, lRunTestTime, ucMaxRepeat ) );
}

/*****************************************************************************
 * Function:     xsvfDoSDRMasking
 * Description:  Update the data value with the next XSDRINC data and address.
 * Example:      dataVal=0x01ff, nextData=0xab, addressMask=0x0100,
 *               dataMask=0x00ff, should set dataVal to 0x02ab
 * Parameters:   plvTdi          - The current TDI value.
 *               plvNextData     - the next data value.
 *               plvAddressMask  - the address mask.
 *               plvDataMask     - the data mask.
 * Returns:      void.
 *****************************************************************************/
#ifdef  XSVF_SUPPORT_COMPRESSION
void xsvfDoSDRMasking( lenVal*  plvTdi,
                   lenVal*  plvNextData,
                   lenVal*  plvAddressMask,
                   lenVal*  plvDataMask )
{
      int             i;
      unsigned char   ucTdi;
      unsigned char   ucTdiMask;
      unsigned char   ucDataMask;
      unsigned char   ucNextData;
      unsigned char   ucNextMask;
      short           sNextData;

      /* add the address Mask to dataVal and return as a new dataVal */
      addVal( plvTdi, plvTdi, plvAddressMask );

      ucNextData  = 0;
      ucNextMask  = 0;
      sNextData   = plvNextData->len;
      for ( i = plvDataMask->len - 1; i >= 0; --i )
      {
            /* Go through data mask in reverse order looking for mask (1) bits */
            ucDataMask  = plvDataMask->val[ i ];
            if ( ucDataMask )
            {
                  /* Retrieve the corresponding TDI byte value */
                  ucTdi       = plvTdi->val[ i ];

                  /* For each bit in the data mask byte, look for 1's */
                  ucTdiMask   = 1;
                  while ( ucDataMask )
                  {
                        if ( ucDataMask & 1 )
                        {
                              if ( !ucNextMask )
                              {
                                    /* Get the next data byte */
                                    ucNextData  = plvNextData->val[ --sNextData ];
                                    ucNextMask  = 1;
                              }

                              /* Set or clear the data bit according to the next data */
                              if ( ucNextData & ucNextMask )
                              {
                                    ucTdi   |= ucTdiMask;       /* Set bit */
                              }
                              else
                              {
                                    ucTdi   &= ( ~ucTdiMask );  /* Clear bit */
                              }

                              /* Update the next data */
                              ucNextMask  <<= 1;
                        }
                        ucTdiMask   <<= 1;
                        ucDataMask  >>= 1;
                  }

                  /* Update the TDI value */
                  plvTdi->val[ i ]    = ucTdi;
            }
      }
}
#endif  /* XSVF_SUPPORT_COMPRESSION */

/*============================================================================
 * XSVF Command Functions (type = TXsvfDoCmdFuncPtr)
 * These functions update pXsvfInfo->iErrorCode only on an error.
 * Otherwise, the error code is left alone.
 * The function returns the error code from the function.
 ============================================================================*/

/*****************************************************************************
 * Function:     xsvfDoIllegalCmd
 * Description:  Function place holder for illegal/unsupported commands.
 * Parameters:   pXsvfInfo   - XSVF information pointer.
 * Returns:      int         - 0 = success;  non-zero = error.
 *****************************************************************************/
int xsvfDoIllegalCmd( SXsvfInfo* pXsvfInfo )
{
      XSVFDBG_PRINTF2( 0, "ERROR:  Encountered unsupported command #%d (%s)\n",
                   ((unsigned int)(pXsvfInfo->ucCommand)),
                   ((pXsvfInfo->ucCommand < XLASTCMD)
                    ? (xsvf_pzCommandName[pXsvfInfo->ucCommand])
                    : "Unknown") );
      pXsvfInfo->iErrorCode   = XSVF_ERROR_ILLEGALCMD;
      return( pXsvfInfo->iErrorCode );
}

/*****************************************************************************
 * Function:     xsvfDoXCOMPLETE
 * Description:  XCOMPLETE (no parameters)
 *               Update complete status for XSVF player.
 * Parameters:   pXsvfInfo   - XSVF information pointer.
 * Returns:      int         - 0 = success;  non-zero = error.
 *****************************************************************************/
int xsvfDoXCOMPLETE( SXsvfInfo* pXsvfInfo )
{
      pXsvfInfo->ucComplete   = 1;
      return( XSVF_ERROR_NONE );
}

/*****************************************************************************
 * Function:     xsvfDoXTDOMASK
 * Description:  XTDOMASK <lenVal.TdoMask[XSDRSIZE]>
 *               Prespecify the TDO compare mask.
 * Parameters:   pXsvfInfo   - XSVF information pointer.
 * Returns:      int         - 0 = success;  non-zero = error.
 *****************************************************************************/
int xsvfDoXTDOMASK( SXsvfInfo* pXsvfInfo )
{
      readVal( &(pXsvfInfo->lvTdoMask), pXsvfInfo->sShiftLengthBytes );
      XSVFDBG_PRINTF( 4, "    TDO Mask     = ");
      XSVFDBG_PRINTLENVAL( 4, &(pXsvfInfo->lvTdoMask) );
      XSVFDBG_PRINTF( 4, "\n");
      return( XSVF_ERROR_NONE );
}

/*****************************************************************************
 * Function:     xsvfDoXSIR
 * Description:  XSIR <(byte)shiftlen> <lenVal.TDI[shiftlen]>
 *               Get the instruction and shift the instruction into the TAP.
 *               If prespecified XRUNTEST!=0, goto RUNTEST and wait after
 *               the shift for XRUNTEST usec.
 * Parameters:   pXsvfInfo   - XSVF information pointer.
 * Returns:      int         - 0 = success;  non-zero = error.
 *****************************************************************************/
int xsvfDoXSIR( SXsvfInfo* pXsvfInfo )
{
      unsigned char   ucShiftIrBits;
      short           sShiftIrBytes;
      int             iErrorCode;

      /* Get the shift length and store */
      readByte( &ucShiftIrBits );
      sShiftIrBytes   = xsvfGetAsNumBytes( ucShiftIrBits );
      XSVFDBG_PRINTF1( 3, "   XSIR length = %d\n",
                   ((unsigned int)ucShiftIrBits) );

      if ( sShiftIrBytes > MAX_LEN )
      {
            iErrorCode  = XSVF_ERROR_DATAOVERFLOW;
      }
      else
      {
            /* Get and store instruction to shift in */
            readVal( &(pXsvfInfo->lvTdi), xsvfGetAsNumBytes( ucShiftIrBits ) );

            /* Shift the data */
            iErrorCode  = xsvfShift( &(pXsvfInfo->ucTapState), XTAPSTATE_SHIFTIR,
                               ucShiftIrBits, &(pXsvfInfo->lvTdi),
                               /*plvTdoCaptured*/0, /*plvTdoExpected*/0,
                               /*plvTdoMask*/0, pXsvfInfo->ucEndIR,
                               pXsvfInfo->lRunTestTime, /*ucMaxRepeat*/0 );
      }

      if ( iErrorCode != XSVF_ERROR_NONE )
      {
            pXsvfInfo->iErrorCode   = iErrorCode;
      }
      return( iErrorCode );
}

/*****************************************************************************
 * Function:     xsvfDoXSIR2
 * Description:  XSIR <(2-byte)shiftlen> <lenVal.TDI[shiftlen]>
 *               Get the instruction and shift the instruction into the TAP.
 *               If prespecified XRUNTEST!=0, goto RUNTEST and wait after
 *               the shift for XRUNTEST usec.
 * Parameters:   pXsvfInfo   - XSVF information pointer.
 * Returns:      int         - 0 = success;  non-zero = error.
 *****************************************************************************/
int xsvfDoXSIR2( SXsvfInfo* pXsvfInfo )
{
      long            lShiftIrBits;
      short           sShiftIrBytes;
      int             iErrorCode;

      /* Get the shift length and store */
      readVal( &(pXsvfInfo->lvTdi), 2 );
      lShiftIrBits    = value( &(pXsvfInfo->lvTdi) );
      sShiftIrBytes   = xsvfGetAsNumBytes( lShiftIrBits );
      XSVFDBG_PRINTF1( 3, "   XSIR2 length = %d\n", (int)lShiftIrBits);

      if ( sShiftIrBytes > MAX_LEN )
      {
            iErrorCode  = XSVF_ERROR_DATAOVERFLOW;
      }
      else
      {
            /* Get and store instruction to shift in */
            readVal( &(pXsvfInfo->lvTdi), xsvfGetAsNumBytes( lShiftIrBits ) );

            /* Shift the data */
            iErrorCode  = xsvfShift( &(pXsvfInfo->ucTapState), XTAPSTATE_SHIFTIR,
                               lShiftIrBits, &(pXsvfInfo->lvTdi),
                               /*plvTdoCaptured*/0, /*plvTdoExpected*/0,
                               /*plvTdoMask*/0, pXsvfInfo->ucEndIR,
                               pXsvfInfo->lRunTestTime, /*ucMaxRepeat*/0 );
      }

      if ( iErrorCode != XSVF_ERROR_NONE )
      {
            pXsvfInfo->iErrorCode   = iErrorCode;
      }
      return( iErrorCode );
}

/*****************************************************************************
 * Function:     xsvfDoXSDR
 * Description:  XSDR <lenVal.TDI[XSDRSIZE]>
 *               Shift the given TDI data into the JTAG scan chain.
 *               Compare the captured TDO with the expected TDO from the
 *               previous XSDRTDO command using the previously specified
 *               XTDOMASK.
 * Parameters:   pXsvfInfo   - XSVF information pointer.
 * Returns:      int         - 0 = success;  non-zero = error.
 *****************************************************************************/
int xsvfDoXSDR( SXsvfInfo* pXsvfInfo )
{
      int iErrorCode;
      readVal( &(pXsvfInfo->lvTdi), pXsvfInfo->sShiftLengthBytes );
      /* use TDOExpected from last XSDRTDO instruction */
      iErrorCode  = xsvfShift( &(pXsvfInfo->ucTapState), XTAPSTATE_SHIFTDR,
                         pXsvfInfo->lShiftLengthBits, &(pXsvfInfo->lvTdi),
                         &(pXsvfInfo->lvTdoCaptured),
                         &(pXsvfInfo->lvTdoExpected),
                         &(pXsvfInfo->lvTdoMask), pXsvfInfo->ucEndDR,
                         pXsvfInfo->lRunTestTime, pXsvfInfo->ucMaxRepeat );
      if ( iErrorCode != XSVF_ERROR_NONE )
      {
            pXsvfInfo->iErrorCode   = iErrorCode;
      }
      return( iErrorCode );
}

/*****************************************************************************
 * Function:     xsvfDoXRUNTEST
 * Description:  XRUNTEST <uint32>
 *               Prespecify the XRUNTEST wait time for shift operations.
 * Parameters:   pXsvfInfo   - XSVF information pointer.
 * Returns:      int         - 0 = success;  non-zero = error.
 *****************************************************************************/
int xsvfDoXRUNTEST( SXsvfInfo* pXsvfInfo )
{
      readVal( &(pXsvfInfo->lvTdi), 4 );
      pXsvfInfo->lRunTestTime = value( &(pXsvfInfo->lvTdi) );
      XSVFDBG_PRINTF1( 3, "   XRUNTEST = %ld\n", pXsvfInfo->lRunTestTime );
      return( XSVF_ERROR_NONE );
}

/*****************************************************************************
 * Function:     xsvfDoXREPEAT
 * Description:  XREPEAT <byte>
 *               Prespecify the maximum number of XC9500/XL retries.
 * Parameters:   pXsvfInfo   - XSVF information pointer.
 * Returns:      int         - 0 = success;  non-zero = error.
 *****************************************************************************/
int xsvfDoXREPEAT( SXsvfInfo* pXsvfInfo )
{
      readByte( &(pXsvfInfo->ucMaxRepeat) );
      XSVFDBG_PRINTF1( 3, "   XREPEAT = %d\n",
                   ((unsigned int)(pXsvfInfo->ucMaxRepeat)) );
      return( XSVF_ERROR_NONE );
}

/*****************************************************************************
 * Function:     xsvfDoXSDRSIZE
 * Description:  XSDRSIZE <uint32>
 *               Prespecify the XRUNTEST wait time for shift operations.
 * Parameters:   pXsvfInfo   - XSVF information pointer.
 * Returns:      int         - 0 = success;  non-zero = error.
 *****************************************************************************/
int xsvfDoXSDRSIZE( SXsvfInfo* pXsvfInfo )
{
      int iErrorCode;
      iErrorCode  = XSVF_ERROR_NONE;
      readVal( &(pXsvfInfo->lvTdi), 4 );
      pXsvfInfo->lShiftLengthBits = value( &(pXsvfInfo->lvTdi) );
      pXsvfInfo->sShiftLengthBytes= xsvfGetAsNumBytes( pXsvfInfo->lShiftLengthBits );
      XSVFDBG_PRINTF1( 3, "   XSDRSIZE = %ld\n", pXsvfInfo->lShiftLengthBits );
      if ( pXsvfInfo->sShiftLengthBytes > MAX_LEN )
      {
            iErrorCode  = XSVF_ERROR_DATAOVERFLOW;
            pXsvfInfo->iErrorCode   = iErrorCode;
      }
      return( iErrorCode );
}

/*****************************************************************************
 * Function:     xsvfDoXSDRTDO
 * Description:  XSDRTDO <lenVal.TDI[XSDRSIZE]> <lenVal.TDO[XSDRSIZE]>
 *               Get the TDI and expected TDO values.  Then, shift.
 *               Compare the expected TDO with the captured TDO using the
 *               prespecified XTDOMASK.
 * Parameters:   pXsvfInfo   - XSVF information pointer.
 * Returns:      int         - 0 = success;  non-zero = error.
 *****************************************************************************/
int xsvfDoXSDRTDO( SXsvfInfo* pXsvfInfo )
{
      int iErrorCode;
      iErrorCode  = xsvfBasicXSDRTDO( &(pXsvfInfo->ucTapState),
                              pXsvfInfo->lShiftLengthBits,
                              pXsvfInfo->sShiftLengthBytes,
                              &(pXsvfInfo->lvTdi),
                              &(pXsvfInfo->lvTdoCaptured),
                              &(pXsvfInfo->lvTdoExpected),
                              &(pXsvfInfo->lvTdoMask),
                              pXsvfInfo->ucEndDR,
                              pXsvfInfo->lRunTestTime,
                              pXsvfInfo->ucMaxRepeat );
      if ( iErrorCode != XSVF_ERROR_NONE )
      {
            pXsvfInfo->iErrorCode   = iErrorCode;
      }
      return( iErrorCode );
}

/*****************************************************************************
 * Function:     xsvfDoXSETSDRMASKS
 * Description:  XSETSDRMASKS <lenVal.AddressMask[XSDRSIZE]>
 *                            <lenVal.DataMask[XSDRSIZE]>
 *               Get the prespecified address and data mask for the XSDRINC
 *               command.
 *               Used for xc9500/xl compressed XSVF data.
 * Parameters:   pXsvfInfo   - XSVF information pointer.
 * Returns:      int         - 0 = success;  non-zero = error.
 *****************************************************************************/
#ifdef  XSVF_SUPPORT_COMPRESSION
int xsvfDoXSETSDRMASKS( SXsvfInfo* pXsvfInfo )
{
      /* read the addressMask */
      readVal( &(pXsvfInfo->lvAddressMask), pXsvfInfo->sShiftLengthBytes );
      /* read the dataMask    */
      readVal( &(pXsvfInfo->lvDataMask), pXsvfInfo->sShiftLengthBytes );

      XSVFDBG_PRINTF( 4, "    Address Mask = " );
      XSVFDBG_PRINTLENVAL( 4, &(pXsvfInfo->lvAddressMask) );
      XSVFDBG_PRINTF( 4, "\n" );
      XSVFDBG_PRINTF( 4, "    Data Mask    = " );
      XSVFDBG_PRINTLENVAL( 4, &(pXsvfInfo->lvDataMask) );
      XSVFDBG_PRINTF( 4, "\n" );

      return( XSVF_ERROR_NONE );
}
#endif  /* XSVF_SUPPORT_COMPRESSION */

/*****************************************************************************
 * Function:     xsvfDoXSDRINC
 * Description:  XSDRINC <lenVal.firstTDI[XSDRSIZE]> <byte(numTimes)>
 *                       <lenVal.data[XSETSDRMASKS.dataMask.len]> ...
 *               Get the XSDRINC parameters and execute the XSDRINC command.
 *               XSDRINC starts by loading the first TDI shift value.
 *               Then, for numTimes, XSDRINC gets the next piece of data,
 *               replaces the bits from the starting TDI as defined by the
 *               XSETSDRMASKS.dataMask, adds the address mask from
 *               XSETSDRMASKS.addressMask, shifts the new TDI value,
 *               and compares the TDO to the expected TDO from the previous
 *               XSDRTDO command using the XTDOMASK.
 *               Used for xc9500/xl compressed XSVF data.
 * Parameters:   pXsvfInfo   - XSVF information pointer.
 * Returns:      int         - 0 = success;  non-zero = error.
 *****************************************************************************/
#ifdef  XSVF_SUPPORT_COMPRESSION
int xsvfDoXSDRINC( SXsvfInfo* pXsvfInfo )
{
      int             iErrorCode;
      int             iDataMaskLen;
      unsigned char   ucDataMask;
      unsigned char   ucNumTimes;
      unsigned char   i;

      readVal( &(pXsvfInfo->lvTdi), pXsvfInfo->sShiftLengthBytes );
      iErrorCode  = xsvfShift( &(pXsvfInfo->ucTapState), XTAPSTATE_SHIFTDR,
                         pXsvfInfo->lShiftLengthBits,
                         &(pXsvfInfo->lvTdi), &(pXsvfInfo->lvTdoCaptured),
                         &(pXsvfInfo->lvTdoExpected),
                         &(pXsvfInfo->lvTdoMask), pXsvfInfo->ucEndDR,
                         pXsvfInfo->lRunTestTime, pXsvfInfo->ucMaxRepeat );
      if ( !iErrorCode )
      {
            /* Calculate number of data mask bits */
            iDataMaskLen    = 0;
            for ( i = 0; i < pXsvfInfo->lvDataMask.len; ++i )
            {
                  ucDataMask  = pXsvfInfo->lvDataMask.val[ i ];
                  while ( ucDataMask )
                  {
                        iDataMaskLen    += ( ucDataMask & 1 );
                        ucDataMask      >>= 1;
                  }
            }

            /* Get the number of data pieces, i.e. number of times to shift */
            readByte( &ucNumTimes );

            /* For numTimes, get data, fix TDI, and shift */
            for ( i = 0; !iErrorCode && ( i < ucNumTimes ); ++i )
            {
                  readVal( &(pXsvfInfo->lvNextData),
                         xsvfGetAsNumBytes( iDataMaskLen ) );
                  xsvfDoSDRMasking( &(pXsvfInfo->lvTdi),
                                &(pXsvfInfo->lvNextData),
                                &(pXsvfInfo->lvAddressMask),
                                &(pXsvfInfo->lvDataMask) );
                  iErrorCode  = xsvfShift( &(pXsvfInfo->ucTapState),
                                     XTAPSTATE_SHIFTDR,
                                     pXsvfInfo->lShiftLengthBits,
                                     &(pXsvfInfo->lvTdi),
                                     &(pXsvfInfo->lvTdoCaptured),
                                     &(pXsvfInfo->lvTdoExpected),
                                     &(pXsvfInfo->lvTdoMask),
                                     pXsvfInfo->ucEndDR,
                                     pXsvfInfo->lRunTestTime,
                                     pXsvfInfo->ucMaxRepeat );
            }
      }
      if ( iErrorCode != XSVF_ERROR_NONE )
      {
            pXsvfInfo->iErrorCode   = iErrorCode;
      }
      return( iErrorCode );
}
#endif  /* XSVF_SUPPORT_COMPRESSION */

/*****************************************************************************
 * Function:     xsvfDoXSDRBCE
 * Description:  XSDRB/XSDRC/XSDRE <lenVal.TDI[XSDRSIZE]>
 *               If not already in SHIFTDR, goto SHIFTDR.
 *               Shift the given TDI data into the JTAG scan chain.
 *               Ignore TDO.
 *               If cmd==XSDRE, then goto ENDDR.  Otherwise, stay in ShiftDR.
 *               XSDRB, XSDRC, and XSDRE are the same implementation.
 * Parameters:   pXsvfInfo   - XSVF information pointer.
 * Returns:      int         - 0 = success;  non-zero = error.
 *****************************************************************************/
int xsvfDoXSDRBCE( SXsvfInfo* pXsvfInfo )
{
      unsigned char   ucEndDR;
      int             iErrorCode;
      ucEndDR = (unsigned char)(( pXsvfInfo->ucCommand == XSDRE ) ?
                          pXsvfInfo->ucEndDR : XTAPSTATE_SHIFTDR);
      iErrorCode  = xsvfBasicXSDRTDO( &(pXsvfInfo->ucTapState),
                              pXsvfInfo->lShiftLengthBits,
                              pXsvfInfo->sShiftLengthBytes,
                              &(pXsvfInfo->lvTdi),
                              /*plvTdoCaptured*/0, /*plvTdoExpected*/0,
                              /*plvTdoMask*/0, ucEndDR,
                              /*lRunTestTime*/0, /*ucMaxRepeat*/0 );
      if ( iErrorCode != XSVF_ERROR_NONE )
      {
            pXsvfInfo->iErrorCode   = iErrorCode;
      }
      return( iErrorCode );
}

/*****************************************************************************
 * Function:     xsvfDoXSDRTDOBCE
 * Description:  XSDRB/XSDRC/XSDRE <lenVal.TDI[XSDRSIZE]> <lenVal.TDO[XSDRSIZE]>
 *               If not already in SHIFTDR, goto SHIFTDR.
 *               Shift the given TDI data into the JTAG scan chain.
 *               Compare TDO, but do NOT use XTDOMASK.
 *               If cmd==XSDRTDOE, then goto ENDDR.  Otherwise, stay in ShiftDR.
 *               XSDRTDOB, XSDRTDOC, and XSDRTDOE are the same implementation.
 * Parameters:   pXsvfInfo   - XSVF information pointer.
 * Returns:      int         - 0 = success;  non-zero = error.
 *****************************************************************************/
int xsvfDoXSDRTDOBCE( SXsvfInfo* pXsvfInfo )
{
      unsigned char   ucEndDR;
      int             iErrorCode;
      ucEndDR = (unsigned char)(( pXsvfInfo->ucCommand == XSDRTDOE ) ?
                          pXsvfInfo->ucEndDR : XTAPSTATE_SHIFTDR);
      iErrorCode  = xsvfBasicXSDRTDO( &(pXsvfInfo->ucTapState),
                              pXsvfInfo->lShiftLengthBits,
                              pXsvfInfo->sShiftLengthBytes,
                              &(pXsvfInfo->lvTdi),
                              &(pXsvfInfo->lvTdoCaptured),
                              &(pXsvfInfo->lvTdoExpected),
                              /*plvTdoMask*/0, ucEndDR,
                              /*lRunTestTime*/0, /*ucMaxRepeat*/0 );
      if ( iErrorCode != XSVF_ERROR_NONE )
      {
            pXsvfInfo->iErrorCode   = iErrorCode;
      }
      return( iErrorCode );
}

/*****************************************************************************
 * Function:     xsvfDoXSTATE
 * Description:  XSTATE <byte>
 *               <byte> == XTAPSTATE;
 *               Get the state parameter and transition the TAP to that state.
 * Parameters:   pXsvfInfo   - XSVF information pointer.
 * Returns:      int         - 0 = success;  non-zero = error.
 *****************************************************************************/
int xsvfDoXSTATE( SXsvfInfo* pXsvfInfo )
{
      unsigned char   ucNextState;
      int             iErrorCode;
      readByte( &ucNextState );
      iErrorCode  = xsvfGotoTapState( &(pXsvfInfo->ucTapState), ucNextState );
      if ( iErrorCode != XSVF_ERROR_NONE )
      {
            pXsvfInfo->iErrorCode   = iErrorCode;
      }
      return( iErrorCode );
}

/*****************************************************************************
 * Function:     xsvfDoXENDXR
 * Description:  XENDIR/XENDDR <byte>
 *               <byte>:  0 = RUNTEST;  1 = PAUSE.
 *               Get the prespecified XENDIR or XENDDR.
 *               Both XENDIR and XENDDR use the same implementation.
 * Parameters:   pXsvfInfo   - XSVF information pointer.
 * Returns:      int         - 0 = success;  non-zero = error.
 *****************************************************************************/
int xsvfDoXENDXR( SXsvfInfo* pXsvfInfo )
{
      int             iErrorCode;
      unsigned char   ucEndState;

      iErrorCode  = XSVF_ERROR_NONE;
      readByte( &ucEndState );
      if ( ( ucEndState != XENDXR_RUNTEST ) && ( ucEndState != XENDXR_PAUSE ) )
      {
            iErrorCode  = XSVF_ERROR_ILLEGALSTATE;
      }
      else
      {

            if ( pXsvfInfo->ucCommand == XENDIR )
            {
                  if ( ucEndState == XENDXR_RUNTEST )
                  {
                        pXsvfInfo->ucEndIR  = XTAPSTATE_RUNTEST;
                  }
                  else
                  {
                        pXsvfInfo->ucEndIR  = XTAPSTATE_PAUSEIR;
                  }
                  XSVFDBG_PRINTF1( 3, "   ENDIR State = %s\n",
                               xsvf_pzTapState[ pXsvfInfo->ucEndIR ] );
            }
            else    /* XENDDR */
            {
                  if ( ucEndState == XENDXR_RUNTEST )
                  {
                        pXsvfInfo->ucEndDR  = XTAPSTATE_RUNTEST;
                  }
                  else
                  {
                        pXsvfInfo->ucEndDR  = XTAPSTATE_PAUSEDR;
                  }
                  XSVFDBG_PRINTF1( 3, "   ENDDR State = %s\n",
                               xsvf_pzTapState[ pXsvfInfo->ucEndDR ] );
            }
      }

      if ( iErrorCode != XSVF_ERROR_NONE )
      {
            pXsvfInfo->iErrorCode   = iErrorCode;
      }
      return( iErrorCode );
}

/*****************************************************************************
 * Function:     xsvfDoXCOMMENT
 * Description:  XCOMMENT <text string ending in \0>
 *               <text string ending in \0> == text comment;
 *               Arbitrary comment embedded in the XSVF.
 * Parameters:   pXsvfInfo   - XSVF information pointer.
 * Returns:      int         - 0 = success;  non-zero = error.
 *****************************************************************************/
int xsvfDoXCOMMENT( SXsvfInfo* pXsvfInfo )
{
      /* Use the comment for debugging */
      /* Otherwise, read through the comment to the end '\0' and ignore */
      unsigned char   ucText;

      if ( xsvf_iDebugLevel > 0 )
      {
            putc( ' ' );
      }

      do
      {
            readByte( &ucText );
            if ( xsvf_iDebugLevel > 0 )
            {
                  putc( ucText ? ucText : '\n' );
            }
      } while ( ucText );

      pXsvfInfo->iErrorCode   = XSVF_ERROR_NONE;

      return( pXsvfInfo->iErrorCode );
}

/*****************************************************************************
 * Function:     xsvfDoXWAIT
 * Description:  XWAIT <wait_state> <end_state> <wait_time>
 *               If not already in <wait_state>, then go to <wait_state>.
 *               Wait in <wait_state> for <wait_time> microseconds.
 *               Finally, if not already in <end_state>, then goto <end_state>.
 * Parameters:   pXsvfInfo   - XSVF information pointer.
 * Returns:      int         - 0 = success;  non-zero = error.
 *****************************************************************************/
int xsvfDoXWAIT( SXsvfInfo* pXsvfInfo )
{
      unsigned char   ucWaitState;
      unsigned char   ucEndState;
      long            lWaitTime;

      /* Get Parameters */
      /* <wait_state> */
      readVal( &(pXsvfInfo->lvTdi), 1 );
      ucWaitState = pXsvfInfo->lvTdi.val[0];

      /* <end_state> */
      readVal( &(pXsvfInfo->lvTdi), 1 );
      ucEndState = pXsvfInfo->lvTdi.val[0];

      /* <wait_time> */
      readVal( &(pXsvfInfo->lvTdi), 4 );
      lWaitTime = value( &(pXsvfInfo->lvTdi) );
      XSVFDBG_PRINTF2( 3, "   XWAIT:  state = %s; time = %ld\n",
                   xsvf_pzTapState[ ucWaitState ], lWaitTime );

      /* If not already in <wait_state>, go to <wait_state> */
      if ( pXsvfInfo->ucTapState != ucWaitState )
      {
            xsvfGotoTapState( &(pXsvfInfo->ucTapState), ucWaitState );
      }

      /* Wait for <wait_time> microseconds */
      waitTime( lWaitTime );

      /* If not already in <end_state>, go to <end_state> */
      if ( pXsvfInfo->ucTapState != ucEndState )
      {
            xsvfGotoTapState( &(pXsvfInfo->ucTapState), ucEndState );
      }

      return( XSVF_ERROR_NONE );
}


/*============================================================================
 * Execution Control Functions
 ============================================================================*/

/*****************************************************************************
 * Function:     xsvfInitialize
 * Description:  Initialize the xsvf player.
 *               Call this before running the player to initialize the data
 *               in the SXsvfInfo struct.
 *               xsvfCleanup is called to clean up the data in SXsvfInfo
 *               after the XSVF is played.
 * Parameters:   pXsvfInfo   - ptr to the XSVF information.
 * Returns:      int - 0 = success; otherwise error.
 *****************************************************************************/
int xsvfInitialize( SXsvfInfo* pXsvfInfo )
{
      /* Initialize values */
      pXsvfInfo->iErrorCode   = xsvfInfoInit( pXsvfInfo );

      if ( !pXsvfInfo->iErrorCode )
      {
            /* Initialize the TAPs */
            pXsvfInfo->iErrorCode   = xsvfGotoTapState( &(pXsvfInfo->ucTapState),
                                              XTAPSTATE_RESET );
      }

      return( pXsvfInfo->iErrorCode );
}

/*****************************************************************************
 * Function:     xsvfRun
 * Description:  Run the xsvf player for a single command and return.
 *               First, call xsvfInitialize.
 *               Then, repeatedly call this function until an error is detected
 *               or until the pXsvfInfo->ucComplete variable is non-zero.
 *               Finally, call xsvfCleanup to cleanup any remnants.
 * Parameters:   pXsvfInfo   - ptr to the XSVF information.
 * Returns:      int         - 0 = success; otherwise error.
 *****************************************************************************/
int xsvfRun( SXsvfInfo* pXsvfInfo )
{
      /* Process the XSVF commands */
      if ( (!pXsvfInfo->iErrorCode) && (!pXsvfInfo->ucComplete) )
      {
            /* read 1 byte for the instruction */
            readByte( &(pXsvfInfo->ucCommand) );
            ++(pXsvfInfo->lCommandCount);

            if ( pXsvfInfo->ucCommand < XLASTCMD )
            {
                  /* Execute the command.  Func sets error code. */
                  XSVFDBG_PRINTF1( 2, "  %s\n",
                               xsvf_pzCommandName[pXsvfInfo->ucCommand] );
                  /* If your compiler cannot take this form,
                     then convert to a switch statement */
#if 0 /* test-only */
                  xsvf_pfDoCmd[ pXsvfInfo->ucCommand ]( pXsvfInfo );
#else
                  switch (pXsvfInfo->ucCommand) {
                  case 0:
                        xsvfDoXCOMPLETE(pXsvfInfo);        /*  0 */
                        break;
                  case 1:
                        xsvfDoXTDOMASK(pXsvfInfo);         /*  1 */
                        break;
                  case 2:
                        xsvfDoXSIR(pXsvfInfo);             /*  2 */
                        break;
                  case 3:
                        xsvfDoXSDR(pXsvfInfo);             /*  3 */
                        break;
                  case 4:
                        xsvfDoXRUNTEST(pXsvfInfo);         /*  4 */
                        break;
                  case 5:
                        xsvfDoIllegalCmd(pXsvfInfo);       /*  5 */
                        break;
                  case 6:
                        xsvfDoIllegalCmd(pXsvfInfo);       /*  6 */
                        break;
                  case 7:
                        xsvfDoXREPEAT(pXsvfInfo);          /*  7 */
                        break;
                  case 8:
                        xsvfDoXSDRSIZE(pXsvfInfo);         /*  8 */
                        break;
                  case 9:
                        xsvfDoXSDRTDO(pXsvfInfo);          /*  9 */
                        break;
#ifdef  XSVF_SUPPORT_COMPRESSION
                  case 10:
                        xsvfDoXSETSDRMASKS(pXsvfInfo);     /* 10 */
                        break;
                  case 11:
                        xsvfDoXSDRINC(pXsvfInfo);          /* 11 */
                        break;
#else
                  case 10:
                        xsvfDoIllegalCmd(pXsvfInfo);       /* 10 */
                        break;
                  case 11:
                        xsvfDoIllegalCmd(pXsvfInfo);       /* 11 */
                        break;
#endif  /* XSVF_SUPPORT_COMPRESSION */
                  case 12:
                        xsvfDoXSDRBCE(pXsvfInfo);          /* 12 */
                        break;
                  case 13:
                        xsvfDoXSDRBCE(pXsvfInfo);          /* 13 */
                        break;
                  case 14:
                        xsvfDoXSDRBCE(pXsvfInfo);          /* 14 */
                        break;
                  case 15:
                        xsvfDoXSDRTDOBCE(pXsvfInfo);       /* 15 */
                        break;
                  case 16:
                        xsvfDoXSDRTDOBCE(pXsvfInfo);       /* 16 */
                        break;
                  case 17:
                        xsvfDoXSDRTDOBCE(pXsvfInfo);       /* 17 */
                        break;
                  case 18:
                        xsvfDoXSTATE(pXsvfInfo);           /* 18 */
                        break;
                  case 19:
                        xsvfDoXENDXR(pXsvfInfo);           /* 19 */
                        break;
                  case 20:
                        xsvfDoXENDXR(pXsvfInfo);           /* 20 */
                        break;
                  case 21:
                        xsvfDoXSIR2(pXsvfInfo);            /* 21 */
                        break;
                  case 22:
                        xsvfDoXCOMMENT(pXsvfInfo);         /* 22 */
                        break;
                  case 23:
                        xsvfDoXWAIT(pXsvfInfo);             /* 23 */
                        break;
                  }
#endif
            }
            else
            {
                  /* Illegal command value.  Func sets error code. */
                  xsvfDoIllegalCmd( pXsvfInfo );
            }
      }

      return( pXsvfInfo->iErrorCode );
}

/*****************************************************************************
 * Function:     xsvfCleanup
 * Description:  cleanup remnants of the xsvf player.
 * Parameters:   pXsvfInfo   - ptr to the XSVF information.
 * Returns:      void.
 *****************************************************************************/
void xsvfCleanup( SXsvfInfo* pXsvfInfo )
{
      xsvfInfoCleanup( pXsvfInfo );
}


/*============================================================================
 * xsvfExecute() - The primary entry point to the XSVF player
 ============================================================================*/

/*****************************************************************************
 * Function:     xsvfExecute
 * Description:  Process, interpret, and apply the XSVF commands.
 *               See port.c:readByte for source of XSVF data.
 * Parameters:   none.
 * Returns:      int - Legacy result values:  1 == success;  0 == failed.
 *****************************************************************************/
int xsvfExecute(void)
{
      SXsvfInfo   xsvfInfo;

      xsvfInitialize( &xsvfInfo );

      while ( !xsvfInfo.iErrorCode && (!xsvfInfo.ucComplete) )
      {
            xsvfRun( &xsvfInfo );
      }

      if ( xsvfInfo.iErrorCode )
      {
            XSVFDBG_PRINTF1( 0, "%s\n", xsvf_pzErrorName[
                               ( xsvfInfo.iErrorCode < XSVF_ERROR_LAST )
                               ? xsvfInfo.iErrorCode : XSVF_ERROR_UNKNOWN ] );
            XSVFDBG_PRINTF2( 0, "ERROR at or near XSVF command #%ld.  See line #%ld in the XSVF ASCII file.\n",
                         xsvfInfo.lCommandCount, xsvfInfo.lCommandCount );
      }
      else
      {
            XSVFDBG_PRINTF( 0, "SUCCESS - Completed XSVF execution.\n" );
      }

      xsvfCleanup( &xsvfInfo );

      return( XSVF_ERRORCODE(xsvfInfo.iErrorCode) );
}


/*****************************************************************************
 * Function:     do_cpld
 * Description:  main function.
 *               Specified here for creating stand-alone debug executable.
 *               Embedded users should call xsvfExecute() directly.
 * Parameters:   iArgc    - number of command-line arguments.
 *               ppzArgv  - array of ptrs to strings (command-line arguments).
 * Returns:      int      - Legacy return value:  1 = success; 0 = error.
 *****************************************************************************/
int do_cpld(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
{
      int     iErrorCode;
      char*   pzXsvfFileName;
      unsigned long duration;
      unsigned long long startClock, endClock;

      if (argc == 2)
            xsvfdata = (unsigned char *)simple_strtoul(argv[1], NULL, 16);
      else {
#ifdef CONFIG_SYS_XSVF_DEFAULT_ADDR
            xsvfdata = (unsigned char *)CONFIG_SYS_XSVF_DEFAULT_ADDR;
#else
            printf("Usage:\ncpld %s\n", cmdtp->help);
            return -1;
#endif
      }

      iErrorCode          = XSVF_ERRORCODE( XSVF_ERROR_NONE );
      pzXsvfFileName      = 0;
      xsvf_iDebugLevel    = 0;

      printf("XSVF Player v%s, Xilinx, Inc.\n", XSVF_VERSION);
      printf("Reading XSVF data @ %p\n", xsvfdata);

      /* Initialize the I/O.  SetPort initializes I/O on first call */
      setPort( TMS, 1 );

      /* Execute the XSVF in the file */
      startClock  = get_ticks();
      iErrorCode  = xsvfExecute();
      endClock    = get_ticks();
      duration    = (unsigned long)(endClock - startClock);
      printf("\nExecution Time = %d seconds\n", (int)(duration/get_tbclk()));

      return( iErrorCode );
}
U_BOOT_CMD(
      cpld, 2,    1,    do_cpld,
      "program onboard CPLD",
      "<xsvf-addr>"
);

Generated by  Doxygen 1.6.0   Back to index