/****************************************************************************
**
**  Name:  trace.c
**
**  Description:
**     Routines to handle the trace data displaying setup, manages the host
**     trace files and to interface with the trace acquisition drivers.
**
**  Status:  PRELIMINARY
**
**  $Log:   S:/tbird/mt2_186/trace/trace.c_v  $
** 
**    Rev 1.10   04 Jun 1998 14:26:16   Eric
** Fixed the bug of Timestamp overflow.
** 
**    Rev 1.9   10 Feb 1998 10:48:36   Eric
** Correct the oldest frame set after collecting buffer.
** 
**    Rev 1.8   21 Jul 1997 15:00:00   Judy
** 
**    Rev 1.7   27 May 1997 15:30:26   Judy
** No change.
** 
**    Rev 1.6   27 May 1997 15:25:36   Judy
** 
**    Rev 1.5   17 Apr 1997 14:17:04   Judy
** 
**    Rev 1.4   10 Apr 1997 08:31:42   Judy
** To fix trace window open error while setting trigger on/off.
** 
**    Rev 1.3   04 Feb 1997 18:19:18   Judy
** 
**    Rev 1.2   22 Jan 1997 16:09:52   Judy
** 
**    Rev 1.1   07 Jan 1997 15:50:52   Judy
** 
**    Rev 1.0   16 Dec 1996 15:26:00   Judy
** Initial revision.
** 
**    Rev 1.4   21 Nov 1996 19:14:16   Judy
** 
**    Rev 1.3   15 Nov 1996 16:48:58   Judy
** 
**    Rev 1.2   23 Oct 1996 18:09:16   Judy
** 
**    Rev 1.1   14 Oct 1996 18:15:16   Judy
** 
**    Rev 1.0   27 Aug 1996 15:23:14   Judy
** Initial revision.
** 
**    Rev 1.0   27 Aug 1996 14:49:04   Judy
** Initial revision.
** 
**    Rev 1.0   14 Jun 1996 17:05:16   Judy
** Initial revision.
** 
**    Rev 1.98   23 Oct 1994 14:40:20   mindy
** fixed a couple problems with getting/not getting frame at the end of the buffer.
** 
**    Rev 1.97   18 Oct 1994 08:39:30   mindy
** server now read btm enable from profile
** 
**    Rev 1.96   13 Sep 1994 09:36:04   ernie
** Changed logic that waits for tracing to stop after a request.  Now
** this waits for a time of 5 seconds rather than 500 iterations of a
** loop.  The loop method was timing out too soon on a Pentium 90 PC.
** 
**    Rev 1.95   08 Aug 1994 10:58:02   mindy
** slight bug in creating address type for linked cursor
** 
**    Rev 1.94   14 Jul 1994 07:09:02   mindy
** get/set btm enable
** 
**    Rev 1.93   30 Jun 1994 09:07:52   mindy
** fixed up linked cursor support
** 
**    Rev 1.92   10 May 1994 10:20:30   ernie
** Added external functions to set/get DebugEmon state.
** 
**    Rev 1.91   08 Nov 1993 20:59:10   mindy
** add max trace buffer support
** 
**    Rev 1.90   28 Jul 1993 09:50:32   john
** Changed output of frequency from 'hz' to 'Hz'.
** Modified code to accept blanks between the number and the M/k(hz)
** designations.
** 
** Added code to prevent incredibly small values from being accepted.
** The code to check valid for valid frequencies was comparing floats
** to doubles, and sometimes giving incorrect answers.
** 
**    Rev 1.89   27 Jul 1993 14:30:22   john
** Modified timestamp header to be right justified with the time display.
** Added chars to the zero frame text to accomodate the new size of the
** timestamp field width.
** Added a space between the time and unit value of the timestamp display.
** 
**    Rev 1.88   26 Jul 1993 12:40:00   paul
** Replace CHECK_ABORT with TskCheckAbort for esc key
** 
**    Rev 1.87   24 Jul 1993 13:35:26   mindy
** minor adjustments to timestamp output
** 
**    Rev 1.86   22 Jul 1993 15:41:12   mindy
** added timestamp support
** 
**    Rev 1.85   13 Jul 1993 19:36:16   doug
** Errors consolidated in errtext/mkerrors.h and use generic error
** 
**    Rev 1.84   01 Jun 1993 12:30:34   ernie
** Added traceInfoDirty flag set by the trace stopped callback.  When
** the presenter asks for trace data that depends on the trace info, the
** information is retrieved at that time.  This improves performance when
** the trace presenter is not open.
** 
**    Rev 1.83   07 Apr 1993 17:16:18   mindy
** FormatFrameToText is now done by making a call to an eventtemplate
** routine this allow us to be able to change the trace display format
** by just changing the ev*.cfg file.
** 
**    Rev 1.82   02 Apr 1993 07:50:56   ernie
** Fixed bit selection for upper word of group T (TPU/GPT bits)
** 
**    Rev 1.81   11 Jan 1993 17:25:10   john
** processor dlls #def's changed, code mod'ed to match
** 
**    Rev 1.80   07 Jan 1993 07:24:50   mindy
** a) numframes wrong if end = start = 0.
** b) format of frame text now includes John's changes - with bug
** fixes included!
** c) Read Trace had major problems with frame placement in raw frame
** buffer.
** 
**    Rev 1.79   17 Dec 1992 10:32:16   john
** fixed comment definition error
** 
**    Rev 1.78   16 Dec 1992 16:36:50   john
** added code to properly format trace for 331
** 
**    Rev 1.77   16 Dec 1992 15:31:44   mindy
** trace moved to fw
** 
**    Rev 1.75   11 Nov 1992 07:01:00   mindy
** fixed initialization bug in trace presenter
** 
**    Rev 1.74   04 Nov 1992 15:21:08   mindy
** fixed ppr7025
** 
**    Rev 1.73   04 Nov 1992 12:03:12   ernie
** Changed low-level trace read function to request only a maximum of 0x10
** frames in each call.  This was necessary to fix a problem with an SX PC
** rebooting unexpectedly in the middle of receiving a large data packet.
** Until the real reason for the rebooting is found, the reduced maximum
** size of trace reads should remain in effect.
** 
**    Rev 1.72   25 Oct 1992 11:16:06   mindy
** When trace clear happened the pre/post counts weren't getting cleared 
** out so get number of frames routines was returning negative number
** of frames.
** 
**    Rev 1.71   21 Oct 1992 17:15:12   mindy
** a) changed max cycles to scan before querying user ppr 6995/6999
** b) change overrun adjustment to just be a constant - no longer call
**    a subroutine.
** c) cleaned up the two zillion warnings
** d) fixed format problems ppr 6965
** 
**    Rev 1.70   14 Oct 1992 14:57:16   mindy
** a) changed update trace to set trace frame to min of trigger and end.
** b) removed kludge in cli get frame area size
** c) if there was only one frame used to figure starting bus cycle - got
**    a UAE.
** d) some trace bits were off. 
** e) fixed some trace caching problems.
** 
**    Rev 1.69   07 Oct 1992 15:00:12   ernie
** Changed both FRAME_OVERRUN and FRAME_OVERRUN_TRIGC to 8 frames.  This
** was necessitated by TMAN hardware changes.  This fixes ppr6890.
** 
**    Rev 1.68   06 Oct 1992 06:36:10   mindy
** a) added valid id check before doing trcupdate.
** b) cache size was too big.
** c) valid cache entry number off by one.
** 
**    Rev 1.67   30 Sep 1992 11:39:12   mindy
** a) Change trace caching to fill cache with start frame - cache_size/2
**    so backward trace gets some benefit too.
** b) Changed get debug emon routine to handle the case where step followed
**    by go both appear in trace buffer.
** 
**    Rev 1.66   23 Sep 1992 06:31:24   mindy
** fixed trc search cli set frame bug
** 
**    Rev 1.65   18 Sep 1992 10:48:54   ernie
** Fixed memory leak in open/close pair.  The eventServerId was not being
** closed in TrcClose().
** 
**    Rev 1.64   16 Sep 1992 18:55:18   mindy
** a) changed all sds calls to use sdn routines.
** b) changed cache size to 256 frames
** 
**    Rev 1.63   16 Sep 1992 09:51:20   mindy
** a) change lowest get trace frames routine to "cache" 100 frames.
** b) changed FormatFrameToText routine to no longer use event template
**    calls - now format is hard coded and very processor specific!!!
** c) debug emon information is calculated once per trace buffer and remains
**    valid until tracing is turned ON.
** 
**    Rev 1.62   11 Sep 1992 12:38:32   ernie
** Changed FRAME_OVERRUN_TRIGC from 8 to 7 frames.  This was necessitated
** by changes to the TMAN xilinx hardware.
** 
**    Rev 1.61   08 Sep 1992 10:27:20   mindy
** added include for events
** 
**    Rev 1.60   31 Aug 1992 05:11:34   mindy
** a) changed valid frame number routine to not return an error for any
**    frame number when no frame is valid because of cycles collected are
**    collected outside of emulation.
** b) fixed how starting bus cycle is retrieved.  Now we just back up to
**    the previous frame qualified and go forward.
** 
**    Rev 1.59   28 Aug 1992 13:13:28   mindy
** cleaned up problems with debugemon info
** 
**    Rev 1.58   27 Aug 1992 15:23:12   mindy
** a) when we open trace we need to calculate the debugEmon pre/post stuff
**    because we are "setting" the trace buffer and there might be trace data
**    collected.
** b) With previous addition I was getting into an infinite loop calculating
**    the debug Emon stuff.
**    Thus I changed how getDebugEmon operates
** c) When setting a frame and there are no "emon"able frames then I just
**    return good - not returning error to user since presenter will handle
**    it better this way.
** d) cli forward_read command changed to avoid getting lock error.
** e) startoffset routine wrong - ernie's fix.
** 
**    Rev 1.57   27 Aug 1992 07:33:30   mindy
** a) added bus cycle user query.  After 60 some cycles if no bus cycle
**    has been found I query user to see if he wants to quit.
** b) tracing set routine changed to wait for SD_TRACING to change to new
**    value rather than just waiting on FW_TRACING_STATUS.
** c) Tracing callback routine uses the new read member without input
**    check so I can get the tracing value that caused the callback not
**    the tracing value that might come in immediately after the first
**    tracing callback happens.
** d) tracing events changed to be a tracing_on and tracing_off event since
**    different presenters need to be registered on one or the other and
**    by the timer the presenter reads the tracing value it could of changed
** 
**    Rev 1.56   25 Aug 1992 11:27:44   mindy
** cleared up some of the warnings
** 
**    Rev 1.55   22 Aug 1992 11:11:36   mindy
** Cleaned up the debug emon on/off calculations.
** Cleaned up the callback routines.
** 
**    Rev 1.54   21 Aug 1992 07:24:42   mindy
** a) fixed post/center number of frames being wrong problem.
**    This done in determining of the trace buffer is full.
** b) Trying to get the callback functions working - there's still a
** problem with the trace stuff not being updated automatically.
** 
**    Rev 1.53   19 Aug 1992 10:25:20   mindy
** can't use desc because CLEAR TRACE event registering too
** 
**    Rev 1.52   19 Aug 1992 07:57:18   mindy
** a) Now register on SD_TRACING and SD_CURRENT_SUBBUFFER since the fw will
**    update these fields only when they are changed.
** b) Removed force status update since it's now done automatically
** c) fixed bug with negative frame numbers in the cli trace read command.
** d) cli read commands return what data they have if an END_OF_BUFFER error
**    is returned.
** 
**    Rev 1.51   11 Aug 1992 09:58:04   mindy
** a) Removed processor specific stuff from trace open - now the configuration
**    information is read from a file: trcXXX.cfg as specified in the *.ini
**    file.
** b) parameters to traceOpen changed.
** c) uncommented out check for valid trace buffer - break when full needs to
**    be working
** d) Sub buffer counter is now incremented after the trigger position is
**    written so calculating "logical" sub buffer number is changed.
** 
**    Rev 1.50   10 Aug 1992 07:45:46   tom
** CLI registration changes.
** 
**    Rev 1.49   06 Aug 1992 07:14:28   mindy
** a) increase frame number to handle largest negative frame number
** b) fixed bug of not being able to reach starting frame
** 
**    Rev 1.49   06 Aug 1992 07:12:40   mindy
** a) incread frame number area (needed more room for -xxxxxx case)
** b) could set frame number to starting frame number.
** 
**    Rev 1.48   03 Aug 1992 09:39:00   mindy
** added 332 support
** 
**    Rev 1.47   28 Jul 1992 06:59:22   mindy
** a) change read raw trace frames not to force bus cycles any more.
**    caller  must now determine what type of cycles they want.
** b) only want always visible evttmptl field types in trace display.
** 
**    Rev 1.46   24 Jul 1992 14:45:08   doug
** using generic shared data
** 
**    Rev 1.45   17 Jul 1992 13:56:40   mindy
** a) cli read frame routines needs to accept and handle negative frame
**    numbers.
** b) trace read frames routines now check for allocating more than 64K
**    of memory.
** c) some trace bits are not to be displayed in trace.
** d) if debugEmon is TRUE then I want to display the emon trace bit.
** 
**    Rev 1.44   10 Jul 1992 08:57:38   mindy
** added include file(s) needed to get rid of 3.1 warnings
** 
**    Rev 1.43   07 Jul 1992 10:09:12   mindy
** made open of template and event common
** 
**    Rev 1.42   07 Jul 1992 10:04:12   mindy
** a) added debug emon support.  Changing debug Emon affects the frame numbering
**    the start align mode - it also changes the number of frames, etc.
** b) changed evttmplt stuff to reference the "default" template.
** 
**    Rev 1.41   25 Jun 1992 12:35:02   mindy
** a) removed swat stuff (timestamp and tsunits, etc)
** b) removed debugEmon routines just left cli routine.
** c) removed go/halt
** d) changed the trace frame numbering stuff to reflect status of
**    debugEmon
** 
**    Rev 1.40   22 Jun 1992 07:56:48   mindy
** added get sub buffer size routine
** 
**    Rev 1.39   15 Jun 1992 08:22:40   mindy
** When tracing is ENABLEd we need to program the trigger hardware.
** 
**    Rev 1.38   28 May 1992 08:00:30   mindy
** I now register on the trigger position once to try and improve the trace
** performance.
** 
**    Rev 1.37   18 May 1992 08:39:12   mindy
** problems in cli trace open
** 
**    Rev 1.36   14 May 1992 11:39:22   mindy
** removed GetErrorText routine and added ErrInitDLL call
** 
**    Rev 1.35   13 May 1992 08:08:40   mindy
** get dll handle since cli might not be initialized
** 
**    Rev 1.34   12 May 1992 12:42:52   mindy
** a) removed unused error codes
** b) added TrcGetErrorText 
** 
**    Rev 1.33   04 May 1992 10:23:44   mindy
** oops!
** 
**    Rev 1.32   04 May 1992 10:17:04   mindy
** a) updated signal information - which signals are valid when bit0-3 are
**    active.
** b) ReadTraceFrames now only searches forward if caller is reading forward.
** c) BackwardReadTrace now calls ForwardReadTrace to shared some code.
** 
**    Rev 1.31   30 Apr 1992 08:30:08   mindy
** Added a check for emon fixing PPR5304.  If EMON is not ON then we setup the
** search parameters to start at the current startFrame and search for the
** first frame with the EMON bit ON.  Also if we see the emon bit turn OFF
** we exit immediately.  This change might mess up the old probe since emon
** signal toggles so beware!!!
** 
**    Rev 1.30   28 Apr 1992 08:28:06   mindy
** a) Fixed ppr5361 - added abort support.
** b) Fixed ppr5542 - tracing status - if trace empty then collecting buffer is
**    always 0.
** c) Added a routine to return the trace cli id so dq commands from cli could
**    work without requiring user to enter a trace id.
** d) trace cli open now just changes the state values if open is called and
**    trace is already opened.  Can no longer do a close/open since that would
**    change the id and if the dq called in and got the trace cli id he would
**    blow up the system!
** 
**    Rev 1.29   23 Apr 1992 11:32:56   mindy
** a) changed memory allocation to use TMalloc
** b) added keyword parsing to cli commands.
** 
**    Rev 1.28   03 Apr 1992 12:01:18   mindy
** removed the portion of the frame to address routine that scans backwards
** through the bus cycles to get the last code read address of the given
** frame isn't a code read.  See rev 1.27's comment.
** 
**    Rev 1.27   03 Apr 1992 08:36:32   mindy
** Added a new routine to determine the address given a frame number - this one
** scans the previous bus cycles to get an address if the incoming frame doesn't
** point to an instruction read - this takes a long time.  I'm going to remove
** this feature for this release but wanted the full code under pvcs.
** 
**    Rev 1.26   31 Mar 1992 14:51:02   mindy
** a) added new routine to count number of instruction boundaries occur
**    between current and next refill. This is processor specific and should
**    be moved. !!!
** b) no reason to do extra lmemcpy if foundFrames == current index (idx)
** 
**    Rev 1.25   27 Mar 1992 11:07:24   mindy
** a) take out buffer validity check until break on full is working so
** I can access all buffers. !!!
** b) foundOne not filled in correctly for bus cycles.
** c) execution breakpoint changed event names.
** 
**    Rev 1.24   17 Mar 1992 08:47:54   mindy
** wrong frame number was being include in the raw trace structure.
** 
**    Rev 1.23   13 Mar 1992 08:57:32   mindy
** a) changed interface to getting raw frames.
** b) setting trace frame number and search frame number had a an unsigned
**    verses signed problem.
** 
**    Rev 1.22   11 Mar 1992 10:41:20   mindy
** added code to handle special status fields like refill- and status-
** that are not qualified.
** 
**    Rev 1.21   28 Feb 1992 07:55:50   mindy
** in go/halt now am using real bkptexec.h names
** 
**    Rev 1.20   27 Feb 1992 11:24:26   mindy
** a)
** a) leave DebugEmon TRUE
** b) when trace frames hits the end of the logical trace buffer - the
**    number of frames until the end was calculated wrong - off by one.
** c) valid trace buffers include the currently active buffer.
** 
**    Rev 1.19   18 Feb 1992 14:10:52   mindy
** Made numerious changes to support the new trace presenter - now have
** a backward read and forward read no longer have trctraceread().
** 
**    Rev 1.18   29 Jan 1992 16:50:52   ernie
** a) FIxed problem in search trace when trace store was divided into multiple
**    trace buffers.
** b) Hopefully fixed the off by one problems when calculating trigger, start
**    end position. Probably haven't seen the last of these type of problems.
** 
**    Rev 1.17   27 Jan 1992 11:28:14   mindy
** removed dummy dq server routines
** 
**    Rev 1.16   27 Jan 1992 10:00:32   ernie
** a) Fixed problem in search trace.
** b) num of frames routine returns the number of frames (no longer inc
**    by one).
** c) Code added to calculate the correct trigger frame when we switch 
**    into a trace buffer via the trigger and continue feature.
** 
**    Rev 1.15   23 Jan 1992 14:04:42   ernie
** Trying to clean up the handling of an empty trace buffer.
** 
**    Rev 1.14   22 Jan 1992 13:23:56   doug
** Added code to unlock data segment in LibMain
** 
**    Rev 1.13   17 Jan 1992 11:10:48   courtney
** Revised return code of LibMain to be compatible with Windows.
** 
**    Rev 1.12   14 Jan 1992 11:36:10   ernie
** a) frame overrun is really 11 not 10
** b) !!! leaving debugEmon TRUE to avoid LONG delays when emon bits
**    from test probe is bad.
** c) frame number for bus cycles is the last frame (i.e.: the frame
**    with the qualifier bit set).
** d) Changed the way tracing is set.
** e) read frame number in cli trace read and trace search need atol not atoi
** f) cli open default opens in clock cycles (quicker then bus cycles)
** g) added a routine to deterine if start of trace buffer is offset by
**    a sub buffer. (i.e.: previous trace buffer ended in an even subbuffer).
** h) beefed up handing an empty trace buffer.
** 
**    Rev 1.11   07 Jan 1992 10:05:40   mindy
** a) Changed all references of BOOL to BOOLEAN so now BOOLEAN are all
**    8 bits.
** b) Removed "until we have a probe" kludges
** c) added a temp. version of go and halt (for debug)
** d) fixed bit of looking at wrong group to determine qualifier bits
**    and emon bit.
** e) fixed defines for frame and sub buffer fields within the trigger position.
** 
**    Rev 1.10   11 Dec 1991 14:48:10   mindy
** a) trace is now the only server in trace.dll so LibMain moved in and 
** got rid of initializing trace server.
** b) cleaned up the errors - assigned text and sent to Tom.
** 
**    Rev 1.9   06 Dec 1991 10:22:14   mindy
** changed to use common routines in swat.c.
** 
**    Rev 1.8   02 Dec 1991 11:01:10   mindy
** a) use global errors for mem lock and alloc errors.
** b) replaced kludged timestamp with swat stuff
** c) added timestamp unit support (including cli commands)
** 
**    Rev 1.7   20 Nov 1991 11:07:14   mindy
** a) Added timestamp trace server support.  This affected the header and
**    outputting of bus and clock trace frames.  The current timestamp
**    value is kluded and needs to be replaced with pa/cc calls(!!!).
** b) added timestamp cli routine.
** c) changed numerious server calls because they didn't return an error if
**    the MemLock failed.
** d) Added trace search cli routines.
** e) Now check to see if search event exists - rather than just telling
**    event server it's the active event because that creates a "new" one
**    if it doesn't exist.  In this case I think the user would want to
**    know he had a "blank" event.
** f) Removed DadSetDqFrame callers will just call trace server directly.
**    All of these Dad routines need to be removed (!!!).
** 
**    Rev 1.6   15 Nov 1991 15:03:42   mindy
** a) changed error # to conform to system numbers.
** b) put prototypes in alphabetical order
** c) added cli command routines
** d) added trace search routines.
** 
**    Rev 1.5   07 Nov 1991 14:26:00   mindy
** Put present copy back under PVCS so I could mark version I sent to
** MHS.
** 
**    Rev 1.4   01 Nov 1991 09:16:46   mindy
** new version to support final trace presenter
** 
**    Rev 1.3   17 Sep 1991 07:53:34   ernie
** Lots of changes for PDR2 release:
** 1. Trace data now returned as 128 bits, regardless of valid data width.
** 2. Trigger position information has changed format.
** 3. Still need to compute and flag valid/invalid frames.
** 
**    Rev 1.2   06 Sep 1991 08:50:44   mindy
** Trace server now goes to the box to get real data.  Template stuff not
** complete.
** 
**    Rev 1.1   31 Jul 1991 14:45:36   john
** Updated to copy used for basic system release.
** 
**    Rev 1.0   26 Jul 1991 15:53:32   jim
** Initial revision.
**
**  $Header:   S:/tbird/mt2_186/trace/trace.c_v   1.10   04 Jun 1998 14:26:16   Eric  $
**
**  Copyright (C) 1991 Microtek International.  All rights reserved.
**
*****************************************************************************/

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

#include "ctype.h"
#include "math.h"
#include "stdlib.h"

#ifndef __STRING_H
#include <string.h>
#endif

#ifndef __TIME_H
#include "time.h"
#endif

#ifndef _BASEWIND_
#include "basewind.h"
#endif
#ifndef _BKPTEXEC_
#include "bkptexec.h"
#endif
#ifndef _BKROOT_
#include "bkroot.h"
#endif
#ifndef _ENLIB_
#include "enlib.h"
#endif

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

#ifndef _HEAP_
#include "heap.h"
#endif
#ifndef _TRACE_
#include "trace.h"
#endif
#ifndef _TRIG_
#include "trig.h"
#endif
#ifndef _EVTTMPLT_
#include "evttmplt.h"
#endif
#ifndef _EVENT_
#include "event.h"
#endif
#ifndef _DASM_
#include "dasm.h"
#endif
#ifndef _EVENTS_
#include "events.h"
#endif
#ifndef _CLISRV_
#include "clisrv.h"
#endif
#ifndef _SDPROBE_
#include "sdprobe.h"
#endif
#ifndef _SSHARED_
#include "sshared.h"
#endif
#ifndef _TBIRDMEM_
#include "tbirdmem.h"
#endif
#ifndef _HOSTERRS_
#include "hosterrs.h"
#endif
#ifndef _LOCAL_
#include "local.h"
#endif
#ifndef _PROC_
#include "proc.h"
#endif
#ifndef  _SDS2ABI_
#include "sds2abi.h"
#endif
#ifndef _TRIG_
#include "trig.h"
#endif



                       /****************************
                        *                          *
                        *     LOCAL DEFINITIONS    *
                        *                          *
                        ****************************/
#define  MAX_TEXT_PER_FRAME   128L      /* 128 <JUDY 8/12/96> */
#define  MAX_FOR_BUS_CYCLE    50
#define  MAX_CYCLES_TO_SCAN   500
#define  FRAME_NUM_AREA_SIZE  10
#define  EVENT_NAME_LENGTH    64
#define  EMON_BIT_MASK        0x10  /* bit 4 is emon bit in all processors */

#define  TIMESTAMP_OPT        0x01
#define  STATUS_OPT           0x08
#define  TRACE_OPT            0x10
#define  ACTION_OPT           0x20
#define  LEVEL_OPT            0x40
#define  EVENT_OPT            0x80
#define  TIMESTAMP_TEXT        " timestamp "
#define  STATUS_TEXT           " status "
#define  TRACE_TEXT            " trace-bit "
#define  LEVEL_TEXT            " SL "
#define  EVENT_TEXT            " bus-event "
#define  EVENT_2TEXT           " 76543210  "
#define  ACTION_TEXT           " action "
#define  TRC_TEXT              " trc trc"
#define  TRC_2TEXT             " on  off"
#define  TC0TC1_TEXT           " tc0 tc0 tc1 tc1"
#define  TC0TC1_2TEXT          " inc rst inc rst"
#define  TC0TM1_TEXT           " tc0 tc0 tm1 tm1 tm1"
#define  TC0TM1_2TEXT          " inc rst on  off rst"
#define  TM0TC1_TEXT           " tm0 tm0 tm0 tc1 tc1"
#define  TM0TC1_2TEXT          " on  off rst inc rst"
#define  TM0TM1_TEXT           " tm0 tm0 tm0 tm1 tm1 tm1"
#define  TM0TM1_2TEXT          " on  off rst on  off rst"
#define  TIMESTAMP_LEN         12  /* max number of digits in timestamp */
#define  STATUS_LEN            8   /* max number of digits in timestamp */
#define  TRACE_LEN             11  /* max number of digits in timestamp */
#define  LEVEL_LEN             4   /* max number of digits in timestamp */
#define  EVENT_LEN             11  /* max number of digits in timestamp */
#define  ACTION_LEN            15  /* max number of digits in timestamp */
#define  END_OF_LINE_TEXT      "\r\n"

typedef struct {
   U16                traceBuffer;     /* active trace buffer */
   S32                startFrame;      /* logical frame in trace buffer */
   TRACE_CYCLES       cycleMode;       /* bus,clock, etc types of cycles */
   FRAME_DISPLAY_MODE frameMode;       /* Frame numbering scheme */
                                       /* header for bus and clock cycles */
   S8 header[NUM_HDR_LINES*MAX_HDR_LINE+1];

   DESCRIPTOR         templateId;      /* Id of active template */
   DESCRIPTOR         dqId;            /* Id of active dq server */
   
   DESCRIPTOR         traceSemaId;     /* Id of trace semaphore */
   DESCRIPTOR         activeBufDesc;   /* desc for active buffer */
   DESCRIPTOR         emonDesc;        /* desc for emon status */
   DESCRIPTOR         frameTypeDesc;   /* desc for trace frame type */
   DESCRIPTOR         traceFrameDesc;  /* desc for trace start frame */
   DESCRIPTOR         traceLenDesc;    /* desc for length of trace read */
   DESCRIPTOR         traceStoreDesc;  /* desc to read trace store memory */

   BOOLEAN            debugEmon;       /* send back EMON off cycles */

   U16                searchBuffer;     /* buffer to search */
   S32                searchStartFrame; /* logical starting search frame */
   S8 searchEvent[EVENT_NAME_LENGTH]; /* name of event to use in search */
   DESCRIPTOR         eventServerId;    /* event server for search event */
   BOOLEAN            timestampOn;   /* determines if timestamp field is on */
   S8                 tsMode;       /* RELATIVETOFRAME or DELTA ts mode */
   S32                zeroedFrame; /* frameNum to start abs. TS from. */
} TRACE_DESC_BLOCK;

typedef enum {                        // actionFlag
              TRC_START_ACT  = 0x80,  // bit 7: TRC_START_MASK
              TRC_STOP_ACT   = 0x40,  // bit 6: TRC_STOP_MASK
              TMR0_RST_ACT   = 0x20,  // bit 5: TC0_RST_MASK     | TC1_RST_MASK
              TMR0_START_ACT = 0x10,  // bit 4: TMR0_START_MASK  | CNT1_INC_MASK
              TMR0_STOP_ACT  = 0x08,  // bit 3: TMR0_STOP_MASK   |
              TMR1_RST_ACT   = 0x04,  // bit 2: TC1_RST_MASK     | TC0_RST_MASK
              TMR1_START_ACT = 0x02,  // bit 1: TMR1_START_MASK  | CNT0_INC_MASK
              TMR1_STOP_ACT  = 0x01,  // bit 0: TMR1_STOP_MASK   |
              CNT0_RST_ACT   = 0x04,
              CNT0_INC_ACT   = 0x02,
              CNT1_RST_ACT   = 0x20,
              CNT1_INC_ACT   = 0x10
} TRC_ACTION;

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

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

static HANDLE cliServerHandle = 0;  /* return address for CLI results */
static U32 numRetrieved;
static S32 startingFrame, endingFrame;
static DESCRIPTOR traceId=0, saveLastTraceId = 0;
static BOOLEAN traceInfoDirty=TRUE;
static float systemPeriod, krystalFrequency = 32768.;
static S8 optionFlag=0;
static DESCRIPTOR theTrigger=NULL;
static COUNTER_TYPE tcMode;
static long double zeroedFrameTS, preFrameTS;
static U8 trcMark=0;
static S32 trcMarkFrameOn=0,trcMark2FrameOn=0, trcMarkFrameOff=0;
static BOOLEAN tracing;
static S32 firstBufferFrame,lastBufferFrame;
                        /****************************
                         *                          *
                         *     LOCAL PROTOTYPES     *
                         *                          *
                         ****************************/
VOID FAR PASCAL SubBufferUpdate(DESCRIPTOR desc);
VOID FAR PASCAL TraceClearCallback(U32 event);
VOID FAR PASCAL TracingStateChange(DESCRIPTOR desc);
RETCODE  SetupBufferCheck(U16 buffer, BOOLEAN emon);
RETCODE  ValidFrameNumber(U16 buffer, S32 frame, BOOLEAN emon);
U16      CalculateTraceBufferFromSubBuffer(U16 subBuffer);
RETCODE  ReadTrace(DESCRIPTOR id, S32 numFrames, BOOLEAN raw, LPSTR *buffer);
RETCODE  FormatFrameToText(DESCRIPTOR tmpltId, TRACE_INFO *framePtr,
                          S32 prevFrame, DESCRIPTOR id, LPSTR dataPtr);
RETCODE  FormulateHeader(TRACE_DESC_BLOCK FAR *trace);
RETCODE  GetHardwareState(VOID);
VOID     InitializeTraceState(DESCRIPTOR id, TRACE_CYCLES tMode, 
                          FRAME_DISPLAY_MODE fMode);
RETCODE TrcGetActionText(ACTION_MASK *actionMask, LPSTR dataPtr);
RETCODE initOptionFlag(VOID);
RETCODE setOptionFlag2Profile(VOID);
VOID GetBusData (U32 addr, U8 status, U16 *data);
long double _strtold(const char *(s), char **(endptr));
                        /****************************
                         *                          *
                         *      EXECUTABLE CODE     *
                         *                          *
                         ****************************/

#pragma argsused
int FAR PASCAL LibMain(HANDLE hInstance, WORD wDataSeg, WORD cbHeapSize,
    LPSTR lpszCmdLine) {
   FARPROC lpProc;
   DESCRIPTOR desc;
   U32 value;
   if (cbHeapSize != 0)  UnlockData(0);   /* allows heap to grow */
   lpProc = MakeProcInstance((FARPROC)TracingStateChange, hInstance);
   SdnRegister(SDN_TRACING,lpProc,&desc);
   lpProc = MakeProcInstance((FARPROC)SubBufferUpdate, hInstance);
   SdnRegister(SDN_CURRENT_SUBBUFFER,lpProc,&desc);
   lpProc = MakeProcInstance((FARPROC)TraceClearCallback, hInstance);
   EnlRegister(EVENT_TRACE_CLEAR_TRACE, (EVCALLBACK)lpProc,&desc);
   {
      S8 str[128], profile[128];
      BOOLEAN btmEnable=FALSE;
      if(!GetProfileString("PowerViews","pwrviewdir","",profile,
         sizeof(profile))) lstrcpy(profile,"pwrviews.ini");
      GetPrivateProfileString("TraceInfo","btmCycles","",(LPSTR)str,
         sizeof(str), profile);
      if(strncmpi(str, "enabled", strlen(str))==0) btmEnable = TRUE;
      SdnWriteMember(SDN_BTM_ENABLE, (U8 FAR *)&btmEnable, GOOD);
   }
   value = 20;   /* update every 3 seconds */
   SdnWriteMember(SDN_UPDATES_PER_MINUTE, (U8 FAR *)&value, GOOD);
   ErrInitDLL(MODULE_TRACE,"trace.dll");
   /* initialize successfully */
    return(TRUE);
}

/**************************************************************************
**
** InitCServer
**
***************************************************************************/
RETCODE EXPORT InitCServer(HANDLE cliHandle, HANDLE dllHandle) {
   CSERVER_NEW_REGISTRATION FAR * msgBufPtr;

   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 = 10;
   msgBufPtr->dllNameIndex = 11;
   msgBufPtr->numberOfCommandsIndex = 12;
   msgBufPtr->commandStartIndex = 13;
   SendMessage(cliHandle, CLI_NEW_SVR_REGISTRATION, CLI_NEW_SVR_REGISTRATION,
      (DWORD)msgBufPtr);
   return(GOOD);
}

/*****************************************************************************
**
**    TrcTraceOpen
**
*****************************************************************************/
RETCODE EXPORT TrcTraceOpen(DESCRIPTOR FAR *id, LPSTR fileName,
                            TRACE_CYCLES cycleMode,
                            FRAME_DISPLAY_MODE frameMode) {
   TRACE_DESC_BLOCK FAR *trace;
   MEMBER_INDEX       memberIndex;   
   MEMBER_NAME memberName[SD_MAX_NAME];
   RETCODE err;
      /* Only support HW trace for now */
   if (lstrcmp((LPSTR)fileName, "hwtrc") != 0) return(ER_ONLY_HW_SUPPORT);
   if( frameMode != TRIGGER_ALIGN ) return(ER_NOT_SUPPORTED);

   /*
    *** Get memory for trace info
    */
   if ((trace = (TRACE_DESC_BLOCK FAR *) TMalloc(sizeof(*trace))) == NULL)
      return(ER_OUT_OF_MEMORY);

   if((err=TrigTriggerOpen(&theTrigger,"","default"))!=GOOD) return(err);
   /*
    *** Open an event template and set active template to default
    */
   if( (err=EvtOpenEvent(&trace->eventServerId,"default")) != GOOD )
      return(err);

   if( (err = TmpltOpenTemplate(&trace->templateId)) != GOOD )
      return(err);

   if( (err = SdRegisterSemaphore(SD_TRACE_SEMAPHORE, NULLPTR,
                 &trace->traceSemaId)) != GOOD) return(err);
   
   if( (err = SdGetMemberIndex(trace->traceSemaId,&memberIndex)) 
      != GOOD) return(err);
   
   wsprintf(memberName,"%s %d", SD_TRACE_START_FRAME, memberIndex);
   if((err=SdRegister(memberName,NULLPTR,&trace->traceFrameDesc))!=GOOD)
      return(err);

   wsprintf(memberName,"%s %d", SD_FRAME_TYPE, memberIndex);
   if((err=SdRegister(memberName,NULLPTR,&trace->frameTypeDesc))
      !=GOOD) return(err);
   wsprintf(memberName,"%s %d", SD_ACTIVE_BUFFER, memberIndex);
   if((err=SdRegister(memberName,NULLPTR,&trace->activeBufDesc))!=GOOD)
      return(err);

   wsprintf(memberName,"%s %d", SD_BUFFER_EMON, memberIndex);
   if((err=SdRegister(memberName,NULLPTR,&trace->emonDesc))!=GOOD)
      return(err);
   
   wsprintf(memberName,"%s %d", SD_TRACE_BUFF_LEN, memberIndex);
   if((err=SdRegister(memberName,NULLPTR,&trace->traceLenDesc))!=GOOD)
      return(err);

   wsprintf(memberName,"%s %d", SD_TRACE_STORE, memberIndex);
   if((err=SdRegister(memberName,NULLPTR,&trace->traceStoreDesc))!=GOOD)
      return(err);

   initOptionFlag();

   InitializeTraceState((DESCRIPTOR)trace, cycleMode, frameMode);

   if((err=SdWriteMember(trace->frameTypeDesc,(U8 FAR *)&trace->cycleMode,
      GOOD)) != GOOD ) return(err);
   if((err=SdWriteMember(trace->activeBufDesc,(U8 FAR *)&trace->traceBuffer,
      GOOD)) != GOOD ) return(err);
   if((err=SdWriteMember(trace->emonDesc,(U8 FAR *)&trace->debugEmon,GOOD))
      != GOOD ) return(err);

   /* formulate the header given the template */
   FormulateHeader(trace);
   
   *id = (DESCRIPTOR)trace;
   saveLastTraceId = *id;

   return(GOOD);
}

/*****************************************************************************
**
**    TrcTraceClose
**
*****************************************************************************/
RETCODE EXPORT TrcTraceClose(DESCRIPTOR id) {
   TRACE_DESC_BLOCK FAR *trace;
   RETCODE err;
   trace = (TRACE_DESC_BLOCK FAR *)id;
   if((err=TmpltTemplateClose(trace->templateId)) != GOOD ) return(err);
   if((err=EvtCloseEvent(trace->eventServerId)) != GOOD ) return(err);
   if((err=SdUnRegister(trace->traceFrameDesc))!=GOOD) return(err);
   if((err=SdUnRegister(trace->frameTypeDesc))!=GOOD) return(err);
   if((err=SdUnRegister(trace->activeBufDesc))!=GOOD) return(err);
   if((err=SdUnRegister(trace->emonDesc))!=GOOD) return(err);
   if((err=SdUnRegister(trace->traceLenDesc))!=GOOD) return(err);
   if((err=SdUnRegister(trace->traceStoreDesc))!=GOOD) return(err);
   if((err=SdUnRegisterSemaphore(trace->traceSemaId))!=GOOD) return(err);
   setOptionFlag2Profile();
   TFree((LPSTR)id);
   return(GOOD);
}

/*****************************************************************************
**
**    TrcTraceTemplateSet
**
*****************************************************************************/
RETCODE EXPORT TrcTraceTemplateSet(DESCRIPTOR id, LPSTR name) {
   return(TmpltSetTemplateName(((TRACE_DESC_BLOCK FAR*)id)->templateId,name));
}

/*****************************************************************************
**
**    TrcTraceTemplateGet
**
*****************************************************************************/
RETCODE EXPORT TrcTraceTemplateGet(DESCRIPTOR id, LPSTR name, U16 maxLen) {
   return(TmpltGetTemplateName(((TRACE_DESC_BLOCK FAR*)id)->templateId, 
                               name, maxLen));
}

/*****************************************************************************
**
**   TrcTraceReadRaw
**
*****************************************************************************/
RETCODE EXPORT TrcTraceReadRaw(DESCRIPTOR id, S32 numFrames,
                               U32 FAR *numGotten, LPSTR *buffer) {
   RETCODE err;
   numRetrieved = 0;
   err=ReadTrace(id,numFrames,TRUE,buffer);
   *numGotten = numRetrieved;
   return(err);
}

/*****************************************************************************
** 
**    TrcForwardRead
** 
*****************************************************************************/
RETCODE EXPORT TrcForwardRead(DESCRIPTOR id, U32 numFrames,
  S32 FAR *startFrame, S32 FAR *endFrame, LPSTR *buffer, U16 FAR *textLen) {
   RETCODE err;
   err = ReadTrace(id, numFrames, FALSE, buffer);
   *startFrame = startingFrame;
   *endFrame = endingFrame;
   *textLen = lstrlen(*buffer);
   return(err);
}
      
/*****************************************************************************
** 
**    TrcBackwardRead
** 
*****************************************************************************/
RETCODE EXPORT TrcBackwardRead(DESCRIPTOR id, U32 numFrames,
   S32 FAR *startFrame, S32 FAR *endFrame, LPSTR *buffer, U16 FAR *textLen) {
   RETCODE err;
   err =  ReadTrace(id, 0-numFrames, FALSE, buffer);
   *startFrame = startingFrame;
   *endFrame = endingFrame;
   *textLen = lstrlen(*buffer);
   return(err);
}

/*****************************************************************************
**
**  TrcTraceBufferInfoGet
**
*****************************************************************************/
RETCODE EXPORT TrcTraceBufferInfoGet(DESCRIPTOR id, S32 FAR *oldest,
                                     S32 FAR *youngest, S32 FAR *trigger) {
   TRACE_DESC_BLOCK FAR *trace;
   RETCODE err;
   trace = (TRACE_DESC_BLOCK FAR *)id;
   *oldest = 0;
   *youngest = 0;
   *trigger = 0;
   if((err=SetupBufferCheck(trace->traceBuffer,trace->debugEmon))!=GOOD)
      return(err);
   if ( (err=Sds2AbiGetTraceBufferInfo(trace->traceBuffer,oldest,youngest,
         trigger)) != GOOD) return(err);
   SdnWriteMember(SDN_BUFFER_OLDEST,oldest,GOOD);
   SdnWriteMember(SDN_BUFFER_YOUNGEST,youngest,GOOD);
   /* added by cjchen 1996/12/20 */
   firstBufferFrame=*oldest;
   lastBufferFrame=*youngest;
   /* eof cjchen 1996/12/20 */
   return(GOOD);
}
                                     
/*****************************************************************************
**
**    TrcFrameNumberAreaSizeGet
**
*****************************************************************************/
RETCODE EXPORT TrcFrameNumberAreaSizeGet(U16 FAR *size) {
   *size = FRAME_NUM_AREA_SIZE;
   return(GOOD);
}

/*****************************************************************************
**
**    TrcSubBufferSizeGet
**
*****************************************************************************/
RETCODE EXPORT TrcSubBufferSizeGet(U16 FAR *size) {
   *size = 128;   
   return(GOOD);
}

/*****************************************************************************
**
**    TrcGetHeader
**
*****************************************************************************/
RETCODE EXPORT TrcGetHeader(DESCRIPTOR id, LPSTR header, U16 maxLen) {
   TRACE_DESC_BLOCK FAR *trace;
   trace = (TRACE_DESC_BLOCK FAR *)id;
   if((NUM_HDR_LINES*MAX_HDR_LINE+1) > maxLen) return(ER_NOT_ENOUGH_STORAGE);
   FormulateHeader(trace);
   lstrcpy(header,trace->header);
   return(GOOD);
}

/*****************************************************************************
**
**    TrcReadFrameGet
**
*****************************************************************************/
RETCODE EXPORT TrcReadFrameGet(DESCRIPTOR id, S32 FAR *frame) {
   TRACE_DESC_BLOCK FAR *trace;
   trace = (TRACE_DESC_BLOCK FAR *)id;
   *frame = trace->startFrame;
   return(GOOD);
}
  
/*****************************************************************************
**
**    TrcReadFrameSet
**
*****************************************************************************/
RETCODE EXPORT TrcReadFrameSet(DESCRIPTOR id, S32 frame) {
   RETCODE err;
   TRACE_DESC_BLOCK FAR *trace;
   trace = (TRACE_DESC_BLOCK FAR *)id;
   if((err=ValidFrameNumber(trace->traceBuffer,frame,trace->debugEmon))!=GOOD)
      return(err);
   trace->startFrame = frame;
   return(GOOD);
}

/*****************************************************************************
**
**    TrcDebugEmonGet
**    TrcDebugEmonSet
**
*****************************************************************************/
RETCODE EXPORT TrcDebugEmonGet(DESCRIPTOR id, BOOLEAN *debugEmon) {
   TRACE_DESC_BLOCK FAR *trace;
   trace = (TRACE_DESC_BLOCK FAR *)id;
   *debugEmon = trace->debugEmon;
   return(GOOD);
}

RETCODE EXPORT TrcDebugEmonSet(DESCRIPTOR id, BOOLEAN debugEmon) {
   RETCODE err;
   TRACE_DESC_BLOCK FAR *trace;
   trace = (TRACE_DESC_BLOCK FAR *)id;
   if((err=SetupBufferCheck(trace->traceBuffer,debugEmon))!=GOOD) return(err);
   trace->debugEmon = debugEmon;
   FormulateHeader(trace);
   if((err=EnlEventNotify(EVENT_TRACE_HEADER_CHANGED)) != GOOD ) return(err); 
   return(GOOD);
}

/*****************************************************************************
**
**    TrcNumFramesGet
**
*****************************************************************************/
RETCODE EXPORT TrcNumFramesGet(DESCRIPTOR id, U32 FAR *frames) {
   TRACE_DESC_BLOCK FAR *trace;
   S32 oldest, youngest;
   RETCODE err;
   trace = (TRACE_DESC_BLOCK FAR *)id;
   if((err=SetupBufferCheck(trace->traceBuffer,trace->debugEmon))!=GOOD)
      return(err);
   if((err=SdnReadMember(SDN_BUFFER_OLDEST,(U8 FAR *)&oldest))!=GOOD) 
      return(err);
   if((err=SdnReadMember(SDN_BUFFER_YOUNGEST,(U8 FAR *)&youngest))!=GOOD) 
      return(err);
   if( (oldest == 0) && (youngest == 0) ) *frames = 0;
   else *frames = youngest - oldest + 1;
   return(GOOD);
}

/*****************************************************************************
**
**    TrcReadBufferGet
**
*****************************************************************************/
RETCODE EXPORT TrcReadBufferGet(DESCRIPTOR id, U16 FAR *buffer) {
/*   *buffer = ((TRACE_DESC_BLOCK FAR*)id)->traceBuffer; */
   *buffer = 0;
   return(GOOD);
}

/*****************************************************************************
**
**    TrcReadBufferSet
**
*****************************************************************************/
RETCODE EXPORT TrcReadBufferSet(DESCRIPTOR id, U16 buffer) {
   TRACE_DESC_BLOCK FAR *trace;
   RETCODE err;
   trace = (TRACE_DESC_BLOCK FAR *)id;
   if((err=SetupBufferCheck(buffer,trace->debugEmon))!=GOOD) return(err);
   trace->traceBuffer = buffer;
   if((err=SdWriteMember(trace->activeBufDesc,(U8 FAR *)&trace->traceBuffer,
      GOOD)) != GOOD ) return(err);

   /* check startFrame against new trace buffer's limits */
   if((err=ValidFrameNumber(buffer,trace->startFrame,trace->debugEmon))!=GOOD)
      trace->startFrame = 0;  /* logical trigger frame */
   return(GOOD);
}

/*****************************************************************************
**
**    TrcTracingGet
**
*****************************************************************************/
RETCODE EXPORT TrcTracingGet(BOOLEAN FAR *value) {
U8 goStatus;
S16 status;
   return(SdnReadMember(SDN_TRACING,value));
   return(GOOD);
}

/*****************************************************************************
**
**    TrcTracingSet
**
*****************************************************************************/
#define SECOND (CLK_TCK)  /* from time.h */
#define WAIT_TRACE_OFF_TIMEOUT (5*SECOND)

RETCODE EXPORT TrcTracingSet(BOOLEAN value) {
   BOOLEAN currentTracing;
   RETCODE err;
   BOOLEAN  abortFromEsc;
   EMULATION_STATE emulState;
   time_t start;
   if((err=SdnReadMember(SDN_TRACING,&currentTracing))!=GOOD) return(err);
   /* our work is already done */
   if( currentTracing == value ) {
      return(GOOD);
   }
   if((err = BkGetEmulationStatus((EMULATION_STATE FAR *)&emulState))
      !=GOOD) return(err);
   if(emulState==EM_HALTED) {
      return(GOOD);
   }
/*   if((err=SdnWriteCmdReadResponse(SDN_SET_TRACING, &value, GOOD,
           SDN_FW_TRACING_STATUS, 0, &timedOut))!= GOOD ) {
      return(err);
   } */
   if ((err=SdnWriteMember(SDN_TRACING, &value, err)) != GOOD) return(err);

   if((err=Sds2AbiSetTracing(value))!= GOOD ) {
      return(err);
   }

/*

   if((err=SdnWriteMember(SDN_SET_TRACING,(U8 FAR *)&value,GOOD))!=GOOD)
      return(err);
*/
/********judy******/
   /* just because SD_FW_TRACING_STATUS has been updated doesn't mean
      SD_TRACING has changed.  So after getting confirmation that fw
      has completed it's attempt to change TRACING we need to wait for
      SD_TRACING to change.  Will also add a timeout so we don't get
      hung here.
   */
   start = clock();
   do {
      if((err=SdnReadMember(SDN_TRACING,&currentTracing))!=GOOD) return(err);
      if( currentTracing == value ) break;
      if ((err = TskCheckAbort(&abortFromEsc)) != GOOD) break;
      if (abortFromEsc!=0) { err=ER_ABORT_FROM_ESC; break; }
   } while (clock() < start+WAIT_TRACE_OFF_TIMEOUT);
   return(err);
}

/*****************************************************************************
**
**    TrcMaxValidTraceBuffers
**
*****************************************************************************/
RETCODE EXPORT TrcMaxValidTraceBuffers(U16 FAR *numBuffers) {
   RETCODE err;
   U16  cnt0, cnt1, maxBuffer;
   if ( (err=Sds2AbiGetTraceInfo(numBuffers,&cnt0,&cnt1,&maxBuffer)) != GOOD)
        return(err);
//   if((err=SdnReadMember(SDN_MAX_TRACE_BUFFER,(U8 FAR *)numBuffers))!=GOOD)
//      return(err);
   return(GOOD);
}
 
/*****************************************************************************
**
**    TrcTraceCycleGet
**
*****************************************************************************/
RETCODE EXPORT TrcTraceCycleGet(DESCRIPTOR id, TRACE_CYCLES FAR *type) {
   *type = ((TRACE_DESC_BLOCK FAR*)id)->cycleMode;
   return(GOOD);
}

/*****************************************************************************
**
**    TrcTraceCycleSet
**
*****************************************************************************/
RETCODE EXPORT TrcTraceCycleSet(DESCRIPTOR id, TRACE_CYCLES type) {
   TRACE_DESC_BLOCK FAR *trace;
   trace = (TRACE_DESC_BLOCK FAR *)id;
   trace->cycleMode = type;
   return(
      SdWriteMember(trace->frameTypeDesc,(U8 FAR *)&trace->cycleMode,GOOD));
}

/*****************************************************************************
**
**    TrcTraceBufferClear
**
*****************************************************************************/
RETCODE EXPORT TrcTraceBufferClear(VOID) {
   RETCODE err;
   BOOLEAN enable = TRUE;
   if((err=SdnWriteMember(SDN_CLEAR_TRACE,(U8 FAR *)&enable,GOOD))!=GOOD)
      return(err);
   if((err=EnlEventNotify(EVENT_TRACE_CLEAR_TRACE)) != GOOD ) return(err); 
   return(GOOD);
}

/*****************************************************************************
** 
**    TrcFrameDisplayModeSet
**
*****************************************************************************/
RETCODE EXPORT TrcFrameDisplayModeSet(DESCRIPTOR id, FRAME_DISPLAY_MODE mode){
   if( mode != TRIGGER_ALIGN ) return(ER_NOT_SUPPORTED);
   ((TRACE_DESC_BLOCK FAR*)id)->frameMode = mode;
   return(GOOD);
}

/*****************************************************************************
** 
**    TrcFrameDisplayModeGet
**
*****************************************************************************/
RETCODE EXPORT TrcFrameDisplayModeGet(DESCRIPTOR id, 
                  FRAME_DISPLAY_MODE FAR *mode){
   *mode = ((TRACE_DESC_BLOCK FAR*)id)->frameMode;
   return(GOOD);
}

/*****************************************************************************
** 
**    TrcSearchBufferGet
** 
*****************************************************************************/
RETCODE EXPORT TrcSearchBufferGet(DESCRIPTOR id, U16 FAR *buffer) {
   *buffer = ((TRACE_DESC_BLOCK FAR*)id)->searchBuffer;
   return(GOOD);
}
      
/*****************************************************************************
** 
**    TrcSearchBufferSet
** 
*****************************************************************************/
RETCODE EXPORT TrcSearchBufferSet(DESCRIPTOR id, U16 buffer) {
   TRACE_DESC_BLOCK FAR *trace;
   RETCODE err;
   trace = (TRACE_DESC_BLOCK FAR *)id;
   if((err=SetupBufferCheck(buffer,trace->debugEmon))!=GOOD)
      return(err);
   trace->searchBuffer = buffer;
   /* check startFrame against new trace buffer's limits */
   if((err=ValidFrameNumber(buffer,trace->searchStartFrame,trace->debugEmon))
      != GOOD ) 
      return(SdnReadMember(SDN_BUFFER_OLDEST,
               (U8 FAR *)&trace->searchStartFrame));
   return(GOOD);
}
      
/*****************************************************************************
** 
**    TrcSearchEventGet
** 
*****************************************************************************/
RETCODE EXPORT TrcSearchEventGet(DESCRIPTOR id, LPSTR event, U16 maxLen) {
   TRACE_DESC_BLOCK FAR *trace;
   trace = (TRACE_DESC_BLOCK FAR *)id;
   if( (lstrlen(trace->searchEvent)+1) > maxLen ) 
      return(ER_NOT_ENOUGH_STORAGE);
   lstrcpy(event,trace->searchEvent);
   return(GOOD);
}
      
/*****************************************************************************
** 
**    TrcSearchEventSet
** 
*****************************************************************************/
RETCODE EXPORT TrcSearchEventSet(DESCRIPTOR id, LPSTR event) {
   if( lstrlen(event) > EVENT_NAME_LENGTH-1 ) return(ER_NOT_ENOUGH_STORAGE);
   lstrcpy(((TRACE_DESC_BLOCK FAR*)id)->searchEvent,event);
   return(GOOD);
}
      
/*****************************************************************************
** 
**    TrcSearchFrameGet
** 
*****************************************************************************/
RETCODE EXPORT TrcSearchFrameGet(DESCRIPTOR id, S32 FAR *frame) {
   TRACE_DESC_BLOCK FAR *trace;
   trace = (TRACE_DESC_BLOCK FAR *)id;
   *frame = trace->searchStartFrame;
   return(GOOD);
}
      
/*****************************************************************************
** 
**    TrcSearchFrameSet
** 
*****************************************************************************/
RETCODE EXPORT TrcSearchFrameSet(DESCRIPTOR id, S32 frame) {
   RETCODE err;
   TRACE_DESC_BLOCK FAR *trace;
   trace = (TRACE_DESC_BLOCK FAR *)id;
   if((err=ValidFrameNumber(trace->searchBuffer,frame,trace->debugEmon))
      !=GOOD) return(err);
   trace->searchStartFrame = frame;
   return(GOOD);
}

/*****************************************************************************
**
**    TrcTraceSearch
** 
*****************************************************************************/
RETCODE EXPORT TrcTraceSearch(DESCRIPTOR id, BOOLEAN FAR *found) {
   TRACE_DESC_BLOCK FAR *trace;
   BOOLEAN  exists;
   LOOP_VAR group;
   EVENT_GROUP_INFO sdEvent;
   EVENT_GROUP_INFO searchItem[4];
   RETCODE err;
   MP_TRACE_INFO  traceData[48];
   U8    frameLen;
   QUALIFY_LIST   qList;
   BOOLEAN  abortFromEsc;
   U16 busData;

   /* Get pointer to the Trace Setup Info */
   *found = FALSE;
   trace = (TRACE_DESC_BLOCK FAR *)id;
   if( (err=SdnWriteMember(SDN_SEARCH_BUFFER,(U8 FAR *)&trace->searchBuffer,
      GOOD)) != GOOD ) return(err);
   if( (err=SdnWriteMember(SDN_SEARCH_EMON,(U8 FAR *)&trace->debugEmon,
      GOOD)) != GOOD ) return(err);
   if((err=EvtDoesEventExist(trace->searchEvent,&exists))!=GOOD) return(err);
   if( !exists ) return(ER_NO_SUCH_EVENT);
   if( (err=EvtSetActiveEvent(trace->eventServerId,trace->searchEvent)) 
        != GOOD ) return(err);
   for (group=0; group<NUM_GROUPS; group++) {
      if( (err=EvtGetEventGroupInfo(trace->eventServerId,group,&sdEvent)) 
         != GOOD ) return(err);
      memcpy(&searchItem[group],&sdEvent,sizeof(EVENT_GROUP_INFO));
      if((err=SdnWriteMember(SDN_SEARCH_EVENT+group,(U8 FAR*)&sdEvent,GOOD))
         != GOOD) return(err);
   }

   qList.qFlag=2; /* Get trace frame without qualifier */
   qList.traceBitData = qList.traceBitWild = 0;
   qList.startAddr = searchItem[0].lo;
   qList.endAddr = searchItem[0].hi;
   qList.addrMask = searchItem[0].mask;
   qList.dataMask = 0;
   if (searchItem[1].lo) qList.status = searchItem[1].lo;
   else qList.status = 0x7f;
   for (;;) {
      err = TskCheckAbort(&abortFromEsc);
      if(err!=GOOD) return err;
      if (abortFromEsc!=0) {
         err = ER_ABORT_FROM_ESC;
         return err;
      }
      iceGetQualifyFrame(trace->searchBuffer, trace->searchStartFrame, &qList, 
                       &frameLen, &traceData);
      if (!frameLen) break;
      if (searchItem[2].mask == 0) break;
      searchItem[2].lo &= searchItem[2].mask;  
      busData = traceData[0].data;
      GetBusData(traceData[0].addr, traceData[0].stat, &busData);
      busData &= searchItem[2].mask;
      if (searchItem[2].lo == busData) break;
      trace->searchStartFrame = traceData[0].frameNo+1;
   }
   if (frameLen) {
      *found = TRUE;
      trace->searchStartFrame = traceData[0].frameNo;
   }
//   if( (err = SdnWriteCmdReadResponse(SDN_SEARCH_START_FRAME, 
//      &trace->searchStartFrame, GOOD, SDN_FOUND_SEARCH_EVENT, 40, 
//         &timedOut)) != GOOD ) return(err);
//   if( (err = SdnReadMember(SDN_FOUND_SEARCH_EVENT, (U8 FAR *)found))!=GOOD )
//      return(err);
//   if((err=SdnReadMember(SDN_SEARCH_START_FRAME,
//      (U8 FAR *)&trace->searchStartFrame)) != GOOD ) return(err);
   return(GOOD);
}
/*****************************************************************************
** 
**    TrcUpdateTrace
**
*****************************************************************************/
RETCODE EXPORT TrcUpdateTrace(DESCRIPTOR id) {
   U16 traceBuffer;
   S32 oldest,youngest,trigger;
   RETCODE err;
   if((err=TrcCollectingBufferGet(&traceBuffer)) != GOOD )
      return(err);
   if((err=TrcReadBufferSet(id, traceBuffer)) != GOOD ) return(err);
   if((err=TrcTraceBufferInfoGet(id,&oldest,&youngest,&trigger))!=GOOD)
      return(err);
   if((err=TrcReadFrameSet(id, min(trigger,youngest))) != GOOD ) return(err);
   return(GOOD);
}

/*****************************************************************************
** 
**    TrcCollectingBufferGet
** 
*****************************************************************************/
RETCODE EXPORT TrcCollectingBufferGet(U16 FAR *traceBuffer) {
   RETCODE err;
   BOOLEAN traceIsEmpty;
   S32 oldest,youngest,trigger;

   *traceBuffer = 0;
   if ( (err=Sds2AbiGetTraceBufferInfo(*traceBuffer,&oldest,&youngest,
	 &trigger)) != GOOD) {
     //Fixed bug ID#199 by Eric 2/2/98
     oldest=0;
     SdnWriteMember(SDN_BUFFER_OLDEST,&oldest,GOOD);
     //eof Eric 2/2/98
     return(err);
   }
   SdnWriteMember(SDN_BUFFER_OLDEST,&oldest,GOOD);
   SdnWriteMember(SDN_BUFFER_YOUNGEST,&youngest,GOOD);
   if((err=SdnReadMember(SDN_TRACE_EMPTY,&traceIsEmpty))!=GOOD ) return(err);
   if(traceIsEmpty)
      return(GOOD);
   /* don't want to read bonus info if no trace data */
//   if((err=SdnReadMember(SDN_CURRENT_SUBBUFFER,(U8 FAR *)traceBuffer))!=GOOD) 
//      return(err);
//   *traceBuffer = CalculateTraceBufferFromSubBuffer(*traceBuffer);
   return(GOOD);
 }

/*****************************************************************************
**
**    TrcGetFrameInstAddress
**
*****************************************************************************/
RETCODE EXPORT TrcGetFrameInstAddress(DESCRIPTOR id, S32 frame, 
                              DESCRIPTOR FAR *addr, BOOLEAN FAR *frameIsInst){
   TRACE_DESC_BLOCK FAR *trace;
   RETCODE err;
   BOOLEAN  timedOut;
   U32 addrOffset;
   ADDR_TYPE type = ADDR_LINEAR;
   trace = (TRACE_DESC_BLOCK FAR *)id;
   if((err=SdnWriteMember(SDN_LINKCURS_BUFFER,(U8 FAR *)&trace->traceBuffer,
      GOOD)) !=GOOD) return(err);
   if((err=SdnWriteMember(SDN_LINKCURS_EMON,(U8 FAR *)&trace->debugEmon,
      GOOD)) !=GOOD) return(err);
   if((err=SdnWriteCmdReadResponse(SDN_LINKCURS_FRAME, &frame, 
              GOOD, SDN_LINKCURS_INST, 10, &timedOut)) != GOOD ) 
      return(err);
   if((err=SdnReadMember(SDN_LINKCURS_ADDRESS,(U8 FAR *)&addrOffset))!=GOOD) 
      return(err);
   if((err=SdnReadMember(SDN_LINKCURS_INST,frameIsInst))!=GOOD) 
      return(err);
   if( !*frameIsInst ) type = ADDR_PHYSICAL; // data is always physical
   if ((err = AdrCreateAddressWithType(type,addr)) != GOOD)
      return err;
   AdrSetAddrSpace(*addr,SPACE_SP);         
   return(AdrSetAddrOffset(*addr,addrOffset));
}

/*****************************************************************************
**
**    TrcTimestampGet
**
*****************************************************************************/
RETCODE EXPORT TrcTimestampGet(DESCRIPTOR id, BOOLEAN FAR *value) {
   TRACE_DESC_BLOCK FAR *trace;
   trace = (TRACE_DESC_BLOCK FAR *)id;
   *value = trace->timestampOn;
   return(GOOD);
}

/*****************************************************************************
**
**    TrcNewestTimestampGet
**
*****************************************************************************/
RETCODE EXPORT TrcNewestTimestampGet(LPSTR dataPtr) {
   U32 time, tmpTime;
   U8  timeMSB;
   float absTime;
   S8  bufTime[20], tmpBuf[20];
   RETCODE err;
   *dataPtr = '\0';

   tmpBuf[0]='0'; tmpBuf[1]='n'; tmpBuf[2]='s'; tmpBuf[3]='\0';
   if( (err= Sds2AbiReadLastStamp(0,&time,&timeMSB)) != GOOD ){
     lstrcpy(dataPtr,tmpBuf);
     return(GOOD);
   }
   ltoa(time*50L,bufTime,10);
   absTime = time;
   absTime = (time < 0) ? absTime * 50. * -1. : absTime * 50.;
   if( strlen(bufTime)< TIMESTAMP_LEN-3)
      sprintf(tmpBuf,"%9.0fns  ",absTime);
   else {
      tmpTime=(U32)absTime / 1000.;
      ltoa(tmpTime,bufTime,10);
      if (strlen(bufTime)< TIMESTAMP_LEN-3)
         sprintf(tmpBuf,"%9.0fus  ",absTime/1000.);
      else {
         sprintf(tmpBuf,"%9.0fms  ",absTime/1000000.);
      }
   }
   lstrcpy(dataPtr,tmpBuf);
   return(GOOD);
}

/*****************************************************************************
**
**    TrcTimestampSet
**
*****************************************************************************/
RETCODE EXPORT TrcTimestampSet(DESCRIPTOR id, BOOLEAN value) {
   TRACE_DESC_BLOCK FAR *trace;
   U8 ts=TIMESTAMP_OPT;
   trace = (TRACE_DESC_BLOCK FAR *)id;
   trace->timestampOn = value;
   optionFlag &= (~ts);
   optionFlag |= (value == TRUE) ? TIMESTAMP_OPT : 0;
   FormulateHeader(trace);
   return(EnlEventNotify(EVENT_TRACE_HEADER_CHANGED));
}

/*****************************************************************************
**
**    TrcTimestampModeGet
**
*****************************************************************************/
RETCODE EXPORT TrcTimestampModeGet(DESCRIPTOR id, TIMESTAMP_MODE FAR *value) {
   TRACE_DESC_BLOCK FAR *trace;
   trace = (TRACE_DESC_BLOCK FAR *)id;
   *value = trace->tsMode;
   return(GOOD);
}

/*****************************************************************************
**
**    TrcTimestampModeSet
**
*****************************************************************************/
RETCODE EXPORT TrcTimestampModeSet(DESCRIPTOR id, TIMESTAMP_MODE value) {
   TRACE_DESC_BLOCK FAR *trace;
   trace = (TRACE_DESC_BLOCK FAR *)id;
   trace->tsMode = value;
   TrcTimestampSet(id,TRUE);  /* force re-generation of header - new data */
   return(GOOD);
}

/*****************************************************************************
**
**    TrcTimestampZeroFrameGet
**
*****************************************************************************/
RETCODE EXPORT TrcTimestampZeroFrameGet(DESCRIPTOR id, S32 FAR *frame) {
   TRACE_DESC_BLOCK FAR *trace;
   trace = (TRACE_DESC_BLOCK FAR *)id;
   *frame = trace->zeroedFrame;
   return(GOOD);
}
  
/*****************************************************************************
**
**    TrcTimestampZeroFrameSet
**
*****************************************************************************/
RETCODE EXPORT TrcTimestampZeroFrameSet(DESCRIPTOR id, S32 frame) {
   RETCODE err;
   TRACE_DESC_BLOCK FAR *trace;
   U32 zFrameTS;
   U8 zFrameTSM;
   U8 bufTime[40];
   trace = (TRACE_DESC_BLOCK FAR *)id;
   if((err=ValidFrameNumber(trace->traceBuffer,frame,trace->debugEmon))!=GOOD)
      return(err);
   trace->zeroedFrame = frame;
   TrcTimestampSet(id,TRUE);  /* force re-generation of header - new data */
   Sds2AbiReadFrameStamp(0, trace->zeroedFrame, &zFrameTS, &zFrameTSM);
   itoa(zFrameTSM, bufTime, 10);
   ultoa(zFrameTS, bufTime+1, 10);
   preFrameTS = zeroedFrameTS = _atold(bufTime); /* <Judy 9/5/97> */
   return(GOOD);
}
/*****************************************************************************
**
**    TrcOptionFlagGet
**
*****************************************************************************/
RETCODE EXPORT TrcOptionFlagGet(DESCRIPTOR id, U16 mode, BOOLEAN FAR *flag) {
   S8 tflag;
   tflag=1;
   *flag= ((optionFlag & (tflag << mode))== 0 ) ? 0 : 1;
   return(GOOD);
}

/*****************************************************************************
**
**    TrcOptionFlagSet
** Note: toggle flag
*****************************************************************************/
RETCODE EXPORT TrcOptionFlagSet(DESCRIPTOR id, U16 mode) {
   S8 flag,getFlag;
   flag=1;
   flag <<= mode;
   getFlag= ((optionFlag & flag)== 0 ) ? 0 : 1;
   if (getFlag==0)
      optionFlag |= flag;
   else {
      flag = ~flag;
      optionFlag &= flag;
   }
   if ((optionFlag & TIMESTAMP_OPT)==0)
      TrcTimestampSet(id, FALSE);
   else
      TrcTimestampSet(id, TRUE);
   return(GOOD);
}

/*****************************************************************************
**
**    TrcSystemCrystalGet
**
*****************************************************************************/
static S8 freqPrefix[4] = {' ','k','M'};
RETCODE EXPORT TrcSystemCrystalGet(LPSTR freqText) {
   U16 index=0;
   float freq = krystalFrequency;
   while( freq > 1000 ) {
      freq = freq / 1000;
      index++;
   }
   sprintf(freqText,"%6.3f%cHz ", freq, freqPrefix[index]);
   return(GOOD);
}
  
/*****************************************************************************
**
**    TrcSystemCrystalSet
**
*****************************************************************************/
RETCODE EXPORT TrcSystemCrystalSet(LPSTR freqText) {
   float freq;
   float multiplier=1;
   LPSTR ptr = freqText;
   LOOP_VAR i, len;
   len = strlen(ptr);
   for( i = 0; i < len; i++ ) {
      if( isdigit(ptr[i]) || (ptr[i]=='.') ||
                 (ptr[i]==',') || (ptr[i] == ' ')) continue;
      if( (ptr[i] == 'k') || (ptr[i] == 'K') ) multiplier = 1000;
      if( ptr[i] == 'M' ) multiplier = 1000000.;
      ptr[i] = '\0';
      break;
   }
   if( sscanf(ptr,"%f",&freq) == 1 ) {
      freq *= multiplier;
      if( (freq==(float)0) || (freq > (float)40000000.) || (freq < (float).01))
         return(ER_BAD_FREQUENCY);
      krystalFrequency = freq;
      systemPeriod = 1 / krystalFrequency;
      return(EnlEventNotify(EVENT_TRACE_HEADER_CHANGED)); // new ts data.
   }   
   return(ER_BAD_FREQUENCY);
}

/*************************** CLI FUNCTIONS ******************************/
RETCODE EXPORT TrcGetCliId(DESCRIPTOR FAR *trcCliId) {
   RETCODE err=GOOD;
   if( !traceId )
      err=TrcTraceOpen(&traceId,"hwtrc", CLOCK_CYCLE, TRIGGER_ALIGN);
   *trcCliId = traceId;
   return(err);
}   

RETCODE EXPORT TrcCliForwardRead( LPSTR cmdString, U32 argc, U32 argv[] ) {
   LPSTR lpBuff;
   RETCODE err;
   U16 len;
   S8 resultBuff[128];
   S32 start,end;
   if( !traceId ) return(ER_NO_TRACE_OPEN);
   if( argc == 2 ) {
      err=
      TrcForwardRead(traceId,(U32)atoi(&cmdString[(U16)argv[1]]),&start,
                     &end,&lpBuff,&len);
   }
   else {  /* just return one trace frame if no number of frames given */
      err=TrcForwardRead(traceId, 1, &start, &end, &lpBuff, &len); 
   }
   if( err && (err != ER_END_OF_BUFFER) ) return(err);
   if( start == end ) {
      lstrcpy(resultBuff,"No frames found");
      return(SendCliResults(resultBuff,cliServerHandle));
   }
   return(SendCliResults(lpBuff,cliServerHandle));
}

RETCODE EXPORT TrcCliBackwardRead( LPSTR cmdString, U32 argc, U32 argv[] ) {
   LPSTR lpBuff;
   RETCODE err;
   U16 len;
   S32 start,end;
   if( !traceId ) return(ER_NO_TRACE_OPEN);
   if( argc == 2 ) {
      err=TrcBackwardRead(traceId,(U32)atoi(&cmdString[(U16)argv[1]]), 
                  &start,&end,&lpBuff,&len);
   }
   else {  /* just return one trace frame if no number of frames given */
      err=TrcBackwardRead(traceId, 1, &start, &end, &lpBuff, &len);
   }
   if( err && (err != ER_END_OF_BUFFER) ) return(err);
   err=SendCliResults(lpBuff,cliServerHandle);
   TFree(lpBuff);
   return(err);
}

RETCODE EXPORT TrcCliReadRaw( LPSTR cmdString, U32 argc, U32 argv[] ) {
   TRACE_INFO *frames;
   RETCODE err;
   LPSTR results, ptr;
   LOOP_VAR i;
   U32 numFrames;
   if( !traceId ) return(ER_NO_TRACE_OPEN);
   if( argc == 2 ) {
      if( (err=TrcTraceReadRaw(traceId, (U32)atoi(&cmdString[(U16)argv[1]]),
         &numFrames,(LPSTR *)&frames)) != GOOD ) return(err);
   }
   else {  /* just return one trace frame if no number of frames given */
      if((err=TrcTraceReadRaw(traceId,1,&numFrames,(LPSTR*)&frames)) != GOOD )
         return(err);
   }
   results = TMalloc(numFrames*75);
   ptr = results;
   *ptr = NULL;
   for( i=0; i<numFrames; i++ ) {
      wsprintf(ptr,"   %8ld     %08lX    %08lX    %08lX\r\n",
         frames[i].frameNumber,frames[i].rGroup,
         frames[i].sGroup, frames[i].tGroup);
      ptr = results + lstrlen(results);
   }
   err = SendCliResults(results,cliServerHandle);
   TFree(results);
   TFree((LPSTR)frames);
   return(err);
}


#pragma argsused
RETCODE EXPORT TrcCliBufferInfo(LPSTR cmdString, U32 argc, U32 argv[]) {
   S32 oldest, youngest, trigger;
   S8 resultBuff[128];
   RETCODE err;
   if( !traceId ) return(ER_NO_TRACE_OPEN);
   if( (err=TrcTraceBufferInfoGet(traceId, &oldest, &youngest, &trigger)) 
      != GOOD ) return(err);
   wsprintf(resultBuff,"start: %ld; end: %ld; trigger: %ld", 
                        oldest, youngest, trigger);
   return(SendCliResults(resultBuff,cliServerHandle));
}

#define START_ALIGN_TEXT "START_ALIGN"
#define TRIGGER_ALIGN_TEXT "TRIGGER_ALIGN"
#define NO_ALIGN_TEXT "NO_ALIGN"
FRAME_DISPLAY_MODE parseFrameMode(LPSTR ptr) {
   FRAME_DISPLAY_MODE mode;
   if( ptr[0] == '0' )
      mode = START_ALIGN;
   else if( ptr[0] == '1' )
      mode = TRIGGER_ALIGN;
   else if( ptr[0] == '2' )
      mode = NO_ALIGN;
   else if(strncmpi(ptr, START_ALIGN_TEXT, strlen(ptr))==0) 
      mode = START_ALIGN;
   else if(strncmpi(ptr, TRIGGER_ALIGN_TEXT, strlen(ptr))==0) 
      mode = TRIGGER_ALIGN;
   else 
      mode = NO_ALIGN;      
   return(mode);
}

RETCODE EXPORT TrcCliFrameMode(LPSTR cmdString, U32 argc, U32 argv[]) {
   FRAME_DISPLAY_MODE mode;
   S8 resultBuff[128];
   RETCODE err;
   if( !traceId ) return(ER_NO_TRACE_OPEN);
   if( argc == 2 ) {
      mode = parseFrameMode(&cmdString[(U16)argv[1]]);
      if( (err=TrcFrameDisplayModeSet(traceId, mode)) != GOOD ) return(err);
   }
   if( (err=TrcFrameDisplayModeGet(traceId,&mode)) != GOOD ) return(err);
   if( mode == START_ALIGN ) lstrcpy(resultBuff,START_ALIGN_TEXT);
   else if( mode == TRIGGER_ALIGN ) lstrcpy(resultBuff,TRIGGER_ALIGN_TEXT);
   else lstrcpy(resultBuff,NO_ALIGN_TEXT);
   return(SendCliResults(resultBuff,cliServerHandle));
}

#define BUS_CYCLE_TEXT "BUS_CYCLE"
#define CLOCK_CYCLE_TEXT "CLOCK_CYCLE"
TRACE_CYCLES parseTraceCycleMode(LPSTR ptr) {
   TRACE_CYCLES mode;
   if( ptr[0] == '0' )
      mode = BUS_CYCLE;
   else if( ptr[0] == '1' )
      mode = CLOCK_CYCLE;
   else if(strncmpi(ptr, BUS_CYCLE_TEXT, strlen(ptr))==0) 
      mode = BUS_CYCLE;
   else if(strncmpi(ptr, CLOCK_CYCLE_TEXT, strlen(ptr))==0) 
      mode = CLOCK_CYCLE;
   else
      mode = BINARY_CYCLE;
   return(mode);
}

RETCODE EXPORT TrcCliTraceCycle(LPSTR cmdString, U32 argc, U32 argv[]) {
   TRACE_CYCLES mode;
   S8 resultBuff[128];
   RETCODE err;
   if( !traceId ) return(ER_NO_TRACE_OPEN);
   if( argc == 2 ) {
      mode = parseTraceCycleMode(&cmdString[(U16)argv[1]]);
      if( (err=TrcTraceCycleSet(traceId, mode)) != GOOD )
         return(err);
   }
   if( (err=TrcTraceCycleGet(traceId,&mode)) != GOOD ) return(err);
   if( mode == BUS_CYCLE ) lstrcpy(resultBuff,BUS_CYCLE_TEXT);
   else if( mode == CLOCK_CYCLE ) lstrcpy(resultBuff,CLOCK_CYCLE_TEXT);
   else lstrcpy(resultBuff,"BINARY_CYCLE");
   return(SendCliResults(resultBuff,cliServerHandle));
}

RETCODE EXPORT TrcCliReadBuffer(LPSTR cmdString, U32 argc, U32 argv[]) {
   U16 trcBuffer;
   S8 resultBuff[128];
   RETCODE err;
   if( !traceId ) return(ER_NO_TRACE_OPEN);
   if( argc == 2 ) {
      if((err=TrcReadBufferSet(traceId,atoi(&cmdString[(U16)argv[1]])))!=GOOD)
         return(err);
   }
   if( (err=TrcReadBufferGet(traceId,&trcBuffer)) != GOOD ) return(err);
   wsprintf(resultBuff,"%d", trcBuffer);
   return(SendCliResults(resultBuff,cliServerHandle));
}

RETCODE EXPORT TrcCliSearchBuffer(LPSTR cmdString, U32 argc, U32 argv[]) {
   U16 trcBuffer;
   S8 resultBuff[128];
   RETCODE err;
   if( !traceId ) return(ER_NO_TRACE_OPEN);
   if( argc == 2 ) {
      if((err=TrcSearchBufferSet(traceId,atoi(&cmdString[(U16)argv[1]])))
         !=GOOD) return(err);
   }
   if( (err=TrcSearchBufferGet(traceId,&trcBuffer))!=GOOD ) return(err);
   wsprintf(resultBuff,"%d", trcBuffer);
   return(SendCliResults(resultBuff,cliServerHandle));
}

#pragma argsused
RETCODE EXPORT TrcCliGetCollectingBuffer(LPSTR cmdString, U32 argc, 
                                         U32 argv[]) {
   U16 buffer;
   S8 resultBuff[128];
   RETCODE err;
   if( !traceId ) return(ER_NO_TRACE_OPEN);
   if( (err=TrcCollectingBufferGet(&buffer)) != GOOD ) return(err);
   wsprintf(resultBuff,"last collected trace buffer: %d", buffer);
   return(SendCliResults(resultBuff,cliServerHandle));
}

#pragma argsused
RETCODE EXPORT TrcCliNumFrames(LPSTR cmdString, U32 argc, U32 argv[]) {
   U32 numFrames;
   S8 resultBuff[128];
   RETCODE err;
   if( !traceId ) return(ER_NO_TRACE_OPEN);
   if( (err=TrcNumFramesGet(traceId,&numFrames)) != GOOD ) return(err);
   wsprintf(resultBuff,"%ld", numFrames);
   return(SendCliResults(resultBuff,cliServerHandle));
}

RETCODE EXPORT TrcCliReadFrame(LPSTR cmdString, U32 argc, U32 argv[]) {
   S8 *ptr;
   S32 frame;
   S8 resultBuff[128];
   RETCODE err;
   if( !traceId ) return(ER_NO_TRACE_OPEN);
   if( (argc == 3) || (argc == 2) ) {
      if( cmdString[(U16)argv[1]] == '-' ) {
         strcpy(resultBuff,"-");
         strcat(resultBuff,&cmdString[(U16)argv[2]]);
      }
      else {
         strcpy(resultBuff,&cmdString[(U16)argv[1]]);
      }         
      frame = strtol(resultBuff,&ptr,0);
      if( lstrlen(ptr) != 0 ) return(ER_INVALID_FRAME);
      if( (err=TrcReadFrameSet(traceId,frame)) != GOOD ) return(err);
   }
   if( (err=TrcReadFrameGet(traceId,&frame)) != GOOD ) return(err);
   wsprintf(resultBuff,"%ld", frame);
   return(SendCliResults(resultBuff,cliServerHandle));
}

RETCODE EXPORT TrcCliSearchFrame(LPSTR cmdString, U32 argc, U32 argv[]) {
   S8 *ptr;
   S32 frame;
   S8 resultBuff[128];
   RETCODE err;
   if( !traceId ) return(ER_NO_TRACE_OPEN);
   if( (argc == 3) || (argc == 2) ) {
      if( cmdString[(U16)argv[1]] == '-' ) {
         strcpy(resultBuff,"-");
         strcat(resultBuff,&cmdString[(U16)argv[2]]);
      }
      else {
         strcpy(resultBuff,&cmdString[(U16)argv[1]]);
      }         
      frame = strtol(resultBuff,&ptr,0);
      if( lstrlen(ptr) != 0 ) return(ER_INVALID_FRAME);
      if( (err=TrcSearchFrameSet(traceId,frame)) != GOOD ) return(err);
   }
   if( (err=TrcSearchFrameGet(traceId,&frame)) != GOOD ) return(err);
   wsprintf(resultBuff,"%ld", frame);
   return(SendCliResults(resultBuff,cliServerHandle));
}

RETCODE EXPORT TrcCliSearchEvent(LPSTR cmdString, U32 argc, U32 argv[]) {
   S8 resultBuff[128];
   RETCODE err;
   if( !traceId ) return(ER_NO_TRACE_OPEN);
   if( argc == 2 ) {
      if( (err=TrcSearchEventSet(traceId, &cmdString[(U16)argv[1]]))!=GOOD ) 
         return(err);
   }
   if((err=TrcSearchEventGet(traceId,resultBuff,128)) != GOOD) return(err);
   return(SendCliResults(resultBuff,cliServerHandle));
}

#pragma argsused
RETCODE EXPORT TrcCliTraceSearch(LPSTR cmdString, U32 argc, U32 argv[]) {
   S8 resultBuff[128];
   BOOLEAN found;
   RETCODE err;
   if( !traceId ) return(ER_NO_TRACE_OPEN);
   if( (err=TrcTraceSearch(traceId, &found)) != GOOD ) return(err);
   if( found ) {
      S32 frame;
      U16 buffer;
      if( (err=TrcSearchBufferGet(traceId, &buffer)) != GOOD ) return(err);
      if( (err=TrcReadBufferSet(traceId, buffer)) != GOOD ) return(err);
      if( (err=TrcSearchFrameGet(traceId, &frame)) != GOOD ) return(err);
      if( (err=TrcReadFrameSet(traceId, frame)) != GOOD ) return(err);
      wsprintf(resultBuff,"Search found match at FRAME: %6ld",frame);
   }
   else lstrcpy(resultBuff,"Search found NO match");
   return(SendCliResults(resultBuff,cliServerHandle));
}

RETCODE EXPORT TrcCliDebugEmon(LPSTR cmdString, U32 argc, U32 argv[]) {
   S8 resultBuff[128];
   RETCODE err;
   TRACE_DESC_BLOCK FAR *trace;
   if( !traceId ) return(ER_NO_TRACE_OPEN);
   trace = (TRACE_DESC_BLOCK FAR *)traceId;
   if( argc == 2 ) {
      BOOLEAN value;
      value = ParseBoolean(&cmdString[(U16)argv[1]]);
      if( trace->debugEmon != value ) {
         if ((err = TrcDebugEmonSet(traceId, value)) != GOOD) return(err);
      }
   }
   if( trace->debugEmon ) lstrcpy(resultBuff,"DEBUG EMON ON");
   else lstrcpy(resultBuff,"DEBUG EMON OFF");
   return(SendCliResults(resultBuff,cliServerHandle));
}

RETCODE EXPORT TrcCliTracing(LPSTR cmdString, U32 argc, U32 argv[]) {
   BOOLEAN value;
   S8 resultBuff[128];
   RETCODE err;
   if( !traceId ) return(ER_NO_TRACE_OPEN);
   if( argc == 2 ) {
      value = ParseBoolean(&cmdString[(U16)argv[1]]);
      if((err=TrcTracingSet(value))!=GOOD) return(err);
   }
   if( (err=TrcTracingGet(&value)) != GOOD ) return(err);
   if( value ) lstrcpy(resultBuff,"TRACING");
   else lstrcpy(resultBuff,"NOT TRACING");
   return(SendCliResults(resultBuff,cliServerHandle));
}

RETCODE EXPORT TrcCliTraceTemplate(LPSTR cmdString, U32 argc, U32 argv[]) {
   S8 resultBuff[128];
   RETCODE err;
   if( !traceId ) return(ER_NO_TRACE_OPEN);
   if( argc == 2 ) {
      if( (err=TrcTraceTemplateSet(traceId, &cmdString[(U16)argv[1]]))!=GOOD) 
         return(err);
   }
   if((err=TrcTraceTemplateGet(traceId,resultBuff,128)) != GOOD) return(err);
   return(SendCliResults(resultBuff,cliServerHandle));
}

#pragma argsused
RETCODE EXPORT TrcCliGetHeader(LPSTR cmdString, U32 argc, U32 argv[]) {
   S8 resultBuff[NUM_HDR_LINES*MAX_HDR_LINE+1];
   RETCODE err;
   if( !traceId ) return(ER_NO_TRACE_OPEN);
   if((err=TrcGetHeader(traceId,resultBuff,NUM_HDR_LINES*MAX_HDR_LINE+1)) 
      != GOOD) return(err);
   return(SendCliResults(resultBuff,cliServerHandle));
}

RETCODE EXPORT TrcCliOpen( LPSTR cmdString, U32 argc, U32 argv[] ) {
   RETCODE err;
   TRACE_CYCLES tMode;
   FRAME_DISPLAY_MODE fMode;
   S8 fileName[128];
   if( argc == 4 ) {
      tMode = parseTraceCycleMode(&cmdString[(U16)argv[2]]);
      fMode = parseFrameMode(&cmdString[(U16)argv[3]]);
      lstrcpy(fileName,&cmdString[(U16)argv[1]]);
   }
   else {
      tMode = CLOCK_CYCLE;
      fMode = TRIGGER_ALIGN;
      lstrcpy(fileName,"hwtrc");
      if( argc == 2 ) traceId = saveLastTraceId;
   }
   if( !traceId ) {
      err = TrcTraceOpen(&traceId,
               fileName,                    /* trace file name */
               tMode,                       /* cycle mode */
               fMode);                      /* frame mode */
   }
   else {
      err=GOOD;
      if( argc != 2 ) 
         InitializeTraceState(traceId, tMode, fMode);
   }
   if( err != GOOD ) return(err);
   return(SendCliResults((LPSTR)"trace opened",cliServerHandle));
}

#pragma argsused
RETCODE EXPORT TrcCliClose( LPSTR cmdString, U32 argc, U32 argv[] ) {
   RETCODE err=GOOD;
   if( traceId ){
      err = TrcTraceClose(traceId);
      traceId = 0;
   }
   return(err);
}

#pragma argsused
RETCODE EXPORT TrcCliClearTrace( LPSTR cmdString, U32 argc, U32 argv[] ) {
   return(TrcTraceBufferClear());
}

RETCODE EXPORT TrcCliGetFrameInstAddress(LPSTR cmdString, U32 argc, 
                     U32 argv[]) {
   DESCRIPTOR addr;
   BOOLEAN instFrame;
   S32 frame;
   S8 resultBuff[128];
   U32 offset;
   RETCODE err;
   S8 *ptr;
   if( !traceId ) return(ER_NO_TRACE_OPEN);
   if( (argc == 3) || (argc == 2) ) {
      if( cmdString[(U16)argv[1]] == '-' ) {
         strcpy(resultBuff,"-");
         strcat(resultBuff,&cmdString[(U16)argv[2]]);
      }
      else {
         strcpy(resultBuff,&cmdString[(U16)argv[1]]);
      }         
      frame = strtol(resultBuff,&ptr,0);
      if( lstrlen(ptr) != 0 ) return(ER_INVALID_FRAME);
      if((err=TrcGetFrameInstAddress(traceId,frame,&addr,&instFrame))!=GOOD) 
         return(err);
      if((err=AdrGetAddrOffset(addr,&offset))!=GOOD) return(err);
      if( instFrame )
         wsprintf(resultBuff,
         "frame:  %ld   contains instruction address:   %lX", frame, offset);
      else
         wsprintf(resultBuff,
            " frame:  %ld  is NOT an instruction read frame", frame);
      return(SendCliResults(resultBuff,cliServerHandle));
   }
   return(ER_CLI_SYNTAX);
}

#pragma argsused
RETCODE EXPORT TrcCliUpdateTrace( LPSTR cmdString, U32 argc, U32 argv[] ) {
   if( !traceId ) return(ER_NO_TRACE_OPEN);
   return(TrcUpdateTrace(traceId));
}

#pragma argsused
RETCODE EXPORT TrcCliFrameNumberAreaSizeGet(LPSTR cmdString, U32 argc,
                                            U32 argv[] ) {
   S8 resultBuff[128];
   U16 num;
   RETCODE err;
   if((err = TrcFrameNumberAreaSizeGet(&num))!=GOOD) return(err);
   wsprintf(resultBuff,"frame number area:  %d",num);
   return(SendCliResults(resultBuff,cliServerHandle));
}

RETCODE EXPORT TrcCliGetTimestamp(LPSTR cmdString, U32 argc, U32 argv[]) {
   S8 resultBuff[128];
   RETCODE err;
   TRACE_DESC_BLOCK FAR *trace;
   if( !traceId ) return(ER_NO_TRACE_OPEN);
   trace = (TRACE_DESC_BLOCK FAR *)traceId;
   if( argc == 2 ) {
      BOOLEAN value;
      value = ParseBoolean(&cmdString[(U16)argv[1]]);
      if( trace->timestampOn != value ) {
         if( (err=TrcTimestampSet(traceId,value)) != GOOD ) return(err);
      }
   }
   if( trace->timestampOn ) lstrcpy(resultBuff,"timestamp on");
   else lstrcpy(resultBuff,"timestamp off");
   return(SendCliResults(resultBuff,cliServerHandle));
}

#define RELATIVE_TEXT "RELATIVE"
#define DELTA_TEXT "DELTA"
#define ABSOLUATE_TEXT "ABSOLUATE"
TIMESTAMP_MODE parseTimestampMode(LPSTR ptr) {
   TIMESTAMP_MODE mode;
   if( ptr[0] == '0' )
      mode = RELATIVETOFRAME;
   else if( ptr[0] == '1' )
      mode = DELTA;
   else if( ptr[0] == '2' )
      mode = ABSOLUATE;
   else if(strncmpi(ptr, RELATIVE_TEXT, strlen(ptr))==0) 
      mode = RELATIVETOFRAME;
   else if(strncmpi(ptr, DELTA_TEXT, strlen(ptr))==0) 
      mode = DELTA;
   else if(strncmpi(ptr, ABSOLUATE_TEXT, strlen(ptr))==0)
      mode = ABSOLUATE;
   return(mode);
}

RETCODE EXPORT TrcCliTimestampMode(LPSTR cmdString, U32 argc,
                                          U32 argv[]) {
   S8 resultBuff[128];
   RETCODE err;
   TRACE_DESC_BLOCK FAR *trace;
   if( !traceId ) return(ER_NO_TRACE_OPEN);
   trace = (TRACE_DESC_BLOCK FAR *)traceId;
   if( argc == 2 ) {
      TIMESTAMP_MODE value;
      value = parseTimestampMode(&cmdString[(U16)argv[1]]);
      if( trace->tsMode != value ) {
         if( (err=TrcTimestampModeSet(traceId,value))!=GOOD ) return(err);
      }
   }
   if( trace->tsMode == RELATIVETOFRAME )
      lstrcpy(resultBuff,"relative to frame");
   else if( trace->tsMode == DELTA )
      lstrcpy(resultBuff,"delta");
   else
      lstrcpy(resultBuff,"absoluate");
   return(SendCliResults(resultBuff,cliServerHandle));
}

RETCODE EXPORT TrcCliGetZeroFrame(LPSTR cmdString, U32 argc, U32 argv[]) {
   S8 *ptr;
   S32 frame;
   S8 resultBuff[128];
   RETCODE err;
   if( !traceId ) return(ER_NO_TRACE_OPEN);
   if( (argc == 3) || (argc == 2) ) {
      if( cmdString[(U16)argv[1]] == '-' ) {
         strcpy(resultBuff,"-");
         strcat(resultBuff,&cmdString[(U16)argv[2]]);
      }
      else {
         strcpy(resultBuff,&cmdString[(U16)argv[1]]);
      }         
      frame = strtol(resultBuff,&ptr,0);
      if( lstrlen(ptr) != 0 ) return(ER_INVALID_FRAME);
      if( (err=TrcTimestampZeroFrameSet(traceId,frame)) != GOOD ) return(err);
   }
   if( (err=TrcTimestampZeroFrameGet(traceId,&frame)) != GOOD ) return(err);
   wsprintf(resultBuff,"%ld", frame);
   return(SendCliResults(resultBuff,cliServerHandle));
}

RETCODE EXPORT TrcCliGetfrequency(LPSTR cmdString, U32 argc, U32 argv[]) {
   S8 resultBuff[128];
   RETCODE err;
   if( argc == 2 ) {
      if( (err=TrcSystemCrystalSet(&cmdString[(U16)argv[1]])) != GOOD )
         return(err);
   }
   if( (err=TrcSystemCrystalGet(resultBuff)) != GOOD ) return(err);
   return(SendCliResults(resultBuff,cliServerHandle));
}

#pragma argsused
RETCODE EXPORT CliFlashRom(LPSTR cmdString, U32 argc, U32 argv[] ) {
   S8 *ptr;
   U8 resultBuff[128], i, tmpBuff[33], tBuff[3];
   RETCODE err;
   if( argc > 1 ) {
     if((err = Sds2AbiReadFRom(tmpBuff))!=GOOD) return(err);
      for (i=0; i< argc-1; i++) {
          strcpy(tBuff,&cmdString[(U16)argv[i+1]]);
          resultBuff[i] = (S8)strtol(tBuff,&ptr,16);
          }
     for (; i<32; i++)
         resultBuff[i]=tmpBuff[i];
     if((err = Sds2AbiWriteFRom(resultBuff))!=GOOD) return(err);
   }
   tmpBuff[0]='\0';
   if((err = Sds2AbiReadFRom(tmpBuff))!=GOOD) return(err);
   for (i=0; i<32 ;i++) {
       itoa((tmpBuff[i] & 0xf0), resultBuff+i*3, 16);
       itoa((tmpBuff[i] & 0x0f), resultBuff+i*3+1, 16);
       resultBuff[i*3+2]=' ';
   }
   resultBuff[i*3]='\0';
   return(SendCliResults(resultBuff,cliServerHandle));
}

/*************************** LOCAL FUNCTIONS ******************************/
/**************************************************************************
**
** ValidFrameNumber
**
** Description:
**    Determines if the incoming physical frame is valid for the given
**    trace buffer. The frame number is compared against the oldest
**    and youngest frames for the given buffer.
**
***************************************************************************/
RETCODE  ValidFrameNumber(U16 buffer, S32 frame, BOOLEAN emon){   
   RETCODE err;
   S32 oldest, youngest;
   if((err=SetupBufferCheck(buffer,emon))!=GOOD) return(err);
   if((err=SdnReadMember(SDN_BUFFER_OLDEST,(U8 FAR *)&oldest))!=GOOD) 
      return(err);
   if((err=SdnReadMember(SDN_BUFFER_YOUNGEST,(U8 FAR *)&youngest))!=GOOD) 
      return(err);
   if( (frame < oldest) || (frame >youngest) ) return(ER_INVALID_FRAME);
   return(GOOD);
}

char statusCode[8]={'A','I','O','H','S','R','W','D'};
char levelCode[4]={'0','1','2','3'};
char *traceCode[2]={"0","1"};

RETCODE  FormatFrameToText(DESCRIPTOR tmpltId, TRACE_INFO *framePtr,
                           S32 prevFrame, DESCRIPTOR id, LPSTR dataPtr) {
   U16 tmp, trcStart, trcStop;
   S8 lineBuff[128];
   LOOP_VAR i,j;
   RETCODE err;
   PROBE_TYPE specificProcessor;
   ACTION_MASK actionMask[8];
   BOOLEAN useEvt;

   wsprintf(lineBuff," %8ld ", framePtr->frameNumber);
   lstrcat(dataPtr,lineBuff);
   tmp= framePtr->leGroup & 0xff;
   if (tmp!= 0) {
      TrigEventSet(theTrigger, tmp);
      TrigSeqLevelSet(theTrigger,(framePtr->leGroup >> 8) & 0x03);
      TrigEventEnableGet(theTrigger, &useEvt);
   } else
       useEvt=FALSE;
   for (i=0x80, j=7; j>=0; i>>=1, j--) {
       actionMask[j]=0;
       if ((tmp & i) != 0) {
          TrcActionGet(j,(framePtr->leGroup >> 8) & 0x03,&actionMask[j]);
       }
   }
   for (i=tmp=trcStart=trcStop=0;i<8;i++) {
       tmp |= ((actionMask[i] & TRC_QUAL_MASK) == TRC_QUAL_MASK) ? 1 : 0;
       trcStart|=((actionMask[i] & TRC_START_MASK) == TRC_START_MASK) ? 1 : 0;
       trcStop|=((actionMask[i] & TRC_STOP_MASK) == TRC_STOP_MASK) ? 1 : 0;
   }
   if (tmp != 1) {
      if (framePtr->frameNumber < 0)
         trcMark=(trcMarkFrameOn > framePtr->frameNumber) ? 0: 1;
      else
         trcMark=(trcMarkFrameOn > framePtr->frameNumber) ? 1: 0;
      if (trcStart == 1) {
          trcMark2FrameOn=(trcMarkFrameOn==framePtr->frameNumber) ?
                          trcMark2FrameOn : trcMarkFrameOn;
          trcMarkFrameOn=framePtr->frameNumber;
          trcMark=1;
         }
      if (trcStop == 1) {
         trcMarkFrameOff=framePtr->frameNumber;
         trcMark=0;
      }
   }
   if (tmp == 1 && useEvt==TRUE)
      lstrcat(dataPtr,"@ ");
   else {
      if (trcMark == 1 ||
         ((framePtr->frameNumber < 0) &&
          ((trcMarkFrameOn <= framePtr->frameNumber) ||
           (trcMark2FrameOn !=0 && trcMark2FrameOn <= framePtr->frameNumber)) &&
          (trcMarkFrameOff > framePtr->frameNumber)) ||
         ((framePtr->frameNumber > 0) &&
          ((trcMarkFrameOn >= framePtr->frameNumber) ||
           (trcMark2FrameOn !=0 && trcMark2FrameOn >= framePtr->frameNumber)) &&
          (trcMarkFrameOff < framePtr->frameNumber)))
         lstrcat(dataPtr,"* ");
      else
         lstrcat(dataPtr,"  ");
   }
/* test */
//   framePtr->tshGroup=1;
/*******/
   if((optionFlag & TIMESTAMP_OPT)!=0)
     if((err=TrcGetTimestampText(id,framePtr->tsGroup,framePtr->tshGroup,
        prevFrame,dataPtr))
         != GOOD ) return(err);
//   if((err=TmpltGetFormattedTrace(tmpltId,dataPtr,
//                                  (XILINX_GROUP FAR *)&framePtr->rGroup))
//      != GOOD ) return(err);
   wsprintf(lineBuff," %05lX  ", framePtr->rGroup);
   lstrcat(dataPtr,lineBuff);
   ProcReturnSpecificProcessor(&specificProcessor);
   switch (specificProcessor) {
      case I80C186_MP:
      case I80C186XL_MP:
      case I80C186EA_MP:
      case I80C186EB_MP:
      case I80C186EC_MP:
        if ( !(framePtr->sGroup&0x10) ) {
           if (!(framePtr->rGroup&1)) 
              wsprintf(lineBuff," %04lX ", framePtr->tGroup);
           else
              wsprintf(lineBuff,"  %02lX  ", (framePtr->tGroup >> 8) & 0xff);
        } else {
           if (!(framePtr->rGroup&1)) 
              wsprintf(lineBuff,"  %02lX  ", framePtr->tGroup & 0xff);
           else
              wsprintf(lineBuff," %04lX ", framePtr->tGroup);
        }
        break;
      case I80C188_MP:
      case I80C188XL_MP:
      case I80C188EA_MP:
      case I80C188EB_MP:
      case I80C188EC_MP:
        wsprintf(lineBuff,"  %02lX  ", framePtr->tGroup & 0xff);
        break;
      default:
        break;
   }
   lstrcat(dataPtr,lineBuff);

   if ((optionFlag & STATUS_OPT)!=0) {
      if (framePtr->sGroup&0x0f)
         tmp=framePtr->sGroup&0x0f-8;
      else
         tmp = (framePtr->sGroup&0x20) ? 7 : framePtr->sGroup&0x0f-8;
      wsprintf(lineBuff,"   %c    ", statusCode[tmp]);
      lstrcat(dataPtr,lineBuff);
   }
   if ((optionFlag & TRACE_OPT)!=0) {
      lstrcat(dataPtr," ");
      tmp=(framePtr->sGroup >> 16) & 0xff;
      for (i=0x80, j=0; j<8; i>>=1, j++) {
          if ((tmp & i) == 0)
             lstrcat(dataPtr,traceCode[0]);
          else
             lstrcat(dataPtr,traceCode[1]);
         }
      lstrcat(dataPtr,"  ");
   }
   if ((optionFlag & LEVEL_OPT)!=0) {
      wsprintf(lineBuff," %c  ", levelCode[(framePtr->leGroup >> 8) & 0x03]);
      lstrcat(dataPtr,lineBuff);
   }
   if ((optionFlag & EVENT_OPT)!=0) {
      lstrcat(dataPtr," ");
      tmp= framePtr->leGroup & 0xff;
      for (i=0x80, j=0; j<8; i>>=1, j++) {
          if ((tmp & i) != 0)
             lstrcat(dataPtr,traceCode[1]);
          else
             lstrcat(dataPtr,traceCode[0]);
         }
      lstrcat(dataPtr,"  ");
   }
   /* bus event matched, <1/9/1997> */
   if ((optionFlag & ACTION_OPT)!=0 && ((framePtr->leGroup & 0x0ff) != 0) &&
       useEvt==TRUE) {
      TrcGetActionText(actionMask, dataPtr);
   }
   lstrcat(dataPtr,END_OF_LINE_TEXT);
   return(GOOD);
}

RETCODE TrcGetActionText(ACTION_MASK *actionMask, LPSTR dataPtr){
   U8 actionFlag, actionFlagMask;
   LOOP_VAR i, j;

   /* actionFlag= bit 7: TRC_START_MASK
                  bit 6: TRC_STOP_MASK
                  bit 5: TMR0_RST_MASK    | TC1_RST_MASK
                  bit 4: TMR0_START_MASK  | CNT1_INC_MASK
                  bit 3: TMR0_STOP_MASK   |
                  bit 2: TMR1_RST_MASK    | TC0_RST_MASK
                  bit 1: TMR1_START_MASK  | CNT0_INC_MASK
                  bit 0: TMR1_STOP_MASK   |                 */
   actionFlag=0;
   for (i=0; i<8; i++) {
       actionFlag |= ((actionMask[i] & TRC_START_MASK)==TRC_START_MASK)          ? 0x80 : 0x00;
       actionFlag |= ((actionMask[i] & TRC_STOP_MASK)==TRC_STOP_MASK)            ? 0x40 : 0x00;
   }
   actionFlagMask=0xc0;
   switch(tcMode) {
      case COUNT_COUNT:
           for (i=0; i<8; i++) {
               actionFlag |= ((actionMask[i] & CNT0_INC_MASK)==CNT0_INC_MASK)     ? 0x20 : 0x00;
               actionFlag |= ((actionMask[i] & TC0_RST_MASK)==TC0_RST_MASK)       ? 0x10 : 0x00;
               actionFlag |= ((actionMask[i] & CNT1_INC_MASK)==CNT1_INC_MASK)     ? 0x04 : 0x00;
               actionFlag |= ((actionMask[i] & TC1_RST_MASK)==TC1_RST_MASK)       ? 0x02 : 0x00;
           }
         actionFlagMask|=0x36;
         break;
      case COUNT_TIMER:
           for (i=0; i<8; i++) {
               actionFlag |= ((actionMask[i] & TMR0_START_MASK)==TMR0_START_MASK) ? 0x20 : 0x00;
               actionFlag |= ((actionMask[i] & TMR0_STOP_MASK)==TMR0_STOP_MASK)   ? 0x10 : 0x00;
               actionFlag |= ((actionMask[i] & TC0_RST_MASK)==TC0_RST_MASK)       ? 0x08 : 0x00;
               actionFlag |= ((actionMask[i] & CNT1_INC_MASK)==CNT1_INC_MASK)     ? 0x04 : 0x00;
               actionFlag |= ((actionMask[i] & TC1_RST_MASK)==TC1_RST_MASK)       ? 0x02 : 0x00;
           }
         actionFlagMask|=0x3e;
         break;
      case TIMER_COUNT:
           for (i=0; i<8; i++) {
               actionFlag |= ((actionMask[i] & CNT0_INC_MASK)==CNT0_INC_MASK)     ? 0x20 : 0x00;
               actionFlag |= ((actionMask[i] & TC0_RST_MASK)==TC0_RST_MASK)       ? 0x10 : 0x00;
               actionFlag |= ((actionMask[i] & TMR1_START_MASK)==TMR1_START_MASK) ? 0x08 : 0x00;
               actionFlag |= ((actionMask[i] & TMR1_STOP_MASK)==TMR1_STOP_MASK)   ? 0x04 : 0x00;
               actionFlag |= ((actionMask[i] & TC1_RST_MASK)==TC1_RST_MASK)       ? 0x02 : 0x00;
           }
         actionFlagMask|=0x3e;
         break;
      case TIMER_TIMER:
           for (i=0; i<8; i++) {
               actionFlag |= ((actionMask[i] & TMR0_START_MASK)==TMR0_START_MASK) ? 0x20 : 0x00;
               actionFlag |= ((actionMask[i] & TMR0_STOP_MASK)==TMR0_STOP_MASK)   ? 0x10 : 0x00;
               actionFlag |= ((actionMask[i] & TC0_RST_MASK)==TC0_RST_MASK)       ? 0x08 : 0x00;
               actionFlag |= ((actionMask[i] & TMR1_START_MASK)==TMR1_START_MASK) ? 0x04 : 0x00;
               actionFlag |= ((actionMask[i] & TMR1_STOP_MASK)==TMR1_STOP_MASK)   ? 0x02 : 0x00;
               actionFlag |= ((actionMask[i] & TC1_RST_MASK)==TC1_RST_MASK)       ? 0x01 : 0x00;
           }
         actionFlagMask|=0x3f;
         break;
      default:
         break;
   }
   lstrcat(dataPtr,"  ");
   for (i=0x80, j=0; j<8; i>>=1, j++) {
       if ((actionFlagMask & i) !=0 ) {
          if ((actionFlag & i) == 0)
             lstrcat(dataPtr,traceCode[0]);
          else
             lstrcat(dataPtr,traceCode[1]);
          lstrcat(dataPtr,"   ");
       }
   }
 return(GOOD);
}


RETCODE ReadTrace(DESCRIPTOR id, S32 numFrames, BOOLEAN raw, LPSTR *buffer){
   S32 numFramesRead, curFrameCount, prevFrame;
   U32 absFrameCount;
   TRACE_DESC_BLOCK FAR *trace;
   TRACE_INFO *framePtr;
   LPSTR dataPtr;
   RETCODE err;
   LOOP_VAR i, frameIdx, startIdx;
   BOOLEAN  backwards;

   err = GOOD;
   trace = (TRACE_DESC_BLOCK FAR *)id;
   startingFrame = endingFrame = 0;  /* special case - frames found */
   absFrameCount = numFrames;
   backwards = (numFrames < 0);
   if( backwards ) absFrameCount = 0 - numFrames;
   numFrames = 0;                    /* <JUDY 8/12/96> */
   preFrameTS=0.;
   if( (absFrameCount > MAX_TEXT_PER_FRAME) && !raw ) return(ER_TOO_MANY_FRAMES);
   if( (*buffer = TMalloc((
      (raw?sizeof(TRACE_INFO):MAX_TEXT_PER_FRAME)*absFrameCount)+1))
      == NULL) return(ER_OUT_OF_MEMORY);
   if((framePtr=(TRACE_INFO FAR *)TMalloc(sizeof(TRACE_INFO)*absFrameCount))
      == NULL ) {
      TFree(*buffer);
      *buffer = NULL;
      return(ER_OUT_OF_MEMORY);
   }
   dataPtr = *buffer;
   *dataPtr = '\0';   /* initialize string to be empty */
   frameIdx = 0;
   /* added by cjchen 1996/12/11
   if (backwards) {
      trace->startFrame=trace->startFrame-absFrameCount+1;
      if (trace->startFrame<firstBufferFrame)
         trace->startFrame=firstBufferFrame;
      if (trace->startFrame>lastBufferFrame)
         trace->startFrame=lastBufferFrame;
   }
    added by cjchen EOF 1996/12/11 */
   while( absFrameCount ) {
      numFramesRead = min(absFrameCount,0x20);
      curFrameCount = numFramesRead;
      if ( (err=Sds2AbiGetTraceFrames(trace->traceBuffer, trace->startFrame,
        &numFramesRead,(TRACE_INFO *)&framePtr[frameIdx])) != GOOD) return(err);
      if (numFramesRead==0) goto clear; /* <Judy 4/7/1997> */
      numFrames += numFramesRead;
      if( backwards ) prevFrame = trace->startFrame;
      startingFrame = framePtr[(U16)numFrames-1].frameNumber+1;
      frameIdx += numFramesRead;
      absFrameCount -= numFramesRead;
      if (curFrameCount != numFramesRead) break;
      if( TrcReadFrameSet(id,startingFrame) != GOOD ) break;
   }
   startIdx = 0;
   startingFrame = framePtr[startIdx].frameNumber;
   /* removed by cjchen 1996/12/09
   if (backwards) endingFrame = prevFrame;
   else endingFrame = framePtr[(U16)(startIdx+numFrames-1)].frameNumber;
   removed by cjchen EOF 1996/12/09 */
   endingFrame=framePtr[(U16)(startIdx+numFrames-1)].frameNumber; /* added by cjchen */
   numFrames = endingFrame - startingFrame + 1;
   if( raw ) {
      for( i=startIdx; i < (startIdx+numFrames); i++ ) {
         memcpy(dataPtr,(LPSTR)&framePtr[i],sizeof(TRACE_INFO));
         dataPtr += sizeof(TRACE_INFO);
         numRetrieved++;   
      }
   }
   else {
      for( i=startIdx; i < (startIdx+numFrames); i++ ) {
         if((err=FormatFrameToText(trace->templateId,&framePtr[i], prevFrame,
                                   id,dataPtr)) != GOOD) break;
         prevFrame = framePtr[i].frameNumber;
      }
   }
clear: /* Judy 4/7/1997 */
   TFree((LPSTR)framePtr);   
   return(err);
}

/**************************************************************************
**
** FormulateHeader
**
** Description:
**    Using the template server given formulates the header string
**    for displaying bus and clock cycles.
**
** Parameters:
**    input:
**       template:      template server id
**       header:        pointer to header storage
**    output:
**       header:        storage contains header text
**
***************************************************************************/
RETCODE FormulateHeader(TRACE_DESC_BLOCK FAR *trace) {
/*   U8 statusName[]=" status  flush  DMA  trace-bit"; */
   U8 displayLen;
   U16 numFields, curField, linePos, tempPos;
   RETCODE err;
   LOOP_VAR i, j;

   for( i=0; i < NUM_HDR_LINES*MAX_HDR_LINE; i++ ) 
      trace->header[i] = ' ';  /* fill header with spaces */
   trace->header[i] = '\0';
   linePos = 2;    /* for trace qualify mark */
   for( i=0; i < NUM_HDR_LINES; i++ ) {
      trace->header[(MAX_HDR_LINE*(i+1))-2] = '\r';
      trace->header[(MAX_HDR_LINE*(i+1))-1] = '\n';
   }

/***Judy 8/7/96 ***/
   if((optionFlag & TIMESTAMP_OPT)!=0) {
      for( i=0; i<lstrlen(TIMESTAMP_TEXT); i++ ) 
         trace->header[MAX_HDR_LINE+linePos+i] = TIMESTAMP_TEXT[i];
      linePos += TIMESTAMP_LEN+1;
   }
/*****/

//   if( (err=TmpltGetNumOfEntries(trace->templateId,&numFields)) != GOOD ) 
//      return(err);
   numFields = 2;
   curField = 1;
   while(numFields--) {
      S8  fieldName[MAX_FIELD_NAME];
      U16 trailing;
      BOOLEAN visible;
      if( (err=TmpltGetNameGivenFieldNumber(trace->templateId, curField++,
               fieldName, MAX_FIELD_NAME)) != GOOD ) return(err);
      if( (err=TmpltGetVisible(trace->templateId, &visible)) != GOOD )
         return(err);
      if(!visible) continue;
      if( (err=TmpltGetDisplayLength(trace->templateId, &displayLen))!=GOOD )
         return(err);
      if( (err=TmpltGetTrailingBlanks(trace->templateId, &trailing)) != GOOD )
         return(err);
      tempPos = linePos;
      for( i=0; i<lstrlen(fieldName); i++ ) 
         trace->header[MAX_HDR_LINE+tempPos+i] = fieldName[i];
      linePos += (lstrlen(fieldName) + trailing);
      if( linePos > MAX_HDR_LINE ) return(ER_TOO_MANY_FIELDS);
   }

   if((optionFlag & STATUS_OPT)!=0) {
      for( i=0; i<lstrlen(STATUS_TEXT); i++ )
         trace->header[MAX_HDR_LINE+linePos+i] = STATUS_TEXT[i];
      linePos += STATUS_LEN;
   }
   if((optionFlag & TRACE_OPT)!=0) {
      for( i=0; i<lstrlen(TRACE_TEXT); i++ )
         trace->header[MAX_HDR_LINE+linePos+i] = TRACE_TEXT[i];
      linePos += TRACE_LEN;
   }
   if((optionFlag & LEVEL_OPT)!=0) {
      for( i=0; i<lstrlen(LEVEL_TEXT); i++ )
         trace->header[MAX_HDR_LINE+linePos+i] = LEVEL_TEXT[i];
      linePos += LEVEL_LEN;
   }
   if((optionFlag & EVENT_OPT)!=0) {
      for( i=0; i<lstrlen(EVENT_TEXT); i++ )
         trace->header[MAX_HDR_LINE+linePos+i] = EVENT_TEXT[i];
      for( i=0; i<lstrlen(EVENT_2TEXT); i++ )
         trace->header[MAX_HDR_LINE*2+linePos+i] = EVENT_2TEXT[i];
      linePos += EVENT_LEN;
   }
   if((optionFlag & ACTION_OPT)!=0) {
      j=linePos;
      for( i=0; i<lstrlen(TRC_TEXT); i++ )
         trace->header[MAX_HDR_LINE+linePos+i] = TRC_TEXT[i];
      for( i=0; i<lstrlen(TRC_2TEXT); i++ )
         trace->header[MAX_HDR_LINE*2+linePos+i] = TRC_2TEXT[i];
      linePos += lstrlen(TRC_TEXT);
      TrcCounterFunctionGet(&tcMode);
      switch(tcMode) {
         case COUNT_COUNT:
            for( i=0; i<lstrlen(TC0TC1_TEXT); i++ )
               trace->header[MAX_HDR_LINE+linePos+i] = TC0TC1_TEXT[i];
            for( i=0; i<lstrlen(TC0TC1_2TEXT); i++ )
               trace->header[MAX_HDR_LINE*2+linePos+i] = TC0TC1_2TEXT[i];
            break;
         case COUNT_TIMER:
            for( i=0; i<lstrlen(TM0TC1_TEXT); i++ )
               trace->header[MAX_HDR_LINE+linePos+i] = TM0TC1_TEXT[i];
            for( i=0; i<lstrlen(TM0TC1_2TEXT); i++ )
               trace->header[MAX_HDR_LINE*2+linePos+i] = TM0TC1_2TEXT[i];
            break;
         case TIMER_COUNT:
            for( i=0; i<lstrlen(TC0TM1_TEXT); i++ )
               trace->header[MAX_HDR_LINE+linePos+i] = TC0TM1_TEXT[i];
            for( i=0; i<lstrlen(TC0TM1_2TEXT); i++ )
               trace->header[MAX_HDR_LINE*2+linePos+i] = TC0TM1_2TEXT[i];
            break;
         case TIMER_TIMER:
            for( i=0; i<lstrlen(TM0TM1_TEXT); i++ )
               trace->header[MAX_HDR_LINE+linePos+i] = TM0TM1_TEXT[i];
            for( i=0; i<lstrlen(TM0TM1_2TEXT); i++ )
               trace->header[MAX_HDR_LINE*2+linePos+i] = TM0TM1_2TEXT[i];
            break;
      }
   }
   return(GOOD);
}

/**************************************************************************
**
** InitializeTraceState
**
** Description:
**    Using the template server given formulates the header string
**    for displaying bus and clock cycles.
**
** Parameters:
**    input:
**       template:      template server id
**       header:        pointer to header storage
**    output:
**       header:        storage contains header text
**
***************************************************************************/
VOID InitializeTraceState(DESCRIPTOR id, TRACE_CYCLES tMode, 
                          FRAME_DISPLAY_MODE fMode) {
   TRACE_DESC_BLOCK FAR *trace;
   RETCODE err;
   trace = (TRACE_DESC_BLOCK FAR *)id;
   trace->debugEmon = FALSE;
   trace->cycleMode = tMode;
   trace->frameMode = fMode;
   trace->traceBuffer = 0;

   trace->searchEvent[0] = '\0'; /* if we end up calculating the emon ON
                                    info this needs to be initialized first */
   TrcUpdateTrace(id);           /* incase trace was collected already */

   trace->searchBuffer = trace->traceBuffer;
   trace->searchStartFrame = trace->startFrame;
   trace->timestampOn = ((optionFlag & TIMESTAMP_OPT)==0) ? 0 : 1;
   trace->tsMode = ABSOLUATE;
   trace->zeroedFrame = 0;
}

RETCODE GetHardwareState(VOID) {
//   if((err=SdnWriteCmdReadResponse(SDN_TRACE_GET_STATUS,&value,GOOD,
//                         SDN_TRACE_GET_STATUS,10,&timedOut))!= GOOD )
//      return(err); <matthew 9/24/96>
   traceInfoDirty=TRUE;  /* Force recalculation next time buffer info needed */
   return(GOOD);
}

VOID FAR PASCAL TracingStateChange(DESCRIPTOR desc)  {
   static BOOLEAN oldTracingValue=0;
   BOOLEAN tracing;
   RETCODE err;
   err = SdReadMemberNoInputCheck(desc, (U8 FAR*)&tracing);
   if( err ) { ErrDisplayError(err, CHECK_MODE); return; }
   if( oldTracingValue != tracing ) {
      U32 eventType=EVENT_TRACE_TRACING_ON;
      oldTracingValue = tracing;
      if( tracing == FALSE ) {
      /* Must have just stopped tracing - so now we need to update
         the tracing status information.
         */
     /* To clear trace on/off mark <judy 4/7/1997> */
         trcMark=0;
         trcMarkFrameOn=0;trcMark2FrameOn=0; trcMarkFrameOff=0;
     /******/
         eventType = EVENT_TRACE_TRACING_OFF;
         if((err=GetHardwareState())!=GOOD) {
            ErrDisplayError(err, CHECK_MODE);
            return;
         }
      }
      /* will only pass notification on if tracing is STOPPING! */
      if((err=EnlEventNotify(eventType))!=GOOD)
         ErrDisplayError(err, CHECK_MODE);
   }
}

U16 EXPORT NumTraceBuffers(VOID) {
   U16 numTraceBuffers;
   if( SdnReadMember(SDN_NUM_TRCBUFS, (U8 FAR *)&numTraceBuffers) ) return(1);
   if( !numTraceBuffers ) numTraceBuffers = 1;  /* always return at least 1 */
   return(numTraceBuffers);
}

U16 EXPORT NumSubBufsPerTraceBuffer(VOID) {
   return(NUM_SUBBUFFERS/NumTraceBuffers());
}

U16 CalculateTraceBufferFromSubBuffer(U16 subBuffer) {
   U16 traceBuffer;
   BOOLEAN tracing;
   RETCODE err;
   traceBuffer = subBuffer / NumSubBufsPerTraceBuffer();
   if((err=TrcTracingGet(&tracing))!= GOOD ) return(err);
   if( !tracing ) {  /* if we have stopped tracing current subbuffer points */
             /* to next trace buffer - so decrement trace buffer to get last 
                collected trace buffer. */
      if( !traceBuffer ) {
         traceBuffer = NumTraceBuffers() - 1; 
      }
      else traceBuffer--;
   }
   /* else if we are tracing then just return currently active trace buffer */
   return(traceBuffer);
}

VOID FAR PASCAL SubBufferUpdate(DESCRIPTOR desc)  {
   RETCODE err;
   static U16 oldBuffer=0;
   U16 curSub, curBuf;
   if((err=SdReadMember(desc, (U8 FAR*)&curSub))!=GOOD) {
      ErrDisplayError(err, CHECK_MODE);
      return;
   }
   curBuf = CalculateTraceBufferFromSubBuffer(curSub);
   if( curBuf != oldBuffer ) {
      oldBuffer = curBuf;
      if( (err=EnlEventNotify(EVENT_TRACE_NEW_SUB_BUFFER)) != GOOD )
         ErrDisplayError(err, CHECK_MODE);
   }
}

#pragma argsused
VOID FAR PASCAL TraceClearCallback(U32 event) {
   RETCODE err;
   if((err=GetHardwareState())!=GOOD)
      ErrDisplayError(err, CHECK_MODE);
}

RETCODE SetupBufferCheck(U16 buffer, BOOLEAN emon) {
   BOOLEAN timedOut;
   RETCODE err;
   U16 curBuffer;
  /* if emon ptr is NIL then use emon that's there. */
   if((err=SdnReadMember(SDN_BUFFER_CHECK,(U8 FAR *)&curBuffer))!=GOOD)
      return(err);
   if(curBuffer != buffer) {
      if((err=SdnWriteCmdReadResponse(SDN_BUFFER_CHECK, &buffer, 
         GOOD, SDN_BUFFER_YOUNGEST, 0, &timedOut)) != GOOD ) 
         return(err);
   }
   return(GOOD);
}

float timeScalar[6]={1., 1000., 1000., 1000., 60., 60};
LPSTR timeUnit[6]={"ns", "us",  "ms",  "s ", "m ", "h "};
RETCODE EXPORT TrcGetTimestampText(DESCRIPTOR id, U32 curTStamp, U8 hcurTStamp,
                                   S32 prevFrame, LPSTR dataPtr) {
/*  period = 1 / frequency
*  Each frame is a clock : thus frameNumber * period is timestamp value
*  when timestamp is centered around trigger (i.e.: trigger's frame number
*  is zero).
*
*  Units need to change depending on what looks best. */
   long double time, spcTime, absTime;
   S8 tmpBuf[40];
   TRACE_DESC_BLOCK FAR *trace;
   U32 tmpTime;
   U8  bufTime[30],i, *endptr;

   trace = (TRACE_DESC_BLOCK FAR *)id;
   if( !trace->timestampOn ) return(GOOD);  /*  no timestamp field-just get out */
   if (hcurTStamp !=0) {
      time=(long double)hcurTStamp;
      time=time * 65536. * 65536.;
      time= time+(long double)curTStamp;
      spcTime=time;
      /*
      itoa(hcurTStamp, bufTime, 16);
      ultoa(curTStamp, bufTime+1, 16);
      spcTime = time = _atold(bufTime);*/
   } else {
      spcTime = time = curTStamp;
   }

   if( trace->tsMode == RELATIVETOFRAME )
      time -= zeroedFrameTS;
   else
   if ( trace->tsMode == DELTA)
        time -= preFrameTS;
   absTime = time * 50.;
   if( time != 0 && (preFrameTS !=0 || trace->tsMode != DELTA)) {
      for(i=0; i<6; i++) {
         absTime/= timeScalar[i];
         if( absTime > pow10l(8) ) continue; //Fixed bug for #289, Eric 6/3/98
         ltoa((long)absTime,bufTime,10);
         if( strlen(bufTime) < TIMESTAMP_LEN-3) {
            sprintf(tmpBuf,"%9s",bufTime);
            sprintf(tmpBuf+strlen(tmpBuf), "%s  ", timeUnit[i]);
            break;
         }
      }
      lstrcat(dataPtr,tmpBuf);
   }
   else lstrcat(dataPtr,"-----------  ");
   preFrameTS = spcTime;
   return(GOOD);
}

/*****************************************************************************
**
**    TrcBtmGet
**
*****************************************************************************/
RETCODE EXPORT TrcBtmGet(BOOLEAN FAR *value) {
   return(SdnReadMember(SDN_BTM_ENABLE,value));
}

/*****************************************************************************
**
**    TrcBtmSet
**
*****************************************************************************/
RETCODE EXPORT TrcBtmSet(BOOLEAN value) {
   return(SdnWriteMember(SDN_BTM_ENABLE,&value,GOOD));
}

VOID GetBusData (U32 addr, U8 status, U16 *data) {
   PROBE_TYPE specificProcessor;

   ProcReturnSpecificProcessor(&specificProcessor);
   switch (specificProcessor) {
      case I80C186_MP:
      case I80C186XL_MP:
      case I80C186EA_MP:
      case I80C186EB_MP:
      case I80C186EC_MP:
        if ( !(status & 0x10) ) {
           if (addr & 1) *data = (*data >> 8) & 0xff;
        } else {
           if (!(addr & 1)) *data = *data & 0xff;
        }
        break;
      case I80C188_MP:
      case I80C188XL_MP:
      case I80C188EA_MP:
      case I80C188EB_MP:
      case I80C188EC_MP:
        *data = *data & 0xff;
        break;
   }
}

/*****************************************************************************
**
**    initOptionFlag
**
*****************************************************************************/
RETCODE initOptionFlag() {
   S8 str[128], profile[128];
   optionFlag=0;

   if(!GetProfileString("PowerViews","pwrviewdir","",profile,
     sizeof(profile))) lstrcpy(profile,"mp186.ini");
   GetPrivateProfileString("TraceInfo","timestamp","",(LPSTR)str,
          sizeof(str), profile);
   if(strncmpi(str, "on", strlen(str))==0)
      optionFlag |= TIMESTAMP_OPT;
   GetPrivateProfileString("TraceInfo","showStatus","",(LPSTR)str,
          sizeof(str), profile);
   if(strncmpi(str, "on", strlen(str))==0)
      optionFlag |= STATUS_OPT;
   GetPrivateProfileString("TraceInfo","showTraceBit","",(LPSTR)str,
          sizeof(str), profile);
   if(strncmpi(str, "on", strlen(str))==0)
      optionFlag |= TRACE_OPT;
   GetPrivateProfileString("TraceInfo","showAction","",(LPSTR)str,
          sizeof(str), profile);
   if(strncmpi(str, "on", strlen(str))==0)
      optionFlag |= ACTION_OPT;
   GetPrivateProfileString("TraceInfo","showSequenceLevel","",(LPSTR)str,
          sizeof(str), profile);
   if(strncmpi(str, "on", strlen(str))==0)
      optionFlag |= LEVEL_OPT;
   GetPrivateProfileString("TraceInfo","showBusEvent","",(LPSTR)str,
          sizeof(str), profile);
   if(strncmpi(str, "on", strlen(str))==0)
      optionFlag |= EVENT_OPT;
/*   trcMark=0; */
   return(GOOD);
}

/*****************************************************************************
**
**    setOptionFlag2Profile
**
*****************************************************************************/
char *onStr="on";
char *offStr="off";
RETCODE setOptionFlag2Profile() {
   if((optionFlag & TIMESTAMP_OPT)==0)
      WritePrivateProfileString("TraceInfo","timestamp",offStr,
                "mp186.ini");
   else
      WritePrivateProfileString("TraceInfo","timestamp",onStr,
                "mp186.ini");
   if((optionFlag & STATUS_OPT)==0)
      WritePrivateProfileString("TraceInfo","showStatus",offStr,
                "mp186.ini");
   else
      WritePrivateProfileString("TraceInfo","showStatus",onStr,
                "mp186.ini");
   if((optionFlag & TRACE_OPT)==0)
      WritePrivateProfileString("TraceInfo","showTraceBit",offStr,
                "mp186.ini");
   else
      WritePrivateProfileString("TraceInfo","showTraceBit",onStr,
                "mp186.ini");
   if((optionFlag & ACTION_OPT)==0)
      WritePrivateProfileString("TraceInfo","showAction",offStr,
                "mp186.ini");
   else
      WritePrivateProfileString("TraceInfo","showAction",onStr,
                "mp186.ini");
   if((optionFlag & LEVEL_OPT)==0)
      WritePrivateProfileString("TraceInfo","showSequenceLevel",offStr,
                "mp186.ini");
   else
      WritePrivateProfileString("TraceInfo","showSequenceLevel",onStr,
                "mp186.ini");
   if((optionFlag & EVENT_OPT)==0)
      WritePrivateProfileString("TraceInfo","showBusEvent",offStr,
                "mp186.ini");
   else
      WritePrivateProfileString("TraceInfo","showBusEvent",onStr,
                "mp186.ini");
   return(GOOD);
}

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