/****************************************************************************
**
**  Name:  tests.c
**
**  Description:
**     Confidence tests.
**
**  $Log:   S:/tbird/mt2_186/pvtest/tests.c_v  $
** 
**    Rev 1.1   27 Mar 1998 15:15:08   Eric
** No change.
** 
**    Rev 1.0   16 Dec 1996 16:45:20   Judy
** Initial revision.
** 
**    Rev 1.6   10 Oct 1994 13:30:02   ernie
** Implemented test 10--ProcConnect for 386EX
** 
**    Rev 1.5   13 Sep 1994 09:47:22   ernie
** Changed CheckTestTrace() to allow test patterns which are not synced
** between groups.  Since TEST is activated asynchronously to the clock,
** the 3 TICs may be out of sync by up to one frame.
** 
**    Rev 1.4   15 Aug 1994 16:09:22   ernie
** 1. Enhanced overlaymemory test to test at byte, word and dword sizes.
** 2. Enhanced ramtst error display to correctly size the expected and
**    actual data fields.
** 
**    Rev 1.3   20 Jun 1994 14:10:02   ernie
** 1. Cleaned up warning.
** 2. Changed iceads -> iceads# to conform to latest ev386ex.cfg.
** 3. Fixed bug in test procbasic debug level--trace was being cleared.
** 
**    Rev 1.2   16 May 1994 14:02:42   ernie
** Modified target connect test to not try to drive TFLT# and TGND to
** different states.  Only TGND is driven and TFLT# is just sampled.
** The AC14 device on the SAST was not powerful enough to overcome the
** 100 ohm resistor between TGND and TFLT#.
** 
**    Rev 1.1   10 May 1994 10:16:34   ernie
** Removed extra Wait() calls--no longer needed.
** 
**    Rev 1.0   10 May 1994 09:53:12   ernie
** Initial revision.
** 
**  $Header:   S:/tbird/mt2_186/pvtest/tests.c_v   1.1   27 Mar 1998 15:15:08   Eric  $
**
*****************************************************************************/

                       /****************************
                        *                          *
                        *       INCLUDE FILES      *
                        *                          *
                        ****************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>

#ifndef _BASEWIND_
#include "basewind.h"
#endif
#ifndef _CPU_
#include "cpu.h"
#endif
#ifndef _EVENT_
#include "event.h"
#endif
#ifndef _HEAP_
#include "heap.h"
#endif
#ifndef _HOSTERRS_
#include "hosterrs.h"
#endif
#ifndef _LOCAL_
#include "local.h"
#endif
#ifndef _PROC_
#include "proc.h"
#endif
#ifndef _PVTASK_
#include "pvtask.h"
#endif
#ifndef _PVTEST_
#include "pvtest.h"
#endif
#ifndef _SDPROBE_
#include "sdprobe.h"
#endif
#ifndef _SSHARED_
#include "sshared.h"
#endif
#ifndef _TBIRDMEM_
#include "tbirdmem.h"
#endif
#ifndef _TRACE_
#include "trace.h"
#endif
#ifndef _TRIG_
#include "trig.h"
#endif
                       /****************************
                        *                          *
                        *     LOCAL DEFINITIONS    *
                        *                          *
                        ****************************/
typedef struct {
   char name[8];
   U8 length;
   U8 data[8];
} OPCODE;

typedef struct {
   U8 strobeBit;
   U8 aqBit;
   U8 fqBit;
   U8 strobeActive;
   U8 aqActive;
   U8 fqActive;
   U8 strobeInactive;
   U8 aqInactive;
   U8 fqInactive;
} QUAL;

/* Bit assignments of TIC control pins in 8751 port P3 */
#define TIC_DI   0x20
#define TIC_DO   0x04
#define TIC_TEST 0x10
#define TIC_CLK  0x08

#define SAST_PORT 0x0005  /* in xdata space */
#define SAST_SER  0x4000  /* in xdata space */
#define SAST_PAR  0x0004  /* in xdata space */
/* bit assignments for SAST_PORT */
#define SAST_ENA         0x02
#define SAST_ENB         0x04
#define SAST_DRIVE_ON    0x08
#define SAST_SENSE       0x20
#define SAST_SENSEB      0x40
#define SAST_WRITE_MASK  (SAST_ENA | SAST_ENB | SAST_DRIVE_ON)

#define JTAG_PORT        0x0006
#define JTAG_DRIVE_ON    0x20
#define JTAG_TMS         0x40
#define JTAG_TRST        0x80   /* Inversion of TRST# pin state */

#define TARG_STATUS_PORT 0x0007
#define TARG_FORCE_EFLT  0      /* write this value to float processor */
#define TARG_EFLT        0x10   /* readback status of EFLT pin */
#define TARG_TFLT        0x01
#define TARG_TGND        0x02
#define TARG_TVCC        0x04

#define ICE_MEMORY_ADDR  0x8000
#define ICE_MEMORY_SIZE  0x2000

#define MAP_MEMORY_SIZE  0x10000ul

#define NUM_TEST_FRAMES 40
static TRACE_INFO trace[NUM_TEST_FRAMES];
static U16 sastDepth;
static U16 jtagDepth;
static U8 jtagMask[MAX_JTAG_BYTES];
static U8 jtagInitData[MAX_JTAG_BYTES];
static U32 rMask, sMask, tMask;
static U32 jrMask, jsMask, jtMask;
static ADDR_SPACE space;
static U32 codeAddr;
static U8 vector[8];
static U8 vectorLength;
static U16 adsBit;
static U16 adsTbit;
static BOOLEAN adsFound=FALSE;

#define NOP 0
#define JMP 1
#define SWB 2
#define RD  3
#define WR  4
#define DOG 5
#define OPEND 0xff
static OPCODE opcode[] = {
   {"nop", 8, {0}},
   {"jmp", 8, {0}},
   {"swb", 8, {0}},
   {"rd",  8, {0}},
   {"wr",  8, {0}},
   {"dog", 8, {0}},
};
#define NUM_OPCODES (sizeof(opcode) / sizeof(*opcode))

static QUAL qual;

                       /****************************
                        *                          *
                        *    EXTERNAL VARIABLES    *
                        *                          *
                        ****************************/
extern BOOLEAN looping;
extern U16 msgThreshold;

                       /****************************
                        *                          *
                        *     LOCAL PROTOTYPES     *
                        *                          *
                        ****************************/
RETCODE ConfigFileReadBytes(LPSTR name, LPSTR key, U8 *data, U8 *length);

RETCODE PRIVATE TestTraceMemoryAction(BOOLEAN *pass, BOOLEAN *abort);
RETCODE PRIVATE TestTrigMemoryAction(BOOLEAN *pass, BOOLEAN *abort);
RETCODE PRIVATE TestVram(U16 board, BOOLEAN *pass, BOOLEAN *abort);

RETCODE PRIVATE TicWrite1Bit(U8 p3in, U8 bit);
RETCODE PRIVATE TicRead1Bit(U8 p3in, U8 *bit);
RETCODE PRIVATE SastWrite1Bit(U8 bit);
RETCODE PRIVATE SastRead1Bit(U8 *bit);
RETCODE PRIVATE ProcessRamtstError(RETCODE err, RAMTST_INFO *info,
   ACCESS_SIZE access, BOOLEAN *abort);
VOID FAR PASCAL RamtstCallback(DESCRIPTOR desc);
RETCODE PRIVATE InitializeSequencer(VOID);
RETCODE PRIVATE CollectTrace(U32 numFrames,BOOLEAN tricTest);
RETCODE PRIVATE CheckTestTrace(BOOLEAN *pass);
RETCODE PRIVATE TestSastCtrlWrite(U8 byte, BOOLEAN *pass);
RETCODE PRIVATE CheckSASTConnected(BOOLEAN *pass);
RETCODE EXPORT SASTConnectCallback(LPSTR key, LPSTR value, BOOLEAN *abort,
      VOID *pass);
RETCODE EXPORT ProcConnectInputCallback(LPSTR key, LPSTR value, BOOLEAN *abort,
      VOID *pass);
RETCODE EXPORT ProcConnectOutputCallback(LPSTR key, LPSTR value,BOOLEAN *abort,
      VOID *pass);
RETCODE PRIVATE ReadJtag(U8 *data);
RETCODE PRIVATE WriteJtag(U8 *data);
RETCODE PRIVATE FloatProcessor(BOOLEAN *pass);
RETCODE PRIVATE ClearSASTShift(VOID);
RETCODE PRIVATE SetSASTBit(LPSTR name, U8 state, U16 *bitNumber);
RETCODE PRIVATE StartStopEmul(TEST_COMMAND cmd, U32 expectedPc, BOOLEAN *pass,
      BOOLEAN looping);
RETCODE PRIVATE SetupResetCode(U16 *data, BOOLEAN *pass);
RETCODE PRIVATE TestResetCpu(BOOLEAN *pass, BOOLEAN looping);
RETCODE PRIVATE GetPcAndEmonResult(U32 *pc, BOOLEAN *emon);
RETCODE PRIVATE TestMapBkptRun(LPSTR op, BOOLEAN *pass, BOOLEAN *abort,
      BOOLEAN *expectedEmon);
RETCODE PRIVATE EnableAllSignals(VOID);
RETCODE EXPORT SignalTestCallback(LPSTR key, LPSTR value, BOOLEAN *abort,
      VOID *pass);

                       /****************************
                        *                          *
                        *      EXECUTABLE CODE     *
                        *                          *
                        ****************************/

/****************************************************************************
**
** TestInit
**
** Function:
**    Initialize this module.
** 
*****************************************************************************/
RETCODE TestInit(VOID) {
   RETCODE err;
   LPSTR token;
   LOOP_VAR i;
   U8 length;
   S8 name[MAX_LINE];
   S8 value[MAX_LINE];

   if ((err = ProcInsertSystemName("[%s]",name)) != GOOD) return(err);
   /* Get sast depth */
   if ((err = ConfigFileRead(name, "sastdepth", value)) != GOOD)
      return(err);
   sastDepth = (U16)strtoul(value,NULL,0);
   if ((err = ConfigFileRead(name, "jtagdepth", value)) != GOOD)
      return(err);
   jtagDepth = (U16)strtoul(value,NULL,0);

   /* Get sast trace masks */
   if ((err = ConfigFileRead(name, "sasttrace", value)) != GOOD)
      return(err);
   rMask=sMask=tMask=0ul;
   token = strtok(value,",");
   if (token) rMask = strtoul(token,NULL,0);
   token = strtok(NULL,",");
   if (token) sMask = strtoul(token,NULL,0);
   token = strtok(NULL,"\n");
   if (token) tMask = strtoul(token,NULL,0);

   /* Get jtag trace masks */
   if ((err = ConfigFileRead(name, "jtagtrace", value)) != GOOD)
      return(err);
   jrMask=jsMask=jtMask=0ul;
   token = strtok(value,",");
   if (token) jrMask = strtoul(token,NULL,0);
   token = strtok(NULL,",");
   if (token) jsMask = strtoul(token,NULL,0);
   token = strtok(NULL,"\n");
   if (token) jtMask = strtoul(token,NULL,0);

   /* Fill in opcode table */
   if ((err = ProcInsertCpu("[%s]",name)) != GOOD) return(err);
   for (i=0; i<NUM_OPCODES; i++) {
      if ((err = ConfigFileReadBytes(name, opcode[i].name, opcode[i].data,
         &opcode[i].length)) != GOOD) return(err);
   }

   /* Read other parameters from config file */
   if ((err = ConfigFileRead(name, "space", value)) != GOOD) return(err);
   space = (ADDR_SPACE)strtoul(value,NULL,0);
   if ((err = ConfigFileRead(name, "resetpc", value)) != GOOD) return(err);
   codeAddr = strtoul(value,NULL,0);
   vectorLength=sizeof(vector);
   if ((err = ConfigFileReadBytes(name, "vector", vector, &vectorLength))
      != GOOD) return(err);
   length = sizeof(qual);
   if ((err = ConfigFileReadBytes(name, "qual", (U8*)&qual, &length))
      != GOOD) return(err);

   if (sastDepth > 0) {
      if ((err = ProcInsertSystemName("[sast %s]",name)) != GOOD) return(err);
      if ((err = ConfigFileRead(name, "ads#", value)) != GOOD)
         return(err);
      if ((token = strtok(value, ",")) != NULL) {
         adsBit = (U16)strtoul(token, NULL, 0);
         if (((token = strtok(NULL, ",")) != NULL)
               && ((token = strtok(NULL, ",\n")) != NULL)) {
            adsTbit = (U16)strtoul(token, NULL, 0);
            adsFound = TRUE;
         }
      }
   }

   return(GOOD);
}

RETCODE ConfigFileReadBytes(LPSTR name, LPSTR key, U8 *data, U8 *length) {
   RETCODE err;
   S8 value[MAX_LINE];
   LPSTR token;
   U8 maxlen = *length;
   *length=0;
   if ((err = ConfigFileRead(name, key, value)) != GOOD) return(err);
   token = strtok(value,",\n");
   while (token) {
      *data++ = (U8)strtoul(token,NULL,0);
      (*length)++;
      token = strtok(NULL,",\n");
      if (*length >= maxlen) return(GOOD);
   }
   return(GOOD);
}

/****************************************************************************
**
** TestChassisControl
**
** Tests:
**    8751 control signal connections from chassis to pod.
** 
** Strategy:
**    Send packets to 8751 to verify data lines.
**    Reset 8751, then check P3 register for its reset value.
**    There is currently no way to test EMINT or EMBRK.
**
*****************************************************************************/
RETCODE TestChassisControl(BOOLEAN *pass, BOOLEAN *abort) {
   RETCODE err;
   U8 byte;
   *abort = FALSE;
   if ((err = Print(VERB,
      "Chassis control test: chassis to pod control signals.")) != GOOD)
      return(err);
   /*
   ** read original contents of P3
   */
   if ((err = TestReadPhysical(3, SPACE_PRB_SFR, 1, &byte, FALSE)) != GOOD)
      return(err);
   if ((err = Print(DEBUG,"Contents of P3: %02X",byte)) != GOOD) return(err);

   /*
   ** reset 8751
   */
   if ((err = Print(VERB,"Resetting 8751.")) != GOOD) return(err);
   byte = 0x0E;
   if ((err = TestWritePhysical(0x27f1, SPACE_MOM_IO, 1, &byte, FALSE))!=GOOD)
      return(err);
   byte = 0x0A;
   if ((err = TestWritePhysical(0x27f1, SPACE_MOM_IO, 1, &byte, FALSE))!=GOOD)
      return(err);

   /*
   ** Read new contents of P3
   */
   if ((err = TestReadPhysical(3, SPACE_PRB_SFR, 1, &byte, FALSE)) != GOOD)
      return(err);
   if ((err = Print(DEBUG,"Contents of P3: %02X",byte)) != GOOD) return(err);
   if ((byte&0xF0) == 0xF0) *pass = TRUE;
   else if ((err = Print(FAIL, "RES8751 failed to reset 8751.")) != GOOD)
      return(err);
   return(GOOD);
}

/****************************************************************************
**
** TestTicControl
**
** Tests:
**    Tic chip shift chain and control signals on pod
** 
** Strategy:
**    Shift in 16*3=48 bits of pattern 0,0,1.
**    Shift out 48 bits, checking the pattern match.
**    Repeat with TEST asserted--check that the pattern output is all 0's
**
*****************************************************************************/
RETCODE TestTicControl(BOOLEAN *pass, BOOLEAN *abort) {
   RETCODE err;
   BOOLEAN fail=FALSE;
   LOOP_VAR i;
   U8 p3orig;
   *abort = FALSE;
   if ((err = Print(VERB,
      "Tic control test: TIC chip control shift chain.")) != GOOD)
      return(err);
   p3orig = ~TIC_TEST & ~TIC_CLK;
   if ((err = Print(VERB,"Shifting in data pattern with TEST off.")) != GOOD)
      return(err);
   for (i=0; i<16; i++) {
      if ((err = TicWrite1Bit(p3orig, 0)) != GOOD) return(err);
      if ((err = TicWrite1Bit(p3orig, 0)) != GOOD) return(err);
      if ((err = TicWrite1Bit(p3orig, 1)) != GOOD) return(err);
   }
   if ((err = TskCheckAbort(abort)) != GOOD) return(err);
   if (*abort) return(GOOD);
   if ((err = Print(VERB,"Verifying data pattern with TEST off.")) != GOOD)
      return(err);
   for (i=0; i<16; i++) {
      U8 bit;
      if ((err = TicRead1Bit(p3orig, &bit)) != GOOD) return(err);
      if (bit != 0) { fail=TRUE; break; }
      if ((err = TicRead1Bit(p3orig, &bit)) != GOOD) return(err);
      if (bit != 0) { fail=TRUE; break; }
      if ((err = TicRead1Bit(p3orig, &bit)) != GOOD) return(err);
      if (bit != 1) { fail=TRUE; break; }
   }
   if (fail) {
      Print(FAIL,"TIC control bit failure.");
      return(GOOD);
   }
   if ((err = TskCheckAbort(abort)) != GOOD) return(err);
   if (*abort) return(GOOD);
   if ((err = Print(VERB,"Shifting in data pattern with TEST on.")) != GOOD)
      return(err);
   for (i=0; i<16; i++) {
      if ((err = TicWrite1Bit(p3orig | TIC_TEST, 0)) != GOOD) return(err);
      if ((err = TicWrite1Bit(p3orig | TIC_TEST, 0)) != GOOD) return(err);
      if ((err = TicWrite1Bit(p3orig | TIC_TEST, 1)) != GOOD) return(err);
   }
   if ((err = TskCheckAbort(abort)) != GOOD) return(err);
   if (*abort) return(GOOD);
   if ((err = Print(VERB,"Verifying data pattern with TEST on.")) != GOOD)
      return(err);
   for (i=0; i<16; i++) {
      U8 bit;
      if ((err = TicRead1Bit(p3orig | TIC_TEST, &bit)) != GOOD) return(err);
      if (bit != 0) { fail=TRUE; break; }
      if ((err = TicRead1Bit(p3orig | TIC_TEST, &bit)) != GOOD) return(err);
      if (bit != 0) { fail=TRUE; break; }
      if ((err = TicRead1Bit(p3orig | TIC_TEST, &bit)) != GOOD) return(err);
      if (bit != 0) { fail=TRUE; break; }
   }
   if (fail) Print(FAIL,"TIC TEST signal failure.");
   else *pass=TRUE;
   return(GOOD);
}

/****************************************************************************
**
** TestTraceMemory
**
** Tests:
**    TMOD VRAM memory
** 
** Strategy:
**    Do par-3 test on each TMOD installed.
**
*****************************************************************************/
RETCODE TestTraceMemory(BOOLEAN *pass, BOOLEAN *abort) {
   RETCODE err,err2;
   DESCRIPTOR desc;
   if ((err = Print(VERB,
      "Trace memory test: TMOD VRAM memory.")) != GOOD)
      return(err);
   if ((err = SdnRegister(SDN_RDWR_BUFFER, (CALLBACK)RamtstCallback, &desc))
      != GOOD) return(err);
   err = TestTraceMemoryAction(pass, abort);
   err2 = SdUnRegister(desc);
   return(err?err:err2);
}

RETCODE PRIVATE TestTraceMemoryAction(BOOLEAN *pass, BOOLEAN *abort) {
   RETCODE err;
   if ((err = TestVram(0, pass, abort)) != GOOD) return(err);
   if (!*pass) return(GOOD);
   if (*abort) return(GOOD);
   if ((err = TestVram(1, pass, abort)) != GOOD) return(err);
   if (!*pass) return(GOOD);
   if (*abort) return(GOOD);
   if ((err = TestVram(2, pass, abort)) != GOOD) return(err);
   if (!*pass) return(GOOD);
   if (*abort) return(GOOD);
   if ((err = TestVram(3, pass, abort)) != GOOD) return(err);
   return(GOOD);
}

RETCODE PRIVATE TestVram(U16 board, BOOLEAN *pass, BOOLEAN *abort) {
   static MEMBER_INDEX presentIndex[] = {
      SDN_TRACE_0_SLOT_PRESENT, SDN_TRACE_1_SLOT_PRESENT,
      SDN_TRACE_2_SLOT_PRESENT, SDN_TRACE_3_SLOT_PRESENT };
   static MEMBER_INDEX compatIndex[] = {
      SDN_TRACE_0_COMPATIBILITY, SDN_TRACE_1_COMPATIBILITY,
      SDN_TRACE_2_COMPATIBILITY, SDN_TRACE_3_COMPATIBILITY };
   static U32 firstAddr[] = {0x400000ul, 0x400800ul, 0x200000ul, 0x200800ul};
   static U32 secondAddr[]= {0x100000ul, 0x100800ul, 0x300000ul, 0x300800ul};
   RETCODE err;
   BOOLEAN present;
   U8 compat;
   RAMTST_INFO info;
   *pass = FALSE;
   if ((err = SdnReadMember(presentIndex[board], &present)) != GOOD)
      return(err);
   if (present) {
      if ((err = SdnReadMember(compatIndex[board],&compat))
         != GOOD) return(err);
      if ((err = Print(VERB,"TMOD %u (%uk), first half.",board,
         ((compat>=2) ? 256 : 128))) != GOOD) return(err);
      if ((err = TestRamtstPhysical(firstAddr[board],
            ((compat>=2) ? 0x200800ul : 0x200c00ul), SPACE_MOM_MEMORY,
            0x100000ul, WORD_SIZE, FALSE, &info)) != GOOD) {
         return(ProcessRamtstError(err,&info,WORD_SIZE,abort));
      }
      if ((err = Print(VERB,"TMOD %u (%uk), second half.",board,
         ((compat>=2) ? 256 : 128))) != GOOD) return(err);
      if ((err = TestRamtstPhysical(secondAddr[board],
            ((compat>=2) ? 0x200800ul : 0x200c00ul), SPACE_MOM_MEMORY,
            0x100000ul, WORD_SIZE, FALSE, &info)) != GOOD) {
         return(ProcessRamtstError(err,&info,WORD_SIZE,abort));
      }
   } else {
      if ((err = Print(VERB,"TMOD %u is not installed.",board)) != GOOD)
         return(err);
   }
   *pass = TRUE;
   return(GOOD);
}

/****************************************************************************
**
** TestTrigMemory
**
** Tests:
**    Sequencer memory
** 
** Strategy:
**    Enable writes to sequencer
**    Run par-3 ramtst
**    Disable writes to sequencer
**
*****************************************************************************/
RETCODE TestTrigMemory(BOOLEAN *pass, BOOLEAN *abort) {
   RETCODE err,err2;
   DESCRIPTOR desc;
   U8 byte;
   /* Release reset to TMAN */
   if ((err = Print(VERB,
      "Trigger memory test: Motherboard sequencer memory.")) != GOOD)
      return(err);
   if ((err = Print(VERB,"Enabling writes to sequencer.")) != GOOD)
      return(err);
   byte = 0x10;
   if ((err = TestWritePhysical(0x27c1ul, SPACE_MOM_IO, 1, &byte, FALSE))
      != GOOD) return(err);
   byte = 0;
   if ((err = TestWritePhysical(0x2106ul, SPACE_MOM_IO, 1, &byte, FALSE))
      != GOOD) return(err);
   if ((err = Print(VERB,"Beginning memory test.")) != GOOD) return(err);
   if ((err = SdnRegister(SDN_RDWR_BUFFER, (CALLBACK)RamtstCallback, &desc))
      != GOOD) return(err);
   err = TestTrigMemoryAction(pass, abort);
   err2 = SdUnRegister(desc);
   if (!err) err = err2;
   /* Restore sequencer to default state */
   err2 = Print(VERB,"Clearing sequencer.");
   if (!err) err = err2;
   err2 = InitializeSequencer();
   return(err?err:err2);
}

RETCODE PRIVATE TestTrigMemoryAction(BOOLEAN *pass, BOOLEAN *abort) {
   RETCODE err;
   RAMTST_INFO info;
   if ((err = TestRamtstPhysical(0xd0c000ul, 0ul, SPACE_MOM_MEMORY,
      0x4000ul, WORD_SIZE, FALSE, &info)) != GOOD) {
      return(ProcessRamtstError(err, &info, WORD_SIZE, abort));
   }
   *pass = TRUE;
   return(GOOD);
}

/****************************************************************************
**
** TestTricConnect
**
** Tests:
**    TRIC - VRAM connections
** 
** Strategy:
**    Turn on trace.
**    Set TRICs to test mode.
**    Turn off trace.
**    Check trace memory for correct pattern.
**    --> Currently, this test does not run.  Data from test mode is not
**        traced correctly.
*****************************************************************************/
RETCODE TestTricConnect(BOOLEAN *pass, BOOLEAN *abort) {
   RETCODE err,err2;
   *abort=FALSE;
   if ((err = Print(VERB,
      "Tric connect test: TMOD trace data signals.")) != GOOD) return(err);
   if ((err = CollectTrace(NUM_TEST_FRAMES,TRUE)) != GOOD) goto CLEANUP;
   err = CheckTestTrace(pass);
CLEANUP:
   err2 = Print(VERB,"Restoring trace logic.");
   if (!err) err = err2;
   err2 = InitializeSequencer();
   return(err?err:err2);
}

/****************************************************************************
**
** TestTraceConnect
**
** Tests:
**    TIC - VRAM connections
** 
** Strategy:
**    Set TICs to test mode.
**    Turn on trace.
**    Turn off trace.
**    Check trace memory for correct pattern.
**
*****************************************************************************/
RETCODE TestTraceConnect(BOOLEAN *pass, BOOLEAN *abort) {
   RETCODE err,err2;
   U8 p3;
   *abort=FALSE;
   if ((err = Print(VERB,
      "Trace connect test: Probe trace data signals.")) != GOOD) return(err);
   if ((err = Print(VERB,"Putting TICs in test mode.")) != GOOD) return(err);
   p3 = ~TIC_CLK;  // TIC_TEST on
   if ((err = TestWritePhysical(3, SPACE_PRB_SFR, 1, &p3, FALSE)) != GOOD)
      return(err);
   if ((err = CollectTrace(NUM_TEST_FRAMES,FALSE)) != GOOD) goto CLEANUP;
   err = CheckTestTrace(pass);
CLEANUP:
   err2 = Print(VERB,"Restoring trace logic.");
   if (!err) err = err2;
   err2 = InitializeSequencer();
   return(err?err:err2);
}

/****************************************************************************
**
** TestXilinxProgramming
**
** Tests:
**    Xilinx programming connections
** 
** Strategy:
**    Try to program xilinx.  Report cause of failure.
**
*****************************************************************************/
RETCODE TestXilinxProgram(BOOLEAN *pass, BOOLEAN *abort) {
   RETCODE err;
   *abort = FALSE;
   if ((err = Print(VERB,
      "Xilinx program test: Programming signals.")) != GOOD) return(err);
   Print(VERB,"Programming EPOD Xilinx.");
   if ((err = TestSendCommand(TEST_XILINXPROGRAM, FALSE)) != GOOD) return(err);
   *pass = TRUE;
   return(GOOD);
}

/****************************************************************************
**
** TestSastConnect
**
** Tests:
**    Sast board connections.
** 
** Strategy:
**    Verify writability of sast control register.
**    Check sast sense and senseb states to verify correct plugin.
**    Keeping outputs disabled, shift a pattern through sast shift register.
**
*****************************************************************************/
RETCODE TestSastConnect(BOOLEAN *pass, BOOLEAN *abort) {
   RETCODE err;
   U8 byte;
   U16 bit;
   static U8 pattern[] = {0,0,1};
   *abort = FALSE;
   if ((err = Print(VERB,
      "SAST connect test: SAST control signals.")) != GOOD) return(err);
   if ((err = CheckSASTConnected(pass)) != GOOD) return(err);
   if (!*pass) return(GOOD);
   *pass = FALSE;
   if ((err = Print(VERB,"Shifting in data pattern.")) != GOOD)
      return(err);
   if ((err = Print(DEBUG,"Enabling SAST drivers.")) != GOOD) return(err);
   byte = 0;
   if ((err = TestWritePhysical(SAST_PORT, SPACE_PRB_XDATA, 1, &byte, FALSE))
      != GOOD) return(err);
   byte = SAST_DRIVE_ON;
   if ((err = TestWritePhysical(SAST_PORT, SPACE_PRB_XDATA, 1, &byte, FALSE))
      != GOOD) return(err);
   for (bit=0; bit<sastDepth; bit++) {
      if ((err = SastWrite1Bit(pattern[bit%sizeof(pattern)])) != GOOD)
         return(err);
   }

   if ((err = Print(VERB,"Verifying data pattern.")) != GOOD) return(err);
   for (bit=0; bit<sastDepth; bit++) {
      if ((err = SastRead1Bit(&byte)) != GOOD) return(err);
      if ((byte&1) != pattern[bit%sizeof(pattern)])
         return(Print(FAIL,
            "SAST data failure, bit %u, expected %u, actual %u",
            bit, pattern[bit%sizeof(pattern)], (byte&1)));
   }

   *pass = TRUE;
   return(GOOD);
}

/****************************************************************************
**
** TestTargetConnect
**
** Tests:
**    Probe to target connections
** 
** Strategy:
**    Disable processor
**    Enable sast drivers
**    Shift patterns thru sast and check that they are connected to trace.
**    For TGND and TFLT, assert/negate from sast and check by reading xilinx.
**
*****************************************************************************/
RETCODE TestTargetConnect(BOOLEAN *pass, BOOLEAN *abort) {
   RETCODE err,err2;
   U8 byte;
   S8 section[32];
   S8 valString[32];
   U16 tgndBit;
   *abort = FALSE;
   if ((err = Print(VERB,
      "Target connect test: probe connection to target.")) != GOOD)
      return(err);
   if ((err = CheckSASTConnected(pass)) != GOOD) return(err);
   if (!*pass) return(GOOD);
   if ((err = FloatProcessor(pass)) != GOOD) return(err);
   if (!*pass) return(GOOD);
   *pass = FALSE;

   if ((err = EnableAllSignals()) != GOOD) return(err);

   if ((err = Print(VERB,"Enabling SAST drivers.")) != GOOD) return(err);
   byte = (SAST_ENA | SAST_ENB | SAST_DRIVE_ON);
   if ((err = TestWritePhysical(SAST_PORT, SPACE_PRB_XDATA, 1, &byte, FALSE))
      != GOOD) return(err);

   if ((err = Print(VERB,"Testing signals.")) != GOOD) goto CLEANUP;
   if ((err = ProcInsertSystemName("[sast %s]",section)) != GOOD) goto CLEANUP;
   *pass = TRUE;
   if ((err = ConfigFileEnumerate(section, SASTConnectCallback,
      abort, pass)) != GOOD) { *pass = FALSE; goto CLEANUP; }
   if (!*pass) goto CLEANUP;
   *pass = FALSE;

   if ((err = ConfigFileRead(section, "TGND", valString)) != GOOD)
      goto CLEANUP;
   tgndBit = (U16)strtoul(valString,NULL,0);

   if ((err = ClearSASTShift()) != GOOD) goto CLEANUP;
   if ((err = Print(VERB,"Disabling set B SAST drivers."))!=GOOD) goto CLEANUP;
   byte = (SAST_ENA | SAST_DRIVE_ON);
   if ((err = TestWritePhysical(SAST_PORT, SPACE_PRB_XDATA, 1, &byte, FALSE))
      != GOOD) goto CLEANUP;
   if ((err = Print(VERB,"Checking TFLT#/TGND connect.")) !=GOOD) goto CLEANUP;
   byte = 0;
   if ((err = TestWritePhysical(tgndBit,SPACE_SAST,1,&byte,FALSE)) != GOOD)
      goto CLEANUP;
   if ((err = TestReadPhysical(TARG_STATUS_PORT,SPACE_PRB_XDATA,1,&byte,FALSE))
      != GOOD) goto CLEANUP;
   if ((byte & (TARG_TFLT | TARG_TGND)) != 0) {
      err = Print(FAIL,
         "TFLT#/TGND connect error, expected 0/0, actual %u/%u.",
         ((byte & TARG_TFLT) ? 1 : 0), ((byte & TARG_TGND) ? 1 : 0));
      goto CLEANUP;
   }
   byte = 1;
   if ((err = TestWritePhysical(tgndBit,SPACE_SAST,1,&byte,FALSE)) != GOOD)
      goto CLEANUP;
   if ((err = TestReadPhysical(TARG_STATUS_PORT,SPACE_PRB_XDATA,1,&byte,FALSE))
      != GOOD) goto CLEANUP;
   if ((byte & (TARG_TFLT | TARG_TGND)) != (TARG_TFLT | TARG_TGND)) {
      err = Print(FAIL,
         "TFLT#/TGND connect error, expected 1/1, actual %u/%u.",
         ((byte & TARG_TFLT) ? 1 : 0), ((byte & TARG_TGND) ? 1 : 0));
      goto CLEANUP;
   }
   *pass = TRUE;

CLEANUP:
   err2 = ClearSASTShift();
   if (!err) err=err2;
   err2 = Print(VERB,"Disabling SAST drivers.");
   if (!err) err=err2;
   byte = 0;
   err2 = TestWritePhysical(SAST_PORT, SPACE_PRB_XDATA, 1, &byte, FALSE);
   if (!err) err=err2;

   return(err);
}

/****************************************************************************
**
** TestProcConnect
**
** Tests:
**    Processor to probe connections
** 
** Strategy:
**    This test implemented only for 386EX (the only processor with JTAG)
**    Disable processor
**    Enable sast drivers
**    Shift patterns thru sast and read thru jtag.
**
*****************************************************************************/
RETCODE TestProcConnect(BOOLEAN *pass, BOOLEAN *abort) {
   RETCODE err,err2;
   U8 byte;
   S8 section[32];
   U8 length;
   S8 name[MAX_LINE];
   *abort = FALSE;
   if ((err = Print(VERB,
      "Processor connect test: processor connection to target.")) != GOOD)
      return(err);
   if (jtagDepth == 0) return(Print(VERB,
      "System does not have JTAG capability."));

   length = sizeof(jtagMask);
   if ((err = ProcInsertSystemName("[%s]",name)) != GOOD) return(err);
   if ((err = ConfigFileReadBytes(name, "jtagmask", jtagMask, &length))
      != GOOD) return(err);

   length = sizeof(jtagInitData);
   if ((err = ProcInsertSystemName("[%s]",name)) != GOOD) return(err);
   if ((err = ConfigFileReadBytes(name, "jtaginit", jtagInitData, &length))
      != GOOD) return(err);

   if ((err = CheckSASTConnected(pass)) != GOOD) return(err);
   if (!*pass) return(GOOD);
   if ((err = EnableAllSignals()) != GOOD) return(err);

   if ((err = Print(VERB,"Enabling JTAG drivers.")) != GOOD) goto CLEANUP;
   byte = (SAST_DRIVE_ON);
   if ((err = TestWritePhysical(SAST_PORT, SPACE_PRB_XDATA, 1, &byte, FALSE))
      != GOOD) return(err);
   byte = (JTAG_DRIVE_ON | JTAG_TRST);
   if ((err = TestWritePhysical(JTAG_PORT, SPACE_PRB_XDATA, 1, &byte, FALSE))
      != GOOD) goto CLEANUP;
   byte = (JTAG_DRIVE_ON);
   if ((err = TestWritePhysical(JTAG_PORT, SPACE_PRB_XDATA, 1, &byte, FALSE))
      != GOOD) goto CLEANUP;

   if ((err = Print(VERB,"Testing output signals.")) != GOOD) goto CLEANUP;
   if ((err = ProcInsertSystemName("[jtagoutput %s]",section)) != GOOD)
      goto CLEANUP;
   *pass = TRUE;
   if ((err = ConfigFileEnumerate(section, ProcConnectOutputCallback,
      abort, pass)) != GOOD) *pass = FALSE;
   if (*abort) goto CLEANUP;
   if (!*pass) goto CLEANUP;

   if ((err = Print(VERB,"Enabling SAST drivers.")) != GOOD) goto CLEANUP;
   byte = (SAST_ENA | SAST_ENB | SAST_DRIVE_ON);
   if ((err = TestWritePhysical(SAST_PORT, SPACE_PRB_XDATA, 1, &byte, FALSE))
      != GOOD) goto CLEANUP;
   if ((err = FloatProcessor(pass)) != GOOD) return(err);
   if (!*pass) goto CLEANUP;
   *pass = FALSE;
   if ((err = Print(VERB,"Testing input signals.")) != GOOD) goto CLEANUP;
   if ((err = ProcInsertSystemName("[jtaginput %s]",section)) != GOOD)
      goto CLEANUP;
   *pass = TRUE;
   if ((err = ConfigFileEnumerate(section, ProcConnectInputCallback,
      abort, pass)) != GOOD) *pass = FALSE;

CLEANUP:
   err2 = ClearSASTShift();
   if (!err) err=err2;
   err2 = Print(VERB,"Disabling SAST drivers.");
   if (!err) err=err2;
   byte = 0;
   err2 = TestWritePhysical(SAST_PORT, SPACE_PRB_XDATA, 1, &byte, FALSE);
   if (!err) err=err2;
   err2 = Print(VERB,"Disabling JTAG drivers.");
   if (!err) err=err2;
   byte = (JTAG_DRIVE_ON | JTAG_TRST);
   err = TestWritePhysical(JTAG_PORT, SPACE_PRB_XDATA, 1, &byte, FALSE);
   if (!err) err=err2;
   byte = (JTAG_DRIVE_ON);
   err = TestWritePhysical(JTAG_PORT, SPACE_PRB_XDATA, 1, &byte, FALSE);
   if (!err) err=err2;
   byte = 0;
   err2 = TestWritePhysical(JTAG_PORT, SPACE_PRB_XDATA, 1, &byte, FALSE);
   if (!err) err=err2;
   return(err);
}

/****************************************************************************
**
** TestIceMemory
**
** Tests:
**    8751 port to ice memory, ice memory chips
** 
** Strategy:
**    Run ramtst on 8751 xdata space mapped to ice memory.
**
*****************************************************************************/
RETCODE TestIceMemory(BOOLEAN *pass, BOOLEAN *abort) {
   RETCODE err,err2;
   DESCRIPTOR desc;
   RAMTST_INFO info;
   if ((err = Print(VERB,
      "Ice memory test: Probe ice memory.")) != GOOD)
      return(err);
   if ((err = FloatProcessor(pass)) != GOOD) return(err);
   if (!*pass) return(GOOD);
   *pass = FALSE;

   if ((err = Print(VERB,"Beginning memory test.")) != GOOD) return(err);
   if ((err = SdnRegister(SDN_RDWR_BUFFER, (CALLBACK)RamtstCallback, &desc))
      != GOOD) return(err);
   if ((err = TestRamtstPhysical(ICE_MEMORY_ADDR, 0ul, SPACE_PRB_XDATA,
      ICE_MEMORY_SIZE, BYTE_SIZE, FALSE, &info)) == GOOD) {
      *pass = TRUE;
   }
   err2 = SdUnRegister(desc);
   return(err ? ProcessRamtstError(err,&info,BYTE_SIZE,abort) : err2);
}

/****************************************************************************
**
** TestProcBasic
**
** Tests:
**    Basic functions of processor--reset, entry to ice mode
** 
** Strategy:
**    This just calls fwpsHwInit.  The firmware returns detailed failure info.
**
*****************************************************************************/
RETCODE TestProcBasic(BOOLEAN *pass, BOOLEAN *abort) {
   RETCODE err,err2;
   DESCRIPTOR eventDesc=NULL, trigDesc=NULL;
   *abort = FALSE;
   if ((err = Print(VERB,
      "Basic functions test: Processor entry to ice mode.")) != GOOD)
      return(err);

   if (msgThreshold >= DEBUG) {
      if ((err = Print(VERB,"Setting up trigger.")) != GOOD) return(err);
      if ((err = TrcTracingSet(FALSE)) != GOOD) return(err);
      if ((err = EvtOpenEvent(&eventDesc, "default")) != GOOD) return(err);
      if ((err = EvtSetActiveEvent(eventDesc, "pvtest")) != GOOD) goto CLEANUP;
      if ((err = EvtSetActiveField(eventDesc, "address"))!= GOOD) goto CLEANUP;
      if ((err = EvtSetStart(eventDesc,"0x0000FFF0")) != GOOD) goto CLEANUP;
      if ((err = EvtSetMask(eventDesc,"0x0000FFFF")) != GOOD) goto CLEANUP;
      if ((err = EvtSetActiveField(eventDesc, "iceads#"))!= GOOD) goto CLEANUP;
      if ((err = EvtSetStartAndMask(eventDesc,"0")) != GOOD) goto CLEANUP;
      if ((err = EvtSetActiveField(eventDesc, "emon")) != GOOD) goto CLEANUP;
      if ((err = EvtSetStartAndMask(eventDesc,"x")) != GOOD) goto CLEANUP;
      if ((err = TrigTriggerOpen(&trigDesc, NULL,"default"))!=GOOD)
         goto CLEANUP;
      if ((err = TrigTriggerClear(trigDesc)) != GOOD) goto CLEANUP;
      if ((err = TrigIgnoreEmonSet(trigDesc,TRUE)) != GOOD) goto CLEANUP;
      if ((err = TrigEventNameSet(trigDesc,"pvtest")) != GOOD) goto CLEANUP;
      if ((err = TrigEventEnableSet(trigDesc,TRUE)) != GOOD) goto CLEANUP;
      if ((err = TrigActionSet(trigDesc,TRIG_HALT_MASK)) != GOOD) goto CLEANUP;
      if ((err = TrigQualifierSet(trigDesc,QUAL_CLOCK)) != GOOD) goto CLEANUP;
      if ((err = TrigTraceModeSet(trigDesc,TRACE_CENTER))!= GOOD) goto CLEANUP;
      if ((err = TrigTriggerProgram()) != GOOD) goto CLEANUP;
      if ((err = TrcTracingSet(TRUE)) != GOOD) goto CLEANUP;
   }

   if ((err = Print(VERB,"Initializing pod.")) != GOOD) return(err);
   if ((err = TestSendCommand(TEST_FWPSINIT, FALSE)) != GOOD) return(err);
   *pass = TRUE;
CLEANUP:
      /* Wait for tracing to stop before trying to clear trigger */
   err2 = TrcTracingSet(FALSE);
   if (!err) err = err2;
   if (eventDesc) {
      err2 = EvtCloseEvent(eventDesc);
      if (!err) err = err2;
   }
   if (trigDesc) {
      err2 = TrigTriggerClear(trigDesc);
      if (!err) err = err2;
      err2 = TrigTriggerClose(trigDesc);
      if (!err) err = err2;
   }
   return(err);
}

/****************************************************************************
**
** TestProcInternal
**
** Tests:
**    Runs processor internal self-test
** 
** Strategy:
**    Assert BUSY# pin from SAST.
**    Reset processor.
**    Check value in eax.  If non-zero, BIST failed.
**
*****************************************************************************/
RETCODE TestProcInternal(BOOLEAN *pass, BOOLEAN *abort) {
   RETCODE err,err2;
   U8 byte;
   U32 eax;
   *abort = FALSE;
   if ((err = Print(VERB,
      "Target connect test: probe connection to target.")) != GOOD)
      return(err);
   if ((err = CheckSASTConnected(pass)) != GOOD) return(err);
   if (!*pass) return(GOOD);
   *pass = FALSE;

   byte = SAST_DRIVE_ON;
   if ((err = TestWritePhysical(SAST_PORT, SPACE_PRB_XDATA, 1, &byte, FALSE))
      != GOOD) return(err);

   if ((err = Print(VERB,"Asserting BUSY# from SAST.")) != GOOD) return(err);
   if ((err = TestSASTInit()) != GOOD) return(err);
   if ((err = SetSASTBit("busy#",0, NULL)) != GOOD) return(err);

   if ((err = Print(VERB,"Enabling SAST drivers.")) != GOOD) return(err);
   byte = (SAST_ENA | SAST_DRIVE_ON);
   if ((err = TestWritePhysical(SAST_PORT, SPACE_PRB_XDATA, 1, &byte, FALSE))
      != GOOD) return(err);

   if ((err = Print(VERB,"Resetting processor.")) != GOOD) goto CLEANUP;
   if ((err = TestResetCpu(pass, FALSE)) != GOOD) goto CLEANUP;
   if (!*pass) goto CLEANUP;
   *pass = FALSE;

CLEANUP:
   err2 = Print(VERB,"Disabling SAST drivers.");
   if (!err) err=err2;
   byte = 0;
   err2 = TestWritePhysical(SAST_PORT, SPACE_PRB_XDATA, 1, &byte, FALSE);
   if (!err) err=err2;
   if (err) return(err);
   if ((err = Print(VERB,"Checking eax.")) != GOOD) return(err);
   if ((err = TestReadPhysical(0x8028ul, SPACE_PRB_XDATA, 4, (U8*)&eax, FALSE))
       != GOOD) return(err);
   if (eax != 0)
      return(Print(FAIL,"Processor selftest failed, code=%08lX.",eax));
   *pass = TRUE;
   return(GOOD);
}

/****************************************************************************
**
** TestMapMemory
**
** Tests:
**    Bondout access to map memory; map memory devices
** 
** Strategy:
**    Run ramtest on map memory.
**
*****************************************************************************/
RETCODE TestMapMemory(BOOLEAN *pass, BOOLEAN *abort) {
   RETCODE err,err2;
   DESCRIPTOR desc;
   RAMTST_INFO info;
   if ((err = Print(VERB,
      "Map memory test: Probe map memory.")) != GOOD)
      return(err);

   if ((err = Print(VERB,"Beginning memory test.")) != GOOD) return(err);
   if ((err = SdnRegister(SDN_RDWR_BUFFER, (CALLBACK)RamtstCallback, &desc))
      != GOOD) return(err);
   if ((err = TestRamtstPhysical(0ul, 0ul, SPACE_MAP, MAP_MEMORY_SIZE,
      WORD_SIZE, FALSE, &info)) == GOOD) {
      *pass = TRUE;
   }
   err2 = SdUnRegister(desc);
   return(err ? ProcessRamtstError(err,&info,WORD_SIZE,abort) : err2);
}

/****************************************************************************
**
** TestOverlayMemory
**
** Tests:
**    Processor overlay access, overlay RAM devices
** 
** Strategy:
**    Map overlay at 0.
**    Run ramtest on mapped region.
**    Restart probe.
**
*****************************************************************************/
RETCODE TestOverlayMemory(BOOLEAN *pass, BOOLEAN *abort) {
   RETCODE err;
   RAMTST_INFO info;
   U32 numBlocks,sizeBlock;

   if ((err = Print(VERB,
      "Overlay memory test.")) != GOOD)
      return(err);

   if ((err = TestMapClear()) != GOOD) return(err);

   if ((err = SdnReadMember(SDN_NUM_MAP_BLOCKS, (U8*)&numBlocks)) != GOOD)
      return(err);
   if ((err = SdnReadMember(SDN_SIZE_MAP_BLOCK, (U8*)&sizeBlock)) != GOOD)
      return(err);

   {
      PROBE_TYPE probeType;
      ACCESS_SIZE access;
      U16 data;
      if ((err = ProcReturnSpecificProcessor(&probeType)) != GOOD) return(err);
      if (probeType == I80386EX_TB) {
         if ((err = Print(VERB,"Setting chip selects for zero waitstates."))
            != GOOD) return(err);
         if ((err = MemGetAccessSize(&access)) != GOOD) return(err);
         if ((err = MemSetAccessSize(BYTE_SIZE)) != GOOD) return(err);
         data=0;
         if ((err = TestWritePhysical(0x23, SPACE_IO, 1, (U8*)&data, FALSE))
            != GOOD) return(err);
         data=0x80;
         if ((err = TestWritePhysical(0x22, SPACE_IO, 1, (U8*)&data, FALSE))
            != GOOD) return(err);
         if ((err = MemSetAccessSize(WORD_SIZE)) != GOOD) return(err);
         if ((err = TestWritePhysical(0x22, SPACE_IO, 2, (U8*)&data, FALSE))
            != GOOD) return(err);
         data=0xff00;
         if ((err = TestWritePhysical(0xf438, SPACE_IO, 2, (U8*)&data, FALSE))
            != GOOD) return(err);
         if ((err = MemSetAccessSize(access)) != GOOD) return(err);
      }
   }

   if ((err = TestMapWrite(0ul, 0ul, numBlocks*sizeBlock, TRUE, MAP_RAM))
      != GOOD) return(err);
   if ((err = Print(VERB,"Beginning byte memory test.")) != GOOD) goto CLEANUP;
   if ((err = TestRamtstPhysical(0ul,0ul, SPACE_USER,numBlocks*sizeBlock,
      BYTE_SIZE, FALSE, &info)) != GOOD) {
      err = ProcessRamtstError(err,&info,BYTE_SIZE,abort);
      goto CLEANUP;
   }
   if ((err = Print(VERB,"Beginning word memory test.")) != GOOD) goto CLEANUP;
   if ((err = TestRamtstPhysical(0ul,0ul, SPACE_USER,numBlocks*sizeBlock,
      WORD_SIZE, FALSE, &info)) != GOOD) {
      err = ProcessRamtstError(err,&info,WORD_SIZE,abort);
      goto CLEANUP;
   }
   if ((err = Print(VERB,"Beginning dword memory test."))!= GOOD) goto CLEANUP;
   if ((err = TestRamtstPhysical(0ul,0ul, SPACE_USER,numBlocks*sizeBlock,
      DWORD_SIZE, FALSE, &info)) != GOOD) {
      err = ProcessRamtstError(err,&info,DWORD_SIZE,abort);
      goto CLEANUP;
   }
   *pass = TRUE;
CLEANUP:
   return(err);
}

/****************************************************************************
**
** TestProcGrHalt
**
** Tests:
**    Processor GR and HALT operations.
** 
** Strategy:
**    Write nop,jmp self at reset vector
**    loop {
**      GR.
**      Check that processor is running.
**      HALT.
**      Check that processor is stopped.
**      Check pc = reset vector+nopsize.
**    }
**    Clear map.
**
*****************************************************************************/
RETCODE TestProcGrHalt(BOOLEAN *pass, BOOLEAN *abort) {
   RETCODE err;
   static U16 data[] = { DOG, JMP, OPEND };
   *abort = FALSE;
   if ((err = Print(VERB,
      "Gr/halt test.")) != GOOD)
      return(err);
   if ((err = SetupResetCode(data, pass)) != GOOD) return(err);
   if (!*pass) return(GOOD);
   *pass=FALSE;
   if ((err = StartStopEmul(TEST_GRHALT, codeAddr+opcode[DOG].length, pass,
      looping)) != GOOD) return(err);
   looping = FALSE;
   return(GOOD);
}

/****************************************************************************
**
** TestProcGoHalt
**
** Tests:
**    Processor GO and HALT operations.
** 
** Strategy:
**    Map memory at reset vector
**    Write nop,nop,jmp self at reset vector
**    Do GR and HALT. Check that pc is at codeAddr+2*noplength
**    Write nop,nop,nop,jmp self at reset vector
**    Write jmp self at reset vector
**    loop {
**      GO.
**      Check that processor is running.
**      HALT.
**      Check that processor is stopped.
**      Check eip = codeAddr+3*noplength.
**    }
**    Clear map.
**
*****************************************************************************/
RETCODE TestProcGoHalt(BOOLEAN *pass, BOOLEAN *abort) {
   RETCODE err;
   static U16 data[] = { DOG, NOP, NOP, JMP, OPEND };
   static U16 data2[]= { DOG, NOP, NOP, NOP, JMP, OPEND };
   static U16 data3[]= { DOG, JMP, OPEND };
   *abort = FALSE;
   if ((err = Print(VERB,
      "Go/halt test.")) != GOOD)
      return(err);
   if ((err = SetupResetCode(data, pass)) != GOOD) return(err);
   if (!*pass) return(GOOD);
   *pass=FALSE;
   if ((err = StartStopEmul(TEST_GRHALT,
      codeAddr+opcode[DOG].length+2*opcode[NOP].length, pass, FALSE)) != GOOD)
      return(err);
   if (!*pass) return(GOOD);
   *pass=FALSE;
   if ((err = SetupResetCode(data2, pass)) != GOOD) return(err);
   if (!*pass) return(GOOD);
   *pass=FALSE;
   if ((err = SetupResetCode(data3, pass)) != GOOD) return(err);
   if (!*pass) return(GOOD);
   *pass=FALSE;

   if ((err = StartStopEmul(TEST_GOHALT,
      codeAddr+opcode[DOG].length+3*opcode[NOP].length, pass,
      looping)) != GOOD) return(err);
   looping=FALSE;
   return(GOOD);
}

/****************************************************************************
**
** TestProcReset
**
** Tests:
**    Processor reset operation
** 
** Strategy:
**    With emulation off, verify that emulator reset leaves emulation off.
**    With emulation on, verify that emulator reset turns emulation off.
**
*****************************************************************************/
RETCODE TestProcReset(BOOLEAN *pass, BOOLEAN *abort) {
   RETCODE err;
   static U16 data[] = { DOG, NOP, JMP, OPEND };
   *abort = FALSE;
   if ((err = Print(VERB,
      "Reset test.  Behavior of processor to emulator reset."))
      != GOOD) return(err);

   if ((err = SetupResetCode(data, pass)) != GOOD) return(err);
   if (!*pass) return(GOOD);
   *pass=FALSE;

   if ((err = TestResetCpu(pass, looping)) != GOOD) return(err);
   if (!*pass) return(GOOD);
   *pass=FALSE;
   looping=FALSE;

   if ((err = Print(VERB,"Starting emulation.")) != GOOD) return(err);
   if ((err = TestSendCommand(TEST_GR, FALSE)) != GOOD) return(err);
   if ((err = TestResetCpu(pass, FALSE)) != GOOD) return(err);

   return(GOOD);
}

/****************************************************************************
**
** TestProcStep
**
** Tests:
**    Processor single-step operation
** 
** Strategy:
**    Set up program in overlay.
**    Execute Step.
**    Verify correct pc.
**
*****************************************************************************/
RETCODE TestProcStep(BOOLEAN *pass, BOOLEAN *abort) {
   RETCODE err;
   U32 pc;
   BOOLEAN emon;
   static U16 data[] = { DOG, JMP, OPEND };
   *abort = FALSE;
   if ((err = Print(VERB,
      "Step test.  Processor single-step."))
      != GOOD) return(err);

   if ((err = SetupResetCode(data, pass)) != GOOD) return(err);
   if (!*pass) return(GOOD);
   *pass=FALSE;

   if ((err = TestResetCpu(pass, FALSE)) != GOOD) return(err);
   if (!*pass) return(GOOD);
   *pass=FALSE;

   if ((err = Print(VERB,"Stepping processor.")) != GOOD) return(err);
   if ((err = TestSendCommand(TEST_STEP, looping)) != GOOD) return(err);
   looping=FALSE;
   if ((err = GetPcAndEmonResult(&pc, &emon)) != GOOD) return(err);
   if (emon) return(Print(FAIL,"Emulation did not stop after step."));
   if (pc != codeAddr+opcode[DOG].length) return(Print(FAIL,
      "Incorrect pc after step: expected %08lX, actual %08lX",
      codeAddr+opcode[DOG].length, pc));
   *pass = TRUE;
   return(GOOD);
}

/****************************************************************************
**
** TestProcSwBkpt
**
** Tests:
**    Processor software breakpoint
** 
** Strategy:
**    Set up program in overlay.
**    Reset.
**    Set sw bkpt.
**    Go.
**    Verify processor halts and pc is correct.
**
*****************************************************************************/
RETCODE TestProcSwBkpt(BOOLEAN *pass, BOOLEAN *abort) {
   RETCODE err;
   U32 pc;
   BOOLEAN emon;
   static U16 data[] = { DOG, NOP, SWB, JMP, OPEND };
   *abort = FALSE;
   if ((err = Print(VERB,
      "Software bkpt test."))
      != GOOD) return(err);

   if ((err = SetupResetCode(data, pass)) != GOOD) return(err);
   if (!*pass) return(GOOD);
   *pass=FALSE;

   if ((err = TestResetCpu(pass, FALSE)) != GOOD) return(err);
   if (!*pass) return(GOOD);
   *pass=FALSE;

   if ((err = Print(VERB,"Setting software breakpoint.")) != GOOD) return(err);
   if ((err = TestSendCommand(TEST_ENABLEBKPT, looping)) != GOOD) return(err);

   if ((err = Print(VERB,"Starting emulation.")) != GOOD) return(err);
   if ((err = TestSendCommand(TEST_GO, looping)) != GOOD) return(err);
   looping=FALSE;
   if ((err = GetPcAndEmonResult(&pc, &emon)) != GOOD) return(err);
   if (emon) return(Print(FAIL,
      "Emulation did not stop at software breakpoint."));
   if (pc != codeAddr+opcode[DOG].length+opcode[NOP].length) return(Print(FAIL,
      "Incorrect pc: expected %08lX, actual %08lX",
      codeAddr+opcode[DOG].length+opcode[NOP].length, pc));
   *pass = TRUE;
   return(GOOD);
}

/****************************************************************************
**
** TestProcHwBkpt
**
** Tests:
**    Processor hardware breakpoint
** 
** Strategy:
**    Set up program in overlay.
**    Reset.
**    Set hw bkpt.
**    Go (not gr).
**    Verify processor halts and pc is correct.
**
*****************************************************************************/
RETCODE TestProcHwBkpt(BOOLEAN *pass, BOOLEAN *abort) {
   RETCODE err;
   U32 pc, addr;
   BOOLEAN emon;
   static U16 data[] = { DOG, NOP, NOP, JMP, OPEND };
   *abort = FALSE;
   if ((err = Print(VERB,
      "Hardware bkpt test."))
      != GOOD) return(err);

   if ((err = SetupResetCode(data, pass)) != GOOD) return(err);
   if (!*pass) return(GOOD);
   *pass=FALSE;

   if ((err = TestResetCpu(pass, FALSE)) != GOOD) return(err);
   if (!*pass) return(GOOD);
   *pass=FALSE;

   if ((err = Print(VERB,"Setting hardware breakpoint.")) != GOOD) return(err);
   addr = codeAddr + opcode[DOG].length + opcode[NOP].length;
   if ((err = SdnWritePartialMember(SDN_TEST_BUFFER,0,4,(U8*)&addr,GOOD))
      != GOOD) return(err);
   if ((err = TestSendCommand(TEST_SETHWBKPT, looping)) != GOOD) return(err);

   if ((err = Print(VERB,"Starting emulation.")) != GOOD) return(err);
   if ((err = TestSendCommand(TEST_GO, looping)) != GOOD) return(err);
   looping=FALSE;
   if ((err = GetPcAndEmonResult(&pc, &emon)) != GOOD) return(err);
   if (emon) return(Print(FAIL,
      "Emulation did not stop at hardware breakpoint."));
   if (pc != codeAddr+opcode[DOG].length+opcode[NOP].length) return(Print(FAIL,
      "Incorrect pc: expected %08lX, actual %08lX",
      codeAddr+opcode[DOG].length+opcode[NOP].length, pc));
   *pass = TRUE;
   return(GOOD);
}

/****************************************************************************
**
** TestProcTrigger
**
** Tests:
**    Processor trigger breakpoint
** 
** Strategy:
**    Set up program in overlay.
**    Reset.
**    Set trigger on code fetch.
**    Go.
**    Verify processor halts and pc is correct.
**    Verify hardware break cause is correct.
**
*****************************************************************************/
RETCODE TestProcTrigger(BOOLEAN *pass, BOOLEAN *abort) {
   RETCODE err,err2;
   U32 pc;
   BOOLEAN emon;
   DESCRIPTOR eventDesc=NULL, trigDesc=NULL;
   static U16 datanop[] = { DOG, NOP, JMP, OPEND };
   static U16 datawr[]= { DOG, WR,  JMP, OPEND };
   *abort = FALSE;
   if ((err = Print(VERB,
      "Trigger bkpt test."))
      != GOOD) return(err);

   if ((err = Print(VERB,"Setting up trigger.")) != GOOD) return(err);
   if ((err = TrcTracingSet(FALSE)) != GOOD) return(err);
   if ((err = EvtOpenEvent(&eventDesc, "default")) != GOOD) return(err);
   if ((err = EvtSetActiveEvent(eventDesc, "pvtest")) != GOOD) goto CLEANUP;
   if ((err = EvtSetActiveField(eventDesc, "address")) != GOOD) goto CLEANUP;
   if ((err = EvtSetStart(eventDesc,"0x00000000")) != GOOD) goto CLEANUP;
   if ((err = EvtSetMask(eventDesc,"0x000FFFFF")) != GOOD) goto CLEANUP;
   if ((err = TrigTriggerOpen(&trigDesc, NULL,"default"))!= GOOD) goto CLEANUP;
   if ((err = TrigTriggerClear(trigDesc)) != GOOD) goto CLEANUP;
   if ((err = TrigEventNameSet(trigDesc,"pvtest")) != GOOD) goto CLEANUP;
   if ((err = TrigEventEnableSet(trigDesc,TRUE)) != GOOD) goto CLEANUP;
   if ((err = TrigActionSet(trigDesc,EM_BRK_MASK)) != GOOD) goto CLEANUP;
   if ((err = TrigQualifierSet(trigDesc,QUAL_CLOCK)) != GOOD) goto CLEANUP;
   if ((err = TrigTriggerProgram()) != GOOD) goto CLEANUP;
   if ((err = TrcTracingSet(TRUE)) != GOOD) goto CLEANUP;

   if ((err = SetupResetCode(datanop, pass)) != GOOD) return(err);
   if (!*pass) return(GOOD);
   *pass=FALSE;
   if ((err = TestResetCpu(pass, FALSE)) != GOOD) return(err);
   if (!*pass) return(GOOD);
   *pass=FALSE;
   if ((err = Print(VERB,"Starting emulation.")) != GOOD) goto CLEANUP;
   if ((err = TestSendCommand(TEST_GO, looping)) != GOOD) goto CLEANUP;
   looping=FALSE;
   if ((err = GetPcAndEmonResult(&pc, &emon)) != GOOD) goto CLEANUP;
   if (!emon) {
      err = Print(FAIL,"Emulation stopped but shouldn't have.");
      goto CLEANUP;
   }

   if ((err = TestResetCpu(pass, FALSE)) != GOOD) goto CLEANUP;
   if (!*pass) goto CLEANUP;
   *pass=FALSE;
   if ((err = SetupResetCode(datawr, pass)) != GOOD) goto CLEANUP;
   if (!*pass) goto CLEANUP;
   *pass=FALSE;
   if ((err = Print(VERB,"Starting emulation.")) != GOOD) goto CLEANUP;
   if ((err = TrcTracingSet(TRUE)) != GOOD) goto CLEANUP;
   if ((err = TestSendCommand(TEST_GO, looping)) != GOOD) goto CLEANUP;
   looping=FALSE;
   if ((err = GetPcAndEmonResult(&pc, &emon)) != GOOD) goto CLEANUP;
   if (emon) {
      err = Print(FAIL,"Emulation did not stop at trigger.");
      goto CLEANUP;
   }
   *pass = TRUE;
CLEANUP:
      /* Wait for tracing to stop before trying to clear trigger */
   err2 = TrcTracingSet(FALSE);
   if (!err) err = err2;
   if (eventDesc) {
      err2 = EvtCloseEvent(eventDesc);
      if (!err) err = err2;
   }
   if (trigDesc) {
      err2 = TrigTriggerClear(trigDesc);
      if (!err) err = err2;
      err2 = TrigTriggerProgram();
      if (!err) err = err2;
      err2 = TrigTriggerClose(trigDesc);
      if (!err) err = err2;
   }
   return(err);
}

/****************************************************************************
**
** TestProcTrace
**
** Tests:
**    Processor to trace connectivity
** 
** Strategy:
**    run program exercising trace bits.
**    compare trace against model.
**    !!!
**
*****************************************************************************/
RETCODE TestProcTrace(BOOLEAN *pass, BOOLEAN *abort) {
   *abort = FALSE;
   *pass = TRUE;
   return(GOOD);
}

/****************************************************************************
**
** TestSastMemory
**
** Tests:
**    SAST memory
** 
** Strategy:
**    clear map.
**    write 0's to all power-of-two boundaries.
**    write pattern to address 0.
**    look at power-of-two boundaries until pattern found.
**    ramtst on amount of sast memory found.
**
*****************************************************************************/
RETCODE TestSastMemory(BOOLEAN *pass, BOOLEAN *abort) {
   RETCODE err,err2;
   U32 data = 0x55aa5aa5ul;
   U32 read = 0ul;
   U32 addr;
   RAMTST_INFO info;
   DESCRIPTOR desc;
   *abort = FALSE;
   if ((err = Print(VERB,
      "SAST memory test."))
      != GOOD) return(err);
   if ((err = CheckSASTConnected(pass)) != GOOD) return(err);
   if (!*pass) return(GOOD);
   *pass = FALSE;

   if ((err = TestMapClear()) != GOOD) return(err);

   if ((err = Print(DEBUG,"Clearing power-of-two locations.")) != GOOD)
      return(err);
   for (addr=0x2000ul; addr<=0x00400000ul; addr<<=1) {
      if ((err = TestWritePhysical(addr, SPACE_USER, 4, (U8*)&read, FALSE))
         != GOOD) return(err);
   }
   if ((err = Print(DEBUG,"Writing pattern to 0.")) != GOOD) return(err);
   if ((err = TestWritePhysical(0ul, SPACE_USER, 4, (U8*)&data,FALSE)) != GOOD)
      return(err);
   if ((err = TestReadPhysical(0ul, SPACE_USER, 4, (U8*)&read, FALSE)) != GOOD)
      return(err);
   if (read != data) return(Print(FAIL,
      "SAST memory write failure: offset %08lX, expected %08lX, actual %08lX",
      0ul, data, read));
   for (addr=0x2000ul; addr<=0x00400000ul; addr<<=1) {
      if ((err = TestReadPhysical(addr, SPACE_USER, 4, (U8*)&read, FALSE))
         != GOOD) return(err);
      if ((err = Print(DEBUG,"Addr %08lX, data %08lX",addr,read)) != GOOD)
         return(err);
      if (read == data) break;   // found memory wrap point
      if (read != 0) return(Print(FAIL,
         "SAST memory write failure: "
         "offset %08lX, expected %08lX or %08lX, actual %08lX",
         addr, data, 0ul, read));
   }

   if ((err = Print(VERB,"Running ramtst on %luk SAST memory.",addr/1024ul))
      != GOOD) return(err);
   if ((err = SdnRegister(SDN_RDWR_BUFFER, (CALLBACK)RamtstCallback, &desc))
      != GOOD) return(err);
   if ((err = TestRamtstPhysical(0ul,0ul, SPACE_USER, addr,
      DWORD_SIZE, FALSE, &info)) == GOOD) {
      *pass = TRUE;
   }
   err = ProcessRamtstError(err,&info,DWORD_SIZE,abort);
   err2 = SdUnRegister(desc);
   return(err?err:err2);
}

/****************************************************************************
**
** TestMapBkpt
**
** Tests:
**    Map access and write protect breaks.
** 
** Strategy:
**    Clear map.
**    Map low memory to RAM.
**    Run program that reads  at 0.  Check that no break occurs.
**    Run program that writes at 0.  Check that no break occurs.
**    Map low memory to ROM.
**    Run program that reads  at 0.  Check that no break occurs.
**    Run program that writes at 0.  Check that no break occurs.
**    Map low memory to ROMBRK.
**    Run program that reads  at 0.  Check that no break occurs.
**    Run program that writes at 0.  Check that break occurs.
**    Map low memory to NONE.
**    Run program that reads  at 0.  Check that break occurs.
**    Run program that writes at 0.  Check that break occurs.
**
*****************************************************************************/
static MAP_PROTECT protect[4] = { MAP_RAM,MAP_ROM_NOBRK,MAP_ROM,MAP_NOACCESS};
static LPSTR protectText[4]   = { "ram", "rom", "rombrk", "none"  };

RETCODE TestMapBkpt(BOOLEAN *pass, BOOLEAN *abort) {
   RETCODE err;
   static U16 datawr[] = { DOG, WR, JMP, OPEND };
   static U16 datard[] = { DOG, RD, JMP, OPEND };
   static BOOLEAN emonRead[4]   ={TRUE,    TRUE,    TRUE,       FALSE   };
   static BOOLEAN emonWrite[4]  ={TRUE,    TRUE,    FALSE,      FALSE   };

   if ((err = Print(VERB,
      "Map breakpoint test: access rights breakpoints."))
      != GOOD) return(err);
   *abort = FALSE;
   if ((err = SetupResetCode(datard, pass)) != GOOD) return(err);
   if (!*pass) return(GOOD);
   *pass=FALSE;
   if ((err = TestMapBkptRun("read",pass,abort,emonRead)) != GOOD) return(err);
   if (!*pass) return(GOOD);
   if (*abort) return(GOOD);
   *pass=FALSE;
   if ((err = SetupResetCode(datawr,pass)) != GOOD) return(err);
   if (!*pass) return(GOOD);
   *pass=FALSE;
   if ((err = TestMapBkptRun("write",pass,abort,emonWrite))!=GOOD) return(err);
   return(GOOD);
}   

RETCODE PRIVATE TestMapBkptRun(LPSTR op, BOOLEAN *pass, BOOLEAN *abort,
      BOOLEAN *expectedEmon){
   RETCODE err;
   U32 pc;
   BOOLEAN emon;
   LOOP_VAR phase;

   for (phase=0; phase<4; phase++) {
      if ((err = TestMapWrite(1ul,0ul,0x10000ul,TRUE,protect[phase])) != GOOD)
         return(err);
      if ((err = Print(VERB,"Starting emulation.")) != GOOD) return(err);
      if ((err = TestSendCommand(TEST_GR, FALSE)) != GOOD) return(err);
      if ((err = GetPcAndEmonResult(&pc, &emon)) != GOOD) return(err);
      if (emon != expectedEmon[phase]) return(Print(FAIL,
         "Map bkpt failure.  Map=%s, Operation=%s, Expected=%s, Actual=%s.",
         protectText[phase], op,
         expectedEmon[phase] ? "no break" : "break",
         emon ? "no break" : "break"));
      if ((err = TestResetCpu(pass, FALSE)) != GOOD) return(err);
      if (!*pass) return(GOOD);
      *pass=FALSE;
      if ((err = TskCheckAbort(abort)) != GOOD) return(err);
      if (*abort) return(GOOD);
   }
   *pass = TRUE;
   return(GOOD);
}

/****************************************************************************
**
** TestMapRom
**
** Tests:
**    Map write protect for overlay memory.
** 
** Strategy:
**    Clear map.
**    Map low memory to RAM.
**    Set memory at address 0 to 0.
**    Run program that writes pattern at 0.  Check that memory is changed.
**    Map low memory to ROM.
**    Set memory at address 0 to 0.
**    Run program that writes pattern at 0.  Check that memory is not changed.
**    Map low memory to ROMBRK.
**    Set memory at address 0 to 0.
**    Run program that writes pattern at 0.  Check that memory is not changed.
**    Map low memory to NONE.
**    Set memory at address 0 to 0.
**    Run program that writes pattern at 0.  Check that memory is not changed.
**
*****************************************************************************/
RETCODE TestMapRom(BOOLEAN *pass, BOOLEAN *abort) {
   RETCODE err;
   U16 zero=0;
   U8 read[2],expected[2];
   LOOP_VAR phase;
   static U16 datawr[]= { DOG, WR, JMP, OPEND };
   static BOOLEAN change[4]   ={TRUE,    FALSE,   FALSE,      FALSE   };

   if ((err = Print(VERB,
      "Map ROM test:  interception of writes to overlay."))
      != GOOD) return(err);

   if ((err = SetupResetCode(datawr, pass)) != GOOD) return(err);
   if (!*pass) return(GOOD);
   *pass=FALSE;

   for (phase=0; phase<4; phase++) {
      if ((err = TestMapWrite(1ul,0ul,0x10000ul,TRUE,protect[phase])) != GOOD)
         return(err);
      if ((err = TestWritePhysical(0ul, space, sizeof(zero),(U8*)&zero, FALSE))
         != GOOD) return(err);
      if ((err = Print(VERB,"Starting emulation.")) != GOOD) return(err);
      if ((err = TestSendCommand(TEST_GR, FALSE)) != GOOD) return(err);
      if ((err = TestResetCpu(pass, FALSE)) != GOOD) return(err);
      if (!*pass) return(GOOD);
      *pass=FALSE;
      if ((err = TestReadPhysical(0ul, SPACE_USER, 2, read, FALSE))
         != GOOD) return(err);
      expected[0] = (change[phase] ? 0x55 : 0);
      expected[1] = (change[phase] ? 0xaa : 0);
      if ((read[0] != expected[0]) || (read[1] != expected[1]))
         return(Print(FAIL,
         "Map write failure.  Map=%s, Expected=%02X%02X, Actual=%02X%02X.",
         protectText[phase], expected[0], expected[1], read[0], read[1]));
      if ((err = TskCheckAbort(abort)) != GOOD) return(err);
      if (*abort) return(GOOD);
   }
   *pass = TRUE;
   return(GOOD);
}

/****************************************************************************
**
** TestSignalGating
**
** Tests:
**    Signal gates between processor and target.
** 
** Strategy:
**    For each gated signal, try for (enabled, disabled) {
**       Assert signal from SAST.
**       Collect trace.
**       Check trace.
**    }
**
*****************************************************************************/
RETCODE TestSignalGating(BOOLEAN *pass, BOOLEAN *abort) {
   RETCODE err;
   U8 byte;
   S8 section[32];
   *abort = FALSE;
   if ((err = Print(VERB,
      "Signal gating test: interruption of signals from target.")) != GOOD)
      return(err);
   if ((err = CheckSASTConnected(pass)) != GOOD) return(err);
   if (!*pass) return(GOOD);
   if ((err = FloatProcessor(pass)) != GOOD) return(err);
   if (!*pass) return(GOOD);
   *pass = FALSE;

   if ((err = EnableAllSignals()) != GOOD) return(err);

   if ((err = Print(VERB,"Enabling SAST drivers.")) != GOOD) return(err);
   byte = (SAST_ENA | SAST_ENB | SAST_DRIVE_ON);
   if ((err = TestWritePhysical(SAST_PORT, SPACE_PRB_XDATA, 1, &byte, FALSE))
      != GOOD) return(err);

   if ((err = Print(VERB,"Testing signals.")) != GOOD) return(err);
   if ((err = ProcInsertSystemName("[sast %s]",section)) != GOOD) return(err);
   *pass = TRUE;
   if ((err = ConfigFileEnumerate(section, SignalTestCallback,
      abort, pass)) != GOOD) { *pass=FALSE; return(err); }

   if ((err = Print(VERB,"Disabling SAST drivers.")) != GOOD) return(err);
   byte = 0;
   if ((err = TestWritePhysical(SAST_PORT, SPACE_PRB_XDATA, 1, &byte, FALSE))
      != GOOD) return(err);

   return(GOOD);
}

/****************************************************************************
**
** TestTraceAux
**
** Tests:
**    Tracing of auxiliary signals (qualifiers, EMON)
** 
** Strategy:
**    Collect trace with emon off and on.  Verify correct emon state in trace.
**    Collect trace of processor bus cycles.  Verify correct timing of quals.
**
*****************************************************************************/
RETCODE TestTraceAux(BOOLEAN *pass, BOOLEAN *abort) {
   RETCODE err;
   U32 pc;
   BOOLEAN emon;
   LOOP_VAR frame;
   PROC_CPU cpu;
   static U16 data[] = { DOG, NOP, NOP, JMP, OPEND };
   *abort = FALSE;
   if ((err = Print(VERB,
      "Auxiliary trace test: emon and qualifiers.")) != GOOD)
      return(err);

   if ((err = SetupResetCode(data, pass)) != GOOD) return(err);
   if (!*pass) return(GOOD);
   *pass=FALSE;
   if ((err = TestResetCpu(pass, FALSE)) != GOOD) return(err);
   if (!*pass) return(GOOD);
   *pass=FALSE;
   if ((err = CollectTrace(1,FALSE)) != GOOD) return(err);
   if ((trace[0].sGroup & 0x10ul) != 0) return(Print(FAIL,
      "EMON trace failure: expected 0, actual 1."));

   if ((err = TestSendCommand(TEST_GR, FALSE)) != GOOD) return(err);
   if ((err = GetPcAndEmonResult(&pc, &emon)) != GOOD) return(err);
   if (!emon) return(Print(FAIL,"GR did not turn on emulation."));
   if ((err = CollectTrace(NUM_TEST_FRAMES, FALSE)) != GOOD) return(err);
   if ((trace[0].sGroup & 0x10ul) == 0) return(Print(FAIL,
      "EMON trace failure: expected 1, actual 0."));
   
   if ((err = ProcReturnCpu(&cpu)) != GOOD) return(err);

   if ((cpu == PROC_CPU_CPU32) || (cpu == PROC_CPU_CPU16)) {
      /*
      ** Trace expected:
      **    strobe  AQUAL   FQUAL
      **     on       on      off
      **     ...      X       X
      **     off      off     on
      **     ...
      */
      /* find inactive strobe */
      for (frame=0; frame<NUM_TEST_FRAMES; frame++) {
         if ((trace[frame].sGroup & qual.strobeBit) != qual.strobeActive)
            break;
      }
      if (frame == NUM_TEST_FRAMES) return(Print(FAIL,
         "No bus cycles captured in trace."));
      /* find next active strobe */
      for ( ; frame<NUM_TEST_FRAMES; frame++) {
         if ((trace[frame].sGroup & qual.strobeBit) == qual.strobeActive)
            break;
      }
      if (frame == NUM_TEST_FRAMES) return(Print(FAIL,
         "No bus cycles captured in trace."));
      if ((trace[frame].sGroup & qual.aqBit) != qual.aqActive)
         return(Print(FAIL,
         "AQUAL trace failure: frame %ld, expected %u, actual %u.",
         trace[frame].frameNumber,
         qual.aqActive, trace[frame].sGroup&qual.aqBit));
      if ((trace[frame].sGroup & qual.fqBit) !=qual.fqInactive)
         return(Print(FAIL,
         "FQUAL trace failure: frame %ld, expected %u, actual %u.",
         trace[frame].frameNumber,
         qual.fqInactive, trace[frame].sGroup&qual.fqBit));

      /* Find next inactive strobe */
      for ( ; frame<NUM_TEST_FRAMES; frame++) {
         if ((trace[frame].sGroup & qual.strobeBit) != qual.strobeActive)
            break;
      }
      if (frame == NUM_TEST_FRAMES) return(Print(FAIL,
         "No bus cycles captured in trace."));
      if ((trace[frame].sGroup & qual.aqBit) !=qual.aqInactive)
         return(Print(FAIL,
         "AQUAL trace failure: frame %ld, expected %u, actual %u.",
         trace[frame].frameNumber,
         qual.aqInactive, trace[frame].sGroup&qual.aqBit));
      if ((trace[frame].sGroup & qual.fqBit) != qual.fqActive)
         return(Print(FAIL,
         "FQUAL trace failure: frame %ld, expected %u, actual %u.",
         trace[frame].frameNumber,
         qual.fqActive, trace[frame].sGroup&qual.fqBit));
   } else if (cpu == PROC_CPU_80386) {
      /*
      ** Trace expected:
      **    strobe  AQUAL   FQUAL
      **     on       on      off
      **     off      off     off
      **     ...      off     off
      **     off      off     on
      */
      /* find inactive strobe */
      for (frame=0; frame<NUM_TEST_FRAMES; frame++) {
         if ((trace[frame].sGroup & qual.strobeBit) != qual.strobeActive)
            break;
      }
      if (frame == NUM_TEST_FRAMES) return(Print(FAIL,
         "No bus cycles captured in trace."));
      /* find next active strobe */
      for ( ; frame<NUM_TEST_FRAMES; frame++) {
         if ((trace[frame].sGroup & qual.strobeBit) == qual.strobeActive)
            break;
      }
      if (frame == NUM_TEST_FRAMES) return(Print(FAIL,
         "No bus cycles captured in trace."));
      if ((trace[frame].sGroup & qual.aqBit) != qual.aqActive)
         return(Print(FAIL,
         "AQUAL trace failure: frame %ld, expected %u, actual %u.",
         trace[frame].frameNumber,
         qual.aqActive, trace[frame].sGroup&qual.aqBit));
      if ((trace[frame].sGroup & qual.fqBit) !=qual.fqInactive)
         return(Print(FAIL,
         "FQUAL trace failure: frame %ld, expected %u, actual %u.",
         trace[frame].frameNumber,
         qual.fqInactive, trace[frame].sGroup&qual.fqBit));

      /* Go till next strobe or AQUAL (errors) or active FQUAL (ok) */
      frame++;
      for ( ; frame<NUM_TEST_FRAMES; frame++) {
         if ((trace[frame].sGroup & qual.strobeBit) == qual.strobeActive)
            return(Print(FAIL,
            "FQUAL trace failure: frame %ld.  ADS# recurred without FQUAL.",
            trace[frame].frameNumber));
         if ((trace[frame].sGroup & qual.aqBit) == qual.aqActive)
            return(Print(FAIL,
            "AQUAL trace failure: frame %ld, expected %u, actual %u.",
            trace[frame].frameNumber,
            qual.aqInactive, trace[frame].sGroup&qual.aqBit));
         if ((trace[frame].sGroup & qual.fqBit) == qual.fqActive) break;
      }
      if (frame == NUM_TEST_FRAMES) return(Print(FAIL,
         "No bus cycles captured in trace."));
   }

   *pass = TRUE;
   return(GOOD);
}


/*|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
  ||                           Support functions                           ||
  |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||*/

/****************************************************************************
**
** TicWrite1Bit
** TicRead1Bit
**
** Shift one bit in or out of the TIC chip chain.
**
*****************************************************************************/
RETCODE PRIVATE TicWrite1Bit(U8 p3in, U8 bit) {
   RETCODE err;
   U8 p3 = (p3in & ~TIC_CLK & ~TIC_DI) | (bit ? TIC_DI : 0);
   if ((err = TestWritePhysical(3, SPACE_PRB_SFR, 1, &p3, FALSE)) != GOOD)
      return(err);
   p3 = (p3 | TIC_CLK);
   if ((err = TestWritePhysical(3, SPACE_PRB_SFR, 1, &p3, FALSE)) != GOOD)
      return(err);
   return(GOOD);
}

RETCODE PRIVATE TicRead1Bit(U8 p3in, U8 *bit) {
   RETCODE err;
   U8 p3;
   if ((err = TestReadPhysical(3, SPACE_PRB_SFR, 1, &p3, FALSE)) != GOOD)
      return(err);
   *bit = ((p3 & TIC_DO) ? 1 : 0);
   p3 = (p3in & ~TIC_CLK & ~TIC_DI);
   if ((err = TestWritePhysical(3, SPACE_PRB_SFR, 1, &p3, FALSE)) != GOOD)
      return(err);
   p3 = (p3 | TIC_CLK);
   if ((err = TestWritePhysical(3, SPACE_PRB_SFR, 1, &p3, FALSE)) != GOOD)
      return(err);
   return(GOOD);
}

/****************************************************************************
**
** SastWrite1Bit
** SastRead1Bit
**
** Shift one bit in or out of the SAST shift chain.
**
*****************************************************************************/
RETCODE PRIVATE SastWrite1Bit(U8 bit) {
   return(TestWritePhysical(SAST_SER, SPACE_PRB_XDATA, 1, &bit, FALSE));
}

RETCODE PRIVATE SastRead1Bit(U8 *bit) {
   RETCODE err;
   if ((err = TestReadPhysical(SAST_SER, SPACE_PRB_XDATA, 1, bit, FALSE))
      != GOOD) return(err);
   if ((err = TestWritePhysical(SAST_SER, SPACE_PRB_XDATA, 1, bit, FALSE))
      != GOOD) return(err);
   return(GOOD);
}

/****************************************************************************
**
** ProcessRamtstError
**
** Interpret errors from ramtsts--memory failure and abort are special.
** Print error info if memory failure.
**
*****************************************************************************/
RETCODE PRIVATE ProcessRamtstError(RETCODE err, RAMTST_INFO *info,
      ACCESS_SIZE access, BOOLEAN *abort) {
   if (err == ER_TEST_ABORT) {
      *abort = TRUE;
      err = GOOD;
   } else if (err == ER_MEMORY_VERIFY) {
      switch (access) {
         case BYTE_SIZE:
            Print(FAIL,
               "Memory failure at %08lXp, expected: %02lX, actual: %02lX.",
               info->offset, info->expected&0xfful, info->actual&0xfful);
            break;
         case WORD_SIZE:
            Print(FAIL,
               "Memory failure at %08lXp, expected: %04lX, actual: %04lX.",
               info->offset, info->expected&0xfffful, info->actual&0xfffful);
            break;
         default:
            Print(FAIL,
               "Memory failure at %08lXp, expected: %08lX, actual: %08lX.",
               info->offset, info->expected, info->actual);
            break;
      }
      err = GOOD;
   }
   return(err);
}

/****************************************************************************
**
** RamtstCallback
**
** Prints current phase of test
**
*****************************************************************************/
VOID FAR PASCAL RamtstCallback(DESCRIPTOR desc) {
   U16 phase;
   if (SdReadPartialMember(desc, 0, sizeof(phase), (U8*)&phase) == GOOD) {
      Print(DEBUG,"Phase %u.",phase);
   }
}

/****************************************************************************
**
** InitializeSequencer
**
** Return sequencer and trigger hardware to default state.
**
*****************************************************************************/
RETCODE PRIVATE InitializeSequencer(VOID) {
   RETCODE err,err2;
   DESCRIPTOR desc;
   if ((err = TrcTracingSet(FALSE)) != GOOD) return(err);
   if ((err = TrigTriggerOpen(&desc, NULL, "default")) != GOOD) return(err);
   err = TrigTriggerClear(desc);
   if (!err) err = TrigTriggerProgram();
   err2 = TrigTriggerClose(desc);
   return(err?err:err2);
}

/****************************************************************************
**
** CollectTrace
**
** Collect and store specified number of frames.  Ignores EMON in all cases.
**
*****************************************************************************/
RETCODE PRIVATE CollectTrace(U32 numFrames, BOOLEAN tricTest) {
   RETCODE err,err2;
   DESCRIPTOR trcDesc;
   DESCRIPTOR trgDesc;
   LPSTR rawTrace;
   U32 actual;
   U8 byte;
   if (numFrames > NUM_TEST_FRAMES) return(ER_TOO_MANY_FRAMES);

   if ((err = Print(DEBUG,"Setting up trace logic.")) != GOOD) return(err);
   if ((err = TrcTracingSet(FALSE)) != GOOD) return(err);
   if ((err = TrcTraceOpen(&trcDesc, "hwtrc", CLOCK_CYCLE, TRIGGER_ALIGN))
      != GOOD) return(err);
   if ((err = TrigTriggerOpen(&trgDesc, NULL, "default")) != GOOD) {
      TrcTraceClose(trcDesc);
      return(err);
   }
   if ((err = TrigTriggerClear(trgDesc)) != GOOD) goto CLEANUP;
   if ((err = TrigIgnoreEmonSet(trgDesc,TRUE)) != GOOD) goto CLEANUP;
   if ((err = TrcDebugEmonSet(trcDesc,TRUE)) != GOOD) goto CLEANUP;

   if ((err = Print(DEBUG,"Starting trace.")) != GOOD) goto CLEANUP;
   if ((err = TrcTracingSet(TRUE)) != GOOD) goto CLEANUP;
   if (tricTest) {
      if ((err = Print(DEBUG,"Setting TRICs to test mode.")) != GOOD)
         goto CLEANUP;
      byte = 0;   // Set TRIC test mode
      if ((err = TestWritePhysical(0x2104ul, SPACE_MOM_IO, 1, &byte, FALSE))
         != GOOD) goto CLEANUP;
   }
   if ((err = Print(DEBUG,"Stopping trace.")) != GOOD) goto CLEANUP;
   if ((err = TrcTracingSet(FALSE)) != GOOD) goto CLEANUP;
   if ((err = TrcReadFrameSet(trcDesc, 1L-numFrames)) != GOOD) goto CLEANUP;
   if ((err = TrcTraceReadRaw(trcDesc, numFrames, &actual, &rawTrace)) != GOOD)
      goto CLEANUP;
   if (actual == numFrames) {
      int i;
      memcpy(trace, rawTrace, (size_t)(numFrames*sizeof(TRACE_INFO)));
      for (i=0; i<numFrames; i++) {
         if ((err = Print(DEBUG,"Frame %3ld: %08lX %08lX %08lX",
            trace[i].frameNumber,trace[i].rGroup,trace[i].sGroup,
            trace[i].tGroup)) != GOOD) break;
      }
   }
   else 
      err = ER_END_OF_BUFFER;
   TFree(rawTrace);

CLEANUP:
   err2 = TrcTraceClose(trcDesc);
   if (!err) err = err2;
   err2 = TrigTriggerClose(trgDesc);
   if (!err) err = err2;
   if (tricTest) {
      U8 byte;
      err2 = Print(VERB,"Setting TRICs to run mode.");
      if (!err) err = err2;
      err2 = TestReadPhysical(0x2114ul, SPACE_MOM_IO, 1, &byte, FALSE);
      if (!err) err = err2;
   }
   return(err);
}

/****************************************************************************
**
** CheckTestTrace
**
** Compare stored trace against expected pattern for TIC or TRIC in test mode.
** Print any discrepencies at message level VERBOSE.
**
*****************************************************************************/
RETCODE PRIVATE CheckTestTrace(BOOLEAN *pass) {
   U32 r,s,t,g;
   U16 frame;
   for (frame=1; frame<NUM_TEST_FRAMES; frame++) {
      if ((trace[frame].rGroup & 0xfful) == 0ul) break;
   }
   if (frame==NUM_TEST_FRAMES)
      return(Print(FAIL,"Trace failure:  no zero frame found."));
   r = 0ul;
   g = trace[frame].sGroup & 0xfful;
   s = g | (g<<8) | (g<<16) | (g<<24);
   g = trace[frame].tGroup & 0xfful;
   t = g | (g<<8) | (g<<16) | (g<<24);
   for ( ; frame<NUM_TEST_FRAMES; frame++) {
      if (r != trace[frame].rGroup) {
         return(Print(FAIL,
            "Trace failure in group R, expected %08lX, actual: %08lX",
            r, trace[frame].rGroup));
      }
      if (s != trace[frame].sGroup) {
         return(Print(FAIL,
            "Trace failure in group S, expected %08lX, actual: %08lX",
            s, trace[frame].sGroup));
      }
      if (t != trace[frame].tGroup) {
         return(Print(FAIL,
            "Trace failure in group T, expected %08lX, actual: %08lX",
            t, trace[frame].tGroup));
      }
      if (r==0ul) r=0x01010101ul;
      else if (r==0x80808080ul) r=0ul;
      else r<<=1;
      if (s==0ul) s=0x01010101ul;
      else if (s==0x80808080ul) s=0ul;
      else s<<=1;
      if (t==0ul) t=0x01010101ul;
      else if (t==0x80808080ul) t=0ul;
      else t<<=1;
   }
   *pass = TRUE;
   return(GOOD);
}

/****************************************************************************
**
** TestSastCtrlWrite
**
** Write byte to sast control register, then verify
**
*****************************************************************************/
RETCODE PRIVATE TestSastCtrlWrite(U8 byte, BOOLEAN *pass) {
   RETCODE err;
   U8 read;
   *pass = FALSE;
   if ((err = Print(DEBUG,"Write %02X.",byte)) != GOOD) return(err);
   if ((err = TestWritePhysical(SAST_PORT, SPACE_PRB_XDATA, 1, &byte, FALSE))
      != GOOD) return(err);
   if ((err = TestReadPhysical(SAST_PORT, SPACE_PRB_XDATA, 1, &read, FALSE))
      != GOOD) return(err);
   if ((err = Print(DEBUG,"Read  %02X.",read)) != GOOD) return(err);
   if ((read & SAST_WRITE_MASK) != (byte & SAST_WRITE_MASK))
      return(Print(FAIL,
        "SAST control register failure: expected %02X, actual %02X.",
        (byte & SAST_WRITE_MASK), (read & SAST_WRITE_MASK)));
   *pass = TRUE;
   return(GOOD);
}

/****************************************************************************
**
** CheckSASTConnected
**
** Test SAST control port writability and cable connection.
**
*****************************************************************************/
RETCODE PRIVATE CheckSASTConnected(BOOLEAN *pass) {
   RETCODE err;
   U8 byte;
   *pass = FALSE;
   if (sastDepth == 0) return(Print(VERB,
      "System does not have SAST capability."));
   if ((err = Print(VERB,"Checking SAST control register.")) != GOOD)
      return(err);
   if ((err = TestSastCtrlWrite(0,pass)) != GOOD) return(err);
   if (!*pass) return(GOOD);
   if ((err = TestSastCtrlWrite(SAST_ENA,pass)) != GOOD) return(err);
   if (!*pass) return(GOOD);
   if ((err = TestSastCtrlWrite(SAST_ENB,pass)) != GOOD) return(err);
   if (!*pass) return(GOOD);
   *pass = FALSE;
   if ((err = Print(VERB,"Checking SAST cable plug-in.")) != GOOD) return(err);
   if ((err = TestReadPhysical(SAST_PORT, SPACE_PRB_XDATA, 1, &byte, FALSE))
      != GOOD) return(err);
   if ((err = Print(DEBUG,"Control register=%02X",byte)) != GOOD) return(err);
   if ((byte & SAST_SENSEB) == 0)
      return(Print(FAIL,"SAST control cable reversed."));
   if ((byte & SAST_SENSE) != 0)
      return(Print(FAIL,"SAST control cable not connected."));
   *pass = TRUE;
   return(GOOD);
}

/****************************************************************************
**
** SASTConnectCallback
**
** Enumeration function for target connect test.
** value is in the form "bit#, numbits, tracebit, ..."
**
*****************************************************************************/
RETCODE EXPORT SASTConnectCallback(LPSTR key, LPSTR value, BOOLEAN *abort,
      VOID *pass) {
   RETCODE err;
   LPSTR token;
   U16 bitNumber, fieldSize, traceBit, fieldStart;
   U32 rGroup, sGroup, tGroup;
   U16 bit;
   U8 sastData[MAX_SAST_BYTES];
   
   if (!*((BOOLEAN*)pass)) return(GOOD);   /* failed earlier */
   *((BOOLEAN*)pass) = FALSE;

   if ((token = strtok(value, ",")) == NULL)
      return(Print(FAIL,"Config file format error for signal %s.",key));
   bitNumber = (U16)strtoul(token, NULL, 0);
   if ((token = strtok(NULL, ",\n")) == NULL)
      return(Print(FAIL,"Config file format error for signal %s.",key));
   fieldSize = (U16)strtoul(token, NULL, 0);
   if ((token = strtok(NULL, ",\n")) == NULL) {
      *((BOOLEAN*)pass) = TRUE;       /* This sast bit has no trace */
      return(GOOD);
   }
   traceBit = (U16)strtoul(token, NULL, 0);
   if ((token = strtok(NULL, ",\n")) != NULL) {
      fieldStart=(U16)strtoul(token, NULL, 0);
   } else fieldStart=0;

   for (bit=bitNumber; bit<bitNumber+fieldSize; bit++) {
      U16 tbit = traceBit+bit-bitNumber;
      if (fieldSize==1) {
         if ((err = Print(VERB,"Checking field %s (bit %u).", key, bit))
            != GOOD) return(err);
      } else {
         if ((err = Print(VERB,"Checking field %s.%u (bit %u).", key,
            fieldStart+bit-bitNumber,bit)) != GOOD) return(err);
      }
      memset(sastData,0,sizeof(sastData));
      rGroup = sGroup = tGroup = 0ul;
      if (!adsFound || (bit != adsBit)) {
         sastData[bit/8] |= (1 << (bit%8));
         rGroup = (tbit<32) ? (1ul<<tbit) : 0ul;
         sGroup = ((tbit>=32) && (tbit<64)) ? (1ul<<(tbit-32)) : 0ul;
         tGroup = (tbit>=64) ? (1ul<<(tbit-64)) : 0ul;
      }
      if (adsFound && (bit != adsBit)) {
         sastData[adsBit/8] |= (1 << (adsBit%8));
         rGroup |= (adsTbit<32) ? (1ul<<adsTbit) : 0ul;
         sGroup |= ((adsTbit>=32) && (adsTbit<64)) ? (1ul<<(adsTbit-32)) : 0ul;
         tGroup |= (adsTbit>=64) ? (1ul<<(adsTbit-64)) : 0ul;
      }
      if ((err = TestWritePhysical(0, SPACE_SAST, sastDepth, sastData, FALSE))
         != GOOD) return(err);
      if ((err = CollectTrace(1, FALSE)) != GOOD) return(err);
      if (((trace[0].rGroup & rMask) != rGroup)
            || ((trace[0].sGroup & sMask) != sGroup)
            || ((trace[0].tGroup & tMask) != tGroup)) {
         if ((err = Print(FAIL,"Trace failure: bit %u (%s):",bit,key)) != GOOD)
            return(err);
         if ((err = Print(FAIL,"  Expected %08lX %08lX %08lX",
            rGroup, sGroup, tGroup)) != GOOD) return(err);
         if ((err = Print(FAIL,"  Actual   %08lX %08lX %08lX",
            trace[0].rGroup & rMask, trace[0].sGroup & sMask,
            trace[0].tGroup & tMask)) != GOOD) return(err);
         return(GOOD);
      }
      if ((err = TskCheckAbort(abort)) != GOOD) return(err);
      if (*abort) return(GOOD);
   }
   *((BOOLEAN*)pass) = TRUE;
   return(GOOD);
}

/****************************************************************************
**
** ProcConnectInputCallback
**
** Enumeration function for processor input connect test.
** value is in the form "sastbit, numbits, jtagbit, jtagDelta"
**
*****************************************************************************/
RETCODE EXPORT ProcConnectInputCallback(LPSTR key, LPSTR value, BOOLEAN *abort,
      VOID *pass) {
   RETCODE err;
   LPSTR token;
   U16 sastBit, fieldSize, jtagBit, jtagBytes, fieldStart;
   S16 jtagDelta;
   U16 bit;
   U8 sastData[MAX_SAST_BYTES];
   U8 jtagData[MAX_JTAG_BYTES];
   U8 testData[MAX_JTAG_BYTES];
   S8 buf[MAX_JTAG_BYTES*3+1];
   S8 *bptr;
   LOOP_VAR i;
   
   if (!*((BOOLEAN*)pass)) return(GOOD);   /* failed earlier */
   *((BOOLEAN*)pass) = FALSE;

   jtagBytes = (7+jtagDepth)/8;
   if ((token = strtok(value, ",")) == NULL)
      return(Print(FAIL,"Config file format error for signal %s.",key));
   sastBit = (U16)strtoul(token, NULL, 0);
   if ((token = strtok(NULL, ",\n")) == NULL)
      return(Print(FAIL,"Config file format error for signal %s.",key));
   fieldSize = (U16)strtoul(token, NULL, 0);
   if ((token = strtok(NULL, ",\n")) == NULL) {
      *((BOOLEAN*)pass) = TRUE;       /* This sast bit has no jtag */
      return(GOOD);
   }
   jtagBit = (U16)strtoul(token, NULL, 0);
   if ((token = strtok(NULL, ",\n")) != NULL) {
      jtagDelta = (S16)strtol(token, NULL, 0);
   } else jtagDelta = 1;
   if ((token = strtok(NULL, ",\n")) != NULL) {
      fieldStart=(U16)strtoul(token, NULL, 0);
   } else fieldStart=0;

   memset(sastData,0,sizeof(sastData));
   if ((err = TestWritePhysical(0, SPACE_SAST, sastDepth, sastData, FALSE))
      != GOOD) return(err);
   if ((err = ReadJtag(jtagData)) != GOOD) return(err);
   for (bptr=buf,i=0; i<jtagBytes; i++) {
      bptr += sprintf(bptr,"%02X ",jtagData[i]);
   }
   if ((err = Print(DEBUG,"Init   %s",buf)) != GOOD) return(err);

   for (bit=sastBit; bit<sastBit+fieldSize; bit++) {
      U16 jbit = jtagBit+(jtagDelta*(bit-sastBit));
      if (fieldSize==1) {
         if ((err = Print(VERB,"Checking field %s (bit %u).", key, bit))
            != GOOD) return(err);
      } else {
         if ((err = Print(VERB,"Checking field %s.%u (bit %u).", key,
            fieldStart+bit-sastBit,bit)) != GOOD) return(err);
      }
      memset(sastData,0,sizeof(sastData));
      memset(testData,0,sizeof(testData));
      sastData[bit/8] |= (1 << (bit%8));
      testData[jbit/8] |= (1 << (jbit%8)) & jtagMask[jbit/8];
      if ((err = TestWritePhysical(0, SPACE_SAST, sastDepth, sastData, FALSE))
         != GOOD) return(err);
      if ((err = ReadJtag(jtagData)) != GOOD) return(err);
      for (i=0;i<sizeof(jtagData);i++) jtagData[i] &= jtagMask[i];
      for (bptr=buf,i=0; i<1+jtagDepth/8; i++) {
         bptr += sprintf(bptr,"%02X ",jtagData[i]);
      }
      if ((err = Print(DEBUG,"Read   %s",buf)) != GOOD) return(err);
      if(memcmp(testData,jtagData,sizeof(jtagData)) != 0) {
         if ((err = Print(FAIL,"Connect failure: bit %u (%s):",bit,key))
            != GOOD) return(err);
         for (bptr=buf,i=0; i<1+jtagDepth/8; i++) {
            bptr += sprintf(bptr,"%02X ",testData[i]);
         }
         if ((err = Print(FAIL,"Expected   %s",buf)) != GOOD) return(err);
         for (bptr=buf,i=0; i<1+jtagDepth/8; i++) {
            bptr += sprintf(bptr,"%02X ",jtagData[i]);
         }
         if ((err = Print(FAIL,"  Actual   %s",buf)) != GOOD) return(err);
         return(GOOD);
      }
      if ((err = TskCheckAbort(abort)) != GOOD) return(err);
      if (*abort) return(GOOD);
   }
   *((BOOLEAN*)pass) = TRUE;
   return(GOOD);
}

/****************************************************************************
**
** ProcConnectOutputCallback
**
** Enumeration function for processor output connect test.
** value is in the form "sastbit, numbits, jtagbit, jtagDelta"
**
*****************************************************************************/
#pragma argsused
RETCODE EXPORT ProcConnectOutputCallback(LPSTR key, LPSTR value,BOOLEAN *abort,
      VOID *pass) {
   RETCODE err;
   LPSTR token;
   U16 sastBit, jtagBit, fieldSize, traceBit, fieldStart;
   S16 jtagDelta;
   U32 rGroup, sGroup, tGroup;
   U16 bit;
   U8 jtagData[MAX_JTAG_BYTES];
   S8 buf[MAX_JTAG_BYTES*3+1];
   S8 *bptr;
   LOOP_VAR i;
   
   if (!*((BOOLEAN*)pass)) return(GOOD);   /* failed earlier */
   *((BOOLEAN*)pass) = FALSE;

   if ((token = strtok(value, ",")) == NULL)
      return(Print(FAIL,"Config file format error for signal %s.",key));
   sastBit = (U16)strtoul(token, NULL, 0);
   if ((token = strtok(NULL, ",\n")) == NULL)
      return(Print(FAIL,"Config file format error for signal %s.",key));
   fieldSize = (U16)strtoul(token, NULL, 0);
   if ((token = strtok(NULL, ",\n")) == NULL) {
      return(Print(FAIL,"Config file format error for signal %s.",key));
   }
   jtagBit = (U16)strtoul(token, NULL, 0);
   if ((token = strtok(NULL, ",\n")) == NULL) {
      *((BOOLEAN*)pass) = TRUE;       /* This sast bit has no trace */
      return(GOOD);
   }
   traceBit = (U16)strtoul(token, NULL, 0);
   if ((token = strtok(NULL, ",\n")) != NULL) {
      jtagDelta = (S16)strtol(token, NULL, 0);
   } else jtagDelta = 1;
   if ((token = strtok(NULL, ",\n")) != NULL) {
      fieldStart=(U16)strtoul(token, NULL, 0);
   } else fieldStart=0;

   for (bit=sastBit; bit<sastBit+fieldSize; bit++) {
      U16 tbit = traceBit+bit-sastBit;
      U16 jbit = jtagBit+(jtagDelta*(bit-sastBit));
      if (fieldSize==1) {
         if ((err = Print(VERB,"Checking field %s (bit %u).", key, bit))
            != GOOD) return(err);
      } else {
         if ((err = Print(VERB,"Checking field %s.%u (bit %u).", key,
            fieldStart+bit-sastBit,bit)) != GOOD) return(err);
      }
      memcpy(jtagData,jtagInitData,sizeof(jtagData));
      rGroup = sGroup = tGroup = 0ul;
      jtagData[jbit/8] |= (1 << (jbit%8));
      for (bptr=buf,i=0; i<(7+jtagDepth)/8; i++) {
         bptr += sprintf(bptr,"%02X ",jtagData[i]);
      }
      if ((err = Print(DEBUG,"Write  %s",buf)) != GOOD) return(err);
      rGroup = (tbit<32) ? (1ul<<tbit) : 0ul;
      sGroup = ((tbit>=32) && (tbit<64)) ? (1ul<<(tbit-32)) : 0ul;
      tGroup = (tbit>=64) ? (1ul<<(tbit-64)) : 0ul;
      if ((err = WriteJtag(jtagData)) != GOOD) return(err);
      if ((err = CollectTrace(1, FALSE)) != GOOD) return(err);
      if (((trace[0].rGroup & jrMask) != rGroup)
            || ((trace[0].sGroup & jsMask) != sGroup)
            || ((trace[0].tGroup & jtMask) != tGroup)) {
         if ((err = Print(FAIL,"Trace failure: bit %u (%s):",bit,key)) != GOOD)
            return(err);
         if ((err = Print(FAIL,"  Expected %08lX %08lX %08lX",
            rGroup, sGroup, tGroup)) != GOOD) return(err);
         if ((err = Print(FAIL,"  Actual   %08lX %08lX %08lX",
            trace[0].rGroup & jrMask, trace[0].sGroup & jsMask,
            trace[0].tGroup & jtMask)) != GOOD) return(err);
         return(GOOD);
      }
      if ((err = TskCheckAbort(abort)) != GOOD) return(err);
      if (*abort) return(GOOD);
   }
   *((BOOLEAN*)pass) = TRUE;
   return(GOOD);
}

RETCODE PRIVATE ReadJtag(U8 *data) {
   RETCODE err;
   U8 samppre = 1;
   U8 zero[MAX_JTAG_BYTES];
   memset(zero,0,sizeof(zero));
   if ((err = SdnWritePartialMember(SDN_TEST_BUFFER,0,1,(U8*)&samppre,GOOD))
      != GOOD) return(err);
   if ((err = TestSendCommand(TEST_JTAG_WRITE_IR, FALSE)) != GOOD) return(err);
   if ((err = SdnWritePartialMember(SDN_TEST_BUFFER,0,(7+jtagDepth)/8,zero,
      GOOD)) != GOOD) return(err);
   if ((err = TestSendCommand(TEST_JTAG_EXCHANGE_DR, FALSE)) != GOOD)
      return(err);
   if ((err = SdnReadPartialMember(SDN_TEST_BUFFER,0,(7+jtagDepth)/8,data))
      != GOOD) return(err);
   return(GOOD);
}

RETCODE PRIVATE WriteJtag(U8 *data) {
   RETCODE err;
   U8 extest = 0;
   if ((err = SdnWritePartialMember(SDN_TEST_BUFFER,0,1,(U8*)&extest,GOOD))
      != GOOD) return(err);
   if ((err = TestSendCommand(TEST_JTAG_WRITE_IR, FALSE)) != GOOD) return(err);
   if ((err = SdnWritePartialMember(SDN_TEST_BUFFER,0,(7+jtagDepth)/8,data,
      GOOD)) != GOOD) return(err);
   if ((err = TestSendCommand(TEST_JTAG_EXCHANGE_DR, FALSE)) != GOOD)
      return(err);
   return(GOOD);
}

/****************************************************************************
**
** FloatProcessor
**
** Set bondout to float mode, check for success.
**
*****************************************************************************/
RETCODE PRIVATE FloatProcessor(BOOLEAN *pass) {
   RETCODE err;
   U8 byte;
   *pass = FALSE;
   if ((err = Print(VERB,"Disabling processor.")) != GOOD) return(err);
   byte = TARG_FORCE_EFLT;
   if ((err = TestWritePhysical(TARG_STATUS_PORT, SPACE_PRB_XDATA, 1, &byte,
      FALSE)) != GOOD) return(err);
   if ((err = TestReadPhysical(TARG_STATUS_PORT, SPACE_PRB_XDATA, 1, &byte,
      FALSE)) != GOOD) return(err);
   if ((byte & TARG_EFLT) != 0)
      return(Print(FAIL,"Bondout FLT# pin failure: expected 0, actual 1."));
   *pass = TRUE;
   return(GOOD);
}

/****************************************************************************
**
** ClearSASTShift
**
** Write all 0's to SAST shift register.
**
*****************************************************************************/
RETCODE PRIVATE ClearSASTShift(VOID) {
   RETCODE err;
   U8 sastData[MAX_SAST_BYTES];
   memset(sastData,0,sizeof(sastData));
   if ((err = TestWritePhysical(0, SPACE_SAST, sastDepth, sastData, FALSE))
      != GOOD) return(err);
   return(GOOD);
}

/****************************************************************************
**
** SetSASTBit
**
** Set one bit in sast shift register.
**
*****************************************************************************/
RETCODE PRIVATE SetSASTBit(LPSTR name, U8 value, U16 *bitNumber) {
   RETCODE err;
   S8 section[32];
   S8 valString[32];
   U16 bit;
   if ((err = ProcInsertSystemName("[sast %s]",section)) != GOOD) return(err);
   if ((err = ConfigFileRead(section, name, valString)) != GOOD) return(err);
   if (*valString == '\0') return(GOOD);  // bit is not in config file.
   bit = (U16)strtoul(valString,NULL,0);
   if ((err = TestWritePhysical(bit,SPACE_SAST,1,&value,FALSE)) != GOOD)
      return(err);
   if (bitNumber) *bitNumber = bit;
   return(GOOD);
}

/****************************************************************************
**
** TestMapClear
**
** Set map hardware to Target RAM.
**
*****************************************************************************/
RETCODE TestMapClear(VOID) {
   RETCODE err;
   if ((err = Print(VERB,"Mapping all memory to target as ram.")) != GOOD)
      return(err);
   if ((err = TestSendCommand(TEST_CLEARMAP, FALSE)) != GOOD) return(err);
   return(GOOD);
}

/****************************************************************************
**
** TestMapWrite
**
** Set map hardware.
**
*****************************************************************************/
RETCODE TestMapWrite(U32 block, U32 addr, U32 length, BOOLEAN enable,
      MAP_PROTECT protect) {
   RETCODE err;
   TEST_WRITEMAP_PARAMS params;
   LPSTR protText;
   memset(&params, 0, sizeof(params));
   params.block = block;
   params.addr = addr;
   params.length = length;
   params.type.protect = protect;
   params.enable = enable;
   switch (protect) {
      case MAP_RAM:       protText = "ram";    break;
      case MAP_ROM_NOBRK: protText = "rom";    break;
      case MAP_ROM:       protText = "rombrk"; break;
      case MAP_NOACCESS:  protText = "none";   break;
      default:            protText = "";       break;
   }
   if ((err = Print(VERB,"Mapping %luk %s memory at 0x%08lX as %s.",
      length/1024ul, (enable ? "overlay" : "target"), addr, protText)) != GOOD)
      return(err);
   if ((err = SdnWritePartialMember(SDN_TEST_BUFFER,0,sizeof(params),
      (U8*)&params, GOOD)) != GOOD) return(err);
   if ((err = TestSendCommand(TEST_WRITEMAP, FALSE)) != GOOD) return(err);
   return(GOOD);
}

/****************************************************************************
**
** StartStopEmul
**
** Start, then stop emulation.  Check that emulation really started and
** stopped and that the pc is the value expected.
**
*****************************************************************************/
RETCODE PRIVATE StartStopEmul(TEST_COMMAND cmd, U32 expectedPc, BOOLEAN *pass,
      BOOLEAN looping) {
   RETCODE err;
   U32 pc;
   BOOLEAN emon1, emon2;
   if ((err = Print(VERB,"Executing start/stop emulation.")) != GOOD)
      return(err);
   if ((err = TestSendCommand(cmd, looping)) != GOOD) return(err);
   if ((err = GetPcAndEmonResult(&pc, &emon1)) != GOOD) return(err);
   if ((err = SdnReadPartialMember(SDN_TEST_BUFFER,5,1,(U8*)&emon2)) != GOOD)
      return(err);
   if (!emon2) return(Print(FAIL,"Go did not start emulation."));
   if ( emon1) return(Print(FAIL,"Halt did not stop emulation."));
   if (pc != expectedPc) return(Print(FAIL,
      "Incorrect pc after halt: expected %08lX, actual %08lX", expectedPc,pc));
   *pass = TRUE;
   return(GOOD);
}

/****************************************************************************
**
** ResetCpu
**
** Reset processor, check that emulation is off.  Loop if so specified.
**
*****************************************************************************/
RETCODE PRIVATE TestResetCpu(BOOLEAN *pass, BOOLEAN looping) {
   RETCODE err;
   U32 pc;
   BOOLEAN emon;
   if ((err = Print(VERB,"Resetting processor.")) != GOOD)
      return(err);
   if ((err = TestSendCommand(TEST_RESETCPU, looping)) != GOOD) return(err);
   if ((err = GetPcAndEmonResult(&pc, &emon)) != GOOD) return(err);
   if (emon) return(Print(FAIL,"Reset did not turn emulation off."));
   if (pc != codeAddr) return(Print(FAIL,
      "Incorrect pc after reset: expected %08lX, actual %08lX", codeAddr, pc));
   *pass = TRUE;
   return(GOOD);
}

/****************************************************************************
**
** TestSendCommand
**
** Send one test command to firmware.
**
*****************************************************************************/
RETCODE TestSendCommand(TEST_COMMAND cmd, BOOLEAN looping) {
   RETCODE err;
   BOOLEAN timedOut;
   if ((err = SdnWriteMember(SDN_TEST_LOOP, (U8*)&looping, GOOD)) != GOOD)
      return(err);
   if ((err = SdnWriteCmdChkAbortReadResponse(SDN_TEST_COMMAND,
      &cmd, GOOD, SDN_TEST_ABORT, &looping, GOOD,
      SDN_TEST_RESULT, 0, &timedOut)) != GOOD) return(err);
   return(GOOD);
}

/****************************************************************************
**
** SetupResetCode
**
** Clear map.
** If sast not installed, map 64k overlay at reset entry.
** If vector required, map 64k at 0 and write vector.
** Write up to 16 bytes of data at reset entry.
** Verify up to 16 bytes at reset entry.
**
*****************************************************************************/
RETCODE PRIVATE SetupResetCode(U16 *data, BOOLEAN *pass) {
   RETCODE err;
   LOOP_VAR i;
   U16 opLength;
   U8 read[16];
   U8 write[16];
   BOOLEAN sastConnected;
   if ((err = CheckSASTConnected(&sastConnected)) != GOOD) return(err);
   if ((err = TestMapClear()) != GOOD) return(err);
   if (!sastConnected) {
      if ((err = Print(VERB,"No sast installed; mapping overlay.")) != GOOD)
         return(err);
      if ((err = TestMapWrite(0ul, codeAddr, 0x10000ul, TRUE, MAP_RAM))
         != GOOD) return(err);
   }
   if (vectorLength > 0) {
      if ((err = TestMapWrite(1ul, 0ul, 0x10000ul, TRUE, MAP_RAM))
         != GOOD) return(err);
      if ((err = Print(VERB,"Initializing reset vector.")) != GOOD)
         return(err);
      if ((err = TestWritePhysical(0ul, space, vectorLength, vector, FALSE))
         != GOOD) return(err);
      if ((err = TestReadPhysical(0ul, space, vectorLength, read, FALSE))
         != GOOD) return(err);
      for (i=0; i<vectorLength; i++)  {
         if (vector[i] != read[i]) return(Print(FAIL,
            "Memory verify error: offset %08lX, expected %02X, actual %02X.",
            (U32)i, vector[i], read[i]));
      }
   }
   if ((err = Print(VERB,"Writing test code at reset entry.")) != GOOD)
      return(err);
   for (opLength=0 ; *data != OPEND; data++) {
      if (opLength+opcode[*data].length > sizeof(write)) break;
      memcpy(&write[opLength], opcode[*data].data, opcode[*data].length);
      opLength += opcode[*data].length;
   }
   if ((err = TestWritePhysical(codeAddr, space, opLength, write, FALSE))
      != GOOD) return(err);
   if ((err = TestReadPhysical(codeAddr, space, opLength, read, FALSE))
      != GOOD) return(err);
   for (i=0; i<opLength; i++)  {
      if (write[i] != read[i]) return(Print(FAIL,
         "Memory verify error: offset %08lX, expected %02X, actual %02X.",
         codeAddr+i, write[i], read[i]));
   }
   *pass = TRUE;
   return(GOOD);
}

/****************************************************************************
**
** GetPcAndEmonResult
**
** Read SDN_TEST_BUFFER after certain test commands that return
** the status of emulation and the ending pc value.
**
*****************************************************************************/
RETCODE PRIVATE GetPcAndEmonResult(U32 *pc, BOOLEAN *emon) {
   RETCODE err;
   if ((err = SdnReadPartialMember(SDN_TEST_BUFFER,0,4,(U8*)pc)) != GOOD)
      return(err);
   if ((err = SdnReadPartialMember(SDN_TEST_BUFFER,4,1,(U8*)emon)) != GOOD)
      return(err);
   return(GOOD);
}

/****************************************************************************
**
** SignalTestCallback
**
** Enumeration function for signal test.
** value is in the form "bit#, numbits, tracebit, signalnum, disabled state
**
*****************************************************************************/
RETCODE EXPORT SignalTestCallback(LPSTR key, LPSTR value, BOOLEAN *abort,
      VOID *pass) {
   RETCODE err;
   LPSTR token;
   U16 bitNumber, traceBit, signalIndex, disabledState;
   U32 rGroup, sGroup, tGroup, exp;
   U32 rBit, sBit, tBit;
   U8 sastData[MAX_SAST_BYTES];
   U8 enable;
   
   if (!*((BOOLEAN*)pass)) return(GOOD);   /* failed earlier */
   *((BOOLEAN*)pass) = FALSE;

   if ((token = strtok(value, ",")) == NULL)
      return(Print(FAIL,"Config file format error for signal %s.",key));
   bitNumber = (U16)strtoul(token, NULL, 0);
   if ((token = strtok(NULL, ",")) == NULL)
      return(Print(FAIL,"Config file format error for signal %s.",key));
   /* Do not need field size */
   if ((token = strtok(NULL, ",\n")) == NULL) {
      *((BOOLEAN*)pass) = TRUE;       /* This sast bit has no trace */
      return(GOOD);
   }
   traceBit = (U16)strtoul(token, NULL, 0);
   if ((token = strtok(NULL, ",\n")) == NULL) {
      *((BOOLEAN*)pass) = TRUE;       /* Not gatable signal */
      return(GOOD);
   }
   signalIndex = (U16)strtoul(token, NULL, 0);
   if ((token = strtok(NULL, ",\n")) == NULL)
      return(Print(FAIL,"Config file format error for signal %s.",key));
   disabledState = (U16)strtoul(token, NULL, 0);

   for (enable=0; enable<=1; enable++) {
      if ((err = Print(VERB,
         (enable ? "Testing signal %s enabled.": "Testing signal %s disabled"),
         key)) != GOOD) return(err);
      if ((err = SdnWriteMember(SDN_SIG00+signalIndex, &enable, GOOD)) != GOOD)
         return(err);
      memset(sastData,0,sizeof(sastData));
      sastData[bitNumber/8] |= (1 << (bitNumber%8));
      if ((err = TestWritePhysical(0, SPACE_SAST, sastDepth, sastData, FALSE))
         != GOOD) return(err);
      if ((err = CollectTrace(1, FALSE)) != GOOD) return(err);
      exp = (U32)(enable ? 1 : disabledState);
      rBit = (traceBit<32) ? (1ul<<traceBit) : 0ul;
      sBit = ((traceBit>=32) && (traceBit<64)) ? (1ul<<(traceBit-32)) : 0ul;
      tBit = (traceBit>=64) ? (1ul<<(traceBit-64)) : 0ul;
      rGroup = (traceBit<32) ? (exp<<traceBit) : 0ul;
      sGroup = ((traceBit>=32) && (traceBit<64)) ? (exp<<(traceBit-32)) : 0ul;
      tGroup = (traceBit>=64) ? (exp<<(traceBit-64)) : 0ul;
      if (((trace[0].rGroup & rBit) != rGroup)
            || ((trace[0].sGroup & sBit) != sGroup)
            || ((trace[0].tGroup & tBit) != tGroup)) {
         if ((err = Print(FAIL,"Trace failure, signal %s:",key)) != GOOD)
            return(err);
         if ((err = Print(FAIL,"  Expected %08lX %08lX %08lX",
            rGroup, sGroup, tGroup)) != GOOD) return(err);
         if ((err = Print(FAIL,"  Actual   %08lX %08lX %08lX",
            trace[0].rGroup & rBit, trace[0].sGroup & sBit,
            trace[0].tGroup & tBit)) != GOOD) return(err);
         return(GOOD);
      }
      if ((err = TskCheckAbort(abort)) != GOOD) return(err);
      if (*abort) return(GOOD);
   }
   *((BOOLEAN*)pass) = TRUE;
   return(GOOD);
}

/****************************************************************************
**
** EnableAllSignals
**
** Enable all signal gates from target.
**
*****************************************************************************/
RETCODE PRIVATE EnableAllSignals(VOID) {
   LOOP_VAR i;
   BOOLEAN enable=TRUE;
   for (i=0; i<NUM_SIGS; i++) {
       SdnWriteMember(SDN_SIG00+i, &enable, GOOD);  /* Ignore error */
   }
   return(GOOD);
}

RETCODE TestSASTInit(VOID) {
   RETCODE err;
   U8 sastData[MAX_SAST_BYTES];
   U8 length = sizeof(sastData);
   S8 name[MAX_LINE];
   if ((err = ProcInsertSystemName("[%s]",name)) != GOOD) return(err);
   if ((err = ConfigFileReadBytes(name, "sastinit", sastData, &length))
      != GOOD) return(err);
   if ((err = TestWritePhysical(0, SPACE_SAST, sastDepth, sastData, FALSE))
      != GOOD) return(err);
   return(GOOD);
}

RETCODE TestSASTOn(VOID) {
   U8 byte = (SAST_DRIVE_ON | SAST_ENA);
   return(TestWritePhysical(SAST_PORT, SPACE_PRB_XDATA, 1, &byte, FALSE));
}

RETCODE TestSASTOff(VOID) {
   U8 byte = 0;
   return(TestWritePhysical(SAST_PORT, SPACE_PRB_XDATA, 1, &byte, FALSE));
}

/******************************** E O F ***********************************/
