/****************************************************************************
**
**  Name:  sharecli.c
**
**  Description:
**     Shared data CLI commands
**
**  Status:  TESTED
**
**  $Log:   S:/tbird/mt2_68k/sds/sharecli.c_v  $
** 
**    Rev 1.0   13 Feb 1997 09:04:00   gene
** Initial revision.
** 
**    Rev 1.2   23 Sep 1996 10:42:10   kevin
** modified sdsclisetcanbaseaddr()
** 
**    Rev 1.1   18 Sep 1996 16:23:36   kevin
** added sdsclisetcanbaseaddr()
** 
**    Rev 1.0   07 Sep 1995 11:12:14   gene
** Initial revision.
** 
**    Rev 1.36   03 Aug 1993 13:06:12   ernie
** Changed to print correct version string for "2.0 ".
** 
**    Rev 1.35   16 Jul 1993 11:59:22   ernie
** Removed obsolete includes error.h and sdserror.h
** 
**    Rev 1.34   13 Jul 1993 19:59:20   doug
** Use generic syntax error.
** 
**    Rev 1.33   13 Jul 1993 09:18:40   ernie
** 1. Conform to new versions.h version definition scheme.
** 2. Implemented new bdmSpeed shell command.
** 
**    Rev 1.32   29 Jun 1993 08:58:56   steve
** pv 1.5a
** 
**    Rev 1.31   16 Jun 1993 14:40:24   mindy
** pv 1.5
** 
**    Rev 1.30   10 Jun 1993 09:54:56   steveh
** pv 1.4a
** 
**    Rev 1.29   09 Jun 1993 08:51:18   ernie
** Added _pvtask command for testing task server
** 
**    Rev 1.28   26 May 1993 08:40:56   steveh
** pv 1.3b
** 
**    Rev 1.27   25 May 1993 11:45:28   ernie
** Added shell command for Microsoft's vprof profiler
** 
**    Rev 1.26   13 May 1993 11:13:22   ernie
** Added _sdlog command support
** 
**    Rev 1.25   05 May 1993 09:24:06   doug
** support demo version (no hardware) run-time
** 
**    Rev 1.24   23 Apr 1993 11:37:42   doug
** pv 1.3
** 
**    Rev 1.23   13 Apr 1993 14:05:42   doug
** bumped to 1.2
** 
**    Rev 1.22   30 Mar 1993 08:05:54   ernie
** Changed version command to use routines in proc.dll
** 
**    Rev 1.21   23 Mar 1993 07:10:52   doug
** Show version with major.minor.bug and not compatibility, so this matches
** how we advertise the release
** 
**    Rev 1.20   22 Mar 1993 07:40:00   ernie
** 1. Added test for F333 processor.
** 2. Added cli handling function for berrRetry command.
** 
**    Rev 1.19   10 Mar 1993 09:00:44   nghia
** Changed SOFTWARE_MINOR_VERSION to 1 for release 1.1a.
** 
**    Rev 1.18   09 Mar 1993 07:14:20   doug
** add F333 as a part of the 332 (no check for difference currently, but
** could be added)
** 
**    Rev 1.17   11 Feb 1993 07:48:32   doug
** bumped compatibility for 1.0b release
** 
**    Rev 1.16   13 Jan 1993 12:43:44   doug
** Version 1.0(0).
** 
**    Rev 1.15   05 Jan 1993 15:06:48   courtney
** Removed call to MemUnlock.
** 
**    Rev 1.14   05 Jan 1993 15:00:24   courtney
** Remove MemAlloc (and related) macros.
** 
**    Rev 1.13   10 Dec 1992 07:52:38   ernie
** Added total packet count to _commerrors command output
** 
**    Rev 1.12   03 Dec 1992 08:55:56   ernie
** Added check for mom present before printing mom version number
** 
**    Rev 1.11   03 Dec 1992 09:14:06   doug
** added trademarks
** 
**    Rev 1.10   30 Nov 1992 12:00:22   doug
** ppr7495: beefed up version information (dos, windows, firmware, etc.)
** 
**    Rev 1.9   03 Nov 1992 12:28:30   ernie
** Removed B2HDelay from commerrors statistics...obsolete
** 
**    Rev 1.8   22 Oct 1992 15:27:46   ernie
** Added cli commands for get/set of comm error recovery parameters.
** 
**    Rev 1.7   09 Oct 1992 08:01:08   doug
** VER command is now working
** 
**    Rev 1.6   03 Sep 1992 13:12:36   doug
** added two debug commands and cleaned up errors
** 
**    Rev 1.5   25 Aug 1992 10:04:16   doug
** Dummy out for now since it UAEs.
** 
**    Rev 1.4   14 Aug 1992 15:59:24   doug
** add prototype for memory allocation and remove warning
** 
**    Rev 1.3   14 Aug 1992 11:10:10   tom
** fixed rc file
** 
**    Rev 1.2   14 Aug 1992 10:53:36   doug
** changes to remove warnings
** 
**    Rev 1.1   06 Aug 1992 08:32:26   doug
** values are binary, not characters from firmware
** 
**    Rev 1.0   30 Jul 1992 15:28:16   doug
** Initial revision.
**
**  $Header:   S:/tbird/mt2_68k/sds/sharecli.c_v   1.0   13 Feb 1997 09:04:00   gene  $
**
**  Copyright (C) 1991 Microtek International.  All rights reserved.
**
*****************************************************************************/

                       /****************************
                        *                          *
                        *       INCLUDE FILES      *
                        *                          *
                        ****************************/
#include <time.h>
#include <ctype.h>

#ifndef __DOS_H
#include "dos.h"
#endif

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

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

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

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

#ifndef _HOSTERRS_
#include "hosterrs.h"
#endif

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

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

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

#ifndef _SHAREDAT_
#include "sharedat.h"
#endif

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

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

#ifndef _VERSIONS_
#include "versions.h"
#endif

                       /****************************
                        *                          *
                        *     LOCAL DEFINITIONS    *
                        *                          *
                        ****************************/
STATIC HANDLE cliServerHandle = (HANDLE)NULL;  /* force definition here */
typedef enum {
   VERSION_LETTER, VERSION_NUMBER
} VERSION_TYPE;
                       /****************************
                        *                          *
                        *    EXTERNAL VARIABLES    *
                        *                          *
                        ****************************/

                       /****************************
                        *                          *
                        *     LOCAL PROTOTYPES     *
                        *                          *
                        ****************************/
RETCODE PRIVATE PrintVersion(S8 *name, MEMBER_INDEX major, MEMBER_INDEX minor,
   MEMBER_INDEX compatibility, VERSION_TYPE type);
extern SHARED_DATA sdSharedData;
VOID EXPORT SdsCliTask0(VOID);
VOID EXPORT SdsCliTask1(VOID);
VOID EXPORT SdsCliTask2(VOID);
VOID EXPORT SdsCliTask3(VOID);

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

/***************************************************************************
**
**  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 = 30;
   msgBufPtr->dllNameIndex = 31;
   msgBufPtr->numberOfCommandsIndex = 32;
   msgBufPtr->commandStartIndex = 33;
   SendMessage(cliHandle, CLI_NEW_SVR_REGISTRATION, CLI_NEW_SVR_REGISTRATION,
      (DWORD)msgBufPtr);
   return(GOOD);
}

/***************************************************************************
**
**  SdsCliVersion
**
*****************************************************************************/
extern unsigned char _osmajor, _osminor;

#pragma argsused
RETCODE EXPORT SdsCliVersion(LPSTR cmdString, U32 argc, U32 argv[]) {
   RETCODE err;
   S8 buff[150];
   PROC_SYSTEM_TYPE systemType;
   S8 processorName[PROC_MAX_PROCESSOR_NAME];
   BOOLEAN present;
   BOOLEAN demo;

   if (argc != 1) return(ER_CLI_SYNTAX);
   if ((err = ProcReturnDemonstrationVersion(&demo)) != GOOD) return(err);
   if ((err = ProcReturnSystemType(&systemType)) != GOOD) return(err);
   if ((err = ProcReturnProcessorName(processorName)) != GOOD) return(err);
   if(demo) SendMessageToCli("Demonstration Version");
   wsprintf(buff, "System configuration is ");
   switch(systemType) {
      case PROC_DUMMY:
          strcat(buff, "no emulator probe connected"); break;
      case PROC_POWERPACK:
          strcat(buff, "PowerPack(tm) for ");
          strcat(buff, processorName);
          break;
      case PROC_POWERSCOPE:
          strcat(buff, "PowerScope(tm) for ");
          strcat(buff, processorName);
          break;
      case PROC_MICEPACK:
          strcat(buff, "MICEpack(tm) for ");
          strcat(buff, processorName);
          break;
      default: strcat(buff,"Unknown probe type"); break;
   }
   if((err = SendMessageToCli(buff))!=GOOD) return(err);
   wsprintf(buff, "Software version is %d.%d%c", VER_MAJOR,
      VER_MINOR, VER_BUILD);
   if((err = SendMessageToCli(buff))!=GOOD) return(err);
   if (systemType != PROC_MICEPACK)
      {
      if((err = PrintVersion("Firmware", SDN_FIRMWARE_MAJOR_VERSION,
         SDN_FIRMWARE_MINOR_VERSION, SDN_FIRMWARE_COMPATIBILITY, VERSION_LETTER))
         !=GOOD) return(err);
      /*
         Motherboard
      */
      if((err = SdnReadMember(SDN_MOM_PRESENT, &present))!=GOOD) return(err);
      if(present)
         {
         if((err = PrintVersion("Motherboard", SDN_MOM_MAJOR_VERSION,
            SDN_MOM_MINOR_VERSION, SDN_MOM_COMPATIBILITY, VERSION_NUMBER))
            !=GOOD) return(err);
         }
      }
   /*
      Probe
   */
   if((systemType!=PROC_DUMMY) && (systemType != PROC_MICEPACK)){
      if((err = PrintVersion("Probe", SDN_PROBE_MAJOR_VERSION,
         SDN_PROBE_MINOR_VERSION,SDN_PROBE_COMPATIBILITY, VERSION_NUMBER))
         !=GOOD) return(err);
   }

if (systemType != PROC_MICEPACK)
{
   /*
      Trace boards
   */
   if((err = SdnReadMember(SDN_TRACE_0_SLOT_PRESENT, &present))!=GOOD)
      return(err);
   if(present) {
      if((err = PrintVersion("Trace R", SDN_TRACE_0_MAJOR_VERSION,
         SDN_TRACE_0_MINOR_VERSION, SDN_TRACE_0_COMPATIBILITY, VERSION_NUMBER))
         !=GOOD) return(err);
   }
   if((err = SdnReadMember(SDN_TRACE_1_SLOT_PRESENT, &present))!=GOOD)
      return(err);
   if(present) {
      if((err = PrintVersion("Trace S", SDN_TRACE_1_MAJOR_VERSION,
         SDN_TRACE_1_MINOR_VERSION, SDN_TRACE_1_COMPATIBILITY, VERSION_NUMBER))
         !=GOOD) return(err);
   }
   if((err = SdnReadMember(SDN_TRACE_2_SLOT_PRESENT, &present))!=GOOD)
      return(err);
   if(present) {
      if((err = PrintVersion("Trace T", SDN_TRACE_2_MAJOR_VERSION,
         SDN_TRACE_2_MINOR_VERSION, SDN_TRACE_2_COMPATIBILITY, VERSION_NUMBER))
         !=GOOD) return(err);
   }
   if((err = SdnReadMember(SDN_TRACE_3_SLOT_PRESENT, &present))!=GOOD)
      return(err);
   if(present) {
      if((err = PrintVersion("Trace U", SDN_TRACE_3_MAJOR_VERSION,
         SDN_TRACE_3_MINOR_VERSION, SDN_TRACE_3_COMPATIBILITY, VERSION_NUMBER))
         !=GOOD) return(err);
   }
   /*
      Swat board
   */
   if((err = SdnReadMember(SDN_SWAT_PRESENT, &present))!=GOOD)
      return(err);
   if(present) {
      if((err = PrintVersion("Swat", SDN_SWAT_MAJOR_VERSION,
         SDN_SWAT_MINOR_VERSION, SDN_SWAT_COMPATIBILITY, VERSION_NUMBER))
         !=GOOD) return(err);
   }
}
   wsprintf(buff, "Dos version is %d.%d", _osmajor, _osminor);
   if((err = SendMessageToCli(buff))!=GOOD) return(err);
   wsprintf(buff, "Windows version is %d.%d", GetVersion()&0xff,
                                              (GetVersion()>>8)&0xff);
   if((err = SendMessageToCli(buff))!=GOOD) return(err);
   return(GOOD);  
}

/****************************************************************************
**
**  SendMessageToCli
**
*****************************************************************************/
RETCODE SendMessageToCli(LPSTR msgPtr) {
   GLOBALHANDLE msgBufHandle;
   CSERVER_RESULTS FAR  *msgBufPtr;
   U16 msgTextSize;
   LOOP_VAR loop;

   msgTextSize = lstrlen(msgPtr);
   msgBufHandle = GlobalAlloc(GMEM_MOVEABLE, (sizeof(CSERVER_RESULTS)
     + msgTextSize + 2));
   if (msgBufHandle == (HANDLE)NULL) {
	  return(ER_OUT_OF_MEMORY);
   }
   else if((msgBufPtr=(CSERVER_RESULTS FAR *)GlobalLock(msgBufHandle)) == NULL) {
	  return(ER_WINDOWS_MEMLOCK);
   }
   /* Initialize message buffer */
   msgBufPtr->target               = 0;
   msgBufPtr->variantCode          = CLI_SERVER_RESULTS;
   msgBufPtr->resultTextLength     = msgTextSize; /* message string length */
   for (loop = 0; loop < msgTextSize; loop++ ) {
      msgBufPtr->messageText[loop]  =  *msgPtr++;
   }
   msgBufPtr->messageText[loop]  =  '\0' ;

   /* output message to memBufPtr->messageText[] */
   /*
   *** CLI Server will consume the handle when it done.
    */
   SendMessage(cliServerHandle, CLI_SERVER_RESULTS, msgBufHandle,
         (DWORD)CLI_SERVER_RESULTS );
   return (GOOD);
}

/***************************************************************************
**
**  PrintVersion
**
*****************************************************************************/
RETCODE PRIVATE PrintVersion(S8 *name, MEMBER_INDEX major, MEMBER_INDEX minor,
      MEMBER_INDEX compatibility, VERSION_TYPE type) {
   RETCODE err;
   U8 majorChr, minorChr, compatChr;
   S8 buff[150];
   
   if((err = SdnReadMember(major, &majorChr))!=GOOD) return(err);
   if((err = SdnReadMember(minor, &minorChr))!=GOOD) return(err);
   if((err = SdnReadMember(compatibility, &compatChr))!=GOOD) return(err);
   if ((type == VERSION_NUMBER) || !isprint(compatChr)) 
      wsprintf(buff, "%s version is %d.%d(%d)", name, majorChr, minorChr,
         compatChr);
   else
      wsprintf(buff, "%s version is %d.%d%c", name, majorChr, minorChr,
         compatChr);
   if((err = SendMessageToCli(buff))!=GOOD) return(err);
   return(GOOD);
}

/***************************************************************************
**
**  SdsCliTimeout
**
*****************************************************************************/
#pragma argsused
RETCODE EXPORT SdsCliTimeout(LPSTR cmdString, U32 argc, U32 argv[]) {
   RETCODE err;
   S8 buff[80];
   U32 timeoutValue;
   S8 *endPtr;
   TIMEOUT currentTimeout;

   if(argc==1) {
      /* display current setting */
      if((err = SdatGetTimeout(&currentTimeout))!=GOOD) return(err);
      wsprintf(buff, "Timeout is %ld seconds", currentTimeout);
      SendMessageToCli(buff);
   } else if(argc==2) {
      /* set */
      timeoutValue = strtoul(&cmdString[(int)argv[1]], &endPtr, 0);
      if(*endPtr != '\0') return(ER_CLI_SYNTAX);

      wsprintf(buff, "value is %ld seconds", timeoutValue);
      SendMessageToCli(buff);
      
      if((err = SdatSetTimeout((TIMEOUT)timeoutValue))!=GOOD) return(err);
   } else return(ER_CLI_SYNTAX);
   return(GOOD);
}

RETCODE EXPORT SdsCliCommRetry(LPSTR cmdString, U32 argc, U32 argv[]) {
   RETCODE err;
   S8 buff[80];
   U32 retry;
   S8 *endPtr;

   switch (argc) {
      case 2:
         /* set */
         retry = strtoul(&cmdString[(int)argv[1]], &endPtr, 0);
         if(*endPtr != '\0') return(ER_CLI_SYNTAX);
         if((err = SdatSetCommRetry(retry))!=GOOD) return(err);
         /* fall thru */
      case 1:
         /* display current setting */
         if((err = SdatGetCommRetry(&retry))!=GOOD) return(err);
         wsprintf(buff, "Number of retries is %ld.", retry);
         SendMessageToCli(buff);
         break;
      default:
         return(ER_CLI_SYNTAX);
   }
   return(GOOD);
}

RETCODE EXPORT SdsCliCommTimeout(LPSTR cmdString, U32 argc, U32 argv[]) {
   RETCODE err;
   S8 buff[80];
   U32 timeout;
   S8 *endPtr;

   switch (argc) {
      case 2:
         /* set */
         timeout = strtoul(&cmdString[(int)argv[1]], &endPtr, 0);
         if(*endPtr != '\0') return(ER_CLI_SYNTAX);
         if((err = SdatSetCommTimeout(timeout))!=GOOD) return(err);
         /* fall thru */
      case 1:
         /* display current setting */
         if((err = SdatGetCommTimeout(&timeout))!=GOOD) return(err);
         wsprintf(buff, "Comm timeout is %ld clock ticks.", timeout);
         SendMessageToCli(buff);
         break;
      default:
         return(ER_CLI_SYNTAX);
   }
   return(GOOD);
}

/***************************************************************************
**
**  SdsCliSdDump
**
*****************************************************************************/
#pragma argsused
RETCODE EXPORT SdsCliSdDump(LPSTR cmdString, U32 argc, U32 argv[]) {
   RETCODE err;
   U32 index;
   S8 *endPtr;

  if(argc==2) {
      /* set */
      index = strtoul(&cmdString[(int)argv[1]], &endPtr, 0);
      if(*endPtr != '\0') return(ER_CLI_SYNTAX);
      if((err = SdatDisplayMember(index))!=GOOD) return(err);
   } else return(ER_CLI_SYNTAX);
   return(GOOD);
}

#pragma argsused
RETCODE EXPORT SdsCliPrintCommErrors(LPSTR cmdString, U32 argc, U32 argv[]) {
   RETCODE err;
   S8 buf[80];
   U32 commErrorH2BTimeout, commErrorH2BRetries, commErrorB2HTimeout;
   U32 commErrorB2HMissing, commErrorB2HGarbled, H2BTotal, B2HTotal;
   if ((err = SdatGetCommErrors(&commErrorH2BTimeout,&commErrorH2BRetries,
      &commErrorB2HTimeout,&commErrorB2HMissing,&commErrorB2HGarbled,
      &H2BTotal, &B2HTotal)) != GOOD) return(err);
   wsprintf(buf, "Host-> Box packets:  %ld",H2BTotal);
   SendMessageToCli(buf);
   wsprintf(buf, "Box ->Host packets:  %ld",B2HTotal);
   SendMessageToCli(buf);
   wsprintf(buf, "Host-> Box timeouts: %ld",commErrorH2BTimeout);
   SendMessageToCli(buf);
   wsprintf(buf, "Host-> Box retries:  %ld",commErrorH2BRetries);
   SendMessageToCli(buf);
   wsprintf(buf, "Box ->Host timeouts: %ld",commErrorB2HTimeout);
   SendMessageToCli(buf);
   wsprintf(buf, "Box ->Host missing:  %ld",commErrorB2HMissing);
   SendMessageToCli(buf);
   wsprintf(buf, "Box ->Host garbled:  %ld",commErrorB2HGarbled);
   SendMessageToCli(buf);
   return(GOOD);
}

#pragma argsused
RETCODE EXPORT SdsCliBerrRetry(LPSTR cmdString, U32 argc, U32 argv[]) {
   RETCODE err;
   BOOLEAN retry;
   S8 buf[64];
   if (argc > 2) return(ER_CLI_SYNTAX);
   else if (argc == 2) {
      if (stricmp(&cmdString[(int)argv[1]],"on") == 0) {
         if ((err = SdatSetBerrRetry(TRUE)) != GOOD) return(err);
      }
      else if (stricmp(&cmdString[(int)argv[1]],"off") == 0) {
         if ((err = SdatSetBerrRetry(FALSE)) != GOOD) return(err);
      }
      else return(ER_CLI_SYNTAX);
   }
   if ((err = SdatGetBerrRetry(&retry)) != GOOD) return(err);
   wsprintf(buf, "BERR Retry is %s", retry ? "on" : "off");
   if ((err = SendMessageToCli(buf)) != GOOD) return(err);
   return(GOOD);
}

#pragma argsused
RETCODE EXPORT SdsCliLog(LPSTR cmdString, U32 argc, U32 argv[]) {
   RETCODE err;
   BOOLEAN log;
   S8 buf[64];
   S8 *name;
   if (argc > 2) return(ER_CLI_SYNTAX);
   else if (argc == 2) {
      if (stricmp(&cmdString[(int)argv[1]],"on") == 0) {
         if ((err = SdatGetSdLog(&log, &name)) != GOOD) return(err);
         if ((err = SdatSetSdLog(TRUE, name)) != GOOD) return(err);
      }
      else if (stricmp(&cmdString[(int)argv[1]],"off") == 0) {
         if ((err = SdatGetSdLog(&log, &name)) != GOOD) return(err);
         if ((err = SdatSetSdLog(FALSE,name)) != GOOD) return(err);
      }
      else {
         if ((err = SdatSetSdLog(TRUE, &cmdString[(int)argv[1]])) != GOOD)
            return(err);
      }
   }
   if ((err = SdatGetSdLog(&log, &name)) != GOOD) return(err);
   wsprintf(buf, "SdLog to %s is %s", name, log ? "on" : "off");
   if ((err = SendMessageToCli(buf)) != GOOD) return(err);
   return(GOOD);
}

#pragma argsused
RETCODE EXPORT SdsCliVprof(LPSTR cmdString, U32 argc, U32 argv[]) {
   RETCODE err;
   static BOOLEAN profiler=FALSE;
   S8 buf[64];
   if (ProfInsChk() != 2) return(ER_VPROF_NOT_INSTALLED);
   if (argc > 2) return(ER_CLI_SYNTAX);
   else if (argc == 2) {
      if (stricmp(&cmdString[(int)argv[1]],"on") == 0) {
         ProfStart();
         profiler=TRUE;
      }
      else if (stricmp(&cmdString[(int)argv[1]],"off") == 0) {
         ProfStop();
         ProfFlush();
         profiler=FALSE;
      }
      else return(ER_CLI_SYNTAX);
   }
   wsprintf(buf, "Vprof is %s", profiler ? "on" : "off");
   if ((err = SendMessageToCli(buf)) != GOOD) return(err);
   return(GOOD);
}

/* _pvtask [add <task> <priority> | delete <task>] */
#define NUM_CLI_TASKS 4
#pragma argsused
RETCODE EXPORT SdsCliPvtask(LPSTR cmdString, U32 argc, U32 argv[]) {
   RETCODE err;
   U16 taskNum=0, priority=0;
   S8 buf[64];
   VOID *state;
   static TASK cliTask[NUM_CLI_TASKS] = {
      SdsCliTask0, SdsCliTask1, SdsCliTask2, SdsCliTask3 };
   static LPSTR cliTaskName[NUM_CLI_TASKS] = {
      "SdsCliTask0", "SdsCliTask1", "SdsCliTask2", "SdsCliTask3" };
   if (argc > 4) return(ER_CLI_SYNTAX);
   if (argc >= 2) {
      if (stricmp(&cmdString[(int)argv[1]],"add") == 0) {
         if (argc != 4) return(ER_CLI_SYNTAX);
         taskNum = atoi(&cmdString[(int)argv[2]]);
         if (taskNum >= NUM_CLI_TASKS) return(ER_TASK_NOT_IN_TABLE);
         priority = atoi(&cmdString[(int)argv[3]]);
         if ((err = TaskRegister(cliTask[taskNum], priority,
            cliTaskName[taskNum])) != GOOD) return(err);
      }
      else if (stricmp(&cmdString[(int)argv[1]],"remove") == 0) {
         if (argc != 3) return(ER_CLI_SYNTAX);
         taskNum = atoi(&cmdString[(int)argv[2]]);
         if (taskNum >= NUM_CLI_TASKS) return(ER_TASK_NOT_IN_TABLE);
         if ((err = TaskUnregister(cliTask[taskNum])) != GOOD) return(err);
      }
      else return(ER_CLI_SYNTAX);
   }

   state = NULL;
   TaskWalk(&state, buf);
   if (state == NULL) {
      SendMessageToCli("Task list is empty.");
   } else do {
      if ((err = SendMessageToCli(buf)) != GOOD) return(err);
      TaskWalk(&state, buf);
   } while (state != NULL);

   return(GOOD);
}

VOID EXPORT SdsCliTask0(VOID) {
   static time_t lastTime=0;
   time_t curTime;
   if ((curTime = time(NULL)) > lastTime + 1) {
      lastTime = curTime;
      SendMessageToCli("Task 0");
   }
}

VOID EXPORT SdsCliTask1(VOID) {
   static time_t lastTime=0;
   time_t curTime;
   if ((curTime = time(NULL)) > lastTime + 2) {
      lastTime = curTime;
      SendMessageToCli("Task 1");
   }
}

VOID EXPORT SdsCliTask2(VOID) {
   static time_t lastTime=0;
   time_t curTime;
   if ((curTime = time(NULL)) > lastTime + 3) {
      lastTime = curTime;
      SendMessageToCli("Task 2");
   }
}

VOID EXPORT SdsCliTask3(VOID) {
   static time_t lastTime=0;
   time_t curTime;
   if ((curTime = time(NULL)) > lastTime + 4) {
      lastTime = curTime;
      SendMessageToCli("Task 3");
   }
}

RETCODE EXPORT SdsCliBdmSpeed(LPSTR cmdString, U32 argc, U32 argv[]) {
   RETCODE err;
   BDM_SPEED bdmSpeed;
   S8 buf[64];
   if (argc > 2) return(ER_CLI_SYNTAX);
   else if (argc == 2) {
      if (stricmp(&cmdString[(int)argv[1]],"fast") == 0) {
         if ((err = SdatSetBdmSpeed(BDM_FAST)) != GOOD) return(err);
      }
      else if (stricmp(&cmdString[(int)argv[1]],"slow") == 0) {
         if ((err = SdatSetBdmSpeed(BDM_SLOW)) != GOOD) return(err);
      }
      else return(ER_CLI_SYNTAX);
   }
   if ((err = SdatGetBdmSpeed(&bdmSpeed)) != GOOD) return(err);
   wsprintf(buf, "bdmSpeed is %s.", (bdmSpeed==BDM_FAST) ? "fast" : "slow");
   if ((err = SendMessageToCli(buf)) != GOOD) return(err);
   return(GOOD);
}

/***************************************************************************
**
**  SdsCliSetCanBaseAddr
**
*****************************************************************************/
#pragma argsused
RETCODE EXPORT SdsCliSetCanBaseAddr(LPSTR cmdString, U32 argc, U32 argv[]) {
   RETCODE err;
   S8 buff[80];
   U32 addrValue;
   S8 *endPtr;

   if(argc==2) {
      /* set */
      addrValue = strtoul(&cmdString[(int)argv[1]], &endPtr, 0);
      if(*endPtr != '\0') return(ER_CLI_SYNTAX);
      addrValue &= 0xFFFFFC00;
      wsprintf(buff, "Base address of CAN is %#06lX", addrValue);
      SendMessageToCli(buff);
      
      if ((err = iceSetCanBaseAddr((U32)addrValue)) != GOOD)
         return(ER_CANT_DO_COMMAND);
   }
   else return(ER_CLI_SYNTAX);

   return(GOOD);
}

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