/****************************************************************************
**
**  Name:  proccli.c
**
**  Description:
**     This is the proc server cli interface.
**
**  $Log:   S:/tbird/mt2_186/proc/proccli.c_v  $
** 
**    Rev 1.1   26 Jun 1997 16:37:16   cjchen
** add AMD186 model by cjchen
** 
**    Rev 1.0   16 Dec 1996 15:28:08   Judy
** Initial revision.
** 
**    Rev 1.2   18 May 1994 08:49:40   dennis
** Added code to set up three new shell system variables, $PROCESSOR,
** $PROCTYPE, $PROCFAMILY.
** 
**    Rev 1.1   30 Mar 1994 11:34:24   john
** Added changes for 360
** 
**    Rev 1.0   14 Feb 1994 13:26:54   marilyn
** Initial revision.
** 
**  $Header:   S:/tbird/mt2_186/proc/proccli.c_v   1.1   26 Jun 1997 16:37:16   cjchen  $
**
**  Copyright (C) 1994 Microtek International.  All rights reserved.
**
*****************************************************************************/

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

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

// #include "ctype.h"

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

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

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

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

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

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

#define PROC_LINE 40       // characters per output line

HANDLE cliServerHandle = (HANDLE)NULL;  /* force definition here */

PRIVATE CSERVER_VARIABLE_VALUE processorSystemVar;
PRIVATE S8 processorSystemVarName[] = "PROCESSOR";

PRIVATE CSERVER_VARIABLE_VALUE procTypeSystemVar;
PRIVATE S8 procTypeSystemVarName[] = "PROCTYPE";

PRIVATE CSERVER_VARIABLE_VALUE procFamilySystemVar;
PRIVATE S8 procFamilySystemVarName[] = "PROCFAMILY";


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

extern BOOLEAN     inTestMode;
extern PROBE_TYPE  testCpu;


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

RETCODE PRIVATE SendMessageToCli(S8 FAR *msgPtr, HANDLE cliHandle);


/**************************************************************************
** SendMessageToCli
**
** Description: Sends a local string to the CLI Server.
**
** Parameters:
**    input:
**       msgPtr:  long pointer to string to be sent
**       cliHandle:  DLL Handle.
**
**    output: none
**
***************************************************************************/
RETCODE PRIVATE SendMessageToCli(S8 FAR *msgPtr,
                                 HANDLE cliHandle) {
   HANDLE msgBufHandle;
   CSERVER_RESULTS FAR *cpPtr;
   LPSTR tmpPtr;
   U32 i;
   U16 size;

   size = strlen((CHAR *)msgPtr);
   // allocate enough memory for the string passed in and the size ;
   // of the CSERVER_RESULTS packet, and then subtract out the extra ;
   // space allocated to the messageText field. ;
   if ((msgBufHandle = GlobalAlloc(GMEM_MOVEABLE,
      (size + sizeof(CSERVER_RESULTS) + 2))) == (HANDLE)NULL) {
      return(ER_OUT_OF_MEMORY);              
   }
   else if ((cpPtr = (CSERVER_RESULTS *)GlobalLock(msgBufHandle)) == NULL) {
      GlobalFree(msgBufHandle);
      return(ER_WINDOWS_MEMLOCK);
   }
   cpPtr->target           = 0;  // address to the cli server;
   cpPtr->variantCode      = CLI_SERVER_RESULTS;
   cpPtr->resultTextLength = size; // size of message;

   /* reassign pointer to beginning of message text */
   (LPSTR)tmpPtr = cpPtr->messageText;

   /* copy the data from msgPtr to the global memory space */
   for(i = 0; i < size; i++) {
      *tmpPtr++ = *msgPtr++;
   }
   SendMessage(cliHandle, CLI_SERVER_RESULTS, msgBufHandle,
               (CLI_SERVER_RESULTS | 0x0L));
   return(GOOD);
}


/**************************************************************************
**
** InitCServer
**
** Description: Initialize the commands for the Proc Server.
**
** Parameters:
**    input:
**       cliHandle:  CLI Server Handle
**       dllHandle:  DLL Handle.
**
**    output: None
**
***************************************************************************/
RETCODE EXPORT InitCServer(HANDLE cliHandle, HANDLE dllHandle) {

   CSERVER_NEW_REGISTRATION FAR * msgBufPtr;
   S8 proc[10];
   S8 cpuType[10];
   S8 familyStr[12];
   PROCESSOR_FAMILY family;
   RETCODE err;

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

   msgBufPtr->stringResourceHandle = dllHandle;

   msgBufPtr->serverNameIndex = 30;
   msgBufPtr->dllNameIndex = 31;
   msgBufPtr->numberOfCommandsIndex = 32;
   msgBufPtr->commandStartIndex = 33;
   SendMessage(cliHandle, CLI_NEW_SVR_REGISTRATION, CLI_NEW_SVR_REGISTRATION,
      (DWORD)msgBufPtr);
 
   if ((err = ProcInsertSpecificProcessor("%s", proc)) != GOOD)
      strcpy(proc, "none");
   if ((err = ProcInsertCpu("%s",cpuType)) != GOOD)
      strcpy(cpuType,"none");
   if ((err = ProcReturnProcFamily(&family)) != GOOD)
      family = FAMILY_UNKNOWN;

   switch (family) {
      case FAMILY_UNKNOWN:
	     strcpy(familyStr, "unknown");
		 break;
      case FAMILY_68K:
         strcpy(familyStr, "FAMILY_68K");
         break;
      case FAMILY_X86:
         strcpy(familyStr, "FAMILY_X86");
         break;
   } /* switch */

   processorSystemVar.integerValueFlag = 0;  /* specify integer system var */
   procTypeSystemVar.integerValueFlag = 0;
   procFamilySystemVar.integerValueFlag = 0;

   processorSystemVar.stringValue = proc;   /* default? */
   procTypeSystemVar.stringValue = cpuType;   /* default? */
   procFamilySystemVar.stringValue = familyStr;   /* default? */

   processorSystemVar.variableName = &processorSystemVarName[0];
   procTypeSystemVar.variableName = &procTypeSystemVarName[0];
   procFamilySystemVar.variableName = &procFamilySystemVarName[0];
 
   SendMessage(cliServerHandle,  /* send system var info to CLI */
            CLI_SYSTEM_VARIABLE,
            0,                   /* don't dealloc mem */
            (DWORD)&processorSystemVar);

   SendMessage(cliServerHandle,  /* send system var info to CLI */
            CLI_SYSTEM_VARIABLE,
            0,                   /* don't dealloc mem */
            (DWORD)&procTypeSystemVar);

   SendMessage(cliServerHandle,  /* send system var info to CLI */
            CLI_SYSTEM_VARIABLE,
            0,                   /* don't dealloc mem */
            (DWORD)&procFamilySystemVar);
 
  return(GOOD);
}

/***************************************************************************
**
**  ProcTestMode
**
**  description:
**     Set testing mode for the proc server.  In testing mode the SDS
**     is ignored and the testCpu is used as the specific processor.
**
**  input:
**     cmdString:  input text
**     argc:  argument count
**     argv:  offsets into cmdString where arguments start
**
**  output:
**     none
**
*****************************************************************************/
#pragma argsused
RETCODE EXPORT ProcTestMode(LPSTR cmdString, U32 argc, U32 argv[]) {
   S8 buff[PROC_LINE];
   
   if(argc>2) return(ER_CLI_SYNTAX);
   if(argc==2) {
      /* set */
      if(strncmpi(&cmdString[(int)argv[1]], "on",
            strlen(&cmdString[(int)argv[1]]))==0) {
         inTestMode = TRUE;
      } else if(strncmpi(&cmdString[(int)argv[1]], "off",
            strlen(&cmdString[(int)argv[1]]))==0) {
         inTestMode = FALSE;
      } else return(ER_CLI_SYNTAX);
   }
   /* return current setting */
   if (inTestMode)
      wsprintf(buff,"proc test mode is on");
   else
      wsprintf(buff,"proc test mode is off");
   SendMessageToCli(buff, cliServerHandle);

   return(GOOD);
}

/***************************************************************************
**
**  ProcTestCpu
**
**  description:
**     Set testing cpu for the proc server.  In testing mode the SDS
**     is ignored and the testCpu is used as the specific processor.
**
**  input:
**     cmdString:  input text
**     argc:  argument count
**     argv:  offsets into cmdString where arguments start
**
**  output:
**     none
**
*****************************************************************************/
#pragma argsused
RETCODE EXPORT ProcTestCpu(LPSTR cmdString, U32 argc, U32 argv[]) {
   S8 buff[PROC_LINE];
   S8 tempbuf[PROC_MAX_PROCESSOR_NAME];
   PROBE_TYPE proc;
   PROC_SYSTEM_TYPE system;
   RETCODE err;

   if(argc>2) return(ER_CLI_SYNTAX);
   if(argc==2) {
      /* set */
      /* use current system type to establish processor.  If that fails
      ** then establish processor in the following order: PowerPack,
      ** MicePack,PowerScope but don't attempt the current processor
      ** since it already failed.
      */
      if ((err = ProcReturnSystemType(&system)) != GOOD)
         return err;
      if ((err = ProcGetProcessorType(&cmdString[(int)argv[1]],
            system,&proc)) != GOOD)
         return err;
      if (proc == PT_DUMMY) {
         /* try PP, MP, and PS */
         switch (system) {
            case PROC_POWERPACK:
               if ((err = ProcGetProcessorType(&cmdString[(int)argv[1]],
                     PROC_MICEPACK,&proc)) != GOOD)
                  return err;
               if (proc == PT_DUMMY) {
                  if ((err = ProcGetProcessorType(&cmdString[(int)argv[1]],
                        PROC_POWERSCOPE,&proc)) != GOOD)
                     return err;
               }
               break;
            case PROC_MICEPACK:
               if ((err = ProcGetProcessorType(&cmdString[(int)argv[1]],
                     PROC_POWERPACK,&proc)) != GOOD)
                  return err;
               if (proc == PT_DUMMY) {
                  if ((err = ProcGetProcessorType(&cmdString[(int)argv[1]],
                        PROC_POWERSCOPE,&proc)) != GOOD)
                     return err;
               }
               break;

            case PROC_POWERSCOPE:
               if ((err = ProcGetProcessorType(&cmdString[(int)argv[1]],
                     PROC_MICEPACK,&proc)) != GOOD)
                  return err;
               if (proc == PT_DUMMY) {
                  if ((err = ProcGetProcessorType(&cmdString[(int)argv[1]],
                        PROC_POWERPACK,&proc)) != GOOD)
                     return err;
               }
               break;
         }
      }
      testCpu = proc;
   }
   /* return current setting */
   if ((err = ProcGetProcessorName(testCpu,tempbuf)) != GOOD)
      return err;
   wsprintf(buff,"test cpu is ");
   strcat(buff,tempbuf);
   SendMessageToCli(buff, cliServerHandle);
   return(GOOD);
}

/***************************************************************************
**
**  ProcTestDump
**
**  description:
**     Dump out all processor specific information to the shell.
**     Performs code coverage type testing for a processor.
**
**  input:
**     cmdString:  input text
**     argc:  argument count
**     argv:  offsets into cmdString where arguments start
**
**  output:
**     none
**
***************************************************************************/
#pragma argsused
RETCODE EXPORT ProcTestDump(LPSTR cmdString, U32 argc, U32 argv[]) {
   S8 buff[PROC_LINE*15];
   S8 tempbuf[PROC_MAX_PROCESSOR_NAME];
   S8 namebuf[PROC_MAX_PROCESSOR_NAME];
   U16 tempU16;
   U32 size;
   PROBE_TYPE proc;
   PROC_CPU cpuType;
   PROCESSOR_FAMILY family;
   ENDIAN_TYPE byteOrder;
   PROC_INSTR_FETCH_SIZE fetch;
   BOOLEAN map;
   RETCODE err;

   strcpy(namebuf,"\0");
   strcpy(tempbuf,"\0");
   if(argc>1) return(ER_CLI_SYNTAX);
   if ((err = ProcReturnSpecificProcessor(&proc)) != GOOD)
         return err;
   // dump all relevant info to a buffer for the shell
   if ((err = ProcGetProcessorName(proc,namebuf)) != GOOD)
      return err;
   wsprintf(buff,"testing cpu: ");
   strcat(buff,namebuf);

   strcat(buff,"\r\nsystem type: PowerPack   ");
   strcat(buff,"probe type enumeration: ");
   if ((err = ProcGetProcessorType(namebuf,PROC_POWERPACK,&proc)) != GOOD)
      return err;
   if (proc == PT_DUMMY)
      strcat(buff,"not supported");
   else {
      wsprintf(tempbuf,"%#x",proc);
      strcat(buff,tempbuf);
   }

   strcat(buff,"\r\nsystem type: PowerScope   ");
   strcat(buff,"probe type enumeration: ");
   if ((err = ProcGetProcessorType(namebuf,PROC_POWERSCOPE,&proc)) != GOOD)
      return err;
   if (proc == PT_DUMMY)
      strcat(buff,"not supported");
   else {
      wsprintf(tempbuf,"%#x",proc);
      strcat(buff,tempbuf);
   }

   strcat(buff,"\r\nsystem type: MicePack   ");
   strcat(buff,"probe type enumeration: ");
   if ((err = ProcGetProcessorType(namebuf,PROC_MICEPACK,&proc)) != GOOD)
      return err;
   if (proc == PT_DUMMY)
      strcat(buff,"not supported");
   else {
      wsprintf(tempbuf,"%#x",proc);
      strcat(buff,tempbuf);
   }

   strcat(buff,"\r\ncpu type: ");
   if ((err = ProcReturnCpu(&cpuType)) != GOOD)
      return err;
   switch (cpuType) {
      case PROC_CPU_68000: strcat(buff,"PROC_CPU_68000"); break;
      case PROC_CPU_68010: strcat(buff,"PROC_CPU_68010"); break;
      case PROC_CPU_68020: strcat(buff,"PROC_CPU_68020"); break;
      case PROC_CPU_68030: strcat(buff,"PROC_CPU_68030"); break;
      case PROC_CPU_68040: strcat(buff,"PROC_CPU_68040"); break;
      case PROC_CPU_CPU32: strcat(buff,"PROC_CPU_CPU32"); break;
      case PROC_CPU_CPU32P: strcat(buff,"PROC_CPU_CPU32P"); break;
      case PROC_CPU_CPU16: strcat(buff,"PROC_CPU_CPU16"); break;
      case PROC_CPU_80186: strcat(buff,"PROC_CPU_80186"); break;
      case PROC_CPU_80386: strcat(buff,"PROC_CPU_80386"); break;
      case PROC_CPU_80486: strcat(buff,"PROC_CPU_80486"); break;
      case PROC_CPU_AM186: strcat(buff,"PROC_CPU_AM186"); break;
      default: strcat(buff,"unknown"); break;
   }

   strcat(buff,"\r\nbyte order: ");
   if ((err = ProcReturnByteOrder(&byteOrder)) != GOOD)
      return err;
   switch (byteOrder) {
      case BIG_ENDIAN: strcat(buff,"big endian"); break;
      case LITTLE_ENDIAN: strcat(buff,"little endian"); break;
      default: strcat(buff,"unknown"); break;
   }

   strcat(buff,"\r\nbytes per instruction: ");
   if ((err = ProcReturnBytesPerInstr(&tempU16)) != GOOD)
      return err;
   wsprintf(tempbuf,"%d",tempU16);
   strcat(buff,tempbuf);

   strcat(buff,"\r\nfetch boundary: ");
   if ((err = ProcReturnFetchBoundary(&fetch)) != GOOD)
      return err;
   switch (fetch) {
      case PROC_WORD: strcat(buff,"word"); break;
      case PROC_BYTE: strcat(buff,"byte"); break;
      case PROC_LONG: strcat(buff,"long"); break;
      default: strcat(buff,"unknown"); break;
   }

   strcat(buff,"\r\nproc family: ");
   if ((err = ProcReturnProcFamily(&family)) != GOOD)
      return err;
   switch (family) {
      case FAMILY_68K: strcat(buff,"68K"); break;
      case FAMILY_X86: strcat(buff,"X86"); break;
      case FAMILY_UNKNOWN: strcat(buff,"unknown"); break;
      default: strcat(buff,"unknown"); break;
   }

   strcat(buff,"\r\ninsert processor: ");
   if ((err = ProcInsertSpecificProcessor("test%s.prc",tempbuf)) != GOOD)
      return err;
   strcat(buff,tempbuf);

   strcat(buff,"\r\ninsert cpu type: ");
   if ((err = ProcInsertCpu("test%s.cpu",tempbuf)) != GOOD)
      return err;
   strcat(buff,tempbuf);

   strcat(buff,"\r\nfunction codes mapable?: ");
   if ((err = ProcReturnFunctionCodesMapable(&map)) != GOOD)
      strcat(buff,"not applicable to processor");
   else {
      if (map)
         strcat(buff,"true");
      else
         strcat(buff,"false");
   }

   strcat(buff,"\r\nbus control mapable?: ");
   if ((err = ProcReturnBusControlMapable(&map)) != GOOD)
      strcat(buff,"not applicable to processor");
   else {
      if (map)
         strcat(buff,"true");
      else
         strcat(buff,"false");
   }

   strcat(buff,"\r\ndefault stack size: ");
   if ((err = ProcDefaultStackSize(&size)) != GOOD)
      strcat(buff,"not applicable to processor");
   else {
      wsprintf(tempbuf,"%d",size);
      strcat(buff,tempbuf);
   }

   SendMessageToCli(buff, cliServerHandle);
   return(GOOD);
}


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