/****************************************************************************
**
**  Name:  memcli.c
**
**  Description:
**     This is the memory server code of the Thunderbird.
**
**  Status:  PRELIMINARY
**
**  $Log:   S:/tbird/mt2_186/mem/memcli.c_v  $
** 
**    Rev 1.11   19 Mar 1998 10:20:46   Winky
** Add MemCliUploadMemory function.
** 
**    Rev 1.10   10 Sep 1997 17:46:18   Judy
** 
**    Rev 1.9   18 Apr 1997 09:32:02   Judy
** 
**    Rev 1.8   31 Jan 1997 13:42:20   Judy
** Modify diagnostic function.
** 
**    Rev 1.7   28 Jan 1997 15:27:54   Judy
** fixed some cli syntax checking problem
** 
**    Rev 1.6   27 Jan 1997 14:20:04   Judy
** 
**    Rev 1.6   27 Jan 1997 14:18:10   Judy
** 
**    Rev 1.6   27 Jan 1997 14:16:08   Judy
** 
**    Rev 1.6   27 Jan 1997 14:14:56   Judy
** 
**    Rev 1.6   27 Jan 1997 14:12:40   Judy
** 
**    Rev 1.5   20 Jan 1997 13:17:48   Judy
** To modify diagnostic function.
** 
**    Rev 1.4   09 Jan 1997 18:47:22   Judy
** modify diagnostic for MTAT2
** 
**    Rev 1.3   07 Jan 1997 16:22:34   Judy
** 
**    Rev 1.2   20 Dec 1996 18:09:24   Judy
** 
**    Rev 1.1   16 Dec 1996 17:59:26   Judy
** To fix shell command TLIST bug
** 
**    Rev 1.0   16 Dec 1996 13:50:08   Judy
** Initial revision.
** 
**    Rev 1.49   11 Aug 1994 08:48:20   ernie
** Removed extra \n's from ramtst failure output.
** 
**    Rev 1.48   10 Aug 1994 15:39:58   marilyn
** Fixed pprs 9539 and 9540.
** 
**    Rev 1.47   23 Jun 1994 14:46:44   marilyn
** Calls to AdrConvAddressToText use no 0x prefix.
** 
**    Rev 1.46   18 May 1994 09:53:24   marilyn
** Updated for 386 beta support.
** 
**    Rev 1.42   16 Jul 1993 11:53:38   ernie
** Removed error.h include.  All errors now in errcodec.h
** 
**    Rev 1.41   14 Jul 1993 16:27:36   tom
** PPR 8278: Dump with backwards addresses now dumps from smaller to larger.
** 
**    Rev 1.40   13 Jul 1993 07:07:22   doug
** Use generic syntax error.
** 
**    Rev 1.39   25 Jun 1993 17:27:48   paul
** Change CHECK_ABORT to TskCheckAbort
** 
**    Rev 1.38   25 May 1993 11:54:40   ernie
** Changed interface to MemRead()
** 
**    Rev 1.37   17 Mar 1993 13:18:48   john
** Checked in memory space changes for Mindy
** 
**    Rev 1.36   06 Jan 1993 11:32:28   ernie
** Implemented cli data size for write, fill, and search
** 
**    Rev 1.35   15 Dec 1992 13:32:00   ernie
** Removed code for write word now that access size support is implemented.
** 
**    Rev 1.34   02 Dec 1992 10:23:56   john
** added error message for word size transfers
** 
**    Rev 1.33   03 Nov 1992 11:08:28   john
** fixed memory cleanup bug
** 
**    Rev 1.32   22 Oct 1992 15:01:10   john
** fixed address display for cli dump command
** 
**    Rev 1.31   20 Oct 1992 11:00:40   john
** moved report verify error to memory.c to provide a more generic
** method of reporting the error.  This allows presenters as well as
** servers to display the data to the user.
** 
**    Rev 1.30   16 Oct 1992 17:07:04   john
** backed out previous changes
** 
**    Rev 1.29   06 Oct 1992 12:52:52   john
** Changed the pattern buffer to a TMalloc'd buffer.  This was done
** because memfill may or may not call memwrite.  Memwrite expects a
** tmalloc'd buffer to free after the successful write.  Memfill frees a
** tmalloc'd buffer like memwrite.
** 
**    Rev 1.28   18 Sep 1992 09:18:38   john
** added code to make writemem use word size bus accesses
** 
**    Rev 1.27   16 Sep 1992 10:44:18   john
** Added word write command
** 
**    Rev 1.26   14 Sep 1992 15:34:56   john
** Added a verify error printout.
** Fixed address/memory descriptor leaks.
** Changed cli write to alloc memory sent to memwrite.  (as spec'd)
** 
**    Rev 1.25   08 Sep 1992 12:06:26   john
** added memory verify printout (untested)
** 
**    Rev 1.24   03 Sep 1992 13:10:50   brucea
** Fixed: max argument bug in MemCliFillMemory
**        Added CLEANUP code
** 
** 
**    Rev 1.23   19 Aug 1992 18:52:20   brucea
** Removed: check for error from SendMessage since it doesn't return one
** 
**    Rev 1.22   18 Aug 1992 18:56:48   brucea
** Changed: AdrConvAddressToText to ...WithParams
** 
**    Rev 1.21   17 Aug 1992 16:43:28   brucea
** Changed: wsprintf to sprintf
** Removed compiler warnings
** 
**    Rev 1.20   08 Aug 1992 11:17:02   tom
** New CLI registration
** 
**    Rev 1.19   03 Aug 1992 06:33:00   mindy
** default to SD if no address space given
** 
**    Rev 1.18   28 Jul 1992 19:47:58   brucea
** Removed: variables no longer in use
** Cast vars which report (from compiler) a potential loss of significance
** 
**    Rev 1.17   22 Jul 1992 16:10:16   doug
** a) added verify command
** b) size with no parameters now displays current setting
** 
**    Rev 1.16   21 Jul 1992 11:57:04   brucea
** Added: #include "proc.h" and modified processor-dependent calls to include
**    an if() to test for processor first
** 
**    Rev 1.15   15 Jun 1992 09:45:40   brucea
** Rewrote: MemCliDumpMemory to support byte, word, long, dword parameter which
**    displays the output in those memory sizes
** 
**    Rev 1.14   20 May 1992 11:29:44   mindy
** initCServer needs to return GOOD if no errors
** 
**    Rev 1.13   15 May 1992 15:38:50   brucea
** Removed: local macro defines
** Cleaned: SendCliMessage error generation
** 
** 
**    Rev 1.12   12 May 1992 19:23:38   brucea
** Fixed: ppr5477 bug in MemCliDumpMemory
** Added: MemCliSetMemSize to set probe memory write size to byte, word, or long
** 
**    Rev 1.11   17 Mar 1992 09:56:30   brucea
** Fixed: MemCliSearchMemory bug in which access to an address descriptor
**    occurred after it was destroyed.
** 
**    Rev 1.10   06 Mar 1992 09:39:42   doug
** added memory search
** 
**    Rev 1.9   03 Mar 1992 10:21:52   doug
** destroy the address descriptor after using
** 
**    Rev 1.8   02 Mar 1992 17:54:10   doug
** memory is returned in buff... use that to get data!
** 
**    Rev 1.7   28 Feb 1992 15:02:14   doug
** a) changed names to match .res
** b) use strtoul instead of sscanf
** 
**    Rev 1.6   28 Feb 1992 11:57:16   doug
** need prototype for freeing memory
** 
**    Rev 1.5   28 Feb 1992 11:23:34   doug
** typo on line length; there are only 3 commands
** 
**    Rev 1.4   28 Feb 1992 11:22:24   doug
** simple read, write, and fill
** 
**    Rev 1.3   14 Feb 1992 12:47:10   doug
** a) ifdef'ed out debug statements
** b) fixed boundary error on byte check
** 
**    Rev 1.2   24 Jan 1992 17:48:26   doug
** Fixed cli interface desc.
** 
**    Rev 1.1   23 Jan 1992 16:22:18   doug
** a) new error numbers
** b) new output for CLI
** c) check for maximum fill length
** 
**    Rev 1.0   14 Jan 1992 13:49:46   tom
** Initial revision.
**
**  $Header:   S:/tbird/mt2_186/mem/memcli.c_v   1.11   19 Mar 1998 10:20:46   Winky  $
**
**  Copyright (C) 1991 Microtek International.  All rights reserved.
**
*****************************************************************************/

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

#ifndef _BASEWIND_
#include "basewind.h"
#endif

#ifndef _ADDR_
#include "addr.h"
#endif

#ifndef _CLISRV_
#include "clisrv.h"
#endif

#ifndef _HEAP_
#include "heap.h"
#endif

#ifndef _MEMCLI_
#include "memcli.h"
#endif

#ifndef _MEMLOCAL_
#include "memlocal.h"
#endif

#ifndef _PROC_
#include "proc.h"
#endif

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

#ifndef _PVTEST_
#include "pvtest.h"
#endif

#ifndef _SDPROBE_
#include "sdprobe.h"
#endif

#ifndef _SSHARED_
#include "sshared.h"
#endif

#ifndef __STDLIB_H
#include "stdlib.h"
#endif

#ifndef __STDIO_H
#include "stdio.h"
#endif

#ifndef __STRING_H
#include "string.h"
#endif

#ifndef _MAP_
#include "map.h"
#endif

#ifndef _TBIRDMEM_
#include "tbirdmem.h"
#endif

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

#ifndef  _CPU_
#include "cpu.h"
#endif

                       /****************************
                        *                          *
                        *     GLOBAL DEFINITIONS    *
                        *                          *
                        ****************************/
/*
RETCODE EXPORT iceGetQualifyFrame(U16 bufID, S32 startFrame, QUALIFY_LIST *cond,
                                U8 *frameLen, MP_TRACE_INFO *frameData);
RETCODE EXPORT iceGetTraceBufferInfo(U16 bufID, S32 *start, S32 *end);
RETCODE EXPORT iceGetTraceInfo(U16 *lastBuf,U16 *cnt0,U16 *cnt1,U16 *maxBuf);
RETCODE EXPORT Sds2AbiFwUnloadRegisters(BOOLEAN patchPCSP);
*/
                       /****************************
                        *                          *
                        *     LOCAL DEFINITIONS    *
                        *                          *
                        ****************************/

HANDLE cliServerHandle = (HANDLE)NULL;  /* force definition here */
PROCESSOR_FAMILY procFamily;
STATIC ADDR_SPACE addrSpace;
STATIC ACCESS_SIZE dataSize;
STATIC BOOLEAN loop;
STATIC BOOLEAN extendedSpaceEnabled;
STATIC ADDR_SPACE extendedSpace;
STATIC BOOLEAN sizeKeyword;
STATIC BOOLEAN spaceKeyword;
STATIC BOOLEAN loopKeyword;
U16 currentBuffID = 0;

#define LINE_LENGTH 16 /* number of bytes on a display line */

#define BYTE_TEXT "byte"
#define WORD_TEXT "word"
#define LONG_TEXT "long"
#define DWORD_TEXT "dword"
#define UNKNOWN_TEXT "unknown"
#define ON_TEXT "on"
#define OFF_TEXT "off"
#define LOOP_TEXT "loop"

#define VERIFY_ERROR_TEXT_SIZE 41

/* Winky 3/17/98 */
#define HEX_TYPE_DATA "00"
#define HEX_TYPE_END  ":00000001FF"
#define HEX_TYPE_EXT  ":02000002"
#define HEX_TYPE_ST   ":04000003"
#define HEX_ADDR_SIZE 2
/* EOF 3/17/98 */

typedef union {
   U32  U32Val;
   U16  U16Val[2];
   U8   U8Val[4];
} DATA_UNION;

                        /****************************
                         *                          *
                         *     LOCAL PROTOTYPES     *
                         *                          *
                         ****************************/

VOID PRIVATE KeywordInit(VOID);
BOOLEAN PRIVATE KeywordCheck(LPSTR str);
RETCODE PRIVATE MemCliDumpAction(LPSTR cmdString, U32 argc, U32 argv[]);
RETCODE PRIVATE MemCliWriteAction(LPSTR cmdString, U32 argc, U32 argv[]);
RETCODE PRIVATE MemCliRamtstAction(LPSTR cmdString, U32 argc, U32 argv[]);
BOOLEAN PRIVATE IsProcessorSpace(ADDR_SPACE space);
VOID DiagnosticMCE(VOID);
VOID DiagnosticMTAT2(U16 diagStatus);
VOID DiagnosticMCEConnect(VOID);
VOID GetBusData (U32 addr, U8 status, U16 *data);
RETCODE  FormatFrameToText(MP_TRACE_INFO *framePtr, LPSTR dataPtr,
            BOOLEAN listAllFlag, U16 buffID);

typedef enum {COLD_START,NORMAL_STATUS,DIAGNOSTIC_STATUS,HW_RESET_STATUS} FW_STATUS;

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

RETCODE SendCliMessage(HANDLE cliHandle, LPSTR msgPtr) {

   HANDLE               msgBufHandle;
   CSERVER_RESULTS FAR  *msgBufPtr;
   U16                  msgTextSize, loop ;

   msgTextSize = lstrlen(msgPtr);
   if ((msgBufHandle =
      GlobalAlloc(GMEM_MOVEABLE,
                  (sizeof(CSERVER_RESULTS) + msgTextSize + 2)))
      == (HANDLE)NULL) {
      return(ER_OUT_OF_MEMORY);
   }
   else if((msgBufPtr=(CSERVER_RESULTS *)GlobalLock(msgBufHandle)) == NULL) {
      GlobalFree(msgBufHandle);
      return(ER_WINDOWS_MEMLOCK);
   }
   msgBufPtr->target               = 0;    /*@@ CLI: not yet def'ed @@*/
   msgBufPtr->variantCode          = CLI_SERVER_RESULTS;
   msgBufPtr->resultTextLength     = msgTextSize; /* message string length */
   for (loop = 0; loop < msgTextSize; loop++ ) {
      msgBufPtr->messageText[loop]  =  *msgPtr++;
   }
   msgBufPtr->messageText[msgTextSize+1] = 0 ;

   SendMessage(cliHandle, CLI_SERVER_RESULTS,
               msgBufHandle, CLI_SERVER_RESULTS);
   return GOOD;
}

RETCODE SendCliMessageNo(HANDLE cliHandle, LPSTR msgPtr) {

   HANDLE               msgBufHandle;
   CSERVER_RESULTS FAR  *msgBufPtr;
   U16                  msgTextSize, loop ;

   msgTextSize = lstrlen(msgPtr);
   if ((msgBufHandle =
      GlobalAlloc(GMEM_MOVEABLE,
                  (sizeof(CSERVER_RESULTS) + msgTextSize + 2)))
      == (HANDLE)NULL) {
      return(ER_OUT_OF_MEMORY);
   }
   else if((msgBufPtr=(CSERVER_RESULTS *)GlobalLock(msgBufHandle)) == NULL) {
      GlobalFree(msgBufHandle);
      return(ER_WINDOWS_MEMLOCK);
   }
   msgBufPtr->target               = 0;    /*@@ CLI: not yet def'ed @@*/
   msgBufPtr->variantCode          = CLI_SERVER_RESULTS;
   msgBufPtr->resultTextLength     = msgTextSize-1; /* message string length */
   for (loop = 0; loop < msgTextSize; loop++ ) {
      msgBufPtr->messageText[loop]  =  *msgPtr++;
   }
/*   msgBufPtr->messageText[msgTextSize+1] = 0 ; */

   SendMessage(cliHandle, CLI_SERVER_RESULTS,
               msgBufHandle, CLI_SERVER_RESULTS);
   return GOOD;
}
/**************************************************************************
**
** InitCServer
**
** Description: Initialize the commands for the Memory Server.
**
** Parameters:
**    input:
**       cliHandle:  CLI Server Handle
**       dllHandle:  DLL Handle.
**
**    output:
**       return a 1 to indicate success
**
***************************************************************************/
RETCODE EXPORT
InitCServer(HANDLE cliHandle, HANDLE dllHandle) {

   CSERVER_NEW_REGISTRATION FAR *msgBufPtr;
   RETCODE err;

   cliServerHandle = cliHandle;
   msgBufPtr =
      (CSERVER_NEW_REGISTRATION FAR *)TMalloc(sizeof(CSERVER_VARIABLE_VALUE));
   if (msgBufPtr == NULL) {
      return(ER_OUT_OF_MEMORY);
   }
   msgBufPtr->stringResourceHandle = dllHandle;

   msgBufPtr->serverNameIndex = 30;
   msgBufPtr->dllNameIndex = 31;
   msgBufPtr->numberOfCommandsIndex = 32;
   msgBufPtr->commandStartIndex = 33;
   SendMessage(cliHandle, CLI_NEW_SVR_REGISTRATION, CLI_NEW_SVR_REGISTRATION,
      (DWORD)msgBufPtr);
   TFree((LPSTR)msgBufPtr);
   if (GOOD != (err = ProcReturnProcFamily(&procFamily))) return err;
   return(GOOD);
}

/***************************************************************************
**
** MemCliDumpMemory
**
** Description:
**    Cli interface to the read (dump) memory content
**
** Syntax:
**    mem_dump [loop] addr1 [addr2] [BYTE|WORD|LONG|DWORD] [<space>]
**
** Input:
**    cmdString
**    argc
**    argv
**
** Output: no parameters
**
*****************************************************************************/
RETCODE EXPORT MemCliDumpMemoryExtended(LPSTR cmdString, U32 argc, U32 argv[]){
   extendedSpaceEnabled=TRUE;
   return(MemCliDumpAction(cmdString, argc, argv));
}

RETCODE EXPORT MemCliDumpMemory(LPSTR cmdString, U32 argc, U32 argv[]) {
   extendedSpaceEnabled=FALSE;
   return(MemCliDumpAction(cmdString, argc, argv));
}

RETCODE PRIVATE MemCliDumpAction(LPSTR cmdString, U32 argc, U32 argv[]) {
   RETCODE    err;
   RETCODE    firstErr = GOOD;
   U32        bytesLeft;
   DESCRIPTOR addr1Desc, addr2Desc;
   U32        bytesToEnd;
   BOOLEAN    firstAddrFound=FALSE;
   LOOP_VAR   args;
   BOOLEAN    abortFromEsc;



   if ((argc < 2) || (argc > 5))
      return(ER_CLI_SYNTAX);

   /* !!! this should be replaced with a call to the map server to get
      the type of memory at the address requested.  How should it handle
      large dumps where the map size may change within the request??? */
   addrSpace = SPACE_DEFAULT;
   if (procFamily == FAMILY_68K)
      dataSize = WORD_SIZE;
   else
      dataSize = BYTE_SIZE;
   loop = FALSE;
   extendedSpace = SPACE_DEFAULT;
   KeywordInit();
   
   /* remove processor dependency */
   if((err = AdrCreateAddress(&addr1Desc))!=GOOD) return(err);
   if (GOOD != (err = AdrCreateAddress(&addr2Desc))) {
      AdrDestroyAddress(addr1Desc);
      return err;
   }

   /* Search for keywords first to get correct data size and space */
   for (args=1; args<argc; args++) 
      KeywordCheck(&(cmdString[(U16)argv[args]]));

   KeywordInit();

   for( args = 1; args < argc; args++ ) {
      if( !KeywordCheck(&(cmdString[(U16)argv[args]])) ) {
         U32 offset;
         DESCRIPTOR *adrDesc;
         if( firstAddrFound == FALSE ) adrDesc = &addr1Desc;
         else adrDesc = &addr2Desc;
         firstAddrFound++;
         if (TestIsSastBitName(&cmdString[(U16)argv[args]], extendedSpace,
               &offset)) {
            if ((err = AdrSetAddrOffset(*adrDesc,offset)) != GOOD)
               goto CLEANUP_1;
         } else if((err=AdrConvTextToAddress(*adrDesc,
            &cmdString[(U16)argv[args]])) != GOOD) goto CLEANUP_1;
      }
   }
   /* set up default size of dump */
   bytesLeft = LINE_LENGTH;
   if(( firstAddrFound == 0) || (firstAddrFound >= 3)) {  /* gene */
      err = ER_CLI_SYNTAX;
      goto CLEANUP_1;
   }
   if((err=AdrSetAddrSpace(addr1Desc, addrSpace))!=GOOD) goto CLEANUP_1;
   if( firstAddrFound == 2 ) {
      ADDR_COMPARE addrCompareResult;
      if((err=AdrSetAddrSpace(addr2Desc, addrSpace))!=GOOD) goto CLEANUP_1;
      /* extract difference between two addresses */
      if(GOOD!=(err=AdrRangeOfAddresses(addr1Desc,addr2Desc,&bytesLeft)))
         goto CLEANUP_1;
      /* now put the smallest address in addr1Desc */
      if((err=AdrCompareAddresses(addr1Desc,addr2Desc,&addrCompareResult))
         != GOOD ) goto CLEANUP_1;

      if (FIRST_ADDR_GREATER == addrCompareResult) {
         /* switch the two values while preserving them */
         return ER_ADR_END_ADDR_TOO_SMALL; /* gene 1/27/97 */
//         DESCRIPTOR addrTempDesc;

//         addrTempDesc = addr2Desc;
//         addr2Desc = addr1Desc;
//         addr1Desc = addrTempDesc;
      }
   }
   /* adjust number of bytes to make even with the requested type (size) */
   switch (dataSize) {
      case WORD_SIZE:
         if (bytesLeft & 0x1L)  /* if odd, increment */
            bytesLeft++;
         break;
   
      case DWORD_SIZE:
         if (bytesLeft & 0x3L)  {
            /* round up to even 4 */
            bytesLeft = (bytesLeft & 0xFFFFFFFCL) + 4L;
         }
   }
   if (0L == bytesLeft)  /* only occurs if entering large address range */
      bytesLeft = 0xFFFFFFFFL;
   /* correct for size of remaining memory when close to the end of memory */
   if (GOOD != (err = AdrRemainingBytes(addr1Desc, &bytesToEnd)))
      goto CLEANUP_1;
   if (0L == bytesToEnd) { /* 0 means largest value; convert */
      bytesToEnd = 0xFFFFFFFFL;
   }
   bytesLeft = min(bytesLeft, bytesToEnd);

  /* clear any ESC previously hit */
   err = TskCheckAbort(&abortFromEsc);
   if(err!=GOOD) goto CLEANUP_1;



   while (TRUE) {
      LPU8 buff;
      S8   outputBuff[(LINE_LENGTH * 3) + 15];  /* few extra for safety */
      U16  blockSize;
      U16  i;
      LPSTR strPtr, tmpPtr;
      U8   ch;
      DATA_UNION dataUnion;

      blockSize = min(bytesLeft, LINE_LENGTH);

      if (loop || extendedSpaceEnabled) {
         /* TestRead TMallocs buff */
         if((err = TestRead(addr1Desc, extendedSpace, (U32)blockSize, &buff,
               loop)) != GOOD) {
            TFree((LPSTR)buff);
            goto CLEANUP_1;
         }
      } else {
         /* MemRead TMallocs buff */
         if((err = MemRead(addr1Desc, blockSize, &buff,CACHE_BYPASS))!=GOOD) {
            TFree((LPSTR)buff);
            goto CLEANUP_1;
         }
      }

      /* !!! what about displaying address space in address now??*/
      if((err = AdrConvAddressToTextWithParams(addr1Desc,
                                               FALSE,
                                               TRUE,
                                               outputBuff))!=GOOD) {
         TFree((LPSTR)buff);
         goto CLEANUP_1;
      }
      /* find end */
      strPtr = outputBuff;
      while (*strPtr)
         strPtr++;
      /* now points to null termination */
      /* insert 2 spaces */
      *strPtr++ = ' ';
      *strPtr++ = ' ';

      dataUnion.U32Val = 0L;
      for(i=0; i<blockSize; ) {
         S8 text[10];
         U8 diff;
         diff = blockSize - i;
         
         if (diff < 4) {  /* only one compare for common case */
            if (diff < 2) {
               dataSize = BYTE_SIZE;
            } else {
               if (DWORD_SIZE == dataSize)   /* only switch if was in long */
                  dataSize = WORD_SIZE;
            }
         }
         /* convert byte(s) to ascii */
         switch (dataSize) {
            case BYTE_SIZE:
               sprintf(text, "%02hX ", buff[i++]);
               break;
            case WORD_SIZE:
               dataUnion.U8Val[0] = buff[i++];
               dataUnion.U8Val[1] = buff[i++];
                  /* Processor spaces are subject to endianness; others
                  ** are referred to test config file */
               dataUnion.U16Val[0] = IsProcessorSpace(extendedSpace)
                    ? MemSwapBytesInWord(dataUnion.U16Val[0])
                    : TestSwapBytesInWord(dataUnion.U16Val[0],extendedSpace);
               sprintf(text, "%04X ", dataUnion.U16Val[0]); 
               break;
            case DWORD_SIZE:
               dataUnion.U8Val[0] = buff[i++];
               dataUnion.U8Val[1] = buff[i++];
               dataUnion.U8Val[2] = buff[i++];
               dataUnion.U8Val[3] = buff[i++];
                  /* Processor spaces are subject to endianness; others
                  ** are referred to test config file */
               dataUnion.U32Val = IsProcessorSpace(extendedSpace)
                     ? MemSwapBytesInLong(dataUnion.U32Val)
                     : TestSwapBytesInLong(dataUnion.U32Val,extendedSpace);
               sprintf(text, "%08lX ", dataUnion.U32Val); 
               break;
         }
         /* copy to output buffer */
         tmpPtr = text;
         while ((ch = *tmpPtr++) > '\0') {
            *strPtr++ = ch;
         }
      } /* end of for */
      /* terminate with null */
      *strPtr = '\0';

      if (!loop) SendCliMessage(cliServerHandle, (LPSTR)outputBuff);
      if((TFree((LPSTR)buff))!=GOOD)
         goto CLEANUP_1;

      if (bytesLeft > blockSize) {
         bytesLeft -= blockSize;
      } else {
         break;  /* exit while loop when no more data to output */
      }
      if((err = AdrAddToAddress(addr1Desc, (U32)blockSize))!=GOOD)
         goto CLEANUP_1;

      err = TskCheckAbort(&abortFromEsc);
      if(err!=GOOD) goto CLEANUP_1;
      if (abortFromEsc!=0) {
         err = ER_ABORT_FROM_ESC;
         goto CLEANUP_1;
      }
   }  /* end of while (TRUE) */

CLEANUP_1:
   firstErr = err;
   err = AdrDestroyAddress(addr2Desc);

CLEANUP_2:
   if (!firstErr) firstErr = err;
   err = AdrDestroyAddress(addr1Desc);
   if (!firstErr) firstErr = err;
   return firstErr;
}  /* end of MemCliDumpMemory */


/***************************************************************************
**
**  MemCliWriteMemory
**
**  Status:  PRELIMINARY
**
**  description:
**     Cli interface to the write memory content
**
**  syntax:
**     write [loop] <address1> <data> [BYTE|WORD|LONG|DWORD] [<space>]
**
**  input:
**     <none>
**
**  output:
**     message:
**     <none> :
**
*****************************************************************************/
RETCODE EXPORT MemCliWriteMemoryExtended(LPSTR cmdString,U32 argc,U32 argv[]) {
   extendedSpaceEnabled=TRUE;
   return(MemCliWriteAction(cmdString, argc, argv));
}

RETCODE EXPORT MemCliWriteMemory(LPSTR cmdString, U32 argc, U32 argv[]) {
   extendedSpaceEnabled=FALSE;
   return(MemCliWriteAction(cmdString, argc, argv));
}

RETCODE PRIVATE MemCliWriteAction(LPSTR cmdString, U32 argc, U32 argv[]) {
   U16         patLength = 0;
   RETCODE     err,writeErr;
   U32         tempData;
   DESCRIPTOR  desc;
   U8          *pattern;
   char        *endptr;
   LOOP_VAR    args;
   BOOLEAN     addrFound=FALSE;
   
   if(argc < 2) return(ER_CLI_SYNTAX);
   if(argc > MAX_CLI_FILL_LENGTH+2) return(ER_MEM_PAT_LEN);

   dataSize = BYTE_SIZE;
   addrSpace = SPACE_DEFAULT;
   loop = FALSE;
   extendedSpace = SPACE_DEFAULT;
   KeywordInit();

   /* malloc a block of memory for memwrite to free */
   pattern =(U8 *) TMalloc(MAX_CLI_FILL_LENGTH);
   if (pattern == NULL) return(ER_OUT_OF_MEMORY);

   /* Search for keywords first to get correct data size and space */
   for (args=1; args<argc; args++) 
      KeywordCheck(&(cmdString[(U16)argv[args]]));

   KeywordInit();

   for (args=1; args<argc; args++) {
      if (!KeywordCheck(&(cmdString[(U16)argv[args]])) ) {
         if (!addrFound) {
            U32 offset;
            addrFound=TRUE;
            if((err = AdrCreateAddress(&desc))!=GOOD) {
                TFree( (LPSTR) pattern);
                return(err);
            }
            if (TestIsSastBitName(&cmdString[(U16)argv[args]], extendedSpace,
                  &offset)) {
               if ((err = AdrSetAddrOffset(desc,offset)) != GOOD) {
                  AdrDestroyAddress(desc);
                  TFree( (LPSTR) pattern);
                  return(err);
               }
            } else if((err = AdrConvTextToAddress(desc,
                  &cmdString[(U16)argv[args]])) != GOOD) {
               AdrDestroyAddress(desc);
               TFree( (LPSTR) pattern);
               return(err);
            }
         } else {
            tempData = strtoul(&cmdString[(U16)argv[args]], &endptr, 0);
            if(*endptr!='\0') {
               AdrDestroyAddress(desc);
               TFree( (LPSTR) pattern);
               return(ER_CLI_SYNTAX);
            }
            switch (dataSize) {
               case BYTE_SIZE:
                  if (tempData >= 0x100L) {
                     AdrDestroyAddress(desc);
                     TFree((LPSTR) pattern);
                     return(ER_MEM_DATA_GREATER_THAN_BYTE);
                  }
                  pattern[patLength++] = (U8)tempData;
                  break;
               case WORD_SIZE: {
                  U16 word;
                  if (tempData >= 0x10000L) {
                     AdrDestroyAddress(desc);
                     TFree((LPSTR) pattern);
                     return(ER_MEM_DATA_GREATER_THAN_WORD);
                  }
                  word = (U16) tempData;
                     /* Processor spaces are subject to endianness; others
                     ** are referred to test config file */
                  word = IsProcessorSpace(extendedSpace)
                      ? MemSwapBytesInWord(word)
                      : TestSwapBytesInWord(word,extendedSpace);
                  pattern[patLength++] = ((U8*)&word)[0];
                  pattern[patLength++] = ((U8*)&word)[1];
                  break;
               }
               case DWORD_SIZE:
                     /* Processor spaces are subject to endianness; others
                     ** are referred to test config file */
                  if (!CheckValidDWORD(tempData,&cmdString[(U16)argv[args]])) { /* gene */
                     AdrDestroyAddress(desc);
                     TFree((LPSTR) pattern);
                     return(ER_MEM_DATA_GREATER_THAN_WORD);
                  }
                  tempData = IsProcessorSpace(extendedSpace)
                       ? MemSwapBytesInLong(tempData)
                       : TestSwapBytesInLong(tempData, extendedSpace);
                  pattern[patLength++] = ((U8*)&tempData)[0];
                  pattern[patLength++] = ((U8*)&tempData)[1];
                  pattern[patLength++] = ((U8*)&tempData)[2];
                  pattern[patLength++] = ((U8*)&tempData)[3];
                  break;
            }
         }
      }
   }
   if (!addrFound) {
      TFree((LPSTR) pattern);
      return(ER_CLI_SYNTAX);
   }

   if((err=AdrSetAddrSpace(desc, addrSpace))!=GOOD) {
      AdrDestroyAddress(desc);
      TFree((LPSTR) pattern);
      return(err);
   }
   
   if (loop || extendedSpaceEnabled) {
      /* TestWrite consumes the pattern buffer */
      writeErr = TestWrite(desc, extendedSpace, patLength, (U8*)pattern, loop);
   } else {
      /* MemWrite consumes the pattern buffer */
      /* writeErr = MemWrite(desc, patLength, (LPU8)pattern); */
      writeErr=MemFill(desc, patLength, (LPU8)pattern, patLength);//<Judy 9/10/97>
   }
   
   /* destroy the address descriptor regardless
      of the success/failure of the memwrite call */
   if((err = AdrDestroyAddress(desc))!=GOOD) return(err);
   
   if (!writeErr && !loop)
      SendCliMessage(cliServerHandle, (LPSTR)"Write successful.");

   return(writeErr);
}

/***************************************************************************
**
**  MemCliFillMem
**
**  Status:  PRELIMINARY
**
**  description:
**     Cli interface to the fill memory content
**
**     Syntax:
**        fill <address> <address> <data>... [BYTE|WORD|LONG|DWORD] [<space>]
**
**  input:
**     standard command input parameters
**
**  output:
**     <none> :
**
*****************************************************************************/
RETCODE EXPORT MemCliFillMemory(LPSTR cmdString, U32 argc, U32 argv[]) {
   U16        patLength = 0;
   RETCODE    firstErr, err;
   U32        tempData;
   DESCRIPTOR desc1, desc2;
   ADDR_COMPARE result;
   U16        i;
   U32        fillLength;
   U8         pattern[MAX_CLI_FILL_LENGTH];
   char       *endptr;

   dataSize = BYTE_SIZE;
   addrSpace = SPACE_DEFAULT;
   KeywordInit();

   if(argc < 4) return(ER_CLI_SYNTAX);
   if(argc > MAX_CLI_FILL_LENGTH+3)
      return(ER_MEM_PAT_LEN);

   /* get starting address into addr desc. */
   if((err=AdrCreateAddressFromText(&cmdString[(U16)argv[1]],
         NULL,&desc1)) != GOOD)
      return err;   

   /* decode ending address - want to use address conv routines
      to get address's value since we want to support symbolics here too */
   if((err=AdrCreateAddressFromText(&cmdString[(U16)argv[2]],
         NULL,&desc2)) != GOOD) {
      AdrDestroyAddress(desc1);
      return err;
   }
   
   if((err=AdrCompareAddresses(desc1, desc2, &result))!= GOOD) goto CLEANUP;
   
   if( result == FIRST_ADDR_GREATER) {
      err = ER_MEM_END_LESS_THAN_START;
      goto CLEANUP;
   }
   
   if((err=AdrRangeOfAddresses(desc1, desc2, &fillLength))!=GOOD)
      goto CLEANUP;

   /* last tokens in cmd line are for data size specifier and addr space */
   while( KeywordCheck(&cmdString[(U16)argv[(U16)argc-1]]) ) argc--;
   if((err=AdrSetAddrSpace(desc1, addrSpace))!=GOOD) goto CLEANUP;

   for (i = 3; i < argc; i++) { /* get data into pattern array */
      tempData = strtoul(&cmdString[(U16)argv[i]], &endptr, 0);
      if(*endptr!='\0') {
         err = ER_CLI_SYNTAX;
         goto CLEANUP;
      }
      switch (dataSize) {
         case BYTE_SIZE:
            if (tempData >= 0x100L) {
               err = ER_MEM_DATA_GREATER_THAN_BYTE;
               goto CLEANUP;
            }
            pattern[patLength++] = (U8)tempData;
            break;
         case WORD_SIZE: {
            U16 word;
            if (tempData >= 0x10000L) {
               err = ER_MEM_DATA_GREATER_THAN_WORD;
               goto CLEANUP;
            }
            word = (U16) tempData;
            /* Processor spaces are subject to endianness */       
            word =  MemSwapBytesInWord(word);
            pattern[patLength++] = ((U8*)&word)[0];
            pattern[patLength++] = ((U8*)&word)[1];
            break;
         }
         case DWORD_SIZE:
            /* Processor spaces are subject to endianness */
            if (!CheckValidDWORD(tempData,&cmdString[(U16)argv[i]]) ) {  /* gene */
               err = ER_MEM_DATA_GREATER_THAN_WORD;
               goto CLEANUP;
            }
            tempData =  MemSwapBytesInLong(tempData);
            pattern[patLength++] = ((U8*)&tempData)[0];
            pattern[patLength++] = ((U8*)&tempData)[1];
            pattern[patLength++] = ((U8*)&tempData)[2];
            pattern[patLength++] = ((U8*)&tempData)[3];
            break;
      }
   }

   if ((err = MemFill(desc1, fillLength, (LPU8)pattern, patLength)) != GOOD) {
      goto CLEANUP;
   }
   SendCliMessage(cliServerHandle, (LPSTR)"Fill successful.");
   err = GOOD;

CLEANUP:
   firstErr = err;
   err = AdrDestroyAddress(desc1);
   err = AdrDestroyAddress(desc2);
   if (GOOD == firstErr)
      firstErr = err;
   return firstErr;
}

/***************************************************************************
**
**  MemCliSearchMem
**
**  Status:  PRELIMINARY
**
**  description:
**     Cli interface to the fill memory content
**
**  syntax:
**     search <start_address> <end_address> [not] <data> [BYTE|WORD|LONG|DWORD]
**            [<space>]
**  input:
**     <none>
**
**  output:
**     message:
**     <none> :
**
*****************************************************************************/
RETCODE EXPORT MemCliSearchMemory(LPSTR cmdString, U32 argc, U32 argv[]) {
   U16        patLength = 0;
   RETCODE    err, tmpErr = GOOD;
   U32        tempData;
   DESCRIPTOR desc1, desc2;
   U16        i;
   U8         pattern[MAX_CLI_FILL_LENGTH];
   char       *endptr;
   BOOLEAN    not = FALSE, found;

   dataSize = BYTE_SIZE;
   addrSpace = SPACE_DEFAULT;
   KeywordInit();

   if(argc < 3) return(ER_CLI_SYNTAX);
   if(argc > MAX_CLI_FILL_LENGTH+3) return(ER_MEM_PAT_LEN);

   if((err=AdrCreateAddressFromText(&cmdString[(U16)argv[1]],NULL,
         &desc1)) != GOOD)
      return err;
   if((err=AdrCreateAddressFromText(&cmdString[(U16)argv[2]],NULL,
         &desc2)) != GOOD) {
      AdrDestroyAddress(desc1);
      return err;
   }
   
   /* last tokens in cmd line are for data size specifier and addr space */
   while( KeywordCheck(&cmdString[(U16)argv[(U16)argc-1]]) ) argc--;
   if((err=AdrSetAddrSpace(desc1, addrSpace))!=GOOD) goto CLEANUP;
   if((err=AdrSetAddrSpace(desc2, addrSpace))!=GOOD) goto CLEANUP;

   for (i = 3; i < argc; i++) { /* get data into pattern array */
      if(strncmpi(&cmdString[(U16)argv[i]], "not",
            strlen(&cmdString[(U16)argv[i]]))==0) {
         not = TRUE;
         err=ER_CLI_SYNTAX;  //!!186
         goto CLEANUP;       //!!186
      } else {
         tempData = strtoul(&cmdString[(U16)argv[i]], &endptr, 0);
         if(*endptr!='\0') {
            err=ER_CLI_SYNTAX;
            goto CLEANUP;
         }
         switch (dataSize) {
            case BYTE_SIZE:
               if (tempData >= 0x100L) {
                  err = ER_MEM_DATA_GREATER_THAN_BYTE;
                  goto CLEANUP;
               }
               pattern[patLength++] = (U8)tempData;
               break;
            case WORD_SIZE: {
               U16 word;
               if (tempData >= 0x10000L) {
                  err = ER_MEM_DATA_GREATER_THAN_WORD;
                  goto CLEANUP;
               }
               word = (U16) tempData;
               /* Processor spaces are subject to endianness */       
               word =  MemSwapBytesInWord(word);
               pattern[patLength++] = ((U8*)&word)[0];
               pattern[patLength++] = ((U8*)&word)[1];
               break;
            }
            case DWORD_SIZE:
               /* Processor spaces are subject to endianness */
               if (!CheckValidDWORD(tempData,&cmdString[(U16)argv[i]]) ) {  /* gene */
                  err = ER_MEM_DATA_GREATER_THAN_WORD;
                  goto CLEANUP;
               }
               tempData =  MemSwapBytesInLong(tempData);
               pattern[patLength++] = ((U8*)&tempData)[0];
               pattern[patLength++] = ((U8*)&tempData)[1];
               pattern[patLength++] = ((U8*)&tempData)[2];
               pattern[patLength++] = ((U8*)&tempData)[3];
               break;
         }
      }
   }
   if((err = MemSearch(desc1, desc2, not, (LPU8)pattern, patLength,
         (BOOLEAN FAR *)&found)) == GOOD) {
      if(found) {
         S8 addrText[ADDR_BUFF_SZ];
         S8 text[ADDR_BUFF_SZ+20];
         if((err = AdrConvAddressToTextWithParams(desc1,
                                                  FALSE,
                                                  TRUE, 
                                                  (LPSTR)addrText))==GOOD) {
            sprintf(text, "Pattern found at %s.", addrText);
            SendCliMessage(cliServerHandle, (LPSTR)text);
         }
      } else {
         SendCliMessage(cliServerHandle, (LPSTR)"Pattern not found.");
      }
   }
CLEANUP:
   tmpErr = err;
   err = AdrDestroyAddress(desc1);
   if (!tmpErr) tmpErr = err;
   err = AdrDestroyAddress(desc2);
   if (!tmpErr) tmpErr = err;
   return(tmpErr);
}

/***************************************************************************
**
** MemCliSetMemSize
**
** Description:
**    Cli interface to the set the global parameter for the size of data
**    when sent to the probe
**
** Syntax:
**    size [BYTE|WORD|LONG|DWORD]
**
** Input:
**    cmdString:
**    argc:
**    argv:
**
** Output: None
**
*****************************************************************************/
RETCODE EXPORT MemCliSetMemSize(LPSTR cmdString, U32 argc, U32 argv[]) {
   RETCODE      err;
   S8           text[32];

   KeywordInit();
   if (argc==1) {
      if((err = MemGetAccessSize(&dataSize))!=GOOD) return(err);
      sprintf(text, "%s",
         (dataSize==BYTE_SIZE)  ? BYTE_TEXT:
         (dataSize==WORD_SIZE)  ? WORD_TEXT:
         (dataSize==DWORD_SIZE) ? DWORD_TEXT:
                                    UNKNOWN_TEXT);
      SendCliMessage(cliServerHandle, (LPSTR)text);
      return(GOOD);
   }

   if ((argc > 2) || (argc < 2))
      return ER_CLI_SYNTAX;
   if( !KeywordCheck(&(cmdString[(U16)argv[1]])) )
      return ER_CLI_SYNTAX;
   if (dataSize == DWORD_SIZE)  //!!186
      return ER_CLI_SYNTAX;     //!!186
   return(MemSetAccessSize(dataSize));
}  /* end of MemCliSetMemSize */

   
/***************************************************************************
**
** MemCliSetVerify
**
** Description:
**    Cli interface to the set the global parameter for verifying memory
**    writes.
**
** Syntax:
**    verify [on|off]
**
** Input:
**    cmdString:
**    argc:
**    argv:
**
** Output: None
**
*****************************************************************************/
RETCODE EXPORT MemCliSetVerify(LPSTR cmdString, U32 argc, U32 argv[]) {
   LPSTR   lpParam;
   RETCODE err;
   BOOLEAN verify;
   S8      text[32];

   if (argc==1) {
      if((err = MemGetVerifyWrites(&verify))!=GOOD) return(err);
      sprintf(text, "%s", verify ? ON_TEXT:OFF_TEXT);
      SendCliMessage(cliServerHandle, (LPSTR)text);
      return(GOOD);
   }
   if ((argc > 2) || (argc < 2))
      return ER_CLI_SYNTAX;
   lpParam = &(cmdString[(U16)argv[1]]);
   if        (strncmpi(lpParam, ON_TEXT, strlen(lpParam))==0) {
      verify = TRUE;
   } else if (strncmpi(lpParam, OFF_TEXT, strlen(lpParam))==0) {
      verify = FALSE;
   } else return ER_CLI_SYNTAX;
   return(MemSetVerifyWrites(verify));
}  /* end of MemCliSetVerify */

/***************************************************************************
**
** MemCliRamtst
**
** Description:
**    Cli interface to the ramtst command
**
** Syntax:
**    ramtst [loop] <address1> <address2> [<space>]
**
*****************************************************************************/
RETCODE EXPORT MemCliRamtstExtended(LPSTR cmdString, U32 argc, U32 argv[]){
   extendedSpaceEnabled=TRUE;
   return(MemCliRamtstAction(cmdString, argc, argv));
}

RETCODE EXPORT MemCliRamtst(LPSTR cmdString, U32 argc, U32 argv[]) {
   extendedSpaceEnabled=FALSE;
   return(MemCliRamtstAction(cmdString, argc, argv));
}

RETCODE PRIVATE MemCliRamtstAction(LPSTR cmdString, U32 argc, U32 argv[]) {
   RETCODE    err;
   RETCODE    firstErr = GOOD;
   U32        bytesLeft;
   DESCRIPTOR addr1Desc, addr2Desc;
   U32        bytesToEnd;
   BOOLEAN    firstAddrFound=FALSE;
   LOOP_VAR   args;
   char outputBuff[80];
   char retStr[48];
   BOOLEAN result;

   if ((argc < 2) || (argc > 5))
      return(ER_CLI_SYNTAX);

   addrSpace = SPACE_DEFAULT;
   loop = FALSE;
   extendedSpace = SPACE_DEFAULT;
   KeywordInit();
   sizeKeyword=TRUE;       /* Size keywords not allowed on this command */
   
   if((err = AdrCreateAddress(&addr1Desc))!=GOOD) return(err);
   if (GOOD != (err = AdrCreateAddress(&addr2Desc))) {
      AdrDestroyAddress(addr1Desc);
      return err;
   }

   for(args = 1; args < argc; args++) {
      DESCRIPTOR *adrDesc;
      if( firstAddrFound == FALSE ) adrDesc = &addr1Desc;
      else adrDesc = &addr2Desc;
      firstAddrFound++;
      if((err=AdrConvTextToAddress(*adrDesc,&cmdString[(U16)argv[args]]))
         != GOOD) goto CLEANUP_1;
   }
   if(( firstAddrFound == 0) || (firstAddrFound >= 3)) {  /* gene */
      err = ER_CLI_SYNTAX;
      goto CLEANUP_1;
   }
   if((err=AdrSetAddrSpace(addr1Desc, addrSpace))!=GOOD) goto CLEANUP_1;
   if( firstAddrFound == 2 ) {
      ADDR_COMPARE addrCompareResult;
      if((err=AdrSetAddrSpace(addr2Desc, addrSpace))!=GOOD) goto CLEANUP_1;
      /* extract difference between two addresses */
      if(GOOD!=(err=AdrRangeOfAddresses(addr1Desc,addr2Desc,&bytesLeft)))
         goto CLEANUP_1;
      /* now put the smallest address in addr1Desc */
      if((err=AdrCompareAddresses(addr1Desc,addr2Desc,&addrCompareResult))
         != GOOD ) goto CLEANUP_1;
      if (FIRST_ADDR_GREATER == addrCompareResult) {
	 /* switch the two values while preserving them */
	 return ER_ADR_END_ADDR_TOO_SMALL; //**Hera 12/30/96**/

         /*DESCRIPTOR addrTempDesc;
         addrTempDesc = addr2Desc;
         addr2Desc = addr1Desc;
         addr1Desc = addrTempDesc;*/
      }
   }
   if (0L == bytesLeft)  /* only occurs if entering large address range */
      bytesLeft = 0xFFFFFFFFL;
   /* correct for size of remaining memory when close to the end of memory */
   if (GOOD != (err = AdrRemainingBytes(addr1Desc, &bytesToEnd)))
      goto CLEANUP_1;
   if (0L == bytesToEnd) { /* 0 means largest value; convert */
      bytesToEnd = 0xFFFFFFFFL;
   }
   bytesLeft = min(bytesLeft, bytesToEnd);

   err = MemTest(addr1Desc, bytesLeft, &result, retStr);
   if (result == TRUE) {
      strcpy(outputBuff, "RAM Test OK.");
   } else {
      sprintf(outputBuff,"RAM Test failure at: %s.", retStr);
      err=GOOD;
   }    
   if (!loop) SendCliMessage(cliServerHandle, outputBuff);

CLEANUP_1:
   firstErr = err;
   err = AdrDestroyAddress(addr2Desc);
   if (!firstErr) firstErr = err;
   err = AdrDestroyAddress(addr1Desc);
   if (!firstErr) firstErr = err;
   return firstErr;
}  /* end of MemCliRamtst */

/***************************************************************************
**
** MemCliChecksum
**
** Description:
**    Cli interface to the checksum command
**
** Syntax:
**    checksum <address1> <address2> 
**
*****************************************************************************/
RETCODE EXPORT MemCliChecksum(LPSTR cmdString, U32 argc, U32 argv[]) {
   RETCODE    err;
   RETCODE    firstErr = GOOD;
   U32        bytesLeft;
   DESCRIPTOR addr1Desc, addr2Desc;
   U32        bytesToEnd;
   BOOLEAN    firstAddrFound=FALSE;
   LOOP_VAR   args;
   char outputBuff[80];
   ACCESS_SIZE size;
   U32 checksum;

   Sds2AbiGetAccessSize(&size);
   if ((argc < 3) || (argc > 4))
      return(ER_CLI_SYNTAX);

   KeywordInit();
   sizeKeyword=TRUE;       /* Size keywords not allowed on this command */
   
   if((err = AdrCreateAddress(&addr1Desc))!=GOOD) return(err);
   if (GOOD != (err = AdrCreateAddress(&addr2Desc))) {
      AdrDestroyAddress(addr1Desc);
      return err;
   }

   for(args = 1; args < argc; args++) {
      DESCRIPTOR *adrDesc;
      if( firstAddrFound == FALSE ) adrDesc = &addr1Desc;
      else adrDesc = &addr2Desc;
      firstAddrFound++;
      if((err=AdrConvTextToAddress(*adrDesc,&cmdString[(U16)argv[args]]))
         != GOOD) goto CLEANUP_1;
   }
   if(( firstAddrFound == 0) || (firstAddrFound >= 3)) {  /* gene */
      err = ER_CLI_SYNTAX;
      goto CLEANUP_1;
   }
   if( firstAddrFound == 2 ) {
      ADDR_COMPARE addrCompareResult;
      /* now put the smallest address in addr1Desc */
      if((err=AdrCompareAddresses(addr1Desc,addr2Desc,&addrCompareResult))
         != GOOD ) goto CLEANUP_1;
      if (FIRST_ADDR_GREATER == addrCompareResult) {
         AdrDestroyAddress(addr2Desc);
         AdrDestroyAddress(addr1Desc);
         return ER_ADR_END_ADDR_TOO_SMALL; 
      }
      /* extract difference between two addresses */
      if(GOOD!=(err=AdrRangeOfAddresses(addr1Desc,addr2Desc,&bytesLeft)))
         goto CLEANUP_1;
   }
   if (0L == bytesLeft)  /* only occurs if entering large address range */
      bytesLeft = 0xFFFFFL;
   /* correct for size of remaining memory when close to the end of memory */
   if (GOOD != (err = AdrRemainingBytes(addr1Desc, &bytesToEnd)))
      goto CLEANUP_1;
   if (0L == bytesToEnd) { /* 0 means largest value; convert */
      bytesToEnd = 0xFFFFFL;
   }
   bytesLeft = min(bytesLeft, bytesToEnd);

   MemChecksum(addr1Desc, bytesLeft, size, &checksum);
   if (size == BYTE_SIZE) {
      sprintf(outputBuff, "Checksum is 0x%02x", checksum);
   } else {
      sprintf(outputBuff, "Checksum is 0x%04x", checksum);
   }    
   SendCliMessage(cliServerHandle, outputBuff);
   err=GOOD;

CLEANUP_1:
   firstErr = err;
   err = AdrDestroyAddress(addr2Desc);
   if (!firstErr) firstErr = err;
   err = AdrDestroyAddress(addr1Desc);
   if (!firstErr) firstErr = err;
   return firstErr;
}  /* end of MemCliRamtst */

/***************************************************************************
**
**  MemCliSelfTest
**
**  Status:  PRELIMINARY
**
**  description:
**     Cli interface to the self-test of MICEpack
**
**     Syntax:
**        selftest
**
**  input:
**     <none>
**
**  output:
**     <none> :
**
*****************************************************************************/
#define NO_TRACE_MODULE -28
#define NO_EMM -45
#define MCE16A_FAIL -54
#define EMM_FAIL -55
#define TRACE_MODULE_FAIL -56

U16 testSeq[] = { 1,     2,    3,    4,    5,    7};
               /*MCE16A, EMM1, EMM2, EMM3, EMM4, TRACE_BOARD */
char *testFunction[] = {"MCE16C","emulation memory bank1",
   "emulation memory bank2","emulation memory bank3",
   "emulation memory bank4","trace module"};

#pragma warn -par
RETCODE EXPORT MemCliSelfTest(LPSTR cmdString, U32 argc, U32 argv[]) {

   RETCODE err;
   S16 result;
   U8 lp;
   char outputBuff[80];
   BOOLEAN abortFromEsc = FALSE;
   MAP_INFO mapData[33];
   U32 block, mapSize;


   if(argc > 1) return(ER_CLI_SYNTAX);

   /* added by <Judy 9/4/97> */
   for (lp=0; lp< 33; lp++)
       mapData[lp].attr=0xff;
   iceGetMap(mapData);
   Sds2AbiFwGetMapSize(&mapSize);
   mapSize <<=2;
   iceSetMap(0, 0, 0x61);
   iceSetMap(0, mapSize, 0x61);
   /* eof <Judy 9/4/97> */

   err = GOOD;
   for (lp = 0; lp < sizeof(testSeq)/sizeof(testSeq[0]); lp++) {
//      err = TskCheckAbort(&abortFromEsc);
//      if(err!=GOOD) break;
//      if (abortFromEsc!=0) {
//         err = ER_ABORT_FROM_ESC;
//         break;
//      }
      result = iceSelfTest(testSeq[lp]);
      switch (result) {
      case MCE16A_FAIL:
      case EMM_FAIL:
      case TRACE_MODULE_FAIL:
         sprintf(outputBuff,"  test %s -- fail", testFunction[lp]);
         break;
      case NO_EMM :
         sprintf(outputBuff,"  no emulation memory");
         lp = 5;
         break;
      case NO_TRACE_MODULE :
         sprintf(outputBuff,"  no trace module");
         break;
      default :
         sprintf(outputBuff,"  test %s -- good", testFunction[lp]);
         break;
      }
      SendCliMessage(cliServerHandle, outputBuff);
   }
   iceSelfTest(0);

   /* added by <Judy 9/4/97> */
   iceSetMap(0, 0, 0x61);
   for (lp=0;mapData[lp].attr != 0xff ;lp++) {
       iceSetMap(mapData[lp].addr1, mapData[lp].addr2, mapData[lp].attr);
   }
   /* eof <Judy 9/4/97> */
   return (err);
}

/**************************************************************************
**
** Name : Diagnostic
**
** Function
**
**    Input  :
**
**    Output :
**
** Notes:
**
**************************************************************************/
#define HighWord(x)      ((U16)((U32)(x) >> 16))
#define LowWord(x)       ((U16)(x))

static char *diagInitDisplay[] = {
    "MCE 8255         ",
    "Download 4003    ",
    "Data Memory      "
};

RETCODE EXPORT MemCliDiagnost(U8 flag) {
RETCODE err;
RETCODE status,diagStatus;
U16 lp2;
U8  retId;
U32 memFailAddress;
char outputBuff[80];
PROBE_TYPE probeType;

   ProcReturnSpecificProcessor(&probeType);
   status = CheckFwStatus();
   if (status == NORMAL_STATUS) {
      iceDiagnostic();
      CheckFwStatus();
   }
   sprintf(outputBuff,"Download diagnostic file....");
   SendCliMessage(cliServerHandle, outputBuff);
   DownLoadFirmware((U8 *)"diagnost.bin", 0x400, 0xff);

   diagStatus = DiagnosticFunction(INITIAL_TEST, &memFailAddress, &retId);

   // MCE_8255_FAIL        = 0x01,
   // DOWNLOAD_4003_FAIL   = 0x02,
   // DATA_MEMORY_FAIL     = 0x04,
   for (lp2 = 0; lp2 < 3 ; lp2++) {
      if (diagStatus & (1 << lp2)) {
         if ((1 << lp2) == DATA_MEMORY_FAIL) {
            sprintf(outputBuff,"%s fail address: %X:%X",diagInitDisplay[lp2],
               HighWord(memFailAddress),LowWord(memFailAddress));
            SendCliMessage(cliServerHandle, outputBuff);
         }
         else
            sprintf(outputBuff,"%s Fail",diagInitDisplay[lp2]);
            SendCliMessage(cliServerHandle, outputBuff);
      }
      else {
         sprintf(outputBuff,"%s OK",diagInitDisplay[lp2]);
         SendCliMessage(cliServerHandle, outputBuff);
      }
   }

   if (flag!=2) { /* all test or mce test only */
      DiagnosticMCE();
   }
   if (flag!=1) { /* all test or mtat2 test only */
      if (!(diagStatus & MTAT_EXIST)) {
         SendCliMessage(cliServerHandle, "No MTAT2 Board");
      }
      else {
   /*    DiagnosticMTAT(diagStatus);  *for MTAT test */
         DiagnosticMTAT2(diagStatus); /* for MTAT2 test */
   /*    DiagnosticMCEConnect();      not support temporally */
      }
   }
   status = DiagnosticFunction(END_DIAG, &memFailAddress, &retId);
   CheckFwStatus();
   sprintf(outputBuff,"Recovery system file....");
   SendCliMessage(cliServerHandle, outputBuff);
   DownLoadFirmware((U8 *)"main186.bin", 0x400, 0xff);
   ReassignProcessorType(probeType);
   Sds2AbiFwUnloadRegisters(TRUE);
   sprintf(outputBuff,"Diagnostic test finished.");
   SendCliMessage(cliServerHandle, outputBuff);
   return(GOOD);
}

VOID EXPORT ReassignProcessorType(PROBE_TYPE probeType){
U8 ID_Info[40];
U16 idType;
   switch (probeType) {
   case I80C188XL_MP:
      idType = 1;
      break;
   case I80C188EA_MP:
      idType = 2;
      break;
   case I80C188EB_MP:
      idType = 3;
      break;
   case I80C188EC_MP:
      idType = 4;
      break;
   case I80C186XL_MP:
      idType = 5;
      break;
   case I80C186EA_MP:
      idType = 6;
      break;
   case I80C186EB_MP:
      idType = 7;
      break;
   case I80C186EC_MP:
      idType = 8;
      break;
   default:
      idType = 5;
      break;
   }
   iceSetID(idType);
   iceGetID(ID_Info);
}

static char *diagDisplayMCE[] = {
    "MCE Open Short   ",
    "MCE Pull High    ",
    "MAP Control RAM  ",
    "MCE Memory       "
};

VOID DiagnosticMCE(VOID) {
DIAG_ID lp;
RETCODE status;
char outputBuff[80];
U32 memFailAddress;
U8  retId;

   for (lp = MCE_OPEN_SHORT_TEST; lp <= MCE_MEMORY_TEST; lp++) {
      status = DiagnosticFunction(lp, &memFailAddress, &retId);
      if (status == GOOD) {
         sprintf(outputBuff,"%s OK",diagDisplayMCE[lp-MCE_OPEN_SHORT_TEST]);
         SendCliMessage(cliServerHandle, outputBuff);
      } else {
         if (lp == MCE_MEMORY_TEST) {
            if (status == NO_EMM) {
               sprintf(outputBuff,"%s no EMM",diagDisplayMCE[lp-MCE_OPEN_SHORT_TEST]);
               SendCliMessage(cliServerHandle, outputBuff);
            } else {
               sprintf(outputBuff,"%s Fail, address: %5lX",
                  diagDisplayMCE[lp-MCE_OPEN_SHORT_TEST], memFailAddress);
               SendCliMessage(cliServerHandle, outputBuff);
            }
         }
         else {
            sprintf(outputBuff,"%s Fail, error code: %lX",
               diagDisplayMCE[lp-MCE_OPEN_SHORT_TEST], status);
            SendCliMessage(cliServerHandle, outputBuff);
         }
      }
   }
}
/*
static char *diagDisplayMTAT[] = {
    "Program Xilinx   ",
    "EREC1            ",
    "EREC2            ",
    "TMAN             ",
    "SAM OF VRAM      ",
    "74AS575 Bus      ",
    "EXTERNAL Bus     ",
    "SEQ RAM          "
};
*/
U16 execCondition[] = {
   0,
   TMAN_EXIST | EREC1_EXIST,  TMAN_EXIST | EREC1_EXIST | EREC2_EXIST,
   TMAN_EXIST,                TMAN_EXIST | EREC1_EXIST,
   TMAN_EXIST | EREC1_EXIST,  TMAN_EXIST | EREC1_EXIST | EREC2_EXIST,
   TMAN_EXIST
};
/*
VOID DiagnosticMTAT(U16 diagStatus) {
DIAG_ID lp;
U32 status;
U8  retId;
char outputBuff[80];
U32 memFailAddress;

   for (lp = PROGRAM_XLX; lp <= SEQ_RAM_TEST; lp++) {
      if ((diagStatus & execCondition[lp-PROGRAM_XLX]) == execCondition[lp-PROGRAM_XLX]) {
         status = DiagnosticFunction(lp, &memFailAddress, &retId);
         if (status == GOOD) {
            sprintf(outputBuff,"%s OK", diagDisplayMTAT[lp-PROGRAM_XLX]);
            SendCliMessage(cliServerHandle, outputBuff);
         } else {
            sprintf(outputBuff,"%s Fail, error code: %4X", 
               diagDisplayMTAT[lp-PROGRAM_XLX], (U16)status);
            SendCliMessage(cliServerHandle, outputBuff);
         }
      }
   }

   if (diagStatus & TMAN_EXIST) {
      for (lp = VRAM_DRAM0_TEST; lp <= VRAM_DRAMF_TEST; lp++) {
         if (lp == VRAM_DRAM8_TEST) lp = VRAM_DRAMF_TEST;
         status = DiagnosticFunction(lp, &memFailAddress, &retId);
         if (status == GOOD) {
            sprintf(outputBuff,"Trace DRAM%X       OK",lp-VRAM_DRAM0_TEST);
            SendCliMessage(cliServerHandle, outputBuff);
         } else {
            sprintf(outputBuff,"Trace DRAM%X       Fail, error code: %lX",
               lp-VRAM_DRAM0_TEST, status);
            SendCliMessage(cliServerHandle, outputBuff);
         }
      }
   }
}
*/
static char *diagDisplayMTAT2[] = {
     "Bus Compare:  RDATA BUS test...",
     "              SDATA BUS test...",
     "              TDATA BUS test...",
     "              UDATA BUS test...",
     "              VDATA BUS test...",
     "              WDATA BUS test...",
     "              RADDR BUS test...",
     "              SADDR BUS test...",
     "              TADDR BUS test...",
     "              UADDR BUS test...",
     "              VADDR BUS test...",
     "              WADDR BUS test...",
     "Trace Buffer: RSDATA BUS test..",
     "              TUDATA BUS test..",
     "              TPDATA BUS test..",
     "              VWDATA BUS test..",
     "              TSDATA BUS test..",
     "              EVDATA BUS test..",
     "              RSADDR BUS test..",
     "              TUADDR BUS test..",
     "              TPADDR BUS test..",
     "              VWADDR BUS test..",
     "              TSADDR BUS test..",
     "              EVADDR BUS test.."
};

VOID DiagnosticMTAT2(U16 diagStatus) {
DIAG_ID lp;
U32 status;
char outputBuff[80];
U32 memFailAddress;
U8  retId;

   status = DiagnosticFunction(TEST_SEQ_RAM, &memFailAddress, &retId);
   if (status == GOOD)
      sprintf(outputBuff,"SEQ RAM TEST      OK");
   else
      sprintf(outputBuff,"SEQ RAM TEST      Fail");
   SendCliMessage(cliServerHandle, outputBuff);

   for (lp = TEST_BC_RDATA_BUS; lp <= TEST_TB_EVADDR_BUS; lp++) {
       sprintf(outputBuff,"%s Please wait 40-60 seconds !",
               diagDisplayMTAT2[lp-TEST_BC_RDATA_BUS]);
       SendCliMessageNo(cliServerHandle, outputBuff);
       status = DiagnosticFunction(lp, &memFailAddress, &retId);
       if (status == GOOD) {
          sprintf(outputBuff,"%s OK", diagDisplayMTAT2[lp-TEST_BC_RDATA_BUS]);
          SendCliMessage(cliServerHandle, outputBuff);
       } else {
          sprintf(outputBuff,"%s Fail--%8X", diagDisplayMTAT2[lp-TEST_BC_RDATA_BUS],
             (U32)memFailAddress);
          SendCliMessage(cliServerHandle, outputBuff);
          if (lp < TEST_BC_WADDR_BUS)
             lp=TEST_BC_WADDR_BUS;
          else
             break;
       }
   }
}

VOID DiagnosticMCEConnect(VOID) {
RETCODE status;
char outputBuff[80];
U32 memFailAddress;
U8  retId;

   status = DiagnosticFunction(MCE_CONNECT_TEST, &memFailAddress, &retId);
   if (status == GOOD) {
      sprintf(outputBuff,"MCE connect       OK");
      SendCliMessage(cliServerHandle, outputBuff);
   } else if (status == 0x3000L) {
      SendCliMessage(cliServerHandle,"Trace Board Xilinx Programming Failure");
   } else {
      sprintf(outputBuff,"MCE connect       Fail");
      SendCliMessage(cliServerHandle, outputBuff);
   }
}

RETCODE EXPORT MemCliBufferID(LPSTR cmdString, U32 argc, U32 argv[]) {
RETCODE    err;
U16  buffID, i;
char *endptr;
U16 lastBuff, cnt0, cnt1, maxBuff;
S8   outputBuff[80];  /* few extra for safety */
S32 startFrame, endFrame;
BOOLEAN abortFromEsc = FALSE;

   if (argc > 1)
      return(ER_CLI_SYNTAX);

   err = iceGetTraceInfo(&lastBuff, &cnt0, &cnt1, &maxBuff);
   if (err != GOOD) {
      SendCliMessage(cliServerHandle, "Trace buffer is empty");
      return GOOD;
   }
   iceGetTraceBufferInfo(i, &startFrame, &endFrame);
   sprintf(outputBuff,"Buffer#%d Frame: Start = %-8ld End = %-8ld",
      i, startFrame, endFrame);
   SendCliMessage(cliServerHandle, outputBuff);
/*
   if (argc == 1) {
      sprintf(outputBuff,"Current active buffer is %d, Maximum buffer ID is %d",
         currentBuffID, lastBuff-1);
      SendCliMessage(cliServerHandle, outputBuff);
      for (i=0; i < lastBuff; i++) {
         err = TskCheckAbort(&abortFromEsc);
         if(err!=GOOD) return err;
         if (abortFromEsc!=0) {
            err = ER_ABORT_FROM_ESC;
            return err;
         }
         iceGetTraceBufferInfo(i, &startFrame, &endFrame);
         sprintf(outputBuff,"Buffer#%d Frame: Start = %-8ld End = %-8ld",
            i, startFrame, endFrame);
         SendCliMessage(cliServerHandle, outputBuff);
      }
   } else {
      buffID = strtoul(&cmdString[(U16)argv[1]], &endptr, 0);
      if(*endptr!='\0') return (ER_CLI_SYNTAX);
      if (buffID >= lastBuff) 
         SendCliMessage(cliServerHandle, "Buffer ID invalid");
      else {
         currentBuffID = buffID;
         iceGetTraceBufferInfo(buffID, &startFrame, &endFrame);
         sprintf(outputBuff,"Buffer#%d Frame: Start = %-8ld  End = %-8ld",
            buffID, startFrame, endFrame);
         SendCliMessage(cliServerHandle, outputBuff);
     }
   }
*/
   return (GOOD);
}

RETCODE EXPORT MemCliListTrace(LPSTR cmdString, U32 argc, U32 argv[]) {
char *statCode[8]={"S","R","W","I","O","A","H","D"};
RETCODE    err;
BOOLEAN abortFromEsc = FALSE;
BOOLEAN dataFlag = FALSE;
BOOLEAN listAllFlag = FALSE;
BOOLEAN startFlag = FALSE;
U16  i, flag, buffID, busData;
LOOP_VAR   args;
char       *endptr;
QUALIFY_LIST qualifyList;
MP_TRACE_INFO traceData[48];
U32 addr1, addr2;
S32 startFrame, endFrame, startFrame2;
U16  lastBuff, cnt0, cnt1, maxBuff;
S8   outputBuff[80];  /* few extra for safety */
U8   numFrame;
U32  data, totalFrames = 0;
DESCRIPTOR  desc;

   if (argc < 4)
      return(ER_CLI_SYNTAX);

   buffID = currentBuffID;
   i = 1;
   if (strncmpi(&cmdString[(U16)argv[i]], "start",
      strlen(&cmdString[(U16)argv[i]])) == 0) {
         startFlag = TRUE;
   } else if (strncmpi(&cmdString[(U16)argv[i]], "all",
      strlen(&cmdString[(U16)argv[i]])) == 0) {
      buffID = 0;
      listAllFlag = TRUE;
   } else {
      if (cmdString[(U16)argv[i]] == '-') {
         i++;
         startFrame2 = strtoul(&cmdString[(U16)argv[i]], &endptr, 0);
         if(*endptr!='\0') return (ER_CLI_SYNTAX);
         startFrame2 = 0 - startFrame2;
      } else {
         startFrame2 = strtoul(&cmdString[(U16)argv[i]], &endptr, 0);
         if(*endptr!='\0') return (ER_CLI_SYNTAX);
      }     
   } 

   i++;
   AdrCreateAddress(&desc);
   AdrSetAddrSegmentSelector(desc,ADDR_USE_CS,NULL);
   if ((err = AdrConvTextToAddress(desc,&cmdString[(U16)argv[i++]])) != GOOD) {
      AdrDestroyAddress(desc);
      return(err);
   }
   AdrGetAddrPhysicalOffset(desc, &addr1);
   if ((err = AdrConvTextToAddress(desc,&cmdString[(U16)argv[i++]])) != GOOD) {
      AdrDestroyAddress(desc);
      return(err);
   }
   AdrGetAddrPhysicalOffset(desc, &addr2);
   AdrDestroyAddress(desc);

   if (addr1 > addr2) {
      sprintf(outputBuff,"Physical start address is greater than end address");
      SendCliMessage(cliServerHandle, outputBuff);
      return GOOD;
   }

   data = strtoul(&cmdString[(U16)argv[i]], &endptr, 0);
   if(*endptr =='\0') {
      if (data > 0xffff) return(ER_VS_USHORT_OVERFLOW);
      dataFlag = TRUE;
      i++;
   }

   flag = 0;
   for ( args = i; args < argc; args++ ) {
      for (i=0; i < 8; i++ ) {
         if (stricmp(statCode[i], &cmdString[(U16)argv[args]]) == NULL) {
            flag = flag | _rotl( 0x01, i);
            break;
         }
      }
      if (i == 8) return(ER_CLI_SYNTAX);
   }
   if (args < argc) return(ER_CLI_SYNTAX);
 
   if (flag == 0) flag = 0x7f;
   qualifyList.qFlag = 1;
   qualifyList.startAddr = addr1;
   qualifyList.endAddr = addr2;
   qualifyList.addrMask = 0xfffffL;
   qualifyList.dataMask = 0;
   qualifyList.status = flag;
   qualifyList.traceBitData = qualifyList.traceBitWild = 0;
   
   err = iceGetTraceInfo(&lastBuff, &cnt0, &cnt1, &maxBuff);
   if (err != GOOD) {
      SendCliMessage(cliServerHandle, "All trace buffers are empty");
      return GOOD;
   }
   lastBuff--;
   err = iceGetTraceBufferInfo(buffID, &startFrame, &endFrame);
   if (err != GOOD) {
      if (!buffID) 
         SendCliMessage(cliServerHandle, "All trace buffers are empty");
      else {
         sprintf(outputBuff,"Trace buffer %d is empty", buffID);
         SendCliMessage(cliServerHandle, outputBuff);
      }
      return GOOD;
   }
   if (listAllFlag || startFlag) startFrame2 = startFrame;
   else {
      if (startFrame2 < startFrame || startFrame2 > endFrame)
         return(ER_INVALID_FRAME);
   }
   while (TRUE) {
      LPSTR strPtr;

      err = iceGetQualifyFrame(buffID,startFrame2,&qualifyList,&numFrame, traceData);
      if (err != GOOD) {
         if (buffID == lastBuff || !listAllFlag) break;
         buffID++;
         iceGetTraceBufferInfo(buffID, &startFrame2, &endFrame);
         continue;
      }
      totalFrames += numFrame;
      for (i=0;i < numFrame; i++) {
         err = TskCheckAbort(&abortFromEsc);
         if(err!=GOOD) return err;
         if (abortFromEsc!=0) {
            err = ER_ABORT_FROM_ESC;
            return err;
         }
         strPtr = outputBuff;
         *strPtr = '\0';
         if (dataFlag) {
            busData = traceData[i].data;
            GetBusData(traceData[i].addr, traceData[i].stat, &busData);
            if (data != busData) continue;
         }
         FormatFrameToText(&traceData[i], outputBuff, listAllFlag, buffID);
         SendCliMessage(cliServerHandle, (LPSTR)outputBuff);
      }
      if (numFrame < 48) {
         if (buffID == lastBuff || !listAllFlag) break;
         buffID++;
         iceGetTraceBufferInfo(buffID, &startFrame2, &endFrame);
      } else {
         startFrame2 = traceData[numFrame-1].frameNo + 1;
      }
   }  /* end of while (TRUE) */

   if (!totalFrames) {
      if (listAllFlag)
         SendCliMessage(cliServerHandle,
            "Cannot find frame in all trace buffers");
      else {
         sprintf(outputBuff,"Cannot find frame in trace buffer %d", buffID);
         SendCliMessage(cliServerHandle, (LPSTR)outputBuff);
      }
   }
   return GOOD;
}  /* end of MemCliListTrace */

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;
   }
}

RETCODE  FormatFrameToText(MP_TRACE_INFO *framePtr, LPSTR dataPtr, 
            BOOLEAN listAllFlag, U16 buffID) {
   U8 lineBuff[80];
   U8 isFlush, isDMA;
   U8 tmpByte;
   PROBE_TYPE specificProcessor;
   char *statusCode[8]={"A","I","O","H","S","R","W","D"};
   char *binaryNibble[16]={"0000","0001","0010","0011",
                        "0100","0101","0110","0111",
                        "1000","1001","1010","1011",
                        "1100","1101","1110","1111"
   };
//   if (listAllFlag) 
//      sprintf(lineBuff,"Buff#%d %8ld  %05lX -%s- ", buffID, framePtr->frameNo,
//         framePtr->addr, statusCode[framePtr->stat & 0x7]);
//   else
      sprintf(lineBuff,"%8ld  %05lX -%s- ", framePtr->frameNo, framePtr->addr,
         statusCode[framePtr->stat & 0x7]);
   lstrcat(dataPtr,lineBuff);
   ProcReturnSpecificProcessor(&specificProcessor);
   switch (specificProcessor) {
      case I80C186_MP:
      case I80C186XL_MP:
      case I80C186EA_MP:
      case I80C186EB_MP:
      case I80C186EC_MP:
        if ( !(framePtr->stat&0x10) ) {
           if (!(framePtr->addr&1)) 
              sprintf(lineBuff,"%04X ", framePtr->data & 0xffff);
           else
              sprintf(lineBuff,"%02X   ", (framePtr->data >> 8) & 0xff);
        } else {
           if (!(framePtr->addr&1)) 
              sprintf(lineBuff,"%02X   ", framePtr->data & 0xff);
           else
              sprintf(lineBuff,"%04X ", framePtr->data & 0xffff);
        }
        break;
      case I80C188_MP:
      case I80C188XL_MP:
      case I80C188EA_MP:
      case I80C188EB_MP:
      case I80C188EC_MP:
        tmpByte = (U8) framePtr->data & 0xff;
        sprintf(lineBuff,"%02X   ", tmpByte);
        break;
   }
   lstrcat(dataPtr,lineBuff);
   if ( framePtr->stat&0x20 ) isDMA = '1'; else isDMA = '0'; 
   if ( framePtr->stat&0x40 ) isFlush = '1'; else isFlush = '0'; 
   sprintf(lineBuff,"  flush=%c  DMA=%c  %s%s", isFlush, isDMA,
      binaryNibble[(framePtr->tbit>>4)&0xf],
      binaryNibble[framePtr->tbit & 0xf]);
   lstrcat(dataPtr,lineBuff);
   return(GOOD);
}

/***************************************************************************
**
**  MemCliInput
**
**  Status:  PRELIMINARY
**
**  description:
**     Cli interface to the input memory content
**
**     Syntax:
**        input <address> [BYTE|WORD]
**
**  input:
**     standard command input parameters
**
**  output:
**     <none> :
**
*****************************************************************************/
RETCODE EXPORT MemCliInput(LPSTR cmdString, U32 argc, U32 argv[]) {
   RETCODE    firstErr, err;
   DESCRIPTOR desc;
   ACCESS_SIZE size;
   U32 offset;
   U16 data;
   char outputBuff[80];

   size = BYTE_SIZE;

   if(argc < 2 || argc > 3) return(ER_CLI_SYNTAX);

   /* get starting address into addr desc. */
   if((err=AdrCreateAddressFromText(&cmdString[(U16)argv[1]],
         NULL,&desc)) != GOOD)
      return err;


   if (argc == 3) {
      if (strncmpi(&cmdString[(U16)argv[2]], "word",
          strlen(&cmdString[(U16)argv[2]])) == 0)
         size = WORD_SIZE;
      else if (strncmpi(&cmdString[(U16)argv[2]], "byte",
         strlen(&cmdString[(U16)argv[2]])) != 0) {
         err = ER_CLI_SYNTAX;
         goto CLEANUP;
      }
   }
   AdrGetAddrOffset(desc, &offset);
   err = Sds2AbiInput((U16)offset,(U16)size,(U16)size-1,(U8 *)&data);
   if (err != GOOD) {
      goto CLEANUP;
   }
   if (size == BYTE_SIZE) 
      sprintf(outputBuff,"port 0x%04lx = 0x%02x",offset,data&0xff);
   else 
      sprintf(outputBuff,"port 0x%04lx = 0x%04x",offset,data);
   SendCliMessage(cliServerHandle, outputBuff);
   err = GOOD;

CLEANUP:
   firstErr = err;
   err = AdrDestroyAddress(desc);
   if (GOOD == firstErr)
      firstErr = err;
   return firstErr;
}

/***************************************************************************
**
**  MemCliOutput
**
**  Status:  PRELIMINARY
**
**  description:
**     Cli interface to the output memory content
**
**     Syntax:
**        output <address> data [BYTE|WORD]
**
**  input:
**     standard command input parameters
**
**  output:
**     <none> :
**
*****************************************************************************/
RETCODE EXPORT MemCliOutput(LPSTR cmdString, U32 argc, U32 argv[]) {
   RETCODE    firstErr, err;
   U32        tempData, offset;
   DESCRIPTOR desc;
   char       *endptr;
   ACCESS_SIZE size;

   size = BYTE_SIZE;

   if(argc < 3 || argc > 4) return(ER_CLI_SYNTAX);

   /* get starting address into addr desc. */
   if((err=AdrCreateAddressFromText(&cmdString[(U16)argv[1]],
         NULL,&desc)) != GOOD)
      return err;
   tempData = strtoul(&cmdString[(U16)argv[2]], &endptr, 0);
   if (*endptr!='\0') {
      err = ER_CLI_SYNTAX;
      goto CLEANUP;
   }

   if (argc == 4) {
      if (strncmpi(&cmdString[(U16)argv[3]], "word",
          strlen(&cmdString[(U16)argv[3]])) == 0)
         size = WORD_SIZE;
      else if (strncmpi(&cmdString[(U16)argv[3]], "byte",
         strlen(&cmdString[(U16)argv[3]])) != 0) {
         err = ER_CLI_SYNTAX;
         goto CLEANUP;
      }
   }
   switch (size) {
      case BYTE_SIZE:
         if (tempData >= 0x100L) {
            err = ER_MEM_DATA_GREATER_THAN_BYTE;
            goto CLEANUP;
         }
         break;
      case WORD_SIZE: {
         if (tempData >= 0x10000L) {
            err = ER_MEM_DATA_GREATER_THAN_WORD;
            goto CLEANUP;
         }
         break;
      }
   }

   AdrGetAddrOffset(desc, &offset);
   if (size == BYTE_SIZE) 
      err = Sds2AbiOutput((U16)offset,(U8 *)&tempData,(U16)size,0);
   else
      err = Sds2AbiOutput((U16)offset,(U8 *)&tempData,(U16)size,1);
   if (err != GOOD) {
      goto CLEANUP;
   }
   err = GOOD;

CLEANUP:
   firstErr = err;
   err = AdrDestroyAddress(desc);
   if (GOOD == firstErr)
      firstErr = err;
   return firstErr;
}

/************************************************************************
**
**  KeywordInit()
**
*************************************************************************/
VOID PRIVATE KeywordInit(VOID) {
   sizeKeyword=FALSE;
   spaceKeyword=FALSE;
   loopKeyword=FALSE;
}

/************************************************************************
**
**  KeywordCheck()
**
************************************************************************/
BOOLEAN PRIVATE KeywordCheck(LPSTR str) {
   U8 paramLen = strlen(str);
   BOOLEAN found = TRUE;
   if (!sizeKeyword && strncmpi(str, BYTE_TEXT, paramLen)==0) {
      dataSize = BYTE_SIZE;
      sizeKeyword = TRUE;
   } else if (!sizeKeyword && strncmpi(str, WORD_TEXT, paramLen)==0) {
      dataSize = WORD_SIZE;
      sizeKeyword = TRUE;
   } else if (!sizeKeyword && strncmpi(str, LONG_TEXT, paramLen)==0) {
      dataSize = DWORD_SIZE;
      sizeKeyword = TRUE;
   } else if (!sizeKeyword && strncmpi(str, DWORD_TEXT, paramLen)==0) {
      dataSize = DWORD_SIZE;
      sizeKeyword = TRUE;
   } else if (!loopKeyword && strncmpi(str, LOOP_TEXT, paramLen)==0) {
      found = FALSE; //!!186
//!!186      loop = TRUE;
//!!186      loopKeyword = TRUE;
   } else if (!spaceKeyword && AdrTranslateSpace(str, &addrSpace)==GOOD) {
      found = FALSE; //!!186
//!!186   extendedSpace = addrSpace;
//!!186   spaceKeyword = TRUE;
   } else if (!spaceKeyword && extendedSpaceEnabled
         && TestIsExtendedSpace(str,&extendedSpace)){
      spaceKeyword = TRUE;
   }
   else found = FALSE;
   return(found);
}

/************************************************************************
**
**  IsProcessorSpace()
**
**************************************************************************/
BOOLEAN PRIVATE IsProcessorSpace(ADDR_SPACE space) {
   return(space <= SPACE_LAST_PROCESSOR);
}

/************************************************************************
**
**  CheckValidDWORD(U32 value,CHAR *str)
**
**************************************************************************/
BOOLEAN CheckValidDWORD(U32 value,CHAR *str) {
   CHAR bufDEC[20], bufHEX[20], *strPtr;
   BOOLEAN retVal = TRUE;

   strPtr = str;
   if (strlen(strPtr) > 8) {
      ultoa(value,bufDEC,10);
      ultoa(value,bufHEX,16);
      if (strncmpi(strPtr,"0x",2) == 0) {
         strPtr += 2;
         if (strcmpi(strPtr,bufHEX) != 0)
            retVal = FALSE;
      } else {
         if (strcmpi(strPtr,bufDEC) != 0) 
            retVal = FALSE;
      }
   }
   return(retVal);
}  /* gene */

/* Winky 3/17/98 */
RETCODE EXPORT MemCliUploadMemory(LPSTR cmdString, U32 argc, U32 argv[]) {
   RETCODE    err;
   RETCODE    firstErr = GOOD;
   U32        bytesLeft, bytesToEnd;
   DESCRIPTOR addr1Desc, addr2Desc;
   BOOLEAN    firstAddrFound=FALSE;
   LOOP_VAR   args;
   BOOLEAN    abortFromEsc;
   int        i, j, hFile;   
   LPSTR      fileName = "upload.hex";
   S8         sizeBuf, hexLen[5], hexCheck[5], hexBase[5];
   U16        sizeAddr, sizeData, sizeCheck;
   U32        iHex, iAdr, regID, regBase;


   if ((argc < 2) || (argc > 5))
      return(ER_CLI_SYNTAX);

   addrSpace = SPACE_DEFAULT;
   dataSize = BYTE_SIZE;
   loop = FALSE;
   extendedSpace = SPACE_DEFAULT;
   KeywordInit();
   
   if((err = AdrCreateAddress(&addr1Desc))!=GOOD) return(err);
   if (GOOD != (err = AdrCreateAddress(&addr2Desc))) {
      AdrDestroyAddress(addr1Desc);
      return err;
   }

   for (args=1; args<argc; args++) 
      KeywordCheck(&(cmdString[(U16)argv[args]]));

   KeywordInit();

   for( args = 1; args < argc; args++ ) {
      if( !KeywordCheck(&(cmdString[(U16)argv[args]])) ) {
         U32 offset;
         DESCRIPTOR *adrDesc;
         if( firstAddrFound == FALSE ) adrDesc = &addr1Desc;
         else adrDesc = &addr2Desc;
         firstAddrFound++;
         if (TestIsSastBitName(&cmdString[(U16)argv[args]], extendedSpace,
               &offset)) {
            if ((err = AdrSetAddrOffset(*adrDesc,offset)) != GOOD)
               goto CLEANUP_1;
         } else if((err=AdrConvTextToAddress(*adrDesc,
            &cmdString[(U16)argv[args]])) != GOOD) goto CLEANUP_1;
      }
   }
   bytesLeft = LINE_LENGTH;
   if(( firstAddrFound == 0) || (firstAddrFound >= 3)) {  
      err = ER_CLI_SYNTAX;
      goto CLEANUP_1;
   }
   if((err=AdrSetAddrSpace(addr1Desc, addrSpace))!=GOOD) goto CLEANUP_1;
   if( firstAddrFound == 2 ) {
      ADDR_COMPARE addrCompareResult;

      if((err=AdrSetAddrSpace(addr2Desc, addrSpace))!=GOOD) goto CLEANUP_1;

      if(GOOD!=(err=AdrRangeOfAddresses(addr1Desc,addr2Desc,&bytesLeft)))
         goto CLEANUP_1;

      if((err=AdrCompareAddresses(addr1Desc,addr2Desc,&addrCompareResult))
         != GOOD ) goto CLEANUP_1;

      if (FIRST_ADDR_GREATER == addrCompareResult) {
         return ER_ADR_END_ADDR_TOO_SMALL; 
      }
   }

   switch (dataSize) {
      case WORD_SIZE:
         if (bytesLeft & 0x1L)
            bytesLeft++;
         break;
   
      case DWORD_SIZE:
         if (bytesLeft & 0x3L)  {
            bytesLeft = (bytesLeft & 0xFFFFFFFCL) + 4L;
         }
   }
   if (0L == bytesLeft)
      bytesLeft = 0xFFFFFFFFL;
   if (GOOD != (err = AdrRemainingBytes(addr1Desc, &bytesToEnd)))
      goto CLEANUP_1;
   if (0L == bytesToEnd) 
      bytesToEnd = 0xFFFFFFFFL;
   bytesLeft = min(bytesLeft, bytesToEnd);

   err = TskCheckAbort(&abortFromEsc);
   if(err!=GOOD) goto CLEANUP_1;

   iHex = NULL;

   while (TRUE) {
      LPU8  buff;
      S8    outputBuff[(LINE_LENGTH * 3) + 15];
      U16   blockSize;
      U16   i;
      LPSTR strPtr, tmpPtr;
      U8    ch;
      DATA_UNION dataUnion;

      blockSize = min(bytesLeft, LINE_LENGTH);

      if (loop || extendedSpaceEnabled) {
         if((err = TestRead(addr1Desc, extendedSpace, (U32)blockSize, &buff,
               loop)) != GOOD) {
            TFree((LPSTR)buff);
            goto CLEANUP_1;
         }
      } else {
         if((err = MemRead(addr1Desc, blockSize, &buff,CACHE_BYPASS))!=GOOD) {
            TFree((LPSTR)buff);
            goto CLEANUP_1;
         }
      }

      if((err = AdrConvAddressToTextWithParams(addr1Desc,
                                               FALSE,
                                               TRUE,
                                               outputBuff))!=GOOD) {
         TFree((LPSTR)buff);
         goto CLEANUP_1;
      }

      sizeData = sizeCheck = NULL;

      i = j = iAdr = 0;
      strPtr = outputBuff;
      while (*strPtr) {
         if (j > 4) {
            SendCliMessage(cliServerHandle,
                           (LPSTR)"Physical address disacceptable!");
            goto CLEANUP_1;
         }
         if (*strPtr == ':') {
            iAdr = i;
            hexBase[j] = '\0';
            j = -1;
         }
         if (iAdr == 0) hexBase[j] = *strPtr;
         if (i > j && j > -1) outputBuff[j] = *strPtr;
         i++;
         j++;
         strPtr++;
      }
      outputBuff[j] = '\0';

      if (iHex == NULL) {
         if (iAdr == 2) {
            if (strcmp(hexBase, "CS") == 0)
               CpuFindRegisterId((LPU8)"CS",&regID);
            else if (strcmp(hexBase, "ES") == 0)
               CpuFindRegisterId((LPU8)"ES",&regID);
            else if (strcmp(hexBase, "SS") == 0)
               CpuFindRegisterId((LPU8)"SS",&regID);
            else 
               CpuFindRegisterId((LPU8)"DS",&regID);
            CpuGetRegister(regID, &regBase);
            sprintf(hexBase, "%04hX", regBase);
         }
         if((hFile = _lcreat(fileName,0)) == -1) return(ER_CANT_OPEN_FILE);
         SendCliMessage(cliServerHandle,
                        (LPSTR)"Write Hex file, please wait...");
         sizeAddr = NULL; 
         for (i = 0; i < HEX_ADDR_SIZE; i++) {
            if (hexBase[2*i] < 'A')
              sizeAddr += (hexBase[2*i] - 48) * 16;
            else
              sizeAddr += (hexBase[2*i] - 55) * 16;

            if (hexBase[2*i + 1] < 'A')
              sizeAddr += hexBase[2*i + 1] - 48;
            else
              sizeAddr += hexBase[2*i + 1] - 55;
         }
         sizeCheck = (0x100 - (0x4 + sizeAddr)) & 0x00ff;
         sprintf(hexCheck, "%02hX", sizeCheck);
         sizeBuf = lstrlen(HEX_TYPE_EXT);
         if(_lwrite(hFile,HEX_TYPE_EXT,sizeBuf) != sizeBuf)
            return(ER_WRITING_FILE);
         if(_lwrite(hFile,hexBase,4) != 4)
            return(ER_WRITING_FILE);
         if(_lwrite(hFile,hexCheck,2) != 2)
            return(ER_WRITING_FILE);
         if(_lwrite(hFile,"\r\n",2)!=2)
            return(ER_WRITING_FILE);
      }

      sizeAddr = NULL;
      for (i = 0; i < HEX_ADDR_SIZE; i++) {
         if (outputBuff[2*i] < 'A')
           sizeAddr += (outputBuff[2*i] - 48) * 16;
         else
           sizeAddr += (outputBuff[2*i] - 55) * 16;

         if (outputBuff[2*i + 1] < 'A')
           sizeAddr += outputBuff[2*i + 1] - 48;
         else
           sizeAddr += outputBuff[2*i + 1] - 55;
      }

      strcat(outputBuff,HEX_TYPE_DATA);

      strPtr = outputBuff;
      while (*strPtr) 
         strPtr++;

      dataUnion.U32Val = 0L;
      for(i=0; i<blockSize; ) {
         S8 text[10];
         U8 diff;
         diff = blockSize - i;
         
         if (diff < 4) {
            if (diff < 2) {
               dataSize = BYTE_SIZE;
            } else {
               if (DWORD_SIZE == dataSize)
                  dataSize = WORD_SIZE;
            }
         }

         switch (dataSize) {
            case BYTE_SIZE:
               sizeData += buff[i];
               sprintf(text, "%02hX", buff[i++]);
               break;
            case WORD_SIZE:
               sizeData += buff[i];
               dataUnion.U8Val[0] = buff[i++];
               sizeData += buff[i];
               dataUnion.U8Val[1] = buff[i++];
               dataUnion.U16Val[0] = IsProcessorSpace(extendedSpace)
                    ? MemSwapBytesInWord(dataUnion.U16Val[0])
                    : TestSwapBytesInWord(dataUnion.U16Val[0],extendedSpace);
               sprintf(text, "%04X", dataUnion.U16Val[0]); 
               break;
            case DWORD_SIZE:
               sizeData += buff[i];
               dataUnion.U8Val[0] = buff[i++];
               sizeData += buff[i];
               dataUnion.U8Val[1] = buff[i++];
               sizeData += buff[i];
               dataUnion.U8Val[2] = buff[i++];
               sizeData += buff[i];
               dataUnion.U8Val[3] = buff[i++];
               dataUnion.U32Val = IsProcessorSpace(extendedSpace)
                     ? MemSwapBytesInLong(dataUnion.U32Val)
                     : TestSwapBytesInLong(dataUnion.U32Val,extendedSpace);
               sprintf(text, "%08lX", dataUnion.U32Val); 
               break;
         }
         tmpPtr = text;
         while ((ch = *tmpPtr++) > '\0') 
           *strPtr++ = ch;
      }
      *strPtr = '\0';

      if (!loop) {
         iHex++;
         sizeCheck = (0x100 - (blockSize + sizeAddr + sizeData)) & 0x00ff;
         sprintf(hexLen, "%02hX", blockSize);
         sprintf(hexCheck, "%02hX", sizeCheck);
         sizeBuf = lstrlen(outputBuff);

         if(_lwrite(hFile,":",1)!=1)
            return(ER_WRITING_FILE);
         if(_lwrite(hFile,hexLen,2)!=2)
            return(ER_WRITING_FILE);
         if(_lwrite(hFile,outputBuff, sizeBuf)!=sizeBuf)
            return(ER_WRITING_FILE);
         if(_lwrite(hFile,hexCheck,2)!=2)
            return(ER_WRITING_FILE);
         if(_lwrite(hFile,"\r\n",2)!=2)
            return(ER_WRITING_FILE);
      }

      if((TFree((LPSTR)buff))!=GOOD)
         goto CLEANUP_1;

      if (bytesLeft > blockSize) {
         bytesLeft -= blockSize;
      } else {
         break;
      }
      if((err = AdrAddToAddress(addr1Desc, (U32)blockSize))!=GOOD)
         goto CLEANUP_1;

      err = TskCheckAbort(&abortFromEsc);
      if(err!=GOOD) goto CLEANUP_1;
      if (abortFromEsc!=0) {
         err = ER_ABORT_FROM_ESC;
         goto CLEANUP_1;
      }
   }

   sizeBuf = lstrlen(HEX_TYPE_END);
   if(_lwrite(hFile,HEX_TYPE_END,sizeBuf) != sizeBuf)
      return(ER_WRITING_FILE);

   if(_lclose(hFile) == -1) return(ER_CANT_CLOSE_FILE);

   SendCliMessage(cliServerHandle, (LPSTR)"OK.");


CLEANUP_1:
   firstErr = err;
   err = AdrDestroyAddress(addr2Desc);

CLEANUP_2:
   if (!firstErr) firstErr = err;
   err = AdrDestroyAddress(addr1Desc);
   if (!firstErr) firstErr = err;
   return firstErr;
}

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