/***************************************************************************
**
**  Name:  trig.c
**
**  Description:
**       Routines to set up the trigger and trace management hardware
**
**  Status:  PRELIMINARY
**
**  $Log:   S:/tbird/mt2_186/trace/trig.c_v  $
** 
**    Rev 1.4   21 Jul 1997 14:59:04   Judy
** 
**    Rev 1.3   27 May 1997 15:29:20   Judy
** No change.
** 
**    Rev 1.2   17 Apr 1997 14:19:52   Judy
** 
**    Rev 1.0   16 Dec 1996 15:25:32   Judy
** Initial revision.
** 
**    Rev 1.5   15 Nov 1996 16:48:54   Judy
** 
**    Rev 1.4   23 Oct 1996 18:09:10   Judy
** 
**    Rev 1.3   14 Oct 1996 18:15:06   Judy
** 
**    Rev 1.2   11 Oct 1996 18:40:44   Judy
** 
**    Rev 1.1   06 Sep 1996 17:29:18   Judy
** 
**    Rev 1.0   27 Aug 1996 15:23:14   Judy
** Initial revision.
** 
**    Rev 1.0   27 Aug 1996 14:57:12   Judy
** Initial revision.
** 
**    Rev 1.1   28 Jun 1996 04:39:06   matt
** 
**    Rev 1.63   10 May 1994 10:25:50   ernie
** Added ignoreEmon member to FW_TRIGGER structure.  When TRUE, this
** causes the hardware to ignore EMON transitions for triggering purposes.
** 
**    Rev 1.62   16 Jul 1993 12:50:18   ernie
** Removed local error defs; use generic errors
** 
**    Rev 1.61   16 Jul 1993 10:18:18   ernie
** Changed abortFromEsc from U16 to BOOLEAN
** 
**    Rev 1.60   13 Jul 1993 09:36:34   ernie
** Changed power-on state of programTrigger to TRUE to force the trigger
** hardware to be programmed the first time GO is used.  This prevents a
** problem seen where an old trigger is left active in the box when
** PowerViews is rebooted but the PowerPack chassis is not.  Now that the
** trigger programming speed is much faster, there is a barely noticeable
** speed difference as the trigger is programmed.
** 
**    Rev 1.59   28 Jun 1993 08:51:00   paul
** Change CHECK_ABORT to TskCheckAbort (esc key support)
** 
**    Rev 1.58   01 Jun 1993 12:28:34   ernie
** Added check for TMOD board present before trying to program it.
** Also changed unused events to have .not=1 as a flag to the firmware
** that the event can remain in its default state.  Improves performance
** greatly.
** 
**    Rev 1.57   05 Jan 1993 15:18:34   courtney
** Removed MemAlloc and related macros (no longer used).
** 
**    Rev 1.56   17 Dec 1992 09:58:18   mindy
** Moved sequencer programming to box to minimize comm link traffic.
** 
**    Rev 1.55   12 Nov 1992 08:13:16   ernie
** Fixed ppr7641.  The timer function worked only when the terminal count
** was greater than 1023 (i.e. when counter 1 was being used).  Changed to
** invoke actions on only timer 0 terminal count if only timer 0 being used.
** 
**    Rev 1.54   25 Oct 1992 11:13:24   mindy
** fixed bug in parse trace mode routine.
** 
**    Rev 1.53   21 Oct 1992 08:07:08   mindy
** a) added sequencer enable flag to prevent enabling sequencer if it is
** 
**    already enabled.  Fixes ppr 6798 and 6830
** b) Made changes to get rid of the two zillion warning messages.
** 
**    Rev 1.52   14 Oct 1992 18:36:42   mindy
** a) fixed ppr6766
** b) fixed ppr6933
** 
**    Rev 1.51   06 Oct 1992 06:39:34   mindy
** add event to notify when number of buffers changed
** 
**    Rev 1.50   23 Sep 1992 06:36:06   mindy
** a) bad counter value is now just a warning because we default counter
**    to max value.
** b) counters now default to 1 not 0.
** c) check counter mode before programming specific actions.
** 
**    Rev 1.49   16 Sep 1992 19:24:56   mindy
** use sdn calls instead of sd
** 
**    Rev 1.48   09 Sep 1992 11:31:26   ernie
** Fixed bug in timer terminal counts when multiple of 1024
** 
**    Rev 1.47   09 Sep 1992 09:52:38   mindy
** added close routines needed
** 
**    Rev 1.46   09 Sep 1992 08:58:56   mindy
** fixed a typo
** 
**    Rev 1.45   09 Sep 1992 08:42:40   mindy
** trig can't reference anything in event during libmain
** 
**    Rev 1.44   08 Sep 1992 16:07:12   doug
** Updated with new events.
** 
**    Rev 1.43   08 Sep 1992 15:58:26   mindy
** changes unknown (john)
** 
**    Rev 1.42   27 Aug 1992 07:16:48   mindy
** a) cleaned up some warnings
** 2) fixed programming trigger problem that actions were being programmed
**    when event was disabled.
** c) if tracing is on then we exit with an error before attempting to
**    disble the sequencer.
** 
**    Rev 1.41   21 Aug 1992 16:17:12   mindy
** a) EVENT_LL still being referenced in callback routine
** b) There's no need to do a clear trace notify after programming trigger - 
** I think trace presenter should not be cleared since user might want to
** view his old trace while he can.
** 
**    Rev 1.40   20 Aug 1992 13:48:58   ernie
** Added handshake on EnableSequencer actions
** 
**    Rev 1.39   18 Aug 1992 06:43:40   mindy
** removed cli program command
** 
**    Rev 1.38   14 Aug 1992 08:52:38   mindy
** put back disable of sequencer
** 
**    Rev 1.37   14 Aug 1992 08:46:28   mindy
** a) register on HL halt and not LL - since user only gets control back
**    after HL halt event happens.  By registering on LL I was slowing 
**    down the source step loop.
** b) When programming the trigger; if the trigger hasn't been modified I
**    still need to enable the sequencer since it is disabled upon getting
**    a halt event.
** c) Need to put disable sequencer in check entry condition routine back.
** 
**    Rev 1.36   11 Aug 1992 09:55:14   mindy
** fixed bug of NEXT never being programmed
** 
**    Rev 1.35   10 Aug 1992 08:20:36   mindy
** replaced initCServer routine for tom's new server registration
** 
**    Rev 1.34   10 Aug 1992 05:49:46   mindy
** No reason to program event if it is never enabled.
** 
**    Rev 1.33   06 Aug 1992 07:17:34   mindy
** a) removed check entry conditions from routines that just change the
**    active level and event pointers
** b) assume trigger is programmed initially by the fw.
** 
**    Rev 1.32   03 Aug 1992 06:26:30   mindy
** if event name is in trigger change modified flag
** 
**    Rev 1.31   24 Jul 1992 14:46:42   doug
** using generic shared data
** 
**    Rev 1.30   17 Jul 1992 13:31:00   mindy
** if user selects NEXT he better have more than one buffer
** 
**    Rev 1.29   11 Jul 1992 15:49:02   courtney
** Callback now gets MakeProcInstance before it is used in event registration.
** 
**    Rev 1.28   10 Jul 1992 08:59:26   mindy
** added include file(s) needed to get rid of 3.1 warnings
** 
**    Rev 1.27   25 Jun 1992 12:29:42   mindy
** a) renamed entry check routine
** b) added a check for trigId being zero before doing cli routines.
** c) moved sdreadmembername and sdwritemembername here
** 
**    Rev 1.26   22 Jun 1992 15:12:28   mindy
** removed swat calls
** 
**    Rev 1.25   15 Jun 1992 08:56:32   mindy
** a) added a routine to check active trigger to see if given event is
**    part of the trigger.
** b) added a flag to determine if program hardware needs to be done.  If
**    no trigger options changed don't need to re-program.
** c) Before allowing any trigger changes make sure tracing is OFF and
**    we automatically disable the sequencer.
** d) When emulation is halted we disable the sequencer.
** e) Changed trigger to have a single globally active trigger - this is
**    the id to use when programming hardware.
** 
**    Rev 1.24   14 May 1992 11:40:58   mindy
** removed GetErrorText routine and added ErrInitDLL call
** 
**    Rev 1.23   13 May 1992 08:10:28   mindy
** get dll handle since cli might not be initialized
** 
**    Rev 1.22   12 May 1992 13:07:36   mindy
** Added trigGetErrorText
** 
**    Rev 1.21   01 May 1992 11:28:14   mindy
** reworded number trace buffer cli output
** 
**    Rev 1.20   28 Apr 1992 08:36:06   mindy
** a) Fixed ppr5361 - added abort support
** b) Change open to use cli's id if cli already opened a trigger setup.
**    !!! Might want to just allow one trigger setup?
** c) Trigger presenter needed access to number of trace buffers - without
**    having to do an open on a trace server.  So added get and set of
**    trace configuration.
** 
**    Rev 1.19   23 Apr 1992 11:27:20   mindy
** a) changed all memory allocation to use TMalloc not MemAlloc
** b) changed all trigger cli commands to no longer use id
** c) added local parsing since cli server doesn't support keywords.
** 
**    Rev 1.18   13 Mar 1992 09:00:38   mindy
** changed cli interface.  Now trigger open keeps the id and all cli commands
** no longer need to pass in the id.
** 
**    Rev 1.17   17 Feb 1992 06:50:46   mindy
** a) added event notification when programming sequencer - this is a signal
** to the trace presenter(s) to clear their display.
** b) now program trigger writes to SD_TRACE_EMPTY to prevent trace presenter(s)
** from reading "old" data from the trigger positions.
** 
**    Rev 1.16   28 Jan 1992 11:36:14   ernie
** 1. Added test for timer terminal count < 1024, in which case only
**    counter 0 is used (terminal count 1 = 0).
** 2. Changed timer chaining logic to not reset sequence level that may
**    already be set up in the sequencer array.
** 
**    Rev 1.15   27 Jan 1992 10:07:50   ernie
** a) exttrig is an active low signal too.
** b) changing bits in sequencer for sequence level only worked for "setting"
**    bits but going from level 1 to 2 didn't work.
** 
**    Rev 1.14   23 Jan 1992 14:03:36   ernie
** we weren't handling programming the sequencer right for seq action.
** 
**    Rev 1.13   22 Jan 1992 13:32:58   courtney
** Added code to LibMain to unlock the heap.
** 
**    Rev 1.12   17 Jan 1992 11:19:20   courtney
** Revised LibMain return type.
** 
**    Rev 1.11   14 Jan 1992 11:43:24   ernie
** If TrigEventNameSet sends in a string of blanks it's not an error
** (this makes it easier for the presenter) but it's also not an event
** name.
** 
**    Rev 1.10   07 Jan 1992 10:11:26   ernie
** a) use BOOLEAN not BOOL
** b) qualifier mode needs to be initialized when trigger created.
** 
**    Rev 1.9   11 Dec 1991 14:54:06   mindy
** a) trig server in its own dll now.
** b) SendCliResults moved to evttmplt.c so there wasn't a circular 
** path of each libraries need to be loaded.
** 
**    Rev 1.8   06 Dec 1991 10:25:58   mindy
** Got rid of global descriptor now use common sd routines in swat.c
** 
**    Rev 1.7   02 Dec 1991 10:56:14   mindy
** a) use global errors for mem lock and alloc errors
** b) when programming evtrec used to put SWAT in timestamp mode.
** 
**    Rev 1.6   26 Nov 1991 11:39:50   mindy
** two commands were added to the trace cli
** 
**    Rev 1.5   20 Nov 1991 10:54:26   mindy
** a) cli indexes changed because the trace search commands were added.
** b) changed a sprintf call to wsprintf - there weren't any obvious problem
**    but to be consistent it was changed.
** 
**    Rev 1.4   15 Nov 1991 15:06:14   mindy
** a) changed error numbering to conform to system numbers.
** b) added cli command routines.
** 
**    Rev 1.3   07 Nov 1991 14:32:26   mindy
** uncommented out new trace features since I got a new version of the fw.
** 
**    Rev 1.2   01 Nov 1991 09:19:54   mindy
** added support for:
** a) timer mode
** b) not condition
** c) using real event server
** 
**    Rev 1.1   02 Oct 1991 12:24:28   ernie
** Completed implementation for PDR2
** 
**    Rev 1.0   28 Aug 1991 11:38:10   ernie
** Initial revision.
** 
**  $Header:   S:/tbird/mt2_186/trace/trig.c_v   1.4   21 Jul 1997 14:59:04   Judy  $
**
**  Copyright (C) 1991 Microtek International.  All rights reserved.
**
*****************************************************************************/

		       /****************************
			*                          *
			*       INCLUDE FILES      *
			*                          *
			****************************/

#include "stdlib.h"
#ifndef __STRING_H
#include <string.h>
#endif
#ifndef __CTYPE_H
#include "ctype.h"
#endif
#ifndef _BASEWIND_
#include "basewind.h"
#endif
#ifndef _TRIG_
#include "trig.h"
#endif
#ifndef _ENLIB_
#include "enlib.h"
#endif
#ifndef _EVENT_
#include "event.h"
#endif
#ifndef _EVENTS_
#include "events.h"
#endif
#ifndef _BKPTEXEC_
#include "bkptexec.h"
#endif
#ifndef _CLISRV_
#include "clisrv.h"
#endif
#ifndef _TRACE_
#include "trace.h"
#endif
#ifndef _SDPROBE_
#include "sdprobe.h"
#endif
#ifndef _SSHARED_
#include "sshared.h"
#endif
#ifndef _HEAP_
#include "heap.h"
#endif
#ifndef _HOSTERRS_
#include "hosterrs.h"
#endif
#ifndef _LOCAL_
#include "local.h"
#endif

#ifndef _PVTASK_
#include "pvtask.h"
#endif

#ifndef  _SDS2ABI_
#include "sds2abi.h"
#endif

		       /****************************
			*                          *
			*     LOCAL DEFINITIONS    *
			*                          *
			****************************/

#define INVALID_EVENT_COND (NUM_EVENT_COND+1)
#define NUM_COUNTERS       2

#define COUNT_COUNT_TEXT "COUNTER_COUNTER"
#define COUNT_TIMER_TEXT "COUNTER_TIMER"
#define TIMER_COUNT_TEXT "TIMER_COUNTER"
#define TIMER_TIMER_TEXT "TIMER_TIMER"
#define CLOCK_TEXT "CLOCK"

HANDLE hInst;

typedef struct {
   U16 numTraceBuffers;
   TRACE_MODE traceMode;              /* pre-post-center */
   DESCRIPTOR eventServerId;          /* id of event server for events */
   U8 enableBreak;                    /* bit 0= trace break, bit 1= trace off */
   U8 modeUnit;                       /* high nibble=timer1, lower nibble=timer0 */
                                      /* 0=EP clock, 1=H, 2=M, 3=S, 4=mS, 5=uS */
   U8 extOut;                         /* external trigger out condition: low, high, high-z */
   QUAL_MODE qualifierMode;           /* trigger on clock or bus cycles */
   EVENT_COND curCond;                /* Current event condition */
   U16 curLevel;                      /* Current sequence level */
   U32 terminalCount[NUM_COUNTERS];
/* U32 timerValue;                 */
   FW_TRIGGER fw;
   LPSTR eventName[NUM_EVENTS][NUM_LEVELS];     /* which named events are in use */
   BOOLEAN trigModified;
   U16 extEvent;
} TRIGGER;

typedef struct {
   DESCRIPTOR templateId;           /* id of template to use */   
   LOOP_VAR nextEventPtr;           /* index to start sending next event */
   LOOP_VAR activeEvent;            /* index into eventList of active event.
				       an Index >= MAX_EVENTS means there's
				       no active event. */
   XILINX_NUMBER activeGroup;       /* which xilinx group does currently
				       selected template field belong */
   FIELD_TYPE activeType;           /* Keep track of active field type to
				       save time calling template server */
} EVENT;

			/****************************
			 *                          *
			 *    EXTERNAL VARIABLES    *
			 *                          *
			 ****************************/

			/****************************
			 *                          *
			 *     LOCAL STORAGE        *
			 *                          *
			 ****************************/

static HANDLE cliServerHandle = 0;       /* return address for CLI results */
/* only one trigger can be open'd in the system (!!!currently) */
DESCRIPTOR trigId=0L;
FARPROC lpTrigCallback;
static U16 defNumBuffers=1;
static TRACE_MODE defTraceMode=TRACE_PRE;
static COUNTER_TYPE defCounterMode=COUNT_TIMER;
static BOOLEAN defExtOut=FALSE;
static BOOLEAN defExtEvent=1;
static U8 defBreak=0;
static U8 defModeUnit=0;
static QUAL_MODE defQMode=QUAL_BUS;
static BOOLEAN programTrigger = TRUE;
static BOOLEAN sequencerEnabled = FALSE;
static TRIGGER myTrigger;
HANDLE hLib;   // for link SDK
ACTION_MASK trc_action[NUM_EVENT_COND][NUM_LEVELS];


			/****************************
			 *                          *
			 *     LOCAL PROTOTYPES     *
			 *                          *
			 ****************************/
RETCODE CheckTriggerConditions(DESCRIPTOR id);
U16     ConvertCond(EVENT_COND cond);
TRACE_MODE ParseTraceMode(LPSTR ptr);
RETCODE ProgramEvents(TRIGGER FAR *trigger);
RETCODE EXPORT TrigCallback(U32 eventNum);
VOID    TriggerInitialize(TRIGGER FAR *trigger);
RETCODE EnableSequencer(BOOLEAN enable);
LPSTR lmemcpy(LPSTR dest, LPSTR source, WORD len);

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

#pragma argsused
int FAR PASCAL LibMain(HANDLE hInstance, WORD wDataSeg, WORD cbHeapSize,
    LPSTR lpszCmdLine) {
   DESCRIPTOR descEvt;  /* unused return param from EnlRegister */
   U8 idx;

   hLib = hInstance;    /* for link SDK */
   hInst = hInstance;
   if (cbHeapSize != 0) UnlockData(0); /* allows heap to grow */
   ErrInitDLL(MODULE_TRIGGER,"trig.dll");
   if((lpTrigCallback=MakeProcInstance((FARPROC)TrigCallback,hInstance))
      !=NULL)
      EnlRegister(EVENT_BKPT_HALTED, 
	 (EVCALLBACK)lpTrigCallback, &descEvt);

   {
      TRACE_MODE mode;
      BOOLEAN eBreak;
      U8 status;
      COUNTER_TYPE cType=COUNT_TIMER;
      QUAL_MODE qType=QUAL_BUS;
      S8 str[128], profile[128];
      if(!GetProfileString("PowerViews","pwrviewdir","",profile,
    	 sizeof(profile))) lstrcpy(profile,"mp186.ini");
/*      GetPrivateProfileString("TrigInfo","numTraceBuffers","",(LPSTR)str,
	     sizeof(str), profile);
      if((ptr=strchr(str,' ')) != NULL) *ptr = '\0';
      numBuf = atoi(str);
      if(numBuf!=defNumBuffers) {
	    defNumBuffers = numBuf;
	    programTrigger = TRUE;
      } */
      GetPrivateProfileString("TrigInfo","traceAlignment","",(LPSTR)str,
	    sizeof(str), profile);
      mode = ParseTraceMode(str);
      if( defTraceMode != mode ) {
	     defTraceMode = mode;
//           programTrigger = TRUE;
      }
      GetPrivateProfileString("TrigInfo","traceBreak","",(LPSTR)str,
	     sizeof(str), profile);
      if(strncmpi(str, "on", strlen(str))==0) 
             eBreak=TRUE;
      else
             eBreak=FALSE;
      status=defBreak;
      if( (status & 0x01) != eBreak ) {
             defBreak &= 0xfe;
             defBreak |= eBreak;
//           programTrigger = TRUE;
      }
      GetPrivateProfileString("TrigInfo","breakOnFull","",(LPSTR)str,
	     sizeof(str), profile);
      if(strncmpi(str, "on", strlen(str))==0) 
	     eBreak = TRUE;
      else
	     eBreak = FALSE;
      status=defBreak;
      if( ((status & 0x02) >> 1) != eBreak ) {
             defBreak &= 0xfd;
             status=eBreak;
             defBreak |= (status << 1);
//           programTrigger = TRUE;
      }
      GetPrivateProfileString("TrigInfo","counterTimer","",(LPSTR)str,
	     sizeof(str), profile);
      if (strncmpi(str,COUNT_COUNT_TEXT,lstrlen(str))==0)   /* <Judy 6/6/1997> */
         cType = COUNT_COUNT;
      else if(strncmpi(str,COUNT_TIMER_TEXT,lstrlen(str))==0)
         cType = COUNT_TIMER;
      else if(strncmpi(str,TIMER_COUNT_TEXT,lstrlen(str))==0)
         cType = TIMER_COUNT;
      else if(strncmpi(str,TIMER_TIMER_TEXT,lstrlen(str))==0)
         cType = TIMER_TIMER;
      if(defCounterMode!=cType) {
	     defCounterMode = cType;
//           programTrigger = TRUE;
      }
      GetPrivateProfileString("TrigInfo","trigMode","",(LPSTR)str,
	     sizeof(str), profile);
      if(strncmpi(str,CLOCK_TEXT,lstrlen(str))==0) qType = QUAL_CLOCK;
      if( defQMode != qType ) {
	     defQMode = qType;
      }
      GetPrivateProfileString("TrigInfo","externalOut","",(LPSTR)str,
	     sizeof(str), profile);
      if(strncmpi(str,"high",lstrlen(str))==0)
             defExtOut = ACTIVE_HIGH;
      else if(strncmpi(str,"high-z",lstrlen(str))==0)
             defExtOut = 2;
      else
             defExtOut = ACTIVE_LOW;
      GetPrivateProfileString("TrigInfo","trigIn","",(LPSTR)str,
	     sizeof(str), profile);
      if(strncmpi(str,"high",lstrlen(str))==0)
             defExtEvent = ACTIVE_HIGH;
      else
             defExtEvent = ACTIVE_LOW;
//      programTrigger = TRUE;
      defModeUnit=0;
      GetPrivateProfileString("TrigInfo","timer0Unit","",(LPSTR)str,
	     sizeof(str), profile);
      if (strncmpi(str,"s",lstrlen(str))==0)
             defModeUnit = 0x03;
      else if (strncmpi(str,"ms",lstrlen(str))==0)
             defModeUnit = 0x04;
      else if (strncmpi(str,"us",lstrlen(str))==0)
             defModeUnit = 0x05;
      GetPrivateProfileString("TrigInfo","timer1Unit","",(LPSTR)str,
	     sizeof(str), profile);
      if (strncmpi(str,"s",lstrlen(str))==0)
             defModeUnit |= 0x30;
      else if (strncmpi(str,"ms",lstrlen(str))==0)
             defModeUnit |= 0x40;
      else if (strncmpi(str,"us",lstrlen(str))==0)
             defModeUnit |= 0x50;
//      programTrigger = TRUE;
      Sds2AbiClearEvent(-1); //clear all events & triggers
      for (idx = 0; idx < NUM_LEVELS; idx++)
           Sds2AbiClearTrig(idx+1);
   }
   /* initialize successfully */
    return(TRUE);
}

/* #ifndef _BORLANDC_ */
/**************************************************************************
**
** WEP {Windows Exit Procedure}
**
** Description: DLL exit procedure to perform cleanup for the DLL before it
**              is unloaded. - not to be used with BC++ compiler.
**
**	Parameters:
**    input:
**       nParam:     Message to indicate whether all of Windows is shutting
**                   down or just the DLL itself.
**
**    output:
**       return a 1 to indicate success
**
*************************************************************************
int FAR PASCAL EXPORT WEP(int nParam) {
   switch(nParam) {
      case WEP_SYSTEM_EXIT:
         break;
      case WEP_FREE_DLL:
         break;
      default:
         break;
   }
   if (trigId !=0)
      TFree(trigId);
   return(TRUE);
}
#endif */
/**************************************************************************
**
** InitCServer
**
***************************************************************************/
RETCODE EXPORT InitCServer(HANDLE cliHandle, HANDLE dllHandle) {
   CSERVER_NEW_REGISTRATION FAR * msgBufPtr;
   RETCODE err;
   cliServerHandle = cliHandle;
   msgBufPtr =
      (CSERVER_NEW_REGISTRATION FAR *)TMalloc(sizeof(CSERVER_VARIABLE_VALUE));
   if (msgBufPtr == NULL) return(ER_OUT_OF_MEMORY);
   msgBufPtr->stringResourceHandle = dllHandle;
   msgBufPtr->serverNameIndex = 30;
   msgBufPtr->dllNameIndex = 31;
   msgBufPtr->numberOfCommandsIndex = 32;
   msgBufPtr->commandStartIndex = 33;
   SendMessage(cliHandle, CLI_NEW_SVR_REGISTRATION, CLI_NEW_SVR_REGISTRATION,
      (DWORD)msgBufPtr);
   if((err=TrigTriggerOpen(&trigId,"","default"))!=GOOD) return(err);
   return(GOOD);
}

/*****************************************************************************
** 
**    TrigActionGet
** 
*****************************************************************************/
RETCODE EXPORT TrigActionGet(DESCRIPTOR id, ACTION_MASK FAR *mask) {
   TRIGGER FAR *trigger;
   trigger = (TRIGGER FAR *)id;
   *mask = 
      trigger->fw.action[ConvertCond(trigger->curCond)][trigger->curLevel];
   return(GOOD);
}

/*****************************************************************************
** 
**    TrcActionGet
** 
*****************************************************************************/
RETCODE EXPORT TrcActionGet(U8 event, U8 level, ACTION_MASK FAR *mask) {
   *mask = trc_action[event][level];
   return(GOOD);
}

/*****************************************************************************
** 
**    TrigActionSet
** 
*****************************************************************************/
RETCODE EXPORT TrigActionSet(DESCRIPTOR id, ACTION_MASK action) {
   TRIGGER FAR *trigger;
   RETCODE err;
   if( (err=CheckTriggerConditions(id))!=GOOD ) return(err);
   trigger = (TRIGGER FAR *)id;
/*   if( (action & TRIG_CONT_MASK)  * user has selected NEXT action *
      && (trigger->numTraceBuffers == 1) * AND only one trace buffer *) {
      err=ER_MULTI_BUFS_NEEDED;
      action &= ~TRIG_CONT_MASK;
   } */
   if (action <4) {
      trigger->fw.action[ConvertCond(trigger->curCond)][trigger->curLevel] &=0xfffc;
      trc_action[ConvertCond(trigger->curCond)][trigger->curLevel]&=0xfffc;
   }
   trigger->fw.action[ConvertCond(trigger->curCond)][trigger->curLevel]|=action;
   trc_action[ConvertCond(trigger->curCond)][trigger->curLevel]|=action;
   return(err);
}

/*****************************************************************************
** 
**    TrigActionClear
** 
*****************************************************************************/
RETCODE EXPORT TrigActionClear(DESCRIPTOR id, ACTION_MASK action) {
   TRIGGER FAR *trigger;
   RETCODE err;
   if( (err=CheckTriggerConditions(id))!=GOOD ) return(err);
   trigger = (TRIGGER FAR *)id;
   trigger->fw.action[ConvertCond(trigger->curCond)][trigger->curLevel]
      &=~action;
   trc_action[ConvertCond(trigger->curCond)][trigger->curLevel]
      &=~action;
   return(GOOD);
}

/*****************************************************************************
** 
**    TrigCounterFunctionGet
** 
*****************************************************************************/
RETCODE EXPORT TrigCounterFunctionGet(DESCRIPTOR id, 
				      COUNTER_TYPE FAR *function) {
   *function = ((TRIGGER FAR *)id)->fw.counterMode;
   return(GOOD);
}
/*****************************************************************************
** 
**    TrcCounterFunctionGet
** 
*****************************************************************************/
RETCODE EXPORT TrcCounterFunctionGet(COUNTER_TYPE FAR *function) {
   *function = defCounterMode;
   return(GOOD);
}

/*****************************************************************************
** 
**    TrigCounterFunctionSet
** 
*****************************************************************************/
RETCODE EXPORT TrigCounterFunctionSet(DESCRIPTOR id, COUNTER_TYPE function) {
   RETCODE err;
   if( (err=CheckTriggerConditions(id))!=GOOD ) return(err);
   ((TRIGGER FAR *)id)->fw.counterMode = function;
   defCounterMode=function;
   return(GOOD);
}
/*****************************************************************************
** 
**    TrigIgnoreEmonGet
**    TrigIgnoreEmonSet
** 
*****************************************************************************/
RETCODE EXPORT TrigIgnoreEmonGet(DESCRIPTOR id, BOOLEAN *ignoreEmon) {
   *ignoreEmon = ((TRIGGER FAR *)id)->fw.ignoreEmon;
   return(GOOD);
}

RETCODE EXPORT TrigIgnoreEmonSet(DESCRIPTOR id, BOOLEAN ignoreEmon) {
   RETCODE err;
   if( (err=CheckTriggerConditions(id))!=GOOD ) return(err);
   ((TRIGGER FAR *)id)->fw.ignoreEmon = ignoreEmon;
   return(GOOD);
}

/*****************************************************************************
** 
**    TrigCounterValueGet
** 
*****************************************************************************/
RETCODE EXPORT TrigCounterValueGet(DESCRIPTOR id, U16 counter,
				   U32 FAR *value) {
   TRIGGER FAR *trigger;
   trigger = (TRIGGER FAR *)id;

   switch(counter)
     {
      case 0:
           *value=trigger->terminalCount[counter] ;
           break;
      case 1:
           *value=trigger->terminalCount[counter];
           break;
      default:
           return(ER_BAD_COUNTER);
     }
   return(GOOD);
}
/*****************************************************************************
** 
**    TrigModeUnitGet
** 
*****************************************************************************/
RETCODE EXPORT TrigModeUnitGet(DESCRIPTOR id, U8 counter,
                                   U8 FAR *value) {
   TRIGGER FAR *trigger;
   trigger = (TRIGGER FAR *)id;

   switch(counter)
     {
      case 0:
           *value=trigger->modeUnit & 0x0f ;
           break;
      case 1:
           *value=(trigger->modeUnit & 0xf0) >> 4;
           break;
      default:
           return(ER_BAD_COUNTER);
     }
   return(GOOD);
}

/*****************************************************************************
** 
**    TrigModeUnitSet
** input: counter=0, COUNT0
**                1, COUNT1
** <judy 8/13/96>
*****************************************************************************/
RETCODE EXPORT TrigModeUnitSet(DESCRIPTOR id, U8 counter, U8 value){
   TRIGGER FAR *trigger;
   RETCODE err;
   if( (err=CheckTriggerConditions(id))!=GOOD ) return(err);
   trigger = (TRIGGER FAR *)id;
   switch(counter)
     {
      case 0:
           trigger->modeUnit &= 0xf0;
           trigger->modeUnit |= (value & 0x0f);
           break;
      case 1:
           trigger->modeUnit &= 0x0f;
           trigger->modeUnit |= ((value << 4) & 0xf0);
           break;
      default:
           return(ER_BAD_COUNTER);
     }
   defModeUnit=trigger->modeUnit;
   return(err);
}
/*****************************************************************************
** 
**    TrigCounterValueSet
** input: U16 counter=0, COUNT0
**                    1, COUNT1
** <judy 8/13/96>
*****************************************************************************/
RETCODE EXPORT TrigCounterValueSet(DESCRIPTOR id, U16 counter, U32 value){
   TRIGGER FAR *trigger;
   RETCODE err;
   if( (err=CheckTriggerConditions(id))!=GOOD ) return(err);
   trigger = (TRIGGER FAR *)id;
   if( value > 0xffffffffL ) {
       err = ER_MAX_COUNTER_VALUE;
       value = 0xffffffffL;
     }
   value = (value == 0) ? 1 : value;
   switch(counter)
     {
      case 0:
           trigger->terminalCount[counter] = value;
           break;
      case 1:
           trigger->terminalCount[counter] = value;
           break;
      default:
           return(ER_BAD_COUNTER);
     }
   return(err);
}

/*****************************************************************************
** 
**    TrigEventClear
** 
*****************************************************************************/
RETCODE EXPORT TrigEventClear(DESCRIPTOR id) {
   TRIGGER FAR *trigger;
   RETCODE err;
   U16 index;
   if( (err=CheckTriggerConditions(id))!=GOOD ) return(err);
   trigger = (TRIGGER FAR *)id;
   index = ConvertCond(trigger->curCond);
   trigger->fw.useEvt[index][trigger->curLevel]=FALSE;
   trigger->fw.useExt[index][trigger->curLevel]=FALSE;
   trigger->fw.action[index][trigger->curLevel]=trigger->curLevel;
   return(GOOD);                               /* NULL_MASK; <Judy 8/15/96> */
}

/*****************************************************************************
** 
**    TrigEventEnableGet
** 
*****************************************************************************/
RETCODE EXPORT TrigEventEnableGet(DESCRIPTOR id, BOOLEAN FAR *enableEvt) {
   TRIGGER FAR *trigger;
   U16 index;
   trigger = (TRIGGER FAR *)id;
   index = ConvertCond(trigger->curCond);
   *enableEvt=trigger->fw.useEvt[index][trigger->curLevel];
   return(GOOD);
}

/*****************************************************************************
** 
**    TrigExtGet
** 
*****************************************************************************/
RETCODE EXPORT TrigExtGet(DESCRIPTOR id, BOOLEAN FAR *enableExt) {
   TRIGGER FAR *trigger;
   trigger = (TRIGGER FAR *)id;
   *enableExt = 
      trigger->fw.useExt[ConvertCond(trigger->curCond)][trigger->curLevel];
   return(GOOD);
}

/*****************************************************************************
** 
**    TrigOutActionGet
** 
*****************************************************************************/
RETCODE EXPORT TrigOutActionGet(DESCRIPTOR id, U8 FAR *enableExt) {
   TRIGGER FAR *trigger;
   trigger = (TRIGGER FAR *)id;
   *enableExt = trigger->extOut;
   return(GOOD);
}

/*****************************************************************************
** 
**    TrigEventEnableSet
** 
*****************************************************************************/
RETCODE EXPORT TrigEventEnableSet(DESCRIPTOR id, BOOLEAN enable) {
   TRIGGER FAR *trigger;
   RETCODE err;
   U16 index;
   if( (err=CheckTriggerConditions(id))!=GOOD ) return(err);
   trigger = (TRIGGER FAR *)id;
   index = ConvertCond(trigger->curCond);
   trigger->fw.useEvt[index][trigger->curLevel] = enable;
   return(GOOD);
}

/*****************************************************************************
** 
**    TrigExtSet
** 
*****************************************************************************/
RETCODE EXPORT TrigExtSet(DESCRIPTOR id, BOOLEAN enable) {
   TRIGGER FAR *trigger;
   RETCODE err;
   if( (err=CheckTriggerConditions(id))!=GOOD ) return(err);
   trigger = (TRIGGER FAR *)id;
   trigger->fw.useExt[ConvertCond(trigger->curCond)][trigger->curLevel] = enable;
   return(GOOD);
}

/*****************************************************************************
** 
**    TrigOutActionSet
** 
*****************************************************************************/
RETCODE EXPORT TrigOutActionSet(DESCRIPTOR id, U8 enable) {
   TRIGGER FAR *trigger;
   RETCODE err;
   if( (err=CheckTriggerConditions(id))!=GOOD ) return(err);
   trigger = (TRIGGER FAR *)id;
   trigger->extOut = enable;
   defExtOut=trigger->extOut;
   if ( (err=Sds2AbiSetTrigOutAction(trigger->extOut)) != GOOD)
        return(err);
   return(GOOD);
}

/*****************************************************************************
** 
**    TrigExtEventSet
** 
*****************************************************************************/
RETCODE EXPORT TrigExtEventSet(DESCRIPTOR id, BOOLEAN enable) {
   TRIGGER FAR *trigger;
   RETCODE err;

   if( (err=CheckTriggerConditions(id))!=GOOD ) return(err);
   trigger = (TRIGGER FAR *)id;
   trigger->extEvent = enable;  /* 0:low, 1:high */
   if ((err=Sds2AbiSetExtEvent(trigger->extEvent)) != GOOD) return(err);
   defExtEvent=trigger->extEvent;
   return(GOOD);
}

/*****************************************************************************
** 
**    TrigExtEventGet
** 
*****************************************************************************/
RETCODE EXPORT TrigExtEventGet(DESCRIPTOR id, BOOLEAN *enable) {
   TRIGGER FAR *trigger;
   RETCODE err;
   U16 extEvent;

   if( (err=CheckTriggerConditions(id))!=GOOD ) return(err);
   trigger = (TRIGGER FAR *)id;
   *enable = trigger->extEvent;
   return(GOOD);
}

/*****************************************************************************
** 
**    TrigEventGet
** 
*****************************************************************************/
RETCODE EXPORT TrigEventGet(DESCRIPTOR id, EVENT_COND FAR *event) {
   *event = ((TRIGGER FAR *)id)->curCond;
   return(GOOD);
}

/*****************************************************************************
** 
**    TrigEventNameGet
** 
*****************************************************************************/
RETCODE EXPORT TrigEventNameGet(DESCRIPTOR id, LPSTR eventName, U16 maxLen){
   TRIGGER FAR *trigger;
   U16 index;
   trigger = (TRIGGER FAR *)id;
   if( (index = ConvertCond(trigger->curCond)) >= NUM_EVENTS ) 
      return(ER_ILLEGAL_EVENT);
   if( trigger->eventName[index][trigger->curLevel] != NULL ) {
      if (lstrlen(trigger->eventName[index][trigger->curLevel]) > maxLen) {
	 return(ER_NAME_TOO_LONG);
      }
      lstrcpy(eventName,trigger->eventName[index][trigger->curLevel]);
   }
   else
      lstrcpy(eventName,"");
   
   return(GOOD);
}

/*****************************************************************************
** 
**    TrigEventNameSet
** 
*****************************************************************************/
RETCODE EXPORT TrigEventNameSet(DESCRIPTOR id, LPSTR eventName) {
   LOOP_VAR i;
   TRIGGER FAR *trigger;
   U16 index;
   RETCODE err;
   if( (err=CheckTriggerConditions(id))!=GOOD ) return(err);
   trigger = (TRIGGER FAR *)id;
   if( (index = ConvertCond(trigger->curCond)) >= NUM_EVENTS ) 
      return(ER_ILLEGAL_EVENT);
   if( trigger->eventName[index][trigger->curLevel] != NULL ) {
      TFree((LPSTR)trigger->eventName[index][trigger->curLevel]);
      trigger->eventName[index][trigger->curLevel] = NULL;
   }
   for(i=0;i<lstrlen(eventName);i++) 
      if( !(isspace(eventName[i])) ) break;
   if( (i == lstrlen(eventName))  /* all spaces */
      || (lstrlen(eventName)== 0) /* no name given */) {
      return(GOOD); 
   }
   if((trigger->eventName[index][trigger->curLevel] =
	(LPSTR)TMalloc(lstrlen(eventName)+1))==NULL){
      return(ER_OUT_OF_MEMORY);
   }
   lstrcpy(trigger->eventName[index][trigger->curLevel],eventName);
   
   return(GOOD);
}

/*****************************************************************************
** 
**    TrigEventSet
** 
*****************************************************************************/
RETCODE EXPORT TrigEventSet(DESCRIPTOR id, EVENT_COND event) {
   if( ConvertCond(event) == INVALID_EVENT_COND ) 
      return(ER_ILLEGAL_EVENT);
   ((TRIGGER FAR *)id)->curCond = event;
   return(GOOD);
}

/*****************************************************************************
** 
**    TrigFillActionGet
** 
*****************************************************************************/
RETCODE EXPORT TrigFillActionGet(DESCRIPTOR id, U8 action,
                                 BOOLEAN FAR *enableBreak) {
   if (action==0)          /* get trace break status */
      *enableBreak=((TRIGGER FAR *)id)->enableBreak & 0x01;
   else                    /* get trace off status */
      *enableBreak = (((TRIGGER FAR *)id)->enableBreak & 0x02) >> 1;
   return(GOOD);
}

/*****************************************************************************
** 
**    TrigFillActionSet
** 
*****************************************************************************/
RETCODE EXPORT TrigFillActionSet(DESCRIPTOR id, U8 action, BOOLEAN enableBreak){
   RETCODE err;
   if( (err=CheckTriggerConditions(id))!=GOOD ) return(err);
   if (action == 0){
      ((TRIGGER FAR *)id)->enableBreak &= 0xfe;
      ((TRIGGER FAR *)id)->enableBreak |= (enableBreak & 0x01);
   } else {
      ((TRIGGER FAR *)id)->enableBreak &= 0xfd;
      ((TRIGGER FAR *)id)->enableBreak |= ((enableBreak & 0x01)<<1);
   }
   if ( (err=Sds2AbiSetTraceBreak(((TRIGGER FAR *)id)->enableBreak)) != GOOD)
        return(err);
   return(GOOD);
}
/*****************************************************************************
** 
**    TrigSeqLevelGet
** 
*****************************************************************************/
RETCODE EXPORT TrigSeqLevelGet(DESCRIPTOR id, U16 FAR *seqLevel) {
   *seqLevel = ((TRIGGER FAR *)id)->curLevel;
   return(GOOD);
}

/*****************************************************************************
** 
**    TrigSeqLevelSet
** 
*****************************************************************************/
RETCODE EXPORT TrigSeqLevelSet(DESCRIPTOR id, U16 seqLevel) {
   ((TRIGGER FAR *)id)->curLevel = seqLevel;
   return(GOOD);
}

/*****************************************************************************
** 
**    TrigTraceConfigureSet
** 
*****************************************************************************/
RETCODE EXPORT TrigTraceConfigureSet(DESCRIPTOR id, U16 numBuffers) {
   RETCODE err;
   if( (err=CheckTriggerConditions(id))!=GOOD ) return(err);
/* if ((err=Sds2AbiSetNumTraceBuffers(numBuffers)) != GOOD) return(err); */
   defNumBuffers = ((TRIGGER FAR *)id)->numTraceBuffers = numBuffers;
   if((err=EnlEventNotify(EVENT_TRIG_TRC_BUF_NUM)) != GOOD ) return(err); 
   return(GOOD);
}

/*****************************************************************************
** 
**    TrigTraceConfigureGet
** 
*****************************************************************************/
RETCODE EXPORT TrigTraceConfigureGet(DESCRIPTOR id, U16 FAR *numBuffers) {
   *numBuffers = ((TRIGGER FAR *)id)->numTraceBuffers;
   return(GOOD);
}

/*****************************************************************************
** 
**    TrigTraceModeGet
** 
*****************************************************************************/
RETCODE EXPORT TrigTraceModeGet(DESCRIPTOR id, TRACE_MODE FAR *mode) {
   *mode = ((TRIGGER FAR *)id)->traceMode;
   return(GOOD);
}

/*****************************************************************************
** 
**    TrigTraceModeSet
** 
*****************************************************************************/
RETCODE EXPORT TrigTraceModeSet(DESCRIPTOR id, TRACE_MODE mode) {
   RETCODE err;
   if( (err=CheckTriggerConditions(id))!=GOOD ) return(err);
   defTraceMode = ((TRIGGER FAR *)id)->traceMode = mode;
   return(GOOD);
}

/*****************************************************************************
** 
**    TrigTriggerClear
** 
*****************************************************************************/
RETCODE EXPORT TrigTriggerClear(DESCRIPTOR id) {
   RETCODE err;

   if( (err=CheckTriggerConditions(id))!=GOOD ) return(err);
   if ( (err=Sds2AbiClearTrig(((TRIGGER FAR *)id)->curLevel+1)) != GOOD) return(err);
   TriggerInitialize(((TRIGGER FAR *)id));
   return(GOOD);
}

/*****************************************************************************
** 
**    TrigTriggerAccept
** 
*****************************************************************************/
RETCODE EXPORT TrigTriggerAccept(DESCRIPTOR id) {
   RETCODE err;
   TRIGGER FAR *trigger;
   EVENT FAR *event;
   U16 idx, i, j, mask, mask2, tmpIdx;
   MP_TRIGGER mp_trig;
   LPSTR nameStr;

   trigger = (TRIGGER FAR *)id;
   event = (EVENT FAR *)trigger->eventServerId;
   tmpIdx=0;
   EvtClsTrigEvent();
   for (idx = 0; idx < NUM_LEVELS; idx++) {
/*      Sds2AbiClearTrig(idx+1);      */
      for (i=0, j=0; i < NUM_EVENT_COND; i++) {
        if (!trigger->fw.useEvt[i][idx]) continue;
	if (i < NUM_EVENTS) {
	   nameStr = trigger->eventName[i][idx];
           EvtSetActiveEvent(trigger->eventServerId,nameStr);
           EvtSetTrigEvent(event->activeEvent, i+1);
           mp_trig.evNo[j] = i+1; // event->activeEvent+1;
	} else {
	  if (i == 10) mp_trig.evNo[j] = 9;
	  else mp_trig.evNo[j] = i+2;
	}
        /*
	mask = trigger->fw.action[i][idx];
	mask2 = 0;
        if ((mask & LV0_MASK)==LV0_MASK) mask2 |= LV0_MASK;
        if ((mask & LV1_MASK)==LV1_MASK) mask2 |= LV1_MASK;
        if ((mask & LV2_MASK)==LV2_MASK) mask2 |= LV2_MASK;
        if ((mask & LV3_MASK)==LV3_MASK) mask2 |= LV3_MASK;
        if ((mask & BRK_MASK)==BRK_MASK) mask2 |= BRK_MASK;
        if ((mask & TC0_RST_MASK)==TC0_RST_MASK) mask2 |= TC0_RST_MASK;
        if ((mask & TC1_RST_MASK)==TC1_RST_MASK) mask2 |= TC1_RST_MASK;
        if ((mask & TMR0_START_MASK)==TMR0_START_MASK) mask2 |= TMR0_START_MASK;
        if ((mask & TMR1_START_MASK)==TMR1_START_MASK) mask2 |= TMR1_START_MASK;
        if ((mask & TMR0_STOP_MASK)==TMR0_STOP_MASK) mask2 |= TMR0_STOP_MASK;
        if ((mask & TMR1_STOP_MASK)==TMR1_STOP_MASK) mask2 |= TMR1_STOP_MASK;
        if ((mask & CNT0_INC_MASK)== CNT0_INC_MASK) mask2 |= CNT0_INC_MASK;
        if ((mask & CNT1_INC_MASK)== CNT1_INC_MASK) mask2 |= CNT1_INC_MASK;
        if ((mask & TRC_DIS_MASK)==TRC_DIS_MASK) mask2 |= TRC_DIS_MASK;
        if ((mask & TRC_START_MASK)==TRC_START_MASK) mask2 |= TRC_START_MASK;
        if ((mask & TRC_STOP_MASK)==TRC_STOP_MASK) mask2 |= TRC_STOP_MASK;
        if ((mask & TRC_QUAL_MASK)==TRC_QUAL_MASK) mask2 |= TRC_QUAL_MASK;
        if ((mask & TRIG_OUT_MASK)==TRIG_OUT_MASK) mask2 |= TRIG_OUT_MASK;
        */
        mp_trig.act[j] = trigger->fw.action[i][idx];
        j++;
      }
      mp_trig.defined = 0;
      if (j==0) {
         Sds2AbiClearTrig(idx+1);
         continue;
      }
      mp_trig.evNo[j] = 0;
      mp_trig.phySet = 0;
      mp_trig.mode = trigger->traceMode;
      if ( (err=Sds2AbiSetTrig(idx+1, &mp_trig)) != GOOD) return(err);
      tmpIdx= idx+1;
   }
   if( (err=EvtAcceptEvent(trigger->eventServerId)) != GOOD )
      return(err);
   if (tmpIdx !=0) {
      mp_trig.phySet=1;  // set trigger into F/W
      if ( (err=Sds2AbiSetTrig(tmpIdx, &mp_trig)) != GOOD) return(err);
   }
   if ( (err=Sds2AbiSetTimerCounter(trigger->fw.counterMode,
         trigger->terminalCount[0],trigger->terminalCount[1])) != GOOD)
        return(err);
   return(GOOD);
}
/*****************************************************************************
** 
**    TrigCheckQualify
** 
*****************************************************************************/
RETCODE EXPORT TrigCheckQualify(DESCRIPTOR id, BOOLEAN *flag) {
   TRIGGER FAR *trigger;
   U16 idx, i, mask, mask2;

   trigger = (TRIGGER FAR *)id;
   mask2 = 0;
   for (idx = 0; idx < NUM_LEVELS; idx++) {
      for (i=0; i < NUM_EVENT_COND; i++) {
        if (!trigger->fw.useEvt[i][idx]) continue;
	mask = trigger->fw.action[i][idx];
        if ((mask & TRC_QUAL_MASK)==TRC_QUAL_MASK) mask2 |= TRC_QUAL_MASK;
      }
   }
   *flag = (mask2 == TRC_QUAL_MASK) ? 1 : 0;
   return(GOOD);
}
/*****************************************************************************
** 
**    TrigFree
** 
*****************************************************************************/
RETCODE EXPORT TrigTriggerFree() {
   if (trigId !=0)
      TFree(trigId);
   trigId=0;
   EvtFreeEvent();
   TmpltTemplateFree();
   return(GOOD);
}
/*****************************************************************************
** 
**    TrigTriggerClose
** 
*****************************************************************************/
RETCODE EXPORT TrigTriggerClose(DESCRIPTOR id) {
   RETCODE err;
   TRIGGER FAR *trigger;

   if (trigId==0L)
      return(GOOD);
   trigger = (TRIGGER FAR *)id;
   if((err=TrigTriggerAccept(id))!=GOOD) return(err);
   lmemcpy(&myTrigger, trigger, sizeof(TRIGGER));
/*   TFree((LPSTR)id);
   trigId = 0L; */
   return(GOOD);
}

/*****************************************************************************
** 
**    TrigTriggerOpen
** 
*****************************************************************************/
RETCODE EXPORT TrigTriggerOpen(DESCRIPTOR FAR *id, LPSTR fileName,
			       LPSTR templateName) {
   TRIGGER FAR *trigger;
   RETCODE err;
   int hFile;
   if( trigId ) {
      *id = trigId;
      return(GOOD);
   }
   if((*id = (DESCRIPTOR)TMalloc(sizeof(TRIGGER))) == NULL) 
      return(ER_OUT_OF_MEMORY);
   trigger = (TRIGGER FAR *) *id;
   if (fileName && (lstrlen(fileName) > 0)) {
      if((hFile = _lopen(fileName,OF_READ)) == -1) return(ER_CANT_OPEN_FILE);
      if(_lread(hFile,(LPSTR)trigger,sizeof(*trigger)) != sizeof(*trigger))
	 return(ER_READING_FILE);
      if(_lclose(hFile) == -1) return(ER_CANT_CLOSE_FILE);
      trigger->curCond = EV0_COND;
      trigger->curLevel = 0;
   }
   else {
      lmemcpy(trigger, &myTrigger, sizeof(TRIGGER));
      if (!(trigger->trigModified)) TriggerInitialize(trigger);
      trigger->numTraceBuffers = defNumBuffers;
/*    if ((err=Sds2AbiSetNumTraceBuffers(defNumBuffers)) != GOOD) return(err); */
      trigger->traceMode = defTraceMode;
      trigger->fw.counterMode = defCounterMode;
      trigger->enableBreak = defBreak;
      trigger->extOut=defExtOut;
      trigger->modeUnit=defModeUnit;
      trigger->qualifierMode = defQMode;
      trigger->trigModified = programTrigger;
      trigger->extEvent = defExtEvent;
   }
   if ( (err=Sds2AbiSetTraceBreak(trigger->enableBreak)) != GOOD)
        return(err);
   if ( (err=Sds2AbiSetTrigOutAction(trigger->extOut)) != GOOD)
        return(err);
   if ((err=Sds2AbiSetExtEvent(trigger->extEvent)) != GOOD)
        return(err);
   if ((err=SdnWriteMember(SDN_TRACE_MODE,(U8 FAR *)&trigger->traceMode,
      GOOD))!=GOOD) return(err);

   if ( (err=Sds2AbiSetTimerCounter(trigger->fw.counterMode,
         trigger->terminalCount[0],trigger->terminalCount[1])) != GOOD)
        return(err);
   if ( (err=EvtOpenEvent(&trigger->eventServerId,templateName)) != GOOD )
      return(err);
   trigId = *id;
   return(GOOD);
}

RETCODE EXPORT TrigCallback(U32 eventNum) {
   if( eventNum == EVENT_BKPT_HALTED ) {
      EnableSequencer(FALSE);
   }
   return(GOOD);  /* error ignored anyway! */
}

/*****************************************************************************
** 
**    TrigTriggerProgram
** 
*****************************************************************************/
RETCODE EXPORT TrigTriggerProgram(VOID) {
   RETCODE err;
   TRIGGER FAR *trigger;
   BOOLEAN true=TRUE, timedOut, enable;
   BOOLEAN abortFromEsc;
   
   /* if trigger not open'd assume there's nothing to program */
   if( !trigId ) {
      if((err=TrigTriggerOpen(&trigId,"","default"))!=GOOD) return(err);
   }
   trigger = (TRIGGER FAR *)trigId;
   if( !trigger->trigModified ) {
      /* even if we didn't need to reprogram trigger we need to make
	 suer the sequencer is enabled
       */
      if( !sequencerEnabled ) return(EnableSequencer(TRUE));
      return(GOOD);
   }
   if( (err=CheckTriggerConditions(trigId))!=GOOD ) return(err);
   if ((err = EnableSequencer(FALSE)) != GOOD) return(err);

   enable=TRUE;
   if((err=SdnWriteMember(SDN_TRIGOUT_ENABLE,&enable,GOOD))!=GOOD)
      return(err);
   if((err=SdnWriteMember(SDN_QUAL_MODE,(U8 FAR *)&trigger->qualifierMode,
      GOOD))!=GOOD) return(err); 
   if((err=SdnWriteMember(SDN_NUM_TRCBUFS,(U8 FAR *)&trigger->numTraceBuffers,
      GOOD)) !=GOOD) return(err);
/*   if((err=SdnWriteMember(SDN_SET_TRACING,(U8 FAR *)&trigger->enableBreak,
      GOOD))!=GOOD) return(err); */
   if ( (err=Sds2AbiSetTraceBreak(trigger->enableBreak)) != GOOD)
        return(err);
   if ( (err=Sds2AbiSetTrigOutAction(trigger->extOut)) != GOOD)
        return(err);
   if((err=SdnWriteMember(SDN_TRACE_MODE,(U8 FAR *)&trigger->traceMode,
      GOOD))!=GOOD) return(err);

   if ( (err=Sds2AbiSetTimerCounter(trigger->fw.counterMode,
         trigger->terminalCount[0],trigger->terminalCount[1])) != GOOD)
        return(err);

   /* program event recognizers */
   if( (err=ProgramEvents(trigger)) != GOOD ) return(err);


   err = TskCheckAbort(&abortFromEsc);
   if(err!=GOOD) return err;
   if (abortFromEsc)
      return(ER_ABORT_FROM_ESC);


   /* Let firmware program trigger sequencer information */

   if((err = SdnWriteCmdChkAbortReadResponse(SDN_TRIGGER_INFO,
      &trigger->fw,GOOD,SDN_TRIGGER_PROG_ABORT, &true, GOOD,
      SDN_TRIGGER_PROGRAM_ACK, 60, &timedOut)) != GOOD)
      return(err);
   if ((err = EnableSequencer(TRUE)) != GOOD) return(err);
   /* need to prevent the trace presenter from reading trigger values
      until we are completely done programming trigger. This is
      sort of a kludge.
    */
   trigger->trigModified = FALSE;  /* programmed latest trig setup */
   if((err=SdnWriteMember(SDN_TRACE_EMPTY,&enable,GOOD))!= GOOD ) return(err);
   return(GOOD);
}

/*****************************************************************************
** 
**    TrigTriggerSaveAs
** 
*****************************************************************************/
RETCODE EXPORT TrigTriggerSaveAs(DESCRIPTOR id, LPSTR fileName) {
   TRIGGER FAR *trigger;
   int hFile;
   trigger = (TRIGGER FAR *)id;
   if((hFile = _lcreat(fileName,0)) == -1) return(ER_CANT_OPEN_FILE);
   if(_lwrite(hFile,(LPSTR)trigger,sizeof(*trigger)) != sizeof(*trigger))
      return(ER_WRITING_FILE);
   if(_lclose(hFile) == -1) return(ER_CANT_CLOSE_FILE);
   return(GOOD);
}

/*****************************************************************************
** 
**    TrigQualifierGet
** 
*****************************************************************************/
RETCODE EXPORT TrigQualifierGet(DESCRIPTOR id, QUAL_MODE FAR *mode) {
   *mode = ((TRIGGER FAR *)id)->qualifierMode;
   return(GOOD);
}

/*****************************************************************************
** 
**    TrigQualifierSet
** 
*****************************************************************************/
RETCODE EXPORT TrigQualifierSet(DESCRIPTOR id, QUAL_MODE mode) {
   RETCODE err;
   if( (err=CheckTriggerConditions(id))!=GOOD ) return(err);
   ((TRIGGER FAR *)id)->qualifierMode = mode;
   return(GOOD);
}

/*****************************************************************************
** 
**    TrigEventServerGet
** 
*****************************************************************************/
RETCODE EXPORT TrigEventServerGet(DESCRIPTOR id, DESCRIPTOR FAR *serverId) {
   *serverId = ((TRIGGER FAR *)id)->eventServerId;
   return(GOOD);
}

/*****************************************************************************
** 
**    TrigEventServerSet
** 
*****************************************************************************/
RETCODE EXPORT TrigEventServerSet(DESCRIPTOR id, DESCRIPTOR serverId) {
   RETCODE err;
   if( (err=CheckTriggerConditions(id))!=GOOD ) return(err);
   ((TRIGGER FAR *)id)->eventServerId = serverId;
   return(GOOD);
}

/*****************************************************************************
** 
**    TrigEventInTrigger
** 
*****************************************************************************/
RETCODE EXPORT TrigEventInTrigger(LPSTR event, BOOLEAN FAR *found) {
   LOOP_VAR evt, level;
   TRIGGER FAR *trigger;
   *found = FALSE;
   if( !trigId ) return(GOOD);  
   trigger = (TRIGGER FAR *)trigId;
   for(evt=0; evt<NUM_EVENTS; evt++) {
      if( trigger->eventName[evt][trigger->curLevel]==NULL) continue;
      if( lstrcmp(event,trigger->eventName[evt][trigger->curLevel]) == 0 ) {
	 for( level = 0; level < NUM_LEVELS; level++ ) {
	    if( trigger->fw.useEvt[evt][level] ) {
	       *found = TRUE;
	       /* if event in question is in trigger assume user is changing
		  it and thus the trigger needs to be reprogramed before 
		  next start of emulation.
		*/
	       trigger->trigModified = TRUE;
	       break;
	    }
	 }
      }
   }
   return(GOOD);
}

/*************************** CLI FUNCTIONS ******************************/
RETCODE HandleTrueFalse(BOOLEAN value) {
   S8 resultBuff[128];
   if( value ) lstrcpy(resultBuff,"TRUE");
   else lstrcpy(resultBuff,"FALSE");
   return(SendCliResults(resultBuff,cliServerHandle));
}

#define  LV0_MASK_TEXT               "LV0"
#define  LV1_MASK_TEXT               "LV1"
#define  LV2_MASK_TEXT               "LV2"
#define  LV3_MASK_TEXT               "LV3"
#define  BRK_MASK_TEXT               "BRK"
#define  TC0_RST_MASK_TEXT           "RST0"
#define  TC1_RST_MASK_TEXT           "RST1"
#define  TMR0_START_MASK_TEXT        "TM0_ON"
#define  TMR1_START_MASK_TEXT        "TM1_ON"
#define  TMR0_STOP_MASK_TEXT         "TM0_OFF"
#define  TMR1_STOP_MASK_TEXT         "TM1_OFF"
#define  CNT0_INC_MASK_TEXT          "INC0"
#define  CNT1_INC_MASK_TEXT          "INC1"
#define  TRC_DIS_MASK_TEXT           "TRC_END"
#define  TRC_START_MASK_TEXT         "TRC_ON"
#define  TRC_STOP_MASK_TEXT          "TRC_OFF"
#define  TRC_QUAL_MASK_TEXT          "TRC_IN"
#define  TRIG_OUT_MASK_TEXT          "TRIG_OUT"

ACTION_MASK ParseTriggerActionParm(LPSTR ptr) {
   ACTION_MASK mask=0;
   if( !trigId ) return(ER_NO_TRIG_DEFINED);
   if(strncmpi(ptr,LV0_MASK_TEXT,lstrlen(ptr))==0)
      mask = LV0_MASK;
   else if(strncmpi(ptr,LV1_MASK_TEXT,lstrlen(ptr))==0)
      mask = LV1_MASK;
   else if(strncmpi(ptr,LV2_MASK_TEXT,lstrlen(ptr))==0)
      mask = LV2_MASK;
   else if(strncmpi(ptr,LV3_MASK_TEXT,lstrlen(ptr))==0)
      mask = LV3_MASK;

   if(strncmpi(ptr,BRK_MASK_TEXT,lstrlen(ptr))==0)
      mask |= BRK_MASK;

   else if(strncmpi(ptr,TC0_RST_MASK_TEXT,lstrlen(ptr))==0)
      mask |= TC0_RST_MASK;
   else if(strncmpi(ptr,TC1_RST_MASK_TEXT,lstrlen(ptr))==0)
      mask |= TC1_RST_MASK;

   else if(strncmpi(ptr,CNT0_INC_MASK_TEXT,lstrlen(ptr))==0)
      mask |= CNT0_INC_MASK;
   else if(strncmpi(ptr,TMR0_START_MASK_TEXT,lstrlen(ptr))==0)
      mask |= TMR0_START_MASK;
   else if(strncmpi(ptr,TMR0_STOP_MASK_TEXT,lstrlen(ptr))==0)
      mask |= TMR0_STOP_MASK;
   else if(strncmpi(ptr,TMR1_START_MASK_TEXT,lstrlen(ptr))==0)
      mask |= TMR1_START_MASK;
   else if(strncmpi(ptr,TMR1_STOP_MASK_TEXT,lstrlen(ptr))==0)
      mask |= TMR1_STOP_MASK;
   else if(strncmpi(ptr,CNT1_INC_MASK_TEXT,lstrlen(ptr))==0)
      mask |= CNT1_INC_MASK;

   else if(strncmpi(ptr,TRC_DIS_MASK_TEXT,lstrlen(ptr))==0)
      mask |= TRC_DIS_MASK;
   else if(strncmpi(ptr,TRC_START_MASK_TEXT,lstrlen(ptr))==0)
      mask |= TRC_START_MASK;
   else if(strncmpi(ptr,TRC_STOP_MASK_TEXT,lstrlen(ptr))==0)
      mask |= TRC_STOP_MASK;
   else if(strncmpi(ptr,TRC_QUAL_MASK_TEXT,lstrlen(ptr))==0)
      mask |= TRC_QUAL_MASK;
   else if(strncmpi(ptr,TRIG_OUT_MASK_TEXT,lstrlen(ptr))==0)
      mask |= TRIG_OUT_MASK;
   return(mask);
}

VOID PrintTriggerAction(ACTION_MASK mask, LPSTR resultBuff) {
   COUNTER_TYPE type;
   if( !mask ) lstrcpy(resultBuff,"NO ACTIONS");
   else {
      if( (mask & LV3_MASK)==LV3_MASK )
        lstrcat(resultBuff,LV3_MASK_TEXT);
      else if( (mask & LV2_MASK)==LV2_MASK )
        lstrcat(resultBuff, lstrlen(resultBuff) ?
        "|"LV2_MASK_TEXT : LV2_MASK_TEXT);
      else if( (mask & LV1_MASK)==LV1_MASK )
        lstrcat(resultBuff, lstrlen(resultBuff) ?
         "|"LV1_MASK_TEXT : LV1_MASK_TEXT);
      else if( (mask & LV0_MASK)==LV0_MASK )
        lstrcat(resultBuff, lstrlen(resultBuff) ?
         "|"LV0_MASK_TEXT : LV0_MASK_TEXT);

      if( (mask & BRK_MASK)==BRK_MASK ) lstrcat(resultBuff,
         lstrlen(resultBuff) ? "|"BRK_MASK_TEXT : BRK_MASK_TEXT);

      if( (mask & TC0_RST_MASK)==TC0_RST_MASK ) lstrcat(resultBuff,
         lstrlen(resultBuff) ? "|"TC0_RST_MASK_TEXT : TC0_RST_MASK_TEXT);
      if( (mask & TC1_RST_MASK)==TC1_RST_MASK ) lstrcat(resultBuff,
         lstrlen(resultBuff) ? "|"TC1_RST_MASK_TEXT : TC1_RST_MASK_TEXT);
      TrigCounterFunctionGet(trigId, &type);
      if(type==COUNT_TIMER || type == TIMER_TIMER) {
        if( (mask & TMR0_START_MASK)==TMR0_START_MASK )
            lstrcat(resultBuff, lstrlen(resultBuff) ?
            "|"TMR0_START_MASK_TEXT : TMR0_START_MASK_TEXT);
        if( (mask & TMR0_STOP_MASK)==TMR0_STOP_MASK )
            lstrcat(resultBuff,lstrlen(resultBuff) ?
            "|"TMR0_STOP_MASK_TEXT : TMR0_STOP_MASK_TEXT);
      } else {
        if( (mask & CNT0_INC_MASK)==CNT0_INC_MASK )
            lstrcat(resultBuff, lstrlen(resultBuff) ?
            "|"CNT0_INC_MASK_TEXT : CNT0_INC_MASK_TEXT);
      }
      if(type==TIMER_COUNT || type == TIMER_TIMER) {
      if( (mask & TMR1_START_MASK)==TMR1_START_MASK ) lstrcat(resultBuff,
         lstrlen(resultBuff) ? "|"TMR1_START_MASK_TEXT : TMR1_START_MASK_TEXT);
      if( (mask & TMR1_STOP_MASK)==TMR1_STOP_MASK ) lstrcat(resultBuff,
         lstrlen(resultBuff) ? "|"TMR1_STOP_MASK_TEXT : TMR1_STOP_MASK_TEXT);
      } else {
         if( (mask & CNT1_INC_MASK)==CNT1_INC_MASK ) lstrcat(resultBuff,
            lstrlen(resultBuff) ? "|"CNT1_INC_MASK_TEXT : CNT1_INC_MASK_TEXT);
      }

      if( (mask & TRC_DIS_MASK)==TRC_DIS_MASK ) lstrcat(resultBuff,
         lstrlen(resultBuff) ? "|"TRC_DIS_MASK_TEXT : TRC_DIS_MASK_TEXT);
      if( (mask & TRC_START_MASK)==TRC_START_MASK ) lstrcat(resultBuff,
         lstrlen(resultBuff) ? "|"TRC_START_MASK_TEXT : TRC_START_MASK_TEXT);
      if( (mask & TRC_STOP_MASK)==TRC_STOP_MASK ) lstrcat(resultBuff,
         lstrlen(resultBuff) ? "|"TRC_STOP_MASK_TEXT : TRC_STOP_MASK_TEXT);
      if( (mask & TRC_QUAL_MASK)==TRC_QUAL_MASK ) lstrcat(resultBuff,
         lstrlen(resultBuff) ? "|"TRC_QUAL_MASK_TEXT : TRC_QUAL_MASK_TEXT);
      if( (mask & TRIG_OUT_MASK)==TRIG_OUT_MASK ) lstrcat(resultBuff,
         lstrlen(resultBuff) ? "|"TRIG_OUT_MASK_TEXT : TRIG_OUT_MASK_TEXT);
   }
}

RETCODE EXPORT TrigCliAction(LPSTR cmdString, U32 argc, U32 argv[]) {
   ACTION_MASK mask=0,curMask;
   S8 resultBuff[128];
   U16 arg;
   RETCODE err;
   if( !trigId ) return(ER_NO_TRIG_DEFINED);
   if( argc >= 2 ) {
      if( (err=TrigActionGet(trigId,&mask)) != GOOD )
         return(err);
      if ((mask & 0x03) ==0 ) {
         TrigSeqLevelGet(trigId, &curMask);
         if( (err=TrigActionSet(trigId,curMask)) != GOOD ) return(err);
      }
      for(arg=1; arg<argc; arg++) {
         curMask=ParseTriggerActionParm(&(cmdString[(U16)argv[arg]]));
         if( (err=TrigActionSet(trigId,curMask)) != GOOD )
            return(err);
      }
   }
   if( (err=TrigActionGet(trigId,&mask)) != GOOD )
      return(err);
   resultBuff[0] = '\0';
   PrintTriggerAction(mask, resultBuff);
   return(SendCliResults(resultBuff,cliServerHandle));
}

RETCODE EXPORT TrigCliClearAction(LPSTR cmdString, U32 argc, U32 argv[]) {
   ACTION_MASK mask=0, curMask;
   S8 resultBuff[128];
   U16 arg;
   RETCODE err;
   if( !trigId ) return(ER_NO_TRIG_DEFINED);
   if( argc >= 2 ) {
      for(arg=1; arg<argc; arg++) {
	 if((curMask=ParseTriggerActionParm(&(cmdString[(U16)argv[arg]])))==0)
	    return(ER_INVALID_ACTION);
	 else
	    mask |= curMask;
      }
      if( (err=TrigActionClear(trigId,mask)) != GOOD ) 
	 return(err);
   }
   if( (err=TrigActionGet(trigId,&mask)) != GOOD )
      return(err);
   resultBuff[0] = '\0';
   PrintTriggerAction(mask, resultBuff);
   return(SendCliResults(resultBuff,cliServerHandle));
}

RETCODE EXPORT TrigCliCounterFunction(LPSTR cmdString, U32 argc, U32 argv[]) {
   COUNTER_TYPE type=COUNT_TIMER;
   S8 resultBuff[128];
   LPSTR ptr;
   RETCODE err;
   if( !trigId ) return(ER_NO_TRIG_DEFINED);
   if( argc == 2 ) {
      ptr = &cmdString[(U16)argv[1]];
      if(strncmpi(ptr,COUNT_COUNT_TEXT,lstrlen(ptr))==0)
         type = COUNT_COUNT;
      else if(strncmpi(ptr,COUNT_TIMER_TEXT,lstrlen(ptr))==0)
         type = COUNT_TIMER;
      else if(strncmpi(ptr,TIMER_COUNT_TEXT,lstrlen(ptr))==0)
         type = TIMER_COUNT;
      else if(strncmpi(ptr,TIMER_TIMER_TEXT,lstrlen(ptr))==0)
         type = TIMER_TIMER;
      if( (err=TrigCounterFunctionSet(trigId,type)) != GOOD ) return(err);
   }
   if( (err=TrigCounterFunctionGet(trigId,&type)) != GOOD )
      return(err);
   if( type == COUNT_COUNT ) lstrcpy(resultBuff,COUNT_COUNT_TEXT);
   else if( type == COUNT_TIMER ) lstrcpy(resultBuff,COUNT_TIMER_TEXT);
   else if( type == TIMER_COUNT ) lstrcpy(resultBuff,TIMER_COUNT_TEXT);
   else if( type == TIMER_TIMER ) lstrcpy(resultBuff,TIMER_TIMER_TEXT);
   else lstrcpy(resultBuff,"NOT SPECIFIED");
   return(SendCliResults(resultBuff,cliServerHandle));
}

RETCODE EXPORT TrigCliCounterValue(LPSTR cmdString, U32 argc, U32 argv[]) {
   U32 value;
   S8 resultBuff[128];
   RETCODE err;
   if( !trigId ) return(ER_NO_TRIG_DEFINED);
   if( argc == 3 ) {
      if( (err=TrigCounterValueSet(trigId,
		  atoi(&cmdString[(U16)argv[1]]),
		  atoi(&cmdString[(U16)argv[2]])))!=GOOD)
	 return(err);
   }
   else if( argc != 2 ) return(ER_CLI_SYNTAX);
   if( (err=TrigCounterValueGet(trigId,
				atoi(&cmdString[(U16)argv[1]]),&value))!=GOOD)
      return(err);
   wsprintf(resultBuff,"%ld", value);
   return(SendCliResults(resultBuff,cliServerHandle));
}

#pragma argsused
RETCODE EXPORT TrigCliClearEvent(LPSTR cmdString, U32 argc, U32 argv[]) {
   if( !trigId ) return(ER_NO_TRIG_DEFINED);
   return(TrigEventClear(trigId));
}

RETCODE EXPORT TrigCliEventEnable(LPSTR cmdString, U32 argc, U32 argv[]) {
   BOOLEAN value;
   RETCODE err;
   if( !trigId ) return(ER_NO_TRIG_DEFINED);
   if( argc == 2 ) {
      value = ParseBoolean(&cmdString[(U16)argv[1]]);
      if( (err=TrigEventEnableSet(trigId,value)) != GOOD ) return(err);
   }
   if( (err=TrigEventEnableGet(trigId,&value)) != GOOD )
      return(err);
   return(HandleTrueFalse(value));
}

RETCODE EXPORT TrigCliExt(LPSTR cmdString, U32 argc, U32 argv[]) {
   BOOLEAN value;
   RETCODE err;
   if( !trigId ) return(ER_NO_TRIG_DEFINED);
   if( argc == 2 ) {
      value = ParseBoolean(&cmdString[(U16)argv[1]]);
      if( (err=TrigExtSet(trigId,value)) != GOOD ) return(err);
   }
   if( (err=TrigExtGet(trigId,&value)) != GOOD )
      return(err);
   return(HandleTrueFalse(value));
}

#define EV0_COND_TEXT "EV0"
#define EV1_COND_TEXT "EV1"
#define EV2_COND_TEXT "EV2"
#define EV3_COND_TEXT "EV3"
#define EV4_COND_TEXT "EV4"
#define EV5_COND_TEXT "EV5"
#define EV6_COND_TEXT "EV6"
#define EV7_COND_TEXT "EV7"
#define TC0_COND_TEXT "TC0"
#define TC1_COND_TEXT "TC1"
#define EXT_COND_TEXT "EXT"
EVENT_COND ParseEventConditionParm(LPSTR ptr) {
   EVENT_COND mask=0;
   if(strncmpi(ptr,EV0_COND_TEXT,lstrlen(ptr))==0)
      mask = EV0_COND;
   else if(strncmpi(ptr,EV1_COND_TEXT,lstrlen(ptr))==0)
      mask = EV1_COND;
   else if(strncmpi(ptr,EV2_COND_TEXT,lstrlen(ptr))==0)
      mask = EV2_COND;
   else if(strncmpi(ptr,EV3_COND_TEXT,lstrlen(ptr))==0) 
      mask = EV3_COND;
   else if(strncmpi(ptr,EV4_COND_TEXT,lstrlen(ptr))==0)
      mask = EV4_COND;
   else if(strncmpi(ptr,EV5_COND_TEXT,lstrlen(ptr))==0)
      mask = EV5_COND;
   else if(strncmpi(ptr,EV6_COND_TEXT,lstrlen(ptr))==0)
      mask = EV6_COND;
   else if(strncmpi(ptr,EV7_COND_TEXT,lstrlen(ptr))==0)
      mask = EV7_COND;
   else if(strncmpi(ptr,TC0_COND_TEXT,lstrlen(ptr))==0)
      mask = TC0_COND;
   else if(strncmpi(ptr,TC1_COND_TEXT,lstrlen(ptr))==0)
      mask = TC1_COND;
   else if(strncmpi(ptr,EXT_COND_TEXT,lstrlen(ptr))==0)
      mask = EXT_COND;
   return(mask);
}

RETCODE EXPORT TrigCliEvent(LPSTR cmdString, U32 argc, U32 argv[]) {
   EVENT_COND event;
   S8 resultBuff[128];
   LPSTR ptr;
   RETCODE err;
   if( !trigId ) return(ER_NO_TRIG_DEFINED);
   if( argc == 2 ) {
      if( (event = ParseEventConditionParm(&cmdString[(U16)argv[1]])) == 0 )
	 return(ER_INVALID_EVENT);
      if( (err=TrigEventSet(trigId,event)) != GOOD ) 
	 return(err);
   }
   if( (err=TrigEventGet(trigId,&event)) != GOOD )
      return(err);
   switch(event) {
      case EV0_COND: ptr = EV0_COND_TEXT; break;
      case EV1_COND: ptr = EV1_COND_TEXT; break;
      case EV2_COND: ptr = EV2_COND_TEXT; break;
      case EV3_COND: ptr = EV3_COND_TEXT; break;
      case EV4_COND: ptr = EV4_COND_TEXT; break;
      case EV5_COND: ptr = EV5_COND_TEXT; break;
      case EV6_COND: ptr = EV6_COND_TEXT; break;
      case EV7_COND: ptr = EV7_COND_TEXT; break;
      case TC0_COND: ptr = TC0_COND_TEXT; break;
      case TC1_COND: ptr = TC1_COND_TEXT; break;
      case EXT_COND: ptr = EXT_COND_TEXT; break;
      default: ptr = "BAD EVENT"; break;
   }
   lstrcpy(resultBuff,ptr);
   return(SendCliResults(resultBuff,cliServerHandle));
}

RETCODE EXPORT TrigCliEventName(LPSTR cmdString, U32 argc, U32 argv[]) {
   S8 resultBuff[128];
   RETCODE err;
   if( !trigId ) return(ER_NO_TRIG_DEFINED);
   if( argc == 2 ) {
      if( (err=TrigEventNameSet(trigId,
			   &cmdString[(U16)argv[1]])) != GOOD ) return(err);
   }
   if((err=TrigEventNameGet(trigId,resultBuff,128))!=GOOD)
      return(err);
   return(SendCliResults(resultBuff,cliServerHandle));
}

RETCODE EXPORT TrigCliEventServer(LPSTR cmdString, U32 argc, U32 argv[]) {
   DESCRIPTOR eventId;
   S8 resultBuff[128];
   RETCODE err;
   if( !trigId ) return(ER_NO_TRIG_DEFINED);
   if( argc == 2 ) {
      if( (err=TrigEventServerSet(trigId, 
				  atoi(&cmdString[(U16)argv[1]]))) != GOOD ) 
      return(err);
   }
   if( (err=TrigEventServerGet(trigId,&eventId)) != GOOD )
      return(err);
   wsprintf(resultBuff,"%d", eventId);
   return(SendCliResults(resultBuff,cliServerHandle));
}

RETCODE EXPORT TrigCliBreakFull(LPSTR cmdString, U32 argc, U32 argv[]) {
   BOOLEAN value;
   RETCODE err;
   if( !trigId ) return(ER_NO_TRIG_DEFINED);
   if( argc == 2 ) {
      value = ParseBoolean(&cmdString[(U16)argv[1]]);
      if( (err=TrigFillActionSet(trigId,0,value))!=GOOD) return(err);
   }
   if( (err=TrigFillActionGet(trigId,0,&value)) != GOOD ) return(err);
   return(HandleTrueFalse(value));
}

RETCODE EXPORT TrigCliOffFull(LPSTR cmdString, U32 argc, U32 argv[]) {
   BOOLEAN value;
   RETCODE err;
   if( !trigId ) return(ER_NO_TRIG_DEFINED);
   if( argc == 2 ) {
      value = ParseBoolean(&cmdString[(U16)argv[1]]);
      if( (err=TrigFillActionSet(trigId,1,value))!=GOOD) return(err);
   }
   if( (err=TrigFillActionGet(trigId,1,&value)) != GOOD ) return(err);
   return(HandleTrueFalse(value));
}

RETCODE EXPORT TrigCliIgnoreEmon(LPSTR cmdString, U32 argc, U32 argv[]) {
   BOOLEAN value;
   RETCODE err;
   if( !trigId ) return(ER_NO_TRIG_DEFINED);
   if( argc == 2 ) {
      value = ParseBoolean(&cmdString[(U16)argv[1]]);
      if( (err=TrigIgnoreEmonSet(trigId,value))!=GOOD) return(err);
   }
   if( (err=TrigIgnoreEmonGet(trigId,&value)) != GOOD ) return(err);
   return(HandleTrueFalse(value));
}

#define BUS_TEXT "BUS"

RETCODE EXPORT TrigCliQualifier(LPSTR cmdString, U32 argc, U32 argv[]) {
   QUAL_MODE type=QUAL_BUS;
   S8 resultBuff[128];
   RETCODE err;
   if( !trigId ) return(ER_NO_TRIG_DEFINED);
   if( argc == 2 ) {
      if(strncmpi(&cmdString[(U16)argv[1]],CLOCK_TEXT,
	 lstrlen(&cmdString[(U16)argv[1]]))==0) type = QUAL_CLOCK;  
      if( (err=TrigQualifierSet(trigId,type)) != GOOD ) return(err);
   }
   if( (err=TrigQualifierGet(trigId,&type)) != GOOD )
      return(err);
   if( type == QUAL_CLOCK ) lstrcpy(resultBuff,CLOCK_TEXT);
   else lstrcpy(resultBuff,BUS_TEXT);
   return(SendCliResults(resultBuff,cliServerHandle));
}

RETCODE EXPORT TrigCliSeqLevel(LPSTR cmdString, U32 argc, U32 argv[]) {
   U16 level;
   S8 resultBuff[128];
   RETCODE err;
   if( !trigId ) return(ER_NO_TRIG_DEFINED);
   if( argc == 2 ) {
      if( (err=TrigSeqLevelSet(trigId,atoi(&cmdString[(U16)argv[1]]))) != GOOD )
      return(err);
   }
   if( (err=TrigSeqLevelGet(trigId,&level)) != GOOD )
      return(err);
   wsprintf(resultBuff,"%d", level);
   return(SendCliResults(resultBuff,cliServerHandle));
}

RETCODE EXPORT TrigCliTraceConfigure(LPSTR cmdString, U32 argc, U32 argv[]) {
   U16 num;
   S8 resultBuff[128];
   RETCODE err;
   if( !trigId ) return(ER_NO_TRIG_DEFINED);
   if( argc == 2 ) {
      if( (err=TrigTraceConfigureSet(trigId, 
				  atoi(&cmdString[(U16)argv[1]]))) != GOOD ) 
      return(err);
   }
   if( (err=TrigTraceConfigureGet(trigId,&num)) != GOOD )
      return(err);
   num=1;
   if( num == 1 )
      lstrcpy(resultBuff,"1 trace buffer");
   else
      wsprintf(resultBuff,"%d trace buffers", num);
   return(SendCliResults(resultBuff,cliServerHandle));
}

#define PRE_TEXT "PRE"
#define POST_TEXT "POST"
#define CENTER_TEXT "CENTER"

TRACE_MODE ParseTraceMode(LPSTR ptr) {
   TRACE_MODE mode=-1;
   if(strncmpi(ptr,PRE_TEXT,lstrlen(ptr))==0)
      mode = TRACE_PRE;
   else if(strncmpi(ptr,POST_TEXT,lstrlen(ptr))==0)
      mode = TRACE_POST;
   else if(strncmpi(ptr,CENTER_TEXT,lstrlen(ptr))==0)
      mode = TRACE_CENTER;
   return(mode);
}

RETCODE EXPORT TrigCliTraceMode(LPSTR cmdString, U32 argc, U32 argv[]) {
   TRACE_MODE mode;
   S8 resultBuff[128];
   RETCODE err;
   if( !trigId ) return(ER_NO_TRIG_DEFINED);
   if( argc == 2 ) {
      if( (mode = ParseTraceMode(&cmdString[(U16)argv[1]])) == -1 )
	 return(ER_INVALID_MODE);      
      if( (err=TrigTraceModeSet(trigId,mode)) != GOOD ) return(err);
   }
   if( (err=TrigTraceModeGet(trigId,&mode)) != GOOD )
      return(err);
   if( mode == TRACE_PRE ) lstrcpy(resultBuff,PRE_TEXT);
   else if( mode == TRACE_POST ) lstrcpy(resultBuff,POST_TEXT);
   else lstrcpy(resultBuff,CENTER_TEXT);
   return(SendCliResults(resultBuff,cliServerHandle));
}

#pragma argsused
RETCODE EXPORT TrigCliClearTrigger(LPSTR cmdString, U32 argc, U32 argv[]) {
   if( !trigId ) return(ER_NO_TRIG_DEFINED);
   return(TrigTriggerClear(trigId));
}

#pragma argsused
RETCODE EXPORT TrigCliClose( LPSTR cmdString, U32 argc, U32 argv[] ) {
   RETCODE err=GOOD;
   if( trigId ) {
      err = TrigTriggerClose(trigId);
   }
   TrigTriggerAccept(trigId);
   return(err);
}

RETCODE EXPORT TrigCliOpen( LPSTR cmdString, U32 argc, U32 argv[] ) {
   RETCODE err;
   if( trigId ) {
      if((err=TrigTriggerClose(trigId))!=GOOD) return(err);
      trigId = 0L;
   }
   if( argc != 2 ) return(ER_CLI_SYNTAX);
   return(TrigTriggerOpen(&trigId,NULL,&cmdString[(U16)argv[1]]));
}

RETCODE EXPORT TrigCliSave(LPSTR cmdString, U32 argc, U32 argv[]) {
   if( !trigId ) return(ER_NO_TRIG_DEFINED);
   if( argc != 2 ) return(ER_CLI_SYNTAX);
   return(TrigTriggerSaveAs(trigId,&cmdString[(U16)argv[1]]));
}

/****************************** LOCAL FUNCTIONS *****************************/

/*****************************************************************************
** 
**    TriggerInitialize
** 
**    Description:
**       Set trigger to default configuration.
**
**    Parameters:
**       input:
**          trigger:      far pointer to trigger structure to initialize
**       output:
**          none
*****************************************************************************/
VOID TriggerInitialize(TRIGGER FAR *trigger) {
   LOOP_VAR evt,level,cond,counter;
   trigger->numTraceBuffers = 1;
   trigger->traceMode   = TRACE_PRE;
   trigger->fw.counterMode = defCounterMode; /* <Judy 6/6/1997> */
   trigger->fw.ignoreEmon = FALSE;
   trigger->enableBreak = 0;
   trigger->qualifierMode = QUAL_BUS;

   trigger->curCond     = EV0_COND;
   trigger->curLevel    = 0;

   for(evt=0; evt<NUM_EVENTS; evt++) {
      for(level=0; level<NUM_LEVELS; level++) 
	 trigger->eventName[evt][level] = NULL;
   }
   
   for(level=0; level<NUM_LEVELS; level++) {
      for (cond=0; cond<NUM_EVENT_COND; cond++) {
         trigger->fw.action[cond][level] = level; /* NULL_MASK; <Judy 8/15/96> */
	 trigger->fw.useEvt[cond][level] = FALSE;
	 trigger->fw.useExt[cond][level] = FALSE;
      }
   }
   for (counter=0; counter<NUM_COUNTERS; counter++) {
      trigger->terminalCount[counter] = 1;
   }
   trigger->modeUnit=0;
}

/* Returns TRUE is event is never used in trigger */
BOOLEAN EventNotUsed(TRIGGER FAR *trigger, LOOP_VAR event) {
   LOOP_VAR level;
   for( level=0; level < NUM_LEVELS; level++ ) {
      if( trigger->fw.useEvt[event][level] ) return(FALSE);
   }
   return(TRUE);
}

/*****************************************************************************
** 
**    ProgramEvents
** 
**    Description:
**       Programs the events (address, data, status, extra).
**
**    Parameters:
**       input:
**          trigger:  trigger definition including array of names of events
**       output:
**          none
*****************************************************************************/
RETCODE ProgramEvents(TRIGGER FAR *trigger) {
   LOOP_VAR group, event; 
   EVENT_GROUP_INFO sdEvent[NUM_EVENTS];
   RETCODE err;
   BOOLEAN slotPresent;
   BOOLEAN abortFromEsc;

   
   for (group=0; group<NUM_GROUPS; group++) {
      if ((err = SdnReadMember(SDN_TRACE_0_SLOT_PRESENT+group,&slotPresent))
	  != GOOD) return(err);
      if (!slotPresent) continue;   /* NO TMOD --> skip programming */


      err = TskCheckAbort(&abortFromEsc);
      if(err!=GOOD) return err;
      if (abortFromEsc)
	 return(ER_ABORT_FROM_ESC);


      for (event=0; event<NUM_EVENTS; event++) {

	 err = TskCheckAbort(&abortFromEsc);
	 if(err!=GOOD) return err;
	 if (abortFromEsc)
	    return(ER_ABORT_FROM_ESC);

	 if( (trigger->eventName[event][trigger->curLevel]==NULL)
	     || (lstrlen(trigger->eventName[event][trigger->curLevel])==0)
	     || EventNotUsed(trigger,event) )  {
	    sdEvent[event].hi = sdEvent[event].lo = sdEvent[event].mask = 0;
	    sdEvent[event].not = 1;
	 }
	 else {
	    LPSTR nameStr;
	    BOOLEAN exists;
	    nameStr = trigger->eventName[event][trigger->curLevel];
	    if( (err=EvtDoesEventExist(nameStr,&exists))!=GOOD ) return(err);
	    if( !exists ) return(ER_INVALID_EVENT_NAME);
	    if( (err=EvtSetActiveEvent(trigger->eventServerId,nameStr)) 
	       != GOOD ) return(err);
	    if( (err=EvtGetEventGroupInfo(trigger->eventServerId,
			group, &sdEvent[event])) != GOOD ) return(err);
	 }
      }


      err = TskCheckAbort(&abortFromEsc);
      if(err!=GOOD) return err;
      if (abortFromEsc)
	 return(ER_ABORT_FROM_ESC);


      if((err=SdnWriteMember(SDN_EVTREC+group,(U8 FAR *)&sdEvent,GOOD))
	 !=GOOD) return(err);
   }
   return(GOOD);
}

U16 ConvertCond(EVENT_COND cond) {
   switch (cond) {
      case EV0_COND: return 0;
      case EV1_COND: return 1;
      case EV2_COND: return 2;
      case EV3_COND: return 3;
      case EV4_COND: return 4;
      case EV5_COND: return 5;
      case EV6_COND: return 6;
      case EV7_COND: return 7;
      case TC0_COND: return CNTR0_COND;
      case TC1_COND: return CNTR1_COND;
      case EXT_COND: return 10;
   }
   return INVALID_EVENT_COND;
}

RETCODE CheckTriggerConditions(DESCRIPTOR id) {
   BOOLEAN tracing;
   RETCODE err;
   if((err=SdnReadMember(SDN_TRACING,&tracing))!=GOOD) return(err);
   /* force sequencer off automatically? If we didn't "halt" sequencer
      could still be running. */
/*   if( tracing ) return(ER_TRACE_TRIG_ON); */
   if ((err = EnableSequencer(FALSE)) != GOOD) return(err);
   ((TRIGGER FAR *)id)->trigModified = TRUE;
   return(GOOD);
}

RETCODE EnableSequencer(BOOLEAN enable) {
   BOOLEAN timedOut;
   sequencerEnabled = enable;
   return(SdnWriteCmdReadResponse(SDN_ENABLE_SEQUENCER,&enable,GOOD,
				  SDN_ENABLE_SEQUENCER_ACK,0,&timedOut));
}
/**************************************************************************
**
** lmemcpy
**
***************************************************************************/
LPSTR lmemcpy(LPSTR dest, LPSTR source, WORD len) {
   WORD i;
   LPSTR s, d;

   s = source; d = dest;
   for (i = 0; i < len; i++) *d++ = *s++;
   if (i == len)
      return(dest);
   return(NULL);
}


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